You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/08/28 05:48:08 UTC

[01/51] [partial] rename folder /datajs into /odatajs. no file modification.

Repository: olingo-odata4-js
Updated Branches:
  refs/heads/master bd682f48e -> d5ec55576


http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/store-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/store-tests.js b/odatajs/tests/store-tests.js
new file mode 100644
index 0000000..48169c3
--- /dev/null
+++ b/odatajs/tests/store-tests.js
@@ -0,0 +1,705 @@
+/*
+ * 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) {
+
+    var cleanDomStorage = function () {
+        /** Cleans all the data saved in the browser's DOM Storage.
+        */
+        if (window.localStorage) {
+            window.localStorage.clear();
+        }
+    };
+
+    var cleanMemoryStorage = function () {
+        /** Clean memory storage is a no op.
+        */
+    };
+
+    var cleanIndexedDbStorage = function () {
+        var stores = this.stores;
+        $.each(stores, function (_, store) {
+            store.close();
+        });
+
+        djstest.wait(function (done) {
+            djstest.cleanStoreOnIndexedDb(stores, done);
+        });
+    };
+
+    var canCreateMemoryStore = function () {
+        /** Checks whether memory storage is supported by the browser.
+         * @returns {boolean} True
+         */
+        return true;
+    };
+
+    var canCreateDomStore = function () {
+        /** Checks whether Web Storage (DOM Storage) is supported by the browser.
+         * @returns {boolean} True if DOM Storage is supported by the browser; false otherwise.
+         */
+        return !!window.localStorage;
+    };
+
+    var canCreateIndexedDb = function () {
+        /** Checks whether Web Storage (DOM Storage) is supported by the browser.
+         * @returns {Boolean} True if IndexedDB is supported by the browser, false otherwise.
+         */
+        return !!djstest.indexedDB;
+    };
+
+    var canCreateStore = function (mechanism) {
+        /** Determines whether a particular mechanism is supported by the browser.
+         * @param {String} mechanism - Mechanism name.
+         * @returns {Boolean} True if the mechanism is supported by the browser; otherwise false.
+         */
+        var implementation = mechanismImplementations[mechanism];
+        return implementation && implementation.canCreate();
+    }
+    var makeUnexpectedErrorHandler = function (fail) {
+        return function (err) {
+            djstest.fail("error: " + err.name + " -- message: " + err.message);
+            fail();
+        };
+    };
+
+    var testJobDone = function (succeeded) {
+        if (!succeeded) {
+            djstest.fail("Job completed but some of the functions it called failed");
+        }
+        djstest.done();
+    };
+
+    var mechanismImplementations = {
+        indexeddb: { factory: odatajs.IndexedDBStore, canCreate: canCreateIndexedDb, cleanup: cleanIndexedDbStorage },
+        dom: { factory: odatajs.DomStore, canCreate: canCreateDomStore, cleanup: cleanDomStorage },
+        memory: { factory: odatajs.MemoryStore, canCreate: canCreateMemoryStore, cleanup: cleanMemoryStorage }
+    };
+
+    var oldWindowOnError;
+
+    for (var mechanism in mechanismImplementations) {
+        module("Unit", {
+            mechanism: mechanism,
+            createStore: function (name) {
+                var store = odatajs.store.createStore(name + "_" + this.mechanism, this.mechanism);
+                this.stores.push(store);
+                return store;
+            },
+            setup: function () {
+                this.stores = [];
+                mechanismImplementations[this.mechanism].cleanup.call(this);
+
+                // FireFox 7.0.1 bubbles an error event when there is an IndexedDB error, even when the error has been handled graciously.
+                // This is a work around to keep QUnit from reporting false failures in IndexedDB negative tests.
+                if (this.mechanism === "indexeddb") {
+                    oldWindowOnError = window.onerror;
+                    window.onerror = null;
+                }
+            },
+            teardown: function () {
+                mechanismImplementations[this.mechanism].cleanup.call(this);
+                this.stores = [];
+
+                // Restore QUnit's onerror handler.
+                if (this.mechanism === "indexeddb") {
+                    window.onerror = oldWindowOnError;
+                }
+            }
+        });
+
+        if (!canCreateStore(mechanism)) {
+            djstest.addTest(function (mechanism) {
+                djstest.expectException(function () {
+                    mechanismImplemenatations[mechanism].factory.create("my horrible not working store");
+                });
+                djstest.done();
+            }, "Local storage mechanism " + mechanism + " not supported by this browser", mechanism);
+        } else {
+
+            djstest.addTest(function storeAddTest(mechanism) {
+                var tuples = [
+                    { key: "null", value: null },
+                    { key: "undefined", value: undefined },
+                    { key: "number", value: 12345.678 },
+                    { key: "string", value: "String value" },
+                    { key: "date", value: new Date() },
+                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b"}} },
+                    { key: "array", value: [1, 2, 3, 4, 5] },
+                    { key: "key1", value: "some value" },
+                    { key: "key1", value: "this should fail", error: true },
+                    { key: ["key", "key2"], value: ["value", "value2"], error: mechanism !== "indexeddb" },
+                    { key: ["key6", "key7", "key6"], value: ["value", "value2", "value3"], error: true }
+                ];
+
+                var store = this.createStore("store1");
+                var job = new djstest.Job();
+
+                $.each(tuples, function (_, tuple) {
+                    job.queue(function task(success, fail) {
+
+                        var unexpectedError = makeUnexpectedErrorHandler(fail);
+                        djstest.log("running task");
+
+                        store.add(tuple.key, tuple.value,
+                            function (key, value) {
+                                djstest.assertAreEqual(key, tuple.key, "Keys match for " + mechanism + " - key = " + key.toString());
+                                djstest.assertAreEqualDeep(value, tuple.value, "Values match for " + mechanism + " - key = " + key.toString());
+
+                                job.queueNext(function (success, fail) {
+                                    store.read(tuple.key, function (key, value) {
+                                        djstest.assertAreEqualDeep(value, tuple.value, "Key: " + key + " is present in the store");
+                                        success();
+                                    }, makeUnexpectedErrorHandler(fail));
+                                });
+                                success();
+                            },
+                            function (err) {
+                                if (!tuple.error) {
+                                    unexpectedError(err);
+                                } else {
+                                    djstest.pass("error handler was called as expected");
+                                    success();
+                                }
+                            });
+                    });
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+
+            }, "Store Add Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeAddOrUpdateTest(mechanism) {
+                var tuples = [
+                    { key: "null", value: null },
+                    { key: "undefined", value: undefined },
+                    { key: "number", value: 12345.678 },
+                    { key: "string", value: "String value" },
+                    { key: "date", value: new Date() },
+                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b"}} },
+                    { key: "array", value: [1, 2, 3, 4, 5] },
+                    { key: "key1", value: "some value" },
+                    { key: "key1", value: "this should not fail" },
+                    { key: ["key", "key2", "key3"], value: ["value", "value2", "value3"], error: mechanism !== "indexeddb" },
+                    { key: ["key", "key2", "key3"], value: ["value4", "value5", "value6"], error: mechanism !== "indexeddb" },
+                    { key: "key1", value: 456 }
+                ];
+
+                var store = this.createStore("store2");
+                var job = new djstest.Job();
+
+                $.each(tuples, function (_, tuple) {
+                    job.queue(function (success, fail) {
+
+                        var unexpectedError = makeUnexpectedErrorHandler(fail);
+
+                        store.addOrUpdate(tuple.key, tuple.value,
+                            function (key, value) {
+                                djstest.assert(!tuple.error, "success should be called");
+                                djstest.assertAreEqual(key, tuple.key, "Keys match");
+                                djstest.assertAreEqualDeep(value, tuple.value, "Values match");
+
+                                store.read(tuple.key, function (key, value) {
+                                    djstest.assertAreEqual(key, tuple.key, "Keys match");
+                                    djstest.assertAreEqualDeep(value, tuple.value, "Values match");
+                                    success();
+                                }, unexpectedError);
+                            },
+                            function (err) {
+                                if (!tuple.error) {
+                                    unexpectedError(err);
+                                } else {
+                                    djstest.pass("error handler was called as expected");
+                                    success();
+                                }
+                            });
+                    });
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Add or Update Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeContainsTest(mechanism) {
+                var store = this.createStore("store3");
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add("Key1", "Some value", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.contains("Key1", function (contained) {
+                        djstest.assert(contained, "Key is present in the store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.contains("Key2", function (contained) {
+                        djstest.assert(!contained, "Key is not present in the store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+
+            }, "Store Contains Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeGetAllKeysTest(mechanism) {
+                var store = this.createStore("store4");
+                var store2 = this.createStore("store4_1");
+
+                var expectedKeys = [];
+                var job = new djstest.Job();
+
+                var i;
+                for (i = 1; i <= 20; i++) {
+                    (function (i) {
+                        job.queue(function (success, fail) {
+                            store.add(i.toString(), "value" + i, success, makeUnexpectedErrorHandler(fail));
+                        });
+
+                        job.queue(function (success, fail) {
+                            store2.add((i + 20).toString(), "value" + (i + 20), success, makeUnexpectedErrorHandler(fail));
+                        });
+                    })(i);
+
+                    expectedKeys.push(i.toString());
+                }
+
+                job.queue(function (success, fail) {
+                    store.getAllKeys(function (keys) {
+                        expectedKeys.sort();
+                        keys.sort();
+                        djstest.assertAreEqualDeep(keys, expectedKeys, "All expected keys where returned");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    store2.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Get All Keys Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeReadTest(mechanism) {
+                var tuples = [
+                    { key: "null", value: null },
+                    { key: "undefined", value: undefined },
+                    { key: "number", value: 12345.678 },
+                    { key: "string", value: "String value" },
+                    { key: "date", value: new Date() },
+                    { key: "dateOffset", value: (function () {
+                        var d = new Date();
+                        d.__type = "Edm.DateTimeOffset";
+                        d.__offset = "+03:30";
+                        return d;
+                    })()
+                    },
+                    { key: "complexDate", value: (function () {
+                        var d = new Date();
+                        d.nestedDate = new Date();
+                        d.nestedDate.__type = "Edm.DateTimeOffset";
+                        d.nestedDate.__offset = "+03:30";
+                        return d;
+                    })()
+                    },
+                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b", p3: new Date()}} },
+                    { key: "array", value: [1, 2, 3, 4, 5] }
+                ];
+
+                var store = this.createStore("store5");
+                var job = new djstest.Job();
+
+                $.each(tuples, function (_, tuple) {
+                    job.queue(function (success, fail) {
+                        store.add(tuple.key, tuple.value,
+                            function () {
+                                job.queue(function (success, fail) {
+                                    store.read(tuple.key, function (key, value) {
+                                        djstest.assertAreEqual(key, tuple.key, "Keys match");
+                                        djstest.assertAreEqualDeep(value, tuple.value, "Values match");
+                                        success();
+                                    }, makeUnexpectedErrorHandler(fail));
+                                });
+                                success();
+                            },
+                           function (err) {
+                               if (!tuple.error) {
+                                   djstest.fail(err.message);
+                                   fail();
+                               } else {
+                                   djstest.pass("error handler was called as expected");
+                                   success();
+                               }
+                           });
+                    });
+                });
+
+                job.queue(function (success, fail) {
+                    store.read("Unknown key", function (key, value) {
+                        djstest.assertAreEqual(value, undefined, "Store get returns undefined for keys that do not exist in the store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+
+            }, "Store Read Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeReadArrayTest(mechanism) {
+                var makeError = function (success, fail) {
+                    return function (err) {
+                        if (mechanism !== "indexeddb") {
+                            djstest.pass("Error callback called as expected");
+                            success();
+                        } else {
+                            djstest.fail(err.message);
+                            fail();
+                        }
+                    };
+                };
+
+                var store = this.createStore("store6");
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add(["key", "key2", "key3"], ["value", "value2", "value3"], success, makeError(success, fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.read(["key", "key2", "key3"], function (keys, values) {
+                        djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
+                        djstest.assertAreEqualDeep(values, ["value", "value2", "value3"]);
+                        success();
+                    }, makeError(success, fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.read(["key", "badkey"], function (keys, values) {
+                        djstest.assertAreEqualDeep(keys, ["key", "badkey"]);
+                        djstest.assertAreEqualDeep(values, ["value", undefined]);
+                        success();
+                    }, makeError(success, fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Read Array Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeRemoveTest(mechanism) {
+                var store = this.createStore("store7");
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add("Key1", "Some value", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.add("Key2", "Some value", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.remove("Key1", function () {
+                        djstest.pass("Key1 was removed from the store")
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.contains("Key1", function (contained) {
+                        djstest.assert(!contained, "Key1 is not present in the store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.remove("Key that has never been added", function () {
+                        djstest.pass('"Key that has never been added" was removed from the store');
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.contains("Key2", function (contained) {
+                        djstest.assert(contained, "Key2 is present in the store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Remove Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeUpdateTest(mechanism) {
+                var store = this.createStore("store8");
+
+                var startKey = "Key1";
+                var startValue = "start value";
+                var updateKey = "Key2";
+                var updatedValue = "updated value";
+
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add(startKey, startValue, success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.add(updateKey, startValue, success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.update(updateKey, updatedValue, function (key, value) {
+                        djstest.assertAreEqual(key, updateKey, "Updated keys match");
+                        djstest.assertAreEqualDeep(value, updatedValue, "Updated values match");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.read(updateKey, function (key, value) {
+                        djstest.assertAreEqual(key, updateKey, "Updated keys match after get");
+                        djstest.assertAreEqualDeep(value, updatedValue, "Updated values match after get");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.read(startKey, function (key, value) {
+                        djstest.assertAreEqual(key, startKey, "Non updated keys match after get");
+                        djstest.assertAreEqualDeep(value, startValue, "Non updated values match after get");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Update Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeClearTest(mechanism) {
+                var store = this.createStore("store9");
+                var store2 = this.createStore("store9_1");
+
+                var job = new djstest.Job();
+                job.queue(function (success, fail) {
+                    store.add("Key1", "value in store", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.add("Key2", "value in store", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.add("Key3", "value in store", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store2.add("Key1", "value in store2", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.clear(function () {
+                        djstest.pass("Store was cleared");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.contains("Key1", function (contained) {
+                        djstest.assert(!contained, "Key1 was removed from store");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store2.contains("Key1", function (contained) {
+                        djstest.assert(contained, "Key1 still exists in store 2");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    store2.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Clear Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeUpdateNonExistentTest(mechanism) {
+                var store = this.createStore("store10");
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add("key", "value", success, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.update("badKey", "new value",
+                        function () {
+                            djstest.fail("Sucess handler called when not expected");
+                            fail();
+                        },
+                        function (err) {
+                            djstest.pass("Error callback called as expexted");
+                            success();
+                        });
+                });
+
+                job.queue(function (success, fail) {
+                    store.update(["key", "badkey"], ["value", "badvalue"],
+                        function () {
+                            djstest.fail("Sucess handler called when not expected");
+                            fail();
+                        },
+                        function (err) {
+                            djstest.pass("Error callback called as expected");
+                            success();
+                        });
+                });
+
+                job.queue(function (success, fail) {
+                    store.read("key", function (key, value) {
+                        djstest.assertAreEqual(value, "value", "value was not changed");
+                        success();
+                    }, makeUnexpectedErrorHandler(fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Update Non-Existent Test with mechanism " + mechanism, mechanism);
+
+            djstest.addTest(function storeUpdateArrayTest(mechanism) {
+                var makeError = function (success, fail) {
+                    return function (err) {
+                        if (mechanism !== "indexeddb") {
+                            djstest.pass("Error callback called as expected");
+                            success();
+                        } else {
+                            djstest.fail(err.message);
+                            fail();
+                        }
+                    };
+                };
+
+                var store = this.createStore("store11");
+                var job = new djstest.Job();
+
+                job.queue(function (success, fail) {
+                    store.add(["key", "key2"], ["value1", "value2"], success, makeError(success, fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.update(["key", "key2"], ["value1", "value4"], success, makeError(success, fail));
+                });
+
+                job.queue(function (success, fail) {
+                    store.read(["key", "key2"], function (key, value) {
+                        djstest.assertAreEqualDeep(value, ["value1", "value4"], "value was not changed");
+                        success();
+                    }, makeError(success, fail));
+                });
+
+                job.run(function (succeeded) {
+                    store.close();
+                    testJobDone(succeeded);
+                });
+            }, "Store Update Array Test with mechanism " + mechanism, mechanism);
+        }
+    }
+
+    module("Unit");
+
+    djstest.addTest(function CreateStoreTest() {
+        var defaultExpected = canCreateDomStore() ? "dom" : "memory";
+        var tests = [
+            { mechanism: "dom", exception: !canCreateDomStore(), expected: "dom" },
+            { mechanism: "memory", exception: false, expected: "memory" },
+            { mechanism: "", exception: false, expected: defaultExpected },
+            { mechanism: null, exception: false, expected: defaultExpected },
+            { mechanism: "unknown", exception: true }
+       ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            try {
+                var test = tests[i];
+                var store = odatajs.store.createStore("testStore" + i, tests[i].mechanism);
+
+                if (!test.exception) {
+                    djstest.assertAreEqual(store.mechanism, test.expected, "Created store of the expected mechanism");
+                } else {
+                    djstest.fail("Didn't get the expected exception");
+                }
+            }
+            catch (e) {
+                djstest.assert(test.exception, "Expected exception");
+            }
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function CreateBestStoreTest() {
+        var bestMechanism;
+
+        for (var name in mechanismImplementations) {
+            if (!bestMechanism && canCreateStore(name) && name !== "indexeddb") {
+                bestMechanism = name;
+            }
+        }
+
+        if (bestMechanism) {
+            var tests = [
+                "best",
+                undefined
+            ];
+
+            for (var i in tests) {
+                var store = odatajs.store.createStore("best store ever " + i, tests[i]);
+                djstest.assertAreEqual(store.mechanism, bestMechanism, "Mechanisms match");
+            }
+        } else {
+            djstest.pass("This browser doesn't support any of the implemented local storage mechanisms");
+        }
+        djstest.done();
+    });
+
+})(this);


[38/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/cache-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/cache-tests.js b/datajs/tests/cache-tests.js
deleted file mode 100644
index f4c1a1c..0000000
--- a/datajs/tests/cache-tests.js
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-(function (window, undefined) {
-
-    module("Unit");
-    var foodsFeed = "./endpoints/FoodStoreDataServiceV4.svc/Foods";
-    var collectionSize = 16;
-
-    var thenFailTest = function (err) {
-        if (err && err.message) {
-            djstest.fail(err.message);
-        } else {
-            djstest.fail("unexepected promise failure");
-        }
-
-        djstest.done();
-    };
-
-    djstest.addTest(function dataCacheCountTest() {
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
-        cache.count().then(function (count) {
-            djstest.assertAreEqual(count, collectionSize, "expected count for Foods");
-            djstest.destroyCacheAndDone(cache);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheCountOnLocalTest() {
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed, pageSize: collectionSize + 10, mechanism: "memory" });
-        cache.readRange(0, collectionSize + 10).then(function (data) {
-            var expectedCount = data.value ? data.value.length : 0;
-            cache.count().then(function (count) {
-                djstest.assertAreEqual(count, expectedCount, "expected count for expectedCount");
-                djstest.destroyCacheAndDone(cache);
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheCountAbortTest() {
-        // Abort before completion.
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
-        var item = cache.count().then(thenFailTest, function (err) {
-            djstest.assertAreEqual(true, err.canceled, "err.aborted is true");
-            djstest.destroyCacheAndDone(cache);
-        }).cancel();
-    });
-
-    var createNewCache = function (options) {
-
-        var thenSuccess = null;
-
-        var resolved = false;
-        var rejected = false;
-
-        var args = null;
-
-        this.then = function (success) {
-            if (resolved) {
-                success.apply(null, args);
-            } else if (!rejected) {
-                thenSuccess = success;
-            }
-        };
-
-        var resolve = function (/*args*/) {
-            resolved = true;
-            args = arguments;
-            if (thenSuccess) {
-                thenSuccess.apply(null, arguments);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache(options);
-        cache.clear().then(function () {
-            var newCache = odatajs.cache.createDataCache(options);
-            resolve(newCache);
-        }, function (err) {
-            rejected = true;
-            thenFailTest(err);
-        });
-
-        return this;
-    };
-
-    djstest.addTest(function dataCacheReadRangeSingleTest() {
-        // Read a new range.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 1, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "food id is 0.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeExactPageTest() {
-        // Read exactly one page.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 2).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 2, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeMultiplePageTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 3).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 3, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                        djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeSyncDelaysTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).
-                    then(function (data) {
-                        djstest.assertAreEqual(counter, 0, "counter is zero for first set of results");
-                        djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
-                        counter++;
-                        cache.readRange(0, 1).
-                            then(function (data) {
-                                djstest.assertAreEqual(counter, 2, "counter is two because even sync results are delayed)");
-                                djstest.assertAreEqual(cache.stats.netReads, 1, "no additional requests since requested data is in cache");
-                                djstest.done();
-                            }, thenFailTest);
-                        djstest.assertAreEqual(counter, 1, "counter is one because readRange hasn't run (even if results are cached)");
-                        counter++;
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangesWithDestroyTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
-        var counter = 0;
-        createNewCache(options).then(function (cache) {
-            cache.readRange(0, 1).then(function (data) {
-                djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
-                cache.clear().then(function () {
-                    djstest.assertAreEqual(cache.stats.netReads, 0, "stats cleared in destroy");
-                    cache.readRange(0, 1).then(function (data) {
-                        djstest.assertAreEqual(cache.stats.netReads, 1, "request made after destroy to fulfill the readRange");
-                        djstest.done();
-                    }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadSimultaneousTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        var theCache;
-        var checkDataAndCount = function (data) {
-            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
-            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
-            djstest.assertAreEqual(theCache.stats.netReads, 1, "single theCache.stats.netReads");
-            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
-            counter++;
-            if (counter === 3) {
-                djstest.done();
-            }
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheMultipleClearTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        var checkCount = function (data) {
-            djstest.assert(true, "clear then was called");
-            counter++;
-            if (counter === 3) {
-                djstest.done();
-            }
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).then(function () {
-                    cache.clear().then(checkCount, thenFailTest);
-                    cache.clear().then(checkCount, thenFailTest);
-                    cache.clear().then(checkCount, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheOnIdleIsFired() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
-
-        createNewCache(options).
-            then(function (cache) {
-                var counter = 0;
-                var clearSucceeded = false;
-
-                var thenFailThisTest = function (err) {
-                    if (err && err.message) {
-                        djstest.fail(err.message);
-                    } else {
-                        djstest.fail("unexepected promise failure");
-                    }
-                };
-
-                cache.onidle = function () {
-                    counter++;
-                    djstest.assertAreEqual(counter, 1, "onidle was called 1 times");
-                    djstest.assert(clearSucceeded, "onidle was called after destroy");
-                    djstest.done();
-                };
-
-                cache.readRange(0, 1).then(null, thenFailThisTest);
-                cache.readRange(0, 1).then(null, thenFailThisTest);
-                cache.readRange(3, 4).then(function () {
-                    cache.readRange(5, 6).then(function () {
-                        cache.clear().then(function () {
-                            clearSucceeded = true;
-                        }, thenFailThisTest);
-                    }, thenFailThisTest);
-                }, thenFailThisTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheOnIdleFiresOnErrorTest() {
-
-        var errorResponse = false;
-        var httpClient = {
-            request: function (request, success, error) {
-                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ d: [1, 2] }) };
-                if (!errorResponse) {
-                    errorResponse = true;
-                    setTimeout(function () {
-                        success(response);
-                    }, 0);
-                } else {
-                    response.statusCode = 500;
-                    response.body = "bad response";
-                    setTimeout(function () {
-                        error({ message: "HTTP request failed", request: request, response: response });
-                    }, 0);
-                }
-            }
-        };
-
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0, httpClient: httpClient };
-
-        createNewCache(options).
-            then(function (cache) {
-                var counter = 0;
-                var errorHandlerCalled = false;
-
-                var thenFailThisTest = function (err) {
-                    if (err && err.message) {
-                        if (errorResponse) {
-                            djstest.assertAreEqual(err.message, "HTTP request failed", "Error is the expected one");
-                            errorHandlerCalled = true;
-                        } else {
-                            djstest.fail(err.message);
-                        }
-                    } else {
-                        djstest.fail("unexepected promise failure");
-                    }
-                };
-
-                cache.onidle = function () {
-                    counter++;
-                    djstest.assertAreEqual(counter, 1, "onidle was called");
-                    djstest.assert(errorHandlerCalled, "error handler was called before onidle");
-                    cache.onidle = null;
-                    cache.clear().then(function () {
-                        djstest.done();
-                    }, thenFailTest);
-                };
-                cache.readRange(0, 2).then(function () {
-                    cache.readRange(2, 4).then(function () {
-                        djstest.fail("unexpected readRange success");
-                    }, thenFailThisTest);
-                }, thenFailThisTest);
-            }, thenFailTest);
-    });
-
-
-    djstest.addTest(function dataCacheOdataSourceNormalizedURITest() {
-        var requestsMade = 0;
-        var httpClient = {
-            request: function (request, success, error) {
-                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ value: [1, 2] }) };
-                if (requestsMade === 0) {
-                    djstest.pass("Cache made first request for data from the source");
-                    requestsMade++;
-                } else {
-                    // In memory storage will make a second request from the new cache since two caches with the same name will coexist
-                    if (window.mozIndexedDB || window.localStorage || requestsMade > 1) {
-                        djstest.fail("Unexpected request to the source");
-                    } else {
-                        djstest.pass("In memory cache requested the data from the source");
-                    }
-                }
-                setTimeout(function () {
-                    success(response);
-                }, 0);
-            }
-        };
-
-        var options = { name: "cache", source: "http://exampleuri.com/my service.svc", pageSize: 2, prefetchSize: 0, httpClient: httpClient };
-
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 2).then(function () {
-                    options.source = "HtTp://ExampleURI.cOm/my%20service.svc";
-                    var newCache = odatajs.cache.createDataCache(options);
-                    newCache.readRange(0, 2).then(function (data) {
-                        djstest.assertAreEqualDeep(data.value, [1, 2], "Got the expected data from the new cache instance");
-                        newCache.clear().then(function () {
-                            djstest.done();
-                        }, thenFailTest);
-                    }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-
-    djstest.addTest(function dataCachePrefetchAllTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: -1 };
-        var counter = 0;
-        var theCache;
-
-        var callback = function () {
-            counter++;
-            if (counter === 2) {
-                djstest.assertAreEqual(1, theCache.stats.netReads, "single page to satisfy read (" + theCache.stats.netReads + ")");
-                djstest.assert(theCache.stats.prefetches > 1, "theCache.stats.prefetches(" + theCache.stats.prefetches + ") > 1 - multiple prefetches");
-                djstest.done();
-            }
-        };
-
-        var checkDataAndCount = function (data) {
-            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
-            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
-            djstest.assertAreEqual(1, theCache.stats.netReads, "single theCache.stats.netReads");
-            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
-            callback();
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.onidle = function () {
-                    djstest.log("onidle fired");
-                    callback();
-                };
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeTakeMoreThanCollectionCountTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.count().then(function (count) {
-                    cache.readRange(0, count + 1).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, count, "all items in the collection were read.");
-                            cache.readRange(2, count + 1).
-                                then(function (data) {
-                                    djstest.assertAreEqual(data.value.length, count - 2, "all requested in the collection were read.");
-                                    djstest.assertAreEqual(data.value[0].FoodID, 2, "first read food id is 2.");
-                                    djstest.done();
-                                }, thenFailTest);
-                        }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeSkipMoreThanCollectionCountTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.count().then(function (count) {
-                    cache.readRange(count + 1, 5).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, 0, "no items were read.");
-                            djstest.done();
-                        }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeTakeMoreThanPrefetchSizeTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 4).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, 4, "all requested in the collection were read.");
-                            djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                            djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                            djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
-                            djstest.assertAreEqual(data.value[3].FoodID, 3, "third food id is 3.");
-                            djstest.done();
-                        }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheRangeInvalidIndexAndCount() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
-        var counter = 0;
-
-        var thenFailSuccess = function () {
-            djstest.fail("Call to success was unexpected");
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var thenFailError = function () {
-            djstest.fail("Call to error was unexpected");
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var invalidValues = [-5, -1, null, undefined, NaN, Infinity, "5", "this is not a number"];
-        var tests = [];
-        $.each(invalidValues, function (_, value) {
-            tests.push({ i: value, c: 0 });
-            tests.push({ i: 0, c: value });
-            tests.push({ i: value, c: value });
-        });
-
-        createNewCache(options).
-            then(function (cache) {
-                var i, len;
-                for (i = 0, len = tests.length; i < len; i++) {
-                    var test = tests[i];
-                    try {
-                        cache.readRange(test.i, test.c).then(thenFailSuccess, thenFailTest);
-                    } catch (err) {
-                        djstest.pass("Expected exception was thrown: " + err.message);
-                        counter++;
-                    }
-                }
-                if (counter === tests.length) {
-                    djstest.done();
-                }
-            });
-    });
-
-
-    djstest.addTest(function cacheOptionsForCountTest() {
-        var httpClient = {
-            request: function (r, success, error) {
-                window.setTimeout(function () {
-                    success({ data: "10" });
-                }, 1);
-                return null;
-            }
-        };
-        var cache = odatajs.cache.createDataCache({
-            name: "mem", mechanism: "memory", source: "http://www.example.org/service/",
-            httpClient: httpClient
-        });
-        cache.count().then(function (count) {
-            djstest.assertAreEqual(count, 10, "count value");
-            djstest.done();
-        }, djstest.failAndDoneCallback("failed to get count"));
-    });
-
-    djstest.addTest(function dataCacheDestoryStopsThePrefetcherTest() {
-        var oldHttpClientRequest = window.odatajs.oData.net.defaultHttpClient.request;
-        var prefetchCount = 0;
-        var theCache;
-
-        window.odatajs.oData.net.defaultHttpClient.request = function (request, success, error) {
-            prefetchCount++;
-            djstest.assert(prefetchCount <= 3, "Expected prefetch request");
-            if (prefetchCount === 3) {
-                theCache.clear().then(function () {
-                    djstest.assertAreEqual(prefetchCount, 3, "cache.clear() stopped the prefetcher");
-                    djstest.done();
-                    window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
-                }, thenFailTest);
-                return {
-                    abort: function () { }
-                };
-            }
-            return oldHttpClientRequest(request, success, error);
-        };
-
-        try {
-            var options = { name: "cache", source: foodsFeed, pageSize: 1, prefetchSize: -1 };
-            createNewCache(options).then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 0).then(null, thenFailTest);
-            });
-        } catch (e) {
-            window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
-            djstest.fail("Exception thrown,  prefetchSize: " + tests[count] + " error:  " + e.message);
-            djstest.done();
-        }
-    });
-
-    djstest.addTest(function dataCacheFilterTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 3, prefetchSize: -1 };
-        var counter = 0;
-
-        var singleItemPredicate = function (data) {
-            return data.FoodID === 2;
-        };
-
-        var multipleItemPredicate = function (data) {
-            return data.FoodID % 2 === 1;
-        };
-
-        var noItemPredicate = function (data) {
-            return data.Name === "something i would never eat";
-        };
-
-        var allItemPredicate = function (data) {
-            return data.FoodID >= 0;
-        };
-
-        var doneAfterAllTests = function () {
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var last = collectionSize - 1;
-        var tests = [
-            { index: 0, count: -5, predicate: singleItemPredicate },    // Single match in entire collection
-            {index: 2, count: 1, predicate: singleItemPredicate },     // Single match, single count
-            {index: 3, count: 1, predicate: singleItemPredicate },     // Single match skipped, i.e. no matches
-            {index: 0, count: -1, predicate: multipleItemPredicate },  // Multiple matches in entire collection
-            {index: 0, count: 5, predicate: multipleItemPredicate },   // Multiple matches, take partial
-            {index: 3, count: 5, predicate: multipleItemPredicate },   // Multiple matches, skip/take partial
-            {index: 7, count: 10, predicate: multipleItemPredicate },  // Multiple matches, skip partial, take past end of collection
-            {index: 13, count: 4, predicate: allItemPredicate },       // All items match, skip/take partial
-            {index: 0, count: 20, predicate: noItemPredicate },        // No matches
-            {index: 0, count: 0, predicate: allItemPredicate },        // Zero count
-            {index: -5, count: 1, predicate: allItemPredicate },       // Negative index
-            {index: last + 1, count: 1, predicate: allItemPredicate }, // Index past end of collection
-
-            {index: last, count: -5, predicate: singleItemPredicate, backwards: true },        // Single match in entire collection
-            {index: 2, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match, single count
-            {index: 1, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match skipped, i.e. no matches
-            {index: last, count: -1, predicate: multipleItemPredicate, backwards: true },      // Multiple matches in entire collection
-            {index: last, count: 6, predicate: multipleItemPredicate, backwards: true },       // Multiple matches, take partial
-            {index: last - 3, count: 5, predicate: multipleItemPredicate, backwards: true },   // Multiple matches, skip/take partial
-            {index: 13, count: 10, predicate: multipleItemPredicate, backwards: true },        // Multiple matches, skip partial, take past end of collection
-            {index: 4, count: 13, predicate: allItemPredicate, backwards: true },              // All items match, skip/take partial
-            {index: last, count: 20, predicate: noItemPredicate, backwards: true },            // No matches
-            {index: 0, count: 0, predicate: allItemPredicate, backwards: true },               // Zero count
-            {index: -5, count: 1, predicate: allItemPredicate, backwards: true },              // Negative index
-            {index: last + 1, count: 1, predicate: allItemPredicate, backwards: true },        // Index past end of collection
-
-            {index: "foo", count: 1, predicate: singleItemPredicate, exception: { message: "'index' must be a valid number.", index: NaN} },
-            { index: 0, count: "foo", predicate: multipleItemPredicate, exception: { message: "'count' must be a valid number.", count: NaN} }
-        ];
-
-        var testDescription = function(test) {
-            return "filter [" + test.index + ", " + test.count + " " + (test.backwards ? "back" : "forward") + "] for predicate " + test.predicate;
-        };
-
-        var filterErrorCallback = function (err) {
-            if (err && err.message) {
-                djstest.fail(err.message);
-            } else {
-                djstest.fail("unexpected promise failure");
-            }
-            doneAfterAllTests();
-        };
-
-        var removeSafariExceptionProperties = function (err) {
-            /** Removes Safari-specific properties from an exception object
-             * @param {Exception} err -The exception object to operate on
-             * @returns {Exception} The original exception object with the Safari-specific properties removed
-             */
-            var safariProperties = ["line", "expressionBeginOffset", "expressionEndOffset", "sourceId", "sourceURL"];
-
-            var result = {};
-            $.each(err, function (property, value) {
-                if ($.inArray(property, safariProperties) === -1) {
-                    result[property] = value;
-                }
-            });
-
-            return result;
-        };
-
-        ODataReadOracle.readJsonAcrossServerPages(foodsFeed, function (expectData) {
-            $.each(tests, function (_, test) {
-                createNewCache(options).then(function (cache) {
-                    try {
-                        var expectedResults = {};
-                        if (test.backwards) {
-                            cache.filterBack(test.index, test.count, test.predicate).then(function (results) {
-                                expectedResults = CacheOracle.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
-                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
-                                doneAfterAllTests();
-                            }, filterErrorCallback);
-                        } else {
-                            cache.filterForward(test.index, test.count, test.predicate).then(function (results) {
-                                expectedResults = CacheOracle.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
-                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
-                                doneAfterAllTests();
-                            }, filterErrorCallback);
-                        }
-
-                        if (test.exception) {
-                            djstest.fail("expected exception for " + testDescription(test));
-                            doneAfterAllTests();
-                        }
-                    } catch (err) {
-                        if (test.exception) {
-                            djstest.assertAreEqualDeep(removeSafariExceptionProperties(err), test.exception, "exception for " + testDescription(test));
-                        } else {
-                            djstest.fail("unexpected exception for " + testDescription(test) + ": " + djstest.toString(err));
-                        }
-                        doneAfterAllTests();
-                    }
-                }, thenFailTest);
-            });
-        });
-    });
-
-    djstest.addTest(function createDataCacheTest() {
-        var cache;
-
-        // Verify the defaults.
-        cache = odatajs.cache.createDataCache({ name: "name", source: "src" });
-
-        djstest.assertAreEqual(cache.onidle, undefined, "onidle is undefined");
-
-        // Verify specific values.
-        cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: 3, idle: 123 });
-
-        djstest.assertAreEqual(cache.onidle, 123, "onidle is as specified");
-
-        // Verify 0 pageSize 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 0, prefetchSize: 3, idle: 123 });
-        }, "zero pageSize");
-
-        // Verify negative pageSize
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: -2, prefetchSize: 3, idle: 123 });
-        }, "negative pageSize");
-
-        // Verify NaN pageSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: "2", prefetchSize: 3, idle: 123 });
-        }, "NaN pageSize");
-
-        // Verify NaN cacheSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: "1", pageSize: 2, prefetchSize: 3, idle: 123 });
-        }, "NaN cacheSize");
-
-        // Verify NaN prefetchSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: "3", idle: 123 });
-        }, "NaN prefetchSize");
-
-        // Verify undefined name 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "undefined name");
-
-        // Verify null name 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: null, source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "null name");
-
-        // Verify undefined source 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "undefined source");
-
-        djstest.done();
-    });
-
-    djstest.addTest(function createDataCacheWithSourceTest() {
-        var cacheSource = {
-            count: function (success) {
-                djstest.pass("cacheSource.count was called");
-                success(0);
-            },
-
-            read: function (index, count, success, error) {
-                djstest.assertAreEqual(index, 0, "index is the expected one");
-                djstest.assertAreEqual(count, 10, "test is the expected one");
-                djstest.assert(success, "success is defined");
-                djstest.assert(error, "error is defined");
-                djstest.pass("cacheSource.read was called");
-
-                setTimeout(function () {
-                    success([]);
-                }, 0);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
-        cache.count().then(function () {
-            cache.readRange(0, 5).then(function () {
-                djstest.done();
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function cacheInitializationFailTest() {
-        // Tests various failure modes for cache initialization.
-        var failures = ["read-settings", "write-settings", "v2"];
-        var failureIndex = 0;
-
-        var originalStore = odatajs.store.createStore;
-        var restoreStore = function () {
-            odatajs.store.createStore = originalStore;
-        };
-
-        var storeError = { message: "cacheInitializationFailTest error" };
-        odatajs.store.createStore = function (name, mechanism) {
-            return {
-                addOrUpdate: function (key, value, successCallback, errorCallback) {
-                    if (failures[failureIndex] === "write-settings") {
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    } else {
-                        djstest.fail("Error unaccounted for in addOrUpdate for " + failures[failureIndex]);
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    }
-                },
-                read: function (key, successCallback, errorCallback) {
-                    if (failures[failureIndex] === "read-settings") {
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    } else if (failures[failureIndex] === "v2") {
-                        window.setTimeout(function () {
-                            successCallback("K", { version: "2.0" });
-                        }, 2);
-                    } else if (failures[failureIndex] === "write-settings") {
-                        window.setTimeout(function () { successCallback(null, null); }, 2);
-                    } else {
-                        djstest.fail("Error unaccounted for read in " + failures[failureIndex]);
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    }
-                }
-            };
-        };
-
-        var nextFailure = function () {
-            djstest.log("Failure mode: " + failures[failureIndex]);
-            var cache = odatajs.cache.createDataCache({ name: "name", source: "foo", mechanism: "memory", pageSize: 10 });
-            try {
-                // The first readRange should succeed, because the data cache isn't really initialized at this time.
-                cache.readRange(1, 2).then(djstest.failAndDoneCallback("No function should succeed"), function (err) {
-                    djstest.expectException(function () {
-                        cache.readRange(1, 2);
-                    }, "readRange after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.count();
-                    }, "count after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.clear();
-                    }, "clear after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.filterForward(1, 2);
-                    }, "filterForward after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.filterBack(1, 2);
-                    }, "filterBack after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.toObservable();
-                    }, "toObservable after store is invalidated");
-
-                    failureIndex++;
-                    if (failureIndex === failures.length) {
-                        restoreStore();
-                        djstest.done();
-                    } else {
-                        nextFailure();
-                    }
-                });
-            } catch (outerError) {
-                djstest.fail("Unexpected failure for first .readRange: " + window.JSON.stringify(outerError));
-                restoreStore();
-                djstest.done();
-            }
-        };
-
-        nextFailure();
-    });
-
-    djstest.addTest(function createDataCacheWithSourceCallsErrorTest() {
-        var cacheSource = {
-            count: function () {
-                djstest.fail("cacheSource.count was called");
-            },
-
-            read: function (index, count, success, error) {
-                setTimeout(function () {
-                    error({ message: "source error" });
-                }, 0);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
-        cache.readRange(0, 5).then(function () {
-            djstest.fail("unexpected call to then success");
-            djstest.done();
-        }, function (err) {
-            djstest.assertAreEqual(err.message, "source error", "got the expected error");
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function toObservableMissingTest() {
-        createNewCache({ name: "cache", source: "http://temp.org" }).then(function (cache) {
-            var hiddenRx = window.Rx;
-            try {
-                window.Rx = null;
-                var error = null;
-                try {
-                    cache.ToObservable();
-                } catch (err) {
-                    error = err;
-                }
-
-                djstest.assert(error !== null, "error !== null");
-            } finally {
-                window.Rx = hiddenRx;
-            }
-
-            djstest.assert(error !== null, "error !== null");
-            djstest.destroyCacheAndDone(cache);
-        });
-    });
-
-    djstest.addTest(function toObservableSinglePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
-            var lastId = -1;
-            cache.ToObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableCaseSinglePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
-            var lastId = -1;
-            cache.toObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableMultiplePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var callCount = 0;
-            cache.toObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-                callCount += 1;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.assert(callCount > 1, "callCount > 1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableEarlyDisposeTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var callCount = 0;
-            var complete = false;
-            var observer = cache.toObservable().subscribe(function (item) {
-                djstest.assert(complete === false, "complete === false");
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-                callCount += 1;
-                complete = true;
-                observer.Dispose();
-                djstest.done();
-            }, thenFailTest);
-        });
-    });
-
-    djstest.addTest(function toObservableFailureTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var complete = false;
-            window.MockHttpClient.clear().addResponse("*", { statusCode: 500, body: "server error" });
-            window.MockHttpClient.async = true;
-            var savedClient = window.odatajs.oData.net.defaultHttpClient;
-            window.odatajs.oData.net.defaultHttpClient = window.MockHttpClient;
-            cache.toObservable().subscribe(function (item) {
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                djstest.fail("Unexpected call to OnNext");
-            }, function (err) {
-                djstest.assert(complete === false, "complete === false");
-                djstest.assert(err, "err defined");
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                complete = true;
-                djstest.done();
-            }, function (complete) {
-                djstest.fail("Unexpected call to complete. Error handler should be called.");
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                complete = true;
-                djstest.done();
-            });
-        });
-    });
-
-    // DATAJS INTERNAL START
-
-    djstest.addTest(function createDeferredTest() {
-        // Verify basic use of deferred object.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (val1, val2) {
-            djstest.assertAreEqual(val1, 1, "val1 is as specified");
-            djstest.assertAreEqual(val2, 2, "val2 is as specified");
-            djstest.done();
-        });
-        deferred.resolve(1, 2);
-    });
-
-    djstest.addTest(function deferredThenTest() {
-        // Verify then registration and chaining.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (val1, val2) {
-            djstest.assertAreEqual(val1, 1, "val1 is as specified");
-            djstest.assertAreEqual(val2, 2, "val2 is as specified");
-            return "foo";
-        }).then(function (foo) {
-            // See Compatibility Note B in DjsDeferred remarks.
-            djstest.assert(foo !== "foo", "argument for chained 'then' is *not* result of previous call");
-            djstest.assert(foo === 1, "argument for chained 'then' is same as for previous call");
-
-            var other = odatajs.deferred.createDeferred();
-            other.then(null, function (err, msg) {
-                djstest.assertAreEqual("error", err, "err is as specified");
-                djstest.assertAreEqual("message", msg, "msg is as specified");
-
-            }).then(null, function (err, msg) {
-                djstest.log("chained errors are called");
-
-                djstest.assertAreEqual("error", err, "err is as specified");
-                djstest.assertAreEqual("message", msg, "msg is as specified");
-
-                var multiple = odatajs.deferred.createDeferred();
-                var count = 0;
-
-                // See Compatibility Note A in DjsDeferred remarks.
-                multiple.then(function () {
-                    djstest.assertAreEqual(count, 0, "first base registration fires as #0");
-                    count++;
-                }).then(function () {
-                    djstest.assertAreEqual(count, 1, "first chained registration fires as #1");
-                    count++;
-                });
-
-                multiple.then(function () {
-                    djstest.assertAreEqual(count, 2, "second base registration fires as #2");
-                    count++;
-                }).then(function () {
-                    djstest.assertAreEqual(count, 3, "second chained registration fires as #3");
-                    djstest.done();
-                });
-
-                multiple.resolve();
-            });
-            other.reject("error", "message");
-        });
-
-        deferred.resolve(1, 2);
-    });
-
-    djstest.addTest(function deferredResolveTest() {
-        // Resolve with no arguments.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (arg) {
-            djstest.assertAreEqual(arg, undefined, "resolve with no args shows up as undefined");
-
-            // Resolve with no callbacks.
-            var other = odatajs.deferred.createDeferred();
-            other.resolve();
-            djstest.done();
-        });
-
-        deferred.resolve();
-    });
-
-    djstest.addTest(function deferredRejectTest() {
-        // Resolve with no arguments.   
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(null, function (arg) {
-            djstest.assertAreEqual(arg, undefined, "reject with no args shows up as undefined");
-
-            // Resolve with no callbacks.
-            var other = odatajs.deferred.createDeferred();
-            other.reject();
-            djstest.done();
-        });
-
-        deferred.reject();
-    });
-
-    djstest.addTest(function estimateSizeTest() {
-        var tests = [
-            { i: null, e: 8 },
-            { i: undefined, e: 8 },
-            { i: 0, e: 8 },
-            { i: "abc", e: 6 },
-            { i: [1, 2, 3], e: 30 },
-            { i: { a1: null, a2: undefined, a3: 5, a4: "ab", a5: { b1: 5, b2: 6} }, e: 72 },
-            { i: {}, e: 0 }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var test = tests[i];
-            djstest.assertAreEqual(odatajs.cache.estimateSize(test.i), test.e);
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function cacheOptionsTunnelTest() {
-        var mockClient = window.MockHttpClient;
-        var doneCalled = false;
-
-        mockClient.clear().setAsync(true).addRequestVerifier("*", function (theRequest) {
-            if (!doneCalled) {
-                doneCalled = true;
-                djstest.assertAreEqual(theRequest.user, "the-user", "theRequest.user");
-                djstest.assertAreEqual(theRequest.password, "the-password", "theRequest.password");
-                djstest.assertAreEqual(theRequest.enableJsonpCallback, false, "theRequest.enableJsonpCallback");
-                djstest.assertAreEqual(theRequest.callbackParameterName, "p", "callbackParameterName");
-                djstest.done();
-            }
-        });
-
-        var cache = odatajs.cache.createDataCache({
-            name: "cacheOptionsTunnel",
-            source: "http://foo-bar/",
-            user: "the-user",
-            password: "the-password",
-            enableJsonpCallback: false,
-            callbackParameterName: "p",
-            httpClient: mockClient
-        });
-
-        cache.readRange(0, 10).then(function (arr) {
-            djstest.fail("unexpected callback into readRange in test cacheOptionsTunnelTest");
-            if (!doneCalled) {
-                doneCalled = true;
-                djstest.done();
-            }
-        });
-    });
-
-    djstest.addTest(function dataCacheHandlesFullStoreTest() {
-
-        var TestStore = function (name) {
-            var that = new window.odatajs.store.MemoryStore(name);
-            that.addOrUpdate = function (key, value, success, error) {
-                if (key === "__settings") {
-                    window.setTimeout(function () {
-                        success(key, value);
-                    }, 0);
-                } else {
-                    window.setTimeout(function () {
-                        error({ name: "QUOTA_EXCEEDED_ERR" });
-                    }, 0);
-                }
-            };
-            return that;
-        };
-
-        TestStore.create = function (name) {
-            return new TestStore(name);
-        };
-
-        TestStore.isSupported = function () {
-            return true;
-        };
-
-        var cacheSource = {
-            identifier: "testSource",
-            count: function (success) {
-                djstest.fail("cacheSource.count was called");
-                success(5);
-            },
-            read: function (index, count, success, error) {
-                djstest.assertAreEqual(index, 0, "index is the expected one");
-                djstest.assertAreEqual(count, 5, "test is the expected one");
-
-                setTimeout(function () {
-                    success({ value: [1, 2, 3, 4, 5] });
-                }, 0);
-            }
-        };
-
-        var originalCreateStore = window.odatajs.store.createStore;
-
-        window.odatajs.store.createStore = function (name, mechanism) {
-            return TestStore(name);
-        };
-
-        try {
-            var cache = odatajs.cache.createDataCache({
-                name: "cache",
-                pageSize: 5,
-                prefetchSize: 0,
-                source: cacheSource,
-                mechanism: "teststore"
-            });
-        } finally {
-            window.odatajs.store.createStore = originalCreateStore;
-        }
-
-        cache.readRange(0, 5).then(function (data) {
-            djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
-            cache.readRange(0, 5).then(function (data) {
-                djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
-                djstest.done();
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    // DATAJS INTERNAL END
-})(this);
\ No newline at end of file


[51/51] [partial] git commit: rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
rename folder /datajs into /odatajs. no file modification.


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/d5ec5557
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/tree/d5ec5557
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/diff/d5ec5557

Branch: refs/heads/master
Commit: d5ec5557673b61c674ffb87118234ab52214193b
Parents: bd682f4
Author: challenh <ch...@microsoft.com>
Authored: Thu Aug 28 11:46:47 2014 +0800
Committer: challenh <ch...@microsoft.com>
Committed: Thu Aug 28 11:46:47 2014 +0800

----------------------------------------------------------------------
 datajs/.gitignore                               |     9 -
 datajs/Gruntfile.js                             |   227 -
 datajs/JSLib.csproj                             |   186 -
 datajs/JSLib.sln                                |    20 -
 datajs/Web.config                               |    34 -
 datajs/demo/mypage.html                         |    28 -
 datajs/demo/scripts/.gitignore                  |     2 -
 datajs/demo/scripts/datajs-1.1.1.js             | 10710 -----------------
 datajs/demo/scripts/datajs-1.1.1.min.js         |    14 -
 datajs/demo/scripts/datajs-1.1.2.js             | 10577 ----------------
 datajs/demo/scripts/datajs-1.1.2.min.js         |    13 -
 datajs/demo/scripts/datajs_demo.js              |   124 -
 datajs/demo/scripts/tools.js                    |   146 -
 datajs/demo/tester.html                         |   217 -
 datajs/demo/testerV2.html                       |    72 -
 .../stripheader/package.json                    |    24 -
 .../stripheader/stripheader.js                  |    21 -
 .../grunt-config/custom-tasks/rat/package.json  |    26 -
 datajs/grunt-config/custom-tasks/rat/readme.md  |     2 -
 .../grunt-config/custom-tasks/rat/tasks/rat.js  |    93 -
 datajs/grunt-config/rat-config.js               |    15 -
 datajs/package.json                             |    42 -
 datajs/packages.config                          |     7 -
 datajs/readme.md                                |    20 -
 datajs/src/banner.txt                           |    19 -
 datajs/src/index.js                             |    33 -
 datajs/src/lib/cache.js                         |  1447 ---
 datajs/src/lib/cache/source.js                  |   206 -
 datajs/src/lib/datajs.js                        |    32 -
 datajs/src/lib/datajs/deferred.js               |   189 -
 datajs/src/lib/datajs/utils.js                  |   582 -
 datajs/src/lib/datajs/xml.js                    |   816 --
 datajs/src/lib/odata.js                         |   178 -
 datajs/src/lib/odata/batch.js                   |   377 -
 datajs/src/lib/odata/handler.js                 |   284 -
 datajs/src/lib/odata/json.js                    |   918 --
 datajs/src/lib/odata/metadata.js                |   523 -
 datajs/src/lib/odata/net.js                     |   340 -
 datajs/src/lib/odata/utils.js                   |  1261 --
 datajs/src/lib/store.js                         |    63 -
 datajs/src/lib/store/dom.js                     |   330 -
 datajs/src/lib/store/indexeddb.js               |   445 -
 datajs/src/lib/store/memory.js                  |   246 -
 datajs/tests-tmp/b-cache-tests.js               |  1191 --
 ...cache-large-collection-functional-tests.html |    53 -
 ...s-cache-large-collection-functional-tests.js |   187 -
 datajs/tests-tmp/bn-odata-json-tests.js         |   211 -
 datajs/tests-tmp/common/ODataVerifiyReader.svc  |   114 -
 datajs/tests-tmp/common/djstest-browser.js      |   142 -
 datajs/tests-tmp/common/djstest.js              |   412 -
 datajs/tests-tmp/common/logging.js              |     5 -
 datajs/tests-tmp/common/mockHttpClient.js       |   138 -
 datajs/tests-tmp/common/node-test-setup.js      |    30 -
 datajs/tests-tmp/common/observableHttpClient.js |    84 -
 datajs/tests-tmp/common/odataCacheVerifier.js   |   241 -
 datajs/tests-tmp/common/odataVerifyReader.js    |   203 -
 datajs/tests-tmp/done.txt                       |    29 -
 .../endpoints/BasicAuthDataService.svc          |   124 -
 .../tests-tmp/endpoints/CustomAnnotations.xml   |   121 -
 .../tests-tmp/endpoints/CustomDataService.svc   |    85 -
 datajs/tests-tmp/endpoints/EpmDataService.svc   |   336 -
 datajs/tests-tmp/endpoints/ErrorDataService.svc |    78 -
 .../endpoints/FoodStoreDataServiceV4.svc        |   590 -
 .../endpoints/LargeCollectionService.svc        |   113 -
 datajs/tests-tmp/endpoints/web.config           |    46 -
 .../tests-tmp/odata-json-tests-todo-analyse.js  |   828 --
 datajs/tests-tmp/odata-qunit-tests-launcher.htm |    61 -
 datajs/tests/cache-tests.js                     |  1191 --
 datajs/tests/code/ReflectionDataContext.cs      |   743 --
 datajs/tests/code/csdlreader.cs                 |   205 -
 datajs/tests/code/jsdate.cs                     |    59 -
 datajs/tests/code/jsonobject.cs                 |    99 -
 datajs/tests/code/readerutils.cs                |    87 -
 datajs/tests/common/CacheOracle.js              |   241 -
 datajs/tests/common/Instrument.js               |    55 -
 datajs/tests/common/Instrument.svc              |    77 -
 datajs/tests/common/ODataReadOracle.js          |   201 -
 datajs/tests/common/ODataReadOracle.svc         |   114 -
 datajs/tests/common/ObservableHttpClient.js     |    84 -
 datajs/tests/common/TestLogger.svc              |   852 --
 datajs/tests/common/TestSynchronizerClient.js   |   229 -
 datajs/tests/common/common.js                   |    25 -
 datajs/tests/common/djstest-browser.js          |   150 -
 datajs/tests/common/djstest.js                  |   419 -
 datajs/tests/common/mockHttpClient.js           |   137 -
 datajs/tests/common/mockXMLHttpRequest.js       |   213 -
 datajs/tests/common/rx.js                       |    26 -
 ...cache-large-collection-functional-tests.html |    53 -
 ...s-cache-large-collection-functional-tests.js |   187 -
 datajs/tests/datajs-cache-long-haul-tests.html  |   194 -
 datajs/tests/datajs-startup-perf-test.html      |   109 -
 datajs/tests/e2etest/Test.html                  |    44 -
 datajs/tests/endpoints/BasicAuthDataService.svc |   124 -
 datajs/tests/endpoints/CustomAnnotations.xml    |   121 -
 datajs/tests/endpoints/CustomDataService.svc    |    85 -
 datajs/tests/endpoints/EpmDataService.svc       |   336 -
 datajs/tests/endpoints/ErrorDataService.svc     |    78 -
 .../tests/endpoints/FoodStoreDataServiceV4.svc  |   590 -
 .../tests/endpoints/LargeCollectionService.svc  |   113 -
 datajs/tests/endpoints/web.config               |    46 -
 datajs/tests/node-test-setup.js                 |    30 -
 datajs/tests/odata-batch-functional-tests.html  |    49 -
 datajs/tests/odata-batch-functional-tests.js    |   291 -
 datajs/tests/odata-batch-tests.js               |   559 -
 .../odata-cache-filter-functional-tests.html    |    52 -
 .../odata-cache-filter-functional-tests.js      |   431 -
 datajs/tests/odata-cache-fperf-tests.html       |    50 -
 datajs/tests/odata-cache-fperf-tests.js         |   115 -
 datajs/tests/odata-cache-functional-tests.html  |    52 -
 datajs/tests/odata-cache-functional-tests.js    |   631 -
 .../tests/odata-cache-rx-functional-tests.html  |    50 -
 datajs/tests/odata-cache-rx-functional-tests.js |    87 -
 datajs/tests/odata-fuzz.html                    |   557 -
 datajs/tests/odata-handler-tests.js             |   364 -
 datajs/tests/odata-json-light-tests.js          |  2492 ----
 datajs/tests/odata-json-parse-tests.html        |    67 -
 datajs/tests/odata-json-parse-tests.js          |   110 -
 datajs/tests/odata-json-tests.js                |   986 --
 datajs/tests/odata-links-functional-tests.html  |    49 -
 datajs/tests/odata-links-functional-tests.js    |   274 -
 ...ata-metadata-awareness-functional-tests.html |    48 -
 ...odata-metadata-awareness-functional-tests.js |   243 -
 datajs/tests/odata-metadata-tests.js            |   499 -
 datajs/tests/odata-net-tests.js                 |   301 -
 datajs/tests/odata-perf-tests.html              |    50 -
 datajs/tests/odata-perf-tests.js                |   242 -
 datajs/tests/odata-qunit-tests.htm              |    76 -
 ...odata-read-crossdomain-functional-tests.html |    49 -
 .../odata-read-crossdomain-functional-tests.js  |   151 -
 datajs/tests/odata-read-functional-tests.html   |    49 -
 datajs/tests/odata-read-functional-tests.js     |   594 -
 .../tests/odata-request-functional-tests.html   |    49 -
 datajs/tests/odata-request-functional-tests.js  |   399 -
 .../tests/odata-roundtrip-functional-tests.js   |   389 -
 datajs/tests/odata-tests.js                     |   322 -
 datajs/tests/odata-xml-tests.js                 |   275 -
 datajs/tests/run-tests.wsf                      |   435 -
 datajs/tests/store-indexeddb-tests.js           |   262 -
 datajs/tests/store-tests.js                     |   705 --
 datajs/tests/test-list.js                       |    26 -
 datajs/tests/test-manager.html                  |   108 -
 odatajs/.gitignore                              |     9 +
 odatajs/Gruntfile.js                            |   227 +
 odatajs/JSLib.csproj                            |   186 +
 odatajs/JSLib.sln                               |    20 +
 odatajs/Web.config                              |    34 +
 odatajs/demo/mypage.html                        |    28 +
 odatajs/demo/scripts/.gitignore                 |     2 +
 odatajs/demo/scripts/datajs-1.1.1.js            | 10710 +++++++++++++++++
 odatajs/demo/scripts/datajs-1.1.1.min.js        |    14 +
 odatajs/demo/scripts/datajs-1.1.2.js            | 10577 ++++++++++++++++
 odatajs/demo/scripts/datajs-1.1.2.min.js        |    13 +
 odatajs/demo/scripts/datajs_demo.js             |   124 +
 odatajs/demo/scripts/tools.js                   |   146 +
 odatajs/demo/tester.html                        |   217 +
 odatajs/demo/testerV2.html                      |    72 +
 .../stripheader/package.json                    |    24 +
 .../stripheader/stripheader.js                  |    21 +
 .../grunt-config/custom-tasks/rat/package.json  |    26 +
 odatajs/grunt-config/custom-tasks/rat/readme.md |     2 +
 .../grunt-config/custom-tasks/rat/tasks/rat.js  |    93 +
 odatajs/grunt-config/rat-config.js              |    15 +
 odatajs/package.json                            |    42 +
 odatajs/packages.config                         |     7 +
 odatajs/readme.md                               |    20 +
 odatajs/src/banner.txt                          |    19 +
 odatajs/src/index.js                            |    33 +
 odatajs/src/lib/cache.js                        |  1447 +++
 odatajs/src/lib/cache/source.js                 |   206 +
 odatajs/src/lib/datajs.js                       |    32 +
 odatajs/src/lib/datajs/deferred.js              |   189 +
 odatajs/src/lib/datajs/utils.js                 |   582 +
 odatajs/src/lib/datajs/xml.js                   |   816 ++
 odatajs/src/lib/odata.js                        |   178 +
 odatajs/src/lib/odata/batch.js                  |   377 +
 odatajs/src/lib/odata/handler.js                |   284 +
 odatajs/src/lib/odata/json.js                   |   918 ++
 odatajs/src/lib/odata/metadata.js               |   523 +
 odatajs/src/lib/odata/net.js                    |   340 +
 odatajs/src/lib/odata/utils.js                  |  1261 ++
 odatajs/src/lib/store.js                        |    63 +
 odatajs/src/lib/store/dom.js                    |   330 +
 odatajs/src/lib/store/indexeddb.js              |   445 +
 odatajs/src/lib/store/memory.js                 |   246 +
 odatajs/tests-tmp/b-cache-tests.js              |  1191 ++
 ...cache-large-collection-functional-tests.html |    53 +
 ...s-cache-large-collection-functional-tests.js |   187 +
 odatajs/tests-tmp/bn-odata-json-tests.js        |   211 +
 odatajs/tests-tmp/common/ODataVerifiyReader.svc |   114 +
 odatajs/tests-tmp/common/djstest-browser.js     |   142 +
 odatajs/tests-tmp/common/djstest.js             |   412 +
 odatajs/tests-tmp/common/logging.js             |     5 +
 odatajs/tests-tmp/common/mockHttpClient.js      |   138 +
 odatajs/tests-tmp/common/node-test-setup.js     |    30 +
 .../tests-tmp/common/observableHttpClient.js    |    84 +
 odatajs/tests-tmp/common/odataCacheVerifier.js  |   241 +
 odatajs/tests-tmp/common/odataVerifyReader.js   |   203 +
 odatajs/tests-tmp/done.txt                      |    29 +
 .../endpoints/BasicAuthDataService.svc          |   124 +
 .../tests-tmp/endpoints/CustomAnnotations.xml   |   121 +
 .../tests-tmp/endpoints/CustomDataService.svc   |    85 +
 odatajs/tests-tmp/endpoints/EpmDataService.svc  |   336 +
 .../tests-tmp/endpoints/ErrorDataService.svc    |    78 +
 .../endpoints/FoodStoreDataServiceV4.svc        |   590 +
 .../endpoints/LargeCollectionService.svc        |   113 +
 odatajs/tests-tmp/endpoints/web.config          |    46 +
 .../tests-tmp/odata-json-tests-todo-analyse.js  |   828 ++
 .../tests-tmp/odata-qunit-tests-launcher.htm    |    61 +
 odatajs/tests/cache-tests.js                    |  1191 ++
 odatajs/tests/code/ReflectionDataContext.cs     |   743 ++
 odatajs/tests/code/csdlreader.cs                |   205 +
 odatajs/tests/code/jsdate.cs                    |    59 +
 odatajs/tests/code/jsonobject.cs                |    99 +
 odatajs/tests/code/readerutils.cs               |    87 +
 odatajs/tests/common/CacheOracle.js             |   241 +
 odatajs/tests/common/Instrument.js              |    55 +
 odatajs/tests/common/Instrument.svc             |    77 +
 odatajs/tests/common/ODataReadOracle.js         |   201 +
 odatajs/tests/common/ODataReadOracle.svc        |   114 +
 odatajs/tests/common/ObservableHttpClient.js    |    84 +
 odatajs/tests/common/TestLogger.svc             |   852 ++
 odatajs/tests/common/TestSynchronizerClient.js  |   229 +
 odatajs/tests/common/common.js                  |    25 +
 odatajs/tests/common/djstest-browser.js         |   150 +
 odatajs/tests/common/djstest.js                 |   419 +
 odatajs/tests/common/mockHttpClient.js          |   137 +
 odatajs/tests/common/mockXMLHttpRequest.js      |   213 +
 odatajs/tests/common/rx.js                      |    26 +
 ...cache-large-collection-functional-tests.html |    53 +
 ...s-cache-large-collection-functional-tests.js |   187 +
 odatajs/tests/datajs-cache-long-haul-tests.html |   194 +
 odatajs/tests/datajs-startup-perf-test.html     |   109 +
 odatajs/tests/e2etest/Test.html                 |    44 +
 .../tests/endpoints/BasicAuthDataService.svc    |   124 +
 odatajs/tests/endpoints/CustomAnnotations.xml   |   121 +
 odatajs/tests/endpoints/CustomDataService.svc   |    85 +
 odatajs/tests/endpoints/EpmDataService.svc      |   336 +
 odatajs/tests/endpoints/ErrorDataService.svc    |    78 +
 .../tests/endpoints/FoodStoreDataServiceV4.svc  |   590 +
 .../tests/endpoints/LargeCollectionService.svc  |   113 +
 odatajs/tests/endpoints/web.config              |    46 +
 odatajs/tests/node-test-setup.js                |    30 +
 odatajs/tests/odata-batch-functional-tests.html |    49 +
 odatajs/tests/odata-batch-functional-tests.js   |   291 +
 odatajs/tests/odata-batch-tests.js              |   559 +
 .../odata-cache-filter-functional-tests.html    |    52 +
 .../odata-cache-filter-functional-tests.js      |   431 +
 odatajs/tests/odata-cache-fperf-tests.html      |    50 +
 odatajs/tests/odata-cache-fperf-tests.js        |   115 +
 odatajs/tests/odata-cache-functional-tests.html |    52 +
 odatajs/tests/odata-cache-functional-tests.js   |   631 +
 .../tests/odata-cache-rx-functional-tests.html  |    50 +
 .../tests/odata-cache-rx-functional-tests.js    |    87 +
 odatajs/tests/odata-fuzz.html                   |   557 +
 odatajs/tests/odata-handler-tests.js            |   364 +
 odatajs/tests/odata-json-light-tests.js         |  2492 ++++
 odatajs/tests/odata-json-parse-tests.html       |    67 +
 odatajs/tests/odata-json-parse-tests.js         |   110 +
 odatajs/tests/odata-json-tests.js               |   986 ++
 odatajs/tests/odata-links-functional-tests.html |    49 +
 odatajs/tests/odata-links-functional-tests.js   |   274 +
 ...ata-metadata-awareness-functional-tests.html |    48 +
 ...odata-metadata-awareness-functional-tests.js |   243 +
 odatajs/tests/odata-metadata-tests.js           |   499 +
 odatajs/tests/odata-net-tests.js                |   301 +
 odatajs/tests/odata-perf-tests.html             |    50 +
 odatajs/tests/odata-perf-tests.js               |   242 +
 odatajs/tests/odata-qunit-tests.htm             |    76 +
 ...odata-read-crossdomain-functional-tests.html |    49 +
 .../odata-read-crossdomain-functional-tests.js  |   151 +
 odatajs/tests/odata-read-functional-tests.html  |    49 +
 odatajs/tests/odata-read-functional-tests.js    |   594 +
 .../tests/odata-request-functional-tests.html   |    49 +
 odatajs/tests/odata-request-functional-tests.js |   399 +
 .../tests/odata-roundtrip-functional-tests.js   |   389 +
 odatajs/tests/odata-tests.js                    |   322 +
 odatajs/tests/odata-xml-tests.js                |   275 +
 odatajs/tests/run-tests.wsf                     |   435 +
 odatajs/tests/store-indexeddb-tests.js          |   262 +
 odatajs/tests/store-tests.js                    |   705 ++
 odatajs/tests/test-list.js                      |    26 +
 odatajs/tests/test-manager.html                 |   108 +
 282 files changed, 56195 insertions(+), 56195 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/.gitignore
----------------------------------------------------------------------
diff --git a/datajs/.gitignore b/datajs/.gitignore
deleted file mode 100644
index d7c3df6..0000000
--- a/datajs/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-node_modules/
-build
-dist
-localgrunt.config
-bin/
-obj/
-packages/
-JSLib.suo
-JSLib.csproj.user

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/Gruntfile.js
----------------------------------------------------------------------
diff --git a/datajs/Gruntfile.js b/datajs/Gruntfile.js
deleted file mode 100644
index bc300e5..0000000
--- a/datajs/Gruntfile.js
+++ /dev/null
@@ -1,227 +0,0 @@
-module.exports = function(grunt) {
-  'use strict';
-  var init = {
-    pkg: grunt.file.readJSON('package.json'),
-    banner: grunt.file.read('src/banner.txt'),
-    filename : '<%= pkg.name %>-<%= pkg.version %>-<%= pkg.postfix %>',
-
-    browserify: {
-      // start with index.js and follow all required source in order pack them together 
-      datajs: {
-        files: {
-          'build/<%= filename %>.js': ['src/index.js'],
-        },
-        options: {
-          transform: ['./grunt-config/browserify_transforms/stripheader/stripheader.js'],
-          browserifyOptions: {
-          } ,
-          bundleOptions: {
-          },
-        }
-      }
-    },
-    uglify: {
-      options: {
-        sourceMap : true,
-        sourceMapName :  'build/<%= filename %>.map',
-        sourceMapIncludeSources :true,
-      },
-      // uglify and compress the packed sources
-      build: {
-        src: 'build/<%= filename %>.js',
-        dest: 'build/<%= filename %>.min.js'
-      }
-    },
-    concat : {
-      options : {
-        banner : '<%= banner %>'
-      },
-      licence_min: {
-        src: 'build/<%= filename %>.min.js',
-        dest: 'build/<%= filename %>.min.js',
-      },
-      licence: {
-        src: 'build/<%= filename %>.js',
-        dest: 'build/<%= filename %>.js',
-      }
-    },
-    copy: {
-      forDemo: {
-        files: [
-          // includes files within path
-          {expand: true, cwd: 'build/', src: ['**'], dest: 'demo/scripts/', filter: 'isFile'},
-        ]
-      }
-    },
-    connect: {
-      demo: {
-        options: {
-          port: 4001 ,
-          hostname: "localhost",
-          base: "demo",
-          keepalive : true,
-          middleware: function (connect, options) {
-            return [
-              require("grunt-connect-proxy/lib/utils").proxyRequest ,
-              connect.static(options.base),   // static content
-              connect.directory(options.base) // browse directories
-            ];
-          },
-        },
-      },
-      // start a node webserver with proxy to host the qunit-test html files
-      'test-browser': {             
-        options: {
-          port: 4003 ,
-          hostname: "localhost",
-          base: "",
-          keepalive : true,
-          //changeOrigin: true,
-          middleware: function (connect, options) {
-            return [
-              require("grunt-connect-proxy/lib/utils").proxyRequest ,
-              connect.static(options.base),   // static content
-              connect.directory(options.base) // browse directories
-            ];
-          },
-        },
-        // proxy all request going to /tests/endpoints/ to the .net data services
-        proxies: [{
-          context: "/tests/endpoints/",  // When the url contains this...
-          host: "localhost",
-          changeOrigin: true,
-          https: false,
-          port: 46541,
-          rejectUnauthorized: false, 
-        }],
-      },
-    },
-    'node-qunit': {   
-      //used to run some background qunit test on node         
-      'default-tests': {
-        setup: {
-          log: {
-            summary: true,
-            assertions: true,
-            errors: true,
-            globalSummary: true,
-            coverage: false,
-            globalCoverage: false,
-            testing: true
-          },
-          coverage: false,
-          deps: null,
-          namespace: null
-        },
-        deps: '',
-        code: './tests-tmp/common/node-test-setup.js',
-        tests: ['./tests-tmp/odata-json-tests.js'],
-        done: function(err, res){
-            !err && publishResults("node", res, this.async());
-        }
-      },
-    },
-    jsdoc : {
-        src : {
-            src: ['src/**/*.js'], 
-            options: {
-                destination: 'build/doc',
-                verbose : false 
-            }
-        },
-        test : {
-            src: ['tests/**/*.js'], 
-            options: {
-                destination: 'build/doc-test',
-                verbose : false 
-            }
-        }
-    },
-    "npm-clean": {
-      tmp: {
-        src: [ "build/tmp"]
-      },
-      doc: {
-        src: ["build/doc"],
-          options: {
-                force: true
-            }
-      },
-      "doc-test": {
-        src: ["build/doc-test"],
-          options: {
-                force: true
-            }
-      },
-    },
-    compress: {
-      build: {
-        options: {archive: 'dist/<%= filename %>-lib.zip'},
-        files: [{expand: true, cwd: 'build/', src: ['*'], filter: 'isFile', dest: '<%= filename %>-lib/'}]
-      },
-      doc: {
-        options: {archive: 'dist/<%= filename %>-doc.zip'},
-        files: [{expand: true, cwd: 'build/doc/', src: ['**'], dest: '<%= filename %>-doc/'}]
-      },
-      src: {
-        options: {archive: 'dist/<%= filename %>-source.zip'},
-        files: [{expand: true, cwd: 'src/', src: ['**'], dest: '<%= filename %>-src/'}]
-      }
-    }
-  };
-  
-  /*** Join local configuration for proxies and local test servers ***/
-  if (grunt.file.exists('localgrunt.config')) {
-    console.log("merge localgrunt.config");
-    var localGrundConfig = grunt.file.read('localgrunt.config');
-    init.connect['test-browser'].proxies = init.connect['test-browser'].proxies.concat(JSON.parse(localGrundConfig).proxies);
-  }
-
-  /*** Init ***/
-  grunt.initConfig(init);
-
-  /*** Load tasks from npm modules ***/
-  grunt.loadNpmTasks('grunt-browserify');
-  grunt.loadNpmTasks('grunt-contrib-uglify');
-  grunt.loadNpmTasks("grunt-connect-proxy");
-  grunt.loadNpmTasks("grunt-contrib-connect");
-  grunt.loadNpmTasks("grunt-contrib-copy");
-  grunt.loadNpmTasks("grunt-contrib-concat");
-  grunt.loadNpmTasks('grunt-contrib-compress');
-  grunt.loadNpmTasks("grunt-jsdoc");
-
-
-  //    Start Qunit tests direcly in node js, internally qunit (npm qunit) 
-  //    is used, no phantomjs instance required
-  grunt.loadNpmTasks('grunt-node-qunit'); 
-  grunt.loadNpmTasks('grunt-contrib-clean');
-
-  //    Load the custom-* tasks from the grunt-config directory
-  grunt.loadTasks('grunt-config');
-
-  //    rename some tasks to avoid name clashes with the user tasks
-  grunt.renameTask('clean','npm-clean');
-  
-
-  /*** E N D U S E R   T A S K S ***/
-
-  grunt.registerTask('clean', ['npm-clean:doc','npm-clean:tmp']);
-
-  //    Runs the license header check to verify the any source file contains a license header
-  grunt.registerTask('license-check', ['custom-license-check']);
-
-  //    Create documentation in /build/doc
-  grunt.registerTask('doc', [/*'npm-clean:doc',*/'jsdoc:src']);
-  grunt.registerTask('doc-test', [/*'npm-clean:doc-test',*/'jsdoc:test']);
-
-  //    Build the odatajs library
-  grunt.registerTask('build', ['browserify:datajs', 'uglify:build', 'concat','copy:forDemo']);
-
-
-  grunt.registerTask('test-browser', ['configureProxies:test-browser', 'connect:test-browser']);
-  grunt.registerTask('test-node', ['node-qunit:default-tests']);
-  grunt.registerTask('release', ['build','doc','compress']);
-
-  
-};
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/JSLib.csproj
----------------------------------------------------------------------
diff --git a/datajs/JSLib.csproj b/datajs/JSLib.csproj
deleted file mode 100644
index c2c3906..0000000
--- a/datajs/JSLib.csproj
+++ /dev/null
@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>
-    </ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}</ProjectGuid>
-    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>JSLib</RootNamespace>
-    <AssemblyName>JSLib</AssemblyName>
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <SccProjectName>SAK</SccProjectName>
-    <SccLocalPath>SAK</SccLocalPath>
-    <SccAuxPath>SAK</SccAuxPath>
-    <SccProvider>SAK</SccProvider>
-    <UseIISExpress>false</UseIISExpress>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Content Include="src\index.js" />
-    <Content Include="src\banner.txt" />
-    <Content Include="src\lib\cache.js" />
-    <Content Include="src\lib\datajs.js" />
-    <Content Include="src\lib\odata.js" />
-    <Content Include="src\lib\store.js" />
-    <Content Include="src\lib\cache\source.js" />
-    <Content Include="src\lib\datajs\deferred.js" />
-    <Content Include="src\lib\datajs\utils.js" />
-    <Content Include="src\lib\datajs\xml.js" />
-    <Content Include="src\lib\odata\batch.js" />
-    <Content Include="src\lib\odata\handler.js" />
-    <Content Include="src\lib\odata\json.js" />
-    <Content Include="src\lib\odata\metadata.js" />
-    <Content Include="src\lib\odata\net.js" />
-    <Content Include="src\lib\odata\utils.js" />
-    <Content Include="src\lib\store\dom.js" />
-    <Content Include="src\lib\store\indexeddb.js" />
-    <Content Include="src\lib\store\memory.js" />
-    <Content Include="tests\cache-tests.js" />
-    <Content Include="tests\common\CacheOracle.js" />
-    <Content Include="tests\common\common.js" />
-    <Content Include="tests\common\Instrument.svc" />
-    <Content Include="tests\common\Instrument.js" />
-    <Content Include="tests\common\mockXMLHttpRequest.js" />
-    <Content Include="tests\common\mockHttpClient.js" />
-    <Content Include="tests\common\djstest.js" />
-    <Content Include="tests\common\gpo-ie8-tour-disable.reg" />
-    <Content Include="tests\common\ObservableHttpClient.js" />
-    <Content Include="tests\common\ODataReadOracle.js" />
-    <Content Include="tests\common\ODataReadOracle.svc" />
-    <Content Include="tests\common\rx.js" />
-    <Content Include="tests\common\TestLogger.svc" />
-    <Content Include="tests\common\TestSynchronizerClient.js" />
-    <Content Include="tests\e2etest\Test.html" />
-    <Content Include="tests\odata-json-light-tests.js" />
-    <Content Include="tests\datajs-startup-perf-test.html" />
-    <Content Include="tests\endpoints\BasicAuthDataService.svc" />
-    <Content Include="tests\endpoints\FoodStoreDataServiceV4.svc" />
-    <Content Include="tests\endpoints\CustomAnnotations.xml" />
-    <Content Include="tests\endpoints\CustomDataService.svc" />
-    <Content Include="tests\endpoints\EpmDataService.svc" />
-    <Content Include="tests\endpoints\ErrorDataService.svc" />
-    <Content Include="tests\endpoints\LargeCollectionService.svc" />
-    <Content Include="tests\endpoints\web.config" />
-    <Content Include="tests\datajs-cache-large-collection-functional-tests.html" />
-    <Content Include="tests\datajs-cache-large-collection-functional-tests.js" />
-    <Content Include="tests\datajs-cache-long-haul-tests.html" />
-    <Content Include="tests\odata-batch-functional-tests.html" />
-    <Content Include="tests\odata-batch-functional-tests.js" />
-    <Content Include="tests\odata-batch-tests.js" />
-    <Content Include="tests\odata-cache-filter-functional-tests.html" />
-    <Content Include="tests\odata-cache-filter-functional-tests.js" />
-    <Content Include="tests\odata-cache-fperf-tests.html" />
-    <Content Include="tests\odata-cache-fperf-tests.js" />
-    <Content Include="tests\odata-cache-functional-tests.html" />
-    <Content Include="tests\odata-cache-functional-tests.js" />
-    <Content Include="tests\odata-cache-rx-functional-tests.html" />
-    <Content Include="tests\odata-cache-rx-functional-tests.js" />
-    <Content Include="tests\odata-fuzz.html" />
-    <Content Include="tests\odata-metadata-tests.js" />
-    <Content Include="tests\odata-handler-tests.js" />
-    <Content Include="tests\odata-json-tests.js" />
-    <Content Include="tests\odata-links-functional-tests.html" />
-    <Content Include="tests\odata-links-functional-tests.js" />
-    <Content Include="tests\odata-metadata-awareness-functional-tests.html" />
-    <Content Include="tests\odata-metadata-awareness-functional-tests.js" />
-    <Content Include="tests\odata-net-tests.js" />
-    <Content Include="tests\odata-perf-tests.html" />
-    <Content Include="tests\odata-perf-tests.js" />
-    <Content Include="tests\odata-read-crossdomain-functional-tests.html" />
-    <Content Include="tests\odata-read-crossdomain-functional-tests.js" />
-    <Content Include="tests\odata-read-functional-tests.html" />
-    <Content Include="tests\odata-request-functional-tests.html" />
-    <Content Include="tests\odata-request-functional-tests.js" />
-    <Content Include="tests\odata-read-functional-tests.js" />
-    <Content Include="tests\odata-qunit-tests.htm" />
-    <Content Include="tests\odata-tests.js" />
-    <Content Include="tests\odata-xml-tests.js" />
-    <Content Include="tests\run-tests.wsf" />
-    <Content Include="tests\store-indexeddb-tests.js" />
-    <Content Include="tests\store-tests.js" />
-    <Content Include="tests\test-list.js" />
-    <Content Include="tests\test-manager.html" />
-    <!-- Configuration file for the web project. -->
-    <Content Include="Web.config">
-      <SubType>Designer</SubType>
-    </Content>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="tests\code\CsdlReader.cs" />
-    <Compile Include="tests\code\JsDate.cs" />
-    <Compile Include="tests\code\JsonObject.cs" />
-    <Compile Include="tests\code\ReaderUtils.cs" />
-    <Compile Include="tests\code\ReflectionDataContext.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="packages.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <Reference Include="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>packages\Microsoft.OData.Client.6.5.0\lib\net40\Microsoft.OData.Client.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.OData.Core">
-      <HintPath>packages\Microsoft.OData.Core.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.OData.Core.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.OData.Edm">
-      <HintPath>packages\Microsoft.OData.Edm.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.OData.Edm.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>packages\Microsoft.OData.Service.6.5.0\lib\net40\Microsoft.OData.Service.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.Spatial">
-      <HintPath>packages\Microsoft.Spatial.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Spatial.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Net" />
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.ServiceModel" />
-    <Reference Include="System.ServiceModel.Activation" />
-    <Reference Include="System.ServiceModel.Web" />
-    <Reference Include="System.Web.Extensions" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Xml.Linq" />
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
-  <ProjectExtensions>
-    <VisualStudio>
-      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
-        <WebProjectProperties>
-          <UseIIS>False</UseIIS>
-          <AutoAssignPort>True</AutoAssignPort>
-          <DevelopmentServerPort>4002</DevelopmentServerPort>
-          <DevelopmentServerVPath>/</DevelopmentServerVPath>
-          <IISUrl>
-          </IISUrl>
-          <NTLMAuthentication>False</NTLMAuthentication>
-          <UseCustomServer>False</UseCustomServer>
-          <CustomServerUrl>
-          </CustomServerUrl>
-          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
-        </WebProjectProperties>
-      </FlavorProperties>
-    </VisualStudio>
-  </ProjectExtensions>
-</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/JSLib.sln
----------------------------------------------------------------------
diff --git a/datajs/JSLib.sln b/datajs/JSLib.sln
deleted file mode 100644
index d265e52..0000000
--- a/datajs/JSLib.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JSLib", "JSLib.csproj", "{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/Web.config
----------------------------------------------------------------------
diff --git a/datajs/Web.config b/datajs/Web.config
deleted file mode 100644
index e45c79e..0000000
--- a/datajs/Web.config
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <system.web>
-    <compilation debug="true" targetFramework="4.0">
-      <assemblies>
-        <add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
-        <add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
-        <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
-        <add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
-        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
-        <add assembly="System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
-        <add assembly="System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
-        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-      </assemblies>
-    </compilation>
-  </system.web>
-  <system.webServer>
-    <directoryBrowse enabled="true" />
-  </system.webServer>
-  <system.codedom>
-    <compilers>
-      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-        <providerOption name="CompilerVersion" value="v4.0" />
-      </compiler>
-    </compilers>
-  </system.codedom>
-  <system.net>
-    <defaultProxy>
-      <proxy autoDetect="True" />
-    </defaultProxy>
-  </system.net>
-</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/mypage.html
----------------------------------------------------------------------
diff --git a/datajs/demo/mypage.html b/datajs/demo/mypage.html
deleted file mode 100644
index 16517a4..0000000
--- a/datajs/demo/mypage.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>data js demo</title>
-    <script type="text/javascript" src="scripts/datajs-2.0.0.js"></script>
-    <script type="text/javascript" src="scripts/jquery-2.0.3.js"></script>
-    <script type="text/javascript" src="scripts/datajs_demo.js"></script>
-    <style type="text/css">.title { font-size: 30px;font-style: italic;}</style>
-</head>
-<body onload="run()"> 
-    <div>
-        <span class="title">Simple Read</span>
-        <pre id="simpleRead"></pre>
-    </div>
-    <div>
-        <span class="title">Simple Read With Metadata</span>
-        <pre id="simpleReadWithMetadata"></pre>
-    </div>
-    <div>
-        <span class="title">Simple Read with JSONP</span>
-        <pre id="simpleReadWithJSONP"></pre>
-    </div>
-    <div>
-        <span class="title">Metadata</span>
-        <pre id="metadata"></pre>
-    </div>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/.gitignore
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/.gitignore b/datajs/demo/scripts/.gitignore
deleted file mode 100644
index f7f55d4..0000000
--- a/datajs/demo/scripts/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-datajs-2*
-tmp/


[35/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/rx.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/rx.js b/datajs/tests/common/rx.js
deleted file mode 100644
index f71e959..0000000
--- a/datajs/tests/common/rx.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- 
-// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
-// This code is licensed by Microsoft Corporation under the terms
-// of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
-// See http://go.microsoft.com/fwlink/?LinkId=186234.
-
-(function(){var a;var b;var c=this;var d="Index out of range";if(typeof ProvideCustomRxRootObject =="undefined")b=c.Rx={}; else b=ProvideCustomRxRootObject();var e=function(){};var f=function(){return new Date().getTime();};var g=function(r0,s0){return r0===s0;};var h=function(r0){return r0;};var i=function(r0){return {Dispose:r0};};var j={Dispose:e};b.Disposable={Create:i,Empty:j};var k=b.BooleanDisposable=function(){var r0=false;this.GetIsDisposed=function(){return r0;};this.Dispose=function(){r0=true;};};var l=function(r0){var s0=false;r0.a++;this.Dispose=function(){var t0=false;if(!r0.b){if(!this.c){this.c=true;r0.a--;if(r0.a==0&&r0.d){r0.b=true;t0=true;}}}if(t0)r0.e.Dispose();};};var m=b.RefCountDisposable=function(r0){this.d=false;this.b=false;this.e=r0;this.a=0;this.Dispose=function(){var s0=false;if(!this.b){if(!this.d){this.d=true;if(this.a==0){this.b=true;s0=true;}}}if(s0)this.e.Dispose();};this.GetDisposable=function(){if(this.b)return j; else return new l(this);};};var n
 =b.CompositeDisposable=function(){var r0=new q();for(var s0=0;s0<arguments.length;s0++) r0.Add(arguments[s0]);var t0=false;this.GetCount=function(){return r0.GetCount();};this.Add=function(u0){if(!t0)r0.Add(u0); else u0.Dispose();};this.Remove=function(u0,v0){if(!t0){var w0=r0.Remove(u0);if(!v0&w0)u0.Dispose();}};this.Dispose=function(){if(!t0){t0=true;this.Clear();}};this.Clear=function(){for(var u0=0;u0<r0.GetCount();u0++) r0.GetItem(u0).Dispose();r0.Clear();};};var o=b.MutableDisposable=function(){var r0=false;var s0;this.Get=function(){return s0;},this.Replace=function(t0){if(r0&&t0!==a)t0.Dispose(); else{if(s0!==a)s0.Dispose();s0=t0;}};this.Dispose=function(){if(!r0){r0=true;if(s0!==a)s0.Dispose();}};};var p=function(r0){var s0=[];for(var t0=0;t0<r0.length;t0++) s0.push(r0[t0]);return s0;};var q=b.List=function(r0){var s0=[];var t0=0;var u0=r0!==a?r0:g;this.Add=function(v0){s0[t0]=v0;t0++;};this.RemoveAt=function(v0){if(v0<0||v0>=t0)throw d;if(v0==0){s0.shift();t0--;}else{s0.sp
 lice(v0,1);t0--;}};this.IndexOf=function(v0){for(var w0=0;w0<t0;w0++){if(u0(v0,s0[w0]))return w0;}return -1;};this.Remove=function(v0){var w0=this.IndexOf(v0);if(w0==-1)return false;this.RemoveAt(w0);return true;};this.Clear=function(){s0=[];t0=0;};this.GetCount=function(){return t0;};this.GetItem=function(v0){if(v0<0||v0>=t0)throw d;return s0[v0];};this.SetItem=function(v0,w0){if(v0<0||v0>=t0)throw d;s0[v0]=w0;};this.ToArray=function(){var v0=[];for(var w0=0;w0<this.GetCount();w0++) v0.push(this.GetItem(w0));return v0;};};var r=function(r0){if(r0===null)r0=g;this.f=r0;var s0=4;this.g=new Array(s0);this.h=0;};r.prototype.i=function(r0,s0){return this.f(this.g[r0],this.g[s0])<0;};r.prototype.j=function(r0){if(r0>=this.h||r0<0)return;var s0=r0-1>>1;if(s0<0||s0==r0)return;if(this.i(r0,s0)){var t0=this.g[r0];this.g[r0]=this.g[s0];this.g[s0]=t0;this.j(s0);}};r.prototype.k=function(r0){if(r0===a)r0=0;var s0=2*r0+1;var t0=2*r0+2;var u0=r0;if(s0<this.h&&this.i(s0,u0))u0=s0;if(t0<this.h&&thi
 s.i(t0,u0))u0=t0;if(u0!=r0){var v0=this.g[r0];this.g[r0]=this.g[u0];this.g[u0]=v0;this.k(u0);}};r.prototype.GetCount=function(){return this.h;};r.prototype.Peek=function(){if(this.h==0)throw "Heap is empty.";return this.g[0];};r.prototype.Dequeue=function(){var r0=this.Peek();this.g[0]=this.g[--this.h];delete this.g[this.h];this.k();return r0;};r.prototype.Enqueue=function(r0){var s0=this.h++;this.g[s0]=r0;this.j(s0);};var s=b.Scheduler=function(r0,s0,t0){this.Schedule=r0;this.ScheduleWithTime=s0;this.Now=t0;this.ScheduleRecursive=function(u0){var v0=this;var w0=new n();var x0;x0=function(){u0(function(){var y0=false;var z0=false;var A0;A0=v0.Schedule(function(){x0();if(y0)w0.Remove(A0); else z0=true;});if(!z0){w0.Add(A0);y0=true;}});};w0.Add(v0.Schedule(x0));return w0;};this.ScheduleRecursiveWithTime=function(u0,v0){var w0=this;var x0=new n();var y0;y0=function(){u0(function(z0){var A0=false;var B0=false;var C0;C0=w0.ScheduleWithTime(function(){y0();if(A0)x0.Remove(C0); else B0=tru
 e;},z0);if(!B0){x0.Add(C0);A0=true;}});};x0.Add(w0.ScheduleWithTime(y0,v0));return x0;};};var t=b.VirtualScheduler=function(r0,s0,t0,u0){var v0=new s(function(w0){return this.ScheduleWithTime(w0,0);},function(w0,x0){return this.ScheduleVirtual(w0,u0(x0));},function(){return t0(this.l);});v0.ScheduleVirtual=function(w0,x0){var y0=new k();var z0=s0(this.l,x0);var A0=function(){if(!y0.IsDisposed)w0();};var B0=new y(A0,z0);this.m.Enqueue(B0);return y0;};v0.Run=function(){while(this.m.GetCount()>0){var w0=this.m.Dequeue();this.l=w0.n;w0.o();}};v0.RunTo=function(w0){while(this.m.GetCount()>0&&this.f(this.m.Peek().n,w0)<=0){var x0=this.m.Dequeue();this.l=x0.n;x0.o();}};v0.GetTicks=function(){return this.l;};v0.l=0;v0.m=new r(function(w0,x0){return r0(w0.n,x0.n);});v0.f=r0;return v0;};var u=b.TestScheduler=function(){var r0=new t(function(s0,t0){return s0-t0;},function(s0,t0){return s0+t0;},function(s0){return new Date(s0);},function(s0){if(s0<=0)return 1;return s0;});return r0;};var v=new 
 s(function(r0){return this.ScheduleWithTime(r0,0);},function(r0,s0){var t0=this.Now()+s0;var u0=new y(r0,t0);if(this.m===a){var v0=new w();try{this.m.Enqueue(u0);v0.p();}finally{v0.q();}}else this.m.Enqueue(u0);return u0.r();},f);v.s=function(r0){if(this.m===a){var s0=new w();try{r0();s0.p();}finally{s0.q();}}else r0();};s.CurrentThread=v;var w=function(){v.m=new r(function(r0,s0){try{return r0.n-s0.n;}catch(t0){debugger;}});this.q=function(){v.m=a;};this.p=function(){while(v.m.GetCount()>0){var r0=v.m.Dequeue();if(!r0.t()){while(r0.n-v.Now()>0);if(!r0.t())r0.o();}}};};var x=0;var y=function(r0,s0){this.u=x++;this.o=r0;this.n=s0;this.v=new k();this.t=function(){return this.v.GetIsDisposed();};this.r=function(){return this.v;};};var z=new s(function(r0){r0();return j;},function(r0,s0){while(this.Now<s0);r0();},f);s.Immediate=z;var A=new s(function(r0){var s0=c.setTimeout(r0,0);return i(function(){c.clearTimeout(s0);});},function(r0,s0){var t0=c.setTimeout(r0,s0);return i(function(){c
 .clearTimeout(t0);});},f);s.Timeout=A;var B=b.Observer=function(r0,s0,t0){this.OnNext=r0===a?e:r0;this.OnError=s0===a?function(u0){throw u0;}:s0;this.OnCompleted=t0===a?e:t0;this.AsObserver=function(){var u0=this;return new B(function(v0){u0.OnNext(v0);},function(v0){u0.OnError(v0);},function(){u0.OnCompleted();});};};var C=B.Create=function(r0,s0,t0){return new B(r0,s0,t0);};var D=b.Observable=function(r0){this.w=r0;};var E=D.CreateWithDisposable=function(r0){return new D(r0);};var F=D.Create=function(r0){return E(function(s0){return i(r0(s0));});};var G=function(){return this.Select(function(r0){return r0.Value;});};D.prototype={Subscribe:function(r0,s0,t0){var u0;if(arguments.length==0||arguments.length>1||typeof r0 =="function")u0=new B(r0,s0,t0); else u0=r0;return this.x(u0);},x:function(r0){var s0=false;var t0=new o();var u0=this;v.s(function(){var v0=new B(function(w0){if(!s0)r0.OnNext(w0);},function(w0){if(!s0){s0=true;t0.Dispose();r0.OnError(w0);}},function(){if(!s0){s0=tru
 e;t0.Dispose();r0.OnCompleted();}});t0.Replace(u0.w(v0));});return new n(t0,i(function(){s0=true;}));},Select:function(r0){var s0=this;return E(function(t0){var u0=0;return s0.Subscribe(new B(function(v0){var w0;try{w0=r0(v0,u0++);}catch(x0){t0.OnError(x0);return;}t0.OnNext(w0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},Let:function(r0,s0){if(s0===a)return r0(this);var t0=this;return E(function(u0){var v0=s0();var w0;try{w0=r0(v0);}catch(A0){return L(A0).Subscribe(u0);}var x0=new o();var y0=new o();var z0=new n(y0,x0);x0.Replace(w0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){u0.OnError(A0);z0.Dispose();},function(){u0.OnCompleted();z0.Dispose();}));y0.Replace(t0.Subscribe(v0));return z0;});},MergeObservable:function(){var r0=this;return E(function(s0){var t0=false;var u0=new n();var v0=new o();u0.Add(v0);v0.Replace(r0.Subscribe(function(w0){var x0=new o();u0.Add(x0);x0.Replace(w0.Subscribe(function(y0){s0.OnNext(y0);},function(y0){s0.OnError(y0);},f
 unction(){u0.Remove(x0);if(u0.GetCount()==1&&t0)s0.OnCompleted();}));},function(w0){s0.OnError(w0);},function(){t0=true;if(u0.GetCount()==1)s0.OnCompleted();}));return u0;});},y:function(r0,s0){var t0=p(s0);t0.unshift(this);return r0(t0);},Concat:function(){return this.y(I,arguments);},Merge:function(){return this.y(H,arguments);},Catch:function(){return this.y(P,arguments);},OnErrorResumeNext:function(){return this.y(V,arguments);},Zip:function(r0,s0){var t0=this;return E(function(u0){var v0=false;var w0=[];var x0=[];var y0=false;var z0=false;var A0=new n();var B0=function(C0){A0.Dispose();w0=a;x0=a;u0.OnError(C0);};A0.Add(t0.Subscribe(function(C0){if(z0){u0.OnCompleted();return;}if(x0.length>0){var D0=x0.shift();var E0;try{E0=s0(C0,D0);}catch(F0){A0.Dispose();u0.OnError(F0);return;}u0.OnNext(E0);}else w0.push(C0);},B0,function(){if(z0){u0.OnCompleted();return;}y0=true;}));A0.Add(r0.Subscribe(function(C0){if(y0){u0.OnCompleted();return;}if(w0.length>0){var D0=w0.shift();var E0;try{
 E0=s0(D0,C0);}catch(F0){A0.Dispose();u0.OnError(F0);return;}u0.OnNext(E0);}else x0.push(C0);},B0,function(){if(y0){u0.OnCompleted();return;}z0=true;}));return A0;});},CombineLatest:function(r0,s0){var t0=this;return E(function(u0){var v0=false;var w0=false;var x0=false;var y0;var z0;var A0=false;var B0=false;var C0=new n();var D0=function(E0){C0.Dispose();u0.OnError(E0);};C0.Add(t0.Subscribe(function(E0){if(B0){u0.OnCompleted();return;}if(x0){var F0;try{F0=s0(E0,z0);}catch(G0){C0.Dispose();u0.OnError(G0);return;}u0.OnNext(F0);}y0=E0;w0=true;},D0,function(){if(B0){u0.OnCompleted();return;}A0=true;}));C0.Add(r0.Subscribe(function(E0){if(A0){u0.OnCompleted();return;}if(w0){var F0;try{F0=s0(y0,E0);}catch(G0){C0.Dispose();u0.OnError(G0);return;}u0.OnNext(F0);}z0=E0;x0=true;},D0,function(){if(A0){u0.OnCompleted();return;}B0=true;}));});},Switch:function(){var r0=this;return E(function(s0){var t0=false;var u0=new o();var v0=new o();v0.Replace(r0.Subscribe(function(w0){if(!t0){var x0=new o(
 );x0.Replace(w0.Subscribe(function(y0){s0.OnNext(y0);},function(y0){v0.Dispose();u0.Dispose();s0.OnError(y0);},function(){u0.Replace(a);if(t0)s0.OnCompleted();}));u0.Replace(x0);}},function(w0){u0.Dispose();s0.OnError(w0);},function(){t0=true;if(u0.Get()===a)s0.OnCompleted();}));return new n(v0,u0);});},TakeUntil:function(r0){var s0=this;return E(function(t0){var u0=new n();u0.Add(r0.Subscribe(function(){t0.OnCompleted();u0.Dispose();},function(v0){t0.OnError(v0);},function(){}));u0.Add(s0.Subscribe(t0));return u0;});},SkipUntil:function(r0){var s0=this;return E(function(t0){var u0=true;var v0=new n();v0.Add(r0.Subscribe(function(){u0=false;},function(w0){t0.OnError(w0);},e));v0.Add(s0.Subscribe(new B(function(w0){if(!u0)t0.OnNext(w0);},function(w0){t0.OnError(w0);},function(){if(!u0)t0.OnCompleted();})));return v0;});},Scan1:function(r0){var s0=this;return O(function(){var t0;var u0=false;return s0.Select(function(v0){if(u0)t0=r0(t0,v0); else{t0=v0;u0=true;}return t0;});});},Scan:f
 unction(r0,s0){var t0=this;return O(function(){var u0;var v0=false;return t0.Select(function(w0){if(v0)u0=s0(u0,w0); else{u0=s0(r0,w0);v0=true;}return u0;});});},Scan0:function(r0,s0){var t0=this;return E(function(u0){var v0=r0;var w0=true;return t0.Subscribe(function(x0){if(w0){w0=false;u0.OnNext(v0);}try{v0=s0(v0,x0);}catch(y0){u0.OnError(y0);return;}u0.OnNext(v0);},function(x0){if(w0)u0.OnNext(v0);u0.OnError(x0);},function(){if(w0)u0.OnNext(v0);u0.OnCompleted();});});},Finally:function(r0){var s0=this;return F(function(t0){var u0=s0.Subscribe(t0);return function(){try{u0.Dispose();r0();}catch(v0){r0();throw v0;}};});},Do:function(r0,s0,t0){var u0;if(arguments.length==0||arguments.length>1||typeof r0 =="function")u0=new B(r0,s0!==a?s0:e,t0); else u0=r0;var v0=this;return E(function(w0){return v0.Subscribe(new B(function(x0){try{u0.OnNext(x0);}catch(y0){w0.OnError(y0);return;}w0.OnNext(x0);},function(x0){if(s0!==a)try{u0.OnError(x0);}catch(y0){w0.OnError(y0);return;}w0.OnError(x0);
 },function(){if(t0!==a)try{u0.OnCompleted();}catch(x0){w0.OnError(x0);return;}w0.OnCompleted();}));});},Where:function(r0){var s0=this;return E(function(t0){var u0=0;return s0.Subscribe(new B(function(v0){var w0=false;try{w0=r0(v0,u0++);}catch(x0){t0.OnError(x0);return;}if(w0)t0.OnNext(v0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},Take:function(r0,s0){if(s0===a)s0=z;var t0=this;return E(function(u0){if(r0<=0){t0.Subscribe().Dispose();return N(s0).Subscribe(u0);}var v0=r0;return t0.Subscribe(new B(function(w0){if(v0-->0){u0.OnNext(w0);if(v0==0)u0.OnCompleted();}},function(w0){u0.OnError(w0);},function(){u0.OnCompleted();}));});},GroupBy:function(r0,s0,t0){if(r0===a)r0=h;if(s0===a)s0=h;if(t0===a)t0=function(v0){return v0.toString();};var u0=this;return E(function(v0){var w0={};var x0=new o();var y0=new m(x0);x0.Replace(u0.Subscribe(function(z0){var A0;try{A0=r0(z0);}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}var B0=false;var C0;try
 {var D0=t0(A0);if(w0[D0]===a){C0=new i0();w0[D0]=C0;B0=true;}else C0=w0[D0];}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}if(B0){var E0=E(function(G0){return new n(y0.GetDisposable(),C0.Subscribe(G0));});E0.Key=A0;v0.OnNext(E0);}var F0;try{F0=s0(z0);}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}C0.OnNext(F0);},function(z0){for(var A0 in w0) w0[A0].OnError(z0);v0.OnError(z0);},function(){for(var z0 in w0) w0[z0].OnCompleted();v0.OnCompleted();}));return y0;});},TakeWhile:function(r0){var s0=this;return E(function(t0){var u0=true;return s0.Subscribe(new B(function(v0){if(u0){try{u0=r0(v0);}catch(w0){t0.OnError(w0);return;}if(u0)t0.OnNext(v0); else t0.OnCompleted();}},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},SkipWhile:function(r0){var s0=this;return E(function(t0){var u0=false;return s0.Subscribe(new B(function(v0){if(!u0)try{u0=!r0(v0);}catch(w0){t0.OnError(w0);return;}if(u0)t0.OnNext(v0);},function(v0){t0.OnE
 rror(v0);},function(){t0.OnCompleted();}));});},Skip:function(r0){var s0=this;return E(function(t0){var u0=r0;return s0.Subscribe(new B(function(v0){if(u0--<=0)t0.OnNext(v0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},SelectMany:function(r0){return this.Select(r0).MergeObservable();},TimeInterval:function(r0){if(r0===a)r0=z;var s0=this;return O(function(){var t0=r0.Now();return s0.Select(function(u0){var v0=r0.Now();var w0=v0-t0;t0=v0;return {Interval:w0,Value:u0};});});},RemoveInterval:G,Timestamp:function(r0){if(r0===a)r0=z;return this.Select(function(s0){return {Timestamp:r0.Now(),Value:s0};});},RemoveTimestamp:G,Materialize:function(){var r0=this;return E(function(s0){return r0.Subscribe(new B(function(t0){s0.OnNext(new h0("N",t0));},function(t0){s0.OnNext(new h0("E",t0));s0.OnCompleted();},function(){s0.OnNext(new h0("C"));s0.OnCompleted();}));});},Dematerialize:function(){return this.SelectMany(function(r0){return r0;});},AsObservable:function(){var r0
 =this;return E(function(s0){return r0.Subscribe(s0);});},Delay:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0=[];var w0=false;var x0=new o();var y0=t0.Materialize().Timestamp().Subscribe(function(z0){if(z0.Value.Kind=="E"){u0.OnError(z0.Value.Value);v0=[];if(w0)x0.Dispose();return;}v0.push({Timestamp:s0.Now()+r0,Value:z0.Value});if(!w0){x0.Replace(s0.ScheduleRecursiveWithTime(function(A0){var B0;do{B0=a;if(v0.length>0&&v0[0].Timestamp<=s0.Now())B0=v0.shift().Value;if(B0!==a)B0.Accept(u0);}while(B0!==a);if(v0.length>0){A0(Math.max(0,v0[0].Timestamp-s0.Now()));w0=true;}else w0=false;},r0));w0=true;}});return new n(y0,x0);});},Throttle:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0;var w0=false;var x0=new o();var y0=0;var z0=t0.Subscribe(function(A0){w0=true;v0=A0;y0++;var B0=y0;x0.Replace(s0.ScheduleWithTime(function(){if(w0&&y0==B0)u0.OnNext(v0);w0=false;},r0));},function(A0){x0.Dispose();u0.OnError(A0);w0=false;y0++;},function(){x0.D
 ispose();if(w0)u0.OnNext(v0);u0.OnCompleted();w0=false;y0++;});return new n(z0,x0);});},Timeout:function(r0,s0,t0){if(t0===a)t0=A;if(s0===a)s0=L("Timeout",t0);var u0=this;return E(function(v0){var w0=new o();var x0=new o();var y0=0;var z0=y0;var A0=false;x0.Replace(t0.ScheduleWithTime(function(){A0=y0==z0;if(A0)w0.Replace(s0.Subscribe(v0));},r0));w0.Replace(u0.Subscribe(function(B0){var C0=0;if(!A0){y0++;C0=y0;v0.OnNext(B0);x0.Replace(t0.ScheduleWithTime(function(){A0=y0==C0;if(A0)w0.Replace(s0.Subscribe(v0));},r0));}},function(B0){if(!A0){y0++;v0.OnError(B0);}},function(){if(!A0){y0++;v0.OnCompleted();}}));return new n(w0,x0);});},Sample:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0=false;var w0;var x0=false;var y0=new n();y0.Add(Y(r0,s0).Subscribe(function(z0){if(v0){u0.OnNext(w0);v0=false;}if(x0)u0.OnCompleted();},function(z0){u0.OnError(z0);},function(){u0.OnCompleted();}));y0.Add(t0.Subscribe(function(z0){v0=true;w0=z0;},function(z0){u0.OnError(z0);y0.
 Dispose();},function(){x0=true;}));return y0;});},Repeat:function(r0,s0){var t0=this;if(s0===a)s0=z;if(r0===a)r0=-1;return E(function(u0){var v0=r0;var w0=new o();var x0=new n(w0);var y0=function(z0){w0.Replace(t0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){u0.OnError(A0);},function(){if(v0>0){v0--;if(v0==0){u0.OnCompleted();return;}}z0();}));};x0.Add(s0.ScheduleRecursive(y0));return x0;});},Retry:function(r0,s0){var t0=this;if(s0===a)s0=z;if(r0===a)r0=-1;return E(function(u0){var v0=r0;var w0=new o();var x0=new n(w0);var y0=function(z0){w0.Replace(t0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){if(v0>0){v0--;if(v0==0){u0.OnError(A0);return;}}z0();},function(){u0.OnCompleted();}));};x0.Add(s0.ScheduleRecursive(y0));return x0;});},BufferWithTime:function(r0,s0,t0){if(t0===a)t0=A;if(s0===a)s0=r0;var u0=this;return E(function(v0){var w0=new q();var x0=t0.Now();var y0=function(){var C0=[];for(var D0=0;D0<w0.GetCount();D0++){var E0=w0.GetItem(D0);if(E0.Timestamp-x0>=0)C0.p
 ush(E0.Value);}return C0;};var z0=new n();var A0=function(C0){v0.OnError(C0);};var B0=function(){v0.OnNext(y0());v0.OnCompleted();};z0.Add(u0.Subscribe(function(C0){w0.Add({Value:C0,Timestamp:t0.Now()});},A0,B0));z0.Add(a0(r0,s0,t0).Subscribe(function(C0){var D0=y0();var E0=t0.Now()+s0-r0;while(w0.GetCount()>0&&w0.GetItem(0).Timestamp-E0<=0)w0.RemoveAt(0);v0.OnNext(D0);x0=E0;},A0,B0));return z0;});},BufferWithTimeOrCount:function(r0,s0,t0){if(t0===a)t0=A;var u0=this;return E(function(v0){var w0=0;var x0=new q();var y0=function(){v0.OnNext(x0.ToArray());x0.Clear();w0++;};var z0=new o();var A0;A0=function(C0){var D0=t0.ScheduleWithTime(function(){var E0=false;var F0=0;if(C0==w0){y0();F0=w0;E0=true;}if(E0)A0(F0);},r0);z0.Replace(D0);};A0(w0);var B0=u0.Subscribe(function(C0){var D0=false;var E0=0;x0.Add(C0);if(x0.GetCount()==s0){y0();E0=w0;D0=true;}if(D0)A0(E0);},function(C0){v0.OnError(C0);x0.Clear();},function(){v0.OnNext(x0.ToArray());w0++;v0.OnCompleted();x0.Clear();});return new n(
 B0,z0);});},BufferWithCount:function(r0,s0){if(s0===a)s0=r0;var t0=this;return E(function(u0){var v0=[];var w0=0;return t0.Subscribe(function(x0){if(w0==0)v0.push(x0); else w0--;var y0=v0.length;if(y0==r0){var z0=v0;v0=[];var A0=Math.min(s0,y0);for(var B0=A0;B0<y0;B0++) v0.push(z0[B0]);w0=Math.max(0,s0-r0);u0.OnNext(z0);}},function(x0){u0.OnError(x0);},function(){if(v0.length>0)u0.OnNext(v0);u0.OnCompleted();});});},StartWith:function(r0,s0){if(!(r0 instanceof Array))r0=[r0];if(s0===a)s0=z;var t0=this;return E(function(u0){var v0=new n();var w0=0;v0.Add(s0.ScheduleRecursive(function(x0){if(w0<r0.length){u0.OnNext(r0[w0]);w0++;x0();}else v0.Add(t0.Subscribe(u0));}));return v0;});},DistinctUntilChanged:function(r0,s0){if(r0===a)r0=h;if(s0===a)s0=g;var t0=this;return E(function(u0){var v0;var w0=false;return t0.Subscribe(function(x0){var y0;try{y0=r0(x0);}catch(A0){u0.OnError(A0);return;}var z0=false;if(w0)try{z0=s0(v0,y0);}catch(A0){u0.OnError(A0);return;}if(!w0||!z0){w0=true;v0=y0;u0
 .OnNext(x0);}},function(x0){u0.OnError(x0);},function(){u0.OnCompleted();});});},Publish:function(r0){if(r0===a)return new q0(this,new i0());var s0=this;return E(function(t0){var u0=new q0(s0,new i0());return new n(r0(u0).Subscribe(B),u0.Connect());});},Prune:function(r0,s0){if(s0===a)s0=z;if(r0===a)return new q0(this,new k0(s0));var t0=this;return E(function(u0){var v0=new q0(t0,new k0(s0));return new n(r0(v0).Subscribe(B),v0.Connect());});},Replay:function(r0,s0,t0,u0){if(u0===a)u0=v;if(r0===a)return new q0(this,new m0(s0,t0,u0));var v0=this;return E(function(w0){var x0=new q0(v0,new m0(s0,t0,u0));return new n(r0(x0).Subscribe(B),x0.Connect());});},SkipLast:function(r0){var s0=this;return E(function(t0){var u0=[];return s0.Subscribe(function(v0){u0.push(v0);if(u0.length>r0)t0.OnNext(u0.shift());},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();});});},TakeLast:function(r0){var s0=this;return E(function(t0){var u0=[];return s0.Subscribe(function(v0){u0.push(v0);if(u0.leng
 th>r0)u0.shift();},function(v0){t0.OnError(v0);},function(){while(u0.length>0)t0.OnNext(u0.shift());t0.OnCompleted();});});}};var H=D.Merge=function(r0,s0){if(s0===a)s0=z;return J(r0,s0).MergeObservable();};var I=D.Concat=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();var v0=0;var w0=s0.ScheduleRecursive(function(x0){if(v0<r0.length){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},function(A0){t0.OnError(A0);},x0));}else t0.OnCompleted();});return new n(u0,w0);});};var J=D.FromArray=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=0;return s0.ScheduleRecursive(function(v0){if(u0<r0.length){t0.OnNext(r0[u0++]);v0();}else t0.OnCompleted();});});};var K=D.Return=function(r0,s0){if(s0===a)s0=z;return E(function(t0){return s0.Schedule(function(){t0.OnNext(r0);t0.OnCompleted();});});};var L=D.Throw=function(r0,s0){if(s0===a)s0=z;return E(function(t0){return s0.Schedule(function(){t0.OnError(r0);});});};v
 ar M=D.Never=function(){return E(function(r0){return j;});};var N=D.Empty=function(r0){if(r0===a)r0=z;return E(function(s0){return r0.Schedule(function(){s0.OnCompleted();});});};var O=D.Defer=function(r0){return E(function(s0){var t0;try{t0=r0();}catch(u0){s0.OnError(u0);return j;}return t0.Subscribe(s0);});};var P=D.Catch=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();var v0=0;var w0=s0.ScheduleRecursive(function(x0){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},function(A0){if(v0<r0.length)x0(); else t0.OnError(A0);},function(){t0.OnCompleted();}));});return new n(u0,w0);});};var Q=D.Using=function(r0,s0){return E(function(t0){var u0;var v0=j;try{var w0=r0();if(w0!==a)v0=w0;u0=s0(w0);}catch(x0){return new n(Throw(x0).Subscribe(t0),v0);}return new n(u0.Subscribe(t0),v0);});};var R=D.Range=function(r0,s0,t0){if(t0===a)t0=z;var u0=r0+s0-1;return T(r0,function(v0){return v0<=u0;},function(v0){return v0+1;},h
 ,t0);};var S=D.Repeat=function(r0,s0,t0){if(t0===a)t0=z;if(s0===a)s0=-1;var u0=s0;return E(function(v0){return t0.ScheduleRecursive(function(w0){v0.OnNext(r0);if(u0>0){u0--;if(u0==0){v0.OnCompleted();return;}}w0();});});};var T=D.Generate=function(r0,s0,t0,u0,v0){if(v0===a)v0=z;return E(function(w0){var x0=r0;var y0=true;return v0.ScheduleRecursive(function(z0){var A0=false;var B0;try{if(y0)y0=false; else x0=t0(x0);A0=s0(x0);if(A0)B0=u0(x0);}catch(C0){w0.OnError(C0);return;}if(A0){w0.OnNext(B0);z0();}else w0.OnCompleted();});});};var U=D.GenerateWithTime=function(r0,s0,t0,u0,v0,w0){if(w0===a)w0=A;return new E(function(x0){var y0=r0;var z0=true;var A0=false;var B0;var C0;return w0.ScheduleRecursiveWithTime(function(D0){if(A0)x0.OnNext(B0);try{if(z0)z0=false; else y0=t0(y0);A0=s0(y0);if(A0){B0=u0(y0);C0=v0(y0);}}catch(E0){x0.OnError(E0);return;}if(A0)D0(C0); else x0.OnCompleted();},0);});};var V=D.OnErrorResumeNext=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();va
 r v0=0;var w0=s0.ScheduleRecursive(function(x0){if(v0<r0.length){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},x0,x0));}else t0.OnCompleted();});return new n(u0,w0);});};var W=D.Amb=function(){var r0=arguments;return E(function(s0){var t0=new n();var u0=new o();u0.Replace(t0);var v0=false;for(var w0=0;w0<r0.length;w0++){var x0=r0[w0];var y0=new o();var z0=new B(function(A0){if(!v0){t0.Remove(this.z,true);t0.Dispose();u0.Replace(this.z);v0=true;}s0.OnNext(A0);},function(A0){s0.OnError(A0);u0.Dispose();},function(){s0.OnCompleted();u0.Dispose();});z0.z=y0;y0.Replace(x0.Subscribe(z0));t0.Add(y0);}return u0;});};var X=D.ForkJoin=function(){var r0=arguments;return E(function(s0){var t0=[];var u0=[];var v0=[];var w0=new n();for(var x0=0;x0<r0.length;x0++) (function(y0){w0.Add(r0[y0].Subscribe(function(z0){t0[y0]=true;v0[y0]=z0;},function(z0){s0.OnError(z0);},function(z0){if(!t0[y0]){s0.OnCompleted();v0=a;t0=a;return;}u0[y0]=true;var 
 A0=true;for(var B0=0;B0<r0.length;B0++){if(!u0[B0])A0=false;}if(A0){s0.OnNext(v0);s0.OnCompleted();v0=a;u0=a;t0=a;}}));})(x0);return w0;});};var Y=D.Interval=function(r0,s0){return a0(r0,r0,s0);};var Z=function(r0){return Math.max(0,r0);};var a0=D.Timer=function(r0,s0,t0){if(t0===a)t0=A;if(r0===a)return M();if(r0 instanceof Date)return O(function(){return D.Timer(r0-new Date(),s0,t0);});var u0=Z(r0);if(s0===a)return E(function(w0){return t0.ScheduleWithTime(function(){w0.OnNext(0);w0.OnCompleted();},u0);});var v0=Z(s0);return E(function(w0){var x0=0;return t0.ScheduleRecursiveWithTime(function(y0){w0.OnNext(x0++);y0(v0);},u0);});};var b0=D.While=function(r0,s0){return E(function(t0){var u0=new o();var v0=new n(u0);v0.Add(z.ScheduleRecursive(function(w0){var x0;try{x0=r0();}catch(y0){t0.OnError(y0);return;}if(x0)u0.Replace(s0.Subscribe(function(y0){t0.OnNext(y0);},function(y0){t0.OnError(y0);},function(){w0();})); else t0.OnCompleted();}));return v0;});};var c0=D.If=function(r0,s0,t0
 ){if(t0===a)t0=N();return O(function(){return r0()?s0:t0;});};var d0=D.DoWhile=function(r0,s0){return I([r0,b0(s0,r0)]);};var e0=D.Case=function(r0,s0,t0,u0){if(u0===a)u0=z;if(t0===a)t0=N(u0);return O(function(){var v0=s0[r0()];if(v0===a)v0=t0;return v0;});};var f0=D.For=function(r0,s0){return E(function(t0){var u0=new n();var v0=0;u0.Add(z.ScheduleRecursive(function(w0){if(v0<r0.length){var x0;try{x0=s0(r0[v0]);}catch(y0){t0.OnError(y0);return;}u0.Add(x0.Subscribe(function(y0){t0.OnNext(y0);},function(y0){t0.OnError(y0);},function(){v0++;w0();}));}else t0.OnCompleted();}));return u0;});};var g0=D.Let=function(r0,s0){return O(function(){return s0(r0);});};var h0=b.Notification=function(r0,s0){this.Kind=r0;this.Value=s0;this.toString=function(){return this.Kind+": "+this.Value;};this.Accept=function(t0){switch(this.Kind){case "N":t0.OnNext(this.Value);break;case "E":t0.OnError(this.Value);break;case "C":t0.OnCompleted();break;}return j;};this.w=function(t0){var u0=this.Accept(t0);if(
 r0=="N")t0.OnCompleted();return u0;};};h0.prototype=new D;var i0=b.Subject=function(){var r0=new q();var s0=false;this.OnNext=function(t0){if(!s0){var u0=r0.ToArray();for(var v0=0;v0<u0.length;v0++){var w0=u0[v0];w0.OnNext(t0);}}};this.OnError=function(t0){if(!s0){var u0=r0.ToArray();for(var v0=0;v0<u0.length;v0++){var w0=u0[v0];w0.OnError(t0);}s0=true;r0.Clear();}};this.OnCompleted=function(){if(!s0){var t0=r0.ToArray();for(var u0=0;u0<t0.length;u0++){var v0=t0[u0];v0.OnCompleted();}s0=true;r0.Clear();}};this.w=function(t0){if(!s0){r0.Add(t0);return i(function(){r0.Remove(t0);});}else return j;};};i0.prototype=new D;for(var j0 in B.prototype) i0.prototype[j0]=B.prototype[j0];var k0=b.AsyncSubject=function(r0){var s0=new q();var t0;var u0=false;if(r0===a)r0=z;this.OnNext=function(v0){if(!u0)t0=new h0("N",v0);};this.OnError=function(v0){if(!u0){t0=new h0("E",v0);var w0=s0.ToArray();for(var x0=0;x0<w0.length;x0++){var y0=w0[x0];if(y0!==a)y0.OnError(v0);}u0=true;s0.Clear();}};this.OnCo
 mpleted=function(){if(!u0){if(t0===a)t0=new h0("C");var v0=s0.ToArray();for(var w0=0;w0<v0.length;w0++){var x0=v0[w0];if(x0!==a)t0.w(x0);}u0=true;s0.Clear();}};this.w=function(v0){if(!u0){s0.Add(v0);return i(function(){s0.Remove(v0);});}else return r0.Schedule(function(){t0.w(v0);});};};k0.prototype=new i0;var l0=b.BehaviorSubject=function(r0,s0){var t0=new m0(1,-1,s0);t0.OnNext(r0);return t0;};var m0=b.ReplaySubject=function(r0,s0,t0){var u0=new q();var v0=new q();var w0=false;if(t0===a)t0=v;var x0=s0>0;var y0=function(z0,A0){v0.Add({Value:new h0(z0,A0),Timestamp:t0.Now()});};this.A=function(){if(r0!==a)while(v0.GetCount()>r0)v0.RemoveAt(0);if(x0)while(v0.GetCount()>0&&t0.Now()-v0.GetItem(0).Timestamp>s0)v0.RemoveAt(0);};this.OnNext=function(z0){if(!w0){var A0=u0.ToArray();for(var B0=0;B0<A0.length;B0++){var C0=A0[B0];C0.OnNext(z0);}y0("N",z0);}};this.OnError=function(z0){if(!w0){var A0=u0.ToArray();for(var B0=0;B0<A0.length;B0++){var C0=A0[B0];C0.OnError(z0);}w0=true;u0.Clear();y0
 ("E",z0);}};this.OnCompleted=function(){if(!w0){var z0=u0.ToArray();for(var A0=0;A0<z0.length;A0++){var B0=z0[A0];B0.OnCompleted();}w0=true;u0.Clear();y0("C");}};this.w=function(z0){var A0=new n0(this,z0);var B0=new n(A0);var C0=this;B0.Add(t0.Schedule(function(){if(!A0.B){C0.A();for(var D0=0;D0<v0.GetCount();D0++) v0.GetItem(D0).Value.Accept(z0);u0.Add(z0);A0.C=true;}}));return B0;};this.D=function(z0){u0.Remove(z0);};};m0.prototype=new i0;var n0=function(r0,s0){this.E=r0;this.F=s0;this.C=false;this.B=false;this.Dispose=function(){if(this.C)this.E.D(this.F);this.B=true;};};var o0=D.ToAsync=function(r0,s0){if(s0===a)s0=A;return function(){var t0=new k0(s0);var u0=function(){var x0;try{x0=r0.apply(this,arguments);}catch(y0){t0.OnError(y0);return;}t0.OnNext(x0);t0.OnCompleted();};var v0=this;var w0=p(arguments);s0.Schedule(function(){u0.apply(v0,w0);});return t0;};};var p0=D.Start=function(r0,s0,t0,u0){if(t0===a)t0=[];return o0(r0,u0).apply(s0,t0);};var q0=b.ConnectableObservable=func
 tion(r0,s0){if(s0===a)s0=new i0();this.E=s0;this.G=r0;this.H=false;this.Connect=function(){var t0;var u0=false;if(!this.H){this.H=true;var v0=this;t0=new n(i(function(){v0.H=false;}));this.I=t0;t0.Add(r0.Subscribe(this.E));}return this.I;};this.w=function(t0){return this.E.Subscribe(t0);};this.RefCount=function(){var t0=0;var u0=this;var v0;return F(function(w0){var x0=false;t0++;x0=t0==1;var y0=u0.Subscribe(w0);if(x0)v0=u0.Connect();return function(){y0.Dispose();t0--;if(t0==0)v0.Dispose();};});};};q0.prototype=new D;})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/datajs-cache-large-collection-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/datajs-cache-large-collection-functional-tests.html b/datajs/tests/datajs-cache-large-collection-functional-tests.html
deleted file mode 100644
index 475deff..0000000
--- a/datajs/tests/datajs-cache-large-collection-functional-tests.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<html>
-<head>
-    <title>datajs.cache and datajs.store full local store tests</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
-    <!--<script type="text/javascript" src="common/common.js"></script>-->
-
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/djstest-browser.js"></script>
-    <script type="text/javascript" src="common/CacheOracle.js"></script>
-    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
-    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
-    
-    <script type="text/javascript" src="datajs-cache-large-collection-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache and datajs.store full local store 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/d5ec5557/datajs/tests/datajs-cache-large-collection-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/datajs-cache-large-collection-functional-tests.js b/datajs/tests/datajs-cache-large-collection-functional-tests.js
deleted file mode 100644
index 557510e..0000000
--- a/datajs/tests/datajs-cache-large-collection-functional-tests.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    window.odatajs.oData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var largeCollectionFeed = "./endpoints/LargeCollectionService.svc/Customers";
-    var itemsInCollection = 2 * 1024 * 1024;
-
-    var cleanDomStorage = function (done) {
-        /* Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
-         *  setup and teardown methods to be consistent with indexedDb's cleanup method.
-         * @param {Function} done - Function to be called after DOM storage is cleared.
-         */
-        if (window.localStorage) {
-            window.localStorage.clear();
-        }
-        done();
-    };
-
-    var cleanIndexedDb = function (done) {
-        /** Cleans all the data saved in the browser's IndexedDb Storage.
-         * @param {Function} done - Function to be called after DOM storage is cleared.
-         */
-        var caches = this.caches;
-
-        djstest.cleanStoreOnIndexedDb(caches, done);
-    };
-
-    var makeUnexpectedErrorHandler = function () {
-        return function (err) {
-            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        };
-    };
-
-    var storageMechanisms = {
-        indexeddb: { cleanup: cleanIndexedDb },
-        dom: { cleanup: cleanDomStorage }
-    };
-
-    var cleanupAllStorage = function(done) {
-        /** Cleans up all available storage mechanisms in the browser.
-         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
-         */
-        var that = this;
-        var storeCleanup = [];
-
-        $.each(CacheOracle.mechanisms, function(_, mechanism) {
-            if (CacheOracle.isMechanismAvailable(mechanism)) {
-                storeCleanup.push(function(done) {
-                    if (storageMechanisms[mechanism]) {
-                        storageMechanisms[mechanism].cleanup.call(that, done);
-                    } else {
-                        done();
-                    }
-                });
-            }
-        });
-
-        djstest.asyncDo(storeCleanup, done);
-    };
-
-
-    module("Functional", {
-        setup: function () {
-            this.observableHttpClient = new ObservableHttpClient();
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
-            this.caches = [];
-            var that = this;
-
-            djstest.wait(function (done) {
-                cleanupAllStorage.call(that, done);
-            });
-        },
-
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
-            var clearActions = [];
-            var that = this;
-
-            $.each(this.caches, function (_, cacheObject) {
-                cacheObject.cache.onidle = undefined;
-
-                clearActions.push(function (done) {
-                    cacheObject.cache.clear().then(function () {
-                        done();
-                    },
-                        function (err) {
-                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
-                        });
-                });
-            });
-
-            djstest.wait(function (done) {
-                djstest.asyncDo(clearActions, function () {
-                    cleanupAllStorage.call(that, function () {
-                        that.caches = [];
-                        done();
-                    });
-                });
-            });
-        }
-    });
-
-    $.each(["dom", "indexeddb"], function (_, mechanism) {
-        if (CacheOracle.isMechanismAvailable(mechanism)) {
-            $.each([-1, 10 * 1024 * 1024, 1024 * 10248], function (_, cacheSize) {
-                var prefetchParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 5, pageSize: 1024, prefetchSize: -1, cacheSize: cacheSize };
-                djstest.addTest(function (params) {
-
-                    djstest.assertsExpected(3);
-                    var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
-                        mechanism: params.mechanism, cacheSize: params.cacheSize
-                    };
-
-                    var cache = odatajs.cache.createDataCache(options);
-                    this.caches.push({ name: options.name,
-                        cache: cache
-                    });
-
-                    cache.onidle = function () {
-                        djstest.assert(true, "onidle Called");
-                        djstest.done();
-                    };
-
-                    var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
-                    var session = this.observableHttpClient.newSession();
-
-                    cache.readRange(params.skip, params.take).then(function (data) {
-                        var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
-                        cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests with prefetch", false, true);
-                        window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                        });
-                    }, function (err) {
-                        makeUnexpectedErrorHandler(err)();
-                    });
-                }, "readRange and prefetch all to fill store on " + prefetchParameters.mechanism + " with cacheSize=" + prefetchParameters.cacheSize, prefetchParameters, 600000);
-
-                $.each([500, 1024 * 10 /*Test reduced from 100 to 10 to work around slow running script error in IE8 and Safari (bug 2200)*/], function (_, pageSize) {
-                    var largeReadParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 1024, pageSize: pageSize, prefetchSize: 0, cacheSize: cacheSize };
-                    djstest.addTest(function (params) {
-
-                        djstest.assertsExpected(2);
-                        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
-                            mechanism: params.mechanism, cacheSize: params.cacheSize
-                        };
-
-                        var cache = odatajs.cache.createDataCache(options);
-                        this.caches.push({ name: options.name, cache: cache });
-
-                        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
-                        var session = this.observableHttpClient.newSession();
-
-                        cache.readRange(params.skip, params.take).then(function (data) {
-                            var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
-                            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests without prefetch", false, false);
-                            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                                djstest.done();
-                            });
-                        }, function (err) {
-                            makeUnexpectedErrorHandler(err)();
-                            djstest.done();
-                        });
-                    }, "readRange of skip=" + largeReadParameters.skip + " take=" + largeReadParameters.take + " cacheSize=" + largeReadParameters.cacheSize + " and pageSize=" + largeReadParameters.pageSize +
-                        " to fill store on " + largeReadParameters.mechanism, largeReadParameters, 600000);
-                });
-            });
-        }
-    });
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/datajs-cache-long-haul-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/datajs-cache-long-haul-tests.html b/datajs/tests/datajs-cache-long-haul-tests.html
deleted file mode 100644
index 3e02e32..0000000
--- a/datajs/tests/datajs-cache-long-haul-tests.html
+++ /dev/null
@@ -1,194 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData Long Haul Tests</title>
-    <meta http-equiv="cache-control" content="no-cache" />
-    <meta http-equiv="pragma" content="no-cache" />
-    <meta http-equiv="expires" content="-1" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/Instrument.js"></script>
-    <script type="text/javascript">
-        var cache;
-        var clearBetweenReads;
-        var currentRunTimeMS;
-        var failureCount;
-        var hourMS = 60 * 60 * 1000;
-        var goalRunTimeMS = hourMS;
-        var isTotalIncreaseHigh;
-        var itemsInCollection = 16;
-        var iterationsRun;
-        var memoryDelta = 5000000;
-        var getBrowserMemorySize;
-        var startMemorySize;
-        var startTimeMs = 0;
-        var testFeed = "http://odata.netflix.com/Catalog/Titles";
-
-        var makeUnexpectedErrorHandler = function () {
-            return function (err) {
-                failureCount++;
-                if (failureCount < 50) {
-                    $("#errors").append("<p>Iteration: " + iterationsRun + " Error reading cache: " + err.message + "<p>");
-                }
-            };
-        };
-
-        var checkMemoryIncrease = function (memorySizeBefore) {
-            getBrowserMemorySize(function (memorySizeAfter) {
-                var incrementalIncreaseInMemory = memorySizeAfter - memorySizeBefore;
-                var totalIncreaseInMemory = memorySizeAfter - startMemorySize;
-                if (incrementalIncreaseInMemory > memoryDelta) {
-                    failureCount++;
-                    if (failureCount < 50) {
-                        $("#errors").append("<p>Iteration: " + iterationsRun + " Memory usage increase in read: " + incrementalIncreaseInMemory + "<p>");
-                    }
-                }
-
-                if (totalIncreaseInMemory > memoryDelta && !isTotalIncreaseHigh) {
-                    isTotalIncreaseHigh = true;
-                    failureCount++;
-                    if (failureCount < 50) {
-                        $("#errors").append("<p>Iteration: " + iterationsRun + " Total memory usage increase over duration: " + totalIncreaseInMemory + "<p>");
-                    }
-                }
-
-                iterationsRun++;
-                nextIteration();
-            });
-        };
-
-        var readRangePrefetchTest = function () {
-            var readPage = 6;
-
-            getBrowserMemorySize(function (memorySizeBefore) {
-                callReadRangeRepeatedly(0, readPage, function () { checkMemoryIncrease(memorySizeBefore) });
-            });
-        };
-
-        var callReadRangeRepeatedly = function (index, count, done) {
-            /** Calls readRange over the whole collection and done when all items have been read.
-             * @param {Integer} index - Index to start the read.
-             * @param {String} count - The count of each readRange.
-             * @param {Function} done - Function to be called when all items in collection have been read.
-            var cacheRead = function () {
-                cache.readRange(index, count).then(function () {
-                    if (index < itemsInCollection) {
-                        index += count;
-                        callReadRangeRepeatedly(index, count, done);
-                    }
-                    else {
-                        done();
-                    }
-                }, makeUnexpectedErrorHandler(cache));
-            };
-
-            if (clearBetweenReads) {
-                cache.clear().then(cacheRead(), makeUnexpectedErrorHandler(cache));
-            }
-            else {
-                cacheRead(); 
-            }
-        }
-
-        function startTest() {
-            var prefetchSize =
-                $('input[name=PrefetchEnabled]').attr('checked') ? -1 : 0;
-            clearBetweenReads = $('input[name=ClearBetweenReads]').attr('checked');
-            var inputHours = parseFloat($('#time').val());
-
-            if (inputHours !== undefined && typeof inputHours === "number" && !isNaN(inputHours) && isFinite(inputHours) && inputHours > 0) {
-                goalRunTimeMS = hourMS * inputHours;
-            }
-            OData.defaultHttpClient.enableJsonpCallback = true;
-            cache = datajs.cache.createDataCache({ name: "cache" + new Date().valueOf(), source: testFeed, pageSize: 5, prefetchSize: prefetchSize });
-            failureCount = 0;
-            iterationsRun = 0;
-            currentRunTimeMS = 0;
-            isTotalIncreaseHigh = false;
-            $("#errors").empty();
-            getBrowserMemorySize = Instrument.getBrowserMemorySize;
-            getBrowserMemorySize(function (memorySizeStart) {
-                startMemorySize = memorySizeStart;
-                $("#starting-memory").text("Starting memory size: " + startMemorySize);
-            });
-            startTimeMs = new Date().getTime();
-
-            nextIteration();
-        }
-
-        function nextIteration() {
-            currentRunTimeMS = new Date().getTime() - startTimeMs;
-            if (currentRunTimeMS > goalRunTimeMS) {
-                getBrowserMemorySize(function (memorySizeAfter) {
-                    $("#stress-status").text("Tests complete. Iterations: " + iterationsRun + " Failures: " + failureCount +
-                    " Start memory: " + startMemorySize + " End memory: " + memorySizeAfter);
-                });
-
-                cache.clear();
-                return;
-            }
-
-            if (iterationsRun % 100 === 0) {
-                getBrowserMemorySize(function (memorySizeAfter) {
-                    var text = "Running tests (iterationsRun=" + iterationsRun;
-                    text += ", Time run: " + currentRunTimeMS + "ms";
-                    text += ", Remaining time: " + (goalRunTimeMS - currentRunTimeMS) + "ms";
-                    text += "). Failures: " + failureCount;
-                    text += " Current memory size: " + memorySizeAfter;
-                    $("#stress-status").text(text);
-                });
-            }
-
-            readRangePrefetchTest();
-        }
-
-        $(document).ready(function () {
-            $("#start-button").click(startTest);
-        });
-    </script>
-</head>
-<body>
-    <h1>
-        OData Long Haul</h1>
-    <p>
-        Repeatedly runs an action and checks the memory usage.
-    </p>
-    <p>
-        <input name="time" id="time" type="text" />Length of time to run test</p>
-    <p>
-        <input type="checkbox" name="PrefetchEnabled" value="false" />Prefetch Enabled</p>
-    <p>
-        <input type="checkbox" name="ClearBetweenReads" value="false" />Clear Between Reads</p>
-    <button id='start-button'>
-        Start</button>
-    <p id='errors'>
-    </p>
-    <p id='stress-status'>
-    </p>
-    <p id='starting-memory'>
-    </p>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/datajs-startup-perf-test.html
----------------------------------------------------------------------
diff --git a/datajs/tests/datajs-startup-perf-test.html b/datajs/tests/datajs-startup-perf-test.html
deleted file mode 100644
index f69684a..0000000
--- a/datajs/tests/datajs-startup-perf-test.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!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" />
-    <title>datajs startup perf test</title>
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/Instrument.js"></script>
-
-    <script type="text/javascript">
-        $(window).load(function () {
-            djstest.addTest(function startupTimeAndMemory() {
-                var durationLimit = 500;
-                var memorySizeDeltaLimit = 5000000;
-
-                var filename = "../build/odatajs-4.0.0-beta-01.js";
-                var getBrowserMemorySize = Instrument.getBrowserMemorySize;
-
-                $.ajax({
-                    url: "../src/" + filename,
-                    dataType: "text",
-                    success: function (script) {
-                        getBrowserMemorySize(function (memorySizeBefore) {
-                            var duration = new Date();
-                            eval(script);
-                            duration = new Date() - duration;
-                            getBrowserMemorySize(function (memorySizeAfter) {
-                                var memorySizeDelta = memorySizeAfter - memorySizeBefore;
-                                djstest.assert(duration < durationLimit, duration + " ms (limit " + durationLimit + " ms)");
-                                djstest.assert(memorySizeDelta < memorySizeDeltaLimit,
-                                    memorySizeDelta + " bytes (limit " + memorySizeDeltaLimit + " bytes, initial " + memorySizeBefore + " bytes)");
-
-                                djstest.done();
-                            });
-                        });
-                    },
-                    error: function () {
-                        // See if we are running the dev build
-                        $.ajax({
-                            url: "../src/odata.js",
-                            dataType: "text",
-                            success: function () {
-                                djstest.pass("Running on dev build, no measurement taken");
-                                djstest.done();
-                            },
-                            error: function (jqXHR, textStatus, errorThrown) {
-                                djstest.fail("Request failed: " + jqXHR.responseText);
-                                djstest.done();
-                            }
-                        });
-                    }
-                });
-            });
-        });
-    </script>
-</head>
-<body>
-    <h1 id="qunit-header">datajs startup perf test</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/d5ec5557/datajs/tests/e2etest/Test.html
----------------------------------------------------------------------
diff --git a/datajs/tests/e2etest/Test.html b/datajs/tests/e2etest/Test.html
deleted file mode 100644
index 265c1da..0000000
--- a/datajs/tests/e2etest/Test.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>odatajs side-by-side test (V3 & V4)</title>
-    <script type="text/javascript" src="../../demo/scripts/datajs-1.1.2.js"></script>
-    <script type="text/javascript" src="../../build/datajs-2.0.0.js"></script>
-</head>
-<body>
-    <h3>
-        Test V3 and V4 running side by side...</h3>
-    <div id="msg">
-    </div>
-    <script type="text/javascript">
-
-        var headers = { "Content-Type": "application/json", Accept: "application/json" };
-        var request = {
-            requestUri: "../endpoints/FoodStoreDataServiceV4.svc/Foods",
-            method: "GET",
-            headers: headers,
-            data: null
-        };
-
-        OData.request(request, function (data, response) {
-            document.getElementById('msg').innerHTML += ("<div>datajs V3 testing failed.</div>");
-        }, function (err) {
-            if ((err.response.statusCode == '200') && (err.response.body.indexOf('}', err.response.body.length - 1) == err.response.body.length - 1) && err.response.headers['Content-Type'] == "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8") {
-                document.getElementById('msg').innerHTML += ("<div>datajs V3 testing pass!</div>");
-            } else {
-                document.getElementById('msg').innerHTML += ("<div>datajs V3 testing failed.</div>");
-            }
-        });
-
-        odatajs.oData.request(request, function (data, response) {
-            if ((response.statusCode == '200') && (response.body.indexOf('}', response.body.length - 1) == response.body.length - 1) && response.headers['Content-Type'] == "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8") {
-                document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing pass!</div>");
-            } else {
-                document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing failed.</div>");
-            }
-        }, function (err) {
-            document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing failed.</div>");
-        });
-    </script>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/BasicAuthDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/BasicAuthDataService.svc b/datajs/tests/endpoints/BasicAuthDataService.svc
deleted file mode 100644
index e059314..0000000
--- a/datajs/tests/endpoints/BasicAuthDataService.svc
+++ /dev/null
@@ -1,124 +0,0 @@
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.BasicAuthDataService" %>
-/*
- * 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.
- */
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Web;
-    using System.Text;
-    using System.Web;
-
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class BasicAuthDataService : DataService<BasicAuthDataSource>
-    {
-        const string Username = "djsUser";
-        const string Password = "djsPassword";
-        
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-            config.UseVerboseErrors = true;
-        }
-
-        public BasicAuthDataService()
-            : base()
-        {
-            this.ProcessingPipeline.ProcessingRequest += OnRequest;
-        }
-
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-
-        private static void UnauthorizedRequest(DataServiceOperationContext context)
-        {
-            context.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"DataJS.Tests\"";
-            throw new DataServiceException(401, "401 Unauthorized");
-        }
-
-        private void OnRequest(object sender, DataServiceProcessingPipelineEventArgs e)
-        {
-            string authHeader = e.OperationContext.RequestHeaders["Authorization"];
-            
-            // Validate the Authorization header
-            if (authHeader == null || !authHeader.StartsWith("Basic"))
-            {
-                UnauthorizedRequest(e.OperationContext);
-            }
-
-            // Decode the username and password from the header
-            string base64Credentials = authHeader.Substring(6);
-            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(':');
-            if (credentials.Length != 2 || !(credentials[0].Equals(Username) && credentials[1].Equals(Password)))
-            {
-                UnauthorizedRequest(e.OperationContext);
-            }
-        }
-    }
-
-    public class BasicAuthDataSource : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Customer> Customers
-        {
-            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
-            foreach (int i in Enumerable.Range(1, 16))
-            {
-                customers.Add(new Customer()
-                {
-                    ID = i,
-                    Name = "Customer " + i
-                });
-            }
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Customer
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/CustomAnnotations.xml
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/CustomAnnotations.xml b/datajs/tests/endpoints/CustomAnnotations.xml
deleted file mode 100644
index ebf4e26..0000000
--- a/datajs/tests/endpoints/CustomAnnotations.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<!--/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<?xml version="1.0" encoding="utf-8"?>
-<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
-  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
-    <Schema xmlns="http://schemas.microsoft.com/ado/2007/05/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:mcns="http://MyCustomNamespace.com"
-             Namespace="DataJS.Tests">
-      <EntityType Name="MappedEntry" mcns:MyCustomAnnotation="My custom attribute.">
-        <Key mcns:MyCustomAnnotation="//">
-          <PropertyRef Name="ID" mcns:MyCustomAnnotation="  "/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author" m:FC_KeepInContent_5="false" m:FC_SourcePath_5="Contributor/Name" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorName" m:FC_KeepInContent_4="false" m:FC_SourcePath_4="Contributor/Email" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorEmail" m:FC_KeepInContent_3="false" m:FC_SourcePath_3="Uri" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationAuthorUri" m:FC_KeepInContent_2="false" m:FC_SourcePath_2="Name" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorName" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Email" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorEmail" m:FC_KeepInContent="false" m:FC_SourcePath="Contributor/Uri" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationContributorUri"/>
-        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished"/>
-        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
-        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary"/>
-        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
-        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
-        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="false" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
-      </EntityType>
-      <ComplexType Name="Author" mcns:MyCustomAnnotation="">
-        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=""/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor"/>
-      </ComplexType>
-      <ComplexType Name="Contributor">
-        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=" "/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="true"/>
-      </ComplexType>
-      <ComplexType Name="Location">
-        <Property Name="Lat" Nullable="false" Type="Edm.Single" mcns:MyCustomAnnotation="27"/>
-        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
-      </ComplexType>
-      <EntityType Name="ReplicatedEntry">
-        <Key>
-          <PropertyRef Name="ID"/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author2" m:FC_KeepInContent_5="true" m:FC_SourcePath_5="Contributor/Uri" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorUri" m:FC_KeepInContent_4="true" m:FC_SourcePath_4="Contributor/Name" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorName" m:FC_KeepInContent_3="true" m:FC_SourcePath_3="Contributor/Email" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationContributorEmail" m:FC_KeepInContent_2="true" m:FC_SourcePath_2="Uri" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorUri" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Name" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorName" m:FC_KeepInContent="true" m:FC_SourcePath="Email" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationAuthorEmail" mcns:MyCustomAnnotation="b>100/b>"/>
-        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished" mcns:MyCustomAnnotation=" . "/>
-        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
-        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary" mcns:MyCustomAnnotation="/Property"/>
-        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
-        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
-        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location2" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="true" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
-      </EntityType>
-      <ComplexType Name="Author2">
-        <Property Name="Email" Nullable="true" Type="Edm.String"/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor2"/>
-      </ComplexType>
-      <ComplexType Name="Contributor2">
-        <Property Name="Email" Nullable="true" Type="Edm.String"/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-      </ComplexType>
-      <ComplexType Name="Location2">
-        <Property Name="Lat" Nullable="false" Type="Edm.Single"/>
-        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
-      </ComplexType>
-      <EntityType Name="DerivedEntry" m:FC_KeepInContent="false" m:FC_SourcePath="MappedInDerivedField" m:FC_TargetPath="mappedField/@mappedInDerived" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy" BaseType="DataJS.Tests.BaseEntry">
-        <Property Name="UnmappedConcreteField" Nullable="true" Type="Edm.String"/>
-        <Property Name="MappedConcreteField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField/@mappedConcrete" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
-      </EntityType>
-      <EntityType Name="BaseEntry">
-        <Key>
-          <PropertyRef Name="ID"/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="MappedInDerivedField" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="false"/>
-        <Property Name="MappedField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
-      </EntityType>
-      <EntityContainer Name="EpmDataSource" m:IsDefaultEntityContainer="true" mcns:MyCustomAnnotation="0">
-        <EntitySet Name="MappedEntries" EntityType="DataJS.Tests.MappedEntry"/>
-        <EntitySet Name="ReplicatedEntries" EntityType="DataJS.Tests.ReplicatedEntry"/>
-        <EntitySet Name="HierarchicalEntries" EntityType="DataJS.Tests.BaseEntry"/>
-        <FunctionImport Name="ResetData" m:HttpMethod="POST" mcns:MyCustomAnnotation="null"/>
-      </EntityContainer>
-      <mcns:EmptyElement></mcns:EmptyElement>
-      <mcns:ParentCustomElement mcns:MyCustomAnnotation="annotation" mcns:MySecondCustomAnnotation="annotation 2">
-        <mcns:CustomChildElement1>Custom metadata 1.</mcns:CustomChildElement1>
-        <mcns:CustomChildElement2>Custom metadata 2.</mcns:CustomChildElement2>
-      </mcns:ParentCustomElement>
-    </Schema>
-  </edmx:DataServices>
-</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/CustomDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/CustomDataService.svc b/datajs/tests/endpoints/CustomDataService.svc
deleted file mode 100644
index 67fcfd0..0000000
--- a/datajs/tests/endpoints/CustomDataService.svc
+++ /dev/null
@@ -1,85 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory"
-    Service="DataJS.Tests.CustomDataService" %>
-
-
-using System.Collections;
-using System.IO;
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Web;
-
-    /// <summary>
-    /// Custom data service that does not use OData
-    /// </summary>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class CustomDataService
-    {
-        static readonly Item[] data = Enumerable.Range(0, 16).Select(i => new Item
-        {
-            ID = i,
-            Name = "Item " + i
-        }).ToArray();
-
-        // This uses the same URI template as OData so that the CacheOracle can be reused
-        [OperationContract]
-        [WebGet(UriTemplate = "ReadRange?$skip={skip}&$top={top}")]
-        public Stream ReadRange(int skip, int top)
-        {
-            IEnumerable selectData = data.Skip(skip).Take(top);
-            Dictionary<string, object> result = new Dictionary<string, object>();
-            List<Dictionary<string, string>> value = new List<Dictionary<string, string>>(); 
-            foreach (Item d in selectData)
-            {
-                Dictionary<string, string> item = new Dictionary<string, string>();
-                item.Add("ID", d.ID.ToString());
-                item.Add("Name", d.Name);
-                value.Add(item);
-            }
-            
-            result.Add("value", value);
-            return ReaderUtils.ConvertDictionarytoJsonlightStream(result);
-        }
-
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public int Count()
-        {
-            return data.Count();
-        }
-    }
-
-    public class Item
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file


[41/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/b-cache-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/b-cache-tests.js b/datajs/tests-tmp/b-cache-tests.js
deleted file mode 100644
index 5b41123..0000000
--- a/datajs/tests-tmp/b-cache-tests.js
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-(function (window, undefined) {
-
-    module("cache-tests.js");
-    var foodsFeed = "./endpoints/FoodStoreDataServiceV4.svc/Foods";
-    var collectionSize = 16;
-
-    var thenFailTest = function (err) {
-        if (err && err.message) {
-            djstest.fail(err.message);
-        } else {
-            djstest.fail("unexepected promise failure");
-        }
-
-        djstest.done();
-    };
-
-    djstest.addTest(function dataCacheCountTest() {
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
-        cache.count().then(function (count) {
-            djstest.assertAreEqual(count, collectionSize, "expected count for Foods");
-            djstest.destroyCacheAndDone(cache);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheCountOnLocalTest() {
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed, pageSize: collectionSize + 10, mechanism: "memory" });
-        cache.readRange(0, collectionSize + 10).then(function (data) {
-            var expectedCount = data.value ? data.value.length : 0;
-            cache.count().then(function (count) {
-                djstest.assertAreEqual(count, expectedCount, "expected count for expectedCount");
-                djstest.destroyCacheAndDone(cache);
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheCountAbortTest() {
-        // Abort before completion.
-        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
-        var item = cache.count().then(thenFailTest, function (err) {
-            djstest.assertAreEqual(true, err.canceled, "err.aborted is true");
-            djstest.destroyCacheAndDone(cache);
-        }).cancel();
-    });
-
-    var createNewCache = function (options) {
-
-        var thenSuccess = null;
-
-        var resolved = false;
-        var rejected = false;
-
-        var args = null;
-
-        this.then = function (success) {
-            if (resolved) {
-                success.apply(null, args);
-            } else if (!rejected) {
-                thenSuccess = success;
-            }
-        };
-
-        var resolve = function (/*args*/) {
-            resolved = true;
-            args = arguments;
-            if (thenSuccess) {
-                thenSuccess.apply(null, arguments);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache(options);
-        cache.clear().then(function () {
-            var newCache = odatajs.cache.createDataCache(options);
-            resolve(newCache);
-        }, function (err) {
-            rejected = true;
-            thenFailTest(err);
-        });
-
-        return this;
-    };
-
-    djstest.addTest(function dataCacheReadRangeSingleTest() {
-        // Read a new range.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 1, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "food id is 0.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeExactPageTest() {
-        // Read exactly one page.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 2).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 2, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeMultiplePageTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 3).
-                    then(function (data) {
-                        djstest.assertAreEqual(data.value.length, 3, "single item was read.");
-                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                        djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
-                        djstest.done();
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeSyncDelaysTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).
-                    then(function (data) {
-                        djstest.assertAreEqual(counter, 0, "counter is zero for first set of results");
-                        djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
-                        counter++;
-                        cache.readRange(0, 1).
-                            then(function (data) {
-                                djstest.assertAreEqual(counter, 2, "counter is two because even sync results are delayed)");
-                                djstest.assertAreEqual(cache.stats.netReads, 1, "no additional requests since requested data is in cache");
-                                djstest.done();
-                            }, thenFailTest);
-                        djstest.assertAreEqual(counter, 1, "counter is one because readRange hasn't run (even if results are cached)");
-                        counter++;
-                    }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangesWithDestroyTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
-        var counter = 0;
-        createNewCache(options).then(function (cache) {
-            cache.readRange(0, 1).then(function (data) {
-                djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
-                cache.clear().then(function () {
-                    djstest.assertAreEqual(cache.stats.netReads, 0, "stats cleared in destroy");
-                    cache.readRange(0, 1).then(function (data) {
-                        djstest.assertAreEqual(cache.stats.netReads, 1, "request made after destroy to fulfill the readRange");
-                        djstest.done();
-                    }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadSimultaneousTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        var theCache;
-        var checkDataAndCount = function (data) {
-            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
-            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
-            djstest.assertAreEqual(theCache.stats.netReads, 1, "single theCache.stats.netReads");
-            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
-            counter++;
-            if (counter === 3) {
-                djstest.done();
-            }
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheMultipleClearTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        var counter = 0;
-        var checkCount = function (data) {
-            djstest.assert(true, "clear then was called");
-            counter++;
-            if (counter === 3) {
-                djstest.done();
-            }
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 1).then(function () {
-                    cache.clear().then(checkCount, thenFailTest);
-                    cache.clear().then(checkCount, thenFailTest);
-                    cache.clear().then(checkCount, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheOnIdleIsFired() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
-
-        createNewCache(options).
-            then(function (cache) {
-                var counter = 0;
-                var clearSucceeded = false;
-
-                var thenFailThisTest = function (err) {
-                    if (err && err.message) {
-                        djstest.fail(err.message);
-                    } else {
-                        djstest.fail("unexepected promise failure");
-                    }
-                };
-
-                cache.onidle = function () {
-                    counter++;
-                    djstest.assertAreEqual(counter, 1, "onidle was called 1 times");
-                    djstest.assert(clearSucceeded, "onidle was called after destroy");
-                    djstest.done();
-                };
-
-                cache.readRange(0, 1).then(null, thenFailThisTest);
-                cache.readRange(0, 1).then(null, thenFailThisTest);
-                cache.readRange(3, 4).then(function () {
-                    cache.readRange(5, 6).then(function () {
-                        cache.clear().then(function () {
-                            clearSucceeded = true;
-                        }, thenFailThisTest);
-                    }, thenFailThisTest);
-                }, thenFailThisTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheOnIdleFiresOnErrorTest() {
-
-        var errorResponse = false;
-        var httpClient = {
-            request: function (request, success, error) {
-                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ d: [1, 2] }) };
-                if (!errorResponse) {
-                    errorResponse = true;
-                    setTimeout(function () {
-                        success(response);
-                    }, 0);
-                } else {
-                    response.statusCode = 500;
-                    response.body = "bad response";
-                    setTimeout(function () {
-                        error({ message: "HTTP request failed", request: request, response: response });
-                    }, 0);
-                }
-            }
-        };
-
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0, httpClient: httpClient };
-
-        createNewCache(options).
-            then(function (cache) {
-                var counter = 0;
-                var errorHandlerCalled = false;
-
-                var thenFailThisTest = function (err) {
-                    if (err && err.message) {
-                        if (errorResponse) {
-                            djstest.assertAreEqual(err.message, "HTTP request failed", "Error is the expected one");
-                            errorHandlerCalled = true;
-                        } else {
-                            djstest.fail(err.message);
-                        }
-                    } else {
-                        djstest.fail("unexepected promise failure");
-                    }
-                };
-
-                cache.onidle = function () {
-                    counter++;
-                    djstest.assertAreEqual(counter, 1, "onidle was called");
-                    djstest.assert(errorHandlerCalled, "error handler was called before onidle");
-                    cache.onidle = null;
-                    cache.clear().then(function () {
-                        djstest.done();
-                    }, thenFailTest);
-                };
-                cache.readRange(0, 2).then(function () {
-                    cache.readRange(2, 4).then(function () {
-                        djstest.fail("unexpected readRange success");
-                    }, thenFailThisTest);
-                }, thenFailThisTest);
-            }, thenFailTest);
-    });
-
-
-    djstest.addTest(function dataCacheOdataSourceNormalizedURITest() {
-        var requestsMade = 0;
-        var httpClient = {
-            request: function (request, success, error) {
-                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ value: [1, 2] }) };
-                if (requestsMade === 0) {
-                    djstest.pass("Cache made first request for data from the source");
-                    requestsMade++;
-                } else {
-                    // In memory storage will make a second request from the new cache since two caches with the same name will coexist
-                    if (window.mozIndexedDB || window.localStorage || requestsMade > 1) {
-                        djstest.fail("Unexpected request to the source");
-                    } else {
-                        djstest.pass("In memory cache requested the data from the source");
-                    }
-                }
-                setTimeout(function () {
-                    success(response);
-                }, 0);
-            }
-        };
-
-        var options = { name: "cache", source: "http://exampleuri.com/my service.svc", pageSize: 2, prefetchSize: 0, httpClient: httpClient };
-
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 2).then(function () {
-                    options.source = "HtTp://ExampleURI.cOm/my%20service.svc";
-                    var newCache = odatajs.cache.createDataCache(options);
-                    newCache.readRange(0, 2).then(function (data) {
-                        djstest.assertAreEqualDeep(data.value, [1, 2], "Got the expected data from the new cache instance");
-                        newCache.clear().then(function () {
-                            djstest.done();
-                        }, thenFailTest);
-                    }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-
-    djstest.addTest(function dataCachePrefetchAllTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: -1 };
-        var counter = 0;
-        var theCache;
-
-        var callback = function () {
-            counter++;
-            if (counter === 2) {
-                djstest.assertAreEqual(1, theCache.stats.netReads, "single page to satisfy read (" + theCache.stats.netReads + ")");
-                djstest.assert(theCache.stats.prefetches > 1, "theCache.stats.prefetches(" + theCache.stats.prefetches + ") > 1 - multiple prefetches");
-                djstest.done();
-            }
-        };
-
-        var checkDataAndCount = function (data) {
-            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
-            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
-            djstest.assertAreEqual(1, theCache.stats.netReads, "single theCache.stats.netReads");
-            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
-            callback();
-        };
-
-        createNewCache(options).
-            then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
-                cache.onidle = function () {
-                    djstest.log("onidle fired");
-                    callback();
-                };
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeTakeMoreThanCollectionCountTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.count().then(function (count) {
-                    cache.readRange(0, count + 1).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, count, "all items in the collection were read.");
-                            cache.readRange(2, count + 1).
-                                then(function (data) {
-                                    djstest.assertAreEqual(data.value.length, count - 2, "all requested in the collection were read.");
-                                    djstest.assertAreEqual(data.value[0].FoodID, 2, "first read food id is 2.");
-                                    djstest.done();
-                                }, thenFailTest);
-                        }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeSkipMoreThanCollectionCountTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.count().then(function (count) {
-                    cache.readRange(count + 1, 5).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, 0, "no items were read.");
-                            djstest.done();
-                        }, thenFailTest);
-                }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheReadRangeTakeMoreThanPrefetchSizeTest() {
-        // Read multiple pages.
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
-        createNewCache(options).
-            then(function (cache) {
-                cache.readRange(0, 4).
-                        then(function (data) {
-                            djstest.assertAreEqual(data.value.length, 4, "all requested in the collection were read.");
-                            djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
-                            djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
-                            djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
-                            djstest.assertAreEqual(data.value[3].FoodID, 3, "third food id is 3.");
-                            djstest.done();
-                        }, thenFailTest);
-            }, thenFailTest);
-    });
-
-    djstest.addTest(function dataCacheRangeInvalidIndexAndCount() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
-        var counter = 0;
-
-        var thenFailSuccess = function () {
-            djstest.fail("Call to success was unexpected");
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var thenFailError = function () {
-            djstest.fail("Call to error was unexpected");
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var invalidValues = [-5, -1, null, undefined, NaN, Infinity, "5", "this is not a number"];
-        var tests = [];
-        $.each(invalidValues, function (_, value) {
-            tests.push({ i: value, c: 0 });
-            tests.push({ i: 0, c: value });
-            tests.push({ i: value, c: value });
-        });
-
-        createNewCache(options).
-            then(function (cache) {
-                var i, len;
-                for (i = 0, len = tests.length; i < len; i++) {
-                    var test = tests[i];
-                    try {
-                        cache.readRange(test.i, test.c).then(thenFailSuccess, thenFailTest);
-                    } catch (err) {
-                        djstest.pass("Expected exception was thrown: " + err.message);
-                        counter++;
-                    }
-                }
-                if (counter === tests.length) {
-                    djstest.done();
-                }
-            });
-    });
-
-
-    djstest.addTest(function cacheOptionsForCountTest() {
-        var httpClient = {
-            request: function (r, success, error) {
-                window.setTimeout(function () {
-                    success({ data: "10" });
-                }, 1);
-                return null;
-            }
-        };
-        var cache = odatajs.cache.createDataCache({
-            name: "mem", mechanism: "memory", source: "http://www.example.org/service/",
-            httpClient: httpClient
-        });
-        cache.count().then(function (count) {
-            djstest.assertAreEqual(count, 10, "count value");
-            djstest.done();
-        }, djstest.failAndDoneCallback("failed to get count"));
-    });
-
-    djstest.addTest(function dataCacheDestoryStopsThePrefetcherTest() {
-        var oldHttpClientRequest = window.odatajs.oData.net.defaultHttpClient.request;
-        var prefetchCount = 0;
-        var theCache;
-
-        window.odatajs.oData.net.defaultHttpClient.request = function (request, success, error) {
-            prefetchCount++;
-            djstest.assert(prefetchCount <= 3, "Expected prefetch request");
-            if (prefetchCount === 3) {
-                theCache.clear().then(function () {
-                    djstest.assertAreEqual(prefetchCount, 3, "cache.clear() stopped the prefetcher");
-                    djstest.done();
-                    window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
-                }, thenFailTest);
-                return {
-                    abort: function () { }
-                };
-            }
-            return oldHttpClientRequest(request, success, error);
-        };
-
-        try {
-            var options = { name: "cache", source: foodsFeed, pageSize: 1, prefetchSize: -1 };
-            createNewCache(options).then(function (cache) {
-                theCache = cache;
-                cache.readRange(0, 0).then(null, thenFailTest);
-            });
-        } catch (e) {
-            window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
-            djstest.fail("Exception thrown,  prefetchSize: " + tests[count] + " error:  " + e.message);
-            djstest.done();
-        }
-    });
-
-    djstest.addTest(function dataCacheFilterTest() {
-        var options = { name: "cache", source: foodsFeed, pageSize: 3, prefetchSize: -1 };
-        var counter = 0;
-
-        var singleItemPredicate = function (data) {
-            return data.FoodID === 2;
-        };
-
-        var multipleItemPredicate = function (data) {
-            return data.FoodID % 2 === 1;
-        };
-
-        var noItemPredicate = function (data) {
-            return data.Name === "something i would never eat";
-        };
-
-        var allItemPredicate = function (data) {
-            return data.FoodID >= 0;
-        };
-
-        var doneAfterAllTests = function () {
-            counter++;
-            if (counter === tests.length) {
-                djstest.done();
-            }
-        };
-
-        var last = collectionSize - 1;
-        var tests = [
-            { index: 0, count: -5, predicate: singleItemPredicate },    // Single match in entire collection
-            {index: 2, count: 1, predicate: singleItemPredicate },     // Single match, single count
-            {index: 3, count: 1, predicate: singleItemPredicate },     // Single match skipped, i.e. no matches
-            {index: 0, count: -1, predicate: multipleItemPredicate },  // Multiple matches in entire collection
-            {index: 0, count: 5, predicate: multipleItemPredicate },   // Multiple matches, take partial
-            {index: 3, count: 5, predicate: multipleItemPredicate },   // Multiple matches, skip/take partial
-            {index: 7, count: 10, predicate: multipleItemPredicate },  // Multiple matches, skip partial, take past end of collection
-            {index: 13, count: 4, predicate: allItemPredicate },       // All items match, skip/take partial
-            {index: 0, count: 20, predicate: noItemPredicate },        // No matches
-            {index: 0, count: 0, predicate: allItemPredicate },        // Zero count
-            {index: -5, count: 1, predicate: allItemPredicate },       // Negative index
-            {index: last + 1, count: 1, predicate: allItemPredicate }, // Index past end of collection
-
-            {index: last, count: -5, predicate: singleItemPredicate, backwards: true },        // Single match in entire collection
-            {index: 2, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match, single count
-            {index: 1, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match skipped, i.e. no matches
-            {index: last, count: -1, predicate: multipleItemPredicate, backwards: true },      // Multiple matches in entire collection
-            {index: last, count: 6, predicate: multipleItemPredicate, backwards: true },       // Multiple matches, take partial
-            {index: last - 3, count: 5, predicate: multipleItemPredicate, backwards: true },   // Multiple matches, skip/take partial
-            {index: 13, count: 10, predicate: multipleItemPredicate, backwards: true },        // Multiple matches, skip partial, take past end of collection
-            {index: 4, count: 13, predicate: allItemPredicate, backwards: true },              // All items match, skip/take partial
-            {index: last, count: 20, predicate: noItemPredicate, backwards: true },            // No matches
-            {index: 0, count: 0, predicate: allItemPredicate, backwards: true },               // Zero count
-            {index: -5, count: 1, predicate: allItemPredicate, backwards: true },              // Negative index
-            {index: last + 1, count: 1, predicate: allItemPredicate, backwards: true },        // Index past end of collection
-
-            {index: "foo", count: 1, predicate: singleItemPredicate, exception: { message: "'index' must be a valid number.", index: NaN} },
-            { index: 0, count: "foo", predicate: multipleItemPredicate, exception: { message: "'count' must be a valid number.", count: NaN} }
-        ];
-
-        var testDescription = function(test) {
-            return "filter [" + test.index + ", " + test.count + " " + (test.backwards ? "back" : "forward") + "] for predicate " + test.predicate;
-        };
-
-        var filterErrorCallback = function (err) {
-            if (err && err.message) {
-                djstest.fail(err.message);
-            } else {
-                djstest.fail("unexpected promise failure");
-            }
-            doneAfterAllTests();
-        };
-
-        var removeSafariExceptionProperties = function (err) {
-            /** Removes Safari-specific properties from an exception object
-             * @param {Exception} err -The exception object to operate on
-             * @returns {Exception} The original exception object with the Safari-specific properties removed
-             */
-            var safariProperties = ["line", "expressionBeginOffset", "expressionEndOffset", "sourceId", "sourceURL"];
-
-            var result = {};
-            $.each(err, function (property, value) {
-                if ($.inArray(property, safariProperties) === -1) {
-                    result[property] = value;
-                }
-            });
-
-            return result;
-        };
-
-        ODataVerifyReader.readJsonAcrossServerPages(foodsFeed, function (expectData) {
-            $.each(tests, function (_, test) {
-                createNewCache(options).then(function (cache) {
-                    try {
-                        var expectedResults = {};
-                        if (test.backwards) {
-                            cache.filterBack(test.index, test.count, test.predicate).then(function (results) {
-                                expectedResults = CacheVerifier.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
-                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
-                                doneAfterAllTests();
-                            }, filterErrorCallback);
-                        } else {
-                            cache.filterForward(test.index, test.count, test.predicate).then(function (results) {
-                                expectedResults = CacheVerifier.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
-                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
-                                doneAfterAllTests();
-                            }, filterErrorCallback);
-                        }
-
-                        if (test.exception) {
-                            djstest.fail("expected exception for " + testDescription(test));
-                            doneAfterAllTests();
-                        }
-                    } catch (err) {
-                        if (test.exception) {
-                            djstest.assertAreEqualDeep(removeSafariExceptionProperties(err), test.exception, "exception for " + testDescription(test));
-                        } else {
-                            djstest.fail("unexpected exception for " + testDescription(test) + ": " + djstest.toString(err));
-                        }
-                        doneAfterAllTests();
-                    }
-                }, thenFailTest);
-            });
-        });
-    });
-
-    djstest.addTest(function createDataCacheTest() {
-        var cache;
-
-        // Verify the defaults.
-        cache = odatajs.cache.createDataCache({ name: "name", source: "src" });
-
-        djstest.assertAreEqual(cache.onidle, undefined, "onidle is undefined");
-
-        // Verify specific values.
-        cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: 3, idle: 123 });
-
-        djstest.assertAreEqual(cache.onidle, 123, "onidle is as specified");
-
-        // Verify 0 pageSize 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 0, prefetchSize: 3, idle: 123 });
-        }, "zero pageSize");
-
-        // Verify negative pageSize
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: -2, prefetchSize: 3, idle: 123 });
-        }, "negative pageSize");
-
-        // Verify NaN pageSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: "2", prefetchSize: 3, idle: 123 });
-        }, "NaN pageSize");
-
-        // Verify NaN cacheSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: "1", pageSize: 2, prefetchSize: 3, idle: 123 });
-        }, "NaN cacheSize");
-
-        // Verify NaN prefetchSize
-        djstest.expectException(function () {
-            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: "3", idle: 123 });
-        }, "NaN prefetchSize");
-
-        // Verify undefined name 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "undefined name");
-
-        // Verify null name 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: null, source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "null name");
-
-        // Verify undefined source 
-        djstest.expectException(function () {
-            odatajs.cache.createDataCache({ name: "name", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
-        }, "undefined source");
-
-        djstest.done();
-    });
-
-    djstest.addTest(function createDataCacheWithSourceTest() {
-        var cacheSource = {
-            count: function (success) {
-                djstest.pass("cacheSource.count was called");
-                success(0);
-            },
-
-            read: function (index, count, success, error) {
-                djstest.assertAreEqual(index, 0, "index is the expected one");
-                djstest.assertAreEqual(count, 10, "test is the expected one");
-                djstest.assert(success, "success is defined");
-                djstest.assert(error, "error is defined");
-                djstest.pass("cacheSource.read was called");
-
-                setTimeout(function () {
-                    success([]);
-                }, 0);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
-        cache.count().then(function () {
-            cache.readRange(0, 5).then(function () {
-                djstest.done();
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    djstest.addTest(function cacheInitializationFailTest() {
-        // Tests various failure modes for cache initialization.
-        var failures = ["read-settings", "write-settings", "v2"];
-        var failureIndex = 0;
-
-        var originalStore = odatajs.store.createStore;
-        var restoreStore = function () {
-            odatajs.store.createStore = originalStore;
-        };
-
-        var storeError = { message: "cacheInitializationFailTest error" };
-        odatajs.store.createStore = function (name, mechanism) {
-            return {
-                addOrUpdate: function (key, value, successCallback, errorCallback) {
-                    if (failures[failureIndex] === "write-settings") {
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    } else {
-                        djstest.fail("Error unaccounted for in addOrUpdate for " + failures[failureIndex]);
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    }
-                },
-                read: function (key, successCallback, errorCallback) {
-                    if (failures[failureIndex] === "read-settings") {
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    } else if (failures[failureIndex] === "v2") {
-                        window.setTimeout(function () {
-                            successCallback("K", { version: "2.0" });
-                        }, 2);
-                    } else if (failures[failureIndex] === "write-settings") {
-                        window.setTimeout(function () { successCallback(null, null); }, 2);
-                    } else {
-                        djstest.fail("Error unaccounted for read in " + failures[failureIndex]);
-                        window.setTimeout(function () { errorCallback(storeError); }, 2);
-                    }
-                }
-            };
-        };
-
-        var nextFailure = function () {
-            djstest.log("Failure mode: " + failures[failureIndex]);
-            var cache = odatajs.cache.createDataCache({ name: "name", source: "foo", mechanism: "memory", pageSize: 10 });
-            try {
-                // The first readRange should succeed, because the data cache isn't really initialized at this time.
-                cache.readRange(1, 2).then(djstest.failAndDoneCallback("No function should succeed"), function (err) {
-                    djstest.expectException(function () {
-                        cache.readRange(1, 2);
-                    }, "readRange after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.count();
-                    }, "count after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.clear();
-                    }, "clear after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.filterForward(1, 2);
-                    }, "filterForward after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.filterBack(1, 2);
-                    }, "filterBack after store is invalidated");
-
-                    djstest.expectException(function () {
-                        cache.toObservable();
-                    }, "toObservable after store is invalidated");
-
-                    failureIndex++;
-                    if (failureIndex === failures.length) {
-                        restoreStore();
-                        djstest.done();
-                    } else {
-                        nextFailure();
-                    }
-                });
-            } catch (outerError) {
-                djstest.fail("Unexpected failure for first .readRange: " + window.JSON.stringify(outerError));
-                restoreStore();
-                djstest.done();
-            }
-        };
-
-        nextFailure();
-    });
-
-    djstest.addTest(function createDataCacheWithSourceCallsErrorTest() {
-        var cacheSource = {
-            count: function () {
-                djstest.fail("cacheSource.count was called");
-            },
-
-            read: function (index, count, success, error) {
-                setTimeout(function () {
-                    error({ message: "source error" });
-                }, 0);
-            }
-        };
-
-        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
-        cache.readRange(0, 5).then(function () {
-            djstest.fail("unexpected call to then success");
-            djstest.done();
-        }, function (err) {
-            djstest.assertAreEqual(err.message, "source error", "got the expected error");
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function toObservableMissingTest() {
-        createNewCache({ name: "cache", source: "http://temp.org" }).then(function (cache) {
-            var hiddenRx = window.Rx;
-            try {
-                window.Rx = null;
-                var error = null;
-                try {
-                    cache.toObservable();
-                } catch (err) {
-                    error = err;
-                }
-
-                djstest.assert(error !== null, "error !== null");
-            } finally {
-                window.Rx = hiddenRx;
-            }
-
-            djstest.assert(error !== null, "error !== null");
-            djstest.destroyCacheAndDone(cache);
-        });
-    });
-
-    djstest.addTest(function toObservableSinglePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
-            var lastId = -1;
-            cache.toObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableCaseSinglePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
-            var lastId = -1;
-            cache.toObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableMultiplePageTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var callCount = 0;
-            cache.toObservable().subscribe(function (item) {
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-                callCount += 1;
-            }, thenFailTest, function () {
-                djstest.assert(lastId !== -1, "lastId !== -1");
-                djstest.assert(callCount > 1, "callCount > 1");
-                djstest.done();
-            });
-        });
-    });
-
-    djstest.addTest(function toObservableEarlyDisposeTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var callCount = 0;
-            var complete = false;
-            var observer = cache.toObservable().subscribe(function (item) {
-                djstest.assert(complete === false, "complete === false");
-                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
-                lastId = item.FoodID;
-                callCount += 1;
-                complete = true;
-                observer.Dispose();
-                djstest.done();
-            }, thenFailTest);
-        });
-    });
-
-    djstest.addTest(function toObservableFailureTest() {
-        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
-            var lastId = -1;
-            var complete = false;
-            window.MockHttpClient.clear().addResponse("*", { statusCode: 500, body: "server error" });
-            window.MockHttpClient.async = true;
-            var savedClient = window.odatajs.oData.net.defaultHttpClient;
-            window.odatajs.oData.net.defaultHttpClient = window.MockHttpClient;
-            cache.toObservable().subscribe(function (item) {
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                djstest.fail("Unexpected call to OnNext");
-            }, function (err) {
-                djstest.assert(complete === false, "complete === false");
-                djstest.assert(err, "err defined");
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                complete = true;
-                djstest.done();
-            }, function (complete) {
-                djstest.fail("Unexpected call to complete. Error handler should be called.");
-                window.odatajs.oData.net.defaultHttpClient = savedClient;
-                complete = true;
-                djstest.done();
-            });
-        });
-    });
-
-    // DATAJS INTERNAL START
-
-    djstest.addTest(function createDeferredTest() {
-        // Verify basic use of deferred object.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (val1, val2) {
-            djstest.assertAreEqual(val1, 1, "val1 is as specified");
-            djstest.assertAreEqual(val2, 2, "val2 is as specified");
-            djstest.done();
-        });
-        deferred.resolve(1, 2);
-    });
-
-    djstest.addTest(function deferredThenTest() {
-        // Verify then registration and chaining.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (val1, val2) {
-            djstest.assertAreEqual(val1, 1, "val1 is as specified");
-            djstest.assertAreEqual(val2, 2, "val2 is as specified");
-            return "foo";
-        }).then(function (foo) {
-            // See Compatibility Note B in DjsDeferred remarks.
-            djstest.assert(foo !== "foo", "argument for chained 'then' is *not* result of previous call");
-            djstest.assert(foo === 1, "argument for chained 'then' is same as for previous call");
-
-            var other = odatajs.deferred.createDeferred();
-            other.then(null, function (err, msg) {
-                djstest.assertAreEqual("error", err, "err is as specified");
-                djstest.assertAreEqual("message", msg, "msg is as specified");
-
-            }).then(null, function (err, msg) {
-                djstest.log("chained errors are called");
-
-                djstest.assertAreEqual("error", err, "err is as specified");
-                djstest.assertAreEqual("message", msg, "msg is as specified");
-
-                var multiple = odatajs.deferred.createDeferred();
-                var count = 0;
-
-                // See Compatibility Note A in DjsDeferred remarks.
-                multiple.then(function () {
-                    djstest.assertAreEqual(count, 0, "first base registration fires as #0");
-                    count++;
-                }).then(function () {
-                    djstest.assertAreEqual(count, 1, "first chained registration fires as #1");
-                    count++;
-                });
-
-                multiple.then(function () {
-                    djstest.assertAreEqual(count, 2, "second base registration fires as #2");
-                    count++;
-                }).then(function () {
-                    djstest.assertAreEqual(count, 3, "second chained registration fires as #3");
-                    djstest.done();
-                });
-
-                multiple.resolve();
-            });
-            other.reject("error", "message");
-        });
-
-        deferred.resolve(1, 2);
-    });
-
-    djstest.addTest(function deferredResolveTest() {
-        // Resolve with no arguments.
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(function (arg) {
-            djstest.assertAreEqual(arg, undefined, "resolve with no args shows up as undefined");
-
-            // Resolve with no callbacks.
-            var other = odatajs.deferred.createDeferred();
-            other.resolve();
-            djstest.done();
-        });
-
-        deferred.resolve();
-    });
-
-    djstest.addTest(function deferredRejectTest() {
-        // Resolve with no arguments.   
-        var deferred = odatajs.deferred.createDeferred();
-        deferred.then(null, function (arg) {
-            djstest.assertAreEqual(arg, undefined, "reject with no args shows up as undefined");
-
-            // Resolve with no callbacks.
-            var other = odatajs.deferred.createDeferred();
-            other.reject();
-            djstest.done();
-        });
-
-        deferred.reject();
-    });
-
-    djstest.addTest(function estimateSizeTest() {
-        var tests = [
-            { i: null, e: 8 },
-            { i: undefined, e: 8 },
-            { i: 0, e: 8 },
-            { i: "abc", e: 6 },
-            { i: [1, 2, 3], e: 30 },
-            { i: { a1: null, a2: undefined, a3: 5, a4: "ab", a5: { b1: 5, b2: 6} }, e: 72 },
-            { i: {}, e: 0 }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var test = tests[i];
-            djstest.assertAreEqual(odatajs.cache.estimateSize(test.i), test.e);
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function cacheOptionsTunnelTest() {
-        var mockClient = window.MockHttpClient;
-        var doneCalled = false;
-
-        mockClient.clear().setAsync(true).addRequestVerifier("*", function (theRequest) {
-            if (!doneCalled) {
-                doneCalled = true;
-                djstest.assertAreEqual(theRequest.user, "the-user", "theRequest.user");
-                djstest.assertAreEqual(theRequest.password, "the-password", "theRequest.password");
-                djstest.assertAreEqual(theRequest.enableJsonpCallback, false, "theRequest.enableJsonpCallback");
-                djstest.assertAreEqual(theRequest.callbackParameterName, "p", "callbackParameterName");
-                djstest.done();
-            }
-        });
-
-        var cache = odatajs.cache.createDataCache({
-            name: "cacheOptionsTunnel",
-            source: "http://foo-bar/",
-            user: "the-user",
-            password: "the-password",
-            enableJsonpCallback: false,
-            callbackParameterName: "p",
-            httpClient: mockClient
-        });
-
-        cache.readRange(0, 10).then(function (arr) {
-            djstest.fail("unexpected callback into readRange in test cacheOptionsTunnelTest");
-            if (!doneCalled) {
-                doneCalled = true;
-                djstest.done();
-            }
-        });
-    });
-
-    djstest.addTest(function dataCacheHandlesFullStoreTest() {
-
-        var TestStore = function (name) {
-            var that = new window.odatajs.store.MemoryStore(name);
-            that.addOrUpdate = function (key, value, success, error) {
-                if (key === "__settings") {
-                    window.setTimeout(function () {
-                        success(key, value);
-                    }, 0);
-                } else {
-                    window.setTimeout(function () {
-                        error({ name: "QUOTA_EXCEEDED_ERR" });
-                    }, 0);
-                }
-            };
-            return that;
-        };
-
-        TestStore.create = function (name) {
-            return new TestStore(name);
-        };
-
-        TestStore.isSupported = function () {
-            return true;
-        };
-
-        var cacheSource = {
-            identifier: "testSource",
-            count: function (success) {
-                djstest.fail("cacheSource.count was called");
-                success(5);
-            },
-            read: function (index, count, success, error) {
-                djstest.assertAreEqual(index, 0, "index is the expected one");
-                djstest.assertAreEqual(count, 5, "test is the expected one");
-
-                setTimeout(function () {
-                    success({ value: [1, 2, 3, 4, 5] });
-                }, 0);
-            }
-        };
-
-        var originalCreateStore = window.odatajs.store.createStore;
-
-        window.odatajs.store.createStore = function (name, mechanism) {
-            return TestStore(name);
-        };
-
-        try {
-            var cache = odatajs.cache.createDataCache({
-                name: "cache",
-                pageSize: 5,
-                prefetchSize: 0,
-                source: cacheSource,
-                mechanism: "teststore"
-            });
-        } finally {
-            window.odatajs.store.createStore = originalCreateStore;
-        }
-
-        cache.readRange(0, 5).then(function (data) {
-            djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
-            cache.readRange(0, 5).then(function (data) {
-                djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
-                djstest.done();
-            }, thenFailTest);
-        }, thenFailTest);
-    });
-
-    // DATAJS INTERNAL END
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html b/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
deleted file mode 100644
index a3820cb..0000000
--- a/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<html>
-<head>
-    <title>datajs.cache and datajs.store full local store tests</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>-->
-    <!--<script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>-->
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
-    <!--<script type="text/javascript" src="common/common.js"></script>-->
-
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/djstest-browser.js"></script>
-    <script type="text/javascript" src="common/cacheVerifier.js"></script>
-    <script type="text/javascript" src="common/observableHttpClient.js"></script>
-    <!--<script type="text/javascript" src="common/ODataReadOracle.js"></script>-->
-    
-    <script type="text/javascript" src="b-datajs-cache-large-collection-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache and datajs.store full local store 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/d5ec5557/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js b/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
deleted file mode 100644
index d09ae51..0000000
--- a/datajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    window.odatajs.oData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var largeCollectionFeed = "./endpoints/LargeCollectionService.svc/Customers";
-    var itemsInCollection = 2 * 1024 * 1024;
-
-    var cleanDomStorage = function (done) {
-        /* Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
-         *  setup and teardown methods to be consistent with indexedDb's cleanup method.
-         * @param {Function} done - Function to be called after DOM storage is cleared.
-         */
-        if (window.localStorage) {
-            window.localStorage.clear();
-        }
-        done();
-    };
-
-    var cleanIndexedDb = function (done) {
-        /** Cleans all the data saved in the browser's IndexedDb Storage.
-         * @param {Function} done - Function to be called after DOM storage is cleared.
-         */
-        var caches = this.caches;
-
-        djstest.cleanStoreOnIndexedDb(caches, done);
-    };
-
-    var makeUnexpectedErrorHandler = function () {
-        return function (err) {
-            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        };
-    };
-
-    var storageMechanisms = {
-        indexeddb: { cleanup: cleanIndexedDb },
-        dom: { cleanup: cleanDomStorage }
-    };
-
-    var cleanupAllStorage = function(done) {
-        /** Cleans up all available storage mechanisms in the browser.
-         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
-         */
-        var that = this;
-        var storeCleanup = [];
-
-        $.each(CacheVerifier.mechanisms, function(_, mechanism) {
-            if (CacheVerifier.isMechanismAvailable(mechanism)) {
-                storeCleanup.push(function(done) {
-                    if (storageMechanisms[mechanism]) {
-                        storageMechanisms[mechanism].cleanup.call(that, done);
-                    } else {
-                        done();
-                    }
-                });
-            }
-        });
-
-        djstest.asyncDo(storeCleanup, done);
-    };
-
-
-    module("Functional", {
-        setup: function () {
-            this.observableHttpClient = new ObservableHttpClient();
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
-            this.caches = [];
-            var that = this;
-
-            djstest.wait(function (done) {
-                cleanupAllStorage.call(that, done);
-            });
-        },
-
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
-            var clearActions = [];
-            var that = this;
-
-            $.each(this.caches, function (_, cacheObject) {
-                cacheObject.cache.onidle = undefined;
-
-                clearActions.push(function (done) {
-                    cacheObject.cache.clear().then(function () {
-                        done();
-                    },
-                        function (err) {
-                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
-                        });
-                });
-            });
-
-            djstest.wait(function (done) {
-                djstest.asyncDo(clearActions, function () {
-                    cleanupAllStorage.call(that, function () {
-                        that.caches = [];
-                        done();
-                    });
-                });
-            });
-        }
-    });
-
-    $.each(["dom", "indexeddb"], function (_, mechanism) {
-        if (CacheVerifier.isMechanismAvailable(mechanism)) {
-            $.each([-1, 10 * 1024 * 1024, 1024 * 10248], function (_, cacheSize) {
-                var prefetchParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 5, pageSize: 1024, prefetchSize: -1, cacheSize: cacheSize };
-                djstest.addTest(function (params) {
-
-                    djstest.assertsExpected(3);
-                    var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
-                        mechanism: params.mechanism, cacheSize: params.cacheSize
-                    };
-
-                    var cache = odatajs.cache.createDataCache(options);
-                    this.caches.push({ name: options.name,
-                        cache: cache
-                    });
-
-                    cache.onidle = function () {
-                        djstest.assert(true, "onidle Called");
-                        djstest.done();
-                    };
-
-                    var cacheOracle = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
-                    var session = this.observableHttpClient.newSession();
-
-                    cache.readRange(params.skip, params.take).then(function (data) {
-                        var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
-                        cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests with prefetch", false, true);
-                        window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                        });
-                    }, function (err) {
-                        makeUnexpectedErrorHandler(err)();
-                    });
-                }, "readRange and prefetch all to fill store on " + prefetchParameters.mechanism + " with cacheSize=" + prefetchParameters.cacheSize, prefetchParameters, 600000);
-
-                $.each([500, 1024 * 10 /*Test reduced from 100 to 10 to work around slow running script error in IE8 and Safari (bug 2200)*/], function (_, pageSize) {
-                    var largeReadParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 1024, pageSize: pageSize, prefetchSize: 0, cacheSize: cacheSize };
-                    djstest.addTest(function (params) {
-
-                        djstest.assertsExpected(2);
-                        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
-                            mechanism: params.mechanism, cacheSize: params.cacheSize
-                        };
-
-                        var cache = odatajs.cache.createDataCache(options);
-                        this.caches.push({ name: options.name, cache: cache });
-
-                        var cacheOracle = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
-                        var session = this.observableHttpClient.newSession();
-
-                        cache.readRange(params.skip, params.take).then(function (data) {
-                            var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
-                            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests without prefetch", false, false);
-                            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                                djstest.done();
-                            });
-                        }, function (err) {
-                            makeUnexpectedErrorHandler(err)();
-                            djstest.done();
-                        });
-                    }, "readRange of skip=" + largeReadParameters.skip + " take=" + largeReadParameters.take + " cacheSize=" + largeReadParameters.cacheSize + " and pageSize=" + largeReadParameters.pageSize +
-                        " to fill store on " + largeReadParameters.mechanism, largeReadParameters, 600000);
-                });
-            });
-        }
-    });
-})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/bn-odata-json-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/bn-odata-json-tests.js b/datajs/tests-tmp/bn-odata-json-tests.js
deleted file mode 100644
index 3e306a5..0000000
--- a/datajs/tests-tmp/bn-odata-json-tests.js
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-tests.js
-
-(function (window, undefined) {
-    QUnit.module("odata-json-tests.js");
-
-    djstest.addTest(function isArrayTest() {
-        djstest.assert(window.odatajs.utils.isArray([]));
-        djstest.assert(window.odatajs.utils.isArray([1, 2]));
-        djstest.assert(!window.odatajs.utils.isArray({}));
-        djstest.assert(!window.odatajs.utils.isArray("1,2,3,4"));
-        djstest.assert(!window.odatajs.utils.isArray());
-        djstest.assert(!window.odatajs.utils.isArray(null));
-        djstest.done();
-    });
-
-    var verifyReadJsonLightDataMetadataFull = function (input, expected, message, model) {
-        var response = { 
-          headers: { 
-            "Content-Type": "application/json;odata.metadata=full",
-             DataServiceVersion: "4.0"
-          },
-          body: JSON.stringify(input) 
-        };
-
-        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-
-    var verifyReadJsonLightDataMetadataMinimal= function (input, expected, message, model) {
-        var response = { 
-          headers: { 
-            "Content-Type": "application/json;odata.metadata=minimal",
-             DataServiceVersion: "4.0"
-          },
-          body: JSON.stringify(input) 
-        };
-
-        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-
-    function createPointValue(geoKind) { 
-      return { 
-        edmType : geoKind+'Point', value : {
-          type: "Point",
-          coordinates: [1.0, 2.0],
-          crs: {
-              type: "Point",
-              properties: {
-                  name: "EPSG:4326"
-              }
-          }
-        }
-      };
-    }
-
-    function createLineStringValue(geoKind) { 
-      return  { 
-        edmType : geoKind+'LineString', value : {
-          "type": "LineString",
-          "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
-          crs: {
-              type: "LineString",
-              properties: {
-                  name: "EPSG:4326"
-              }
-          }
-        }
-      };
-    }
-
-    function createPolygonValue(geoKind) { 
-      return  {
-        edmType : geoKind+'Polygon', value : {
-          "type": "Polygon",
-          "coordinates": [
-            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
-            [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
-            ],
-          crs: {
-              type: "Polygon",
-              properties: {
-                  name: "EPSG:4326"
-              }
-          }
-        }
-      };
-    }
-
-    function createMultiPointValue(geoKind) { 
-      return  { 
-        edmType : geoKind+'MultiPoint', value : {
-          "type": "MultiPoint",
-          "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
-          crs: {
-              type: "MultiPoint",
-              properties: {
-                  name: "EPSG:4326"
-              }
-          }
-        }
-      };
-    }
-
-    function createMultiLineStringValue(geoKind) { 
-      return  { 
-        edmType : geoKind+'MultiLineString', value : {
-          "type": "MultiLineString",
-          "coordinates": [
-              [ [100.0, 0.0], [101.0, 1.0] ],
-              [ [102.0, 2.0], [103.0, 3.0] ]
-            ],
-          crs: {
-              type: "MultiLineString",
-              properties: {
-                  name: "EPSG:4326"
-              }
-          }
-        }
-      };
-    }
-    function createMultiPolygonStringValue(geoKind) { 
-      return  { 
-        edmType : geoKind+'MultiPolygon', value : {
-                "type": "MultiPolygon",
-                "coordinates": [
-                  [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
-                  [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
-                   [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
-                  ],
-              crs: {
-                  type: "MultiPolygon",
-                  properties: {
-                      name: "EPSG:4326"
-                  }
-              }
-            }
-          };
-        }
-
-    function createWorkload(geoKind) { 
-      return [
-        createPointValue(geoKind),
-        createLineStringValue(geoKind), 
-        createPolygonValue(geoKind),
-        createMultiPointValue(geoKind),
-        createMultiLineStringValue(geoKind),
-        createMultiPolygonStringValue(geoKind) 
-      ];
-    }
-
-    function checkGeoKind(geoKind, full) {
-      var workload = createWorkload(geoKind);
-      for ( var i = 0; i < workload.length; i++) {
-        var item = workload[i]; 
-        var input = {
-          "@odata.context": "http://someUri#Edm."+item.edmType,
-          "value@odata.type" : item.edmType,
-          value: item.value
-        }; 
-
-        var expected = {
-          "@odata.context": "http://someUri#Edm."+item.edmType,
-          "value@odata.type" : item.edmType,
-          value: item.value
-        };
-        if (full) {
-          verifyReadJsonLightDataMetadataFull(input, expected, item.edmType + " was read properly.", {});
-        } else {
-          verifyReadJsonLightDataMetadataMinimal(input, expected, item.edmType + " was read properly.", {});
-        }
-      }
-      
-      djstest.done();
-    }
-
-    djstest.addTest(function jsonReadGeometryFull() {
-      checkGeoKind('Geometry',true);
-    });
-    djstest.addTest(function jsonReadGeometryMinimal() {
-      checkGeoKind('Geometry',false);
-    });
-    djstest.addTest(function jsonReadGeographyFull() {
-      checkGeoKind('Geography',true);
-    });
-    djstest.addTest(function jsonReadGeographyMinimal() {
-      checkGeoKind('Geography',false);
-    });
-
-})(window);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/ODataVerifiyReader.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/ODataVerifiyReader.svc b/datajs/tests-tmp/common/ODataVerifiyReader.svc
deleted file mode 100644
index 101cf36..0000000
--- a/datajs/tests-tmp/common/ODataVerifiyReader.svc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
-    Service="DataJS.Tests.ODataVerifyReader" %>
-
-//uncomment this line to debug JSON serialization.
-//#define DEBUG_SERIALIZATION
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.IO;
-    using System.Linq;
-    using System.Net;
-    using System.Runtime.Serialization;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Syndication;
-    using System.ServiceModel.Web;
-    using System.Xml;
-    using System.Xml.Linq;
-    using Microsoft.Spatial;
-    using Microsoft.OData.Core;
-    using System.Web.Script.Serialization;
-
-    /// <summary>
-    /// Oracle for the OData.read library function
-    /// </summary>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class ODataVerifyReader
-    {
-        const string jsonlightMediaType = "application/json";
-
-        /// <summary>
-        /// Reads a URI that will return a metadata object
-        /// </summary>
-        /// <param name="url">The URL to send the request to</param>
-        /// <returns>Stream of metadata in json light format</returns>
-        [OperationContract]
-        [WebGet]
-        public Stream ReadMetadata(string url)
-        {
-            WebResponse response = WebRequest.Create(ResolveUri(url, UriKind.Absolute)).GetResponse();
-            Dictionary<string, object> jsonObject = CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream()));
-            return ReaderUtils.ConvertDictionarytoJsonlightStream(jsonObject);
-        }
-        
-        /// <summary>
-        /// Reads a URI that will get the Json response and return the stream
-        /// </summary>
-        /// <param name="url">URL of the entry</param>
-        /// <param name="user">The username for basic authentication</param>
-        /// <param name="password">The password for basic authentication</param>
-        /// <returns>Stream of the Json response expected to be returned by OData.read</returns>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public Stream ReadJson(string url, string mimeType, string user, string password)
-        {
-            if (mimeType == null)
-            {
-                mimeType = jsonlightMediaType + ";odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8";
-            }
-            
-            HttpWebRequest request = (HttpWebRequest)ReaderUtils.CreateRequest(ResolveUri(url, UriKind.Absolute), user, password);
-            request.Accept = mimeType;
-            WebResponse response = request.GetResponse();
-
-            return response.GetResponseStream();
-        }
-
-        /// <summary>
-        /// Resolves the given url string to a URI
-        /// </summary>
-        /// <param name="url">The given URL string</param>
-        /// <param name="urlKind">URI kind to resolve to</param>
-        /// <returns>The resolved URI</returns>
-        private static string ResolveUri(string url, UriKind uriKind)
-        {
-            Uri resolvedUri = new Uri(url, UriKind.RelativeOrAbsolute);
-            if (!resolvedUri.IsAbsoluteUri)
-            {
-                // If the given URI is relative, then base it on the Referer URI
-                Uri baseUri = new Uri(WebOperationContext.Current.IncomingRequest.Headers["Referer"]);
-                resolvedUri = new Uri(baseUri, resolvedUri);
-                if (uriKind == UriKind.Relative)
-                {
-                    resolvedUri = baseUri.MakeRelativeUri(resolvedUri);
-                }
-            }
-
-            return resolvedUri.ToString();
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/djstest-browser.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/djstest-browser.js b/datajs/tests-tmp/common/djstest-browser.js
deleted file mode 100644
index 14e5401..0000000
--- a/datajs/tests-tmp/common/djstest-browser.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
-// we define the @namespace djstest here instead of the a @module name djstest
-
-/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
- * @namespace djstest
- */
-
-if (typeof window !== 'undefined') {
-    //expose to browsers window object
-    window.djstest = window.djstest || {};
-    init(window.djstest);
-} else {
-    //expose in commonjs style
-    module.exports = init();
-}
-
-
-function init (parent) {
-    djstest = parent || {};
-
-    // Initialize indexedDB if the window object is available
-    djstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
-
-    /** Cleans all the test data saved in the IndexedDb database.
-     * @param {Array} storeNames - Array of store objects with a property that is the name of the store
-     * @param {Function} done - Callback function
-     */
-    djstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
-        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
-
-        function deleteObjectStores(db) {
-            for ( var i = 0 ; i < db.objectStoreNames.length ; i ++) {
-                db.deleteObjectStore(db.objectStoreNames[i]);
-            }
-        }
-        var job;
-
-        if (djstest.indexedDB) {
-            job = new djstest.Job();
-            for ( var i = 0 ; i < storeObjects.length ; i ++) {
-                storeObject = storeObjects[i];
-                job.queue((function (storeObject) {
-                    return function (success, fail) {
-                        var dbname = "_datajs_" + storeObject.name;
-                        var request = djstest.indexedDB.open(dbname);
-                        request.onsuccess = function (event) {
-                            var db = request.result;
-
-                            if ("setVersion" in db) {
-                                var versionRequest = db.setVersion("0.1");
-                                versionRequest.onsuccess = function (event) {
-                                    var transaction = versionRequest.transaction;
-                                    transaction.oncomplete = function () {
-                                        db.close();
-                                        success();
-                                    };
-                                    deleteObjectStores(db);
-                                };
-                                versionRequest.onerror = function (e) {
-                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
-                                    fail();
-                                };
-                                return;
-                            }
-
-                            // new api cleanup
-                            db.close();
-                            var deleteRequest = djstest.indexedDB.deleteDatabase(dbname);
-                            deleteRequest.onsuccess = function (event) {
-                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
-                                success();
-                            };
-                            deleteRequest.onerror = function (e) {
-                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
-                                fail();
-                            };
-                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
-                        };
-
-                        request.onerror = function (e) {
-                            djstest.fail(e.code + ": " + e.message);
-                        };
-                    };
-                })(storeObject));
-            }
-        }
-
-        if (job) {
-            job.run(function (succeeded) {
-                if (!succeeded) {
-                    djstest.fail("cleanup job failed");
-                }
-                done();
-            });
-        }
-        else {
-            done();
-        }
-    };
-
-
-    // Disable caching to ensure that every test-related AJAX request is actually being sent,
-    // and set up a default error handler
-    if (typeof window !== undefined) {
-        $.ajaxSetup({
-            cache: false,
-            error: function (jqXHR, textStatus, errorThrown) {
-                // Work around bug in IE-Mobile on Windows Phone 7
-                if (jqXHR.status !== 1223) {
-                    var err = {
-                        status: jqXHR.status,
-                        statusText: jqXHR.statusText,
-                        responseText: jqXHR.responseText
-                    };
-                    djstest.fail("AJAX request failed with: " + djstest.toString(err));
-                }
-                djstest.done();
-            }
-        });
-    }
-    return djstest;
-}


[21/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/tools.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/tools.js b/odatajs/demo/scripts/tools.js
new file mode 100644
index 0000000..d13dd7d
--- /dev/null
+++ b/odatajs/demo/scripts/tools.js
@@ -0,0 +1,146 @@
+(function($) {
+  $.fn.prettify = function(options) {
+    return this.each(function() {
+      try {
+        var $code = $(document.createElement('div')).addClass('code');
+        $(this).before($code).remove();
+        var content = $(this).text();
+        var match = /(xml|json)/.exec($(this).attr('data-type'));
+        var format = (match) ? match[1] : null;
+        var html = null;
+        if (format == 'xml') {
+          var xmlDoc = $.parseXML(content);
+          html = (xmlDoc) ? formatXML(xmlDoc) : null;
+        } else if (format == 'json') {
+          var jsonObj = $.parseJSON(content);
+          html = (jsonObj) ? formatJSON(jsonObj) : null;
+        }
+        if (html) {
+          $code.addClass(format).html(html).find('.list').each(function() {
+            if (this.parentNode.nodeName == 'LI') {
+              $(document.createElement('div')).addClass("toggle").text("-").click(function() {
+                var target = $(this).siblings('.list:first');
+                if (target.size() != 1)
+                  return;
+                if (target.is(':hidden')) {
+                  target.show().siblings('.deffered').remove();
+                } else {
+                  target.hide().before($(document.createElement('span')).attr("class", "deffered").html("..."));
+                }
+                $(this).text($(this).text() == '-' ? '+' : '-');
+              }).insertBefore($(this.parentNode).children(':first'));
+            }
+          });
+        }
+      } catch (e) {
+        console.log(e);
+      }
+      /* encode html */
+      function encodeHtml(html) {
+        return (html != null) ? html.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
+      }
+      /* convert json to html */
+      function formatJSON(value) {
+        var typeofValue = typeof value;
+        if (value == null) {
+          return '<span class="null">null</span>';
+        } else if (typeofValue == 'number') {
+          return '<span class="numeric">' + encodeHtml(value) + '</span>';
+        } else if (typeofValue == 'string') {
+          if (/^(http|https):\/\/[^\s]+$/.test(value)) {
+            var fragment = '';
+            var fragmentIndex = value.indexOf('#');
+            if (fragmentIndex != -1) {
+              fragment = value.substr(fragmentIndex);
+              value = value.substr(0, fragmentIndex);
+            }
+            var format = (value.length > 7) ? (value.substr(value.length - 7, 7) == '/$value' ? '' : '&$format=json' ) : '';
+            format = (value.length > 10) ? (value.substr(value.length - 10, 10) == '/$metadata' ? '' : '&$format=json' ) : '';
+            var separator = (value.indexOf('?') == -1) ? '?' : '&';
+            return '<span class="string">"<a href="' + value + separator + 'sap-ds-debug=true' + format + fragment + '">' + encodeHtml(value) + encodeHtml(fragment) + '</a>"</span>';
+          } else {
+            return '<span class="string">"' + encodeHtml(value) + '"</span>'
+          }
+        } else if (typeofValue == 'boolean') {
+          return '<span class="boolean">' + encodeHtml(value) + '</span>'
+        } else if (value && value.constructor == Array) {
+          return formatArray(value);
+        } else if (typeofValue == 'object') {
+          return formatObject(value);
+        } else {
+          return '';
+        }
+        function formatArray(json) {
+          var html = '';
+          for ( var prop in json)
+            html += '<li>' + formatJSON(json[prop]) + '</li>';
+          return (html) ? '<span class="array">[</span><ul class="array list">' + html + '</ul><span class="array">]</span>' : '<span class="array">[]</span>'
+        }
+        function formatObject(json) {
+          var html = '';
+          for ( var prop in json)
+            html += '<li><span class="property">' + encodeHtml(prop) + '</span>: ' + formatJSON(json[prop]) + '</li>';
+          return (html) ? '<span class="obj">{</span><ul class="obj list">' + html + '</ul><span class="obj">}</span>' : '<span class="obj">{}</span>';
+        }
+      }
+      /* convert xml to html */
+      function formatXML(document) {
+        return formatElement(document.documentElement);
+        function formatElement(element) {
+          var html = '<span>&lt;</span><span class="tag">' + encodeHtml(element.nodeName) + '</span>';
+          if (element.attributes && element.attributes.length > 0) {
+           html += formatAttributes(element);
+          }
+          if (element.childNodes && element.childNodes.length > 0) {
+            html += '<span>&gt;</span>';
+            if (element.childNodes.length == 1 && element.childNodes[0].nodeType == 3) {
+              html += '<span class="text">' + encodeHtml(element.childNodes[0].nodeValue) + '</span>';
+            } else {
+              html += formatChildNodes(element.childNodes);                    
+            } 
+            html += '<span>&lt;/</span><span class="tag">' + encodeHtml(element.nodeName) + '</span><span>&gt;</span>';
+          } else {
+            html += '<span>/&gt;</span>';
+          } 
+          return html;                
+        }
+        function formatChildNodes(childNodes) {
+          html = '<ul class="list">';
+          for ( var i = 0; i < childNodes.length; i++) {
+            var node = childNodes[i];
+            if (node.nodeType == 1) {
+              html += '<li>' + formatElement(node) + '</li>';
+            } else if (node.nodeType == 3 && !/^\s+$/.test(node.nodeValue)) {
+              html += '<li><span class="text">' + encodeHtml(node.nodeValue) + '</span></li>';
+            } else if (node.nodeType == 4) {
+              html += '<li><span class="cdata">&lt;![CDATA[' + encodeHtml(node.nodeValue) + ']]&gt;</span></li>';
+            } else if (node.nodeType == 8) {
+              html += '<li><span class="comment">&lt;!--' + encodeHtml(node.nodeValue) + '--&gt;</span></li>';
+            }
+          }
+          html += '</ul>';
+          return html;
+        }
+        function formatAttributes(element) {
+          var html = '';
+          for (var i = 0; i < element.attributes.length; i++) {
+            var attribute = element.attributes[i];
+            if (/^xmlns:[^\s]+$/.test(attribute.nodeName)) {
+              html += ' <span class="ns">' + encodeHtml(attribute.nodeName) + '="' + encodeHtml(attribute.nodeValue) + '"</span>';
+            } else {
+              html += ' <span class="atn">' + encodeHtml(attribute.nodeName) + '</span>=';
+              if (attribute.nodeName == 'href' || attribute.nodeName == 'src') {
+                var separator = (attribute.nodeValue.indexOf('?') == -1) ? '?' : '&';
+                var href = (element.baseURI && attribute.nodeValue[0] != '/') ? element.baseURI + attribute.nodeValue : attribute.nodeValue;
+                html += '"<a class="link" href="' + href + separator + 'sap-ds-debug=true">' + encodeHtml(attribute.nodeValue) + '</a>"';                    
+              } else {
+                html += '"<span class="atv">' + encodeHtml(attribute.nodeValue) + '</span>"';
+              }                
+            }   
+          }
+          return html;
+        }
+      }
+    });
+  };
+})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/tester.html
----------------------------------------------------------------------
diff --git a/odatajs/demo/tester.html b/odatajs/demo/tester.html
new file mode 100644
index 0000000..512b9e1
--- /dev/null
+++ b/odatajs/demo/tester.html
@@ -0,0 +1,217 @@
+<html>
+    <head>
+        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+        <title>datajs startup perf test</title>
+        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
+        <script type="text/javascript" src="./scripts/odatajs-4.0.0-beta-01.js"></script>
+        <script type="text/javascript" src="./scripts/tools.js" ></script>
+        <style type="text/css">
+            .code{font-family:"Courier New",monospace;font-size:13px;line-height:18px;}
+            .code ul{list-style:none;margin:0 0 0 1.5em;padding:0;}
+            .code li{position:relative;}
+            .code.json li:after{content:',';}
+            .code.json li:last-child:after{content:'';}
+            .code span{white-space:nowrap;padding:2px 1px;}
+            .code .property{font-weight:bold;color:#000000;}
+            .code .null{color:#9d261d;}
+            .code .boolean{color:#760a85;}
+            .code .numeric{color:#0076cb;}
+            .code .string{color:#247230;}
+            .code .deffered{color:#666666;font-size:0.9em;}
+            .code .toggle{position:absolute;left:-1em;cursor:pointer;}
+            .code .tag{color:#003283;}
+            .code .atn{color:#760a85;}
+            .code .atv{color:#247230;}
+            .code .text{color:#000000;}
+            .code .cdata{color:#008080;}
+            .code .comment,.code .ns{color:#666666;}
+
+            .left {
+                margin-left : 20px;
+                position:relative;
+            }
+
+        </style>
+    </head>   
+    <body>
+        <table><tr><td valign="top" width="150px">
+            Metadata<br>
+            <input type="radio" id="inMetadata1" name="inMetadata" value="none"/>                       
+            <label for="inMetadata1">none</label><br>
+
+            <input type="radio" id="inMetadata2" name="inMetadata" value="minimal" checked="checked"/>  
+            <label for="inMetadata2">minimal<br>
+            <div class="left">                                   
+                <input type="checkbox" id="inMinimalToFull">                                   
+                <label for="inMinimalToFull" id="lblInMinimalToFull">minimal to full</label><br>
+            </div>
+
+            <input type="radio" id="inMetadata3" name="inMetadata" value="full"><label for="inMetadata3">full</label>
+            <br>
+            Recognize Dates<br>
+            <input type="checkbox" id="inRecognizeDates"><label for="check1">yes/no</label><br>
+
+        </td><td>
+            <div id="buttons"></div>
+        </td><td>
+            <button id="btnMetaData">MetaData</button><br/>
+            <button id="btnPOST_entry_food">POST food entry</button><br/>
+            <button id="btnPOST_entry_categorie">POST categorie entry</button><br/>
+        </td></tr></table>
+        <div id='resultsArea' data-type="json">
+        </div>
+        <script>
+            // Config
+            var config = [
+                { name: 'Feed', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods'},
+                { name: 'Entry', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)'},
+                { name: 'Collection of Complex', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Providers'},
+                { name: 'Collection of Simple', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/AlternativeNames'},
+                { name: 'Complex property', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Packaging'},
+                { name: 'Simple property', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Name'},
+            ];
+
+            // UI Stuff
+            var createButtonClickHandler = function(nr) {
+                return function() { buttonClick(nr);};
+            };
+
+            var buttonRoot = $('#buttons');
+            $("input[name*='inMetadata'").click( function() {
+                var metadata = $("input[name*='inMetadata']:checked").val();
+                if (metadata === "minimal") {
+                    $("#lblInMinimalToFull").css('color', '#000000');
+                    $("#inMinimalToFull").removeAttr('disabled');
+                } else {
+                    $("#lblInMinimalToFull").css('color', '#999999');
+                    $("#inMinimalToFull").attr('disabled','disabled');
+                }
+            });
+
+            for (var i = 0; i < config.length; i++) {
+                var button = $('<button id="btnArray">'+config[i].name+'</button><br/>"');
+                button.click( createButtonClickHandler(i));
+                buttonRoot.append(button);
+            }
+
+            // Testing 
+            function buttonClick(configNr) {
+                var metadata = $("input[name*='inMetadata']:checked").val();
+                var recognizeDates  = ($("#inRecognizeDates").val() ==='on') ? true : false;
+                var inMinimalToFull = ($("#inMinimalToFull").val() ==='on') ? true : false;
+
+                var requestUri = {
+                    requestUri : config[configNr].url
+                };
+
+                requestUri.recognizeDates = recognizeDates;
+
+                var metaDatasuccess = function(metadata){
+                    odatajs.oData.read(requestUri, success, errorFunc, null, null, metadata);
+                };
+
+                if ( metadata === 'full') {
+                    requestUri.headers =  { Accept : 'application/json;odata.metadata=full' };
+                    odatajs.oData.read(requestUri, success, errorFunc);
+                } else if ( metadata === 'minimal') {
+                    requestUri.headers =  { Accept : 'application/json;odata.metadata=minimal' };
+                    if (inMinimalToFull) {
+                        getMetaData(metaDatasuccess);
+                    } else {
+                        odatajs.oData.read(requestUri, success, errorFunc);   
+                    }
+                } else {
+                    requestUri.headers =  { Accept : 'application/json;odata.metadata=none' };
+                    odatajs.oData.read(requestUri, success, errorFunc);
+                }
+            }
+
+            function show(data) {
+                $('#resultsArea').empty();
+                var code = $('<code data-type="json"></code>').text(JSON.stringify(data));
+                $('#resultsArea').append(code);
+                $('code[data-type]').prettify();
+            }
+            function success(data) {
+                show(data);
+            }
+
+            function errorFunc(err) {
+                $('#resultsArea').empty();
+                $("#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,
+                };
+                odatajs.oData.read(metadataRequest, metaDatasuccess, errorFunc,odatajs.oData.metadataHandler);
+            }
+
+            /*******Special buttons***********/           
+
+            $('#btnMetaData').on("click", function(){
+                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,
+                };
+
+                odatajs.oData.read(metadataRequest, success, errorFunc,odatajs.oData.metadataHandler);
+            });
+
+            $('#btnPOST_entry_food').on("click", function(){
+                var requestUri = {
+                    requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
+                    method: 'POST',
+                    headers : { Accept : 'application/json' },
+                    recognizeDates : true,
+                    data : {
+                        "@odata.type": "#DataJS.Tests.V4.Food",
+                        "@odata.context": "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Foods/$entity",
+                        FoodID: 111,
+                        Name: "flour1"
+                    }
+                };
+                odatajs.oData.read(requestUri, success, errorFunc);
+            });
+            $('#btnPOST_entry_categorie').on("click", function(){
+
+                var requestUri = {
+                    requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories',
+                    method: 'POST',
+                    headers : { Accept : 'application/json' },
+                    recognizeDates : true,
+                    data : {
+                        "@odata.type": "#DataJS.Tests.V4.Category",
+                        "@odata.context": "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity",
+                        CategoryID: 111,
+                        Name: "cat111"
+                    }
+                };
+                odatajs.oData.read(requestUri, success, errorFunc);
+            });
+
+
+
+        </script>
+    </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/testerV2.html
----------------------------------------------------------------------
diff --git a/odatajs/demo/testerV2.html b/odatajs/demo/testerV2.html
new file mode 100644
index 0000000..b9bf1c8
--- /dev/null
+++ b/odatajs/demo/testerV2.html
@@ -0,0 +1,72 @@
+<html>
+    <head>
+        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+        <title>datajs startup perf test</title>
+        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
+        <script type="text/javascript" src="./scripts/datajs-1.1.2.js"></script>
+        <script type="text/javascript" src="./scripts/tools.js" ></script>
+        <style type="text/css">
+            .code{font-family:"Courier New",monospace;font-size:13px;line-height:18px;}
+            .code ul{list-style:none;margin:0 0 0 1.5em;padding:0;}
+            .code li{position:relative;}
+            .code.json li:after{content:',';}
+            .code.json li:last-child:after{content:'';}
+            .code span{white-space:nowrap;padding:2px 1px;}
+            .code .property{font-weight:bold;color:#000000;}
+            .code .null{color:#9d261d;}
+            .code .boolean{color:#760a85;}
+            .code .numeric{color:#0076cb;}
+            .code .string{color:#247230;}
+            .code .deffered{color:#666666;font-size:0.9em;}
+            .code .toggle{position:absolute;left:-1em;cursor:pointer;}
+            .code .tag{color:#003283;}
+            .code .atn{color:#760a85;}
+            .code .atv{color:#247230;}
+            .code .text{color:#000000;}
+            .code .cdata{color:#008080;}
+            .code .comment,.code .ns{color:#666666;}
+        </style>
+    </head>   
+    <body>
+        <button id="btnMetaData">MetaData</button><br/>
+        <button id="btnJSON_minimal">pure JSON</button><br/>
+
+        <div id='resultsArea'>
+
+        </div>
+        <script>
+            function show(data) {
+                $('#resultsArea').empty();
+                var code = $('<code data-type="json"></code>').text(JSON.stringify(data))
+                $('#resultsArea').append(code);
+                $('code[data-type]').prettify();
+            }
+            function success(data) {
+                show(data);
+            }
+
+            function errorFunc(err) {
+                $('#resultsArea').empty();
+                $("#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);
+            });
+            
+            $('#btnJSON_minimal').on("click", function(){
+                var requestUri ='http://localhost:4003/sap/bc/odata/Employees?$format=json';
+                OData.read(requestUri, success, errorFunc);
+            });
+
+        </script>
+    </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/browserify_transforms/stripheader/package.json
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/browserify_transforms/stripheader/package.json b/odatajs/grunt-config/browserify_transforms/stripheader/package.json
new file mode 100644
index 0000000..b8837af
--- /dev/null
+++ b/odatajs/grunt-config/browserify_transforms/stripheader/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "grunt-rat",
+  "version": "0.0.1",
+  "description": "Transform vor removing license headers",
+  "license": "Apache",
+  "author": {
+    "name": "Sven Kobler-Morris",
+    "email": "koblers@apache.org"
+  },
+  "files": [
+    "tasks"
+  ],
+  "dependencies": {
+    "through": "^2.3.4"
+  },
+  "devDependencies": {
+  },
+  "peerDependencies": {
+    "grunt": "~0.4.0"
+  },
+  "engines": {
+    "node": ">=0.8.0"
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/browserify_transforms/stripheader/stripheader.js
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/browserify_transforms/stripheader/stripheader.js b/odatajs/grunt-config/browserify_transforms/stripheader/stripheader.js
new file mode 100644
index 0000000..7df58cb
--- /dev/null
+++ b/odatajs/grunt-config/browserify_transforms/stripheader/stripheader.js
@@ -0,0 +1,21 @@
+var through = require('through');
+
+module.exports = function (file) {
+  //if (/\.json$/.test(file)) return through();
+
+  var data = "";
+
+  return through(
+    function (buf) { data += buf;    },
+    function () {
+      try {
+        var out = data.replace(/^(\/\*(.|\n|\r)*?\*\/)/gi,"");
+        this.queue(out);
+      } catch (er) {
+        this.emit("error", new Error(er.toString().replace("Error: ", "") + " (" + file + ")"));
+      }
+      this.queue(null);
+    }
+  );
+};
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/custom-tasks/rat/package.json
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/custom-tasks/rat/package.json b/odatajs/grunt-config/custom-tasks/rat/package.json
new file mode 100644
index 0000000..6753173
--- /dev/null
+++ b/odatajs/grunt-config/custom-tasks/rat/package.json
@@ -0,0 +1,26 @@
+{
+  "name": "grunt-rat",
+  "version": "0.0.1",
+  "description": "Run Apache Rat(release audit tool)",
+  "license": "Apache",
+  "author": {
+    "name": "Sven Kobler-Morris",
+    "email": "koblers@apache.org"
+  },
+  "files": [
+    "tasks"
+  ],
+  "dependencies": {
+    "chalk": "~0.4.0"
+  },
+  "devDependencies": {
+    "grunt": "~0.4.0",
+    "xml2js": "^0.4.4"
+  },
+  "peerDependencies": {
+    "grunt": "~0.4.0"
+  },
+  "engines": {
+    "node": ">=0.8.0"
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/custom-tasks/rat/readme.md
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/custom-tasks/rat/readme.md b/odatajs/grunt-config/custom-tasks/rat/readme.md
new file mode 100644
index 0000000..2921499
--- /dev/null
+++ b/odatajs/grunt-config/custom-tasks/rat/readme.md
@@ -0,0 +1,2 @@
+require http://creadur.apache.org/rat/download_rat.cgi --> apache-rat-0.10-bin.zip
+to be upacked to /tools/apache-rat-0.10-bin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/custom-tasks/rat/tasks/rat.js
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/custom-tasks/rat/tasks/rat.js b/odatajs/grunt-config/custom-tasks/rat/tasks/rat.js
new file mode 100644
index 0000000..8c6e8b0
--- /dev/null
+++ b/odatajs/grunt-config/custom-tasks/rat/tasks/rat.js
@@ -0,0 +1,93 @@
+'use strict';
+
+module.exports = function (grunt) {
+  grunt.registerMultiTask('rat', 'Run Apache Rat', function () {
+    var path = require('path');
+    var chalk = require('chalk');
+    var childProcess = require('child_process');
+    var xml2js = require('xml2js');
+    var fs = require('fs');
+
+    var cb = this.async();
+
+    var options = this.options({ xml : true, tmpDir : './build/tmp'});
+    var dir = this.data.dir;
+    var out = options.tmpDir + '/' + (options.xml ? 'rat.xml' : 'rat.txt');
+
+    var pathToRat =  path.resolve(__dirname,'./../tools/apache-rat-0.10/apache-rat-0.10.jar');
+    
+    //sample command java -jar apache-rat-0.10.jar -x -d ./src > ./build/tmp/rat.txt
+    var cmd = 'java -jar ' + pathToRat+ ' ';
+    cmd += options.xml ? ' -x' : '';
+    cmd += ' --force -d ' + dir + ' > ' + out;
+
+    grunt.verbose.writeln('Directory: '+dir);
+
+    var cp = childProcess.exec(cmd, options.execOptions, function (err, stdout, stderr) {
+      if (err) {
+        grunt.fail.warn('rat --> ' + err, 1); //exit grunt with error code 1
+      }
+      
+      
+      
+      if (!options.xml) {
+        grunt.fail.warn('rat --> ' + 'No XML output: checkRatLogFile skipped!', 1); 
+      }
+
+      var xml = grunt.file.read(out);
+      var parser = new xml2js.Parser();
+
+      parser.parseString(xml, function (err, result) {
+
+          if (err) {
+            grunt.fail.warn('rat --> ' + err, 1); 
+          }
+          
+          if (checkRatLogFile(result)) {
+            grunt.fail.warn('rat --> ' + 'Missing or Invalied license header detected ( see "'+out+'")', 1);
+          }
+
+          
+      });
+      cb(); 
+      
+    }.bind(this));
+
+    var checkRatLogFile = function(result) {
+
+      var list = result['rat-report']['resource'];
+      for (var i = 0; i < list.length; i++ ){
+        var item = list[i];
+
+        var headerType = list[i]['header-type'];
+        var attr = headerType[0]['$'];
+        if (attr.name.trim() !== 'AL') {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    var captureOutput = function (child, output) {
+      if (grunt.option('color') === false) {
+        child.on('data', function (data) {
+          output.write(chalk.stripColor(data));
+        });
+      } else {
+        child.pipe(output);
+      }
+    };
+
+    grunt.verbose.writeln('Command:', chalk.yellow(cmd));
+
+    captureOutput(cp.stdout, process.stdout);
+      captureOutput(cp.stderr, process.stderr);
+
+    if (options.stdin) {
+      process.stdin.resume();
+      process.stdin.setEncoding('utf8');
+      process.stdin.pipe(cp.stdin);
+    }
+  });
+};
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/grunt-config/rat-config.js
----------------------------------------------------------------------
diff --git a/odatajs/grunt-config/rat-config.js b/odatajs/grunt-config/rat-config.js
new file mode 100644
index 0000000..06f5b7d
--- /dev/null
+++ b/odatajs/grunt-config/rat-config.js
@@ -0,0 +1,15 @@
+module.exports = function(grunt) {
+  grunt.config('rat', {
+    options: { xml : true, tmpDir : './build/tmp' },
+    src: {                      
+      dir: './src',
+    },
+    test: {                      
+      dir: './tests'
+    },
+  });
+
+ 
+  grunt.loadTasks('grunt-config/custom-tasks/rat/tasks');
+  grunt.registerTask('custom-license-check',['rat:src','rat:test']);
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/package.json
----------------------------------------------------------------------
diff --git a/odatajs/package.json b/odatajs/package.json
new file mode 100644
index 0000000..18eee26
--- /dev/null
+++ b/odatajs/package.json
@@ -0,0 +1,42 @@
+{
+  "name": "odatajs",
+  "postfix" : "beta-01",
+  "title": "Olingo OData Client for Java Script",
+  "version": "4.0.0",
+  "description": "odatajs is a new cross-browser JavaScript library that enables data-centric web applications by leveraging modern protocols such as JSON and OData and HTML5-enabled browser features. It's designed to be small, fast and easy to use.",
+  "homepage": "http://olingo.apache.org",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "http://git-wip-us.apache.org/repos/asf/olingo-odata4-js.git"
+  },
+  "engines": {
+    "node": ">= 0.10.0"
+  },
+  "contributors": [
+    {
+      "name": "Bing Li",
+      "email": "bingl@apache.org"
+    },
+    {
+      "name": "Sven Kobler-Morris",
+      "email": "koblers@apache.org"
+    }
+  ],
+  "scripts": {},
+  "devDependencies": {
+    "browserify": "^4.1.5",
+    "grunt": "^0.4.5",
+    "grunt-browserify": "^2.1.0",
+    "grunt-connect-proxy": "^0.1.10",
+    "grunt-contrib-clean": "^0.6.0",
+    "grunt-contrib-compress": "^0.10.0",
+    "grunt-contrib-concat": "^0.5.0",
+    "grunt-contrib-connect": "^0.7.1",
+    "grunt-contrib-copy": "^0.5.0",
+    "grunt-contrib-uglify": "^0.4.0",
+    "grunt-jsdoc": "^0.5.6",
+    "grunt-node-qunit": "^2.0.2",
+    "through": "^2.3.4"
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/packages.config
----------------------------------------------------------------------
diff --git a/odatajs/packages.config b/odatajs/packages.config
new file mode 100644
index 0000000..9e7480b
--- /dev/null
+++ b/odatajs/packages.config
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Microsoft.OData.Client" version="6.5.0" targetFramework="net40" />
+  <package id="Microsoft.OData.Core" version="6.5.0" targetFramework="net40" />
+  <package id="Microsoft.OData.Edm" version="6.5.0" targetFramework="net40" />
+  <package id="Microsoft.Spatial" version="6.5.0" targetFramework="net40" />
+</packages>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/readme.md
----------------------------------------------------------------------
diff --git a/odatajs/readme.md b/odatajs/readme.md
new file mode 100644
index 0000000..bcd2560
--- /dev/null
+++ b/odatajs/readme.md
@@ -0,0 +1,20 @@
+Development
+===========
+
+Preparation 
+1.  npm install -g grunt-cli
+
+Installation
+1.  git clone https://git-wip-us.apache.org/repos/asf/olingo-odata4-js
+1.  cd datajs
+1.  npm install
+
+Build datajs-x.x.x.js
+1.  grunt build
+*   Output is copied into the directory ...
+
+Run demo
+1.  grunt run
+
+Run tests
+1.  grunt test

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/banner.txt
----------------------------------------------------------------------
diff --git a/odatajs/src/banner.txt b/odatajs/src/banner.txt
new file mode 100644
index 0000000..edbaff2
--- /dev/null
+++ b/odatajs/src/banner.txt
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+ 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/index.js
----------------------------------------------------------------------
diff --git a/odatajs/src/index.js b/odatajs/src/index.js
new file mode 100644
index 0000000..fa4203d
--- /dev/null
+++ b/odatajs/src/index.js
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+var odatajs = require('./lib/datajs.js');
+
+odatajs.oData = require('./lib/odata.js');
+odatajs.store = require('./lib/store.js');
+odatajs.cache = require('./lib/cache.js');
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    window.odatajs = odatajs;
+} else {
+    //expose in commonjs style
+    odatajs.node = "node";
+    module.exports = odatajs;
+}


[48/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/datajs-1.1.2.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/datajs-1.1.2.js b/datajs/demo/scripts/datajs-1.1.2.js
deleted file mode 100644
index 5040efc..0000000
--- a/datajs/demo/scripts/datajs-1.1.2.js
+++ /dev/null
@@ -1,10577 +0,0 @@
-// 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.
-
-// odatajs.js
-
-(function (window, undefined) {
-
-    var datajs = window.odatajs || {};
-    var odata = window.OData || {};
-
-    // AMD support
-    if (typeof define === 'function' && define.amd) {
-        define('datajs', datajs);
-        define('OData', odata);
-    } else {
-        window.odatajs = datajs;
-        window.OData = odata;
-    }
-
-    odatajs.version = {
-        major: 1,
-        minor: 1,
-        build: 1
-    };
-
-
-    var activeXObject = function (progId) {
-        /// <summary>Creates a new ActiveXObject from the given progId.</summary>
-        /// <param name="progId" type="String" mayBeNull="false" optional="false">
-        ///    ProgId string of the desired ActiveXObject.
-        /// </param>
-        /// <remarks>
-        ///    This function throws whatever exception might occur during the creation
-        ///    of the ActiveXObject.
-        /// </remarks>
-        /// <returns type="Object">
-        ///     The ActiveXObject instance. Null if ActiveX is not supported by the
-        ///     browser.
-        /// </returns>
-        if (window.ActiveXObject) {
-            return new window.ActiveXObject(progId);
-        }
-        return null;
-    };
-
-    var assigned = function (value) {
-        /// <summary>Checks whether the specified value is different from null and undefined.</summary>
-        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
-        /// <returns type="Boolean">true if the value is assigned; false otherwise.</returns>
-        return value !== null && value !== undefined;
-    };
-
-    var contains = function (arr, item) {
-        /// <summary>Checks whether the specified item is in the array.</summary>
-        /// <param name="arr" type="Array" optional="false" mayBeNull="false">Array to check in.</param>
-        /// <param name="item">Item to look for.</param>
-        /// <returns type="Boolean">true if the item is contained, false otherwise.</returns>
-
-        var i, len;
-        for (i = 0, len = arr.length; i < len; i++) {
-            if (arr[i] === item) {
-                return true;
-            }
-        }
-
-        return false;
-    };
-
-    var defined = function (a, b) {
-        /// <summary>Given two values, picks the first one that is not undefined.</summary>
-        /// <param name="a">First value.</param>
-        /// <param name="b">Second value.</param>
-        /// <returns>a if it's a defined value; else b.</returns>
-        return (a !== undefined) ? a : b;
-    };
-
-    var delay = function (callback) {
-        /// <summary>Delays the invocation of the specified function until execution unwinds.</summary>
-        /// <param name="callback" type="Function">Callback function.</param>
-        if (arguments.length === 1) {
-            window.setTimeout(callback, 0);
-            return;
-        }
-
-        var args = Array.prototype.slice.call(arguments, 1);
-        window.setTimeout(function () {
-            callback.apply(this, args);
-        }, 0);
-    };
-
-
-    var extend = function (target, values) {
-        /// <summary>Extends the target with the specified values.</summary>
-        /// <param name="target" type="Object">Object to add properties to.</param>
-        /// <param name="values" type="Object">Object with properties to add into target.</param>
-        /// <returns type="Object">The target object.</returns>
-
-        for (var name in values) {
-            target[name] = values[name];
-        }
-
-        return target;
-    };
-
-    var find = function (arr, callback) {
-        /// <summary>Returns the first item in the array that makes the callback function true.</summary>
-        /// <param name="arr" type="Array" optional="false" mayBeNull="true">Array to check in.</param>
-        /// <param name="callback" type="Function">Callback function to invoke once per item in the array.</param>
-        /// <returns>The first item that makes the callback return true; null otherwise or if the array is null.</returns>
-
-        if (arr) {
-            var i, len;
-            for (i = 0, len = arr.length; i < len; i++) {
-                if (callback(arr[i])) {
-                    return arr[i];
-                }
-            }
-        }
-        return null;
-    };
-
-    var isArray = function (value) {
-        /// <summary>Checks whether the specified value is an array object.</summary>
-        /// <param name="value">Value to check.</param>
-        /// <returns type="Boolean">true if the value is an array object; false otherwise.</returns>
-
-        return Object.prototype.toString.call(value) === "[object Array]";
-    };
-
-    var isDate = function (value) {
-        /// <summary>Checks whether the specified value is a Date object.</summary>
-        /// <param name="value">Value to check.</param>
-        /// <returns type="Boolean">true if the value is a Date object; false otherwise.</returns>
-
-        return Object.prototype.toString.call(value) === "[object Date]";
-    };
-
-    var isObject = function (value) {
-        /// <summary>Tests whether a value is an object.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <remarks>
-        ///     Per javascript rules, null and array values are objects and will cause this function to return true.
-        /// </remarks>
-        /// <returns type="Boolean">True is the value is an object; false otherwise.</returns>
-
-        return typeof value === "object";
-    };
-
-    var parseInt10 = function (value) {
-        /// <summary>Parses a value in base 10.</summary>
-        /// <param name="value" type="String">String value to parse.</param>
-        /// <returns type="Number">The parsed value, NaN if not a valid value.</returns>
-
-        return parseInt(value, 10);
-    };
-
-    var renameProperty = function (obj, oldName, newName) {
-        /// <summary>Renames a property in an object.</summary>
-        /// <param name="obj" type="Object">Object in which the property will be renamed.</param>
-        /// <param name="oldName" type="String">Name of the property that will be renamed.</param>
-        /// <param name="newName" type="String">New name of the property.</param>
-        /// <remarks>
-        ///    This function will not do anything if the object doesn't own a property with the specified old name.
-        /// </remarks>
-
-        if (obj.hasOwnProperty(oldName)) {
-            obj[newName] = obj[oldName];
-            delete obj[oldName];
-        }
-    };
-
-    var throwErrorCallback = function (error) {
-        /// <summary>Default error handler.</summary>
-        /// <param name="error" type="Object">Error to handle.</param>
-        throw error;
-    };
-
-    var trimString = function (str) {
-        /// <summary>Removes leading and trailing whitespaces from a string.</summary>
-        /// <param name="str" type="String" optional="false" mayBeNull="false">String to trim</param>
-        /// <returns type="String">The string with no leading or trailing whitespace.</returns>
-
-        if (str.trim) {
-            return str.trim();
-        }
-
-        return str.replace(/^\s+|\s+$/g, '');
-    };
-
-    var undefinedDefault = function (value, defaultValue) {
-        /// <summary>Returns a default value in place of undefined.</summary>
-        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
-        /// <param name="defaultValue">Value to return if value is undefined.</param>
-        /// <returns>value if it's defined; defaultValue otherwise.</returns>
-        /// <remarks>
-        /// This should only be used for cases where falsy values are valid;
-        /// otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
-        /// </remarks>
-        return (value !== undefined) ? value : defaultValue;
-    };
-
-    // Regular expression that splits a uri into its components:
-    // 0 - is the matched string.
-    // 1 - is the scheme.
-    // 2 - is the authority.
-    // 3 - is the path.
-    // 4 - is the query.
-    // 5 - is the fragment.
-    var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
-    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
-
-    var getURIInfo = function (uri) {
-        /// <summary>Gets information about the components of the specified URI.</summary>
-        /// <param name="uri" type="String">URI to get information from.</param>
-        /// <returns type="Object">
-        /// An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
-        /// </returns>
-
-        var result = { isAbsolute: false };
-
-        if (uri) {
-            var matches = uriRegEx.exec(uri);
-            if (matches) {
-                var i, len;
-                for (i = 0, len = uriPartNames.length; i < len; i++) {
-                    if (matches[i + 1]) {
-                        result[uriPartNames[i]] = matches[i + 1];
-                    }
-                }
-            }
-            if (result.scheme) {
-                result.isAbsolute = true;
-            }
-        }
-
-        return result;
-    };
-
-    var getURIFromInfo = function (uriInfo) {
-        /// <summary>Builds a URI string from its components.</summary>
-        /// <param name="uriInfo" type="Object"> An object with uri parts (scheme, authority, etc.).</param>
-        /// <returns type="String">URI string.</returns>
-
-        return "".concat(
-            uriInfo.scheme || "",
-            uriInfo.authority || "",
-            uriInfo.path || "",
-            uriInfo.query || "",
-            uriInfo.fragment || "");
-    };
-
-    // Regular expression that splits a uri authority into its subcomponents:
-    // 0 - is the matched string.
-    // 1 - is the userinfo subcomponent.
-    // 2 - is the host subcomponent.
-    // 3 - is the port component.
-    var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
-
-    // Regular expression that matches percentage enconded octects (i.e %20 or %3A);
-    var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
-
-    var normalizeURICase = function (uri) {
-        /// <summary>Normalizes the casing of a URI.</summary>
-        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
-        /// <returns type="String">The URI normalized to lower case.</returns>
-
-        var uriInfo = getURIInfo(uri);
-        var scheme = uriInfo.scheme;
-        var authority = uriInfo.authority;
-
-        if (scheme) {
-            uriInfo.scheme = scheme.toLowerCase();
-            if (authority) {
-                var matches = uriAuthorityRegEx.exec(authority);
-                if (matches) {
-                    uriInfo.authority = "//" +
-                    (matches[1] ? matches[1] + "@" : "") +
-                    (matches[2].toLowerCase()) +
-                    (matches[3] ? ":" + matches[3] : "");
-                }
-            }
-        }
-
-        uri = getURIFromInfo(uriInfo);
-
-        return uri.replace(pctEncodingRegEx, function (str) {
-            return str.toLowerCase();
-        });
-    };
-
-    var normalizeURI = function (uri, base) {
-        /// <summary>Normalizes a possibly relative URI with a base URI.</summary>
-        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
-        /// <param name="base" type="String" mayBeNull="true">Base URI to compose with.</param>
-        /// <returns type="String">The composed URI if relative; the original one if absolute.</returns>
-
-        if (!base) {
-            return uri;
-        }
-
-        var uriInfo = getURIInfo(uri);
-        if (uriInfo.isAbsolute) {
-            return uri;
-        }
-
-        var baseInfo = getURIInfo(base);
-        var normInfo = {};
-        var path;
-
-        if (uriInfo.authority) {
-            normInfo.authority = uriInfo.authority;
-            path = uriInfo.path;
-            normInfo.query = uriInfo.query;
-        } else {
-            if (!uriInfo.path) {
-                path = baseInfo.path;
-                normInfo.query = uriInfo.query || baseInfo.query;
-            } else {
-                if (uriInfo.path.charAt(0) === '/') {
-                    path = uriInfo.path;
-                } else {
-                    path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
-                }
-                normInfo.query = uriInfo.query;
-            }
-            normInfo.authority = baseInfo.authority;
-        }
-
-        normInfo.path = removeDotsFromPath(path);
-
-        normInfo.scheme = baseInfo.scheme;
-        normInfo.fragment = uriInfo.fragment;
-
-        return getURIFromInfo(normInfo);
-    };
-
-    var mergeUriPathWithBase = function (uriPath, basePath) {
-        /// <summary>Merges the path of a relative URI and a base URI.</summary>
-        /// <param name="uriPath" type="String>Relative URI path.</param>
-        /// <param name="basePath" type="String">Base URI path.</param>
-        /// <returns type="String">A string with the merged path.</returns>
-
-        var path = "/";
-        var end;
-
-        if (basePath) {
-            end = basePath.lastIndexOf("/");
-            path = basePath.substring(0, end);
-
-            if (path.charAt(path.length - 1) !== "/") {
-                path = path + "/";
-            }
-        }
-
-        return path + uriPath;
-    };
-
-    var removeDotsFromPath = function (path) {
-        /// <summary>Removes the special folders . and .. from a URI's path.</summary>
-        /// <param name="path" type="string">URI path component.</param>
-        /// <returns type="String">Path without any . and .. folders.</returns>
-
-        var result = "";
-        var segment = "";
-        var end;
-
-        while (path) {
-            if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
-                path = path.replace(/^\.\.?\/?/g, "");
-            } else if (path.indexOf("/..") === 0) {
-                path = path.replace(/^\/\..\/?/g, "/");
-                end = result.lastIndexOf("/");
-                if (end === -1) {
-                    result = "";
-                } else {
-                    result = result.substring(0, end);
-                }
-            } else if (path.indexOf("/.") === 0) {
-                path = path.replace(/^\/\.\/?/g, "/");
-            } else {
-                segment = path;
-                end = path.indexOf("/", 1);
-                if (end !== -1) {
-                    segment = path.substring(0, end);
-                }
-                result = result + segment;
-                path = path.replace(segment, "");
-            }
-        }
-        return result;
-    };
-
-    var convertByteArrayToHexString = function (str) {
-        var arr = [];
-        if (window.atob === undefined) {
-            arr = decodeBase64(str);
-        } else {
-            var binaryStr = window.atob(str);
-            for (var i = 0; i < binaryStr.length; i++) {
-                arr.push(binaryStr.charCodeAt(i));
-            }
-        }
-        var hexValue = "";
-        var hexValues = "0123456789ABCDEF";
-        for (var j = 0; j < arr.length; j++) {
-            var t = arr[j];
-            hexValue += hexValues[t >> 4];
-            hexValue += hexValues[t & 0x0F];
-        }
-        return hexValue;
-    };
-
-    var decodeBase64 = function (str) {
-        var binaryString = "";
-        for (var i = 0; i < str.length; i++) {
-            var base65IndexValue = getBase64IndexValue(str[i]);
-            var binaryValue = "";
-            if (base65IndexValue !== null) {
-                binaryValue = base65IndexValue.toString(2);
-                binaryString += addBase64Padding(binaryValue);
-            }
-        }
-        var byteArray = [];
-        var numberOfBytes = parseInt(binaryString.length / 8, 10);
-        for (i = 0; i < numberOfBytes; i++) {
-            var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
-            byteArray.push(intValue);
-        }
-        return byteArray;
-    };
-
-    var getBase64IndexValue = function (character) {
-        var asciiCode = character.charCodeAt(0);
-        var asciiOfA = 65;
-        var differenceBetweenZanda = 6;
-        if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
-            return asciiCode - asciiOfA;
-        } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
-            return asciiCode - asciiOfA - differenceBetweenZanda;
-        } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
-            return asciiCode + 4;
-        } else if (character == "+") {
-            return 62;
-        } else if (character == "/") {
-            return 63;
-        } else {
-            return null;
-        }
-    };
-
-    var addBase64Padding = function (binaryString) {
-        while (binaryString.length < 6) {
-            binaryString = "0" + binaryString;
-        }
-        return binaryString;
-    };
-
-
-    // URI prefixes to generate smaller code.
-    var http = "http://";
-    var w3org = http + "www.w3.org/";               // http://www.w3.org/
-
-    var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
-    var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
-    var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
-
-    var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
-
-    var hasLeadingOrTrailingWhitespace = function (text) {
-        /// <summary>Checks whether the specified string has leading or trailing spaces.</summary>
-        /// <param name="text" type="String">String to check.</param>
-        /// <returns type="Boolean">true if text has any leading or trailing whitespace; false otherwise.</returns>
-
-        var re = /(^\s)|(\s$)/;
-        return re.test(text);
-    };
-
-    var isWhitespace = function (text) {
-        /// <summary>Determines whether the specified text is empty or whitespace.</summary>
-        /// <param name="text" type="String">Value to inspect.</param>
-        /// <returns type="Boolean">true if the text value is empty or all whitespace; false otherwise.</returns>
-
-        var ws = /^\s*$/;
-        return text === null || ws.test(text);
-    };
-
-    var isWhitespacePreserveContext = function (domElement) {
-        /// <summary>Determines whether the specified element has xml:space='preserve' applied.</summary>
-        /// <param name="domElement">Element to inspect.</param>
-        /// <returns type="Boolean">Whether xml:space='preserve' is in effect.</returns>
-
-        while (domElement !== null && domElement.nodeType === 1) {
-            var val = xmlAttributeValue(domElement, "space", xmlNS);
-            if (val === "preserve") {
-                return true;
-            } else if (val === "default") {
-                break;
-            } else {
-                domElement = domElement.parentNode;
-            }
-        }
-
-        return false;
-    };
-
-    var isXmlNSDeclaration = function (domAttribute) {
-        /// <summary>Determines whether the attribute is a XML namespace declaration.</summary>
-        /// <param name="domAttribute">Element to inspect.</param>
-        /// <returns type="Boolean">
-        ///    True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
-        /// </returns>
-
-        var nodeName = domAttribute.nodeName;
-        return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
-    };
-
-    var safeSetProperty = function (obj, name, value) {
-        /// <summary>Safely set as property in an object by invoking obj.setProperty.</summary>
-        /// <param name="obj">Object that exposes a setProperty method.</param>
-        /// <param name="name" type="String" mayBeNull="false">Property name.</param>
-        /// <param name="value">Property value.</param>
-
-        try {
-            obj.setProperty(name, value);
-        } catch (_) { }
-    };
-
-    var msXmlDom3 = function () {
-        /// <summary>Creates an configures new MSXML 3.0 ActiveX object.</summary>
-        /// <remakrs>
-        ///    This function throws any exception that occurs during the creation
-        ///    of the MSXML 3.0 ActiveX object.
-        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
-
-        var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
-        if (msxml3) {
-            safeSetProperty(msxml3, "ProhibitDTD", true);
-            safeSetProperty(msxml3, "MaxElementDepth", 256);
-            safeSetProperty(msxml3, "AllowDocumentFunction", false);
-            safeSetProperty(msxml3, "AllowXsltScript", false);
-        }
-        return msxml3;
-    };
-
-    var msXmlDom = function () {
-        /// <summary>Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.</summary>
-        /// <remakrs>
-        ///    This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
-        ///    it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
-        ///    happens during the creation of the MSXML 6.0 will be handled by the function while
-        ///    the ones that happend during the creation of the MSXML 3.0 will be thrown.
-        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
-
-        try {
-            var msxml = activeXObject("Msxml2.DOMDocument.6.0");
-            if (msxml) {
-                msxml.async = true;
-            }
-            return msxml;
-        } catch (_) {
-            return msXmlDom3();
-        }
-    };
-
-    var msXmlParse = function (text) {
-        /// <summary>Parses an XML string using the MSXML DOM.</summary>
-        /// <remakrs>
-        ///    This function throws any exception that occurs during the creation
-        ///    of the MSXML ActiveX object.  It also will throw an exception
-        ///    in case of a parsing error.
-        /// <returns type="Object">New MSXML DOMDocument node representing the parsed XML string.</returns>
-
-        var dom = msXmlDom();
-        if (!dom) {
-            return null;
-        }
-
-        dom.loadXML(text);
-        var parseError = dom.parseError;
-        if (parseError.errorCode !== 0) {
-            xmlThrowParserError(parseError.reason, parseError.srcText, text);
-        }
-        return dom;
-    };
-
-    var xmlThrowParserError = function (exceptionOrReason, srcText, errorXmlText) {
-        /// <summary>Throws a new exception containing XML parsing error information.</summary>
-        /// <param name="exceptionOrReason">
-        ///    String indicatin the reason of the parsing failure or
-        ///    Object detailing the parsing error.
-        /// </param>
-        /// <param name="srcText" type="String">
-        ///    String indicating the part of the XML string that caused the parsing error.
-        /// </param>
-        /// <param name="errorXmlText" type="String">XML string for wich the parsing failed.</param>
-
-        if (typeof exceptionOrReason === "string") {
-            exceptionOrReason = { message: exceptionOrReason };
-        }
-        throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
-    };
-
-    var xmlParse = function (text) {
-        /// <summary>Returns an XML DOM document from the specified text.</summary>
-        /// <param name="text" type="String">Document text.</param>
-        /// <returns>XML DOM document.</returns>
-        /// <remarks>This function will throw an exception in case of a parse error.</remarks>
-
-        var domParser = window.DOMParser && new window.DOMParser();
-        var dom;
-
-        if (!domParser) {
-            dom = msXmlParse(text);
-            if (!dom) {
-                xmlThrowParserError("XML DOM parser not supported");
-            }
-            return dom;
-        }
-
-        try {
-            dom = domParser.parseFromString(text, "text/xml");
-        } catch (e) {
-            xmlThrowParserError(e, "", text);
-        }
-
-        var element = dom.documentElement;
-        var nsURI = element.namespaceURI;
-        var localName = xmlLocalName(element);
-
-        // Firefox reports errors by returing the DOM for an xml document describing the problem.
-        if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
-            var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
-            var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
-            xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
-        }
-
-        // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
-        // The error may be localized, so instead we simply check for a header as the
-        // top element or descendant child of the document.
-        if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
-            var reason = "";
-            var siblings = [];
-            var cursor = element.firstChild;
-            while (cursor) {
-                if (cursor.nodeType === 1) {
-                    reason += xmlInnerText(cursor) || "";
-                }
-                siblings.push(cursor.nextSibling);
-                cursor = cursor.firstChild || siblings.shift();
-            }
-            reason += xmlInnerText(element) || "";
-            xmlThrowParserError(reason, "", text);
-        }
-
-        return dom;
-    };
-
-    var xmlQualifiedName = function (prefix, name) {
-        /// <summary>Builds a XML qualified name string in the form of "prefix:name".</summary>
-        /// <param name="prefix" type="String" maybeNull="true">Prefix string.</param>
-        /// <param name="name" type="String">Name string to qualify with the prefix.</param>
-        /// <returns type="String">Qualified name.</returns>
-
-        return prefix ? prefix + ":" + name : name;
-    };
-
-    var xmlAppendText = function (domNode, textNode) {
-        /// <summary>Appends a text node into the specified DOM element node.</summary>
-        /// <param name="domNode">DOM node for the element.</param>
-        /// <param name="text" type="String" mayBeNull="false">Text to append as a child of element.</param>
-        if (hasLeadingOrTrailingWhitespace(textNode.data)) {
-            var attr = xmlAttributeNode(domNode, xmlNS, "space");
-            if (!attr) {
-                attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
-                xmlAppendChild(domNode, attr);
-            }
-            attr.value = "preserve";
-        }
-        domNode.appendChild(textNode);
-        return domNode;
-    };
-
-    var xmlAttributes = function (element, onAttributeCallback) {
-        /// <summary>Iterates through the XML element's attributes and invokes the callback function for each one.</summary>
-        /// <param name="element">Wrapped element to iterate over.</param>
-        /// <param name="onAttributeCallback" type="Function">Callback function to invoke with wrapped attribute nodes.</param>
-
-        var attributes = element.attributes;
-        var i, len;
-        for (i = 0, len = attributes.length; i < len; i++) {
-            onAttributeCallback(attributes.item(i));
-        }
-    };
-
-    var xmlAttributeValue = function (domNode, localName, nsURI) {
-        /// <summary>Returns the value of a DOM element's attribute.</summary>
-        /// <param name="domNode">DOM node for the owning element.</param>
-        /// <param name="localName" type="String">Local name of the attribute.</param>
-        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
-        /// <returns type="String" maybeNull="true">The attribute value, null if not found.</returns>
-
-        var attribute = xmlAttributeNode(domNode, localName, nsURI);
-        return attribute ? xmlNodeValue(attribute) : null;
-    };
-
-    var xmlAttributeNode = function (domNode, localName, nsURI) {
-        /// <summary>Gets an attribute node from a DOM element.</summary>
-        /// <param name="domNode">DOM node for the owning element.</param>
-        /// <param name="localName" type="String">Local name of the attribute.</param>
-        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
-        /// <returns>The attribute node, null if not found.</returns>
-
-        var attributes = domNode.attributes;
-        if (attributes.getNamedItemNS) {
-            return attributes.getNamedItemNS(nsURI || null, localName);
-        }
-
-        return attributes.getQualifiedItem(localName, nsURI) || null;
-    };
-
-    var xmlBaseURI = function (domNode, baseURI) {
-        /// <summary>Gets the value of the xml:base attribute on the specified element.</summary>
-        /// <param name="domNode">Element to get xml:base attribute value from.</param>
-        /// <param name="baseURI" mayBeNull="true" optional="true">Base URI used to normalize the value of the xml:base attribute.</param>
-        /// <returns type="String">Value of the xml:base attribute if found; the baseURI or null otherwise.</returns>
-
-        var base = xmlAttributeNode(domNode, "base", xmlNS);
-        return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
-    };
-
-
-    var xmlChildElements = function (domNode, onElementCallback) {
-        /// <summary>Iterates through the XML element's child DOM elements and invokes the callback function for each one.</summary>
-        /// <param name="element">DOM Node containing the DOM elements to iterate over.</param>
-        /// <param name="onElementCallback" type="Function">Callback function to invoke for each child DOM element.</param>
-
-        xmlTraverse(domNode, /*recursive*/false, function (child) {
-            if (child.nodeType === 1) {
-                onElementCallback(child);
-            }
-            // continue traversing.
-            return true;
-        });
-    };
-
-    var xmlFindElementByPath = function (root, namespaceURI, path) {
-        /// <summary>Gets the descendant element under root that corresponds to the specified path and namespace URI.</summary>
-        /// <param name="root">DOM element node from which to get the descendant element.</param>
-        /// <param name="namespaceURI" type="String">The namespace URI of the element to match.</param>
-        /// <param name="path" type="String">Path to the desired descendant element.</param>
-        /// <returns>The element specified by path and namespace URI.</returns>
-        /// <remarks>
-        ///     All the elements in the path are matched against namespaceURI.
-        ///     The function will stop searching on the first element that doesn't match the namespace and the path.
-        /// </remarks>
-
-        var parts = path.split("/");
-        var i, len;
-        for (i = 0, len = parts.length; i < len; i++) {
-            root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
-        }
-        return root || null;
-    };
-
-    var xmlFindNodeByPath = function (root, namespaceURI, path) {
-        /// <summary>Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.</summary>
-        /// <param name="root">DOM element node from which to get the descendant node.</param>
-        /// <param name="namespaceURI" type="String">The namespace URI of the node to match.</param>
-        /// <param name="path" type="String">Path to the desired descendant node.</param>
-        /// <returns>The node specified by path and namespace URI.</returns>
-        /// <remarks>
-        ///     This function will traverse the path and match each node associated to a path segement against the namespace URI.
-        ///     The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
-        ///
-        ///     The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
-        /// </remarks>
-
-        var lastSegmentStart = path.lastIndexOf("/");
-        var nodePath = path.substring(lastSegmentStart + 1);
-        var parentPath = path.substring(0, lastSegmentStart);
-
-        var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
-        if (node) {
-            if (nodePath.charAt(0) === "@") {
-                return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
-            }
-            return xmlFirstChildElement(node, namespaceURI, nodePath);
-        }
-        return null;
-    };
-
-    var xmlFirstChildElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the child DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
-    };
-
-    var xmlFirstDescendantElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        if (domNode.getElementsByTagNameNS) {
-            var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
-            return result.length > 0 ? result[0] : null;
-        }
-        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
-    };
-
-    var xmlFirstElementMaybeRecursive = function (domNode, namespaceURI, localName, recursive) {
-        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <param name="recursive" type="Boolean">
-        ///     True if the search should include all the descendants of the DOM node.
-        ///     False if the search should be scoped only to the direct children of the DOM node.
-        /// </param>
-        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        var firstElement = null;
-        xmlTraverse(domNode, recursive, function (child) {
-            if (child.nodeType === 1) {
-                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
-                var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
-
-                if (isExpectedNamespace && isExpectedNodeName) {
-                    firstElement = child;
-                }
-            }
-            return firstElement === null;
-        });
-        return firstElement;
-    };
-
-    var xmlInnerText = function (xmlElement) {
-        /// <summary>Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.</summary>
-        /// <param name="domElement">Element to get values for.</param>
-        /// <returns type="String">Text for all direct children.</returns>
-
-        var result = null;
-        var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
-        var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
-        var whitespacePreserveContext;
-
-        xmlTraverse(root, false, function (child) {
-            if (child.nodeType === 3 || child.nodeType === 4) {
-                // isElementContentWhitespace indicates that this is 'ignorable whitespace',
-                // but it's not defined by all browsers, and does not honor xml:space='preserve'
-                // in some implementations.
-                //
-                // If we can't tell either way, we walk up the tree to figure out whether
-                // xml:space is set to preserve; otherwise we discard pure-whitespace.
-                //
-                // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
-                var text = xmlNodeValue(child);
-                var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
-                if (!shouldInclude) {
-                    // Walk up the tree to figure out whether we are in xml:space='preserve' context
-                    // for the cursor (needs to happen only once).
-                    if (whitespacePreserveContext === undefined) {
-                        whitespacePreserveContext = isWhitespacePreserveContext(root);
-                    }
-
-                    shouldInclude = whitespacePreserveContext;
-                }
-
-                if (shouldInclude) {
-                    if (!result) {
-                        result = text;
-                    } else {
-                        result += text;
-                    }
-                }
-            }
-            // Continue traversing?
-            return true;
-        });
-        return result;
-    };
-
-    var xmlLocalName = function (domNode) {
-        /// <summary>Returns the localName of a XML node.</summary>
-        /// <param name="domNode">DOM node to get the value from.</param>
-        /// <returns type="String">localName of domNode.</returns>
-
-        return domNode.localName || domNode.baseName;
-    };
-
-    var xmlNamespaceURI = function (domNode) {
-        /// <summary>Returns the namespace URI of a XML node.</summary>
-        /// <param name="node">DOM node to get the value from.</param>
-        /// <returns type="String">Namespace URI of domNode.</returns>
-
-        return domNode.namespaceURI || null;
-    };
-
-    var xmlNodeValue = function (domNode) {
-        /// <summary>Returns the value or the inner text of a XML node.</summary>
-        /// <param name="node">DOM node to get the value from.</param>
-        /// <returns>Value of the domNode or the inner text if domNode represents a DOM element node.</returns>
-        
-        if (domNode.nodeType === 1) {
-            return xmlInnerText(domNode);
-        }
-        return domNode.nodeValue;
-    };
-
-    var xmlTraverse = function (domNode, recursive, onChildCallback) {
-        /// <summary>Walks through the descendants of the domNode and invokes a callback for each node.</summary>
-        /// <param name="domNode">DOM node whose descendants are going to be traversed.</param>
-        /// <param name="recursive" type="Boolean">
-        ///    True if the traversal should include all the descenants of the DOM node.
-        ///    False if the traversal should be scoped only to the direct children of the DOM node.
-        /// </param>
-        /// <returns type="String">Namespace URI of node.</returns>
-
-        var subtrees = [];
-        var child = domNode.firstChild;
-        var proceed = true;
-        while (child && proceed) {
-            proceed = onChildCallback(child);
-            if (proceed) {
-                if (recursive && child.firstChild) {
-                    subtrees.push(child.firstChild);
-                }
-                child = child.nextSibling || subtrees.shift();
-            }
-        }
-    };
-
-    var xmlSiblingElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the next sibling DOM element of the specified DOM node.</summary>
-        /// <param name="domNode">DOM node from which the next sibling is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's next sibling DOM element, null if there is none.</returns>
-
-        var sibling = domNode.nextSibling;
-        while (sibling) {
-            if (sibling.nodeType === 1) {
-                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
-                var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
-
-                if (isExpectedNamespace && isExpectedNodeName) {
-                    return sibling;
-                }
-            }
-            sibling = sibling.nextSibling;
-        }
-        return null;
-    };
-
-    var xmlDom = function () {
-        /// <summary>Creates a new empty DOM document node.</summary>
-        /// <returns>New DOM document node.</returns>
-        /// <remarks>
-        ///    This function will first try to create a native DOM document using
-        ///    the browsers createDocument function.  If the browser doesn't
-        ///    support this but supports ActiveXObject, then an attempt to create
-        ///    an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
-        ///    for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
-        ///    the browser doesn't support ActiveXObject then an exception will be thrown.
-        /// </remarks>
-
-        var implementation = window.document.implementation;
-        return (implementation && implementation.createDocument) ?
-           implementation.createDocument(null, null, null) :
-           msXmlDom();
-    };
-
-    var xmlAppendChildren = function (parent, children) {
-        /// <summary>Appends a collection of child nodes or string values to a parent DOM node.</summary>
-        /// <param name="parent">DOM node to which the children will be appended.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be appended to the parent.</param>
-        /// <returns>The parent with the appended children or string values.</returns>
-        /// <remarks>
-        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
-        ///    for it and then appended to the parent.
-        /// </remarks>
-
-        if (!isArray(children)) {
-            return xmlAppendChild(parent, children);
-        }
-
-        var i, len;
-        for (i = 0, len = children.length; i < len; i++) {
-            children[i] && xmlAppendChild(parent, children[i]);
-        }
-        return parent;
-    };
-
-    var xmlAppendChild = function (parent, child) {
-        /// <summary>Appends a child node or a string value to a parent DOM node.</summary>
-        /// <param name="parent">DOM node to which the child will be appended.</param>
-        /// <param name="child">Child DOM node or string value to append to the parent.</param>
-        /// <returns>The parent with the appended child or string value.</returns>
-        /// <remarks>
-        ///    If child is a string value, then a new DOM text node is going to be created
-        ///    for it and then appended to the parent.
-        /// </remarks>
-
-        if (child) {
-            if (typeof child === "string") {
-                return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
-            }
-            if (child.nodeType === 2) {
-                parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
-            } else {
-                parent.appendChild(child);
-            }
-        }
-        return parent;
-    };
-
-    var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) {
-        /// <summary>Creates a new DOM attribute node.</summary>
-        /// <param name="dom">DOM document used to create the attribute.</param>
-        /// <param name="prefix" type="String">Namespace prefix.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI.</param>
-        /// <returns>DOM attribute node for the namespace declaration.</returns>
-
-        var attribute =
-            dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
-            dom.createNode(2, qualifiedName, namespaceURI || undefined);
-
-        attribute.value = value || "";
-        return attribute;
-    };
-
-    var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) {
-        /// <summary>Creates a new DOM element node.</summary>
-        /// <param name="dom">DOM document used to create the DOM element.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element.</param>
-        /// <param name="qualifiedName" type="String">Qualified name in the form of "prefix:name" of the new DOM element.</param>
-        /// <param name="children" type="Array" optional="true">
-        ///     Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
-        /// </param>
-        /// <returns>New DOM element.</returns>
-        /// <remarks>
-        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
-        ///    for it and then appended to the new DOM element.
-        /// </remarks>
-
-        var element =
-            dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
-            dom.createNode(1, qualifiedName, nampespaceURI || undefined);
-
-        return xmlAppendChildren(element, children || []);
-    };
-
-    var xmlNewNSDeclaration = function (dom, namespaceURI, prefix) {
-        /// <summary>Creates a namespace declaration attribute.</summary>
-        /// <param name="dom">DOM document used to create the attribute.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI.</param>
-        /// <param name="prefix" type="String">Namespace prefix.</param>
-        /// <returns>DOM attribute node for the namespace declaration.</returns>
-
-        return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
-    };
-
-    var xmlNewFragment = function (dom, text) {
-        /// <summary>Creates a new DOM document fragment node for the specified xml text.</summary>
-        /// <param name="dom">DOM document from which the fragment node is going to be created.</param>
-        /// <param name="text" type="String" mayBeNull="false">XML text to be represented by the XmlFragment.</param>
-        /// <returns>New DOM document fragment object.</returns>
-
-        var value = "<c>" + text + "</c>";
-        var tempDom = xmlParse(value);
-        var tempRoot = tempDom.documentElement;
-        var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
-        var fragment = dom.createDocumentFragment();
-
-        var importedChild = imported.firstChild;
-        while (importedChild) {
-            fragment.appendChild(importedChild);
-            importedChild = importedChild.nextSibling;
-        }
-        return fragment;
-    };
-
-    var xmlNewText = function (dom, text) {
-        /// <summary>Creates new DOM text node.</summary>
-        /// <param name="dom">DOM document used to create the text node.</param>
-        /// <param name="text" type="String">Text value for the DOM text node.</param>
-        /// <returns>DOM text node.</returns>
-
-        return dom.createTextNode(text);
-    };
-
-    var xmlNewNodeByPath = function (dom, root, namespaceURI, prefix, path) {
-        /// <summary>Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.</summary>
-        /// <param name="dom">DOM document used to create the new node.</param>
-        /// <param name="root">DOM element node used as root of the subtree on which the new nodes are going to be created.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element or attribute.</param>
-        /// <param name="namespacePrefix" type="String">Prefix used to qualify the name of the new DOM element or attribute.</param>
-        /// <param name="Path" type="String">Path string describing the location of the new DOM element or attribute from the root element.</param>
-        /// <returns>DOM element or attribute node for the last segment of the path.</returns>
-        /// <remarks>
-        ///     This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
-        ///     for each segment that doesn't have a matching element under root.
-        ///
-        ///     The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
-        ///     will be created.
-        /// </remarks>
-
-        var name = "";
-        var parts = path.split("/");
-        var xmlFindNode = xmlFirstChildElement;
-        var xmlNewNode = xmlNewElement;
-        var xmlNode = root;
-
-        var i, len;
-        for (i = 0, len = parts.length; i < len; i++) {
-            name = parts[i];
-            if (name.charAt(0) === "@") {
-                name = name.substring(1);
-                xmlFindNode = xmlAttributeNode;
-                xmlNewNode = xmlNewAttribute;
-            }
-
-            var childNode = xmlFindNode(xmlNode, namespaceURI, name);
-            if (!childNode) {
-                childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
-                xmlAppendChild(xmlNode, childNode);
-            }
-            xmlNode = childNode;
-        }
-        return xmlNode;
-    };
-
-    var xmlSerialize = function (domNode) {
-        /// <summary>
-        /// Returns the text representation of the document to which the specified node belongs.
-        /// </summary>
-        /// <param name="root">Wrapped element in the document to serialize.</param>
-        /// <returns type="String">Serialized document.</returns>
-
-        var xmlSerializer = window.XMLSerializer;
-        if (xmlSerializer) {
-            var serializer = new xmlSerializer();
-            return serializer.serializeToString(domNode);
-        }
-
-        if (domNode.xml) {
-            return domNode.xml;
-        }
-
-        throw { message: "XML serialization unsupported" };
-    };
-
-    var xmlSerializeDescendants = function (domNode) {
-        /// <summary>Returns the XML representation of the all the descendants of the node.</summary>
-        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
-        /// <returns type="String">The XML representation of all the descendants of the node.</returns>
-
-        var children = domNode.childNodes;
-        var i, len = children.length;
-        if (len === 0) {
-            return "";
-        }
-
-        // Some implementations of the XMLSerializer don't deal very well with fragments that
-        // don't have a DOMElement as their first child. The work around is to wrap all the
-        // nodes in a dummy root node named "c", serialize it and then just extract the text between
-        // the <c> and the </c> substrings.
-
-        var dom = domNode.ownerDocument;
-        var fragment = dom.createDocumentFragment();
-        var fragmentRoot = dom.createElement("c");
-
-        fragment.appendChild(fragmentRoot);
-        // Move the children to the fragment tree.
-        for (i = 0; i < len; i++) {
-            fragmentRoot.appendChild(children[i]);
-        }
-
-        var xml = xmlSerialize(fragment);
-        xml = xml.substr(3, xml.length - 7);
-
-        // Move the children back to the original dom tree.
-        for (i = 0; i < len; i++) {
-            domNode.appendChild(fragmentRoot.childNodes[i]);
-        }
-
-        return xml;
-    };
-
-    var xmlSerializeNode = function (domNode) {
-        /// <summary>Returns the XML representation of the node and all its descendants.</summary>
-        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
-        /// <returns type="String">The XML representation of the node and all its descendants.</returns>
-
-        var xml = domNode.xml;
-        if (xml !== undefined) {
-            return xml;
-        }
-
-        if (window.XMLSerializer) {
-            var serializer = new window.XMLSerializer();
-            return serializer.serializeToString(domNode);
-        }
-
-        throw { message: "XML serialization unsupported" };
-    };
-
-
-
-
-    var forwardCall = function (thisValue, name, returnValue) {
-        /// <summary>Creates a new function to forward a call.</summary>
-        /// <param name="thisValue" type="Object">Value to use as the 'this' object.</param>
-        /// <param name="name" type="String">Name of function to forward to.</param>
-        /// <param name="returnValue" type="Object">Return value for the forward call (helps keep identity when chaining calls).</param>
-        /// <returns type="Function">A new function that will forward a call.</returns>
-
-        return function () {
-            thisValue[name].apply(thisValue, arguments);
-            return returnValue;
-        };
-    };
-
-    var DjsDeferred = function () {
-        /// <summary>Initializes a new DjsDeferred object.</summary>
-        /// <remarks>
-        /// Compability Note A - Ordering of callbacks through chained 'then' invocations
-        ///
-        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
-        /// implies that .then() returns a distinct object.
-        ////
-        /// For compatibility with http://api.jquery.com/category/deferred-object/
-        /// we return this same object. This affects ordering, as
-        /// the jQuery version will fire callbacks in registration
-        /// order regardless of whether they occur on the result
-        /// or the original object.
-        ///
-        /// Compability Note B - Fulfillment value
-        ///
-        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
-        /// implies that the result of a success callback is the
-        /// fulfillment value of the object and is received by
-        /// other success callbacks that are chained.
-        ///
-        /// For compatibility with http://api.jquery.com/category/deferred-object/
-        /// we disregard this value instead.
-        /// </remarks>
-
-        this._arguments = undefined;
-        this._done = undefined;
-        this._fail = undefined;
-        this._resolved = false;
-        this._rejected = false;
-    };
-
-    DjsDeferred.prototype = {
-        then: function (fulfilledHandler, errorHandler /*, progressHandler */) {
-            /// <summary>Adds success and error callbacks for this deferred object.</summary>
-            /// <param name="fulfilledHandler" type="Function" mayBeNull="true" optional="true">Success callback.</param>
-            /// <param name="errorHandler" type="Function" mayBeNull="true" optional="true">Error callback.</param>
-            /// <remarks>See Compatibility Note A.</remarks>
-
-            if (fulfilledHandler) {
-                if (!this._done) {
-                    this._done = [fulfilledHandler];
-                } else {
-                    this._done.push(fulfilledHandler);
-                }
-            }
-
-            if (errorHandler) {
-                if (!this._fail) {
-                    this._fail = [errorHandler];
-                } else {
-                    this._fail.push(errorHandler);
-                }
-            }
-
-            //// See Compatibility Note A in the DjsDeferred constructor.
-            //// if (!this._next) {
-            ////    this._next = createDeferred();
-            //// }
-            //// return this._next.promise();
-
-            if (this._resolved) {
-                this.resolve.apply(this, this._arguments);
-            } else if (this._rejected) {
-                this.reject.apply(this, this._arguments);
-            }
-
-            return this;
-        },
-
-        resolve: function (/* args */) {
-            /// <summary>Invokes success callbacks for this deferred object.</summary>
-            /// <remarks>All arguments are forwarded to success callbacks.</remarks>
-
-
-            if (this._done) {
-                var i, len;
-                for (i = 0, len = this._done.length; i < len; i++) {
-                    //// See Compability Note B - Fulfillment value.
-                    //// var nextValue =
-                    this._done[i].apply(null, arguments);
-                }
-
-                //// See Compatibility Note A in the DjsDeferred constructor.
-                //// this._next.resolve(nextValue);
-                //// delete this._next;
-
-                this._done = undefined;
-                this._resolved = false;
-                this._arguments = undefined;
-            } else {
-                this._resolved = true;
-                this._arguments = arguments;
-            }
-        },
-
-        reject: function (/* args */) {
-            /// <summary>Invokes error callbacks for this deferred object.</summary>
-            /// <remarks>All arguments are forwarded to error callbacks.</remarks>
-            if (this._fail) {
-                var i, len;
-                for (i = 0, len = this._fail.length; i < len; i++) {
-                    this._fail[i].apply(null, arguments);
-                }
-
-                this._fail = undefined;
-                this._rejected = false;
-                this._arguments = undefined;
-            } else {
-                this._rejected = true;
-                this._arguments = arguments;
-            }
-        },
-
-        promise: function () {
-            /// <summary>Returns a version of this object that has only the read-only methods available.</summary>
-            /// <returns>An object with only the promise object.</returns>
-
-            var result = {};
-            result.then = forwardCall(this, "then", result);
-            return result;
-        }
-    };
-
-    var createDeferred = function () {
-        /// <summary>Creates a deferred object.</summary>
-        /// <returns type="DjsDeferred">
-        /// A new deferred object. If jQuery is installed, then a jQuery
-        /// Deferred object is returned, which provides a superset of features.
-        /// </returns>
-
-        if (window.jQuery && window.jQuery.Deferred) {
-            return new window.jQuery.Deferred();
-        } else {
-            return new DjsDeferred();
-        }
-    };
-
-
-
-
-    var dataItemTypeName = function (value, metadata) {
-        /// <summary>Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property.</summary>
-        /// <param name="value">Value of the data item from which the type name is going to be retrieved.</param>
-        /// <param name="metadata" type="object" optional="true">Object containing metadata about the data tiem.</param>
-        /// <remarks>
-        ///    This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
-        ///    it will try to recover it from the metadata.  If both attempts fail, it will return null.
-        /// </remarks>
-        /// <returns type="String">Data item type name; null if the type name cannot be found within the value or the metadata</returns>
-
-        var valueTypeName = ((value && value.__metadata) || {}).type;
-        return valueTypeName || (metadata ? metadata.type : null);
-    };
-
-    var EDM = "Edm.";
-    var EDM_BINARY = EDM + "Binary";
-    var EDM_BOOLEAN = EDM + "Boolean";
-    var EDM_BYTE = EDM + "Byte";
-    var EDM_DATETIME = EDM + "DateTime";
-    var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
-    var EDM_DECIMAL = EDM + "Decimal";
-    var EDM_DOUBLE = EDM + "Double";
-    var EDM_GUID = EDM + "Guid";
-    var EDM_INT16 = EDM + "Int16";
-    var EDM_INT32 = EDM + "Int32";
-    var EDM_INT64 = EDM + "Int64";
-    var EDM_SBYTE = EDM + "SByte";
-    var EDM_SINGLE = EDM + "Single";
-    var EDM_STRING = EDM + "String";
-    var EDM_TIME = EDM + "Time";
-
-    var EDM_GEOGRAPHY = EDM + "Geography";
-    var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
-    var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
-    var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
-    var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
-    var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
-    var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
-    var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
-
-    var EDM_GEOMETRY = EDM + "Geometry";
-    var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
-    var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
-    var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
-    var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
-    var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
-    var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
-    var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
-
-    var GEOJSON_POINT = "Point";
-    var GEOJSON_LINESTRING = "LineString";
-    var GEOJSON_POLYGON = "Polygon";
-    var GEOJSON_MULTIPOINT = "MultiPoint";
-    var GEOJSON_MULTILINESTRING = "MultiLineString";
-    var GEOJSON_MULTIPOLYGON = "MultiPolygon";
-    var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
-
-    var primitiveEdmTypes = [
-        EDM_STRING,
-        EDM_INT32,
-        EDM_INT64,
-        EDM_BOOLEAN,
-        EDM_DOUBLE,
-        EDM_SINGLE,
-        EDM_DATETIME,
-        EDM_DATETIMEOFFSET,
-        EDM_TIME,
-        EDM_DECIMAL,
-        EDM_GUID,
-        EDM_BYTE,
-        EDM_INT16,
-        EDM_SBYTE,
-        EDM_BINARY
-    ];
-
-    var geometryEdmTypes = [
-        EDM_GEOMETRY,
-        EDM_GEOMETRY_POINT,
-        EDM_GEOMETRY_LINESTRING,
-        EDM_GEOMETRY_POLYGON,
-        EDM_GEOMETRY_COLLECTION,
-        EDM_GEOMETRY_MULTIPOLYGON,
-        EDM_GEOMETRY_MULTILINESTRING,
-        EDM_GEOMETRY_MULTIPOINT
-    ];
-
-    var geographyEdmTypes = [
-        EDM_GEOGRAPHY,
-        EDM_GEOGRAPHY_POINT,
-        EDM_GEOGRAPHY_LINESTRING,
-        EDM_GEOGRAPHY_POLYGON,
-        EDM_GEOGRAPHY_COLLECTION,
-        EDM_GEOGRAPHY_MULTIPOLYGON,
-        EDM_GEOGRAPHY_MULTILINESTRING,
-        EDM_GEOGRAPHY_MULTIPOINT
-    ];
-
-    var forEachSchema = function (metadata, callback) {
-        /// <summary>Invokes a function once per schema in metadata.</summary>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <param name="callback" type="Function">Callback function to invoke once per schema.</param>
-        /// <returns>
-        /// The first truthy value to be returned from the callback; null or the last falsy value otherwise.
-        /// </returns>
-
-        if (!metadata) {
-            return null;
-        }
-
-        if (isArray(metadata)) {
-            var i, len, result;
-            for (i = 0, len = metadata.length; i < len; i++) {
-                result = forEachSchema(metadata[i], callback);
-                if (result) {
-                    return result;
-                }
-            }
-
-            return null;
-        } else {
-            if (metadata.dataServices) {
-                return forEachSchema(metadata.dataServices.schema, callback);
-            }
-
-            return callback(metadata);
-        }
-    };
-
-    var formatMilliseconds = function (ms, ns) {
-        /// <summary>Formats a millisecond and a nanosecond value into a single string.</summary>
-        /// <param name="ms" type="Number" mayBeNull="false">Number of milliseconds to format.</param>
-        /// <param name="ns" type="Number" mayBeNull="false">Number of nanoseconds to format.</param>
-        /// <returns type="String">Formatted text.</returns>
-        /// <remarks>If the value is already as string it's returned as-is.</remarks>
-
-        // Avoid generating milliseconds if not necessary.
-        if (ms === 0) {
-            ms = "";
-        } else {
-            ms = "." + formatNumberWidth(ms.toString(), 3);
-        }
-        if (ns > 0) {
-            if (ms === "") {
-                ms = ".000";
-            }
-            ms += formatNumberWidth(ns.toString(), 4);
-        }
-        return ms;
-    };
-
-    var formatDateTimeOffset = function (value) {
-        /// <summary>Formats a DateTime or DateTimeOffset value a string.</summary>
-        /// <param name="value" type="Date" mayBeNull="false">Value to format.</param>
-        /// <returns type="String">Formatted text.</returns>
-        /// <remarks>If the value is already as string it's returned as-is.</remarks>
-
-        if (typeof value === "string") {
-            return value;
-        }
-
-        var hasOffset = isDateTimeOffset(value);
-        var offset = getCanonicalTimezone(value.__offset);
-        if (hasOffset && offset !== "Z") {
-            // We're about to change the value, so make a copy.
-            value = new Date(value.valueOf());
-
-            var timezone = parseTimezone(offset);
-            var hours = value.getUTCHours() + (timezone.d * timezone.h);
-            var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
-
-            value.setUTCHours(hours, minutes);
-        } else if (!hasOffset) {
-            // Don't suffix a 'Z' for Edm.DateTime values.
-            offset = "";
-        }
-
-        var year = value.getUTCFullYear();
-        var month = value.getUTCMonth() + 1;
-        var sign = "";
-        if (year <= 0) {
-            year = -(year - 1);
-            sign = "-";
-        }
-
-        var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
-
-        return sign +
-            formatNumberWidth(year, 4) + "-" +
-            formatNumberWidth(month, 2) + "-" +
-            formatNumberWidth(value.getUTCDate(), 2) + "T" +
-            formatNumberWidth(value.getUTCHours(), 2) + ":" +
-            formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
-            formatNumberWidth(value.getUTCSeconds(), 2) +
-            ms + offset;
-    };
-
-    var formatDuration = function (value) {
-        /// <summary>Converts a duration to a string in xsd:duration format.</summary>
-        /// <param name="value" type="Object">Object with ms and __edmType properties.</param>
-        /// <returns type="String">String representation of the time object in xsd:duration format.</returns>
-
-        var ms = value.ms;
-
-        var sign = "";
-        if (ms < 0) {
-            sign = "-";
-            ms = -ms;
-        }
-
-        var days = Math.floor(ms / 86400000);
-        ms -= 86400000 * days;
-        var hours = Math.floor(ms / 3600000);
-        ms -= 3600000 * hours;
-        var minutes = Math.floor(ms / 60000);
-        ms -= 60000 * minutes;
-        var seconds = Math.floor(ms / 1000);
-        ms -= seconds * 1000;
-
-        return sign + "P" +
-               formatNumberWidth(days, 2) + "DT" +
-               formatNumberWidth(hours, 2) + "H" +
-               formatNumberWidth(minutes, 2) + "M" +
-               formatNumberWidth(seconds, 2) +
-               formatMilliseconds(ms, value.ns) + "S";
-    };
-
-    var formatNumberWidth = function (value, width, append) {
-        /// <summary>Formats the specified value to the given width.</summary>
-        /// <param name="value" type="Number">Number to format (non-negative).</param>
-        /// <param name="width" type="Number">Minimum width for number.</param>
-        /// <param name="append" type="Boolean">Flag indicating if the value is padded at the beginning (false) or at the end (true).</param>
-        /// <returns type="String">Text representation.</returns>
-        var result = value.toString(10);
-        while (result.length < width) {
-            if (append) {
-                result += "0";
-            } else {
-                result = "0" + result;
-            }
-        }
-
-        return result;
-    };
-
-    var getCanonicalTimezone = function (timezone) {
-        /// <summary>Gets the canonical timezone representation.</summary>
-        /// <param name="timezone" type="String">Timezone representation.</param>
-        /// <returns type="String">An 'Z' string if the timezone is absent or 0; the timezone otherwise.</returns>
-
-        return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
-    };
-
-    var getCollectionType = function (typeName) {
-        /// <summary>Gets the type of a collection type name.</summary>
-        /// <param name="typeName" type="String">Type name of the collection.</param>
-        /// <returns type="String">Type of the collection; null if the type name is not a collection type.</returns>
-
-        if (typeof typeName === "string") {
-            var end = typeName.indexOf(")", 10);
-            if (typeName.indexOf("Collection(") === 0 && end > 0) {
-                return typeName.substring(11, end);
-            }
-        }
-        return null;
-    };
-
-    var invokeRequest = function (request, success, error, handler, httpClient, context) {
-        /// <summary>Sends a request containing OData payload to a server.</summary>
-        /// <param name="request">Object that represents the request to be sent..</param>
-        /// <param name="success">Callback for a successful read operation.</param>
-        /// <param name="error">Callback for handling errors.</param>
-        /// <param name="handler">Handler for data serialization.</param>
-        /// <param name="httpClient">HTTP client layer.</param>
-        /// <param name="context">Context used for processing the request</param>
-
-        return httpClient.request(request, function (response) {
-            try {
-                if (response.headers) {
-                    normalizeHeaders(response.headers);
-                }
-
-                if (response.data === undefined && response.statusCode !== 204) {
-                    handler.read(response, context);
-                }
-            } catch (err) {
-                if (err.request === undefined) {
-                    err.request = request;
-                }
-                if (err.response === undefined) {
-                    err.response = response;
-                }
-                error(err);
-                return;
-            }
-
-            success(response.data, response);
-        }, error);
-    };
-
-    var isBatch = function (value) {
-        /// <summary>Tests whether a value is a batch object in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a batch object; false otherwise.</returns>
-
-        return isComplex(value) && isArray(value.__batchRequests);
-    };
-
-    // Regular expression used for testing and parsing for a collection type.
-    var collectionTypeRE = /Collection\((.*)\)/;
-
-    var isCollection = function (value, typeName) {
-        /// <summary>Tests whether a value is a collection value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
-        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
-
-        var colData = value && value.results || value;
-        return !!colData &&
-            (isCollectionType(typeName)) ||
-            (!typeName && isArray(colData) && !isComplex(colData[0]));
-    };
-
-    var isCollectionType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a collection type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is the name of a collection type; false otherwise.</returns>
-        return collectionTypeRE.test(typeName);
-    };
-
-    var isComplex = function (value) {
-        /// <summary>Tests whether a value is a complex type value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a complex type value; false otherwise.</returns>
-
-        return !!value &&
-            isObject(value) &&
-            !isArray(value) &&
-            !isDate(value);
-    };
-
-    var isDateTimeOffset = function (value) {
-        /// <summary>Checks whether a Date object is DateTimeOffset value</summary>
-        /// <param name="value" type="Date" mayBeNull="false">Value to check.</param>
-        /// <returns type="Boolean">true if the value is a DateTimeOffset, false otherwise.</returns>
-        return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
-    };
-
-    var isDeferred = function (value) {
-        /// <summary>Tests whether a value is a deferred navigation property in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a deferred navigation property; false otherwise.</returns>
-
-        if (!value && !isComplex(value)) {
-            return false;
-        }
-        var metadata = value.__metadata || {};
-        var deferred = value.__deferred || {};
-        return !metadata.type && !!deferred.uri;
-    };
-
-    var isEntry = function (value) {
-        /// <summary>Tests whether a value is an entry object in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is an entry object; false otherwise.</returns>
-
-        return isComplex(value) && value.__metadata && "uri" in value.__metadata;
-    };
-
-    var isFeed = function (value, typeName) {
-        /// <summary>Tests whether a value is a feed value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
-        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
-
-        var feedData = value && value.results || value;
-        return isArray(feedData) && (
-            (!isCollectionType(typeName)) &&
-            (isComplex(feedData[0]))
-        );
-    };
-
-    var isGeographyEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a geography EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a geography EDM type; false otherwise.</returns>
-
-        return contains(geographyEdmTypes, typeName);
-    };
-
-    var isGeometryEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a geometry EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a geometry EDM type; false otherwise.</returns>
-
-        return contains(geometryEdmTypes, typeName);
-    };
-
-    var isNamedStream = function (value) {
-        /// <summary>Tests whether a value is a named stream value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a named stream; false otherwise.</returns>
-
-        if (!value && !isComplex(value)) {
-            return false;
-        }
-        var metadata = value.__metadata;
-        var mediaResource = value.__mediaresource;
-        return !metadata && !!mediaResource && !!mediaResource.media_src;
-    };
-
-    var isPrimitive = function (value) {
-        /// <summary>Tests whether a value is a primitive type value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <remarks>
-        ///    Date objects are considered primitive types by the library.
-        /// </remarks>
-        /// <returns type="Boolean">True is the value is a primitive type value.</returns>
-
-        return isDate(value) ||
-            typeof value === "string" ||
-            typeof value === "number" ||
-            typeof value === "boolean";
-    };
-
-    var isPrimitiveEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a primitive EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a primitive EDM type; false otherwise.</returns>
-
-        return contains(primitiveEdmTypes, typeName);
-    };
-
-    var navigationPropertyKind = function (value, propertyModel) {
-        /// <summary>Gets the kind of a navigation property value.</summary>
-        /// <param name="value">Value of the navigation property.</param>
-        /// <param name="propertyModel" type="Object" optional="true">
-        ///     Object that describes the navigation property in an OData conceptual schema.
-        /// </param>
-        /// <remarks>
-        ///     The returned string is as follows
-        /// </remarks>
-        /// <returns type="String">String value describing the kind of the navigation property; null if the kind cannot be determined.</returns>
-
-        if (isDeferred(value)) {
-            return "deferred";
-        }
-        if (isEntry(value)) {
-            return "entry";
-        }
-        if (isFeed(value)) {
-            return "feed";
-        }
-        if (propertyModel && propertyModel.relationship) {
-            if (value === null || value === undefined || !isFeed(value)) {
-                return "entry";
-            }
-            return "feed";
-        }
-        return null;
-    };
-
-    var lookupProperty = function (properties, name) {
-        /// <summary>Looks up a property by name.</summary>
-        /// <param name="properties" type="Array" mayBeNull="true">Array of property objects as per EDM metadata.</param>
-        /// <param name="name" type="String">Name to look for.</param>
-        /// <returns type="Object">The property object; null if not found.</returns>
-
-        return find(properties, function (property) {
-            return property.name === name;
-        });
-    };
-
-    var lookupInMetadata = function (name, metadata, kind) {
-        /// <summary>Looks up a type object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
-        /// <returns>An type description if the name is found; null otherwise.</returns>
-
-        return (name) ? forEachSchema(metadata, function (schema) {
-            return lookupInSchema(name, schema, kind);
-        }) : null;
-    };
-
-    var lookupEntitySet = function (entitySets, 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(entitySets, function (entitySet) {
-            return entitySet.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>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>A complex type description if the name is found; null otherwise.</returns>
-
-        return lookupInMetadata(name, metadata, "complexType");
-    };
-
-    var lookupEntityType = function (name, metadata) {
-        /// <summary>Looks up an entity type object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity type description if the name is found; null otherwise.</returns>
-
-        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>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity container description if the name is found; null otherwise.</returns>
-
-        return forEachSchema(metadata, function (schema) {
-            return find(schema.entityContainer, function (container) {
-                return parseBool(container.isDefaultEntityContainer);
-            });
-        });
-    };
-
-    var lookupEntityContainer = function (name, metadata) {
-        /// <summary>Looks up an entity container object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity container description if the name is found; null otherwise.</returns>
-
-        return lookupInMetadata(name, metadata, "entityContainer");
-    };
-
-    var lookupFunctionImport = function (functionImports, name) {
-        /// <summary>Looks up a function import by name.</summary>
-        /// <param name="properties" type="Array" mayBeNull="true">Array of function import 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(functionImports, function (functionImport) {
-            return functionImport.name === name;
-        });
-    };
-
-    var lookupNavigationPropertyType = function (navigationProperty, metadata) {
-        /// <summary>Looks up the target entity type for a navigation property.</summary>
-        /// <param name="navigationProperty" type="Object"></param>
-        /// <param name="metadata" type="Object"></param>
-        /// <returns type="String">The entity type name for the specified property, null if not found.</returns>
-
-        var result = null;
-        if (navigationProperty) {
-            var rel = navigationProperty.relationship;
-            var association = forEachSchema(metadata, function (schema) {
-                // The name should be the namespace qualified name in 'ns'.'type' format.
-                var nameOnly = removeNamespace(schema["namespace"], rel);
-                var associations = schema.association;
-                if (nameOnly && associations) {
-                    var i, len;
-                    for (i = 0, len = associations.length; i < len; i++) {
-                        if (associations[i].name === nameOnly) {
-                            return associations[i];
-                        }
-                    }
-                }
-                return null;
-            });
-
-            if (association) {
-                var end = association.end[0];
-                if (end.role !== navigationProperty.toRole) {
-                    end = association.end[1];
-                    // For metadata to be valid, end.role === navigationProperty.toRole now.
-                }
-                result = end.type;
-            }
-        }
-        return result;
-    };
-
-    var lookupNavigationPropertyEntitySet = function (navigationProperty, sourceEntitySetName, metadata) {
-        /// <summary>Looks up the target entityset name for a navigation property.</summary>
-        /// <param name="navigationProperty" type="Object"></param>
-        /// <param name="metadata" type="Object"></param>
-        /// <returns type="String">The entityset name for the specified property, null if not found.</returns>
-
-        if (navigationProperty) {
-            var rel = navigationProperty.relationship;
-            var associationSet = forEachSchema(metadata, function (schema) {
-                var containers = schema.entityContainer;
-                for (var i = 0; i < containers.length; i++) {
-                    var associationSets = containers[i].associationSet;
-                    if (associationSets) {
-                        for (var j = 0; j < associationSets.length; j++) {
-                            if (associationSets[j].association == rel) {
-                                return associationSets[j];
-                            }
-                        }
-                    }
-                }
-                return null;
-            });
-            if (associationSet && associationSet.end[0] && associationSet.end[1]) {
-                return (associationSet.end[0].entitySet == sourceEntitySetName) ? associationSet.end[1].entitySet : associationSet.end[0].entitySet;
-            }
-        }
-        return null;
-    };
-
-    var getEntitySetInfo = function (entitySetName, metadata) {
-        /// <summary>Gets the entitySet info, container name and functionImports for an entitySet</summary>
-        /// <param name="navigationProperty" type="Object"></param>
-        /// <param name="metadata" type="Object"></param>
-        /// <returns type="Object">The info about the entitySet.</returns>
-
-        var info = forEachSchema(metadata, function (schema) {
-            var containers

<TRUNCATED>

[19/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/datajs/utils.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/datajs/utils.js b/odatajs/src/lib/datajs/utils.js
new file mode 100644
index 0000000..27af705
--- /dev/null
+++ b/odatajs/src/lib/datajs/utils.js
@@ -0,0 +1,582 @@
+/*
+ * 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.
+ */
+
+/** @module datajs/utils */
+
+
+function inBrowser() {
+    return typeof window !== 'undefined';
+}
+
+/** Creates a new ActiveXObject from the given progId.
+ * @param {String} progId - ProgId string of the desired ActiveXObject.
+ * @returns {Object} The ActiveXObject instance. Null if ActiveX is not supported by the browser.
+ * This function throws whatever exception might occur during the creation
+ * of the ActiveXObject.
+*/
+var activeXObject = function (progId) {
+    
+    if (window.ActiveXObject) {
+        return new window.ActiveXObject(progId);
+    }
+    return null;
+};
+
+/** Checks whether the specified value is different from null and undefined.
+ * @param [value] Value to check ( may be null)
+ * @returns {Boolean} true if the value is assigned; false otherwise.
+*/     
+function assigned(value) {
+    return value !== null && value !== undefined;
+}
+
+/** Checks whether the specified item is in the array.
+ * @param {Array} [arr] Array to check in.
+ * @param item - Item to look for.
+ * @returns {Boolean} true if the item is contained, false otherwise.
+*/
+function contains(arr, item) {
+    var i, len;
+    for (i = 0, len = arr.length; i < len; i++) {
+        if (arr[i] === item) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/** Given two values, picks the first one that is not undefined.
+ * @param a - First value.
+ * @param b - Second value.
+ * @returns a if it's a defined value; else b.</returns>
+ */
+function defined(a, b) {
+    return (a !== undefined) ? a : b;
+}
+
+/** Delays the invocation of the specified function until execution unwinds.
+ * @param {Function} callback - Callback function.
+ */
+function delay(callback) {
+
+    if (arguments.length === 1) {
+        window.setTimeout(callback, 0);
+        return;
+    }
+
+    var args = Array.prototype.slice.call(arguments, 1);
+    window.setTimeout(function () {
+        callback.apply(this, args);
+    }, 0);
+}
+
+/** Throws an exception in case that a condition evaluates to false.
+ * @param {Boolean} condition - Condition to evaluate.
+ * @param {String} message - Message explaining the assertion.
+ * @param {Object} data - Additional data to be included in the exception.
+ */
+// DATAJS INTERNAL START
+function djsassert(condition, message, data) {
+
+
+    if (!condition) {
+        throw { message: "Assert fired: " + message, data: data };
+    }
+}
+// DATAJS INTERNAL END
+
+/** Extends the target with the specified values.
+ * @param {Object} target - Object to add properties to.
+ * @param {Object} values - Object with properties to add into target.
+ * @returns {Object} The target object.
+*/
+function extend(target, values) {
+    for (var name in values) {
+        target[name] = values[name];
+    }
+
+    return target;
+}
+
+function find(arr, callback) {
+    /** Returns the first item in the array that makes the callback function true.
+     * @param {Array} [arr] Array to check in. ( may be null)
+     * @param {Function} callback - Callback function to invoke once per item in the array.
+     * @returns The first item that makes the callback return true; null otherwise or if the array is null.
+    */
+
+    if (arr) {
+        var i, len;
+        for (i = 0, len = arr.length; i < len; i++) {
+            if (callback(arr[i])) {
+                return arr[i];
+            }
+        }
+    }
+    return null;
+}
+
+function isArray(value) {
+    /** Checks whether the specified value is an array object.
+     * @param value - Value to check.
+     * @returns {Boolean} true if the value is an array object; false otherwise.
+     */
+
+    return Object.prototype.toString.call(value) === "[object Array]";
+}
+
+/** Checks whether the specified value is a Date object.
+ * @param value - Value to check.
+ * @returns {Boolean} true if the value is a Date object; false otherwise.
+ */
+function isDate(value) {
+    return Object.prototype.toString.call(value) === "[object Date]";
+}
+
+/** Tests whether a value is an object.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is an object; false otherwise.
+ * Per javascript rules, null and array values are objects and will cause this function to return true.
+ */
+function isObject(value) {
+    return typeof value === "object";
+}
+
+/** Parses a value in base 10.
+ * @param {String} value - String value to parse.
+ * @returns {Number} The parsed value, NaN if not a valid value.
+*/   
+function parseInt10(value) {
+    return parseInt(value, 10);
+}
+
+/** Renames a property in an object.
+ * @param {Object} obj - Object in which the property will be renamed.
+ * @param {String} oldName - Name of the property that will be renamed.
+ * @param {String} newName - New name of the property.
+ * This function will not do anything if the object doesn't own a property with the specified old name.
+ */
+function renameProperty(obj, oldName, newName) {
+    if (obj.hasOwnProperty(oldName)) {
+        obj[newName] = obj[oldName];
+        delete obj[oldName];
+    }
+}
+
+/** Default error handler.
+ * @param {Object} error - Error to handle.
+ */
+function throwErrorCallback(error) {
+    throw error;
+}
+
+/** Removes leading and trailing whitespaces from a string.
+ * @param {String str String to trim
+ * @returns {String} The string with no leading or trailing whitespace.
+ */
+function trimString(str) {
+    if (str.trim) {
+        return str.trim();
+    }
+
+    return str.replace(/^\s+|\s+$/g, '');
+}
+
+/** Returns a default value in place of undefined.
+ * @param [value] Value to check (may be null)
+ * @param defaultValue - Value to return if value is undefined.
+ * @returns value if it's defined; defaultValue otherwise.
+ * This should only be used for cases where falsy values are valid;
+ * otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
+ */
+function undefinedDefault(value, defaultValue) {
+    return (value !== undefined) ? value : defaultValue;
+}
+
+// Regular expression that splits a uri into its components:
+// 0 - is the matched string.
+// 1 - is the scheme.
+// 2 - is the authority.
+// 3 - is the path.
+// 4 - is the query.
+// 5 - is the fragment.
+var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
+var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
+
+/** Gets information about the components of the specified URI.
+ * @param {String} uri - URI to get information from.
+ * @return  {Object} An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
+ */
+function getURIInfo(uri) {
+    var result = { isAbsolute: false };
+
+    if (uri) {
+        var matches = uriRegEx.exec(uri);
+        if (matches) {
+            var i, len;
+            for (i = 0, len = uriPartNames.length; i < len; i++) {
+                if (matches[i + 1]) {
+                    result[uriPartNames[i]] = matches[i + 1];
+                }
+            }
+        }
+        if (result.scheme) {
+            result.isAbsolute = true;
+        }
+    }
+
+    return result;
+}
+
+/** Builds a URI string from its components.
+ * @param {Object} uriInfo -  An object with uri parts (scheme, authority, etc.).
+ * @returns {String} URI string.
+ */
+function getURIFromInfo(uriInfo) {
+    return "".concat(
+        uriInfo.scheme || "",
+        uriInfo.authority || "",
+        uriInfo.path || "",
+        uriInfo.query || "",
+        uriInfo.fragment || "");
+}
+
+// Regular expression that splits a uri authority into its subcomponents:
+// 0 - is the matched string.
+// 1 - is the userinfo subcomponent.
+// 2 - is the host subcomponent.
+// 3 - is the port component.
+var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
+
+// Regular expression that matches percentage enconded octects (i.e %20 or %3A);
+var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
+
+/** Normalizes the casing of a URI.
+ * @param {String} uri - URI to normalize, absolute or relative.
+ * @returns {String} The URI normalized to lower case.
+*/
+function normalizeURICase(uri) {
+    var uriInfo = getURIInfo(uri);
+    var scheme = uriInfo.scheme;
+    var authority = uriInfo.authority;
+
+    if (scheme) {
+        uriInfo.scheme = scheme.toLowerCase();
+        if (authority) {
+            var matches = uriAuthorityRegEx.exec(authority);
+            if (matches) {
+                uriInfo.authority = "//" +
+                (matches[1] ? matches[1] + "@" : "") +
+                (matches[2].toLowerCase()) +
+                (matches[3] ? ":" + matches[3] : "");
+            }
+        }
+    }
+
+    uri = getURIFromInfo(uriInfo);
+
+    return uri.replace(pctEncodingRegEx, function (str) {
+        return str.toLowerCase();
+    });
+}
+
+/** Normalizes a possibly relative URI with a base URI.
+ * @param {String} uri - URI to normalize, absolute or relative
+ * @param {String} base - Base URI to compose with (may be null)
+ * @returns {String} The composed URI if relative; the original one if absolute.
+ */
+function normalizeURI(uri, base) {
+    if (!base) {
+        return uri;
+    }
+
+    var uriInfo = getURIInfo(uri);
+    if (uriInfo.isAbsolute) {
+        return uri;
+    }
+
+    var baseInfo = getURIInfo(base);
+    var normInfo = {};
+    var path;
+
+    if (uriInfo.authority) {
+        normInfo.authority = uriInfo.authority;
+        path = uriInfo.path;
+        normInfo.query = uriInfo.query;
+    } else {
+        if (!uriInfo.path) {
+            path = baseInfo.path;
+            normInfo.query = uriInfo.query || baseInfo.query;
+        } else {
+            if (uriInfo.path.charAt(0) === '/') {
+                path = uriInfo.path;
+            } else {
+                path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
+            }
+            normInfo.query = uriInfo.query;
+        }
+        normInfo.authority = baseInfo.authority;
+    }
+
+    normInfo.path = removeDotsFromPath(path);
+
+    normInfo.scheme = baseInfo.scheme;
+    normInfo.fragment = uriInfo.fragment;
+
+    return getURIFromInfo(normInfo);
+}
+
+/** Merges the path of a relative URI and a base URI.
+ * @param {String} uriPath - Relative URI path.</param>
+ * @param {String} basePath - Base URI path.
+ * @returns {String} A string with the merged path.
+ */
+function mergeUriPathWithBase(uriPath, basePath) {
+    var path = "/";
+    var end;
+
+    if (basePath) {
+        end = basePath.lastIndexOf("/");
+        path = basePath.substring(0, end);
+
+        if (path.charAt(path.length - 1) !== "/") {
+            path = path + "/";
+        }
+    }
+
+    return path + uriPath;
+}
+
+/** Removes the special folders . and .. from a URI's path.
+ * @param {string} path - URI path component.
+ * @returns {String} Path without any . and .. folders.
+ */
+function removeDotsFromPath(path) {
+    var result = "";
+    var segment = "";
+    var end;
+
+    while (path) {
+        if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
+            path = path.replace(/^\.\.?\/?/g, "");
+        } else if (path.indexOf("/..") === 0) {
+            path = path.replace(/^\/\..\/?/g, "/");
+            end = result.lastIndexOf("/");
+            if (end === -1) {
+                result = "";
+            } else {
+                result = result.substring(0, end);
+            }
+        } else if (path.indexOf("/.") === 0) {
+            path = path.replace(/^\/\.\/?/g, "/");
+        } else {
+            segment = path;
+            end = path.indexOf("/", 1);
+            if (end !== -1) {
+                segment = path.substring(0, end);
+            }
+            result = result + segment;
+            path = path.replace(segment, "");
+        }
+    }
+    return result;
+}
+
+function convertByteArrayToHexString(str) {
+    var arr = [];
+    if (window.atob === undefined) {
+        arr = decodeBase64(str);
+    } else {
+        var binaryStr = window.atob(str);
+        for (var i = 0; i < binaryStr.length; i++) {
+            arr.push(binaryStr.charCodeAt(i));
+        }
+    }
+    var hexValue = "";
+    var hexValues = "0123456789ABCDEF";
+    for (var j = 0; j < arr.length; j++) {
+        var t = arr[j];
+        hexValue += hexValues[t >> 4];
+        hexValue += hexValues[t & 0x0F];
+    }
+    return hexValue;
+}
+
+function decodeBase64(str) {
+    var binaryString = "";
+    for (var i = 0; i < str.length; i++) {
+        var base65IndexValue = getBase64IndexValue(str[i]);
+        var binaryValue = "";
+        if (base65IndexValue !== null) {
+            binaryValue = base65IndexValue.toString(2);
+            binaryString += addBase64Padding(binaryValue);
+        }
+    }
+    var byteArray = [];
+    var numberOfBytes = parseInt(binaryString.length / 8, 10);
+    for (i = 0; i < numberOfBytes; i++) {
+        var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
+        byteArray.push(intValue);
+    }
+    return byteArray;
+}
+
+function getBase64IndexValue(character) {
+    var asciiCode = character.charCodeAt(0);
+    var asciiOfA = 65;
+    var differenceBetweenZanda = 6;
+    if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
+        return asciiCode - asciiOfA;
+    } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
+        return asciiCode - asciiOfA - differenceBetweenZanda;
+    } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
+        return asciiCode + 4;
+    } else if (character == "+") {
+        return 62;
+    } else if (character == "/") {
+        return 63;
+    } else {
+        return null;
+    }
+}
+
+function addBase64Padding(binaryString) {
+    while (binaryString.length < 6) {
+        binaryString = "0" + binaryString;
+    }
+    return binaryString;
+
+}
+
+function getJsonValueArraryLength(data) {
+    if (data && data.value) {
+        return data.value.length;
+    }
+
+    return 0;
+}
+
+function sliceJsonValueArray(data, start, end) {
+    if (data === undefined || data.value === undefined) {
+        return data;
+    }
+
+    if (start < 0) {
+        start = 0;
+    }
+
+    var length = getJsonValueArraryLength(data);
+    if (length < end) {
+        end = length;
+    }
+
+    var newdata = {};
+    for (var property in data) {
+        if (property == "value") {
+            newdata[property] = data[property].slice(start, end);
+        } else {
+            newdata[property] = data[property];
+        }
+    }
+
+    return newdata;
+}
+
+function concatJsonValueArray(data, concatData) {
+    if (concatData === undefined || concatData.value === undefined) {
+        return data;
+    }
+
+    if (data === undefined || Object.keys(data).length === 0) {
+        return concatData;
+    }
+
+    if (data.value === undefined) {
+        data.value = concatData.value;
+        return data;
+    }
+
+    data.value = data.value.concat(concatData.value);
+
+    return data;
+}
+
+function endsWith(input, search) {
+    return input.indexOf(search, input.length - search.length) !== -1;
+}
+
+function startsWith (input, search) {
+    return input.indexOf(search) === 0;
+}
+
+function getFormatKind(format, defaultFormatKind) {
+    var formatKind = defaultFormatKind;
+    if (!assigned(format)) {
+        return formatKind;
+    }
+
+    var normalizedFormat = format.toLowerCase();
+    switch (normalizedFormat) {
+        case "none":
+            formatKind = 0;
+            break;
+        case "minimal":
+            formatKind = 1;
+            break;
+        case "full":
+            formatKind = 2;
+            break;
+        default:
+            break;
+    }
+
+    return formatKind;
+}
+
+
+    
+    
+exports.inBrowser = inBrowser;
+exports.activeXObject = activeXObject;
+exports.assigned = assigned;
+exports.contains = contains;
+exports.defined = defined;
+exports.delay = delay;
+exports.djsassert = djsassert;
+exports.extend = extend;
+exports.find = find;
+exports.getURIInfo = getURIInfo;
+exports.isArray = isArray;
+exports.isDate = isDate;
+exports.isObject = isObject;
+exports.normalizeURI = normalizeURI;
+exports.normalizeURICase = normalizeURICase;
+exports.parseInt10 = parseInt10;
+exports.renameProperty = renameProperty;
+exports.throwErrorCallback = throwErrorCallback;
+exports.trimString = trimString;
+exports.undefinedDefault = undefinedDefault;
+exports.decodeBase64 = decodeBase64;
+exports.convertByteArrayToHexString = convertByteArrayToHexString;
+exports.getJsonValueArraryLength = getJsonValueArraryLength;
+exports.sliceJsonValueArray = sliceJsonValueArray;
+exports.concatJsonValueArray = concatJsonValueArray;
+exports.startsWith = startsWith;
+exports.endsWith = endsWith;
+exports.getFormatKind = getFormatKind;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/datajs/xml.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/datajs/xml.js b/odatajs/src/lib/datajs/xml.js
new file mode 100644
index 0000000..b8af4fe
--- /dev/null
+++ b/odatajs/src/lib/datajs/xml.js
@@ -0,0 +1,816 @@
+/*
+ * 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.
+ */
+ 
+
+/** @module datajs/xml */
+
+var utils    = require('./utils.js');
+
+var activeXObject = utils.activeXObject;
+var djsassert = utils.djsassert;
+var extend = utils.extend;
+var isArray = utils.isArray;
+var normalizeURI = utils.normalizeURI;
+
+// URI prefixes to generate smaller code.
+var http = "http://";
+var w3org = http + "www.w3.org/";               // http://www.w3.org/
+
+var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
+var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
+var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
+
+var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
+
+/** Checks whether the specified string has leading or trailing spaces.
+ * @param {String} text - String to check.
+ * @returns {Boolean} true if text has any leading or trailing whitespace; false otherwise.
+ */
+function hasLeadingOrTrailingWhitespace(text) {
+    var re = /(^\s)|(\s$)/;
+    return re.test(text);
+}
+
+/** Determines whether the specified text is empty or whitespace.
+ * @param {String} text - Value to inspect.
+ * @returns {Boolean} true if the text value is empty or all whitespace; false otherwise.
+ */
+function isWhitespace(text) {
+
+
+    var ws = /^\s*$/;
+    return text === null || ws.test(text);
+}
+
+/** Determines whether the specified element has xml:space='preserve' applied.
+ * @param domElement - Element to inspect.
+ * @returns {Boolean} Whether xml:space='preserve' is in effect.
+ */
+function isWhitespacePreserveContext(domElement) {
+
+
+    while (domElement !== null && domElement.nodeType === 1) {
+        var val = xmlAttributeValue(domElement, "space", xmlNS);
+        if (val === "preserve") {
+            return true;
+        } else if (val === "default") {
+            break;
+        } else {
+            domElement = domElement.parentNode;
+        }
+    }
+
+    return false;
+}
+
+/** Determines whether the attribute is a XML namespace declaration.
+ * @param domAttribute - Element to inspect.
+ * @return {Boolean} True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
+ */
+function isXmlNSDeclaration(domAttribute) {
+    var nodeName = domAttribute.nodeName;
+    return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
+}
+
+/** Safely set as property in an object by invoking obj.setProperty.
+ * @param obj - Object that exposes a setProperty method.
+ * @param {String} name - Property name
+ * @param value - Property value.
+ */
+function safeSetProperty(obj, name, value) {
+
+
+    try {
+        obj.setProperty(name, value);
+    } catch (_) { }
+}
+
+/** Creates an configures new MSXML 3.0 ActiveX object.
+ * @returns {Object} New MSXML 3.0 ActiveX object.
+ * This function throws any exception that occurs during the creation
+ * of the MSXML 3.0 ActiveX object.
+ */
+function msXmlDom3() {
+    var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
+    if (msxml3) {
+        safeSetProperty(msxml3, "ProhibitDTD", true);
+        safeSetProperty(msxml3, "MaxElementDepth", 256);
+        safeSetProperty(msxml3, "AllowDocumentFunction", false);
+        safeSetProperty(msxml3, "AllowXsltScript", false);
+    }
+    return msxml3;
+}
+
+/** Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.
+ * @returns {Object} New MSXML 3.0 ActiveX object.
+ * This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
+ * it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
+ * happens during the creation of the MSXML 6.0 will be handled by the function while
+ * the ones that happend during the creation of the MSXML 3.0 will be thrown.
+ */
+function msXmlDom() {
+    try {
+        var msxml = activeXObject("Msxml2.DOMDocument.6.0");
+        if (msxml) {
+            msxml.async = true;
+        }
+        return msxml;
+    } catch (_) {
+        return msXmlDom3();
+    }
+}
+
+/** Parses an XML string using the MSXML DOM.
+ * @returns {Object} New MSXML DOMDocument node representing the parsed XML string.
+ * This function throws any exception that occurs during the creation
+ * of the MSXML ActiveX object.  It also will throw an exception
+ * in case of a parsing error.
+ */
+function msXmlParse(text) {
+    var dom = msXmlDom();
+    if (!dom) {
+        return null;
+    }
+
+    dom.loadXML(text);
+    var parseError = dom.parseError;
+    if (parseError.errorCode !== 0) {
+        xmlThrowParserError(parseError.reason, parseError.srcText, text);
+    }
+    return dom;
+}
+
+/** Throws a new exception containing XML parsing error information.
+ * @param exceptionOrReason - String indicating the reason of the parsing failure or Object detailing the parsing error.
+ * @param {String} srcText -     String indicating the part of the XML string that caused the parsing error.
+ * @param {String} errorXmlText - XML string for wich the parsing failed.
+ */
+function xmlThrowParserError(exceptionOrReason, srcText, errorXmlText) {
+
+    if (typeof exceptionOrReason === "string") {
+        exceptionOrReason = { message: exceptionOrReason };
+    }
+    throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
+}
+
+/** Returns an XML DOM document from the specified text.
+ * @param {String} text - Document text.
+ * @returns XML DOM document.
+ * This function will throw an exception in case of a parse error
+ */
+function xmlParse(text) {
+    var domParser = window.DOMParser && new window.DOMParser();
+    var dom;
+
+    if (!domParser) {
+        dom = msXmlParse(text);
+        if (!dom) {
+            xmlThrowParserError("XML DOM parser not supported");
+        }
+        return dom;
+    }
+
+    try {
+        dom = domParser.parseFromString(text, "text/xml");
+    } catch (e) {
+        xmlThrowParserError(e, "", text);
+    }
+
+    var element = dom.documentElement;
+    var nsURI = element.namespaceURI;
+    var localName = xmlLocalName(element);
+
+    // Firefox reports errors by returing the DOM for an xml document describing the problem.
+    if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
+        var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
+        var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
+        xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
+    }
+
+    // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
+    // The error may be localized, so instead we simply check for a header as the
+    // top element or descendant child of the document.
+    if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
+        var reason = "";
+        var siblings = [];
+        var cursor = element.firstChild;
+        while (cursor) {
+            if (cursor.nodeType === 1) {
+                reason += xmlInnerText(cursor) || "";
+            }
+            siblings.push(cursor.nextSibling);
+            cursor = cursor.firstChild || siblings.shift();
+        }
+        reason += xmlInnerText(element) || "";
+        xmlThrowParserError(reason, "", text);
+    }
+
+    return dom;
+}
+
+/** Builds a XML qualified name string in the form of "prefix:name".
+ * @param {String} prefix - Prefix string (may be null)
+ * @param {String} name - Name string to qualify with the prefix.
+ * @returns {String} Qualified name.
+ */
+function xmlQualifiedName(prefix, name) {
+    return prefix ? prefix + ":" + name : name;
+}
+
+/** Appends a text node into the specified DOM element node.
+ * @param domNode - DOM node for the element.
+ * @param {String} text - Text to append as a child of element.
+*/
+function xmlAppendText(domNode, textNode) {
+    if (hasLeadingOrTrailingWhitespace(textNode.data)) {
+        var attr = xmlAttributeNode(domNode, xmlNS, "space");
+        if (!attr) {
+            attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
+            xmlAppendChild(domNode, attr);
+        }
+        attr.value = "preserve";
+    }
+    domNode.appendChild(textNode);
+    return domNode;
+}
+
+/** Iterates through the XML element's attributes and invokes the callback function for each one.
+ * @param element - Wrapped element to iterate over.
+ * @param {Function} onAttributeCallback - Callback function to invoke with wrapped attribute nodes.
+*/
+function xmlAttributes(element, onAttributeCallback) {
+    var attributes = element.attributes;
+    var i, len;
+    for (i = 0, len = attributes.length; i < len; i++) {
+        onAttributeCallback(attributes.item(i));
+    }
+}
+
+/** Returns the value of a DOM element's attribute.
+ * @param domNode - DOM node for the owning element.
+ * @param {String} localName - Local name of the attribute.
+ * @param {String} nsURI - Namespace URI of the attribute.
+ * @returns {String} - The attribute value, null if not found (may be null)
+ */
+function xmlAttributeValue(domNode, localName, nsURI) {
+
+    var attribute = xmlAttributeNode(domNode, localName, nsURI);
+    return attribute ? xmlNodeValue(attribute) : null;
+}
+
+/** Gets an attribute node from a DOM element.
+ * @param domNode - DOM node for the owning element.
+ * @param {String} localName - Local name of the attribute.
+ * @param {String} nsURI - Namespace URI of the attribute.
+ * @returns The attribute node, null if not found.
+ */
+function xmlAttributeNode(domNode, localName, nsURI) {
+
+    var attributes = domNode.attributes;
+    if (attributes.getNamedItemNS) {
+        return attributes.getNamedItemNS(nsURI || null, localName);
+    }
+
+    return attributes.getQualifiedItem(localName, nsURI) || null;
+}
+
+/** Gets the value of the xml:base attribute on the specified element.
+ * @param domNode - Element to get xml:base attribute value from.
+ * @param [baseURI] - Base URI used to normalize the value of the xml:base attribute ( may be null)
+ * @returns {String} Value of the xml:base attribute if found; the baseURI or null otherwise.
+ */
+function xmlBaseURI(domNode, baseURI) {
+
+    var base = xmlAttributeNode(domNode, "base", xmlNS);
+    return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
+}
+
+
+/** Iterates through the XML element's child DOM elements and invokes the callback function for each one.
+ * @param element - DOM Node containing the DOM elements to iterate over.
+ * @param {Function} onElementCallback - Callback function to invoke for each child DOM element.
+*/
+function xmlChildElements(domNode, onElementCallback) {
+
+    xmlTraverse(domNode, /*recursive*/false, function (child) {
+        if (child.nodeType === 1) {
+            onElementCallback(child);
+        }
+        // continue traversing.
+        return true;
+    });
+}
+
+/** Gets the descendant element under root that corresponds to the specified path and namespace URI.
+ * @param root - DOM element node from which to get the descendant element.
+ * @param {String} namespaceURI - The namespace URI of the element to match.
+ * @param {String} path - Path to the desired descendant element.
+ * @return The element specified by path and namespace URI.
+ * All the elements in the path are matched against namespaceURI.
+ * The function will stop searching on the first element that doesn't match the namespace and the path.
+ */
+function xmlFindElementByPath(root, namespaceURI, path) {
+    var parts = path.split("/");
+    var i, len;
+    for (i = 0, len = parts.length; i < len; i++) {
+        root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
+    }
+    return root || null;
+}
+
+/** Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.
+ * @param root - DOM element node from which to get the descendant node.
+ * @param {String} namespaceURI - The namespace URI of the node to match.
+ * @param {String} path - Path to the desired descendant node.
+ * @return The node specified by path and namespace URI.</returns>
+
+* This function will traverse the path and match each node associated to a path segement against the namespace URI.
+* The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
+* The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
+*/
+function xmlFindNodeByPath(root, namespaceURI, path) {
+    
+
+    var lastSegmentStart = path.lastIndexOf("/");
+    var nodePath = path.substring(lastSegmentStart + 1);
+    var parentPath = path.substring(0, lastSegmentStart);
+
+    var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
+    if (node) {
+        if (nodePath.charAt(0) === "@") {
+            return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
+        }
+        return xmlFirstChildElement(node, namespaceURI, nodePath);
+    }
+    return null;
+}
+
+/** Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.
+ * @param domNode - DOM node from which the child DOM element is going to be retrieved.
+ * @param {String} [namespaceURI] - 
+ * @param {String} [localName] - 
+ * @return The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+ */
+function xmlFirstChildElement(domNode, namespaceURI, localName) {
+
+    return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
+}
+
+/** Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
+ * @param domNode - DOM node from which the descendant DOM element is going to be retrieved.
+ * @param {String} [namespaceURI] - 
+ * @param {String} [localName] - 
+ * @return The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.
+*/
+function xmlFirstDescendantElement(domNode, namespaceURI, localName) {
+    if (domNode.getElementsByTagNameNS) {
+        var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
+        return result.length > 0 ? result[0] : null;
+    }
+    return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
+}
+
+/** Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
+ * @param domNode - DOM node from which the descendant DOM element is going to be retrieved.
+ * @param {String} [namespaceURI] - 
+ * @param {String} [localName] - 
+ * @param {Boolean} recursive 
+ * - True if the search should include all the descendants of the DOM node.  
+ * - False if the search should be scoped only to the direct children of the DOM node.
+ * @return The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.
+ */
+function xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, recursive) {
+
+    var firstElement = null;
+    xmlTraverse(domNode, recursive, function (child) {
+        if (child.nodeType === 1) {
+            var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
+            var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
+
+            if (isExpectedNamespace && isExpectedNodeName) {
+                firstElement = child;
+            }
+        }
+        return firstElement === null;
+    });
+    return firstElement;
+}
+
+/** Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.
+ * @param domElement - Element to get values for.
+ * @returns {String} Text for all direct children.
+ */
+function xmlInnerText(xmlElement) {
+
+    var result = null;
+    var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
+    var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
+    var whitespacePreserveContext;
+
+    xmlTraverse(root, false, function (child) {
+        if (child.nodeType === 3 || child.nodeType === 4) {
+            // isElementContentWhitespace indicates that this is 'ignorable whitespace',
+            // but it's not defined by all browsers, and does not honor xml:space='preserve'
+            // in some implementations.
+            //
+            // If we can't tell either way, we walk up the tree to figure out whether
+            // xml:space is set to preserve; otherwise we discard pure-whitespace.
+            //
+            // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
+            var text = xmlNodeValue(child);
+            var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
+            if (!shouldInclude) {
+                // Walk up the tree to figure out whether we are in xml:space='preserve' context
+                // for the cursor (needs to happen only once).
+                if (whitespacePreserveContext === undefined) {
+                    whitespacePreserveContext = isWhitespacePreserveContext(root);
+                }
+
+                shouldInclude = whitespacePreserveContext;
+            }
+
+            if (shouldInclude) {
+                if (!result) {
+                    result = text;
+                } else {
+                    result += text;
+                }
+            }
+        }
+        // Continue traversing?
+        return true;
+    });
+    return result;
+}
+
+/** Returns the localName of a XML node.
+ * @param domNode - DOM node to get the value from.
+ * @returns {String} localName of domNode.
+ */
+function xmlLocalName(domNode) {
+
+    return domNode.localName || domNode.baseName;
+}
+
+/** Returns the namespace URI of a XML node.
+ * @param node - DOM node to get the value from.
+ * @returns {String} Namespace URI of domNode.
+ */
+function xmlNamespaceURI(domNode) {
+
+    return domNode.namespaceURI || null;
+}
+
+/** Returns the value or the inner text of a XML node.
+ * @param node - DOM node to get the value from.
+ * @return Value of the domNode or the inner text if domNode represents a DOM element node.
+ */
+function xmlNodeValue(domNode) {
+    
+    if (domNode.nodeType === 1) {
+        return xmlInnerText(domNode);
+    }
+    return domNode.nodeValue;
+}
+
+/** Walks through the descendants of the domNode and invokes a callback for each node.
+ * @param domNode - DOM node whose descendants are going to be traversed.
+ * @param {Boolean} recursive
+ * - True if the traversal should include all the descenants of the DOM node.
+ * - False if the traversal should be scoped only to the direct children of the DOM node.
+ * @returns {String} Namespace URI of node.
+ */
+function xmlTraverse(domNode, recursive, onChildCallback) {
+
+    var subtrees = [];
+    var child = domNode.firstChild;
+    var proceed = true;
+    while (child && proceed) {
+        proceed = onChildCallback(child);
+        if (proceed) {
+            if (recursive && child.firstChild) {
+                subtrees.push(child.firstChild);
+            }
+            child = child.nextSibling || subtrees.shift();
+        }
+    }
+}
+
+/** Returns the next sibling DOM element of the specified DOM node.
+ * @param domNode - DOM node from which the next sibling is going to be retrieved.
+ * @param {String} [namespaceURI] - 
+ * @param {String} [localName] - 
+ * @return The node's next sibling DOM element, null if there is none.</returns>
+ */
+function xmlSiblingElement(domNode, namespaceURI, localName) {
+
+    var sibling = domNode.nextSibling;
+    while (sibling) {
+        if (sibling.nodeType === 1) {
+            var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
+            var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
+
+            if (isExpectedNamespace && isExpectedNodeName) {
+                return sibling;
+            }
+        }
+        sibling = sibling.nextSibling;
+    }
+    return null;
+}
+
+/** Creates a new empty DOM document node.
+ * @return New DOM document node.</returns>
+ *
+ * This function will first try to create a native DOM document using
+ * the browsers createDocument function.  If the browser doesn't
+ * support this but supports ActiveXObject, then an attempt to create
+ * an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
+ * for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
+ * the browser doesn't support ActiveXObject then an exception will be thrown.
+ */
+function xmlDom() {
+    var implementation = window.document.implementation;
+    return (implementation && implementation.createDocument) ?
+       implementation.createDocument(null, null, null) :
+       msXmlDom();
+}
+
+/** Appends a collection of child nodes or string values to a parent DOM node.
+ * @param parent - DOM node to which the children will be appended.
+ * @param {Array} children - Array containing DOM nodes or string values that will be appended to the parent.
+ * @return The parent with the appended children or string values.</returns>
+ *  If a value in the children collection is a string, then a new DOM text node is going to be created
+ *  for it and then appended to the parent.
+ */
+function xmlAppendChildren(parent, children) {
+    if (!isArray(children)) {
+        return xmlAppendChild(parent, children);
+    }
+
+    var i, len;
+    for (i = 0, len = children.length; i < len; i++) {
+        children[i] && xmlAppendChild(parent, children[i]);
+    }
+    return parent;
+}
+
+/** Appends a child node or a string value to a parent DOM node.
+ * @param parent - DOM node to which the child will be appended.
+ * @param child - Child DOM node or string value to append to the parent.
+ * @return The parent with the appended child or string value.</returns>
+ * If child is a string value, then a new DOM text node is going to be created
+ * for it and then appended to the parent.
+ */
+function xmlAppendChild(parent, child) {
+
+    djsassert(parent !== child, "xmlAppendChild() - parent and child are one and the same!");
+    if (child) {
+        if (typeof child === "string") {
+            return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
+        }
+        if (child.nodeType === 2) {
+            parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
+        } else {
+            parent.appendChild(child);
+        }
+    }
+    return parent;
+}
+
+/** Creates a new DOM attribute node.
+ * @param dom - DOM document used to create the attribute.
+ * @param {String} prefix - Namespace prefix.
+ * @param {String} namespaceURI - Namespace URI.
+ * @return DOM attribute node for the namespace declaration.
+ */
+function xmlNewAttribute(dom, namespaceURI, qualifiedName, value) {
+
+    var attribute =
+        dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
+        dom.createNode(2, qualifiedName, namespaceURI || undefined);
+
+    attribute.value = value || "";
+    return attribute;
+}
+
+/** Creates a new DOM element node.
+ * @param dom - DOM document used to create the DOM element.
+ * @param {String} namespaceURI - Namespace URI of the new DOM element.
+ * @param {String} qualifiedName - Qualified name in the form of "prefix:name" of the new DOM element.
+ * @param {Array} [children] Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
+ * @return New DOM element.</returns>
+ * If a value in the children collection is a string, then a new DOM text node is going to be created
+ * for it and then appended to the new DOM element.
+ */
+function xmlNewElement(dom, nampespaceURI, qualifiedName, children) {
+    var element =
+        dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
+        dom.createNode(1, qualifiedName, nampespaceURI || undefined);
+
+    return xmlAppendChildren(element, children || []);
+}
+
+/** Creates a namespace declaration attribute.
+ * @param dom - DOM document used to create the attribute.
+ * @param {String} namespaceURI - Namespace URI.
+ * @param {String} prefix - Namespace prefix.
+ * @return DOM attribute node for the namespace declaration.</returns>
+ */
+function xmlNewNSDeclaration(dom, namespaceURI, prefix) {
+    return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
+}
+
+/** Creates a new DOM document fragment node for the specified xml text.
+ * @param dom - DOM document from which the fragment node is going to be created.
+ * @param {String} text XML text to be represented by the XmlFragment.
+ * @return New DOM document fragment object.
+ */
+function xmlNewFragment(dom, text) {
+
+    var value = "<c>" + text + "</c>";
+    var tempDom = xmlParse(value);
+    var tempRoot = tempDom.documentElement;
+    var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
+    var fragment = dom.createDocumentFragment();
+
+    var importedChild = imported.firstChild;
+    while (importedChild) {
+        fragment.appendChild(importedChild);
+        importedChild = importedChild.nextSibling;
+    }
+    return fragment;
+}
+
+/** Creates new DOM text node.
+ * @param dom - DOM document used to create the text node.
+ * @param {String} text - Text value for the DOM text node.
+ * @return DOM text node.</returns>
+ */ 
+function xmlNewText(dom, text) {
+    return dom.createTextNode(text);
+}
+
+/** Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.
+ * @param dom - DOM document used to create the new node.
+ * @param root - DOM element node used as root of the subtree on which the new nodes are going to be created.
+ * @param {String} namespaceURI - Namespace URI of the new DOM element or attribute.
+ * @param {String} namespacePrefix - Prefix used to qualify the name of the new DOM element or attribute.
+ * @param {String} Path - Path string describing the location of the new DOM element or attribute from the root element.
+ * @return DOM element or attribute node for the last segment of the path.</returns>
+
+ * This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
+ * for each segment that doesn't have a matching element under root.
+ * The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
+ * will be created.
+ */
+function xmlNewNodeByPath(dom, root, namespaceURI, prefix, path) {
+    var name = "";
+    var parts = path.split("/");
+    var xmlFindNode = xmlFirstChildElement;
+    var xmlNewNode = xmlNewElement;
+    var xmlNode = root;
+
+    var i, len;
+    for (i = 0, len = parts.length; i < len; i++) {
+        name = parts[i];
+        if (name.charAt(0) === "@") {
+            name = name.substring(1);
+            xmlFindNode = xmlAttributeNode;
+            xmlNewNode = xmlNewAttribute;
+        }
+
+        var childNode = xmlFindNode(xmlNode, namespaceURI, name);
+        if (!childNode) {
+            childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
+            xmlAppendChild(xmlNode, childNode);
+        }
+        xmlNode = childNode;
+    }
+    return xmlNode;
+}
+
+/** Returns the text representation of the document to which the specified node belongs.
+ * @param root - Wrapped element in the document to serialize.
+ * @returns {String} Serialized document.
+*/
+function xmlSerialize(domNode) {
+    var xmlSerializer = window.XMLSerializer;
+    if (xmlSerializer) {
+        var serializer = new xmlSerializer();
+        return serializer.serializeToString(domNode);
+    }
+
+    if (domNode.xml) {
+        return domNode.xml;
+    }
+
+    throw { message: "XML serialization unsupported" };
+}
+
+/** Returns the XML representation of the all the descendants of the node.
+ * @param domNode - Node to serialize.</param>
+ * @returns {String} The XML representation of all the descendants of the node.
+ */
+function xmlSerializeDescendants(domNode) {
+    var children = domNode.childNodes;
+    var i, len = children.length;
+    if (len === 0) {
+        return "";
+    }
+
+    // Some implementations of the XMLSerializer don't deal very well with fragments that
+    // don't have a DOMElement as their first child. The work around is to wrap all the
+    // nodes in a dummy root node named "c", serialize it and then just extract the text between
+    // the <c> and the </c> substrings.
+
+    var dom = domNode.ownerDocument;
+    var fragment = dom.createDocumentFragment();
+    var fragmentRoot = dom.createElement("c");
+
+    fragment.appendChild(fragmentRoot);
+    // Move the children to the fragment tree.
+    for (i = 0; i < len; i++) {
+        fragmentRoot.appendChild(children[i]);
+    }
+
+    var xml = xmlSerialize(fragment);
+    xml = xml.substr(3, xml.length - 7);
+
+    // Move the children back to the original dom tree.
+    for (i = 0; i < len; i++) {
+        domNode.appendChild(fragmentRoot.childNodes[i]);
+    }
+
+    return xml;
+}
+
+/** Returns the XML representation of the node and all its descendants.
+ * @param domNode - Node to serialize
+ * @returns {String} The XML representation of the node and all its descendants.
+ */
+function xmlSerializeNode(domNode) {
+
+    var xml = domNode.xml;
+    if (xml !== undefined) {
+        return xml;
+    }
+
+    if (window.XMLSerializer) {
+        var serializer = new window.XMLSerializer();
+        return serializer.serializeToString(domNode);
+    }
+
+    throw { message: "XML serialization unsupported" };
+}
+
+exports.http = http;
+exports.w3org = w3org;
+exports.xmlNS = xmlNS;
+exports.xmlnsNS = xmlnsNS;
+
+exports.hasLeadingOrTrailingWhitespace = hasLeadingOrTrailingWhitespace;
+exports.isXmlNSDeclaration = isXmlNSDeclaration;
+exports.xmlAppendChild = xmlAppendChild;
+exports.xmlAppendChildren = xmlAppendChildren;
+exports.xmlAttributeNode = xmlAttributeNode;
+exports.xmlAttributes = xmlAttributes;
+exports.xmlAttributeValue = xmlAttributeValue;
+exports.xmlBaseURI = xmlBaseURI;
+exports.xmlChildElements = xmlChildElements;
+exports.xmlFindElementByPath = xmlFindElementByPath;
+exports.xmlFindNodeByPath = xmlFindNodeByPath;
+exports.xmlFirstChildElement = xmlFirstChildElement;
+exports.xmlFirstDescendantElement = xmlFirstDescendantElement;
+exports.xmlInnerText = xmlInnerText;
+exports.xmlLocalName = xmlLocalName;
+exports.xmlNamespaceURI = xmlNamespaceURI;
+exports.xmlNodeValue = xmlNodeValue;
+exports.xmlDom = xmlDom;
+exports.xmlNewAttribute = xmlNewAttribute;
+exports.xmlNewElement = xmlNewElement;
+exports.xmlNewFragment = xmlNewFragment;
+exports.xmlNewNodeByPath = xmlNewNodeByPath;
+exports.xmlNewNSDeclaration = xmlNewNSDeclaration;
+exports.xmlNewText = xmlNewText;
+exports.xmlParse = xmlParse;
+exports.xmlQualifiedName = xmlQualifiedName;
+exports.xmlSerialize = xmlSerialize;
+exports.xmlSerializeDescendants = xmlSerializeDescendants;
+exports.xmlSiblingElement = xmlSiblingElement;

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata.js b/odatajs/src/lib/odata.js
new file mode 100644
index 0000000..0249aa3
--- /dev/null
+++ b/odatajs/src/lib/odata.js
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+ /** @module odata */
+
+// Imports
+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');
+var odataJson     = exports.json      = require('./odata/json.js');
+                    exports.batch     = require('./odata/batch.js');
+                    
+
+
+var utils = require('./datajs/utils.js');
+var assigned = utils.assigned;
+
+var defined = utils.defined;
+var throwErrorCallback = utils.throwErrorCallback;
+
+var invokeRequest = odataUtils.invokeRequest;
+var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
+var prepareRequest = odataUtils.prepareRequest;
+var metadataParser = odataMetadata.metadataParser;
+
+// CONTENT START
+
+var handlers = [odataJson.jsonHandler, odataHandler.textHandler];
+
+/** Dispatches an operation to handlers.
+ * @param {String} handlerMethod - Name of handler method to invoke.
+ * @param {Object} requestOrResponse - request/response argument for delegated call.
+ * @param {Object} context - context argument for delegated call.
+ */
+function dispatchHandler(handlerMethod, requestOrResponse, context) {
+
+    var i, len;
+    for (i = 0, len = handlers.length; i < len && !handlers[i][handlerMethod](requestOrResponse, context); i++) {
+    }
+
+    if (i === len) {
+        throw { message: "no handler for data" };
+    }
+}
+
+/** Default success handler for OData.
+ * @param data - Data to process.
+ */
+exports.defaultSuccess = function (data) {
+
+    window.alert(window.JSON.stringify(data));
+};
+
+exports.defaultError = throwErrorCallback;
+
+exports.defaultHandler = {
+
+        /** Reads the body of the specified response by delegating to JSON handlers.
+        * @param response - Response object.
+        * @param context - Operation context.
+        */
+        read: function (response, context) {
+
+            if (response && assigned(response.body) && response.headers["Content-Type"]) {
+                dispatchHandler("read", response, context);
+            }
+        },
+
+        /** Write the body of the specified request by delegating to JSON handlers.
+        * @param request - Reques tobject.
+        * @param context - Operation context.
+        */
+        write: function (request, context) {
+
+            dispatchHandler("write", request, context);
+        },
+
+        maxDataServiceVersion: MAX_DATA_SERVICE_VERSION,
+        accept: "application/json;q=0.9, */*;q=0.1"
+    };
+
+exports.defaultMetadata = []; //TODO check why is the defaultMetadata an Array? and not an Object.
+
+/** Reads data from the specified URL.
+ * @param urlOrRequest - URL to read data from.
+ * @param {Function} [success] - 
+ * @param {Function} [error] - 
+ * @param {Object} [handler] - 
+ * @param {Object} [httpClient] - 
+ * @param {Object} [metadata] - 
+ */
+exports.read = function (urlOrRequest, success, error, handler, httpClient, metadata) {
+
+    var request;
+    if (urlOrRequest instanceof String || typeof urlOrRequest === "string") {
+        request = { requestUri: urlOrRequest };
+    } else {
+        request = urlOrRequest;
+    }
+
+    return exports.request(request, success, error, handler, httpClient, metadata);
+};
+
+/** Sends a request containing OData payload to a server.
+ * @param {Object} request - Object that represents the request to be sent.
+ * @param {Function} [success] - 
+ * @param {Function} [error] - 
+ * @param {Object} [handler] - 
+ * @param {Object} [httpClient] - 
+ * @param {Object} [metadata] - 
+ */
+exports.request = function (request, success, error, handler, httpClient, metadata) {
+
+    success = success || exports.defaultSuccess;
+    error = error || exports.defaultError;
+    handler = handler || exports.defaultHandler;
+    httpClient = httpClient || odataNet.defaultHttpClient;
+    metadata = metadata || exports.defaultMetadata;
+
+    // Augment the request with additional defaults.
+    request.recognizeDates = utils.defined(request.recognizeDates, odataJson.jsonHandler.recognizeDates);
+    request.callbackParameterName = utils.defined(request.callbackParameterName, odataNet.defaultHttpClient.callbackParameterName);
+    request.formatQueryString = utils.defined(request.formatQueryString, odataNet.defaultHttpClient.formatQueryString);
+    request.enableJsonpCallback = utils.defined(request.enableJsonpCallback, odataNet.defaultHttpClient.enableJsonpCallback);
+
+    // Create the base context for read/write operations, also specifying complete settings.
+    var context = {
+        metadata: metadata,
+        recognizeDates: request.recognizeDates,
+        callbackParameterName: request.callbackParameterName,
+        formatQueryString: request.formatQueryString,
+        enableJsonpCallback: request.enableJsonpCallback
+    };
+
+    try {
+        odataUtils.prepareRequest(request, handler, context);
+        return odataUtils.invokeRequest(request, success, error, handler, httpClient, context);
+    } catch (err) {
+        // errors in success handler for sync requests are catched here and result in error handler calls. 
+        // So here we fix this and throw that error further.
+        if (err.bIsSuccessHandlerError) {
+            throw err;
+        } else {
+            error(err);
+        }
+    }
+
+};
+
+/** Parses the csdl metadata to DataJS metatdata format. This method can be used when the metadata is retrieved using something other than DataJS
+ * @param {string} csdlMetadata - A string that represents the entire csdl metadata.
+ * @returns {Object} An object that has the representation of the metadata in Datajs format.
+ */
+exports.parseMetadata = function (csdlMetadataDocument) {
+
+    return metadataParser(null, csdlMetadataDocument);
+};
+
+// Configure the batch handler to use the default handler for the batch parts.
+exports.batch.batchHandler.partHandler = exports.defaultHandler;
+exports.metadataHandler =  odataMetadata.metadataHandler;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/batch.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/batch.js b/odatajs/src/lib/odata/batch.js
new file mode 100644
index 0000000..5b006ff
--- /dev/null
+++ b/odatajs/src/lib/odata/batch.js
@@ -0,0 +1,377 @@
+/*
+ * 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.
+ */
+
+/** @module odata/batch */
+
+var utils    = require('./../datajs.js').utils;
+var odataUtils    = require('./utils.js');
+var odataHandler = require('./handler.js');
+
+var extend = utils.extend;
+var isArray = utils.isArray;
+var trimString = utils.trimString;
+
+var contentType = odataHandler.contentType;
+var handler = odataHandler.handler;
+var isBatch = odataUtils.isBatch;
+var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
+var normalizeHeaders = odataUtils.normalizeHeaders;
+//TODO var payloadTypeOf = odata.payloadTypeOf;
+var prepareRequest = odataUtils.prepareRequest;
+
+
+
+
+
+// Imports
+
+
+
+// CONTENT START
+var batchMediaType = "multipart/mixed";
+var responseStatusRegex = /^HTTP\/1\.\d (\d{3}) (.*)$/i;
+var responseHeaderRegex = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/;
+
+/* Calculates a random 16 bit number and returns it in hexadecimal format.
+ * @returns {String} A 16-bit number in hex format.
+ */
+function hex16() {
+
+    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substr(1);
+}
+
+/* Creates a string that can be used as a multipart request boundary.
+ * @param {String} [prefix] - 
+ * @returns {String} Boundary string of the format: <prefix><hex16>-<hex16>-<hex16>
+ */
+function createBoundary(prefix) {
+
+    return prefix + hex16() + "-" + hex16() + "-" + hex16();
+}
+
+/* Gets the handler for data serialization of individual requests / responses in a batch.
+ * @param context - Context used for data serialization.
+ * @returns Handler object
+ */
+function partHandler(context) {
+
+    return context.handler.partHandler;
+}
+
+/* Gets the current boundary used for parsing the body of a multipart response.
+ * @param context - Context used for parsing a multipart response.
+ * @returns {String} Boundary string.
+ */
+function currentBoundary(context) {
+    var boundaries = context.boundaries;
+    return boundaries[boundaries.length - 1];
+}
+
+/** Parses a batch response.
+ * @param handler - This handler.
+ * @param {String} text - Batch text.
+ * @param {Object} context - Object with parsing context.
+ * @return An object representation of the batch.
+ */
+function batchParser(handler, text, context) {
+
+    var boundary = context.contentType.properties["boundary"];
+    return { __batchResponses: readBatch(text, { boundaries: [boundary], handlerContext: context }) };
+}
+
+/** Serializes a batch object representation into text.
+ * @param handler - This handler.
+ * @param {Object} data - Representation of a batch.
+ * @param {Object} context - Object with parsing context.
+ * @return An text representation of the batch object; undefined if not applicable.#
+ */
+function batchSerializer(handler, data, context) {
+
+    var cType = context.contentType = context.contentType || contentType(batchMediaType);
+    if (cType.mediaType === batchMediaType) {
+        return writeBatch(data, context);
+    }
+}
+
+/* Parses a multipart/mixed response body from from the position defined by the context.
+ * @param {String}  text - Body of the multipart/mixed response.
+ * @param context - Context used for parsing.
+ * @return Array of objects representing the individual responses.
+ */
+function readBatch(text, context) {
+    var delimiter = "--" + currentBoundary(context);
+
+    // Move beyond the delimiter and read the complete batch
+    readTo(text, context, delimiter);
+
+    // Ignore the incoming line
+    readLine(text, context);
+
+    // Read the batch parts
+    var responses = [];
+    var partEnd;
+
+    while (partEnd !== "--" && context.position < text.length) {
+        var partHeaders = readHeaders(text, context);
+        var partContentType = contentType(partHeaders["Content-Type"]);
+
+        var changeResponses;
+        if (partContentType && partContentType.mediaType === batchMediaType) {
+            context.boundaries.push(partContentType.properties.boundary);
+            try {
+                changeResponses = readBatch(text, context);
+            } catch (e) {
+                e.response = readResponse(text, context, delimiter);
+                changeResponses = [e];
+            }
+            responses.push({ __changeResponses: changeResponses });
+            context.boundaries.pop();
+            readTo(text, context, "--" + currentBoundary(context));
+        } else {
+            if (!partContentType || partContentType.mediaType !== "application/http") {
+                throw { message: "invalid MIME part type " };
+            }
+            // Skip empty line
+            readLine(text, context);
+            // Read the response
+            var response = readResponse(text, context, delimiter);
+            try {
+                if (response.statusCode >= 200 && response.statusCode <= 299) {
+                    partHandler(context.handlerContext).read(response, context.handlerContext);
+                } else {
+                    // Keep track of failed responses and continue processing the batch.
+                    response = { message: "HTTP request failed", response: response };
+                }
+            } catch (e) {
+                response = e;
+            }
+
+            responses.push(response);
+        }
+
+        partEnd = text.substr(context.position, 2);
+
+        // Ignore the incoming line.
+        readLine(text, context);
+    }
+    return responses;
+}
+
+/* Parses the http headers in the text from the position defined by the context.
+* @param {String} text - Text containing an http response's headers</param>
+* @param context - Context used for parsing.
+* @returns Object containing the headers as key value pairs.
+* This function doesn't support split headers and it will stop reading when it hits two consecutive line breaks.
+*/
+function readHeaders(text, context) {
+    var headers = {};
+    var parts;
+    var line;
+    var pos;
+
+    do {
+        pos = context.position;
+        line = readLine(text, context);
+        parts = responseHeaderRegex.exec(line);
+        if (parts !== null) {
+            headers[parts[1]] = parts[2];
+        } else {
+            // Whatever was found is not a header, so reset the context position.
+            context.position = pos;
+        }
+    } while (line && parts);
+
+    normalizeHeaders(headers);
+
+    return headers;
+}
+
+/* Parses an HTTP response.
+ * @param {String} text -Text representing the http response.
+ * @param context optional - Context used for parsing.
+ * @param {String} delimiter -String used as delimiter of the multipart response parts.
+ * @return Object representing the http response.
+ */
+function readResponse(text, context, delimiter) {
+    // Read the status line.
+    var pos = context.position;
+    var match = responseStatusRegex.exec(readLine(text, context));
+
+    var statusCode;
+    var statusText;
+    var headers;
+
+    if (match) {
+        statusCode = match[1];
+        statusText = match[2];
+        headers = readHeaders(text, context);
+        readLine(text, context);
+    } else {
+        context.position = pos;
+    }
+
+    return {
+        statusCode: statusCode,
+        statusText: statusText,
+        headers: headers,
+        body: readTo(text, context, "\r\n" + delimiter)
+    };
+}
+
+/** Returns a substring from the position defined by the context up to the next line break (CRLF).
+ * @param {String} text - Input string.
+ * @param context - Context used for reading the input string.
+ * @returns {String} Substring to the first ocurrence of a line break or null if none can be found. 
+ */
+function readLine(text, context) {
+
+    return readTo(text, context, "\r\n");
+}
+
+/** Returns a substring from the position given by the context up to value defined by the str parameter and increments the position in the context.
+ * @param {String} text - Input string.</param>
+ * @param context - Context used for reading the input string.</param>
+ * @param {String} [str] - Substring to read up to.
+ * @returns {String} Substring to the first ocurrence of str or the end of the input string if str is not specified. Null if the marker is not found.
+ */
+function readTo(text, context, str) {
+    var start = context.position || 0;
+    var end = text.length;
+    if (str) {
+        end = text.indexOf(str, start);
+        if (end === -1) {
+            return null;
+        }
+        context.position = end + str.length;
+    } else {
+        context.position = end;
+    }
+
+    return text.substring(start, end);
+}
+
+/** Serializes a batch request object to a string.
+ * @param data - Batch request object in payload representation format
+ * @param context - Context used for the serialization
+ * @returns {String} String representing the batch request
+ */
+function writeBatch(data, context) {
+    if (!isBatch(data)) {
+        throw { message: "Data is not a batch object." };
+    }
+
+    var batchBoundary = createBoundary("batch_");
+    var batchParts = data.__batchRequests;
+    var batch = "";
+    var i, len;
+    for (i = 0, len = batchParts.length; i < len; i++) {
+        batch += writeBatchPartDelimiter(batchBoundary, false) +
+                 writeBatchPart(batchParts[i], context);
+    }
+    batch += writeBatchPartDelimiter(batchBoundary, true);
+
+    // Register the boundary with the request content type.
+    var contentTypeProperties = context.contentType.properties;
+    contentTypeProperties.boundary = batchBoundary;
+
+    return batch;
+}
+
+/** Creates the delimiter that indicates that start or end of an individual request.
+ * @param {String} boundary Boundary string used to indicate the start of the request</param>
+ * @param {Boolean} close - Flag indicating that a close delimiter string should be generated
+ * @returns {String} Delimiter string
+ */
+function writeBatchPartDelimiter(boundary, close) {
+    var result = "\r\n--" + boundary;
+    if (close) {
+        result += "--";
+    }
+
+    return result + "\r\n";
+}
+
+/** Serializes a part of a batch request to a string. A part can be either a GET request or
+ * a change set grouping several CUD (create, update, delete) requests.
+ * @param part - Request or change set object in payload representation format</param>
+ * @param context - Object containing context information used for the serialization</param>
+ * @param {boolean} [nested] - 
+ * @returns {String} String representing the serialized part
+ * A change set is an array of request objects and they cannot be nested inside other change sets.
+ */
+function writeBatchPart(part, context, nested) {
+    
+
+    var changeSet = part.__changeRequests;
+    var result;
+    if (isArray(changeSet)) {
+        if (nested) {
+            throw { message: "Not Supported: change set nested in other change set" };
+        }
+
+        var changeSetBoundary = createBoundary("changeset_");
+        result = "Content-Type: " + batchMediaType + "; boundary=" + changeSetBoundary + "\r\n";
+        var i, len;
+        for (i = 0, len = changeSet.length; i < len; i++) {
+            result += writeBatchPartDelimiter(changeSetBoundary, false) +
+                 writeBatchPart(changeSet[i], context, true);
+        }
+
+        result += writeBatchPartDelimiter(changeSetBoundary, true);
+    } else {
+        result = "Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\n";
+        var partContext = extend({}, context);
+        partContext.handler = handler;
+        partContext.request = part;
+        partContext.contentType = null;
+
+        prepareRequest(part, partHandler(context), partContext);
+        result += writeRequest(part);
+    }
+
+    return result;
+}
+
+/* Serializes a request object to a string.
+ * @param request - Request object to serialize</param>
+ * @returns {String} String representing the serialized request
+ */
+function writeRequest(request) {
+    var result = (request.method ? request.method : "GET") + " " + request.requestUri + " HTTP/1.1\r\n";
+    for (var name in request.headers) {
+        if (request.headers[name]) {
+            result = result + name + ": " + request.headers[name] + "\r\n";
+        }
+    }
+
+    result += "\r\n";
+
+    if (request.body) {
+        result += request.body;
+    }
+
+    return result;
+}
+
+
+
+/** batchHandler (see {@link module:odata/batch~batchParser}) */
+exports.batchHandler = handler(batchParser, batchSerializer, batchMediaType, MAX_DATA_SERVICE_VERSION);
+exports.batchSerializer = batchSerializer;
+exports.writeRequest = writeRequest;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/handler.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/handler.js b/odatajs/src/lib/odata/handler.js
new file mode 100644
index 0000000..3e85a1e
--- /dev/null
+++ b/odatajs/src/lib/odata/handler.js
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+/** @module odata/handler */
+
+
+var utils    = require('./../datajs.js').utils;
+var oDataUtils    = require('./utils.js');
+
+// Imports.
+var assigned = utils.assigned;
+var extend = utils.extend;
+var trimString = utils.trimString;
+var maxVersion = oDataUtils.maxVersion;
+var MAX_DATA_SERVICE_VERSION = "4.0";
+
+/** Parses a string into an object with media type and properties.
+ * @param {String} str - String with media type to parse.
+ * @return null if the string is empty; an object with 'mediaType' and a 'properties' dictionary otherwise.
+ */
+function contentType(str) {
+
+    if (!str) {
+        return null;
+    }
+
+    var contentTypeParts = str.split(";");
+    var properties = {};
+
+    var i, len;
+    for (i = 1, len = contentTypeParts.length; i < len; i++) {
+        var contentTypeParams = contentTypeParts[i].split("=");
+        properties[trimString(contentTypeParams[0])] = contentTypeParams[1];
+    }
+
+    return { mediaType: trimString(contentTypeParts[0]), properties: properties };
+}
+
+/** Serializes an object with media type and properties dictionary into a string.
+ * @param contentType - Object with media type and properties dictionary to serialize.
+ * @return String representation of the media type object; undefined if contentType is null or undefined.</returns>
+ */
+function contentTypeToString(contentType) {
+    if (!contentType) {
+        return undefined;
+    }
+
+    var result = contentType.mediaType;
+    var property;
+    for (property in contentType.properties) {
+        result += ";" + property + "=" + contentType.properties[property];
+    }
+    return result;
+}
+
+/** Creates an object that is going to be used as the context for the handler's parser and serializer.
+ * @param contentType - Object with media type and properties dictionary.
+ * @param {String} dataServiceVersion - String indicating the version of the protocol to use.
+ * @param context - Operation context.
+ * @param handler - Handler object that is processing a resquest or response.
+ * @return Context object.</returns>
+ */
+function createReadWriteContext(contentType, dataServiceVersion, context, handler) {
+
+    var rwContext = {};
+    extend(rwContext, context);
+    extend(rwContext, {
+        contentType: contentType,
+        dataServiceVersion: dataServiceVersion,
+        handler: handler
+    });
+
+    return rwContext;
+}
+
+/** Sets a request header's value. If the header has already a value other than undefined, null or empty string, then this method does nothing.
+ * @param request - Request object on which the header will be set.
+ * @param {String} name - Header name.
+ * @param {String} value - Header value.
+ */
+function fixRequestHeader(request, name, value) {
+    if (!request) {
+        return;
+    }
+
+    var headers = request.headers;
+    if (!headers[name]) {
+        headers[name] = value;
+    }
+}
+
+/** Sets the DataServiceVersion header of the request if its value is not yet defined or of a lower version.
+ * @param request - Request object on which the header will be set.
+ * @param {String} version - Version value.
+ *  If the request has already a version value higher than the one supplied the this function does nothing.
+ */
+function fixDataServiceVersionHeader(request, version) {   
+
+    if (request) {
+        var headers = request.headers;
+        var dsv = headers["OData-Version"];
+        headers["OData-Version"] = dsv ? maxVersion(dsv, version) : version;
+    }
+}
+
+/** Gets the value of a request or response header.
+ * @param requestOrResponse - Object representing a request or a response.
+ * @param {String} name - Name of the header to retrieve.
+ * @returns {String} String value of the header; undefined if the header cannot be found.
+ */
+function getRequestOrResponseHeader(requestOrResponse, name) {
+
+    var headers = requestOrResponse.headers;
+    return (headers && headers[name]) || undefined;
+}
+
+/** Gets the value of the Content-Type header from a request or response.
+ * @param requestOrResponse - Object representing a request or a response.
+ * @returns {Object} Object with 'mediaType' and a 'properties' dictionary; null in case that the header is not found or doesn't have a value.
+ */
+function getContentType(requestOrResponse) {
+
+    return contentType(getRequestOrResponseHeader(requestOrResponse, "Content-Type"));
+}
+
+var versionRE = /^\s?(\d+\.\d+);?.*$/;
+/** Gets the value of the DataServiceVersion header from a request or response.
+ * @param requestOrResponse - Object representing a request or a response.
+ * @returns {String} Data service version; undefined if the header cannot be found.
+ */
+function getDataServiceVersion(requestOrResponse) {
+
+    var value = getRequestOrResponseHeader(requestOrResponse, "OData-Version");
+    if (value) {
+        var matches = versionRE.exec(value);
+        if (matches && matches.length) {
+            return matches[1];
+        }
+    }
+
+    // Fall through and return undefined.
+}
+
+/** Checks that a handler can process a particular mime type.
+ * @param handler - Handler object that is processing a resquest or response.
+ * @param cType - Object with 'mediaType' and a 'properties' dictionary.
+ * @returns {Boolean} True if the handler can process the mime type; false otherwise.
+ *
+ * The following check isn't as strict because if cType.mediaType = application/; it will match an accept value of "application/xml";
+ * however in practice we don't not expect to see such "suffixed" mimeTypes for the handlers.
+ */
+function handlerAccepts(handler, cType) {
+    return handler.accept.indexOf(cType.mediaType) >= 0;
+}
+
+/** Invokes the parser associated with a handler for reading the payload of a HTTP response.
+ * @param handler - Handler object that is processing the response.
+ * @param {Function} parseCallback - Parser function that will process the response payload.
+ * @param response - HTTP response whose payload is going to be processed.
+ * @param context - Object used as the context for processing the response.
+ * @returns {Boolean} True if the handler processed the response payload and the response.data property was set; false otherwise.
+ */
+function handlerRead(handler, parseCallback, response, context) {
+
+    if (!response || !response.headers) {
+        return false;
+    }
+
+    var cType = getContentType(response);
+    var version = getDataServiceVersion(response) || "";
+    var body = response.body;
+
+    if (!assigned(body)) {
+        return false;
+    }
+
+    if (handlerAccepts(handler, cType)) {
+        var readContext = createReadWriteContext(cType, version, context, handler);
+        readContext.response = response;
+        response.data = parseCallback(handler, body, readContext);
+        return response.data !== undefined;
+    }
+
+    return false;
+}
+
+/** Invokes the serializer associated with a handler for generating the payload of a HTTP request.
+ * @param handler - Handler object that is processing the request.
+ * @param {Function} serializeCallback - Serializer function that will generate the request payload.
+ * @param response - HTTP request whose payload is going to be generated.
+ * @param context - Object used as the context for serializing the request.
+ * @returns {Boolean} True if the handler serialized the request payload and the request.body property was set; false otherwise.
+ */
+function handlerWrite(handler, serializeCallback, request, context) {
+    if (!request || !request.headers) {
+        return false;
+    }
+
+    var cType = getContentType(request);
+    var version = getDataServiceVersion(request);
+
+    if (!cType || handlerAccepts(handler, cType)) {
+        var writeContext = createReadWriteContext(cType, version, context, handler);
+        writeContext.request = request;
+
+        request.body = serializeCallback(handler, request.data, writeContext);
+
+        if (request.body !== undefined) {
+            fixDataServiceVersionHeader(request, writeContext.dataServiceVersion || "4.0");
+
+            fixRequestHeader(request, "Content-Type", contentTypeToString(writeContext.contentType));
+            fixRequestHeader(request, "OData-MaxVersion", handler.maxDataServiceVersion);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/** Creates a handler object for processing HTTP requests and responses.
+ * @param {Function} parseCallback - Parser function that will process the response payload.
+ * @param {Function} serializeCallback - Serializer function that will generate the request payload.
+ * @param {String} accept - String containing a comma separated list of the mime types that this handler can work with.
+ * @param {String} maxDataServiceVersion - String indicating the highest version of the protocol that this handler can work with.
+ * @returns {Object} Handler object.
+ */
+function handler(parseCallback, serializeCallback, accept, maxDataServiceVersion) {
+
+    return {
+        accept: accept,
+        maxDataServiceVersion: maxDataServiceVersion,
+
+        read: function (response, context) {
+            return handlerRead(this, parseCallback, response, context);
+        },
+
+        write: function (request, context) {
+            return handlerWrite(this, serializeCallback, request, context);
+        }
+    };
+}
+
+function textParse(handler, body /*, context */) {
+    return body;
+}
+
+function textSerialize(handler, data /*, context */) {
+    if (assigned(data)) {
+        return data.toString();
+    } else {
+        return undefined;
+    }
+}
+
+
+
+
+exports.textHandler = handler(textParse, textSerialize, "text/plain", MAX_DATA_SERVICE_VERSION);
+
+exports.contentType = contentType;
+exports.contentTypeToString = contentTypeToString;
+exports.handler = handler;
+exports.createReadWriteContext = createReadWriteContext;
+exports.fixRequestHeader = fixRequestHeader;
+exports.getRequestOrResponseHeader = getRequestOrResponseHeader;
+exports.getContentType = getContentType;
+exports.getDataServiceVersion = getDataServiceVersion;
+exports.MAX_DATA_SERVICE_VERSION = MAX_DATA_SERVICE_VERSION;
\ No newline at end of file


[30/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/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
deleted file mode 100644
index 57db067..0000000
--- a/datajs/tests/odata-json-parse-tests.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!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/odatajs-4.0.0-beta-01.js"></script>   
-    <script type="text/javascript" src="common/common.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/d5ec5557/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
deleted file mode 100644
index 00f0ba2..0000000
--- a/datajs/tests/odata-json-parse-tests.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// 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,
-        };
-        odatajs.oData.read(metadataRequest, metaDatasuccess, errorFunc,OData.metadataHandler);
-    }
-
-    djstest.addTest(function test1() {
-        var checkAll = function (metadata, input, expected) {
-            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
-            djstest.assertAreEqual(info,expected, "Test context fragment: "+ input);
-        };
-
-        var checkLastTypeName = function (metadata, input, expectedKind, expectedLastTypeName) {
-            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
-            djstest.assertAreEqual(info.detectedPayloadKind,expectedKind, "Test context fragment: "+ input);
-            djstest.assertAreEqual(info.typeName,expectedLastTypeName, "Test context fragment: "+ input);
-        };
-
-        var checkProjection = function (metadata, input, expectedKind, expectedLastTypeName, projection) {
-            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
-            djstest.assertAreEqual(info.detectedPayloadKind,expectedKind, "Test context fragment: "+ input);
-            djstest.assertAreEqual(info.typeName,expectedLastTypeName, "Test context fragment: "+ input);
-            djstest.assertAreEqual(info.projection,projection, "Test context fragment: "+ input);
-        };
-
-        var checkKind = function (metadata, input, expected) {
-            var info = window.odatajs.oData.json.createPayloadInfo({ "@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
-            checkLastTypeName(metadata, '#Foods', 'f', 'DataJS.Tests.V4.Food');
-            //Chapter 10.3
-            checkLastTypeName(metadata, '#Foods/$entity', 'e', 'DataJS.Tests.V4.Food');
-            //Chapter 10.4
-            //checkKind(metadata, '#Singleton', '');
-            //Chapter 10.5
-            checkLastTypeName(metadata, '#Foods/DataJS.Tests.V4.Food', 'f', 'DataJS.Tests.V4.Food');
-            //Chapter 10.6
-            checkLastTypeName(metadata, '#Foods/DataJS.Tests.V4.Food/$entity', 'e', 'DataJS.Tests.V4.Food');
-            //Chapter 10.7
-            checkProjection(metadata, '#Foods(FoodID,Name)', 'f', 'DataJS.Tests.V4.Food','FoodID,Name');
-            //Chapter 10.8
-            checkProjection(metadata, '#Foods(FoodID,Name)/$entity', 'e', 'DataJS.Tests.V4.Food','FoodID,Name');
-            //Chapter 10.9
-            checkProjection(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))', 'f', 
-                'DataJS.Tests.V4.Food','FoodID,Name,Category,Category+(CategoryID,Name)');
-            //Chapter 10.10
-            checkProjection(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))/$entity', 'e',
-                'DataJS.Tests.V4.Food','FoodID,Name,Category,Category+(CategoryID,Name)');
-            //Chapter 10.11
-            checkKind(metadata, '#Collection($ref)', 'erls');
-            //Chapter 10.12
-            checkKind(metadata, '#$ref', 'erl');
-            //Chapter 10.13
-            checkKind(metadata, '#Foods(0)/Packaging', 'p', 'DataJS.Tests.V4.Package');
-            //Chapter 10.14
-            checkKind(metadata, '#Collection(Edm.String)', 'c',  'Edm.String');
-            //Chapter 10.15
-            checkKind(metadata, '#Edm.String', 'v');
-
-            checkKind(metadata, '#Edm.Null', 'v');
-            //TODO add tests for delta tokens
-            djstest.done();
-        };
-
-        runWithMetadata(success);
-    },'test createPayloadInfo');
-
-
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-json-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-json-tests.js b/datajs/tests/odata-json-tests.js
deleted file mode 100644
index 7d30a7c..0000000
--- a/datajs/tests/odata-json-tests.js
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-tests.js
-
-(function (window, undefined) {
-   
-    
-    djstest.addTest(function isArrayTest() {
-        console.log("hier-----------------------");
-        djstest.assert(odatajs.utils.isArray([]));
-        djstest.assert(odatajs.utils.isArray([1, 2]));
-        djstest.assert(!odatajs.utils.isArray({}));
-        djstest.assert(!odatajs.utils.isArray("1,2,3,4"));
-        djstest.assert(!odatajs.utils.isArray());
-        djstest.assert(!odatajs.utils.isArray(null));
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonParserTest() {
-        var tests = [
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: {} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata",
-                    value: [
-                      {
-                          name: "Products",
-                          kind: "EntitySet",
-                          url: "Products"
-                      },
-                      {
-                          name: "ProductDetails",
-                          kind: "EntitySet",
-                          url: "ProductDetails"
-                      }
-                  ]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    value: [
-                      {
-                          name: "Products",
-                          kind: "EntitySet",
-                          url: "http://foo/OData.svc/Products"
-                      },
-                      {
-                          name: "ProductDetails",
-                          kind: "EntitySet",
-                          url: "http://foo/OData.svc/ProductDetails"
-                      }
-                  ]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { "@odata.context": "http://foo/OData.svc/$metadata#Products(0)/Name", value: "Bread"} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
-                    value: [
-                      {
-                          "@odata.type": "#ODataDemo.Product",
-                          "@odata.id": "http://foo/OData.svc/Products(0)",
-                          "@odata.editLink": "Products(0)",
-                          "Categories@odata.navigationLink": "Products(0)/Categories",
-                          "Categories@odata.associationLink": "Products(0)/Categories/$ref",
-                          "Supplier@odata.navigationLink": "Products(0)/Supplier",
-                          "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
-                          "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
-                          "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          "ReleaseDate@odata.type": "#DateTimeOffset",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          "Rating@odata.type": "#Int16",
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
-                    value: [
-                      {
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                }
-            },
-             { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                 expected: {
-                     value: [
-                      {
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                 }
-             },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
-                      "@odata.type": "#ODataDemo.Product",
-                      "@odata.id": "http://foo/OData.svc/Products(0)",
-                      "@odata.editLink": "Products(0)",
-                      "Categories@odata.navigationLink": "Products(0)/Categories",
-                      "Categories@odata.associationLink": "Products(0)/Categories/$ref",
-                      "Supplier@odata.navigationLink": "Products(0)/Supplier",
-                      "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
-                      "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
-                      "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      "ReleaseDate@odata.type": "#DateTimeOffset",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      "Rating@odata.type": "#Int16",
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/$metadata#Customer(-10)/PrimaryContactInfo/AlternativeNames",
-                      "@odata.type": "#Collection(String)",
-                      value: [
-                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
-                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
-                      "btsnhqrjqryqzgxducl",
-                      "qbtlssjhunufmzdv",
-                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
-                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
-                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
-                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
-                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
-                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
-                     ]
-                  }
-              }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var data = JSON.stringify(tests[i].expected);
-            var actual = window.odatajs.oData.json.jsonParser(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
-            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected data");
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonSerializerTest() {
-        var tests = [
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: ""} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: []} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    ID: 0,
-                    Name: "Bread",
-                    Description: "Whole grain bread",
-                    ReleaseDate: "1992-01-01T00:00:00Z",
-                    DiscontinuedDate: null,
-                    Rating: 4,
-                    Price: 2.5
-                }
-            },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   value: [
-                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
-                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
-                      "btsnhqrjqryqzgxducl",
-                      "qbtlssjhunufmzdv",
-                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
-                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
-                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
-                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
-                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
-                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
-                     ]
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   ID: 0,
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                   "@odata.editLink": "Foods(0)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                   ID: 0,
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   value : [{
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   }]
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.editLink": "Foods(0)",
-                   value : [{
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   }]
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   ID: 0,
-                   ComplexInLayerOne:
-                   {
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 1,
-                       ComplexInLayerTwo:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 2,
-                           ComplexInLayerThree:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 3,
-                               Name: "BreadInLayer3",
-                               Description: "Whole grain bread inLayer3",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 7,
-                               Price: 5.5
-                           },
-                           Name: "BreadInLayer2",
-                           Description: "Whole grain bread inLayer2",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 6,
-                           Price: 4.5
-                       },
-                       Name: "BreadInLayer1",
-                       Description: "Whole grain bread inLayer1",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 5,
-                       Price: 3.5
-                   },
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                   "@odata.editLink": "Foods(0)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                   ID: 0,
-                   ComplexInLayerOne:
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                       ID: 1,
-                       ComplexInLayerTwo:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                           ID: 2,
-                           ComplexInLayerThree:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                               ID: 3,
-                               Name: "BreadInLayer3",
-                               Description: "Whole grain bread inLayer3",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 7,
-                               Price: 5.5
-                           },
-                           Name: "BreadInLayer2",
-                           Description: "Whole grain bread inLayer2",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 6,
-                           Price: 4.5
-                       },
-                       Name: "BreadInLayer1",
-                       Description: "Whole grain bread inLayer1",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 5,
-                       Price: 3.5
-                   },
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   value: [{
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.id": "Foods(2)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 1,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1999-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 6,
-                       Price: 3.5
-                   }]
-               },
-               data: {
-                   value: [{
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(2)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(2)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink2",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink2",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType2",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag2",
-                       ID: 1,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1999-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 6,
-                       Price: 3.5
-                   }]
-               }
-           }
-          ];
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var data = tests[i].data ? tests[i].data : tests[i].expected;
-            var actual = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
-            var expected = JSON.stringify(tests[i].expected);
-            djstest.assertAreEqualDeep(actual, expected, "test " + i + "didn't return the expected data");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function normalizeHeadersReadTest() {
-        // Verifies that headers are normalized for reading.
-        // See issue at http://datajs.codeplex.com/workitem/148
-        MockHttpClient.clear();
-
-        MockHttpClient.clear().addResponse("/foo", {
-            statusCode: 200,
-            body: { "@odata.context": "http://foo", value: [] },
-            headers: { "unknown": "u", "Content-Encoding": "compress, gzip", "Content-Length": "8042",
-                "Content-Type": "application/json", "OData-Version": "4.0", "Etag": "Vetag", "Location": "foo", "OData-EntityId": "entityId",
-                "Preference-Applied": "prefered", "Retry-After": "retry"
-            }
-        });
-
-        odatajs.oData.read("/foo", function (data, response) {
-            // djstest.assertAreEqual(data.results.length, 2, "data.results.length has two entries");
-            djstest.assertAreEqual(response.headers.unknown, "u", "u unmodified");
-            djstest.assertAreEqual(response.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
-            djstest.assertAreEqual(response.headers["Content-Length"], "8042", "Content-Length available");
-            djstest.assertAreEqual(response.headers["Content-Type"], "application/json", "Content-Type available");
-            djstest.assertAreEqual(response.headers["ETag"], "Vetag", "Content-Type available");
-            djstest.assertAreEqual(response.headers["Location"], "foo", "Content-Type available");
-            djstest.assertAreEqual(response.headers["OData-EntityId"], "entityId", "OData-EntityId available");
-            djstest.assertAreEqual(response.headers["Preference-Applied"], "prefered", "Preference-Applied available");
-            djstest.assertAreEqual(response.headers["Retry-After"], "retry", "Retry available");
-            djstest.assertAreEqual(response.headers["OData-Version"], "4.0", "OData-Version available");
-            djstest.done();
-        }, undefined, undefined, MockHttpClient);
-    });
-
-    djstest.addTest(function normalizeHeadersWriteTest() {
-
-        // Verifies that headers are normalized for writing.
-        // See issue at http://datajs.codeplex.com/workitem/148
-
-        MockHttpClient.clear().addRequestVerifier("/foo", function (request) {
-            djstest.assertAreEqual(request.headers.Accept, "application/json", "Accept available");
-            djstest.assertAreEqual(request.headers["Content-Type"], "application/json", "json found");
-            djstest.assertAreEqual(request.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
-            djstest.assertAreEqual(request.headers["Content-Length"], "8042", "Content-Length available");
-            djstest.assertAreEqual(request.headers["OData-Version"], "4.0", "OData-Version available");
-            djstest.assertAreEqual(request.headers["Accept-Charset"], "Accept-Charset", "Accept-Charset available");
-            djstest.assertAreEqual(request.headers["If-Match"], "true", "If-Match available");
-            djstest.assertAreEqual(request.headers["If-None-Match"], "false", "If-None-Match available");
-            djstest.assertAreEqual(request.headers["OData-Isolation"], "isolation", "OData-Isolation available");
-            djstest.assertAreEqual(request.headers["OData-MaxVersion"], "4.0", "OData-MaxVersion available");
-            djstest.assertAreEqual(request.headers["Prefer"], "prefer", "prefer available");
-            djstest.done();
-        });
-
-        var request = {
-            method: "POST",
-            requestUri: "/foo",
-            data: { value: 123 },
-            headers: { "Accept": "application/json", "Content-Encoding": "compress, gzip", "Content-Length": "8042", "content-type": "application/json", "OData-Version": "4.0",
-                "accept-charset": "Accept-Charset", "if-match": "true", "if-none-match": "false", "odata-isolation": "isolation",
-                "odata-maxversion": "4.0", "prefer": "prefer"
-            }
-        };
-        odatajs.oData.request(request, function (data) { }, undefined, undefined, MockHttpClient);
-
-    });
-
-    var verifyReadJsonLightDataMetadataFull = function (input, expected, message, model) {
-        var response = { 
-          headers: { 
-            "Content-Type": "application/json;odata.metadata=full",
-             DataServiceVersion: "4.0"
-          },
-          body: JSON.stringify(input) 
-        };
-
-        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-
-    var verifyReadJsonLightDataMetadataMinimal= function (input, expected, message, model) {
-        var response = { 
-          headers: { 
-            "Content-Type": "application/json;odata.metadata=minimal",
-             DataServiceVersion: "4.0"
-          },
-          body: JSON.stringify(input) 
-        };
-
-        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-    var getPointValue =  { edmType : 'GeographyPoint', value : {
-                type: "Point",
-                coordinates: [1.0, 2.0],
-                crs: {
-                    type: "Point",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-
-    var getLineStringValue =  { edmType : 'GeographyLineString', value : {
-                "type": "LineString",
-                "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
-                crs: {
-                    type: "LineString",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-
-    var getPolygonValue =  { edmType : 'GeographyPolygon', value : {
-                "type": "Polygon",
-                "coordinates": [
-                  [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
-                  [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
-                  ],
-                crs: {
-                    type: "Polygon",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-
-    var getMultiPointValue =  { edmType : 'GeographyMultiPoint', value : {
-                "type": "MultiPoint",
-                "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
-                crs: {
-                    type: "MultiPoint",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-
-    var getMultiLineStringValue =  { edmType : 'GeographyMultiLineString', value : {
-                  "type": "MultiLineString",
-                  "coordinates": [
-                      [ [100.0, 0.0], [101.0, 1.0] ],
-                      [ [102.0, 2.0], [103.0, 3.0] ]
-                    ],
-                crs: {
-                    type: "MultiLineString",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-      var getMultiPolygonStringValue =  { edmType : 'GeographyMultiPolygon', value : {
-                  "type": "MultiPolygon",
-                  "coordinates": [
-                    [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
-                    [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
-                     [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
-                    ],
-                crs: {
-                    type: "MultiPolygon",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-              }};
-
-      var getWorkload = [getPointValue, getLineStringValue, getPolygonValue, getMultiPointValue, getMultiLineStringValue, getMultiPolygonStringValue ];
-
-
-      djstest.addTest(function jsonReadGeometryPointFull() {
-
-        for ( var i = 0; i < getWorkload.length; i++) {
-          var item = getWorkload[i]; 
-          var input = {
-            "@odata.context": "http://someUri#Edm."+item.edmType,
-            "value@odata.type" : item.edmType,
-            value: item.value
-          }; 
-
-          var expected = {
-            "@odata.context": "http://someUri#Edm."+item.edmType,
-            "value@odata.type" : item.edmType,
-            value: item.value
-          };
-          verifyReadJsonLightDataMetadataFull(input, expected, "Json light top level primitive property was read properly.");
-        }
-        
-        djstest.done();
-    });
-
-
-    djstest.addTest(function jsonReadGeometryPointMinimal() {
-      for ( var i = 0; i < getWorkload.length; i++) {
-        var item = getWorkload[i]; 
-        var input = {
-            "@odata.context": "http://someUri#Edm."+item.edmType,
-            value: item.value
-        };
-
-        var expected = {
-            "@odata.context": "http://someUri#Edm."+item.edmType,
-            value: item.value,
-            "value@odata.type" : item.edmType,
-        };
-
-        verifyReadJsonLightDataMetadataMinimal(input, expected, "Json light top level primitive property was read properly.", {});
-      }
-      djstest.done();
-    });
-
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-links-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-links-functional-tests.html b/datajs/tests/odata-links-functional-tests.html
deleted file mode 100644
index 21952d8..0000000
--- a/datajs/tests/odata-links-functional-tests.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData tests against local service</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>   
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-links-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">OData.Read tests against local in-memory service</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-links-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-links-functional-tests.js b/datajs/tests/odata-links-functional-tests.js
deleted file mode 100644
index eb64ec0..0000000
--- a/datajs/tests/odata-links-functional-tests.js
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var uriRegEx = /^([^:/?#]+:)?(\/\/[^/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
-    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
-
-    var getURIInfo = function (uri) {
-        /** Gets information about the components of the specified URI.
-         * @param {String} uri - URI to get information from.
-         * @returns {Object}
-         * An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
-         */
-
-        var result = { isAbsolute: false };
-
-        if (uri) {
-            var matches = uriRegEx.exec(uri);
-            if (matches) {
-                var i, len;
-                for (i = 0, len = uriPartNames.length; i < len; i++) {
-                    if (matches[i + 1]) {
-                        result[uriPartNames[i]] = matches[i + 1];
-                    }
-                }
-            }
-            if (result.scheme) {
-                result.isAbsolute = true;
-            }
-        }
-
-        return result;
-    };
-
-    var normalizeURI = function (uri, base) {
-        /** Normalizes a possibly relative URI with a base URI.
-         * @param {String} uri - URI to normalize, absolute or relative.
-         * @param {String} base - Base URI to compose with (may be null)
-         * @returns {String} The composed URI if relative; the original one if absolute.
-         */
-
-        if (!base) {
-            return uri;
-        }
-
-        var uriInfo = getURIInfo(uri);
-        if (uriInfo.isAbsolute) {
-            return uri;
-        }
-
-        var baseInfo = getURIInfo(base);
-        var normInfo = {};
-
-        if (uriInfo.authority) {
-            normInfo.authority = uriInfo.authority;
-            normInfo.path = uriInfo.path;
-            normInfo.query = uriInfo.query;
-        } else {
-            if (!uriInfo.path) {
-                normInfo.path = baseInfo.path;
-                normInfo.query = uriInfo.query || baseInfo.query;
-            } else {
-                if (uriInfo.path.charAt(0) === '/') {
-                    normInfo.path = uriInfo.path;
-                } else {
-                    normInfo.path = mergeUriPathWithBase(uriInfo, baseInfo);
-                }
-
-                normInfo.query = uriInfo.query;
-            }
-
-            normInfo.authority = baseInfo.authority;
-        }
-
-        normInfo.scheme = baseInfo.scheme;
-        normInfo.fragment = uriInfo.fragment;
-
-        return "".concat(
-            normInfo.scheme || "",
-            normInfo.authority || "",
-            normInfo.path || "",
-            normInfo.query || "",
-            normInfo.fragment || "");
-    };
-
-    var mergeUriPathWithBase = function (uriInfo, baseInfo) {
-        /** Merges the path of a relative URI and a base URI.
-         * @param uriInfo - URI component information for the relative URI.
-         * @param baseInfo - URI component information for the base URI.
-         * @returns {String} A string with the merged path.
-         */
-
-        var basePath = "/";
-        if (baseInfo.path) {
-            var end = baseInfo.path.lastIndexOf("/");
-            basePath = baseInfo.path.substring(0, end);
-
-            if (basePath.charAt(basePath.length - 1) !== "/") {
-                basePath = basePath + "/";
-            }
-        }
-
-        return basePath + uriInfo.path;
-    };
-
-    var services = [
-        "./endpoints/FoodStoreDataServiceV4.svc"
-    ];
-
-    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
-
-    var httpStatusCode = {
-        created: 201,
-        noContent: 204,
-        notFound: 404
-    };
-
-    $.each(services, function (_, service) {
-
-        var foodsFeed = service + "/Foods";
-        var categoriesFeed = service + "/Categories";
-
-        var baseLinkUri = normalizeURI(service.substr(2), window.location.href);
-
-        var newFoodLinks = {
-            "@odata.id": baseLinkUri + "/Foods" + "(1)"
-        };
-
-        var newCategoryLinks = {
-            "@odata.id": baseLinkUri + "/Categories" + "(2)"
-        };
-
-
-        module("Functional", {
-            setup: function () {
-                djstest.wait(function (done) {
-                    $.post(service + "/ResetData", done);
-                });
-            }
-        });
-
-        var readLinksFeed = categoriesFeed + "(1)/Foods/$ref";
-        var readLinksEntry = foodsFeed + "(0)/Category/$ref";
-
-        $.each(mimeTypes, function (_, mimeType) {
-
-            var headers = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
-
-            djstest.addTest(function readValidLinksFeedTests(params) {
-                djstest.assertsExpected(1);
-                odatajs.oData.read({ requestUri: params.linksFeed, headers: headers },
-                    function (data, response) {
-                        window.ODataReadOracle.readLinksFeed(params.linksFeed,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, params.mimeType
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-            }, "Testing valid read of " + readLinksFeed + " with " + mimeType, { linksFeed: readLinksFeed, mimeType: mimeType });
-
-            djstest.addTest(function readValidLinksEntryTest(params) {
-                djstest.assertsExpected(1);
-                odatajs.oData.read({ requestUri: params.linksEntry, headers: headers },
-                    function (data, response) {
-                        window.ODataReadOracle.readLinksEntry(params.linksEntry,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, params.mimeType
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-            }, "Testing valid read of " + readLinksEntry + " with " + mimeType, { linksEntry: readLinksEntry, mimeType: mimeType });
-
-            djstest.addTest(function updateLinksEntityTest(mimeType) {
-
-                var request = {
-                    requestUri: foodsFeed + "(1)/Category/$ref",
-                    method: "PUT",
-                    headers: djstest.clone(headers),
-                    data: newCategoryLinks
-                };
-
-
-                odatajs.oData.request(request, function (data, response) {
-                    var httpOperation = request.method + " " + request.requestUri;
-                    djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
-                    ODataReadOracle.readLinksEntry(request.requestUri, function (actualData) {
-                        if (actualData && actualData["@odata.context"]) {
-                            delete actualData["@odata.context"];
-                        }
-                        
-                        djstest.assertAreEqualDeep(actualData, request.data, "Verify new links entry against the request: " + httpOperation);
-                        djstest.done();
-                    });
-                }, unexpectedErrorHandler);
-
-            }, "Update links entity (mimeType = " + mimeType + " service = " + service + ")", mimeType);
-
-            djstest.addTest(function addDeleteLinksFeedTest(mimeType) {
-
-                var request = {
-                    requestUri: categoriesFeed + "(2)/Foods/$ref",
-                    method: "POST",
-                    headers: djstest.clone(headers),
-                    data: newFoodLinks
-                };
-
-                var deleteAndVerify = function (){
-                
-                    // delete by id
-                    var deletionRequest = {
-                        requestUri: categoriesFeed + "(2)/Foods/$ref?$id=" + newFoodLinks["@odata.id"],
-                        method: "DELETE",
-                        headers: djstest.clone(headers),
-                        data: null
-                    };
-
-                    odatajs.oData.request(deletionRequest, function (data, response) {
-                        var httpOperation = deletionRequest.method + " " + deletionRequest.requestUri;
-                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
-
-                        odatajs.oData.read(request.requestUri, function (data, response) {
-                           var httpOperation = "Read " + request.requestUri;
-                           djstest.assertAreEqual(0, response.data.value.length, "Verify links against the request: " + httpOperation);
-                           djstest.done();
-                        },unexpectedErrorHandler);
-                    }, unexpectedErrorHandler);
-                };
-
-                // add
-                odatajs.oData.request(request, function (data, response) {
-
-                    var httpOperation = request.method + " " + request.requestUri;
-                    djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
-
-                    odatajs.oData.read(request.requestUri, function (data, response) {
-                        ODataReadOracle.readLinksFeed(request.requestUri, function (actualData) {
-                            djstest.assertAreEqualDeep(actualData, response.data, "Verify updated links entry against the request: " + httpOperation);
-                            deleteAndVerify();
-                        });
-                    });
-                }, unexpectedErrorHandler);
-                
-            }, "Add & Delete entity (mimeType = " + mimeType + " service = " + service + ")", mimeType);
-            
-        });
-    });
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-metadata-awareness-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-metadata-awareness-functional-tests.html b/datajs/tests/odata-metadata-awareness-functional-tests.html
deleted file mode 100644
index fc5bb0b..0000000
--- a/datajs/tests/odata-metadata-awareness-functional-tests.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>metadata awareness tests</title>
-    <meta http-equiv="cache-control" content="no-cache" />
-    <meta http-equiv="pragma" content="no-cache" />
-    <meta http-equiv="expires" content="-1" />
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>   
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-metadata-awareness-functional-tests.js"></script>
-</head>
-<body>
-    <h1 id="qunit-header">metadata awareness 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


[50/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/datajs-1.1.1.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/datajs-1.1.1.js b/datajs/demo/scripts/datajs-1.1.1.js
deleted file mode 100644
index 339b153..0000000
--- a/datajs/demo/scripts/datajs-1.1.1.js
+++ /dev/null
@@ -1,10710 +0,0 @@
-// Copyright (c) Microsoft.  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.
-
-// odatajs.js
-
-(function (window, undefined) {
-
-    var datajs = window.odatajs || {};
-    var odata = window.OData || {};
-
-    // AMD support
-    if (typeof define === 'function' && define.amd) {
-        define('datajs', datajs);
-        define('OData', odata);
-    } else {
-        window.odatajs = datajs;
-        window.OData = odata;
-    }
-
-    odatajs.version = {
-        major: 1,
-        minor: 1,
-        build: 1
-    };
-
-
-    var activeXObject = function (progId) {
-        /// <summary>Creates a new ActiveXObject from the given progId.</summary>
-        /// <param name="progId" type="String" mayBeNull="false" optional="false">
-        ///    ProgId string of the desired ActiveXObject.
-        /// </param>
-        /// <remarks>
-        ///    This function throws whatever exception might occur during the creation
-        ///    of the ActiveXObject.
-        /// </remarks>
-        /// <returns type="Object">
-        ///     The ActiveXObject instance. Null if ActiveX is not supported by the
-        ///     browser.
-        /// </returns>
-        if (window.ActiveXObject) {
-            return new window.ActiveXObject(progId);
-        }
-        return null;
-    };
-
-    var assigned = function (value) {
-        /// <summary>Checks whether the specified value is different from null and undefined.</summary>
-        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
-        /// <returns type="Boolean">true if the value is assigned; false otherwise.</returns>
-        return value !== null && value !== undefined;
-    };
-
-    var contains = function (arr, item) {
-        /// <summary>Checks whether the specified item is in the array.</summary>
-        /// <param name="arr" type="Array" optional="false" mayBeNull="false">Array to check in.</param>
-        /// <param name="item">Item to look for.</param>
-        /// <returns type="Boolean">true if the item is contained, false otherwise.</returns>
-
-        var i, len;
-        for (i = 0, len = arr.length; i < len; i++) {
-            if (arr[i] === item) {
-                return true;
-            }
-        }
-
-        return false;
-    };
-
-    var defined = function (a, b) {
-        /// <summary>Given two values, picks the first one that is not undefined.</summary>
-        /// <param name="a">First value.</param>
-        /// <param name="b">Second value.</param>
-        /// <returns>a if it's a defined value; else b.</returns>
-        return (a !== undefined) ? a : b;
-    };
-
-    var delay = function (callback) {
-        /// <summary>Delays the invocation of the specified function until execution unwinds.</summary>
-        /// <param name="callback" type="Function">Callback function.</param>
-        if (arguments.length === 1) {
-            window.setTimeout(callback, 0);
-            return;
-        }
-
-        var args = Array.prototype.slice.call(arguments, 1);
-        window.setTimeout(function () {
-            callback.apply(this, args);
-        }, 0);
-    };
-
-
-    var extend = function (target, values) {
-        /// <summary>Extends the target with the specified values.</summary>
-        /// <param name="target" type="Object">Object to add properties to.</param>
-        /// <param name="values" type="Object">Object with properties to add into target.</param>
-        /// <returns type="Object">The target object.</returns>
-
-        for (var name in values) {
-            target[name] = values[name];
-        }
-
-        return target;
-    };
-
-    var find = function (arr, callback) {
-        /// <summary>Returns the first item in the array that makes the callback function true.</summary>
-        /// <param name="arr" type="Array" optional="false" mayBeNull="true">Array to check in.</param>
-        /// <param name="callback" type="Function">Callback function to invoke once per item in the array.</param>
-        /// <returns>The first item that makes the callback return true; null otherwise or if the array is null.</returns>
-
-        if (arr) {
-            var i, len;
-            for (i = 0, len = arr.length; i < len; i++) {
-                if (callback(arr[i])) {
-                    return arr[i];
-                }
-            }
-        }
-        return null;
-    };
-
-    var isArray = function (value) {
-        /// <summary>Checks whether the specified value is an array object.</summary>
-        /// <param name="value">Value to check.</param>
-        /// <returns type="Boolean">true if the value is an array object; false otherwise.</returns>
-
-        return Object.prototype.toString.call(value) === "[object Array]";
-    };
-
-    var isDate = function (value) {
-        /// <summary>Checks whether the specified value is a Date object.</summary>
-        /// <param name="value">Value to check.</param>
-        /// <returns type="Boolean">true if the value is a Date object; false otherwise.</returns>
-
-        return Object.prototype.toString.call(value) === "[object Date]";
-    };
-
-    var isObject = function (value) {
-        /// <summary>Tests whether a value is an object.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <remarks>
-        ///     Per javascript rules, null and array values are objects and will cause this function to return true.
-        /// </remarks>
-        /// <returns type="Boolean">True is the value is an object; false otherwise.</returns>
-
-        return typeof value === "object";
-    };
-
-    var parseInt10 = function (value) {
-        /// <summary>Parses a value in base 10.</summary>
-        /// <param name="value" type="String">String value to parse.</param>
-        /// <returns type="Number">The parsed value, NaN if not a valid value.</returns>
-
-        return parseInt(value, 10);
-    };
-
-    var renameProperty = function (obj, oldName, newName) {
-        /// <summary>Renames a property in an object.</summary>
-        /// <param name="obj" type="Object">Object in which the property will be renamed.</param>
-        /// <param name="oldName" type="String">Name of the property that will be renamed.</param>
-        /// <param name="newName" type="String">New name of the property.</param>
-        /// <remarks>
-        ///    This function will not do anything if the object doesn't own a property with the specified old name.
-        /// </remarks>
-
-        if (obj.hasOwnProperty(oldName)) {
-            obj[newName] = obj[oldName];
-            delete obj[oldName];
-        }
-    };
-
-    var throwErrorCallback = function (error) {
-        /// <summary>Default error handler.</summary>
-        /// <param name="error" type="Object">Error to handle.</param>
-        throw error;
-    };
-
-    var trimString = function (str) {
-        /// <summary>Removes leading and trailing whitespaces from a string.</summary>
-        /// <param name="str" type="String" optional="false" mayBeNull="false">String to trim</param>
-        /// <returns type="String">The string with no leading or trailing whitespace.</returns>
-
-        if (str.trim) {
-            return str.trim();
-        }
-
-        return str.replace(/^\s+|\s+$/g, '');
-    };
-
-    var undefinedDefault = function (value, defaultValue) {
-        /// <summary>Returns a default value in place of undefined.</summary>
-        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
-        /// <param name="defaultValue">Value to return if value is undefined.</param>
-        /// <returns>value if it's defined; defaultValue otherwise.</returns>
-        /// <remarks>
-        /// This should only be used for cases where falsy values are valid;
-        /// otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
-        /// </remarks>
-        return (value !== undefined) ? value : defaultValue;
-    };
-
-    // Regular expression that splits a uri into its components:
-    // 0 - is the matched string.
-    // 1 - is the scheme.
-    // 2 - is the authority.
-    // 3 - is the path.
-    // 4 - is the query.
-    // 5 - is the fragment.
-    var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
-    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
-
-    var getURIInfo = function (uri) {
-        /// <summary>Gets information about the components of the specified URI.</summary>
-        /// <param name="uri" type="String">URI to get information from.</param>
-        /// <returns type="Object">
-        /// An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
-        /// </returns>
-
-        var result = { isAbsolute: false };
-
-        if (uri) {
-            var matches = uriRegEx.exec(uri);
-            if (matches) {
-                var i, len;
-                for (i = 0, len = uriPartNames.length; i < len; i++) {
-                    if (matches[i + 1]) {
-                        result[uriPartNames[i]] = matches[i + 1];
-                    }
-                }
-            }
-            if (result.scheme) {
-                result.isAbsolute = true;
-            }
-        }
-
-        return result;
-    };
-
-    var getURIFromInfo = function (uriInfo) {
-        /// <summary>Builds a URI string from its components.</summary>
-        /// <param name="uriInfo" type="Object"> An object with uri parts (scheme, authority, etc.).</param>
-        /// <returns type="String">URI string.</returns>
-
-        return "".concat(
-            uriInfo.scheme || "",
-            uriInfo.authority || "",
-            uriInfo.path || "",
-            uriInfo.query || "",
-            uriInfo.fragment || "");
-    };
-
-    // Regular expression that splits a uri authority into its subcomponents:
-    // 0 - is the matched string.
-    // 1 - is the userinfo subcomponent.
-    // 2 - is the host subcomponent.
-    // 3 - is the port component.
-    var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
-
-    // Regular expression that matches percentage enconded octects (i.e %20 or %3A);
-    var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
-
-    var normalizeURICase = function (uri) {
-        /// <summary>Normalizes the casing of a URI.</summary>
-        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
-        /// <returns type="String">The URI normalized to lower case.</returns>
-
-        var uriInfo = getURIInfo(uri);
-        var scheme = uriInfo.scheme;
-        var authority = uriInfo.authority;
-
-        if (scheme) {
-            uriInfo.scheme = scheme.toLowerCase();
-            if (authority) {
-                var matches = uriAuthorityRegEx.exec(authority);
-                if (matches) {
-                    uriInfo.authority = "//" +
-                    (matches[1] ? matches[1] + "@" : "") +
-                    (matches[2].toLowerCase()) +
-                    (matches[3] ? ":" + matches[3] : "");
-                }
-            }
-        }
-
-        uri = getURIFromInfo(uriInfo);
-
-        return uri.replace(pctEncodingRegEx, function (str) {
-            return str.toLowerCase();
-        });
-    };
-
-    var normalizeURI = function (uri, base) {
-        /// <summary>Normalizes a possibly relative URI with a base URI.</summary>
-        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
-        /// <param name="base" type="String" mayBeNull="true">Base URI to compose with.</param>
-        /// <returns type="String">The composed URI if relative; the original one if absolute.</returns>
-
-        if (!base) {
-            return uri;
-        }
-
-        var uriInfo = getURIInfo(uri);
-        if (uriInfo.isAbsolute) {
-            return uri;
-        }
-
-        var baseInfo = getURIInfo(base);
-        var normInfo = {};
-        var path;
-
-        if (uriInfo.authority) {
-            normInfo.authority = uriInfo.authority;
-            path = uriInfo.path;
-            normInfo.query = uriInfo.query;
-        } else {
-            if (!uriInfo.path) {
-                path = baseInfo.path;
-                normInfo.query = uriInfo.query || baseInfo.query;
-            } else {
-                if (uriInfo.path.charAt(0) === '/') {
-                    path = uriInfo.path;
-                } else {
-                    path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
-                }
-                normInfo.query = uriInfo.query;
-            }
-            normInfo.authority = baseInfo.authority;
-        }
-
-        normInfo.path = removeDotsFromPath(path);
-
-        normInfo.scheme = baseInfo.scheme;
-        normInfo.fragment = uriInfo.fragment;
-
-        return getURIFromInfo(normInfo);
-    };
-
-    var mergeUriPathWithBase = function (uriPath, basePath) {
-        /// <summary>Merges the path of a relative URI and a base URI.</summary>
-        /// <param name="uriPath" type="String>Relative URI path.</param>
-        /// <param name="basePath" type="String">Base URI path.</param>
-        /// <returns type="String">A string with the merged path.</returns>
-
-        var path = "/";
-        var end;
-
-        if (basePath) {
-            end = basePath.lastIndexOf("/");
-            path = basePath.substring(0, end);
-
-            if (path.charAt(path.length - 1) !== "/") {
-                path = path + "/";
-            }
-        }
-
-        return path + uriPath;
-    };
-
-    var removeDotsFromPath = function (path) {
-        /// <summary>Removes the special folders . and .. from a URI's path.</summary>
-        /// <param name="path" type="string">URI path component.</param>
-        /// <returns type="String">Path without any . and .. folders.</returns>
-
-        var result = "";
-        var segment = "";
-        var end;
-
-        while (path) {
-            if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
-                path = path.replace(/^\.\.?\/?/g, "");
-            } else if (path.indexOf("/..") === 0) {
-                path = path.replace(/^\/\..\/?/g, "/");
-                end = result.lastIndexOf("/");
-                if (end === -1) {
-                    result = "";
-                } else {
-                    result = result.substring(0, end);
-                }
-            } else if (path.indexOf("/.") === 0) {
-                path = path.replace(/^\/\.\/?/g, "/");
-            } else {
-                segment = path;
-                end = path.indexOf("/", 1);
-                if (end !== -1) {
-                    segment = path.substring(0, end);
-                }
-                result = result + segment;
-                path = path.replace(segment, "");
-            }
-        }
-        return result;
-    };
-
-    var convertByteArrayToHexString = function (str) {
-        var arr = [];
-        if (window.atob === undefined) {
-            arr = decodeBase64(str);
-        } else {
-            var binaryStr = window.atob(str);
-            for (var i = 0; i < binaryStr.length; i++) {
-                arr.push(binaryStr.charCodeAt(i));
-            }
-        }
-        var hexValue = "";
-        var hexValues = "0123456789ABCDEF";
-        for (var j = 0; j < arr.length; j++) {
-            var t = arr[j];
-            hexValue += hexValues[t >> 4];
-            hexValue += hexValues[t & 0x0F];
-        }
-        return hexValue;
-    };
-
-    var decodeBase64 = function (str) {
-        var binaryString = "";
-        for (var i = 0; i < str.length; i++) {
-            var base65IndexValue = getBase64IndexValue(str[i]);
-            var binaryValue = "";
-            if (base65IndexValue !== null) {
-                binaryValue = base65IndexValue.toString(2);
-                binaryString += addBase64Padding(binaryValue);
-            }
-        }
-        var byteArray = [];
-        var numberOfBytes = parseInt(binaryString.length / 8, 10);
-        for (i = 0; i < numberOfBytes; i++) {
-            var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
-            byteArray.push(intValue);
-        }
-        return byteArray;
-    };
-
-    var getBase64IndexValue = function (character) {
-        var asciiCode = character.charCodeAt(0);
-        var asciiOfA = 65;
-        var differenceBetweenZanda = 6;
-        if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
-            return asciiCode - asciiOfA;
-        } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
-            return asciiCode - asciiOfA - differenceBetweenZanda;
-        } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
-            return asciiCode + 4;
-        } else if (character == "+") {
-            return 62;
-        } else if (character == "/") {
-            return 63;
-        } else {
-            return null;
-        }
-    };
-
-    var addBase64Padding = function (binaryString) {
-        while (binaryString.length < 6) {
-            binaryString = "0" + binaryString;
-        }
-        return binaryString;
-    };
-
-    var getJsonValueArraryLength = function (data) {
-        if (data && data.value) {
-            return data.value.length;
-        }
-
-        return 0;
-    };
-
-    var sliceJsonValueArray = function (data, start, end) {
-        if (data == undefined || data.value == undefined) {
-            return data;
-        }
-
-        if (start < 0) {
-            start = 0;
-        }
-
-        var length = getJsonValueArraryLength(data);
-        if (length < end) {
-            end = length;
-        }
-
-        var newdata = {};
-        for (var property in data) {
-            if (property == "value") {
-                newdata[property] = data[property].slice(start, end);
-            } else {
-                newdata[property] = data[property];
-            }
-        }
-
-        return newdata;
-    };
-
-    var concatJsonValueArray = function (data, concatData) {
-        if (concatData == undefined || concatData.value == undefined) {
-            return data;
-        }
-
-        if (data == undefined || Object.keys(data).length == 0) {
-            return concatData;
-        }
-
-        if (data.value == undefined) {
-            data.value = concatData.value;
-            return data;
-        }
-
-        data.value = data.value.concat(concatData.value);
-
-        return data;
-    };
-
-
-
-    // URI prefixes to generate smaller code.
-    var http = "http://";
-    var w3org = http + "www.w3.org/";               // http://www.w3.org/
-
-    var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
-    var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
-    var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
-
-    var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
-
-    var hasLeadingOrTrailingWhitespace = function (text) {
-        /// <summary>Checks whether the specified string has leading or trailing spaces.</summary>
-        /// <param name="text" type="String">String to check.</param>
-        /// <returns type="Boolean">true if text has any leading or trailing whitespace; false otherwise.</returns>
-
-        var re = /(^\s)|(\s$)/;
-        return re.test(text);
-    };
-
-    var isWhitespace = function (text) {
-        /// <summary>Determines whether the specified text is empty or whitespace.</summary>
-        /// <param name="text" type="String">Value to inspect.</param>
-        /// <returns type="Boolean">true if the text value is empty or all whitespace; false otherwise.</returns>
-
-        var ws = /^\s*$/;
-        return text === null || ws.test(text);
-    };
-
-    var isWhitespacePreserveContext = function (domElement) {
-        /// <summary>Determines whether the specified element has xml:space='preserve' applied.</summary>
-        /// <param name="domElement">Element to inspect.</param>
-        /// <returns type="Boolean">Whether xml:space='preserve' is in effect.</returns>
-
-        while (domElement !== null && domElement.nodeType === 1) {
-            var val = xmlAttributeValue(domElement, "space", xmlNS);
-            if (val === "preserve") {
-                return true;
-            } else if (val === "default") {
-                break;
-            } else {
-                domElement = domElement.parentNode;
-            }
-        }
-
-        return false;
-    };
-
-    var isXmlNSDeclaration = function (domAttribute) {
-        /// <summary>Determines whether the attribute is a XML namespace declaration.</summary>
-        /// <param name="domAttribute">Element to inspect.</param>
-        /// <returns type="Boolean">
-        ///    True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
-        /// </returns>
-
-        var nodeName = domAttribute.nodeName;
-        return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
-    };
-
-    var safeSetProperty = function (obj, name, value) {
-        /// <summary>Safely set as property in an object by invoking obj.setProperty.</summary>
-        /// <param name="obj">Object that exposes a setProperty method.</param>
-        /// <param name="name" type="String" mayBeNull="false">Property name.</param>
-        /// <param name="value">Property value.</param>
-
-        try {
-            obj.setProperty(name, value);
-        } catch (_) { }
-    };
-
-    var msXmlDom3 = function () {
-        /// <summary>Creates an configures new MSXML 3.0 ActiveX object.</summary>
-        /// <remakrs>
-        ///    This function throws any exception that occurs during the creation
-        ///    of the MSXML 3.0 ActiveX object.
-        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
-
-        var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
-        if (msxml3) {
-            safeSetProperty(msxml3, "ProhibitDTD", true);
-            safeSetProperty(msxml3, "MaxElementDepth", 256);
-            safeSetProperty(msxml3, "AllowDocumentFunction", false);
-            safeSetProperty(msxml3, "AllowXsltScript", false);
-        }
-        return msxml3;
-    };
-
-    var msXmlDom = function () {
-        /// <summary>Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.</summary>
-        /// <remakrs>
-        ///    This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
-        ///    it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
-        ///    happens during the creation of the MSXML 6.0 will be handled by the function while
-        ///    the ones that happend during the creation of the MSXML 3.0 will be thrown.
-        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
-
-        try {
-            var msxml = activeXObject("Msxml2.DOMDocument.6.0");
-            if (msxml) {
-                msxml.async = true;
-            }
-            return msxml;
-        } catch (_) {
-            return msXmlDom3();
-        }
-    };
-
-    var msXmlParse = function (text) {
-        /// <summary>Parses an XML string using the MSXML DOM.</summary>
-        /// <remakrs>
-        ///    This function throws any exception that occurs during the creation
-        ///    of the MSXML ActiveX object.  It also will throw an exception
-        ///    in case of a parsing error.
-        /// <returns type="Object">New MSXML DOMDocument node representing the parsed XML string.</returns>
-
-        var dom = msXmlDom();
-        if (!dom) {
-            return null;
-        }
-
-        dom.loadXML(text);
-        var parseError = dom.parseError;
-        if (parseError.errorCode !== 0) {
-            xmlThrowParserError(parseError.reason, parseError.srcText, text);
-        }
-        return dom;
-    };
-
-    var xmlThrowParserError = function (exceptionOrReason, srcText, errorXmlText) {
-        /// <summary>Throws a new exception containing XML parsing error information.</summary>
-        /// <param name="exceptionOrReason">
-        ///    String indicatin the reason of the parsing failure or
-        ///    Object detailing the parsing error.
-        /// </param>
-        /// <param name="srcText" type="String">
-        ///    String indicating the part of the XML string that caused the parsing error.
-        /// </param>
-        /// <param name="errorXmlText" type="String">XML string for wich the parsing failed.</param>
-
-        if (typeof exceptionOrReason === "string") {
-            exceptionOrReason = { message: exceptionOrReason };
-        }
-        throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
-    };
-
-    var xmlParse = function (text) {
-        /// <summary>Returns an XML DOM document from the specified text.</summary>
-        /// <param name="text" type="String">Document text.</param>
-        /// <returns>XML DOM document.</returns>
-        /// <remarks>This function will throw an exception in case of a parse error.</remarks>
-
-        var domParser = window.DOMParser && new window.DOMParser();
-        var dom;
-
-        if (!domParser) {
-            dom = msXmlParse(text);
-            if (!dom) {
-                xmlThrowParserError("XML DOM parser not supported");
-            }
-            return dom;
-        }
-
-        try {
-            dom = domParser.parseFromString(text, "text/xml");
-        } catch (e) {
-            xmlThrowParserError(e, "", text);
-        }
-
-        var element = dom.documentElement;
-        var nsURI = element.namespaceURI;
-        var localName = xmlLocalName(element);
-
-        // Firefox reports errors by returing the DOM for an xml document describing the problem.
-        if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
-            var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
-            var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
-            xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
-        }
-
-        // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
-        // The error may be localized, so instead we simply check for a header as the
-        // top element or descendant child of the document.
-        if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
-            var reason = "";
-            var siblings = [];
-            var cursor = element.firstChild;
-            while (cursor) {
-                if (cursor.nodeType === 1) {
-                    reason += xmlInnerText(cursor) || "";
-                }
-                siblings.push(cursor.nextSibling);
-                cursor = cursor.firstChild || siblings.shift();
-            }
-            reason += xmlInnerText(element) || "";
-            xmlThrowParserError(reason, "", text);
-        }
-
-        return dom;
-    };
-
-    var xmlQualifiedName = function (prefix, name) {
-        /// <summary>Builds a XML qualified name string in the form of "prefix:name".</summary>
-        /// <param name="prefix" type="String" maybeNull="true">Prefix string.</param>
-        /// <param name="name" type="String">Name string to qualify with the prefix.</param>
-        /// <returns type="String">Qualified name.</returns>
-
-        return prefix ? prefix + ":" + name : name;
-    };
-
-    var xmlAppendText = function (domNode, textNode) {
-        /// <summary>Appends a text node into the specified DOM element node.</summary>
-        /// <param name="domNode">DOM node for the element.</param>
-        /// <param name="text" type="String" mayBeNull="false">Text to append as a child of element.</param>
-        if (hasLeadingOrTrailingWhitespace(textNode.data)) {
-            var attr = xmlAttributeNode(domNode, xmlNS, "space");
-            if (!attr) {
-                attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
-                xmlAppendChild(domNode, attr);
-            }
-            attr.value = "preserve";
-        }
-        domNode.appendChild(textNode);
-        return domNode;
-    };
-
-    var xmlAttributes = function (element, onAttributeCallback) {
-        /// <summary>Iterates through the XML element's attributes and invokes the callback function for each one.</summary>
-        /// <param name="element">Wrapped element to iterate over.</param>
-        /// <param name="onAttributeCallback" type="Function">Callback function to invoke with wrapped attribute nodes.</param>
-
-        var attributes = element.attributes;
-        var i, len;
-        for (i = 0, len = attributes.length; i < len; i++) {
-            onAttributeCallback(attributes.item(i));
-        }
-    };
-
-    var xmlAttributeValue = function (domNode, localName, nsURI) {
-        /// <summary>Returns the value of a DOM element's attribute.</summary>
-        /// <param name="domNode">DOM node for the owning element.</param>
-        /// <param name="localName" type="String">Local name of the attribute.</param>
-        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
-        /// <returns type="String" maybeNull="true">The attribute value, null if not found.</returns>
-
-        var attribute = xmlAttributeNode(domNode, localName, nsURI);
-        return attribute ? xmlNodeValue(attribute) : null;
-    };
-
-    var xmlAttributeNode = function (domNode, localName, nsURI) {
-        /// <summary>Gets an attribute node from a DOM element.</summary>
-        /// <param name="domNode">DOM node for the owning element.</param>
-        /// <param name="localName" type="String">Local name of the attribute.</param>
-        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
-        /// <returns>The attribute node, null if not found.</returns>
-
-        var attributes = domNode.attributes;
-        if (attributes.getNamedItemNS) {
-            return attributes.getNamedItemNS(nsURI || null, localName);
-        }
-
-        return attributes.getQualifiedItem(localName, nsURI) || null;
-    };
-
-    var xmlBaseURI = function (domNode, baseURI) {
-        /// <summary>Gets the value of the xml:base attribute on the specified element.</summary>
-        /// <param name="domNode">Element to get xml:base attribute value from.</param>
-        /// <param name="baseURI" mayBeNull="true" optional="true">Base URI used to normalize the value of the xml:base attribute.</param>
-        /// <returns type="String">Value of the xml:base attribute if found; the baseURI or null otherwise.</returns>
-
-        var base = xmlAttributeNode(domNode, "base", xmlNS);
-        return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
-    };
-
-
-    var xmlChildElements = function (domNode, onElementCallback) {
-        /// <summary>Iterates through the XML element's child DOM elements and invokes the callback function for each one.</summary>
-        /// <param name="element">DOM Node containing the DOM elements to iterate over.</param>
-        /// <param name="onElementCallback" type="Function">Callback function to invoke for each child DOM element.</param>
-
-        xmlTraverse(domNode, /*recursive*/false, function (child) {
-            if (child.nodeType === 1) {
-                onElementCallback(child);
-            }
-            // continue traversing.
-            return true;
-        });
-    };
-
-    var xmlFindElementByPath = function (root, namespaceURI, path) {
-        /// <summary>Gets the descendant element under root that corresponds to the specified path and namespace URI.</summary>
-        /// <param name="root">DOM element node from which to get the descendant element.</param>
-        /// <param name="namespaceURI" type="String">The namespace URI of the element to match.</param>
-        /// <param name="path" type="String">Path to the desired descendant element.</param>
-        /// <returns>The element specified by path and namespace URI.</returns>
-        /// <remarks>
-        ///     All the elements in the path are matched against namespaceURI.
-        ///     The function will stop searching on the first element that doesn't match the namespace and the path.
-        /// </remarks>
-
-        var parts = path.split("/");
-        var i, len;
-        for (i = 0, len = parts.length; i < len; i++) {
-            root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
-        }
-        return root || null;
-    };
-
-    var xmlFindNodeByPath = function (root, namespaceURI, path) {
-        /// <summary>Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.</summary>
-        /// <param name="root">DOM element node from which to get the descendant node.</param>
-        /// <param name="namespaceURI" type="String">The namespace URI of the node to match.</param>
-        /// <param name="path" type="String">Path to the desired descendant node.</param>
-        /// <returns>The node specified by path and namespace URI.</returns>
-        /// <remarks>
-        ///     This function will traverse the path and match each node associated to a path segement against the namespace URI.
-        ///     The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
-        ///
-        ///     The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
-        /// </remarks>
-
-        var lastSegmentStart = path.lastIndexOf("/");
-        var nodePath = path.substring(lastSegmentStart + 1);
-        var parentPath = path.substring(0, lastSegmentStart);
-
-        var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
-        if (node) {
-            if (nodePath.charAt(0) === "@") {
-                return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
-            }
-            return xmlFirstChildElement(node, namespaceURI, nodePath);
-        }
-        return null;
-    };
-
-    var xmlFirstChildElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the child DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
-    };
-
-    var xmlFirstDescendantElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        if (domNode.getElementsByTagNameNS) {
-            var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
-            return result.length > 0 ? result[0] : null;
-        }
-        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
-    };
-
-    var xmlFirstElementMaybeRecursive = function (domNode, namespaceURI, localName, recursive) {
-        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
-        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <param name="recursive" type="Boolean">
-        ///     True if the search should include all the descendants of the DOM node.
-        ///     False if the search should be scoped only to the direct children of the DOM node.
-        /// </param>
-        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
-
-        var firstElement = null;
-        xmlTraverse(domNode, recursive, function (child) {
-            if (child.nodeType === 1) {
-                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
-                var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
-
-                if (isExpectedNamespace && isExpectedNodeName) {
-                    firstElement = child;
-                }
-            }
-            return firstElement === null;
-        });
-        return firstElement;
-    };
-
-    var xmlInnerText = function (xmlElement) {
-        /// <summary>Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.</summary>
-        /// <param name="domElement">Element to get values for.</param>
-        /// <returns type="String">Text for all direct children.</returns>
-
-        var result = null;
-        var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
-        var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
-        var whitespacePreserveContext;
-
-        xmlTraverse(root, false, function (child) {
-            if (child.nodeType === 3 || child.nodeType === 4) {
-                // isElementContentWhitespace indicates that this is 'ignorable whitespace',
-                // but it's not defined by all browsers, and does not honor xml:space='preserve'
-                // in some implementations.
-                //
-                // If we can't tell either way, we walk up the tree to figure out whether
-                // xml:space is set to preserve; otherwise we discard pure-whitespace.
-                //
-                // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
-                var text = xmlNodeValue(child);
-                var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
-                if (!shouldInclude) {
-                    // Walk up the tree to figure out whether we are in xml:space='preserve' context
-                    // for the cursor (needs to happen only once).
-                    if (whitespacePreserveContext === undefined) {
-                        whitespacePreserveContext = isWhitespacePreserveContext(root);
-                    }
-
-                    shouldInclude = whitespacePreserveContext;
-                }
-
-                if (shouldInclude) {
-                    if (!result) {
-                        result = text;
-                    } else {
-                        result += text;
-                    }
-                }
-            }
-            // Continue traversing?
-            return true;
-        });
-        return result;
-    };
-
-    var xmlLocalName = function (domNode) {
-        /// <summary>Returns the localName of a XML node.</summary>
-        /// <param name="domNode">DOM node to get the value from.</param>
-        /// <returns type="String">localName of domNode.</returns>
-
-        return domNode.localName || domNode.baseName;
-    };
-
-    var xmlNamespaceURI = function (domNode) {
-        /// <summary>Returns the namespace URI of a XML node.</summary>
-        /// <param name="node">DOM node to get the value from.</param>
-        /// <returns type="String">Namespace URI of domNode.</returns>
-
-        return domNode.namespaceURI || null;
-    };
-
-    var xmlNodeValue = function (domNode) {
-        /// <summary>Returns the value or the inner text of a XML node.</summary>
-        /// <param name="node">DOM node to get the value from.</param>
-        /// <returns>Value of the domNode or the inner text if domNode represents a DOM element node.</returns>
-        
-        if (domNode.nodeType === 1) {
-            return xmlInnerText(domNode);
-        }
-        return domNode.nodeValue;
-    };
-
-    var xmlTraverse = function (domNode, recursive, onChildCallback) {
-        /// <summary>Walks through the descendants of the domNode and invokes a callback for each node.</summary>
-        /// <param name="domNode">DOM node whose descendants are going to be traversed.</param>
-        /// <param name="recursive" type="Boolean">
-        ///    True if the traversal should include all the descenants of the DOM node.
-        ///    False if the traversal should be scoped only to the direct children of the DOM node.
-        /// </param>
-        /// <returns type="String">Namespace URI of node.</returns>
-
-        var subtrees = [];
-        var child = domNode.firstChild;
-        var proceed = true;
-        while (child && proceed) {
-            proceed = onChildCallback(child);
-            if (proceed) {
-                if (recursive && child.firstChild) {
-                    subtrees.push(child.firstChild);
-                }
-                child = child.nextSibling || subtrees.shift();
-            }
-        }
-    };
-
-    var xmlSiblingElement = function (domNode, namespaceURI, localName) {
-        /// <summary>Returns the next sibling DOM element of the specified DOM node.</summary>
-        /// <param name="domNode">DOM node from which the next sibling is going to be retrieved.</param>
-        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
-        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
-        /// <returns>The node's next sibling DOM element, null if there is none.</returns>
-
-        var sibling = domNode.nextSibling;
-        while (sibling) {
-            if (sibling.nodeType === 1) {
-                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
-                var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
-
-                if (isExpectedNamespace && isExpectedNodeName) {
-                    return sibling;
-                }
-            }
-            sibling = sibling.nextSibling;
-        }
-        return null;
-    };
-
-    var xmlDom = function () {
-        /// <summary>Creates a new empty DOM document node.</summary>
-        /// <returns>New DOM document node.</returns>
-        /// <remarks>
-        ///    This function will first try to create a native DOM document using
-        ///    the browsers createDocument function.  If the browser doesn't
-        ///    support this but supports ActiveXObject, then an attempt to create
-        ///    an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
-        ///    for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
-        ///    the browser doesn't support ActiveXObject then an exception will be thrown.
-        /// </remarks>
-
-        var implementation = window.document.implementation;
-        return (implementation && implementation.createDocument) ?
-           implementation.createDocument(null, null, null) :
-           msXmlDom();
-    };
-
-    var xmlAppendChildren = function (parent, children) {
-        /// <summary>Appends a collection of child nodes or string values to a parent DOM node.</summary>
-        /// <param name="parent">DOM node to which the children will be appended.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be appended to the parent.</param>
-        /// <returns>The parent with the appended children or string values.</returns>
-        /// <remarks>
-        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
-        ///    for it and then appended to the parent.
-        /// </remarks>
-
-        if (!isArray(children)) {
-            return xmlAppendChild(parent, children);
-        }
-
-        var i, len;
-        for (i = 0, len = children.length; i < len; i++) {
-            children[i] && xmlAppendChild(parent, children[i]);
-        }
-        return parent;
-    };
-
-    var xmlAppendChild = function (parent, child) {
-        /// <summary>Appends a child node or a string value to a parent DOM node.</summary>
-        /// <param name="parent">DOM node to which the child will be appended.</param>
-        /// <param name="child">Child DOM node or string value to append to the parent.</param>
-        /// <returns>The parent with the appended child or string value.</returns>
-        /// <remarks>
-        ///    If child is a string value, then a new DOM text node is going to be created
-        ///    for it and then appended to the parent.
-        /// </remarks>
-
-        if (child) {
-            if (typeof child === "string") {
-                return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
-            }
-            if (child.nodeType === 2) {
-                parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
-            } else {
-                parent.appendChild(child);
-            }
-        }
-        return parent;
-    };
-
-    var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) {
-        /// <summary>Creates a new DOM attribute node.</summary>
-        /// <param name="dom">DOM document used to create the attribute.</param>
-        /// <param name="prefix" type="String">Namespace prefix.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI.</param>
-        /// <returns>DOM attribute node for the namespace declaration.</returns>
-
-        var attribute =
-            dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
-            dom.createNode(2, qualifiedName, namespaceURI || undefined);
-
-        attribute.value = value || "";
-        return attribute;
-    };
-
-    var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) {
-        /// <summary>Creates a new DOM element node.</summary>
-        /// <param name="dom">DOM document used to create the DOM element.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element.</param>
-        /// <param name="qualifiedName" type="String">Qualified name in the form of "prefix:name" of the new DOM element.</param>
-        /// <param name="children" type="Array" optional="true">
-        ///     Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
-        /// </param>
-        /// <returns>New DOM element.</returns>
-        /// <remarks>
-        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
-        ///    for it and then appended to the new DOM element.
-        /// </remarks>
-
-        var element =
-            dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
-            dom.createNode(1, qualifiedName, nampespaceURI || undefined);
-
-        return xmlAppendChildren(element, children || []);
-    };
-
-    var xmlNewNSDeclaration = function (dom, namespaceURI, prefix) {
-        /// <summary>Creates a namespace declaration attribute.</summary>
-        /// <param name="dom">DOM document used to create the attribute.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI.</param>
-        /// <param name="prefix" type="String">Namespace prefix.</param>
-        /// <returns>DOM attribute node for the namespace declaration.</returns>
-
-        return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
-    };
-
-    var xmlNewFragment = function (dom, text) {
-        /// <summary>Creates a new DOM document fragment node for the specified xml text.</summary>
-        /// <param name="dom">DOM document from which the fragment node is going to be created.</param>
-        /// <param name="text" type="String" mayBeNull="false">XML text to be represented by the XmlFragment.</param>
-        /// <returns>New DOM document fragment object.</returns>
-
-        var value = "<c>" + text + "</c>";
-        var tempDom = xmlParse(value);
-        var tempRoot = tempDom.documentElement;
-        var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
-        var fragment = dom.createDocumentFragment();
-
-        var importedChild = imported.firstChild;
-        while (importedChild) {
-            fragment.appendChild(importedChild);
-            importedChild = importedChild.nextSibling;
-        }
-        return fragment;
-    };
-
-    var xmlNewText = function (dom, text) {
-        /// <summary>Creates new DOM text node.</summary>
-        /// <param name="dom">DOM document used to create the text node.</param>
-        /// <param name="text" type="String">Text value for the DOM text node.</param>
-        /// <returns>DOM text node.</returns>
-
-        return dom.createTextNode(text);
-    };
-
-    var xmlNewNodeByPath = function (dom, root, namespaceURI, prefix, path) {
-        /// <summary>Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.</summary>
-        /// <param name="dom">DOM document used to create the new node.</param>
-        /// <param name="root">DOM element node used as root of the subtree on which the new nodes are going to be created.</param>
-        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element or attribute.</param>
-        /// <param name="namespacePrefix" type="String">Prefix used to qualify the name of the new DOM element or attribute.</param>
-        /// <param name="Path" type="String">Path string describing the location of the new DOM element or attribute from the root element.</param>
-        /// <returns>DOM element or attribute node for the last segment of the path.</returns>
-        /// <remarks>
-        ///     This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
-        ///     for each segment that doesn't have a matching element under root.
-        ///
-        ///     The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
-        ///     will be created.
-        /// </remarks>
-
-        var name = "";
-        var parts = path.split("/");
-        var xmlFindNode = xmlFirstChildElement;
-        var xmlNewNode = xmlNewElement;
-        var xmlNode = root;
-
-        var i, len;
-        for (i = 0, len = parts.length; i < len; i++) {
-            name = parts[i];
-            if (name.charAt(0) === "@") {
-                name = name.substring(1);
-                xmlFindNode = xmlAttributeNode;
-                xmlNewNode = xmlNewAttribute;
-            }
-
-            var childNode = xmlFindNode(xmlNode, namespaceURI, name);
-            if (!childNode) {
-                childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
-                xmlAppendChild(xmlNode, childNode);
-            }
-            xmlNode = childNode;
-        }
-        return xmlNode;
-    };
-
-    var xmlSerialize = function (domNode) {
-        /// <summary>
-        /// Returns the text representation of the document to which the specified node belongs.
-        /// </summary>
-        /// <param name="root">Wrapped element in the document to serialize.</param>
-        /// <returns type="String">Serialized document.</returns>
-
-        var xmlSerializer = window.XMLSerializer;
-        if (xmlSerializer) {
-            var serializer = new xmlSerializer();
-            return serializer.serializeToString(domNode);
-        }
-
-        if (domNode.xml) {
-            return domNode.xml;
-        }
-
-        throw { message: "XML serialization unsupported" };
-    };
-
-    var xmlSerializeDescendants = function (domNode) {
-        /// <summary>Returns the XML representation of the all the descendants of the node.</summary>
-        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
-        /// <returns type="String">The XML representation of all the descendants of the node.</returns>
-
-        var children = domNode.childNodes;
-        var i, len = children.length;
-        if (len === 0) {
-            return "";
-        }
-
-        // Some implementations of the XMLSerializer don't deal very well with fragments that
-        // don't have a DOMElement as their first child. The work around is to wrap all the
-        // nodes in a dummy root node named "c", serialize it and then just extract the text between
-        // the <c> and the </c> substrings.
-
-        var dom = domNode.ownerDocument;
-        var fragment = dom.createDocumentFragment();
-        var fragmentRoot = dom.createElement("c");
-
-        fragment.appendChild(fragmentRoot);
-        // Move the children to the fragment tree.
-        for (i = 0; i < len; i++) {
-            fragmentRoot.appendChild(children[i]);
-        }
-
-        var xml = xmlSerialize(fragment);
-        xml = xml.substr(3, xml.length - 7);
-
-        // Move the children back to the original dom tree.
-        for (i = 0; i < len; i++) {
-            domNode.appendChild(fragmentRoot.childNodes[i]);
-        }
-
-        return xml;
-    };
-
-    var xmlSerializeNode = function (domNode) {
-        /// <summary>Returns the XML representation of the node and all its descendants.</summary>
-        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
-        /// <returns type="String">The XML representation of the node and all its descendants.</returns>
-
-        var xml = domNode.xml;
-        if (xml !== undefined) {
-            return xml;
-        }
-
-        if (window.XMLSerializer) {
-            var serializer = new window.XMLSerializer();
-            return serializer.serializeToString(domNode);
-        }
-
-        throw { message: "XML serialization unsupported" };
-    };
-
-
-
-
-    var forwardCall = function (thisValue, name, returnValue) {
-        /// <summary>Creates a new function to forward a call.</summary>
-        /// <param name="thisValue" type="Object">Value to use as the 'this' object.</param>
-        /// <param name="name" type="String">Name of function to forward to.</param>
-        /// <param name="returnValue" type="Object">Return value for the forward call (helps keep identity when chaining calls).</param>
-        /// <returns type="Function">A new function that will forward a call.</returns>
-
-        return function () {
-            thisValue[name].apply(thisValue, arguments);
-            return returnValue;
-        };
-    };
-
-    var DjsDeferred = function () {
-        /// <summary>Initializes a new DjsDeferred object.</summary>
-        /// <remarks>
-        /// Compability Note A - Ordering of callbacks through chained 'then' invocations
-        ///
-        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
-        /// implies that .then() returns a distinct object.
-        ////
-        /// For compatibility with http://api.jquery.com/category/deferred-object/
-        /// we return this same object. This affects ordering, as
-        /// the jQuery version will fire callbacks in registration
-        /// order regardless of whether they occur on the result
-        /// or the original object.
-        ///
-        /// Compability Note B - Fulfillment value
-        ///
-        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
-        /// implies that the result of a success callback is the
-        /// fulfillment value of the object and is received by
-        /// other success callbacks that are chained.
-        ///
-        /// For compatibility with http://api.jquery.com/category/deferred-object/
-        /// we disregard this value instead.
-        /// </remarks>
-
-        this._arguments = undefined;
-        this._done = undefined;
-        this._fail = undefined;
-        this._resolved = false;
-        this._rejected = false;
-    };
-
-    DjsDeferred.prototype = {
-        then: function (fulfilledHandler, errorHandler /*, progressHandler */) {
-            /// <summary>Adds success and error callbacks for this deferred object.</summary>
-            /// <param name="fulfilledHandler" type="Function" mayBeNull="true" optional="true">Success callback.</param>
-            /// <param name="errorHandler" type="Function" mayBeNull="true" optional="true">Error callback.</param>
-            /// <remarks>See Compatibility Note A.</remarks>
-
-            if (fulfilledHandler) {
-                if (!this._done) {
-                    this._done = [fulfilledHandler];
-                } else {
-                    this._done.push(fulfilledHandler);
-                }
-            }
-
-            if (errorHandler) {
-                if (!this._fail) {
-                    this._fail = [errorHandler];
-                } else {
-                    this._fail.push(errorHandler);
-                }
-            }
-
-            //// See Compatibility Note A in the DjsDeferred constructor.
-            //// if (!this._next) {
-            ////    this._next = createDeferred();
-            //// }
-            //// return this._next.promise();
-
-            if (this._resolved) {
-                this.resolve.apply(this, this._arguments);
-            } else if (this._rejected) {
-                this.reject.apply(this, this._arguments);
-            }
-
-            return this;
-        },
-
-        resolve: function (/* args */) {
-            /// <summary>Invokes success callbacks for this deferred object.</summary>
-            /// <remarks>All arguments are forwarded to success callbacks.</remarks>
-
-
-            if (this._done) {
-                var i, len;
-                for (i = 0, len = this._done.length; i < len; i++) {
-                    //// See Compability Note B - Fulfillment value.
-                    //// var nextValue =
-                    this._done[i].apply(null, arguments);
-                }
-
-                //// See Compatibility Note A in the DjsDeferred constructor.
-                //// this._next.resolve(nextValue);
-                //// delete this._next;
-
-                this._done = undefined;
-                this._resolved = false;
-                this._arguments = undefined;
-            } else {
-                this._resolved = true;
-                this._arguments = arguments;
-            }
-        },
-
-        reject: function (/* args */) {
-            /// <summary>Invokes error callbacks for this deferred object.</summary>
-            /// <remarks>All arguments are forwarded to error callbacks.</remarks>
-            if (this._fail) {
-                var i, len;
-                for (i = 0, len = this._fail.length; i < len; i++) {
-                    this._fail[i].apply(null, arguments);
-                }
-
-                this._fail = undefined;
-                this._rejected = false;
-                this._arguments = undefined;
-            } else {
-                this._rejected = true;
-                this._arguments = arguments;
-            }
-        },
-
-        promise: function () {
-            /// <summary>Returns a version of this object that has only the read-only methods available.</summary>
-            /// <returns>An object with only the promise object.</returns>
-
-            var result = {};
-            result.then = forwardCall(this, "then", result);
-            return result;
-        }
-    };
-
-    var createDeferred = function () {
-        /// <summary>Creates a deferred object.</summary>
-        /// <returns type="DjsDeferred">
-        /// A new deferred object. If jQuery is installed, then a jQuery
-        /// Deferred object is returned, which provides a superset of features.
-        /// </returns>
-
-        if (window.jQuery && window.jQuery.Deferred) {
-            return new window.jQuery.Deferred();
-        } else {
-            return new DjsDeferred();
-        }
-    };
-
-
-
-
-    var dataItemTypeName = function (value, metadata) {
-        /// <summary>Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property.</summary>
-        /// <param name="value">Value of the data item from which the type name is going to be retrieved.</param>
-        /// <param name="metadata" type="object" optional="true">Object containing metadata about the data tiem.</param>
-        /// <remarks>
-        ///    This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
-        ///    it will try to recover it from the metadata.  If both attempts fail, it will return null.
-        /// </remarks>
-        /// <returns type="String">Data item type name; null if the type name cannot be found within the value or the metadata</returns>
-
-        var valueTypeName = ((value && value.__metadata) || {}).type;
-        return valueTypeName || (metadata ? metadata.type : null);
-    };
-
-    var EDM = "Edm.";
-    var EDM_BINARY = EDM + "Binary";
-    var EDM_BOOLEAN = EDM + "Boolean";
-    var EDM_BYTE = EDM + "Byte";
-    var EDM_DATETIME = EDM + "DateTime";
-    var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
-    var EDM_DECIMAL = EDM + "Decimal";
-    var EDM_DOUBLE = EDM + "Double";
-    var EDM_GUID = EDM + "Guid";
-    var EDM_INT16 = EDM + "Int16";
-    var EDM_INT32 = EDM + "Int32";
-    var EDM_INT64 = EDM + "Int64";
-    var EDM_SBYTE = EDM + "SByte";
-    var EDM_SINGLE = EDM + "Single";
-    var EDM_STRING = EDM + "String";
-    var EDM_TIME = EDM + "Time";
-
-    var EDM_GEOGRAPHY = EDM + "Geography";
-    var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
-    var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
-    var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
-    var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
-    var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
-    var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
-    var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
-
-    var EDM_GEOMETRY = EDM + "Geometry";
-    var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
-    var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
-    var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
-    var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
-    var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
-    var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
-    var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
-
-    var GEOJSON_POINT = "Point";
-    var GEOJSON_LINESTRING = "LineString";
-    var GEOJSON_POLYGON = "Polygon";
-    var GEOJSON_MULTIPOINT = "MultiPoint";
-    var GEOJSON_MULTILINESTRING = "MultiLineString";
-    var GEOJSON_MULTIPOLYGON = "MultiPolygon";
-    var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
-
-    var primitiveEdmTypes = [
-        EDM_STRING,
-        EDM_INT32,
-        EDM_INT64,
-        EDM_BOOLEAN,
-        EDM_DOUBLE,
-        EDM_SINGLE,
-        EDM_DATETIME,
-        EDM_DATETIMEOFFSET,
-        EDM_TIME,
-        EDM_DECIMAL,
-        EDM_GUID,
-        EDM_BYTE,
-        EDM_INT16,
-        EDM_SBYTE,
-        EDM_BINARY
-    ];
-
-    var geometryEdmTypes = [
-        EDM_GEOMETRY,
-        EDM_GEOMETRY_POINT,
-        EDM_GEOMETRY_LINESTRING,
-        EDM_GEOMETRY_POLYGON,
-        EDM_GEOMETRY_COLLECTION,
-        EDM_GEOMETRY_MULTIPOLYGON,
-        EDM_GEOMETRY_MULTILINESTRING,
-        EDM_GEOMETRY_MULTIPOINT
-    ];
-
-    var geographyEdmTypes = [
-        EDM_GEOGRAPHY,
-        EDM_GEOGRAPHY_POINT,
-        EDM_GEOGRAPHY_LINESTRING,
-        EDM_GEOGRAPHY_POLYGON,
-        EDM_GEOGRAPHY_COLLECTION,
-        EDM_GEOGRAPHY_MULTIPOLYGON,
-        EDM_GEOGRAPHY_MULTILINESTRING,
-        EDM_GEOGRAPHY_MULTIPOINT
-    ];
-
-    var forEachSchema = function (metadata, callback) {
-        /// <summary>Invokes a function once per schema in metadata.</summary>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <param name="callback" type="Function">Callback function to invoke once per schema.</param>
-        /// <returns>
-        /// The first truthy value to be returned from the callback; null or the last falsy value otherwise.
-        /// </returns>
-
-        if (!metadata) {
-            return null;
-        }
-
-        if (isArray(metadata)) {
-            var i, len, result;
-            for (i = 0, len = metadata.length; i < len; i++) {
-                result = forEachSchema(metadata[i], callback);
-                if (result) {
-                    return result;
-                }
-            }
-
-            return null;
-        } else {
-            if (metadata.dataServices) {
-                return forEachSchema(metadata.dataServices.schema, callback);
-            }
-
-            return callback(metadata);
-        }
-    };
-
-    var formatMilliseconds = function (ms, ns) {
-        /// <summary>Formats a millisecond and a nanosecond value into a single string.</summary>
-        /// <param name="ms" type="Number" mayBeNull="false">Number of milliseconds to format.</param>
-        /// <param name="ns" type="Number" mayBeNull="false">Number of nanoseconds to format.</param>
-        /// <returns type="String">Formatted text.</returns>
-        /// <remarks>If the value is already as string it's returned as-is.</remarks>
-
-        // Avoid generating milliseconds if not necessary.
-        if (ms === 0) {
-            ms = "";
-        } else {
-            ms = "." + formatNumberWidth(ms.toString(), 3);
-        }
-        if (ns > 0) {
-            if (ms === "") {
-                ms = ".000";
-            }
-            ms += formatNumberWidth(ns.toString(), 4);
-        }
-        return ms;
-    };
-
-    var formatDateTimeOffset = function (value) {
-        /// <summary>Formats a DateTime or DateTimeOffset value a string.</summary>
-        /// <param name="value" type="Date" mayBeNull="false">Value to format.</param>
-        /// <returns type="String">Formatted text.</returns>
-        /// <remarks>If the value is already as string it's returned as-is.</remarks>
-
-        if (typeof value === "string") {
-            return value;
-        }
-
-        var hasOffset = isDateTimeOffset(value);
-        var offset = getCanonicalTimezone(value.__offset);
-        if (hasOffset && offset !== "Z") {
-            // We're about to change the value, so make a copy.
-            value = new Date(value.valueOf());
-
-            var timezone = parseTimezone(offset);
-            var hours = value.getUTCHours() + (timezone.d * timezone.h);
-            var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
-
-            value.setUTCHours(hours, minutes);
-        } else if (!hasOffset) {
-            // Don't suffix a 'Z' for Edm.DateTime values.
-            offset = "";
-        }
-
-        var year = value.getUTCFullYear();
-        var month = value.getUTCMonth() + 1;
-        var sign = "";
-        if (year <= 0) {
-            year = -(year - 1);
-            sign = "-";
-        }
-
-        var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
-
-        return sign +
-            formatNumberWidth(year, 4) + "-" +
-            formatNumberWidth(month, 2) + "-" +
-            formatNumberWidth(value.getUTCDate(), 2) + "T" +
-            formatNumberWidth(value.getUTCHours(), 2) + ":" +
-            formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
-            formatNumberWidth(value.getUTCSeconds(), 2) +
-            ms + offset;
-    };
-
-    var formatDuration = function (value) {
-        /// <summary>Converts a duration to a string in xsd:duration format.</summary>
-        /// <param name="value" type="Object">Object with ms and __edmType properties.</param>
-        /// <returns type="String">String representation of the time object in xsd:duration format.</returns>
-
-        var ms = value.ms;
-
-        var sign = "";
-        if (ms < 0) {
-            sign = "-";
-            ms = -ms;
-        }
-
-        var days = Math.floor(ms / 86400000);
-        ms -= 86400000 * days;
-        var hours = Math.floor(ms / 3600000);
-        ms -= 3600000 * hours;
-        var minutes = Math.floor(ms / 60000);
-        ms -= 60000 * minutes;
-        var seconds = Math.floor(ms / 1000);
-        ms -= seconds * 1000;
-
-        return sign + "P" +
-               formatNumberWidth(days, 2) + "DT" +
-               formatNumberWidth(hours, 2) + "H" +
-               formatNumberWidth(minutes, 2) + "M" +
-               formatNumberWidth(seconds, 2) +
-               formatMilliseconds(ms, value.ns) + "S";
-    };
-
-    var formatNumberWidth = function (value, width, append) {
-        /// <summary>Formats the specified value to the given width.</summary>
-        /// <param name="value" type="Number">Number to format (non-negative).</param>
-        /// <param name="width" type="Number">Minimum width for number.</param>
-        /// <param name="append" type="Boolean">Flag indicating if the value is padded at the beginning (false) or at the end (true).</param>
-        /// <returns type="String">Text representation.</returns>
-        var result = value.toString(10);
-        while (result.length < width) {
-            if (append) {
-                result += "0";
-            } else {
-                result = "0" + result;
-            }
-        }
-
-        return result;
-    };
-
-    var getCanonicalTimezone = function (timezone) {
-        /// <summary>Gets the canonical timezone representation.</summary>
-        /// <param name="timezone" type="String">Timezone representation.</param>
-        /// <returns type="String">An 'Z' string if the timezone is absent or 0; the timezone otherwise.</returns>
-
-        return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
-    };
-
-    var getCollectionType = function (typeName) {
-        /// <summary>Gets the type of a collection type name.</summary>
-        /// <param name="typeName" type="String">Type name of the collection.</param>
-        /// <returns type="String">Type of the collection; null if the type name is not a collection type.</returns>
-
-        if (typeof typeName === "string") {
-            var end = typeName.indexOf(")", 10);
-            if (typeName.indexOf("Collection(") === 0 && end > 0) {
-                return typeName.substring(11, end);
-            }
-        }
-        return null;
-    };
-
-    var invokeRequest = function (request, success, error, handler, httpClient, context) {
-        /// <summary>Sends a request containing OData payload to a server.</summary>
-        /// <param name="request">Object that represents the request to be sent..</param>
-        /// <param name="success">Callback for a successful read operation.</param>
-        /// <param name="error">Callback for handling errors.</param>
-        /// <param name="handler">Handler for data serialization.</param>
-        /// <param name="httpClient">HTTP client layer.</param>
-        /// <param name="context">Context used for processing the request</param>
-
-        return httpClient.request(request, function (response) {
-            try {
-                if (response.headers) {
-                    normalizeHeaders(response.headers);
-                }
-
-                if (response.data === undefined && response.statusCode !== 204) {
-                    handler.read(response, context);
-                }
-            } catch (err) {
-                if (err.request === undefined) {
-                    err.request = request;
-                }
-                if (err.response === undefined) {
-                    err.response = response;
-                }
-                error(err);
-                return;
-            }
-
-            success(response.data, response);
-        }, error);
-    };
-
-    var isBatch = function (value) {
-        /// <summary>Tests whether a value is a batch object in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a batch object; false otherwise.</returns>
-
-        return isComplex(value) && isArray(value.__batchRequests);
-    };
-
-    // Regular expression used for testing and parsing for a collection type.
-    var collectionTypeRE = /Collection\((.*)\)/;
-
-    var isCollection = function (value, typeName) {
-        /// <summary>Tests whether a value is a collection value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
-        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
-
-        var colData = value && value.results || value;
-        return !!colData &&
-            (isCollectionType(typeName)) ||
-            (!typeName && isArray(colData) && !isComplex(colData[0]));
-    };
-
-    var isCollectionType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a collection type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is the name of a collection type; false otherwise.</returns>
-        return collectionTypeRE.test(typeName);
-    };
-
-    var isComplex = function (value) {
-        /// <summary>Tests whether a value is a complex type value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a complex type value; false otherwise.</returns>
-
-        return !!value &&
-            isObject(value) &&
-            !isArray(value) &&
-            !isDate(value);
-    };
-
-    var isDateTimeOffset = function (value) {
-        /// <summary>Checks whether a Date object is DateTimeOffset value</summary>
-        /// <param name="value" type="Date" mayBeNull="false">Value to check.</param>
-        /// <returns type="Boolean">true if the value is a DateTimeOffset, false otherwise.</returns>
-        return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
-    };
-
-    var isDeferred = function (value) {
-        /// <summary>Tests whether a value is a deferred navigation property in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a deferred navigation property; false otherwise.</returns>
-
-        if (!value && !isComplex(value)) {
-            return false;
-        }
-        var metadata = value.__metadata || {};
-        var deferred = value.__deferred || {};
-        return !metadata.type && !!deferred.uri;
-    };
-
-    var isEntry = function (value) {
-        /// <summary>Tests whether a value is an entry object in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is an entry object; false otherwise.</returns>
-
-        return isComplex(value) && value.__metadata && "uri" in value.__metadata;
-    };
-
-    var isFeed = function (value, typeName) {
-        /// <summary>Tests whether a value is a feed value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
-        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
-
-        var feedData = value && value.results || value;
-        return isArray(feedData) && (
-            (!isCollectionType(typeName)) &&
-            (isComplex(feedData[0]))
-        );
-    };
-
-    var isGeographyEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a geography EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a geography EDM type; false otherwise.</returns>
-
-        return contains(geographyEdmTypes, typeName);
-    };
-
-    var isGeometryEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a geometry EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a geometry EDM type; false otherwise.</returns>
-
-        return contains(geometryEdmTypes, typeName);
-    };
-
-    var isNamedStream = function (value) {
-        /// <summary>Tests whether a value is a named stream value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <returns type="Boolean">True is the value is a named stream; false otherwise.</returns>
-
-        if (!value && !isComplex(value)) {
-            return false;
-        }
-        var metadata = value.__metadata;
-        var mediaResource = value.__mediaresource;
-        return !metadata && !!mediaResource && !!mediaResource.media_src;
-    };
-
-    var isPrimitive = function (value) {
-        /// <summary>Tests whether a value is a primitive type value in the library's internal representation.</summary>
-        /// <param name="value">Value to test.</param>
-        /// <remarks>
-        ///    Date objects are considered primitive types by the library.
-        /// </remarks>
-        /// <returns type="Boolean">True is the value is a primitive type value.</returns>
-
-        return isDate(value) ||
-            typeof value === "string" ||
-            typeof value === "number" ||
-            typeof value === "boolean";
-    };
-
-    var isPrimitiveEdmType = function (typeName) {
-        /// <summary>Checks whether the specified type name is a primitive EDM type.</summary>
-        /// <param name="typeName" type="String">Name of type to check.</param>
-        /// <returns type="Boolean">True if the type is a primitive EDM type; false otherwise.</returns>
-
-        return contains(primitiveEdmTypes, typeName);
-    };
-
-    var navigationPropertyKind = function (value, propertyModel) {
-        /// <summary>Gets the kind of a navigation property value.</summary>
-        /// <param name="value">Value of the navigation property.</param>
-        /// <param name="propertyModel" type="Object" optional="true">
-        ///     Object that describes the navigation property in an OData conceptual schema.
-        /// </param>
-        /// <remarks>
-        ///     The returned string is as follows
-        /// </remarks>
-        /// <returns type="String">String value describing the kind of the navigation property; null if the kind cannot be determined.</returns>
-
-        if (isDeferred(value)) {
-            return "deferred";
-        }
-        if (isEntry(value)) {
-            return "entry";
-        }
-        if (isFeed(value)) {
-            return "feed";
-        }
-        if (propertyModel && propertyModel.relationship) {
-            if (value === null || value === undefined || !isFeed(value)) {
-                return "entry";
-            }
-            return "feed";
-        }
-        return null;
-    };
-
-    var lookupProperty = function (properties, name) {
-        /// <summary>Looks up a property by name.</summary>
-        /// <param name="properties" type="Array" mayBeNull="true">Array of property objects as per EDM metadata.</param>
-        /// <param name="name" type="String">Name to look for.</param>
-        /// <returns type="Object">The property object; null if not found.</returns>
-
-        return find(properties, function (property) {
-            return property.name === name;
-        });
-    };
-
-    var lookupInMetadata = function (name, metadata, kind) {
-        /// <summary>Looks up a type object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
-        /// <returns>An type description if the name is found; null otherwise.</returns>
-
-        return (name) ? forEachSchema(metadata, function (schema) {
-            return lookupInSchema(name, schema, kind);
-        }) : null;
-    };
-
-    var lookupEntitySet = function (entitySets, 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(entitySets, function (entitySet) {
-            return entitySet.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>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>A complex type description if the name is found; null otherwise.</returns>
-
-        return lookupInMetadata(name, metadata, "complexType");
-    };
-
-    var lookupEntityType = function (name, metadata) {
-        /// <summary>Looks up an entity type object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity type description if the name is found; null otherwise.</returns>
-
-        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>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity container description if the name is found; null otherwise.</returns>
-
-        return forEachSchema(metadata, function (schema) {
-            return find(schema.entityContainer, function (container) {
-                return parseBool(container.isDefaultEntityContainer);
-            });
-        });
-    };
-
-    var lookupEntityContainer = function (name, metadata) {
-        /// <summary>Looks up an entity container object by name.</summary>
-        /// <param name="name" type="String">Name, possibly null or empty.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <returns>An entity container description if the name is found; null otherwise.</returns>
-
-        return lookupInMetadata(name, metadata, "entityContainer");
-    };
-
-    var lookupFunctionImport = function (functionImports, name) {
-        /// <summary>Looks up a function import by name.</summary>
-        /// <param name="properties" type="Array" mayBeNull="true">Array of function import 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(functionImports, function (functionImport) {
-            return functionImport.name === name;
-        });
-    };
-
-    var lookupNavigationPropertyType = function (navigationProperty, metadata) {
-        /// <summary>Looks up the target entity type for a navigation property.</summary>
-        /// <param name="navigationProperty" type="Object"></param>
-        /// <param name="metadata" type="Object"></param>
-        /// <returns type="String">The entity type name for the specified property, null if not found.</returns>
-
-        var result = null;
-        if (navigationProperty) {
-            var rel = navigationProperty.relationship;
-            var association = forEachSchema(metadata, function (schema) {
-                // The name should be the namespace qualified name in 'ns'.'type' format.
-                var nameOnly = removeNamespace(schema["namespace"], rel);
-                var associations = schema.association;
-                if (nameOnly && associations) {
-                    var i, len;
-                    for (i = 0, len = associations.length; i < len; i++) {
-                        if (associations[i].name === nameOnly) {
-                            return associations[i];
-                        }
-                    }
-                }
-                return null;
-            });
-
-            if (association) {
-                var end = association.end[0];
-                if (end.role !== navigationProperty.toRole) {
-                    end = association.end[1];
-                    // For metadata to be valid, end.role === navigationProperty.toRole now.
-                }
-                result = end.type;
-            }
-        }
-        return result;
-    };
-
-    var lookupNavigationPropertyEntitySet = function (navigationProperty, sourceEntitySetName, metadata) {
-        /// <summary>Looks up the target entityset name for a navigation property.</summary>
-        /// <param name="navigationProperty" type="Object"></param>
-        /// <param name="metadata" type="Object"></param>
-        /// <returns type="String">The entityset name for the specified property, null if not found.</returns>
-
-        if (navigationProperty) {
-            var rel = navigationProperty.relationship;
-            var associationSet = forEachSchema(metadata, function (schema) {
-                var containers = schema.entity

<TRUNCATED>

[17/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/utils.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/utils.js b/odatajs/src/lib/odata/utils.js
new file mode 100644
index 0000000..efaea05
--- /dev/null
+++ b/odatajs/src/lib/odata/utils.js
@@ -0,0 +1,1261 @@
+/*
+ * 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.
+ */
+ /** @module odata/utils */
+
+var utils    = require('./../datajs.js').utils;
+
+// Imports
+var assigned = utils.assigned;
+var contains = utils.contains;
+var find = utils.find;
+var isArray = utils.isArray;
+var isDate = utils.isDate;
+var isObject = utils.isObject;
+var parseInt10 = utils.parseInt10;
+
+
+/** Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property
+ * @param {string} value - Value of the data item from which the type name is going to be retrieved.
+ * @param {object} [metadata] - Object containing metadata about the data tiem.
+ * @returns {string} Data item type name; null if the type name cannot be found within the value or the metadata
+ * This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
+ * it will try to recover it from the metadata.  If both attempts fail, it will return null.
+ */
+var dataItemTypeName = function (value, metadata) {
+    var valueTypeName = ((value && value.__metadata) || {}).type;
+    return valueTypeName || (metadata ? metadata.type : null);
+};
+
+var EDM = "Edm.";
+var EDM_BINARY = EDM + "Binary";
+var EDM_BOOLEAN = EDM + "Boolean";
+var EDM_BYTE = EDM + "Byte";
+var EDM_DATETIME = EDM + "DateTime";
+var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
+var EDM_DECIMAL = EDM + "Decimal";
+var EDM_DOUBLE = EDM + "Double";
+var EDM_GUID = EDM + "Guid";
+var EDM_INT16 = EDM + "Int16";
+var EDM_INT32 = EDM + "Int32";
+var EDM_INT64 = EDM + "Int64";
+var EDM_SBYTE = EDM + "SByte";
+var EDM_SINGLE = EDM + "Single";
+var EDM_STRING = EDM + "String";
+var EDM_TIME = EDM + "Time";
+
+var GEOGRAPHY = "Geography";
+var EDM_GEOGRAPHY = EDM + GEOGRAPHY;
+var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
+var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
+var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
+var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
+var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
+var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
+var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
+
+var GEOGRAPHY_POINT = GEOGRAPHY + "Point";
+var GEOGRAPHY_LINESTRING = GEOGRAPHY + "LineString";
+var GEOGRAPHY_POLYGON = GEOGRAPHY + "Polygon";
+var GEOGRAPHY_COLLECTION = GEOGRAPHY + "Collection";
+var GEOGRAPHY_MULTIPOLYGON = GEOGRAPHY + "MultiPolygon";
+var GEOGRAPHY_MULTILINESTRING = GEOGRAPHY + "MultiLineString";
+var GEOGRAPHY_MULTIPOINT = GEOGRAPHY + "MultiPoint";
+
+var GEOMETRY = "Geometry";
+var EDM_GEOMETRY = EDM + GEOMETRY;
+var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
+var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
+var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
+var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
+var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
+var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
+var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
+
+var GEOMETRY_POINT = GEOMETRY + "Point";
+var GEOMETRY_LINESTRING = GEOMETRY + "LineString";
+var GEOMETRY_POLYGON = GEOMETRY + "Polygon";
+var GEOMETRY_COLLECTION = GEOMETRY + "Collection";
+var GEOMETRY_MULTIPOLYGON = GEOMETRY + "MultiPolygon";
+var GEOMETRY_MULTILINESTRING = GEOMETRY + "MultiLineString";
+var GEOMETRY_MULTIPOINT = GEOMETRY + "MultiPoint";
+
+var GEOJSON_POINT = "Point";
+var GEOJSON_LINESTRING = "LineString";
+var GEOJSON_POLYGON = "Polygon";
+var GEOJSON_MULTIPOINT = "MultiPoint";
+var GEOJSON_MULTILINESTRING = "MultiLineString";
+var GEOJSON_MULTIPOLYGON = "MultiPolygon";
+var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
+
+var primitiveEdmTypes = [
+    EDM_STRING,
+    EDM_INT32,
+    EDM_INT64,
+    EDM_BOOLEAN,
+    EDM_DOUBLE,
+    EDM_SINGLE,
+    EDM_DATETIME,
+    EDM_DATETIMEOFFSET,
+    EDM_TIME,
+    EDM_DECIMAL,
+    EDM_GUID,
+    EDM_BYTE,
+    EDM_INT16,
+    EDM_SBYTE,
+    EDM_BINARY
+];
+
+var geometryEdmTypes = [
+    EDM_GEOMETRY,
+    EDM_GEOMETRY_POINT,
+    EDM_GEOMETRY_LINESTRING,
+    EDM_GEOMETRY_POLYGON,
+    EDM_GEOMETRY_COLLECTION,
+    EDM_GEOMETRY_MULTIPOLYGON,
+    EDM_GEOMETRY_MULTILINESTRING,
+    EDM_GEOMETRY_MULTIPOINT
+];
+
+var geometryTypes = [
+    GEOMETRY,
+    GEOMETRY_POINT,
+    GEOMETRY_LINESTRING,
+    GEOMETRY_POLYGON,
+    GEOMETRY_COLLECTION,
+    GEOMETRY_MULTIPOLYGON,
+    GEOMETRY_MULTILINESTRING,
+    GEOMETRY_MULTIPOINT
+];
+
+var geographyEdmTypes = [
+    EDM_GEOGRAPHY,
+    EDM_GEOGRAPHY_POINT,
+    EDM_GEOGRAPHY_LINESTRING,
+    EDM_GEOGRAPHY_POLYGON,
+    EDM_GEOGRAPHY_COLLECTION,
+    EDM_GEOGRAPHY_MULTIPOLYGON,
+    EDM_GEOGRAPHY_MULTILINESTRING,
+    EDM_GEOGRAPHY_MULTIPOINT
+];
+
+var geographyTypes = [
+    GEOGRAPHY,
+    GEOGRAPHY_POINT,
+    GEOGRAPHY_LINESTRING,
+    GEOGRAPHY_POLYGON,
+    GEOGRAPHY_COLLECTION,
+    GEOGRAPHY_MULTIPOLYGON,
+    GEOGRAPHY_MULTILINESTRING,
+    GEOGRAPHY_MULTIPOINT
+];
+
+/** Invokes a function once per schema in metadata.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @param {Function} callback - Callback function to invoke once per schema.
+ * @returns The first truthy value to be returned from the callback; null or the last falsy value otherwise.
+ */
+function forEachSchema(metadata, callback) {
+    
+
+    if (!metadata) {
+        return null;
+    }
+
+    if (isArray(metadata)) {
+        var i, len, result;
+        for (i = 0, len = metadata.length; i < len; i++) {
+            result = forEachSchema(metadata[i], callback);
+            if (result) {
+                return result;
+            }
+        }
+
+        return null;
+    } else {
+        if (metadata.dataServices) {
+            return forEachSchema(metadata.dataServices.schema, callback);
+        }
+
+        return callback(metadata);
+    }
+}
+
+/** Formats a millisecond and a nanosecond value into a single string.
+ * @param {Numaber} ms - Number of milliseconds to format.</param>
+ * @param {Numaber} ns - Number of nanoseconds to format.</param>
+ * @returns {String} Formatted text.
+ * If the value is already as string it's returned as-is.</remarks>
+ */
+function formatMilliseconds(ms, ns) {
+
+    // Avoid generating milliseconds if not necessary.
+    if (ms === 0) {
+        ms = "";
+    } else {
+        ms = "." + formatNumberWidth(ms.toString(), 3);
+    }
+    if (ns > 0) {
+        if (ms === "") {
+            ms = ".000";
+        }
+        ms += formatNumberWidth(ns.toString(), 4);
+    }
+    return ms;
+}
+
+function formatDateTimeOffsetJSON(value) {
+    return "\/Date(" + value.getTime() + ")\/";
+}
+
+/** Formats a DateTime or DateTimeOffset value a string.
+ * @param {Date} value - Value to format
+ * @returns {String} Formatted text.
+ * If the value is already as string it's returned as-is
+´*/
+function formatDateTimeOffset(value) {
+
+    if (typeof value === "string") {
+        return value;
+    }
+
+    var hasOffset = isDateTimeOffset(value);
+    var offset = getCanonicalTimezone(value.__offset);
+    if (hasOffset && offset !== "Z") {
+        // We're about to change the value, so make a copy.
+        value = new Date(value.valueOf());
+
+        var timezone = parseTimezone(offset);
+        var hours = value.getUTCHours() + (timezone.d * timezone.h);
+        var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
+
+        value.setUTCHours(hours, minutes);
+    } else if (!hasOffset) {
+        // Don't suffix a 'Z' for Edm.DateTime values.
+        offset = "";
+    }
+
+    var year = value.getUTCFullYear();
+    var month = value.getUTCMonth() + 1;
+    var sign = "";
+    if (year <= 0) {
+        year = -(year - 1);
+        sign = "-";
+    }
+
+    var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
+
+    return sign +
+        formatNumberWidth(year, 4) + "-" +
+        formatNumberWidth(month, 2) + "-" +
+        formatNumberWidth(value.getUTCDate(), 2) + "T" +
+        formatNumberWidth(value.getUTCHours(), 2) + ":" +
+        formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
+        formatNumberWidth(value.getUTCSeconds(), 2) +
+        ms + offset;
+}
+
+/** Converts a duration to a string in xsd:duration format.
+ * @param {Object} value - Object with ms and __edmType properties.
+ * @returns {String} String representation of the time object in xsd:duration format.
+ */
+function formatDuration(value) {
+
+    var ms = value.ms;
+
+    var sign = "";
+    if (ms < 0) {
+        sign = "-";
+        ms = -ms;
+    }
+
+    var days = Math.floor(ms / 86400000);
+    ms -= 86400000 * days;
+    var hours = Math.floor(ms / 3600000);
+    ms -= 3600000 * hours;
+    var minutes = Math.floor(ms / 60000);
+    ms -= 60000 * minutes;
+    var seconds = Math.floor(ms / 1000);
+    ms -= seconds * 1000;
+
+    return sign + "P" +
+           formatNumberWidth(days, 2) + "DT" +
+           formatNumberWidth(hours, 2) + "H" +
+           formatNumberWidth(minutes, 2) + "M" +
+           formatNumberWidth(seconds, 2) +
+           formatMilliseconds(ms, value.ns) + "S";
+}
+
+/** Formats the specified value to the given width.
+ * @param {Number} value - Number to format (non-negative).
+ * @param {Number} width - Minimum width for number.
+ * @param {Boolean} append - Flag indicating if the value is padded at the beginning (false) or at the end (true).
+ * @returns {String} Text representation.
+ */
+function formatNumberWidth(value, width, append) {
+    var result = value.toString(10);
+    while (result.length < width) {
+        if (append) {
+            result += "0";
+        } else {
+            result = "0" + result;
+        }
+    }
+
+    return result;
+}
+
+/** Gets the canonical timezone representation.
+ * @param {String} timezone - Timezone representation.
+ * @returns {String} An 'Z' string if the timezone is absent or 0; the timezone otherwise.
+ */
+function getCanonicalTimezone(timezone) {
+
+    return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
+}
+
+/** Gets the type of a collection type name.
+ * @param {String} typeName - Type name of the collection.
+ * @returns {String} Type of the collection; null if the type name is not a collection type.
+ */
+function getCollectionType(typeName) {
+
+    if (typeof typeName === "string") {
+        var end = typeName.indexOf(")", 10);
+        if (typeName.indexOf("Collection(") === 0 && end > 0) {
+            return typeName.substring(11, end);
+        }
+    }
+    return null;
+}
+
+/** Sends a request containing OData payload to a server.
+* @param request - Object that represents the request to be sent..
+* @param success - Callback for a successful read operation.
+* @param error - Callback for handling errors.
+* @param handler - Handler for data serialization.
+* @param httpClient - HTTP client layer.
+* @param context - Context used for processing the request
+*/
+function invokeRequest(request, success, error, handler, httpClient, context) {
+
+    return httpClient.request(request, function (response) {
+        try {
+            if (response.headers) {
+                normalizeHeaders(response.headers);
+            }
+
+            if (response.data === undefined && response.statusCode !== 204) {
+                handler.read(response, context);
+            }
+        } catch (err) {
+            if (err.request === undefined) {
+                err.request = request;
+            }
+            if (err.response === undefined) {
+                err.response = response;
+            }
+            error(err);
+            return;
+        }
+        // errors in success handler for sync requests result in error handler calls. So here we fix this. 
+        try {
+            success(response.data, response);
+        } catch (err) {
+            err.bIsSuccessHandlerError = true;
+            throw err;
+        }
+    }, error);
+}
+
+/** Tests whether a value is a batch object in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is a batch object; false otherwise.
+ */
+function isBatch(value) {
+
+    return isComplex(value) && isArray(value.__batchRequests);
+}
+
+// Regular expression used for testing and parsing for a collection type.
+var collectionTypeRE = /Collection\((.*)\)/;
+
+/** Tests whether a value is a collection value in the library's internal representation.
+ * @param value - Value to test.
+ * @param {Sting} typeName - Type name of the value. This is used to disambiguate from a collection property value.
+ * @returns {Boolean} True is the value is a feed value; false otherwise.
+ */
+function isCollection(value, typeName) {
+
+    var colData = value && value.results || value;
+    return !!colData &&
+        (isCollectionType(typeName)) ||
+        (!typeName && isArray(colData) && !isComplex(colData[0]));
+}
+
+/** Checks whether the specified type name is a collection type.
+ * @param {String} typeName - Name of type to check.
+ * @returns {Boolean} True if the type is the name of a collection type; false otherwise.
+ */
+function isCollectionType(typeName) {
+    return collectionTypeRE.test(typeName);
+}
+
+/** Tests whether a value is a complex type value in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is a complex type value; false otherwise.
+ */
+function isComplex(value) {
+
+    return !!value &&
+        isObject(value) &&
+        !isArray(value) &&
+        !isDate(value);
+}
+
+/** Checks whether a Date object is DateTimeOffset value
+ * @param {Date} value - Value to check
+ * @returns {Boolean} true if the value is a DateTimeOffset, false otherwise.
+ */
+function isDateTimeOffset(value) {
+    return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
+}
+
+/** Tests whether a value is a deferred navigation property in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is a deferred navigation property; false otherwise.
+ */
+function isDeferred(value) {
+
+    if (!value && !isComplex(value)) {
+        return false;
+    }
+    var metadata = value.__metadata || {};
+    var deferred = value.__deferred || {};
+    return !metadata.type && !!deferred.uri;
+}
+
+/** Tests whether a value is an entry object in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is an entry object; false otherwise.
+ */
+function isEntry(value) {
+
+    return isComplex(value) && value.__metadata && "uri" in value.__metadata;
+}
+
+/** Tests whether a value is a feed value in the library's internal representation.
+ * @param value - Value to test.
+ * @param {Sting} typeName - Type name of the value. This is used to disambiguate from a collection property value.
+ * @returns {Boolean} True is the value is a feed value; false otherwise.
+ */
+function isFeed(value, typeName) {
+
+    var feedData = value && value.results || value;
+    return isArray(feedData) && (
+        (!isCollectionType(typeName)) &&
+        (isComplex(feedData[0]))
+    );
+}
+
+/** Checks whether the specified type name is a geography EDM type.
+ * @param {String} typeName - Name of type to check.
+ * @returns {Boolean} True if the type is a geography EDM type; false otherwise.
+ */
+function isGeographyEdmType(typeName) {
+
+    //check with edm
+    var ret = contains(geographyEdmTypes, typeName) || 
+        (typeName.indexOf('.') === -1 && contains(geographyTypes, typeName));
+    return ret; 
+        
+}
+
+/** Checks whether the specified type name is a geometry EDM type.
+ * @param {String} typeName - Name of type to check.
+ * @returns {Boolean} True if the type is a geometry EDM type; false otherwise.
+ */
+function isGeometryEdmType(typeName) {
+
+    var ret = contains(geometryEdmTypes, typeName) ||
+        (typeName.indexOf('.') === -1 && contains(geometryTypes, typeName));
+    return ret; 
+}
+
+/** Tests whether a value is a named stream value in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is a named stream; false otherwise.
+ */
+function isNamedStream(value) {
+
+    if (!value && !isComplex(value)) {
+        return false;
+    }
+    var metadata = value.__metadata;
+    var mediaResource = value.__mediaresource;
+    return !metadata && !!mediaResource && !!mediaResource.media_src;
+}
+
+/** Tests whether a value is a primitive type value in the library's internal representation.
+ * @param value - Value to test.
+ * @returns {Boolean} True is the value is a primitive type value.
+ * Date objects are considered primitive types by the library.
+ */
+function isPrimitive(value) {
+
+    return isDate(value) ||
+        typeof value === "string" ||
+        typeof value === "number" ||
+        typeof value === "boolean";
+}
+
+/** Checks whether the specified type name is a primitive EDM type.
+ * @param {String} typeName - Name of type to check.
+ * @returns {Boolean} True if the type is a primitive EDM type; false otherwise.
+ */
+function isPrimitiveEdmType(typeName) {
+
+    return contains(primitiveEdmTypes, typeName);
+}
+
+/** Gets the kind of a navigation property value.
+ * @param value - Value of the navigation property.
+ * @param {Object} [propertyModel] - Object that describes the navigation property in an OData conceptual schema.
+ * @returns {String} String value describing the kind of the navigation property; null if the kind cannot be determined.
+ */
+function navigationPropertyKind(value, propertyModel) {
+
+    if (isDeferred(value)) {
+        return "deferred";
+    }
+    if (isEntry(value)) {
+        return "entry";
+    }
+    if (isFeed(value)) {
+        return "feed";
+    }
+    if (propertyModel && propertyModel.relationship) {
+        if (value === null || value === undefined || !isFeed(value)) {
+            return "entry";
+        }
+        return "feed";
+    }
+    return null;
+}
+
+/** Looks up a property by name.
+ * @param {Array} properties - Array of property objects as per EDM metadata (may be null)
+ * @param {String} name - Name to look for.
+ * @returns {Object} The property object; null if not found.
+ */
+function lookupProperty(properties, name) {
+
+    return find(properties, function (property) {
+        return property.name === name;
+    });
+}
+
+/** Looks up a type object by name.
+ * @param {String} name - Name, possibly null or empty.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @param {String} kind - Kind of object to look for as per EDM metadata.
+ * @returns An type description if the name is found; null otherwise
+ */
+function lookupInMetadata(name, metadata, kind) {
+
+    return (name) ? forEachSchema(metadata, function (schema) {
+        return lookupInSchema(name, schema, kind);
+    }) : null;
+}
+
+/** Looks up a entity set by name.
+ * @param {Array} properties - Array of entity set objects as per EDM metadata( may be null)
+ * @param {String} name - Name to look for.
+ * @returns {Object} The entity set object; null if not found.
+ */
+function lookupEntitySet(entitySets, name) {
+
+    return find(entitySets, function (entitySet) {
+        return entitySet.name === name;
+    });
+}
+
+/** Looks up a entity set by name.
+ * @param {Array} properties - Array of entity set objects as per EDM metadata (may be null)
+ * @param {String} name - Name to look for.
+ * @returns {Object} The entity set object; null if not found.
+ */
+function lookupSingleton(singletons, name) {
+
+    return find(singletons, function (singleton) {
+        return singleton.name === name;
+    });
+}
+
+/** Looks up a complex type object by name.
+ * @param {String} name - Name, possibly null or empty.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @returns A complex type description if the name is found; null otherwise.</returns>
+ */
+function lookupComplexType(name, metadata) {
+
+    return lookupInMetadata(name, metadata, "complexType");
+}
+
+/** Looks up an entity type object by name.
+ * @param {String} name - Name, possibly null or empty.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @returns An entity type description if the name is found; null otherwise.</returns>
+ */
+function lookupEntityType(name, metadata) {
+
+    return lookupInMetadata(name, metadata, "entityType");
+}
+
+
+/** Looks up an
+ * @param {String} name - Name, possibly null or empty.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @returns An entity container description if the name is found; null otherwise.</returns>
+ */
+function lookupDefaultEntityContainer(metadata) {
+
+    return forEachSchema(metadata, function (schema) {
+        if (isObject(schema.entityContainer)) { 
+            return schema.entityContainer;
+        }
+    });
+}
+
+/** Looks up an entity container object by name.
+ * @param {String} name - Name, possibly null or empty.
+ * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
+ * @returns An entity container description if the name is found; null otherwise.</returns>
+ */
+function lookupEntityContainer(name, metadata) {
+
+    return lookupInMetadata(name, metadata, "entityContainer");
+}
+
+/** Looks up a function import by name.
+ * @param {Array} properties - Array of function import objects as per EDM metadata (May be null)
+ * @param {String} name - Name to look for.
+ * @returns {Object} The entity set object; null if not found.
+ */
+function lookupFunctionImport(functionImports, name) {
+    return find(functionImports, function (functionImport) {
+        return functionImport.name === name;
+    });
+}
+
+/** Looks up the target entity type for a navigation property.
+ * @param {Object} navigationProperty - 
+ * @param {Object} metadata - 
+ * @returns {String} The entity type name for the specified property, null if not found.
+ */
+function lookupNavigationPropertyType(navigationProperty, metadata) {
+
+    var result = null;
+    if (navigationProperty) {
+        var rel = navigationProperty.relationship;
+        var association = forEachSchema(metadata, function (schema) {
+            // The name should be the namespace qualified name in 'ns'.'type' format.
+            var nameOnly = removeNamespace(schema.namespace, rel);
+            var associations = schema.association;
+            if (nameOnly && associations) {
+                var i, len;
+                for (i = 0, len = associations.length; i < len; i++) {
+                    if (associations[i].name === nameOnly) {
+                        return associations[i];
+                    }
+                }
+            }
+            return null;
+        });
+
+        if (association) {
+            var end = association.end[0];
+            if (end.role !== navigationProperty.toRole) {
+                end = association.end[1];
+                // For metadata to be valid, end.role === navigationProperty.toRole now.
+            }
+            result = end.type;
+        }
+    }
+    return result;
+}
+
+/** Looks up the target entityset name for a navigation property.
+ * @param {Object} navigationProperty - 
+ * @param {Object} metadata - 
+ * @returns {String} The entityset name for the specified property, null if not found.
+ */
+function lookupNavigationPropertyEntitySet(navigationProperty, sourceEntitySetName, metadata) {
+
+    if (navigationProperty) {
+        var rel = navigationProperty.relationship;
+        var associationSet = forEachSchema(metadata, function (schema) {
+            var containers = schema.entityContainer;
+            for (var i = 0; i < containers.length; i++) {
+                var associationSets = containers[i].associationSet;
+                if (associationSets) {
+                    for (var j = 0; j < associationSets.length; j++) {
+                        if (associationSets[j].association == rel) {
+                            return associationSets[j];
+                        }
+                    }
+                }
+            }
+            return null;
+        });
+        if (associationSet && associationSet.end[0] && associationSet.end[1]) {
+            return (associationSet.end[0].entitySet == sourceEntitySetName) ? associationSet.end[1].entitySet : associationSet.end[0].entitySet;
+        }
+    }
+    return null;
+}
+
+/** Gets the entitySet info, container name and functionImports for an entitySet
+ * @param {Object} navigationProperty - 
+ * @param {Object} metadata - 
+ * @returns {Object} The info about the entitySet.
+ */
+function getEntitySetInfo(entitySetName, metadata) {
+
+    var info = forEachSchema(metadata, function (schema) {
+        var container = schema.entityContainer;
+        var entitySets = container.entitySet;
+        if (entitySets) {
+            for (var j = 0; j < entitySets.length; j++) {
+                if (entitySets[j].name == entitySetName) {
+                    return { entitySet: entitySets[j], containerName: container.name, functionImport: container.functionImport };
+                }
+            }
+        }
+        return null;
+    });
+
+    return info;
+}
+
+/** Given an expected namespace prefix, removes it from a full name.
+ * @param {String} ns - Expected namespace.
+ * @param {String} fullName - Full name in 'ns'.'name' form.
+ * @returns {String} The local name, null if it isn't found in the expected namespace.
+ */
+function removeNamespace(ns, fullName) {
+
+    if (fullName.indexOf(ns) === 0 && fullName.charAt(ns.length) === ".") {
+        return fullName.substr(ns.length + 1);
+    }
+
+    return null;
+}
+
+/** Looks up a schema object by name.
+ * @param {String} name - Name (assigned).
+ * @param schema - Schema object as per EDM metadata.
+ * @param {String} kind - Kind of object to look for as per EDM metadata.
+ * @returns An entity type description if the name is found; null otherwise.</returns>
+ */
+function lookupInSchema(name, schema, kind) {
+
+    if (name && schema) {
+        // The name should be the namespace qualified name in 'ns'.'type' format.
+        var nameOnly = removeNamespace(schema.namespace, name);
+        if (nameOnly) {
+            return find(schema[kind], function (item) {
+                return item.name === nameOnly;
+            });
+        }
+    }
+    return null;
+}
+
+/** Compares to version strings and returns the higher one.
+ * @param {String} left - Version string in the form "major.minor.rev"
+ * @param {String} right - Version string in the form "major.minor.rev"
+ * @returns {String} The higher version string.
+ */
+function maxVersion(left, right) {
+
+    if (left === right) {
+        return left;
+    }
+
+    var leftParts = left.split(".");
+    var rightParts = right.split(".");
+
+    var len = (leftParts.length >= rightParts.length) ?
+        leftParts.length :
+        rightParts.length;
+
+    for (var i = 0; i < len; i++) {
+        var leftVersion = leftParts[i] && parseInt10(leftParts[i]);
+        var rightVersion = rightParts[i] && parseInt10(rightParts[i]);
+        if (leftVersion > rightVersion) {
+            return left;
+        }
+        if (leftVersion < rightVersion) {
+            return right;
+        }
+    }
+}
+
+var normalHeaders = {
+    // Headers shared by request and response
+    "content-type": "Content-Type",
+    "content-encoding": "Content-Encoding",
+    "content-length": "Content-Length",
+    "odata-version": "OData-Version",
+    
+    // Headers used by request
+    "accept": "Accept",
+    "accept-charset": "Accept-Charset",
+    "if-match": "If-Match",
+    "if-none-match": "If-None-Match",
+    "odata-isolation": "OData-Isolation",
+    "odata-maxversion": "OData-MaxVersion",
+    "prefer": "Prefer",
+    "content-id": "Content-ID",
+    "content-transfer-encoding": "Content-Transfer-Encoding",
+    
+    // Headers used by response
+    "etag": "ETag",
+    "location": "Location",
+    "odata-entityid": "OData-EntityId",
+    "preference-applied": "Preference-Applied",
+    "retry-after": "Retry-After"
+};
+
+/** Normalizes headers so they can be found with consistent casing.
+ * @param {Object} headers - Dictionary of name/value pairs.
+ */
+function normalizeHeaders(headers) {
+
+    for (var name in headers) {
+        var lowerName = name.toLowerCase();
+        var normalName = normalHeaders[lowerName];
+        if (normalName && name !== normalName) {
+            var val = headers[name];
+            delete headers[name];
+            headers[normalName] = val;
+        }
+    }
+}
+
+/** Parses a string into a boolean value.
+ * @param propertyValue - Value to parse.
+ * @returns {Boolean} true if the property value is 'true'; false otherwise.
+ */
+function parseBool(propertyValue) {
+
+    if (typeof propertyValue === "boolean") {
+        return propertyValue;
+    }
+
+    return typeof propertyValue === "string" && propertyValue.toLowerCase() === "true";
+}
+
+
+// The captured indices for this expression are:
+// 0     - complete input
+// 1,2,3 - year with optional minus sign, month, day
+// 4,5,6 - hours, minutes, seconds
+// 7     - optional milliseconds
+// 8     - everything else (presumably offset information)
+var parseDateTimeRE = /^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/;
+
+/** Parses a string into a DateTime value.
+ * @param {String} value - Value to parse.
+ * @param {Boolean} withOffset - Whether offset is expected.
+ * @returns {Date} The parsed value.
+ */
+function parseDateTimeMaybeOffset(value, withOffset, nullOnError) {
+
+    // We cannot parse this in cases of failure to match or if offset information is specified.
+    var parts = parseDateTimeRE.exec(value);
+    var offset = (parts) ? getCanonicalTimezone(parts[8]) : null;
+
+    if (!parts || (!withOffset && offset !== "Z")) {
+        if (nullOnError) {
+            return null;
+        }
+        throw { message: "Invalid date/time value" };
+    }
+
+    // Pre-parse years, account for year '0' being invalid in dateTime.
+    var year = parseInt10(parts[1]);
+    if (year <= 0) {
+        year++;
+    }
+
+    // Pre-parse optional milliseconds, fill in default. Fail if value is too precise.
+    var ms = parts[7];
+    var ns = 0;
+    if (!ms) {
+        ms = 0;
+    } else {
+        if (ms.length > 7) {
+            if (nullOnError) {
+                return null;
+            }
+            throw { message: "Cannot parse date/time value to given precision." };
+        }
+
+        ns = formatNumberWidth(ms.substring(3), 4, true);
+        ms = formatNumberWidth(ms.substring(0, 3), 3, true);
+
+        ms = parseInt10(ms);
+        ns = parseInt10(ns);
+    }
+
+    // Pre-parse other time components and offset them if necessary.
+    var hours = parseInt10(parts[4]);
+    var minutes = parseInt10(parts[5]);
+    var seconds = parseInt10(parts[6]) || 0;
+    if (offset !== "Z") {
+        // The offset is reversed to get back the UTC date, which is
+        // what the API will eventually have.
+        var timezone = parseTimezone(offset);
+        var direction = -(timezone.d);
+        hours += timezone.h * direction;
+        minutes += timezone.m * direction;
+    }
+
+    // Set the date and time separately with setFullYear, so years 0-99 aren't biased like in Date.UTC.
+    var result = new Date();
+    result.setUTCFullYear(
+        year,                       // Year.
+        parseInt10(parts[2]) - 1,   // Month (zero-based for Date.UTC and setFullYear).
+        parseInt10(parts[3])        // Date.
+        );
+    result.setUTCHours(hours, minutes, seconds, ms);
+
+    if (isNaN(result.valueOf())) {
+        if (nullOnError) {
+            return null;
+        }
+        throw { message: "Invalid date/time value" };
+    }
+
+    if (withOffset) {
+        result.__edmType = "Edm.DateTimeOffset";
+        result.__offset = offset;
+    }
+
+    if (ns) {
+        result.__ns = ns;
+    }
+
+    return result;
+}
+
+/** Parses a string into a Date object.
+ * @param {String} propertyValue - Value to parse.
+ * @returns {Date} The parsed with year, month, day set, time values are set to 0
+ */
+function parseDate(propertyValue, nullOnError) {
+    var parts = propertyValue.split('-');
+
+    if (parts.length != 3 && nullOnError) {
+        return null;
+    }
+    return new Date(
+        parseInt10(parts[0]),       // Year.
+        parseInt10(parts[1]) - 1,   // Month (zero-based for Date.UTC and setFullYear).
+        parseInt10(parts[2],
+        0,0,0,0)        // Date.
+        );
+
+}
+
+var parseTimeOfDayRE = /^(\d+):(\d+)(:(\d+)(.(\d+))?)?$/;
+
+function parseTimeOfDay(propertyValue, nullOnError) {
+    var parts = parseTimeOfDayRE.exec(propertyValue);
+
+
+    return {
+        'h' :parseInt10(parts[1]),
+        'm' :parseInt10(parts[2]),
+        's' :parseInt10(parts[4]),
+        'ms' :parseInt10(parts[6]),
+     };
+}
+
+/** Parses a string into a DateTimeOffset value.
+ * @param {String} propertyValue - Value to parse.
+ * @returns {Date} The parsed value.
+
+
+ * The resulting object is annotated with an __edmType property and
+ * an __offset property reflecting the original intended offset of
+ * the value. The time is adjusted for UTC time, as the current
+ * timezone-aware Date APIs will only work with the local timezone.
+ */
+function parseDateTimeOffset(propertyValue, nullOnError) {
+    
+
+    return parseDateTimeMaybeOffset(propertyValue, true, nullOnError);
+}
+
+// The captured indices for this expression are:
+// 0       - complete input
+// 1       - direction
+// 2,3,4   - years, months, days
+// 5,6,7,8 - hours, minutes, seconds, miliseconds
+
+var parseTimeRE = /^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/;
+
+function isEdmDurationValue(value) {
+    parseTimeRE.test(value);
+}
+
+/** Parses a string in xsd:duration format.
+ * @param {String} duration - Duration value.
+
+ * This method will throw an exception if the input string has a year or a month component.
+
+ * @returns {Object} Object representing the time
+ */
+function parseDuration(duration) {
+
+    var parts = parseTimeRE.exec(duration);
+
+    if (parts === null) {
+        throw { message: "Invalid duration value." };
+    }
+
+    var years = parts[2] || "0";
+    var months = parts[3] || "0";
+    var days = parseInt10(parts[4] || 0);
+    var hours = parseInt10(parts[5] || 0);
+    var minutes = parseInt10(parts[6] || 0);
+    var seconds = parseFloat(parts[7] || 0);
+
+    if (years !== "0" || months !== "0") {
+        throw { message: "Unsupported duration value." };
+    }
+
+    var ms = parts[8];
+    var ns = 0;
+    if (!ms) {
+        ms = 0;
+    } else {
+        if (ms.length > 7) {
+            throw { message: "Cannot parse duration value to given precision." };
+        }
+
+        ns = formatNumberWidth(ms.substring(3), 4, true);
+        ms = formatNumberWidth(ms.substring(0, 3), 3, true);
+
+        ms = parseInt10(ms);
+        ns = parseInt10(ns);
+    }
+
+    ms += seconds * 1000 + minutes * 60000 + hours * 3600000 + days * 86400000;
+
+    if (parts[1] === "-") {
+        ms = -ms;
+    }
+
+    var result = { ms: ms, __edmType: "Edm.Time" };
+
+    if (ns) {
+        result.ns = ns;
+    }
+    return result;
+}
+
+/** Parses a timezone description in (+|-)nn:nn format.
+ * @param {String} timezone - Timezone offset.
+ * @returns {Object} An object with a (d)irection property of 1 for + and -1 for -, offset (h)ours and offset (m)inutes.
+ */
+function parseTimezone(timezone) {
+
+    var direction = timezone.substring(0, 1);
+    direction = (direction === "+") ? 1 : -1;
+
+    var offsetHours = parseInt10(timezone.substring(1));
+    var offsetMinutes = parseInt10(timezone.substring(timezone.indexOf(":") + 1));
+    return { d: direction, h: offsetHours, m: offsetMinutes };
+}
+
+/** Prepares a request object so that it can be sent through the network.
+* @param request - Object that represents the request to be sent.
+* @param handler - Handler for data serialization
+* @param context - Context used for preparing the request
+*/
+function prepareRequest(request, handler, context) {
+
+    // Default to GET if no method has been specified.
+    if (!request.method) {
+        request.method = "GET";
+    }
+
+    if (!request.headers) {
+        request.headers = {};
+    } else {
+        normalizeHeaders(request.headers);
+    }
+
+    if (request.headers.Accept === undefined) {
+        request.headers.Accept = handler.accept;
+    }
+
+    if (assigned(request.data) && request.body === undefined) {
+        handler.write(request, context);
+    }
+
+    if (!assigned(request.headers["OData-MaxVersion"])) {
+        request.headers["OData-MaxVersion"] = handler.maxDataServiceVersion || "4.0";
+    }
+
+    if (request.async === undefined) {
+        request.async = true;
+    }
+
+}
+
+/** Traverses a tree of objects invoking callback for every value.
+ * @param {Object} item - Object or array to traverse.
+ * @param {Function} callback - Callback function with key and value, similar to JSON.parse reviver.
+ * @returns {Object} The object with traversed properties.
+ Unlike the JSON reviver, this won't delete null members.</remarks>
+*/
+function traverseInternal(item, owner, callback) {
+
+    if (item && typeof item === "object") {
+        for (var name in item) {
+            var value = item[name];
+            var result = traverseInternal(value, name, callback);
+            result = callback(name, result, owner);
+            if (result !== value) {
+                if (value === undefined) {
+                    delete item[name];
+                } else {
+                    item[name] = result;
+                }
+            }
+        }
+    }
+
+    return item;
+}
+
+/** Traverses a tree of objects invoking callback for every value.
+ * @param {Object} item - Object or array to traverse.
+ * @param {Function} callback - Callback function with key and value, similar to JSON.parse reviver.
+ * @returns {Object} The traversed object.
+ * Unlike the JSON reviver, this won't delete null members.</remarks>
+*/
+function traverse(item, callback) {
+
+    return callback("", traverseInternal(item, "", callback));
+}
+
+exports.dataItemTypeName = dataItemTypeName;
+exports.EDM_BINARY = EDM_BINARY;
+exports.EDM_BOOLEAN = EDM_BOOLEAN;
+exports.EDM_BYTE = EDM_BYTE;
+exports.EDM_DATETIME = EDM_DATETIME;
+exports.EDM_DATETIMEOFFSET = EDM_DATETIMEOFFSET;
+exports.EDM_DECIMAL = EDM_DECIMAL;
+exports.EDM_DOUBLE = EDM_DOUBLE;
+exports.EDM_GEOGRAPHY = EDM_GEOGRAPHY;
+exports.EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY_POINT;
+exports.EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY_LINESTRING;
+exports.EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY_POLYGON;
+exports.EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY_COLLECTION;
+exports.EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY_MULTIPOLYGON;
+exports.EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY_MULTILINESTRING;
+exports.EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY_MULTIPOINT;
+exports.EDM_GEOMETRY = EDM_GEOMETRY;
+exports.EDM_GEOMETRY_POINT = EDM_GEOMETRY_POINT;
+exports.EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY_LINESTRING;
+exports.EDM_GEOMETRY_POLYGON = EDM_GEOMETRY_POLYGON;
+exports.EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY_COLLECTION;
+exports.EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY_MULTIPOLYGON;
+exports.EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY_MULTILINESTRING;
+exports.EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY_MULTIPOINT;
+exports.EDM_GUID = EDM_GUID;
+exports.EDM_INT16 = EDM_INT16;
+exports.EDM_INT32 = EDM_INT32;
+exports.EDM_INT64 = EDM_INT64;
+exports.EDM_SBYTE = EDM_SBYTE;
+exports.EDM_SINGLE = EDM_SINGLE;
+exports.EDM_STRING = EDM_STRING;
+exports.EDM_TIME = EDM_TIME;
+exports.GEOJSON_POINT = GEOJSON_POINT;
+exports.GEOJSON_LINESTRING = GEOJSON_LINESTRING;
+exports.GEOJSON_POLYGON = GEOJSON_POLYGON;
+exports.GEOJSON_MULTIPOINT = GEOJSON_MULTIPOINT;
+exports.GEOJSON_MULTILINESTRING = GEOJSON_MULTILINESTRING;
+exports.GEOJSON_MULTIPOLYGON = GEOJSON_MULTIPOLYGON;
+exports.GEOJSON_GEOMETRYCOLLECTION = GEOJSON_GEOMETRYCOLLECTION;
+exports.forEachSchema = forEachSchema;
+exports.formatDateTimeOffset = formatDateTimeOffset;
+exports.formatDateTimeOffsetJSON = formatDateTimeOffsetJSON;
+exports.formatDuration = formatDuration;
+exports.formatNumberWidth = formatNumberWidth;
+exports.getCanonicalTimezone = getCanonicalTimezone;
+exports.getCollectionType = getCollectionType;
+exports.invokeRequest = invokeRequest;
+exports.isBatch = isBatch;
+exports.isCollection = isCollection;
+exports.isCollectionType = isCollectionType;
+exports.isComplex = isComplex;
+exports.isDateTimeOffset = isDateTimeOffset;
+exports.isDeferred = isDeferred;
+exports.isEntry = isEntry;
+exports.isFeed = isFeed;
+exports.isGeographyEdmType = isGeographyEdmType;
+exports.isGeometryEdmType = isGeometryEdmType;
+exports.isNamedStream = isNamedStream;
+exports.isPrimitive = isPrimitive;
+exports.isPrimitiveEdmType = isPrimitiveEdmType;
+exports.lookupComplexType = lookupComplexType;
+exports.lookupDefaultEntityContainer = lookupDefaultEntityContainer;
+exports.lookupEntityContainer = lookupEntityContainer;
+exports.lookupEntitySet = lookupEntitySet;
+exports.lookupSingleton = lookupSingleton;
+exports.lookupEntityType = lookupEntityType;
+exports.lookupFunctionImport = lookupFunctionImport;
+exports.lookupNavigationPropertyType = lookupNavigationPropertyType;
+exports.lookupNavigationPropertyEntitySet = lookupNavigationPropertyEntitySet;
+exports.lookupInSchema = lookupInSchema;
+exports.lookupProperty = lookupProperty;
+exports.lookupInMetadata = lookupInMetadata;
+exports.getEntitySetInfo = getEntitySetInfo;
+exports.maxVersion = maxVersion;
+exports.navigationPropertyKind = navigationPropertyKind;
+exports.normalizeHeaders = normalizeHeaders;
+exports.parseBool = parseBool;
+
+
+exports.parseDate = parseDate;
+exports.parseDateTimeOffset = parseDateTimeOffset;
+exports.parseDuration = parseDuration;
+exports.parseTimeOfDay = parseTimeOfDay;
+
+exports.parseInt10 = parseInt10;
+exports.prepareRequest = prepareRequest;
+exports.removeNamespace = removeNamespace;
+exports.traverse = traverse;
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/store.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/store.js b/odatajs/src/lib/store.js
new file mode 100644
index 0000000..5989253
--- /dev/null
+++ b/odatajs/src/lib/store.js
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+ /** @module store */
+
+
+
+
+
+exports.defaultStoreMechanism = "best";
+
+/** Creates a new store object.
+ * @param {String} name - Store name.
+ * @param {String} [mechanism] - 
+ * @returns {Object} Store object.
+*/
+exports.createStore = function (name, mechanism) {
+
+
+    if (!mechanism) {
+        mechanism = exports.defaultStoreMechanism;
+    }
+
+    if (mechanism === "best") {
+        mechanism = (DomStore.isSupported()) ? "dom" : "memory";
+    }
+
+    var factory = mechanisms[mechanism];
+    if (factory) {
+        return factory.create(name);
+    }
+
+    throw { message: "Failed to create store", name: name, mechanism: mechanism };
+};
+
+exports.mechanisms = mechanisms;
+
+
+exports.DomStore       = DomStore       = require('./store/dom.js');
+exports.IndexedDBStore = IndexedDBStore = require('./store/indexeddb.js');
+exports.MemoryStore    = MemoryStore    = require('./store/memory.js');
+
+var mechanisms = {
+    indexeddb: IndexedDBStore,
+    dom: DomStore,
+    memory: MemoryStore
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/store/dom.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/store/dom.js b/odatajs/src/lib/store/dom.js
new file mode 100644
index 0000000..740b1ba
--- /dev/null
+++ b/odatajs/src/lib/store/dom.js
@@ -0,0 +1,330 @@
+/*
+ * 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.
+ */
+
+/** @module store/dom */
+
+
+
+var utils = require('./../datajs.js').utils;
+
+// Imports.
+var throwErrorCallback = utils.throwErrorCallback;
+var delay = utils.delay;
+
+var localStorage = null;
+
+/** This method is used to override the Date.toJSON method and is called only by
+ * JSON.stringify.  It should never be called directly.
+ * @summary Converts a Date object into an object representation friendly to JSON serialization.
+ * @returns {Object} Object that represents the Date.
+ */
+function domStoreDateToJSON() {
+    var newValue = { v: this.valueOf(), t: "[object Date]" };
+    // Date objects might have extra properties on them so we save them.
+    for (var name in this) {
+        newValue[name] = this[name];
+    }
+    return newValue;
+}
+
+/** This method is used during JSON parsing and invoked only by the reviver function.
+ * It should never be called directly.
+ * @summary JSON reviver function for converting an object representing a Date in a JSON stream to a Date object
+ * @param Object - Object to convert.
+ * @returns {Date} Date object.
+ */
+function domStoreJSONToDate(_, value) {
+    if (value && value.t === "[object Date]") {
+        var newValue = new Date(value.v);
+        for (var name in value) {
+            if (name !== "t" && name !== "v") {
+                newValue[name] = value[name];
+            }
+        }
+        value = newValue;
+    }
+    return value;
+}
+
+/** Qualifies the key with the name of the store.
+ * @param {Object} store - Store object whose name will be used for qualifying the key.
+ * @param {String} key - Key string.
+ * @returns {String} Fully qualified key string.
+ */
+function qualifyDomStoreKey(store, key) {
+    return store.name + "#!#" + key;
+}
+
+/** Gets the key part of a fully qualified key string.
+ * @param {Object} store - Store object whose name will be used for qualifying the key.
+ * @param {String} key - Fully qualified key string.
+ * @returns {String} Key part string
+ */
+function unqualifyDomStoreKey(store, key) {
+    return key.replace(store.name + "#!#", "");
+}
+
+/** Constructor for store objects that use DOM storage as the underlying mechanism.
+ * @class DomStore
+ * @constructor
+ * @param {String} name - Store name.
+ */
+function DomStore(name) {
+    this.name = name;
+}
+
+/** Creates a store object that uses DOM Storage as its underlying mechanism.
+ * @method module:store/dom~DomStore.create
+ * @param {String} name - Store name.
+ * @returns {Object} Store object.
+ */
+DomStore.create = function (name) {
+
+    if (DomStore.isSupported()) {
+        localStorage = localStorage || window.localStorage;
+        return new DomStore(name);
+    }
+
+    throw { message: "Web Storage not supported by the browser" };
+};
+
+/** Checks whether the underlying mechanism for this kind of store objects is supported by the browser.
+ * @method DomStore.isSupported
+ * @returns {Boolean} - True if the mechanism is supported by the browser; otherwise false.
+*/
+DomStore.isSupported = function () {
+    return !!window.localStorage;
+};
+
+/** Adds a new value identified by a key to the store.
+ * @method module:store/dom~DomStore#add
+ * @param {String} key - Key string.
+ * @param value - Value that is going to be added to the store.
+ * @param {Funcktion} success - Callback for a successful add operation.</param>
+ * @param {Funcktion} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+ * This method errors out if the store already contains the specified key.
+ */
+DomStore.prototype.add = function (key, value, success, error) {
+    error = error || this.defaultError;
+    var store = this;
+    this.contains(key, function (contained) {
+        if (!contained) {
+            store.addOrUpdate(key, value, success, error);
+        } else {
+            delay(error, { message: "key already exists", key: key });
+        }
+    }, error);
+};
+
+/** This method will overwrite the key's current value if it already exists in the store; otherwise it simply adds the new key and value.
+ * @summary Adds or updates a value identified by a key to the store.
+ * @method module:store/dom~DomStore#addOrUpdate
+ * @param {String} key - Key string.
+ * @param value - Value that is going to be added or updated to the store.
+ * @param {Function} success - Callback for a successful add or update operation.</param>
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+ */
+DomStore.prototype.addOrUpdate = function (key, value, success, error) {
+    error = error || this.defaultError;
+
+    if (key instanceof Array) {
+        error({ message: "Array of keys not supported" });
+    } else {
+        var fullKey = qualifyDomStoreKey(this, key);
+        var oldDateToJSON = Date.prototype.toJSON;
+        try {
+            var storedValue = value;
+            if (storedValue !== undefined) {
+                // Dehydrate using json
+                Date.prototype.toJSON = domStoreDateToJSON;
+                storedValue = window.JSON.stringify(value);
+            }
+            // Save the json string.
+            localStorage.setItem(fullKey, storedValue);
+            delay(success, key, value);
+        }
+        catch (e) {
+            if (e.code === 22 || e.number === 0x8007000E) {
+                delay(error, { name: "QUOTA_EXCEEDED_ERR", error: e });
+            } else {
+                delay(error, e);
+            }
+        }
+        finally {
+            Date.prototype.toJSON = oldDateToJSON;
+        }
+    }
+};
+
+/** In case of an error, this method will not restore any keys that might have been deleted at that point.
+ * @summary Removes all the data associated with this store object.
+ * @method module:store/dom~DomStore#clear
+ * @param {Function} success - Callback for a successful clear operation.</param>
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+ */
+DomStore.prototype.clear = function (success, error) {
+
+    error = error || this.defaultError;
+    try {
+        var i = 0, len = localStorage.length;
+        while (len > 0 && i < len) {
+            var fullKey = localStorage.key(i);
+            var key = unqualifyDomStoreKey(this, fullKey);
+            if (fullKey !== key) {
+                localStorage.removeItem(fullKey);
+                len = localStorage.length;
+            } else {
+                i++;
+            }
+        }
+        delay(success);
+    }
+    catch (e) {
+        delay(error, e);
+    }
+};
+
+/** This function does nothing in DomStore as it does not have a connection model
+ * @method module:store/dom~DomStore#close
+ */
+DomStore.prototype.close = function () {
+};
+
+/** Checks whether a key exists in the store.
+ * @method module:store/dom~DomStore#contains
+ * @param {String} key - Key string.
+ * @param {Function} success - Callback indicating whether the store contains the key or not.</param>
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+*/
+DomStore.prototype.contains = function (key, success, error) {
+    error = error || this.defaultError;
+    try {
+        var fullKey = qualifyDomStoreKey(this, key);
+        var value = localStorage.getItem(fullKey);
+        delay(success, value !== null);
+    } catch (e) {
+        delay(error, e);
+    }
+};
+
+DomStore.prototype.defaultError = throwErrorCallback;
+
+/** Gets all the keys that exist in the store.
+ * @method module:store/dom~DomStore#getAllKeys
+ * @param {Function} success - Callback for a successful get operation.</param>
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+ */
+DomStore.prototype.getAllKeys = function (success, error) {
+
+    error = error || this.defaultError;
+
+    var results = [];
+    var i, len;
+
+    try {
+        for (i = 0, len = localStorage.length; i < len; i++) {
+            var fullKey = localStorage.key(i);
+            var key = unqualifyDomStoreKey(this, fullKey);
+            if (fullKey !== key) {
+                results.push(key);
+            }
+        }
+        delay(success, results);
+    }
+    catch (e) {
+        delay(error, e);
+    }
+};
+
+/** Identifies the underlying mechanism used by the store.*/
+DomStore.prototype.mechanism = "dom";
+
+/** Reads the value associated to a key in the store.
+ * @method module:store/dom~DomStore#read
+ * @param {String} key - Key string.
+ * @param {Function} success - Callback for a successful reads operation.
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.
+ */
+DomStore.prototype.read = function (key, success, error) {
+
+    error = error || this.defaultError;
+
+    if (key instanceof Array) {
+        error({ message: "Array of keys not supported" });
+    } else {
+        try {
+            var fullKey = qualifyDomStoreKey(this, key);
+            var value = localStorage.getItem(fullKey);
+            if (value !== null && value !== "undefined") {
+                // Hydrate using json
+                value = window.JSON.parse(value, domStoreJSONToDate);
+            }
+            else {
+                value = undefined;
+            }
+            delay(success, key, value);
+        } catch (e) {
+            delay(error, e);
+        }
+    }
+};
+
+/** Removes a key and its value from the store.
+ * @method module:store/dom~DomStore#remove
+ * @param {String} key - Key string.
+ * @param {Funtion} success - Callback for a successful remove operation.</param>
+ * @param {Funtion} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+ */
+DomStore.prototype.remove = function (key, success, error) {
+    error = error || this.defaultError;
+
+    if (key instanceof Array) {
+        error({ message: "Batches not supported" });
+    } else {
+        try {
+            var fullKey = qualifyDomStoreKey(this, key);
+            localStorage.removeItem(fullKey);
+            delay(success);
+        } catch (e) {
+            delay(error, e);
+        }
+    }
+};
+
+/** Updates the value associated to a key in the store.
+ * @method module:store/dom~DomStore#update
+ * @param {String} key - Key string.
+ * @param value - New value.
+ * @param {Function} success - Callback for a successful update operation.
+ * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked
+ * This method errors out if the specified key is not found in the store.
+ */
+DomStore.prototype.update = function (key, value, success, error) {
+    error = error || this.defaultError;
+    var store = this;
+    this.contains(key, function (contained) {
+        if (contained) {
+            store.addOrUpdate(key, value, success, error);
+        } else {
+            delay(error, { message: "key not found", key: key });
+        }
+    }, error);
+};
+
+module.exports = DomStore;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/store/indexeddb.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/store/indexeddb.js b/odatajs/src/lib/store/indexeddb.js
new file mode 100644
index 0000000..397354a
--- /dev/null
+++ b/odatajs/src/lib/store/indexeddb.js
@@ -0,0 +1,445 @@
+/*
+ * 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.
+ */
+
+/** @module store/indexeddb */
+var utils = require('./../datajs.js').utils;
+
+// Imports.
+var throwErrorCallback = utils.throwErrorCallback;
+var delay = utils.delay;
+
+
+var indexedDB = utils.inBrowser() ? window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB : undefined;
+var IDBKeyRange = utils.inBrowser() ? window.IDBKeyRange || window.webkitIDBKeyRange : undefined;
+var IDBTransaction = utils.inBrowser() ? window.IDBTransaction || window.webkitIDBTransaction || {} : {} ;
+
+var IDBT_READ_ONLY = IDBTransaction.READ_ONLY || "readonly";
+var IDBT_READ_WRITE = IDBTransaction.READ_WRITE || "readwrite";
+
+/** Returns either a specific error handler or the default error handler
+ * @param {Function} error - The specific error handler
+ * @param {Function} defaultError - The default error handler
+ * @returns {Function} The error callback
+ */
+function getError(error, defaultError) {
+
+    return function (e) {
+        var errorFunc = error || defaultError;
+        if (!errorFunc) {
+            return;
+        }
+
+        // Old api quota exceeded error support.
+        if (Object.prototype.toString.call(e) === "[object IDBDatabaseException]") {
+            if (e.code === 11 /* IndexedDb disk quota exceeded */) {
+                errorFunc({ name: "QuotaExceededError", error: e });
+                return;
+            }
+            errorFunc(e);
+            return;
+        }
+
+        var errName;
+        try {
+            var errObj = e.target.error || e;
+            errName = errObj.name;
+        } catch (ex) {
+            errName = (e.type === "blocked") ? "IndexedDBBlocked" : "UnknownError";
+        }
+        errorFunc({ name: errName, error: e });
+    };
+}
+
+/** Opens the store object's indexed db database.
+ * @param {IndexedDBStore} store - The store object
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+function openStoreDb(store, success, error) {
+
+    var storeName = store.name;
+    var dbName = "_datajs_" + storeName;
+
+    var request = indexedDB.open(dbName);
+    request.onblocked = error;
+    request.onerror = error;
+
+    request.onupgradeneeded = function () {
+        var db = request.result;
+        if (!db.objectStoreNames.contains(storeName)) {
+            db.createObjectStore(storeName);
+        }
+    };
+
+    request.onsuccess = function (event) {
+        var db = request.result;
+        if (!db.objectStoreNames.contains(storeName)) {
+            // Should we use the old style api to define the database schema?
+            if ("setVersion" in db) {
+                var versionRequest = db.setVersion("1.0");
+                versionRequest.onsuccess = function () {
+                    var transaction = versionRequest.transaction;
+                    transaction.oncomplete = function () {
+                        success(db);
+                    };
+                    db.createObjectStore(storeName, null, false);
+                };
+                versionRequest.onerror = error;
+                versionRequest.onblocked = error;
+                return;
+            }
+
+            // The database doesn't have the expected store.
+            // Fabricate an error object for the event for the schema mismatch
+            // and error out.
+            event.target.error = { name: "DBSchemaMismatch" };
+            error(event);
+            return;
+        }
+
+        db.onversionchange = function(event) {
+            event.target.close();
+        };
+        success(db);
+    };
+}
+
+/** Opens a new transaction to the store
+ * @param {IndexedDBStore} store - The store object
+ * @param {Short} mode - The read/write mode of the transaction (constants from IDBTransaction)
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+function openTransaction(store, mode, success, error) {
+
+    var storeName = store.name;
+    var storeDb = store.db;
+    var errorCallback = getError(error, store.defaultError);
+
+    if (storeDb) {
+        success(storeDb.transaction(storeName, mode));
+        return;
+    }
+
+    openStoreDb(store, function (db) {
+        store.db = db;
+        success(db.transaction(storeName, mode));
+    }, errorCallback);
+}
+
+/** Creates a new IndexedDBStore.
+ * @class IndexedDBStore
+ * @constructor
+ * @param {String} name - The name of the store.
+ * @returns {Object} The new IndexedDBStore.
+ */
+function IndexedDBStore(name) {
+    this.name = name;
+}
+
+/** Creates a new IndexedDBStore.
+ * @method module:store/indexeddb~IndexedDBStore.create
+ * @param {String} name - The name of the store.
+ * @returns {Object} The new IndexedDBStore.
+ */
+IndexedDBStore.create = function (name) {
+    if (IndexedDBStore.isSupported()) {
+        return new IndexedDBStore(name);
+    }
+
+    throw { message: "IndexedDB is not supported on this browser" };
+};
+
+/** Returns whether IndexedDB is supported.
+ * @method module:store/indexeddb~IndexedDBStore.isSupported
+ * @returns {Boolean} True if IndexedDB is supported, false otherwise.
+ */
+IndexedDBStore.isSupported = function () {
+    return !!indexedDB;
+};
+
+/** Adds a key/value pair to the store
+ * @method module:store/indexeddb~IndexedDBStore#add
+ * @param {String} key - The key
+ * @param {Object} value - The value
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+*/
+IndexedDBStore.prototype.add = function (key, value, success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    var keys = [];
+    var values = [];
+
+    if (key instanceof Array) {
+        keys = key;
+        values = value;
+    } else {
+        keys = [key];
+        values = [value];
+    }
+
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        transaction.onabort = getError(error, defaultError, key, "add");
+        transaction.oncomplete = function () {
+            if (key instanceof Array) {
+                success(keys, values);
+            } else {
+                success(key, value);
+            }
+        };
+
+        for (var i = 0; i < keys.length && i < values.length; i++) {
+            transaction.objectStore(name).add({ v: values[i] }, keys[i]);
+        }
+    }, error);
+};
+
+/** Adds or updates a key/value pair in the store
+ * @method module:store/indexeddb~IndexedDBStore#addOrUpdate
+ * @param {String} key - The key
+ * @param {Object} value - The value
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.addOrUpdate = function (key, value, success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    var keys = [];
+    var values = [];
+
+    if (key instanceof Array) {
+        keys = key;
+        values = value;
+    } else {
+        keys = [key];
+        values = [value];
+    }
+
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        transaction.onabort = getError(error, defaultError);
+        transaction.oncomplete = function () {
+            if (key instanceof Array) {
+                success(keys, values);
+            } else {
+                success(key, value);
+            }
+        };
+
+        for (var i = 0; i < keys.length && i < values.length; i++) {
+            var record = { v: values[i] };
+            transaction.objectStore(name).put(record, keys[i]);
+        }
+    }, error);
+};
+
+/** Clears the store
+ * @method module:store/indexeddb~IndexedDBStore#clear
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.clear = function (success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        transaction.onerror = getError(error, defaultError);
+        transaction.oncomplete = function () {
+            success();
+        };
+
+        transaction.objectStore(name).clear();
+    }, error);
+};
+/** Closes the connection to the database
+ * @method module:store/indexeddb~IndexedDBStore#close
+*/
+IndexedDBStore.prototype.close = function () {
+    
+    if (this.db) {
+        this.db.close();
+        this.db = null;
+    }
+};
+
+/** Returns whether the store contains a key
+ * @method module:store/indexeddb~IndexedDBStore#contains
+ * @param {String} key - The key
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.contains = function (key, success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
+        var objectStore = transaction.objectStore(name);
+        var request = objectStore.get(key);
+
+        transaction.oncomplete = function () {
+            success(!!request.result);
+        };
+        transaction.onerror = getError(error, defaultError);
+    }, error);
+};
+
+IndexedDBStore.prototype.defaultError = throwErrorCallback;
+
+/** Gets all the keys from the store
+ * @method module:store/indexeddb~IndexedDBStore#getAllKeys
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.getAllKeys = function (success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        var results = [];
+
+        transaction.oncomplete = function () {
+            success(results);
+        };
+
+        var request = transaction.objectStore(name).openCursor();
+
+        request.onerror = getError(error, defaultError);
+        request.onsuccess = function (event) {
+            var cursor = event.target.result;
+            if (cursor) {
+                results.push(cursor.key);
+                // Some tools have issues because continue is a javascript reserved word.
+                cursor["continue"].call(cursor);
+            }
+        };
+    }, error);
+};
+
+/** Identifies the underlying mechanism used by the store.
+*/
+IndexedDBStore.prototype.mechanism = "indexeddb";
+
+/** Reads the value for the specified key
+ * @method module:store/indexeddb~IndexedDBStore#read
+ * @param {String} key - The key
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ * If the key does not exist, the success handler will be called with value = undefined
+ */
+IndexedDBStore.prototype.read = function (key, success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    var keys = (key instanceof Array) ? key : [key];
+
+    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
+        var values = [];
+
+        transaction.onerror = getError(error, defaultError, key, "read");
+        transaction.oncomplete = function () {
+            if (key instanceof Array) {
+                success(keys, values);
+            } else {
+                success(keys[0], values[0]);
+            }
+        };
+
+        for (var i = 0; i < keys.length; i++) {
+            // Some tools have issues because get is a javascript reserved word. 
+            var objectStore = transaction.objectStore(name);
+            var request = objectStore.get.call(objectStore, keys[i]);
+            request.onsuccess = function (event) {
+                var record = event.target.result;
+                values.push(record ? record.v : undefined);
+            };
+        }
+    }, error);
+};
+
+/** Removes the specified key from the store
+ * @method module:store/indexeddb~IndexedDBStore#remove
+ * @param {String} key - The key
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.remove = function (key, success, error) {
+
+    var name = this.name;
+    var defaultError = this.defaultError;
+    var keys = (key instanceof Array) ? key : [key];
+
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        transaction.onerror = getError(error, defaultError);
+        transaction.oncomplete = function () {
+            success();
+        };
+
+        for (var i = 0; i < keys.length; i++) {
+            // Some tools have issues because continue is a javascript reserved word.
+            var objectStore = transaction.objectStore(name);
+            objectStore["delete"].call(objectStore, keys[i]);
+        }
+    }, error);
+};
+
+/** Updates a key/value pair in the store
+ * @method module:store/indexeddb~IndexedDBStore#update
+ * @param {String} key - The key
+ * @param {Object} value - The value
+ * @param {Function} success - The success callback
+ * @param {Function} error - The error callback
+ */
+IndexedDBStore.prototype.update = function (key, value, success, error) {
+    var name = this.name;
+    var defaultError = this.defaultError;
+    var keys = [];
+    var values = [];
+
+    if (key instanceof Array) {
+        keys = key;
+        values = value;
+    } else {
+        keys = [key];
+        values = [value];
+    }
+
+    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
+        transaction.onabort = getError(error, defaultError);
+        transaction.oncomplete = function () {
+            if (key instanceof Array) {
+                success(keys, values);
+            } else {
+                success(key, value);
+            }
+        };
+
+        for (var i = 0; i < keys.length && i < values.length; i++) {
+            var request = transaction.objectStore(name).openCursor(IDBKeyRange.only(keys[i]));
+            var record = { v: values[i] };
+            request.pair = { key: keys[i], value: record };
+            request.onsuccess = function (event) {
+                var cursor = event.target.result;
+                if (cursor) {
+                    cursor.update(event.target.pair.value);
+                } else {
+                    transaction.abort();
+                }
+            }
+        }
+    }, error);
+};
+
+
+module.exports = IndexedDBStore;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/store/memory.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/store/memory.js b/odatajs/src/lib/store/memory.js
new file mode 100644
index 0000000..7203c46
--- /dev/null
+++ b/odatajs/src/lib/store/memory.js
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+
+/** @module store/memory */
+
+
+var utils = require('./../datajs.js').utils;
+
+// Imports.
+var throwErrorCallback = utils.throwErrorCallback;
+var delay = utils.delay;
+
+/** Constructor for store objects that use a sorted array as the underlying mechanism.
+ * @class MemoryStore
+ * @constructor
+ * @param {String} name - Store name.
+ */
+function MemoryStore(name) {
+
+    var holes = [];
+    var items = [];
+    var keys = {};
+
+    this.name = name;
+
+    var getErrorCallback = function (error) {
+        return error || this.defaultError;
+    };
+
+    /** Validates that the specified key is not undefined, not null, and not an array
+     * @param key - Key value.
+     * @param {Function} error - Error callback.
+     * @returns {Boolean} True if the key is valid. False if the key is invalid and the error callback has been queued for execution.
+     */
+    function validateKeyInput(key, error) {
+
+        var messageString;
+
+        if (key instanceof Array) {
+            messageString = "Array of keys not supported";
+        }
+
+        if (key === undefined || key === null) {
+            messageString = "Invalid key";
+        }
+
+        if (messageString) {
+            delay(error, { message: messageString });
+            return false;
+        }
+        return true;
+    }
+
+    /** This method errors out if the store already contains the specified key.
+     * @summery Adds a new value identified by a key to the store.
+     * @method module:store/memory~MemoryStore#add
+     * @param {String} key - Key string.
+     * @param value - Value that is going to be added to the store.
+     * @param {Function} success - Callback for a successful add operation.</param>
+     * @param {Function} error - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+     */
+    this.add = function (key, value, success, error) {
+        error = getErrorCallback(error);
+
+        if (validateKeyInput(key, error)) {
+            if (!keys.hasOwnProperty(key)) {
+                this.addOrUpdate(key, value, success, error);
+            } else {
+                error({ message: "key already exists", key: key });
+            }
+        }
+    };
+
+    /** This method will overwrite the key's current value if it already exists in the store; otherwise it simply adds the new key and value.
+     * @summary Adds or updates a value identified by a key to the store.
+     * @method module:store/memory~MemoryStore#addOrUpdate
+     * @param {String} key - Key string.
+     * @param value - Value that is going to be added or updated to the store.
+     * @param {Function} success - Callback for a successful add or update operation.</param>
+     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+    */
+    this.addOrUpdate = function (key, value, success, error) {
+        
+        error = getErrorCallback(error);
+
+        if (validateKeyInput(key, error)) {
+            var index = keys[key];
+            if (index === undefined) {
+                if (holes.length > 0) {
+                    index = holes.splice(0, 1);
+                } else {
+                    index = items.length;
+                }
+            }
+            items[index] = value;
+            keys[key] = index;
+            delay(success, key, value);
+        }
+    };
+
+    /** Removes all the data associated with this store object.
+     * @method module:store/memory~MemoryStore#clear
+     * @param {Function} success>Callback for a successful clear operation.
+     */
+    this.clear = function (success) {
+        items = [];
+        keys = {};
+        holes = [];
+        delay(success);
+    };
+
+    /** Checks whether a key exists in the store.
+     * @method module:store/memory~MemoryStore#contains
+     * @param {String} key - Key string.
+     * @param {Funktion} success - Callback indicating whether the store contains the key or not.</param>
+     */
+    this.contains = function (key, success) {
+        var contained = keys.hasOwnProperty(key);
+        delay(success, contained);
+    };
+
+    /** Gets all the keys that exist in the store.
+     * @method module:store/memory~MemoryStore#getAllKeys
+     * @param {Function} success - Callback for a successful get operation.</param>
+     */
+    this.getAllKeys = function (success) {
+
+        var results = [];
+        for (var name in keys) {
+            results.push(name);
+        }
+        delay(success, results);
+    };
+
+    /** Reads the value associated to a key in the store.
+     * @method module:store/memory~MemoryStore#read
+     * @param {String} key - Key string.
+     * @param {Function} Function - Callback for a successful reads operation.</param>
+     * @param {Function{}Function - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+     */
+    this.read = function (key, success, error) {
+        error = getErrorCallback(error);
+
+        if (validateKeyInput(key, error)) {
+            var index = keys[key];
+            delay(success, key, items[index]);
+        }
+    };
+
+    /** Removes a key and its value from the store.
+     * @method module:store/memory~MemoryStore#remove
+     * @param {String} key - Key string.
+     * @param {Function} success - Callback for a successful remove operation.</param>
+     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+     */
+    this.remove = function (key, success, error) {
+        error = getErrorCallback(error);
+
+        if (validateKeyInput(key, error)) {
+            var index = keys[key];
+            if (index !== undefined) {
+                if (index === items.length - 1) {
+                    items.pop();
+                } else {
+                    items[index] = undefined;
+                    holes.push(index);
+                }
+                delete keys[key];
+
+                // The last item was removed, no need to keep track of any holes in the array.
+                if (items.length === 0) {
+                    holes = [];
+                }
+            }
+
+            delay(success);
+        }
+    };
+
+    /** Updates the value associated to a key in the store.
+     * @method module:store/memory~MemoryStore#update
+     * @param {String} key - Key string.
+     * @param value - New value.
+     * @param {Function} success - Callback for a successful update operation.</param>
+     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
+     * This method errors out if the specified key is not found in the store.
+     */
+    this.update = function (key, value, success, error) {
+        error = getErrorCallback(error);
+        if (validateKeyInput(key, error)) {
+            if (keys.hasOwnProperty(key)) {
+                this.addOrUpdate(key, value, success, error);
+            } else {
+                error({ message: "key not found", key: key });
+            }
+        }
+    };
+}
+
+/** Creates a store object that uses memory storage as its underlying mechanism.
+ * @method MemoryStore.create
+ * @param {String} name - Store name.
+ * @returns {Object} Store object.
+ */
+MemoryStore.create = function (name) {
+    return new MemoryStore(name);
+};
+
+/** Checks whether the underlying mechanism for this kind of store objects is supported by the browser.
+ * @method MemoryStore.isSupported
+ * @returns {Boolean} True if the mechanism is supported by the browser; otherwise false.
+ */
+MemoryStore.isSupported = function () {
+    return true;
+};
+
+/** This function does nothing in MemoryStore as it does not have a connection model.
+*/
+MemoryStore.prototype.close = function () {
+};
+
+MemoryStore.prototype.defaultError = throwErrorCallback;
+
+/** Identifies the underlying mechanism used by the store.
+*/
+MemoryStore.prototype.mechanism = "memory";
+
+
+/** MemoryStore (see {@link MemoryStore}) */
+module.exports = MemoryStore;
\ No newline at end of file


[40/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/djstest.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/djstest.js b/datajs/tests-tmp/common/djstest.js
deleted file mode 100644
index 104c4cf..0000000
--- a/datajs/tests-tmp/common/djstest.js
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
-// we define the @namespace djstest here instead of the a @module name djstest
-
-/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
- * @namespace djstest
- */
-
-if (typeof window !== 'undefined') {
-    //expose to browsers window object
-    window.djstest = window.djstest || {};
-    init(window.djstest);
-} else {
-    //expose in commonjs style
-    module.exports = init();
-}
-
-
-function init (parent) {
-    djstest = parent || {};
-
-    /** Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.
-     * @class Job
-     * @constructor
-     * @returns {Object} Job object
-     */
-    djstest.Job = function () {
-        
-        var currentTask = -1;
-        var tasks = [];
-
-        var failedTasks = 0;
-
-        /** Adds a function to the job queue regardless if the queue is already executing or not.
-         * @method djstest.Job#queue
-         * @param {Function} fn - Function to execute.
-         */
-        this.queue = function (fn) {
-            
-            tasks.push(fn);
-        };
-
-        /** Adds a function to the front of the job queue regardless if the queue is already executing or not.
-         * @method djstest.Job#queueNext
-         * @param {Function} fn - Function to execute.
-         */
-        this.queueNext = function (fn) {
-        
-            if (currentTask < 0) {
-                tasks.unshift(fn);
-            } else {
-                tasks.splice(currentTask + 1, 0, fn);
-            }
-        };
-
-        /** Starts the execution of this job.
-         * @method djstest.Job#run
-         * @param {Function} done - Callback invoked when the job has finished executing all of its enqueued tasks.
-         */
-        this.run = function (done) {
-            /// This method does nothing if called on a unit of work that is already executing.
-            if (currentTask >= 0) {
-                return;
-            }
-
-            if (tasks.length === 0) {
-                done(true);
-                return;
-            }
-
-            /**
-             * @method djstest.Job~makeTaskDoneCallBack
-            */
-            function makeTaskDoneCallBack(failed) {
-                return function () {
-                    // Track the failed task and continue the execution of the job. 
-                    if (failed) {
-                        failedTasks++;
-                    }
-                    currentTask++;
-                    if (currentTask === tasks.length) {
-                        done(failedTasks === 0);
-                    } else {
-                        runNextTask();
-                    }
-                };
-            }
-
-            /** Executes the next function in the queue.
-             * @method djstest.Job~runNextTask
-            */
-            function runNextTask() {
-                defer(function () {
-                    try {
-                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
-                    } catch (e) {
-                        makeTaskDoneCallBack(true)();
-                    }
-                });
-            }
-
-            currentTask = 0;
-            runNextTask();
-        };
-    };
-
-    /** Defers the execution of an arbitrary function that takes no parameters.
-     * @memberof djstest
-     * @inner
-     * @param {Function} fn - Function to schedule for later execution.
-     */
-    function defer(fn) {
-        setTimeout(fn, 0);
-    }
-
-    /** Exposes date values for Date objects to facilitate debugging
-     * @memberof djstest
-     * @inner
-     * @param {Object} data - The object to operate on
-     */
-    function exposeDateValues(data) {
-     
-        if (typeof data === "object") {
-            if (data instanceof Date) {
-                data.__date__ = data.toUTCString();
-            }
-            else {
-                for (var prop in data) {
-                    exposeDateValues(data[prop]);
-                }
-            }
-        }
-
-        return data;
-    }
-
-    /** Determines the name of a function.
-     * @memberof djstest
-     * @inner
-     * @param {String} text - Function text.
-     * @returns {String} The name of the function from text if found; the original text otherwise.
-     */
-    function extractFunctionName(text) {
-
-        var index = text.indexOf("function ");
-        if (index < 0) {
-            return text;
-        }
-
-        var nameStart = index + "function ".length;
-        var parensIndex = text.indexOf("(", nameStart);
-        if (parensIndex < 0) {
-            return text;
-        }
-
-        var result = text.substr(nameStart, parensIndex - nameStart);
-        if (result.indexOf("test") === 0) {
-            result = result.substr("test".length);
-        }
-
-        return result;
-    }
-
-    /** Removes metadata annotations from the specified object.
-     * @memberof djstest
-     * @inner
-     * @param data - Object to remove metadata from; possibly null.
-     */
-    function removeMetadata(data) {
-
-        if (typeof data === "object" && data !== null) {
-            delete data.__metadata;
-            for (var prop in data) {
-                removeMetadata(data[prop]);
-            }
-        }
-    }
-
-    /** Add the unit test cases
-     * @param disable - Indicate whether this test case should be disabled
-    */
-    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
-
-        if (disable !== true) {
-            djstest.addTest(fn, name, arg, timeout);
-        }
-    };
-
-    /** Add the unit test cases
-     * @param disable - Indicate whether this test case should be disabled
-    */
-    djstest.addTest = function (fn, name, arg, timeout) {
-        if (!name) {
-            name = extractFunctionName(fn.toString());
-        }
-
-        test(name, function () {
-            if (!timeout) {
-                timeout = 20000;
-            }
-
-            QUnit.config.testTimeout = timeout;
-            QUnit.stop();
-            fn.call(this, arg);
-        });
-    };
-
-    /** Asserts that a condition is true.
-     * @param {Boolean} test - Condition to test.
-     * @param {String} message - Text message for condition being tested.
-     */
-    djstest.assert = function (test, message) {
-        
-        QUnit.ok(test, message);
-    };
-
-    /** Asserts that the values of the expected and actualobjects are equal.
-     * @memberof djstest
-     * @inner
-     */
-    djstest.assertAreEqual = function (actual, expected, message) {
-        QUnit.equal(actual, expected, message);
-    };
-
-    /** Asserts that the actual and expected objects are the same.
-     */
-    djstest.assertAreEqualDeep = function (actual, expected, message) {
-        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
-    };
-
-    /** Asserts that the actual and expected objects are the same but removes the metadata bevore
-     */
-    djstest.assertWithoutMetadata = function (actual, expected, message) {
-        removeMetadata(actual);
-        removeMetadata(expected);
-        djstest.assertAreEqualDeep(actual, expected, message);
-    };
-
-    /** Calls each async action in asyncActions, passing each action a function which keeps a count and
-     * calls the passed done function when all async actions complete
-     * @param {Array} asyncActions -Array of asynchronous actions to be executed, 
-     * each taking a single parameter - the callback function to call when the action is done.</param>
-     * @param {Function} done - Function to be executed in the last async action to complete.
-     */
-    djstest.asyncDo = function (asyncActions, done) {
-
-        var count = 0;
-        var doneOne = function () {
-            count++;
-            if (count >= asyncActions.length) {
-                done();
-            }
-        };
-
-        if (asyncActions.length > 0) {
-            for ( var i = 0; i < asyncActions.length; i++) {
-                asyncActions[i](doneOne);
-            }
-        } else {
-            done();
-        }
-    };
-
-    /** Makes a deep copy of an object.
-     */
-    djstest.clone = function (object) {
-        if ( object === undefined ) {
-            return undefined;
-        } else if (object === null) {
-            return null;
-        } else if (typeof(object) !== 'object') {
-            return object;
-        } else {
-            var ret = {};
-            for(var key in object) {
-                if(object.hasOwnProperty(key)) {
-                    ret[key] = this.clone(object[key]);
-                }
-            }
-            return ret;
-        }
-        throw("Error cloning an object");
-    };
-
-    /** Destroys the cache and then completes the test
-     * @param cache - The cache to destroy
-     */
-    djstest.destroyCacheAndDone = function (cache) {
-     
-        cache.clear().then(function () {
-            djstest.done();
-        }, function (err) {
-            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
-            djstest.done();
-        });
-    };
-
-    /** Indicates that the currently running test has finished.
-     */
-    djstest.done = function () {
-      
-        QUnit.start();
-    };
-
-    /** Test passes if and only if an exception is thrown.
-     */
-    djstest.expectException = function (testFunction, message) {
-     
-        try {
-            testFunction();
-            djstest.fail("Expected exception but function succeeded: " + " " + message);
-        }
-        catch (e) {
-            // Swallow exception.
-            djstest.pass("Thrown exception expected");
-        }
-    };
-
-    /** Indicates the expected number of asserts, fails test if number is not met.
-     * @param {Number} asserts - Number of asserts expected in test.
-     */
-    djstest.assertsExpected = function (asserts) {
-        
-        expect(asserts);
-    };
-    /** Marks the current test as failed.
-     * @param {String} message - Failure message.
-     */
-    djstest.fail = function (message) {
-
-        QUnit.ok(false, message);
-    };
-
-    /** Returns a function that when invoked will fail this test and be done with it.
-     * @param {String} message - Failure message.
-     * @param {Function} [cleanupCallback] - 
-     * @returns {Function} A new function.
-     */
-    djstest.failAndDoneCallback = function (message, cleanupCallback) {
-
-        return function (err) {
-            message = "" + message + (err) ? JSON.stringify(err) : "";
-            djstest.fail(message);
-            if (cleanupCallback) {
-                try {
-                    cleanupCallback();
-                } catch (e) {
-                    djstest.fail("error during cleanupCallback: " + JSON.stringify(e));
-                }
-            }
-
-            djstest.done();
-        };
-    };
-
-    /** Logs a test message.
-     * @param {String} message - Test message.
-     */
-    djstest.log = function (message) {
-
-        var context = { result: true, actual: true, expected: true, message: message };
-        QUnit.ok(true, message);
-        
-    };
-
-    /** Marks the current test as failed.
-     * @param {String} message - Failure message.
-     */
-    djstest.pass = function (message) {
-        QUnit.ok(true, message);
-    };
-
-    /** Dumps the object as a string
-     * @param {Object} obj - Object to dump
-     */
-    djstest.toString = function (obj) {
-        return QUnit.jsDump.parse(obj);
-    };
-
-    /** Executes the function, pausing test execution until the callback is called
-     * @param {Function} fn - Function to execute; takes one parameter which is the callback
-     * This function is typically used in asynchronous setup/teardown methods</remarks>
-     */
-    djstest.wait = function (fn) {
-        QUnit.stop();
-        fn(function () {
-            QUnit.start();
-        });
-    };
-
-    return djstest;
-}
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/logging.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/logging.js b/datajs/tests-tmp/common/logging.js
deleted file mode 100644
index 9297527..0000000
--- a/datajs/tests-tmp/common/logging.js
+++ /dev/null
@@ -1,5 +0,0 @@
-QUnit.log( function (context) {
-    if (window.console && window.console.log && context.message) {
-        window.console.log(context.result + ' :: ' + context.message  );
-    }
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/mockHttpClient.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/mockHttpClient.js b/datajs/tests-tmp/common/mockHttpClient.js
deleted file mode 100644
index 2ec97e7..0000000
--- a/datajs/tests-tmp/common/mockHttpClient.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-//mockHttpClient.js
-//this object allows for associating a uri with a requestVerfier and mock responses that will be sent back to the client of the httpStack.  
-//It can be used to replace OData's httpClient for testing purposes.
-//
-//RequestVerifiers
-//
-//    A request verifier is a function associated to a particular URI that will be executed by the mockHttpClient when it receives a request with the matching URI.
-//    the callback receives as its only parameter the request object passed to the mockHttpClient.
-//
-//    To register a request verifier, simply do 
-//        
-//            MockHttpClient.addRequestVerifier("http://someUri", function(request) {
-//                djstest.assertAreEqual(request.requestUri,"http://someUri");
-//            }
-//
-//Responses
-//    Mock responses can be associated with a particular URI.  When the MockHttpClient receives a request with a URI mapped to a response, then it will, 
-//    depending on the response status code invoke either the success or the error callbacks. 
-//
-//    To register a response,
-//       
-//           MockHttpClient.addResponse("http://someUri", {status: 200, body:"some body"});
-//
-//Exceptions
-//    MockHttpClient will throw an exception if it receives a request to a URI that is not mapped to either a request verifier or a response.
-//
-
-
-if (typeof window !== 'undefined') {
-    //in browser call init() directly window as context
-    window.MockHttpClient = window.MockHttpClient || {};
-    init(window.MockHttpClient);
-} else {
-    //expose function init to be called with a custom context
-    module.exports = init();
-}
-
-
-function init(parent, undefined) {
-    httpClient = parent || {};
-
-    var responses = {};
-    var requestVerifiers = {};
-
-    httpClient.addRequestVerifier = function (uri, verifier) {
-        requestVerifiers[uri] = verifier;
-        return this;
-    };
-
-    httpClient.addResponse = function (uri, response) {
-        responses[uri] = response;
-        return this;
-    };
-
-    httpClient.async = false;
-
-    httpClient.clear = function () {
-        /** Clears all registered responses and verifiers.
-         * @returns this client
-         */
-        responses = {};
-        requestVerifiers = {};
-        this.async = false;
-        return this;
-    };
-
-    httpClient.request = function (request, success, error) {
-        var uri = request.requestUri;
-        var verifier = requestVerifiers[uri];
-        var response = responses[uri];
-
-        if (verifier === undefined) {
-            verifier = requestVerifiers["*"];
-        }
-
-        if (response === undefined) {
-            response = responses["*"];
-        }
-
-        if (!verifier && !response) {
-            throw { message: "neither verifier or response defined for uri: " + uri };
-        }
-
-        if (verifier) {
-            verifier(request);
-        }
-
-        if (response) {
-            response.requestUri = uri;
-            if (response.statusCode >= 200 && response.statusCode <= 299) {
-                if (this.async) {
-                    setTimeout(function () {
-                        success(response);
-                    });
-                } else {
-                    success(response);
-                }
-            } else {
-                if (this.async) {
-                    setTimeout(function () {
-                        error({ message: "failed test response", request: request, response: response });
-                    });
-                }
-                else {
-                    error({ message: "failed test response", request: request, response: response });
-                }
-            }
-        }
-    };
-
-    httpClient.setAsync = function (value) {
-        this.async = value;
-        return this;
-    };
-
-    return httpClient;
-}
-
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/node-test-setup.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/node-test-setup.js b/datajs/tests-tmp/common/node-test-setup.js
deleted file mode 100644
index c08c439..0000000
--- a/datajs/tests-tmp/common/node-test-setup.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-//Creates the global objects
-
-//tools
-
-var window = {};
-window.djstest = require("./djstest.js");
-window.mockHttpClient = require("./mockHttpClient.js");
-window.odatajs  = require('./../../src/index.js');
-
-global.window = window;
-console.log(global.window.odatajs.node+'asdfasdfasdfasdf');
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/observableHttpClient.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/observableHttpClient.js b/datajs/tests-tmp/common/observableHttpClient.js
deleted file mode 100644
index 9be75f8..0000000
--- a/datajs/tests-tmp/common/observableHttpClient.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// ObservableHttpClient.js
-// This object extends OData's default httpClient by supporting request and response recording sessions, and firing a custom
-// JQuery event for each request/response.
-//
-// The events fired by this object are:
-//      request: Before a request is made
-//      success: Before the primary success handler is called
-//
-// To bind to an event, JQuery event attachers can be used on the object, e.g.
-//      $(observableHttpClient).bind("request", function (request) { ... });
-//
-// To begin a new recording session, use:
-//      var session = observableHttpClient.newSession();
-//
-// Requests and responses are then recorded in session.requests and session.responses. Session can be ended by session.end().
-// Multiple simultaneous sessions are supported.
-
-(function (window, undefined) {
-
-    var ObservableHttpClient = function (provider) {
-        this.provider = provider ? provider : window.odatajs.oData.net.defaultHttpClient;
-    };
-
-    ObservableHttpClient.prototype.newSession = function () {
-        return new Session(this);
-    };
-
-    ObservableHttpClient.prototype.request = function (request, success, error) {
-        var that = this;
-
-        $(this).triggerHandler("request", request);
-        return this.provider.request(request, function (response) {
-            $(that).triggerHandler("success", response);
-            success(response);
-        }, error);
-    };
-
-
-    var Session = function (client) {
-        var that = this;
-
-        this.client = client;
-        this.clear();
-
-        this.requestHandler = function (event, request) { that.requests.push(request); };
-        $(client).bind("request", this.requestHandler);
-
-        this.successHandler = function (event, response) { that.responses.push(response); };
-        $(client).bind("success", this.successHandler);
-    };
-
-    Session.prototype.clear = function () {
-        this.requests = [];
-        this.responses = [];
-    }
-
-    Session.prototype.end = function () {
-        $(this.client).unbind("request", this.requestHandler);
-        $(this.client).unbind("success", this.successHandler);
-    };
-
-    window.ObservableHttpClient = ObservableHttpClient;
-    window.Session = Session;
-
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/odataCacheVerifier.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/odataCacheVerifier.js b/datajs/tests-tmp/common/odataCacheVerifier.js
deleted file mode 100644
index 54e4659..0000000
--- a/datajs/tests-tmp/common/odataCacheVerifier.js
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// CacheVerifier.js
-// This object verifies the operation of the cache.
-// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
-
-(function (window, undefined) {
-
-    var CacheVerifier = function (baseUri, pageSize, total, cacheSize) {
-        /** Creates a new CacheVerifier
-         * @param {String} baseUri - The base URI of the collection
-         * @param {Integer} pageSize - The page size used in the cache
-         * @param {Integer} total - The total number of items in the collection
-         * @param {Integer} cacheSize - Cache size in bytes
-         */
-        this.baseUri = baseUri;
-        this.pageSize = pageSize;
-        this.total = total;
-        this.cacheSize = (cacheSize !== undefined) ? cacheSize : 1024 * 1024;
-        this.actualSize = 0;
-        this.actualCount = 0;
-        this.cachedPages = [];
-        this.exactPageCount = (total % pageSize === 0);
-        this.maxPage = Math.floor(total / pageSize);
-        this.overflowed = this.cacheSize === 0;
-    };
-
-    CacheVerifier.mechanisms = {
-        memory: "memory",
-        indexeddb: "indexeddb",
-        dom: "dom",
-        best: "best"
-    };
-
-    CacheVerifier.isMechanismAvailable = function (mechanism) {
-        /** Determines if the specified local storage mechanism is available
-         * @param mechanism - The name of the mechanism
-         * @returns Whether the mechanism is available
-         */
-        switch (mechanism) {
-            case CacheVerifier.mechanisms.indexeddb:
-                if (window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.indexedDB) {
-                    return true;
-                }
-                else {
-                    return false;
-                }
-                break;
-            case CacheVerifier.mechanisms.dom:
-                if (window.localStorage) {
-                    return true;
-                }
-                else {
-                    return false;
-                }
-                break;
-            case CacheVerifier.mechanisms.memory:
-            case CacheVerifier.mechanisms.best:
-            case undefined:
-                return true;
-            default:
-                return false;
-        }
-    };
-
-    CacheVerifier.prototype.clear = function () {
-        /** Clears the cache in the oracle
-        */
-        this.cachedPages = [];
-        this.actualSize = 0;
-        this.actualCount = 0;
-        this.overflowed = this.cacheSize === 0;
-    };
-
-    CacheVerifier.prototype.verifyRequests = function (requests, responses, index, count, description, backwards, isPrefetch) {
-        /** Verifies the HTTP requests for a single data request, and updates the oracle with cached pages
-         * @param {Array} requests - The sequence of request objects (from OData.defaultHttpClient)
-         * @param {Array} responses - The sequence of response objects (from OData.defaultHttpClient)
-         * @param {Integer} index - The starting index of the read
-         * @param {Integer} count - The count of items in the read
-         * @param {String} description - The description of the requests being verified
-         * @param {Boolean} backwards - Whether or not filterBack is being verified
-         * @param {Boolean} isPrefetch - Whether the requests being verified come from the prefetcher
-         */
-        var that = this;
-
-        index = (index < 0 ? 0 : index);
-        var pageIndex = function (index) {
-            /** Returns the page index that the given item index belongs to
-             * @param {Integer} index - The item index
-             * @returns The page index
-             */
-            return Math.floor(index / that.pageSize);
-        };
-
-        var estimateSize = function (obj) {
-            /** Estimates the size of an object in bytes.
-             * @param {Object} obj - Object to determine the size of.
-             * @returns {Number} Estimated size of the object in bytes.
-             */
-
-            var size = 0;
-            var type = typeof obj;
-
-            if (type === "object" && obj) {
-                for (var name in obj) {
-                    size += name.length * 2 + estimateSize(obj[name]);
-                }
-            } else if (type === "string") {
-                size = obj.length * 2;
-            } else {
-                size = 8;
-            }
-            return size;
-        };
-
-        var expectedUris = [];
-        var responseIndex = 0;
-        if (count >= 0) {
-            var minPage = pageIndex(index);
-            var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(this.total));
-
-            // In the case that the index is outside the range of the collection the minPage will be greater than the maxPage  
-            maxPage = Math.max(minPage, maxPage);
-
-            if (!(isPrefetch && !this.exactPageCount && minPage > this.maxPage)) {
-                for (var page = minPage; page <= maxPage && this.actualCount <= this.total && !(isPrefetch && this.overflowed); page++) {
-                    if (!this.cachedPages[page]) {
-
-                        expectedUris.push(that.baseUri + "?$skip=" + page * this.pageSize + "&$top=" + (this.pageSize));
-
-                        var actualPageSize = 0;
-                        var actualPageCount = 0;
-                        if (responses[responseIndex] && responses[responseIndex].data) {
-                            actualPageSize += estimateSize(responses[responseIndex].data);
-                            actualPageCount += responses[responseIndex].data.value.length;
-                            // Handle server paging skipToken requests
-                            while (responses[responseIndex].data["@odata.nextLink"]) {
-                                var nextLink = responses[responseIndex].data["@odata.nextLink"];
-                                if (nextLink) {
-                                    var index = that.baseUri.indexOf(".svc/", 0);
-                                    if (index != -1) {
-                                        nextLink = that.baseUri.substring(0, index + 5) + nextLink;
-                                    }
-                                }
-
-                                expectedUris.push(nextLink);
-                                responseIndex++;
-                                actualPageSize += estimateSize(responses[responseIndex].data);
-                                actualPageCount += responses[responseIndex].data.value.length;
-                            }
-
-                            actualPageSize += 24; // 24 byte overhead for the pages (i)ndex, and (c)ount fields
-                        }
-
-                        responseIndex++;
-
-                        this.overflowed = this.cacheSize >= 0 && this.actualSize + actualPageSize > this.cacheSize;
-                        if (!this.overflowed) {
-                            this.cachedPages[page] = true;
-                            this.actualSize += actualPageSize;
-                            this.actualCount += actualPageCount;
-                        }
-                    }
-                }
-            }
-        }
-
-        if (backwards) {
-            expectedUris.reverse();
-        }
-
-        var actualUris = $.map(requests, function (r) { return r.requestUri; });
-        djstest.assertAreEqualDeep(actualUris, expectedUris, description);
-    };
-
-    CacheVerifier.getExpectedFilterResults = function (data, filterIndex, filterCount, predicate, backwards) {
-        /** Verifies the cache filter returns the correct data
-         * @param {Array} collection - Array of items in the collection
-         * @param {Integer} filterIndex - The index value
-         * @param {Integer} filterCount - The count value
-         * @param {Function} predicate - Predicate to be applied in filter, takes an item
-         * @param {Boolean} backwards - Whether or not filterBackwards is being verified
-         */
-        if (!data || !data.value) {
-            return data;
-        }
-
-        var value = [];
-        if (filterCount !== 0) {
-            // Convert [item0, item1, ...] into [{ index: 0, item: item0 }, { index: 1, item: item1 }, ...]
-            var indexedCollection = $.map(data.value, function (item, index) {
-                return { index: index, item: item };
-            });
-
-            var grepPredicate = function (element, index) {
-                return predicate(element.item);
-            };
-
-            var index = filterIndex < 0 ? 0 : filterIndex;
-            var count = filterCount < 0 ? indexedCollection.length : filterCount;
-
-            value = backwards ?
-            // Slice up to 'index', filter, then slice 'count' number of items from the end
-                $.grep(indexedCollection.slice(0, index + 1), grepPredicate).slice(-count) :
-            // Slice from 'index' to the end, filter, then slice 'count' number of items from the beginning
-                $.grep(indexedCollection.slice(index), grepPredicate).slice(0, count);
-        }
-
-        var expectedResults = {};
-        for (var property in data) {
-            if (property == "value") {
-                expectedResults[property] = value;
-            } else {
-                expectedResults[property] = data[property];
-            }
-        }
-
-        return expectedResults;
-    };
-
-    window.CacheVerifier = CacheVerifier;
-
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/common/odataVerifyReader.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/common/odataVerifyReader.js b/datajs/tests-tmp/common/odataVerifyReader.js
deleted file mode 100644
index 14bf54e..0000000
--- a/datajs/tests-tmp/common/odataVerifyReader.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-
-// Client for the odata.read oracle service
-
-(function (window, undefined) {
-    var jsonMime = "application/json";
-    var universalMime = "*/*";
-
-    function readFeed(url, success, mimeType, recognizeDates) {
-        /** Calls the ReadFeed endpoint with the specified URL
-         * @param {String} url - The URL to read the feed from
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME media type in the Accept header
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) {
-            success(data);
-        });
-    }
-
-    function readEntry(url, success, mimeType, recognizeDates) {
-        /** Calls the ReadEntry endpoint with the specified URL
-         * @param {String} url - The URL to read the entry from
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME media type in the Accept header
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, success);
-    }
-
-    function readLinksEntry(url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        readJson(
-            url,
-            success
-        );
-    }
-
-    function readLinksFeed(url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        readJson(
-            url,
-            function (data) {
-                success(data);
-            }
-        );
-    }
-
-    function readMetadata(url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success);
-    }
-
-    function readServiceDocument (url, success, mimeType) {
-        /** Calls the ReadServiceDocument endpoint with the specified URL
-         * @param {String} url - The URL to the service
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME type being tested
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success);
-    }
-
-    function readJson(url, success) {
-        $.ajax({
-            url: url,
-            accepts: null,
-            dataType: "json",
-            beforeSend: function (xhr) {
-                xhr.setRequestHeader("Accept", jsonMime);
-                xhr.setRequestHeader("OData-MaxVersion", "4.0");
-            },
-            success: function (data) {
-                success(data);
-            }
-        });
-    }
-
-    function readJsonAcrossServerPages(url, success) {
-        var data = {};
-        var readPage = function (url) {
-            readJson(url, function (feedData) {
-                var nextLink = feedData["@odata.nextLink"];
-                if (nextLink) {
-                    var index = url.indexOf(".svc/", 0);
-                    if (index != -1) {
-                        nextLink = url.substring(0, index + 5) + nextLink;
-                    }
-                }
-
-                if (data.value && feedData.value) {
-                    data.value = data.value.concat(feedData.value);
-                }
-                else {
-                    for (var property in feedData) {
-                        if (property != "@odata.nextLink") {
-                            data[property] = feedData[property];
-                        }
-                    }
-                }
-
-                if (nextLink) {
-                    readPage(nextLink);
-                }
-                else {
-                    success(data);
-                }
-            });
-        };
-
-        readPage(url);
-    }
-
-    function getReadMethod(mimeType) {
-        switch (mimeType) {
-            case jsonMime:
-            case universalMime:
-                /* falls through */
-            default:
-                return "ReadJson";
-        }
-        return undefined;
-    }
-
-    function oracleRequest(method, endpoint, data, mimeType, recognizeDates, success) {
-        /** Requests a JSON object from the oracle service, removing WCF-specific artifacts
-         * @param {String} method - The HTTP method (GET or POST)
-         * @param {String} endpoint - The oracle endpoint
-         * @param {Object} data - The data to send with the request
-         * @param {Function} reviver - The reviver function to run on each deserialized object
-         * @param {Function} success - Success callback
-         */
-        var url = "./common/ODataVerifiyReader.svc/" + endpoint;
-        if (mimeType) {
-            data.mimeType = mimeType;
-        }
-
-        $.ajax({
-            type: method,
-            url: url,
-            data: data,
-            dataType: "text",
-            success: function (data) {
-                var json = JSON.parse(data);
-                success(json);
-            }
-        });
-    }
-
-    function removeProperty(data, property) {
-        /** Removes the specified property recursively from the given object
-         * @param {Object} data - The object to operate on
-         * @param {String} property - The name of the property to remove
-         */
-        if (typeof data === "object" && data !== null) {
-            if (data[property]) {
-                delete data[property];
-            }
-
-            for (var prop in data) {
-                removeProperty(data[prop], property);
-            }
-        }
-    }
-
-    window.ODataVerifyReader = {
-        readFeed: readFeed,
-        readEntry: readEntry,
-        readLinksEntry: readLinksEntry,
-        readLinksFeed: readLinksFeed,
-        readJson: readJson,
-        readJsonAcrossServerPages: readJsonAcrossServerPages,
-        readMetadata: readMetadata,
-        readServiceDocument: readServiceDocument
-    };
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/done.txt
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/done.txt b/datajs/tests-tmp/done.txt
deleted file mode 100644
index 85ca39b..0000000
--- a/datajs/tests-tmp/done.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-This tests-tmp folder will repleace the tests folder.
-The plan is to 
-- select test case per testcase,
-- verify it, and 
-- copy it to the tmp-tests
-- once each tests is checkt and copied the folder tests will be deleted and replaced by tmp-tests
-
-DONE
-
-TestSynchronizerClient.js 
-  -> removed
-  -> Moved from custom c# logging service to jenkins
-
-ODataReadOracle.js 
-  -> removed
-  -> TODO check dependencies
-
-rx.js 
-  -> removed
-  -> TODO check dependencies
-
-odata-json-test.js 
-  -> copied and splittet 
-
-  
-ODataReadOracle.js -> odataVerifyReader.js
-ODataReadOracle.svc -> odataVerifyReader.svc
-
-ODataReadOracle -> odataVerifyReader

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/BasicAuthDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/BasicAuthDataService.svc b/datajs/tests-tmp/endpoints/BasicAuthDataService.svc
deleted file mode 100644
index e059314..0000000
--- a/datajs/tests-tmp/endpoints/BasicAuthDataService.svc
+++ /dev/null
@@ -1,124 +0,0 @@
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.BasicAuthDataService" %>
-/*
- * 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.
- */
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Web;
-    using System.Text;
-    using System.Web;
-
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class BasicAuthDataService : DataService<BasicAuthDataSource>
-    {
-        const string Username = "djsUser";
-        const string Password = "djsPassword";
-        
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-            config.UseVerboseErrors = true;
-        }
-
-        public BasicAuthDataService()
-            : base()
-        {
-            this.ProcessingPipeline.ProcessingRequest += OnRequest;
-        }
-
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-
-        private static void UnauthorizedRequest(DataServiceOperationContext context)
-        {
-            context.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"DataJS.Tests\"";
-            throw new DataServiceException(401, "401 Unauthorized");
-        }
-
-        private void OnRequest(object sender, DataServiceProcessingPipelineEventArgs e)
-        {
-            string authHeader = e.OperationContext.RequestHeaders["Authorization"];
-            
-            // Validate the Authorization header
-            if (authHeader == null || !authHeader.StartsWith("Basic"))
-            {
-                UnauthorizedRequest(e.OperationContext);
-            }
-
-            // Decode the username and password from the header
-            string base64Credentials = authHeader.Substring(6);
-            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(':');
-            if (credentials.Length != 2 || !(credentials[0].Equals(Username) && credentials[1].Equals(Password)))
-            {
-                UnauthorizedRequest(e.OperationContext);
-            }
-        }
-    }
-
-    public class BasicAuthDataSource : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Customer> Customers
-        {
-            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
-            foreach (int i in Enumerable.Range(1, 16))
-            {
-                customers.Add(new Customer()
-                {
-                    ID = i,
-                    Name = "Customer " + i
-                });
-            }
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Customer
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/CustomAnnotations.xml
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/CustomAnnotations.xml b/datajs/tests-tmp/endpoints/CustomAnnotations.xml
deleted file mode 100644
index ebf4e26..0000000
--- a/datajs/tests-tmp/endpoints/CustomAnnotations.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<!--/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<?xml version="1.0" encoding="utf-8"?>
-<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
-  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
-    <Schema xmlns="http://schemas.microsoft.com/ado/2007/05/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:mcns="http://MyCustomNamespace.com"
-             Namespace="DataJS.Tests">
-      <EntityType Name="MappedEntry" mcns:MyCustomAnnotation="My custom attribute.">
-        <Key mcns:MyCustomAnnotation="//">
-          <PropertyRef Name="ID" mcns:MyCustomAnnotation="  "/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author" m:FC_KeepInContent_5="false" m:FC_SourcePath_5="Contributor/Name" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorName" m:FC_KeepInContent_4="false" m:FC_SourcePath_4="Contributor/Email" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorEmail" m:FC_KeepInContent_3="false" m:FC_SourcePath_3="Uri" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationAuthorUri" m:FC_KeepInContent_2="false" m:FC_SourcePath_2="Name" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorName" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Email" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorEmail" m:FC_KeepInContent="false" m:FC_SourcePath="Contributor/Uri" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationContributorUri"/>
-        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished"/>
-        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
-        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary"/>
-        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
-        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
-        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="false" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
-      </EntityType>
-      <ComplexType Name="Author" mcns:MyCustomAnnotation="">
-        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=""/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor"/>
-      </ComplexType>
-      <ComplexType Name="Contributor">
-        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=" "/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="true"/>
-      </ComplexType>
-      <ComplexType Name="Location">
-        <Property Name="Lat" Nullable="false" Type="Edm.Single" mcns:MyCustomAnnotation="27"/>
-        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
-      </ComplexType>
-      <EntityType Name="ReplicatedEntry">
-        <Key>
-          <PropertyRef Name="ID"/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author2" m:FC_KeepInContent_5="true" m:FC_SourcePath_5="Contributor/Uri" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorUri" m:FC_KeepInContent_4="true" m:FC_SourcePath_4="Contributor/Name" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorName" m:FC_KeepInContent_3="true" m:FC_SourcePath_3="Contributor/Email" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationContributorEmail" m:FC_KeepInContent_2="true" m:FC_SourcePath_2="Uri" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorUri" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Name" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorName" m:FC_KeepInContent="true" m:FC_SourcePath="Email" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationAuthorEmail" mcns:MyCustomAnnotation="b>100/b>"/>
-        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished" mcns:MyCustomAnnotation=" . "/>
-        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
-        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary" mcns:MyCustomAnnotation="/Property"/>
-        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
-        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
-        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
-        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
-        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location2" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="true" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
-      </EntityType>
-      <ComplexType Name="Author2">
-        <Property Name="Email" Nullable="true" Type="Edm.String"/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor2"/>
-      </ComplexType>
-      <ComplexType Name="Contributor2">
-        <Property Name="Email" Nullable="true" Type="Edm.String"/>
-        <Property Name="Name" Nullable="true" Type="Edm.String"/>
-        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
-      </ComplexType>
-      <ComplexType Name="Location2">
-        <Property Name="Lat" Nullable="false" Type="Edm.Single"/>
-        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
-      </ComplexType>
-      <EntityType Name="DerivedEntry" m:FC_KeepInContent="false" m:FC_SourcePath="MappedInDerivedField" m:FC_TargetPath="mappedField/@mappedInDerived" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy" BaseType="DataJS.Tests.BaseEntry">
-        <Property Name="UnmappedConcreteField" Nullable="true" Type="Edm.String"/>
-        <Property Name="MappedConcreteField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField/@mappedConcrete" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
-      </EntityType>
-      <EntityType Name="BaseEntry">
-        <Key>
-          <PropertyRef Name="ID"/>
-        </Key>
-        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
-        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
-        <Property Name="MappedInDerivedField" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="false"/>
-        <Property Name="MappedField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
-      </EntityType>
-      <EntityContainer Name="EpmDataSource" m:IsDefaultEntityContainer="true" mcns:MyCustomAnnotation="0">
-        <EntitySet Name="MappedEntries" EntityType="DataJS.Tests.MappedEntry"/>
-        <EntitySet Name="ReplicatedEntries" EntityType="DataJS.Tests.ReplicatedEntry"/>
-        <EntitySet Name="HierarchicalEntries" EntityType="DataJS.Tests.BaseEntry"/>
-        <FunctionImport Name="ResetData" m:HttpMethod="POST" mcns:MyCustomAnnotation="null"/>
-      </EntityContainer>
-      <mcns:EmptyElement></mcns:EmptyElement>
-      <mcns:ParentCustomElement mcns:MyCustomAnnotation="annotation" mcns:MySecondCustomAnnotation="annotation 2">
-        <mcns:CustomChildElement1>Custom metadata 1.</mcns:CustomChildElement1>
-        <mcns:CustomChildElement2>Custom metadata 2.</mcns:CustomChildElement2>
-      </mcns:ParentCustomElement>
-    </Schema>
-  </edmx:DataServices>
-</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/CustomDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/CustomDataService.svc b/datajs/tests-tmp/endpoints/CustomDataService.svc
deleted file mode 100644
index 67fcfd0..0000000
--- a/datajs/tests-tmp/endpoints/CustomDataService.svc
+++ /dev/null
@@ -1,85 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory"
-    Service="DataJS.Tests.CustomDataService" %>
-
-
-using System.Collections;
-using System.IO;
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Web;
-
-    /// <summary>
-    /// Custom data service that does not use OData
-    /// </summary>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class CustomDataService
-    {
-        static readonly Item[] data = Enumerable.Range(0, 16).Select(i => new Item
-        {
-            ID = i,
-            Name = "Item " + i
-        }).ToArray();
-
-        // This uses the same URI template as OData so that the CacheOracle can be reused
-        [OperationContract]
-        [WebGet(UriTemplate = "ReadRange?$skip={skip}&$top={top}")]
-        public Stream ReadRange(int skip, int top)
-        {
-            IEnumerable selectData = data.Skip(skip).Take(top);
-            Dictionary<string, object> result = new Dictionary<string, object>();
-            List<Dictionary<string, string>> value = new List<Dictionary<string, string>>(); 
-            foreach (Item d in selectData)
-            {
-                Dictionary<string, string> item = new Dictionary<string, string>();
-                item.Add("ID", d.ID.ToString());
-                item.Add("Name", d.Name);
-                value.Add(item);
-            }
-            
-            result.Add("value", value);
-            return ReaderUtils.ConvertDictionarytoJsonlightStream(result);
-        }
-
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public int Count()
-        {
-            return data.Count();
-        }
-    }
-
-    public class Item
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/EpmDataService.svc b/datajs/tests-tmp/endpoints/EpmDataService.svc
deleted file mode 100644
index 316c9ae..0000000
--- a/datajs/tests-tmp/endpoints/EpmDataService.svc
+++ /dev/null
@@ -1,336 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.EpmDataService" %>
-
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel.Web;
-
-    /// <summary>
-    /// A data service that uses EPM
-    /// </summary>
-    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class EpmDataService : DataService<EpmDataSource>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-            config.UseVerboseErrors = true;
-
-        }
-        
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-    }
-
-    public class EpmDataSource : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<MappedEntry> MappedEntries
-        {
-            get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
-        }
-
-        public IQueryable<ReplicatedEntry> ReplicatedEntries
-        {
-            get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
-        }
-
-        public IQueryable<BaseEntry> HierarchicalEntries
-        {
-            get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            MappedEntry[] mappedEntries = new MappedEntry[]
-            {
-                new MappedEntry
-                {
-                    ID = 0,
-                    UnmappedField = "Unmapped0",
-                    Author = new Author
-                    {
-                        Email = "AuthorEmail0",
-                        Name = "AuthorName0",
-                        Uri = "http://www.example.com/AuthorUri",
-                        Contributor = new Contributor
-                        {
-                            Email = "ContributorEmail0",
-                            Name = "ContributorName0",
-                            Uri = "http://www.example.com/ContributorUri",
-                        },
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = "Rights0",
-                    Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
-                    Title = "Title<b>0</b>",
-                    Updated = "2000-01-01T00:00:00-08:00",
-                    CustomElement = "CustomElement0",
-                    CustomAttribute = "CustomAttribute0",
-                    NestedElement1 = "NestedElement1_0",
-                    NestedElement2 = "NestedElement2_0",
-                    CommonAttribute1 = "CommonAttribute1_0",
-                    CommonAttribute2 = "CommonAttribute2_0",
-                    Location = new Location
-                    {
-                        Lat = 3.14f,
-                        Long = 2.72f
-                    }
-                },
-                
-                new MappedEntry
-                {
-                    ID = 1,
-                    UnmappedField = null,
-                    Author = new Author
-                    {
-                        Email = null,
-                        Name = string.Empty,
-                        Uri = "http://www.example.com/AuthorUri1",
-                        Contributor = new Contributor
-                        {
-                            Email = null,
-                            Name = string.Empty,
-                            Uri = "http://www.example.com/ContributorUri1",
-                        },
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = null,
-                    Summary = "",
-                    Title = "Title<i>1</i>",
-                    Updated = "2111-01-01T00:00:00-08:00",
-                    CustomElement = null,
-                    NestedElement1 = string.Empty,
-                    NestedElement2 = "NestedElement2_1",
-                    CustomAttribute = null,
-                    CommonAttribute1 = string.Empty,
-                    CommonAttribute2 = "CommonAttribute2_1",
-                    Location = new Location
-                    {
-                        Lat = float.MaxValue,
-                        Long = float.MinValue
-                    }
-                },
-                
-                new MappedEntry
-                {
-                    ID = 2,
-                    UnmappedField = "Unmapped2",
-                    Author = new Author
-                    {
-                        Email = "AuthorEmail2",
-                        Name = "AuthorName2",
-                        Uri = "http://www.example.com/AuthorUri2",
-                        Contributor = null
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = "Rights2",
-                    Summary = "Summary2",
-                    Title = "Title2",
-                    Updated = "2000-01-01T00:00:00-08:00",
-                    CustomElement = "CustomElement2",
-                    CustomAttribute = "CustomAttribute2",
-                    NestedElement1 = "NestedElement1_2",
-                    NestedElement2 = "NestedElement2_2",
-                    CommonAttribute1 = "CommonAttribute1_2",
-                    CommonAttribute2 = "CommonAttribute2_2",
-                    Location = null
-                },
-            };
-            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
-
-            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
-            {
-                ID = item.ID,
-                UnmappedField = item.UnmappedField,
-                Author = item.Author == null ? null : new Author2
-                {
-                    Email = item.Author.Email,
-                    Name = item.Author.Name,
-                    Uri = item.Author.Uri,
-                    Contributor = item.Author.Contributor == null ? null : new Contributor2
-                    {
-                        Name = item.Author.Contributor.Name,
-                        Email = item.Author.Contributor.Email,
-                        Uri = item.Author.Contributor.Uri
-                    },
-                },
-                Published = item.Published,
-                Rights = item.Rights,
-                Summary = item.Summary,
-                Title = item.Title,
-                Updated = item.Updated,
-                CustomElement = item.CustomElement,
-                CustomAttribute = item.CustomAttribute,
-                NestedElement1 = item.NestedElement1,
-                NestedElement2 = item.NestedElement2,
-                CommonAttribute1 = item.CommonAttribute1,
-                CommonAttribute2 = item.CommonAttribute2,
-                Location = item.Location == null ? null : new Location2
-                {
-                    Lat = item.Location.Lat,
-                    Long = item.Location.Long
-                }
-            }));
-
-            BaseEntry[] hierarchicalEntries = new BaseEntry[]
-            {
-                new BaseEntry
-                {
-                    ID = 0,
-                    MappedField = "MappedField0",
-                    MappedInDerivedField = "MappedInDerivedField0",
-                    UnmappedField = "UnmappedField0"
-                },
-                new DerivedEntry
-                {
-                    ID = 1,
-                    MappedField = "MappedField1",
-                    MappedInDerivedField = "MappedInDerivedField1",
-                    UnmappedField = "UnmappedField1",
-                    MappedConcreteField = "MappedConcreteField1",
-                    UnmappedConcreteField = "UnmappedConcreteField1"
-                },
-            };
-            Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Author
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-        public Contributor Contributor { get; set; }
-    }
-
-    public class Contributor
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-    }
-    
-    public class Location
-    {
-        public float Lat { get; set; }
-        public float Long { get; set; }
-    }
-
-    public class Author2
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-        public Contributor2 Contributor { get; set; }
-    }
-
-    public class Contributor2
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-    }
-
-    public class Location2
-    {
-        public float Lat { get; set; }
-        public float Long { get; set; }
-    }
-    
-    public class MappedEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public Author Author { get; set; }
-        public string Published { get; set; }
-        public string Rights { get; set; }
-        public string Summary { get; set; }
-        public string Title { get; set; }
-        public string Updated { get; set; }
-        public string CustomElement { get; set; }
-        public string CustomAttribute { get; set; }
-        public string NestedElement1 { get; set; }
-        public string NestedElement2 { get; set; }
-        public string CommonAttribute1 { get; set; }
-        public string CommonAttribute2 { get; set; }
-        public Location Location { get; set; }
-    }
-
-    public class ReplicatedEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public Author2 Author { get; set; }
-        public string Published { get; set; }
-        public string Rights { get; set; }
-        public string Summary { get; set; }
-        public string Title { get; set; }
-        public string Updated { get; set; }
-        public string CustomElement { get; set; }
-        public string CustomAttribute { get; set; }
-        public string NestedElement1 { get; set; }
-        public string NestedElement2 { get; set; }
-        public string CommonAttribute1 { get; set; }
-        public string CommonAttribute2 { get; set; }
-        public Location2 Location { get; set; }
-    }
-    
-    public class BaseEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public string MappedInDerivedField { get; set; }
-        public string MappedField { get; set; }
-    }
-    
-    public class DerivedEntry : BaseEntry
-    {
-        public string UnmappedConcreteField { get; set; }
-        public string MappedConcreteField { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/ErrorDataService.svc b/datajs/tests-tmp/endpoints/ErrorDataService.svc
deleted file mode 100644
index 052a2df..0000000
--- a/datajs/tests-tmp/endpoints/ErrorDataService.svc
+++ /dev/null
@@ -1,78 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.ErrorDataService" %>
-
-
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-
-    /// <summary>
-    /// A data service that contains in-stream errors
-    /// </summary>
-    public class ErrorDataService : DataService<ErrorDataSource>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-        }
-    }
-
-    public class ErrorDataSource
-    {
-        public IQueryable<ErrorType> Entities
-        {
-            get
-            {
-                ErrorType[] entities = new ErrorType[]
-                {
-                    new ErrorType(() => 0),
-                    new ErrorType(() => { throw new ApplicationException(); })
-                };
-
-                return entities.AsQueryable();
-            }
-        }
-    }
-    
-    public class ErrorType
-    {
-        Func<int> generateID;
-        
-        public ErrorType(Func<int> generateID)
-        {
-            this.generateID = generateID;
-        }
-        
-        public int ID
-        {
-            get { return this.generateID(); }
-        }
-    }
-}
\ No newline at end of file


[13/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/cache-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/cache-tests.js b/odatajs/tests/cache-tests.js
new file mode 100644
index 0000000..f4c1a1c
--- /dev/null
+++ b/odatajs/tests/cache-tests.js
@@ -0,0 +1,1191 @@
+/*
+ * 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.
+*/
+
+(function (window, undefined) {
+
+    module("Unit");
+    var foodsFeed = "./endpoints/FoodStoreDataServiceV4.svc/Foods";
+    var collectionSize = 16;
+
+    var thenFailTest = function (err) {
+        if (err && err.message) {
+            djstest.fail(err.message);
+        } else {
+            djstest.fail("unexepected promise failure");
+        }
+
+        djstest.done();
+    };
+
+    djstest.addTest(function dataCacheCountTest() {
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
+        cache.count().then(function (count) {
+            djstest.assertAreEqual(count, collectionSize, "expected count for Foods");
+            djstest.destroyCacheAndDone(cache);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheCountOnLocalTest() {
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed, pageSize: collectionSize + 10, mechanism: "memory" });
+        cache.readRange(0, collectionSize + 10).then(function (data) {
+            var expectedCount = data.value ? data.value.length : 0;
+            cache.count().then(function (count) {
+                djstest.assertAreEqual(count, expectedCount, "expected count for expectedCount");
+                djstest.destroyCacheAndDone(cache);
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheCountAbortTest() {
+        // Abort before completion.
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
+        var item = cache.count().then(thenFailTest, function (err) {
+            djstest.assertAreEqual(true, err.canceled, "err.aborted is true");
+            djstest.destroyCacheAndDone(cache);
+        }).cancel();
+    });
+
+    var createNewCache = function (options) {
+
+        var thenSuccess = null;
+
+        var resolved = false;
+        var rejected = false;
+
+        var args = null;
+
+        this.then = function (success) {
+            if (resolved) {
+                success.apply(null, args);
+            } else if (!rejected) {
+                thenSuccess = success;
+            }
+        };
+
+        var resolve = function (/*args*/) {
+            resolved = true;
+            args = arguments;
+            if (thenSuccess) {
+                thenSuccess.apply(null, arguments);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache(options);
+        cache.clear().then(function () {
+            var newCache = odatajs.cache.createDataCache(options);
+            resolve(newCache);
+        }, function (err) {
+            rejected = true;
+            thenFailTest(err);
+        });
+
+        return this;
+    };
+
+    djstest.addTest(function dataCacheReadRangeSingleTest() {
+        // Read a new range.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 1, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "food id is 0.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeExactPageTest() {
+        // Read exactly one page.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 2).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 2, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeMultiplePageTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 3).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 3, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                        djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeSyncDelaysTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).
+                    then(function (data) {
+                        djstest.assertAreEqual(counter, 0, "counter is zero for first set of results");
+                        djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
+                        counter++;
+                        cache.readRange(0, 1).
+                            then(function (data) {
+                                djstest.assertAreEqual(counter, 2, "counter is two because even sync results are delayed)");
+                                djstest.assertAreEqual(cache.stats.netReads, 1, "no additional requests since requested data is in cache");
+                                djstest.done();
+                            }, thenFailTest);
+                        djstest.assertAreEqual(counter, 1, "counter is one because readRange hasn't run (even if results are cached)");
+                        counter++;
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangesWithDestroyTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
+        var counter = 0;
+        createNewCache(options).then(function (cache) {
+            cache.readRange(0, 1).then(function (data) {
+                djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
+                cache.clear().then(function () {
+                    djstest.assertAreEqual(cache.stats.netReads, 0, "stats cleared in destroy");
+                    cache.readRange(0, 1).then(function (data) {
+                        djstest.assertAreEqual(cache.stats.netReads, 1, "request made after destroy to fulfill the readRange");
+                        djstest.done();
+                    }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadSimultaneousTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        var theCache;
+        var checkDataAndCount = function (data) {
+            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
+            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
+            djstest.assertAreEqual(theCache.stats.netReads, 1, "single theCache.stats.netReads");
+            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
+            counter++;
+            if (counter === 3) {
+                djstest.done();
+            }
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheMultipleClearTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        var checkCount = function (data) {
+            djstest.assert(true, "clear then was called");
+            counter++;
+            if (counter === 3) {
+                djstest.done();
+            }
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).then(function () {
+                    cache.clear().then(checkCount, thenFailTest);
+                    cache.clear().then(checkCount, thenFailTest);
+                    cache.clear().then(checkCount, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheOnIdleIsFired() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
+
+        createNewCache(options).
+            then(function (cache) {
+                var counter = 0;
+                var clearSucceeded = false;
+
+                var thenFailThisTest = function (err) {
+                    if (err && err.message) {
+                        djstest.fail(err.message);
+                    } else {
+                        djstest.fail("unexepected promise failure");
+                    }
+                };
+
+                cache.onidle = function () {
+                    counter++;
+                    djstest.assertAreEqual(counter, 1, "onidle was called 1 times");
+                    djstest.assert(clearSucceeded, "onidle was called after destroy");
+                    djstest.done();
+                };
+
+                cache.readRange(0, 1).then(null, thenFailThisTest);
+                cache.readRange(0, 1).then(null, thenFailThisTest);
+                cache.readRange(3, 4).then(function () {
+                    cache.readRange(5, 6).then(function () {
+                        cache.clear().then(function () {
+                            clearSucceeded = true;
+                        }, thenFailThisTest);
+                    }, thenFailThisTest);
+                }, thenFailThisTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheOnIdleFiresOnErrorTest() {
+
+        var errorResponse = false;
+        var httpClient = {
+            request: function (request, success, error) {
+                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ d: [1, 2] }) };
+                if (!errorResponse) {
+                    errorResponse = true;
+                    setTimeout(function () {
+                        success(response);
+                    }, 0);
+                } else {
+                    response.statusCode = 500;
+                    response.body = "bad response";
+                    setTimeout(function () {
+                        error({ message: "HTTP request failed", request: request, response: response });
+                    }, 0);
+                }
+            }
+        };
+
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0, httpClient: httpClient };
+
+        createNewCache(options).
+            then(function (cache) {
+                var counter = 0;
+                var errorHandlerCalled = false;
+
+                var thenFailThisTest = function (err) {
+                    if (err && err.message) {
+                        if (errorResponse) {
+                            djstest.assertAreEqual(err.message, "HTTP request failed", "Error is the expected one");
+                            errorHandlerCalled = true;
+                        } else {
+                            djstest.fail(err.message);
+                        }
+                    } else {
+                        djstest.fail("unexepected promise failure");
+                    }
+                };
+
+                cache.onidle = function () {
+                    counter++;
+                    djstest.assertAreEqual(counter, 1, "onidle was called");
+                    djstest.assert(errorHandlerCalled, "error handler was called before onidle");
+                    cache.onidle = null;
+                    cache.clear().then(function () {
+                        djstest.done();
+                    }, thenFailTest);
+                };
+                cache.readRange(0, 2).then(function () {
+                    cache.readRange(2, 4).then(function () {
+                        djstest.fail("unexpected readRange success");
+                    }, thenFailThisTest);
+                }, thenFailThisTest);
+            }, thenFailTest);
+    });
+
+
+    djstest.addTest(function dataCacheOdataSourceNormalizedURITest() {
+        var requestsMade = 0;
+        var httpClient = {
+            request: function (request, success, error) {
+                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ value: [1, 2] }) };
+                if (requestsMade === 0) {
+                    djstest.pass("Cache made first request for data from the source");
+                    requestsMade++;
+                } else {
+                    // In memory storage will make a second request from the new cache since two caches with the same name will coexist
+                    if (window.mozIndexedDB || window.localStorage || requestsMade > 1) {
+                        djstest.fail("Unexpected request to the source");
+                    } else {
+                        djstest.pass("In memory cache requested the data from the source");
+                    }
+                }
+                setTimeout(function () {
+                    success(response);
+                }, 0);
+            }
+        };
+
+        var options = { name: "cache", source: "http://exampleuri.com/my service.svc", pageSize: 2, prefetchSize: 0, httpClient: httpClient };
+
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 2).then(function () {
+                    options.source = "HtTp://ExampleURI.cOm/my%20service.svc";
+                    var newCache = odatajs.cache.createDataCache(options);
+                    newCache.readRange(0, 2).then(function (data) {
+                        djstest.assertAreEqualDeep(data.value, [1, 2], "Got the expected data from the new cache instance");
+                        newCache.clear().then(function () {
+                            djstest.done();
+                        }, thenFailTest);
+                    }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+
+    djstest.addTest(function dataCachePrefetchAllTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: -1 };
+        var counter = 0;
+        var theCache;
+
+        var callback = function () {
+            counter++;
+            if (counter === 2) {
+                djstest.assertAreEqual(1, theCache.stats.netReads, "single page to satisfy read (" + theCache.stats.netReads + ")");
+                djstest.assert(theCache.stats.prefetches > 1, "theCache.stats.prefetches(" + theCache.stats.prefetches + ") > 1 - multiple prefetches");
+                djstest.done();
+            }
+        };
+
+        var checkDataAndCount = function (data) {
+            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
+            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
+            djstest.assertAreEqual(1, theCache.stats.netReads, "single theCache.stats.netReads");
+            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
+            callback();
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.onidle = function () {
+                    djstest.log("onidle fired");
+                    callback();
+                };
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeTakeMoreThanCollectionCountTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.count().then(function (count) {
+                    cache.readRange(0, count + 1).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, count, "all items in the collection were read.");
+                            cache.readRange(2, count + 1).
+                                then(function (data) {
+                                    djstest.assertAreEqual(data.value.length, count - 2, "all requested in the collection were read.");
+                                    djstest.assertAreEqual(data.value[0].FoodID, 2, "first read food id is 2.");
+                                    djstest.done();
+                                }, thenFailTest);
+                        }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeSkipMoreThanCollectionCountTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.count().then(function (count) {
+                    cache.readRange(count + 1, 5).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, 0, "no items were read.");
+                            djstest.done();
+                        }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeTakeMoreThanPrefetchSizeTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 4).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, 4, "all requested in the collection were read.");
+                            djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                            djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                            djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
+                            djstest.assertAreEqual(data.value[3].FoodID, 3, "third food id is 3.");
+                            djstest.done();
+                        }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheRangeInvalidIndexAndCount() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
+        var counter = 0;
+
+        var thenFailSuccess = function () {
+            djstest.fail("Call to success was unexpected");
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var thenFailError = function () {
+            djstest.fail("Call to error was unexpected");
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var invalidValues = [-5, -1, null, undefined, NaN, Infinity, "5", "this is not a number"];
+        var tests = [];
+        $.each(invalidValues, function (_, value) {
+            tests.push({ i: value, c: 0 });
+            tests.push({ i: 0, c: value });
+            tests.push({ i: value, c: value });
+        });
+
+        createNewCache(options).
+            then(function (cache) {
+                var i, len;
+                for (i = 0, len = tests.length; i < len; i++) {
+                    var test = tests[i];
+                    try {
+                        cache.readRange(test.i, test.c).then(thenFailSuccess, thenFailTest);
+                    } catch (err) {
+                        djstest.pass("Expected exception was thrown: " + err.message);
+                        counter++;
+                    }
+                }
+                if (counter === tests.length) {
+                    djstest.done();
+                }
+            });
+    });
+
+
+    djstest.addTest(function cacheOptionsForCountTest() {
+        var httpClient = {
+            request: function (r, success, error) {
+                window.setTimeout(function () {
+                    success({ data: "10" });
+                }, 1);
+                return null;
+            }
+        };
+        var cache = odatajs.cache.createDataCache({
+            name: "mem", mechanism: "memory", source: "http://www.example.org/service/",
+            httpClient: httpClient
+        });
+        cache.count().then(function (count) {
+            djstest.assertAreEqual(count, 10, "count value");
+            djstest.done();
+        }, djstest.failAndDoneCallback("failed to get count"));
+    });
+
+    djstest.addTest(function dataCacheDestoryStopsThePrefetcherTest() {
+        var oldHttpClientRequest = window.odatajs.oData.net.defaultHttpClient.request;
+        var prefetchCount = 0;
+        var theCache;
+
+        window.odatajs.oData.net.defaultHttpClient.request = function (request, success, error) {
+            prefetchCount++;
+            djstest.assert(prefetchCount <= 3, "Expected prefetch request");
+            if (prefetchCount === 3) {
+                theCache.clear().then(function () {
+                    djstest.assertAreEqual(prefetchCount, 3, "cache.clear() stopped the prefetcher");
+                    djstest.done();
+                    window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
+                }, thenFailTest);
+                return {
+                    abort: function () { }
+                };
+            }
+            return oldHttpClientRequest(request, success, error);
+        };
+
+        try {
+            var options = { name: "cache", source: foodsFeed, pageSize: 1, prefetchSize: -1 };
+            createNewCache(options).then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 0).then(null, thenFailTest);
+            });
+        } catch (e) {
+            window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
+            djstest.fail("Exception thrown,  prefetchSize: " + tests[count] + " error:  " + e.message);
+            djstest.done();
+        }
+    });
+
+    djstest.addTest(function dataCacheFilterTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 3, prefetchSize: -1 };
+        var counter = 0;
+
+        var singleItemPredicate = function (data) {
+            return data.FoodID === 2;
+        };
+
+        var multipleItemPredicate = function (data) {
+            return data.FoodID % 2 === 1;
+        };
+
+        var noItemPredicate = function (data) {
+            return data.Name === "something i would never eat";
+        };
+
+        var allItemPredicate = function (data) {
+            return data.FoodID >= 0;
+        };
+
+        var doneAfterAllTests = function () {
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var last = collectionSize - 1;
+        var tests = [
+            { index: 0, count: -5, predicate: singleItemPredicate },    // Single match in entire collection
+            {index: 2, count: 1, predicate: singleItemPredicate },     // Single match, single count
+            {index: 3, count: 1, predicate: singleItemPredicate },     // Single match skipped, i.e. no matches
+            {index: 0, count: -1, predicate: multipleItemPredicate },  // Multiple matches in entire collection
+            {index: 0, count: 5, predicate: multipleItemPredicate },   // Multiple matches, take partial
+            {index: 3, count: 5, predicate: multipleItemPredicate },   // Multiple matches, skip/take partial
+            {index: 7, count: 10, predicate: multipleItemPredicate },  // Multiple matches, skip partial, take past end of collection
+            {index: 13, count: 4, predicate: allItemPredicate },       // All items match, skip/take partial
+            {index: 0, count: 20, predicate: noItemPredicate },        // No matches
+            {index: 0, count: 0, predicate: allItemPredicate },        // Zero count
+            {index: -5, count: 1, predicate: allItemPredicate },       // Negative index
+            {index: last + 1, count: 1, predicate: allItemPredicate }, // Index past end of collection
+
+            {index: last, count: -5, predicate: singleItemPredicate, backwards: true },        // Single match in entire collection
+            {index: 2, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match, single count
+            {index: 1, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match skipped, i.e. no matches
+            {index: last, count: -1, predicate: multipleItemPredicate, backwards: true },      // Multiple matches in entire collection
+            {index: last, count: 6, predicate: multipleItemPredicate, backwards: true },       // Multiple matches, take partial
+            {index: last - 3, count: 5, predicate: multipleItemPredicate, backwards: true },   // Multiple matches, skip/take partial
+            {index: 13, count: 10, predicate: multipleItemPredicate, backwards: true },        // Multiple matches, skip partial, take past end of collection
+            {index: 4, count: 13, predicate: allItemPredicate, backwards: true },              // All items match, skip/take partial
+            {index: last, count: 20, predicate: noItemPredicate, backwards: true },            // No matches
+            {index: 0, count: 0, predicate: allItemPredicate, backwards: true },               // Zero count
+            {index: -5, count: 1, predicate: allItemPredicate, backwards: true },              // Negative index
+            {index: last + 1, count: 1, predicate: allItemPredicate, backwards: true },        // Index past end of collection
+
+            {index: "foo", count: 1, predicate: singleItemPredicate, exception: { message: "'index' must be a valid number.", index: NaN} },
+            { index: 0, count: "foo", predicate: multipleItemPredicate, exception: { message: "'count' must be a valid number.", count: NaN} }
+        ];
+
+        var testDescription = function(test) {
+            return "filter [" + test.index + ", " + test.count + " " + (test.backwards ? "back" : "forward") + "] for predicate " + test.predicate;
+        };
+
+        var filterErrorCallback = function (err) {
+            if (err && err.message) {
+                djstest.fail(err.message);
+            } else {
+                djstest.fail("unexpected promise failure");
+            }
+            doneAfterAllTests();
+        };
+
+        var removeSafariExceptionProperties = function (err) {
+            /** Removes Safari-specific properties from an exception object
+             * @param {Exception} err -The exception object to operate on
+             * @returns {Exception} The original exception object with the Safari-specific properties removed
+             */
+            var safariProperties = ["line", "expressionBeginOffset", "expressionEndOffset", "sourceId", "sourceURL"];
+
+            var result = {};
+            $.each(err, function (property, value) {
+                if ($.inArray(property, safariProperties) === -1) {
+                    result[property] = value;
+                }
+            });
+
+            return result;
+        };
+
+        ODataReadOracle.readJsonAcrossServerPages(foodsFeed, function (expectData) {
+            $.each(tests, function (_, test) {
+                createNewCache(options).then(function (cache) {
+                    try {
+                        var expectedResults = {};
+                        if (test.backwards) {
+                            cache.filterBack(test.index, test.count, test.predicate).then(function (results) {
+                                expectedResults = CacheOracle.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
+                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
+                                doneAfterAllTests();
+                            }, filterErrorCallback);
+                        } else {
+                            cache.filterForward(test.index, test.count, test.predicate).then(function (results) {
+                                expectedResults = CacheOracle.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
+                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
+                                doneAfterAllTests();
+                            }, filterErrorCallback);
+                        }
+
+                        if (test.exception) {
+                            djstest.fail("expected exception for " + testDescription(test));
+                            doneAfterAllTests();
+                        }
+                    } catch (err) {
+                        if (test.exception) {
+                            djstest.assertAreEqualDeep(removeSafariExceptionProperties(err), test.exception, "exception for " + testDescription(test));
+                        } else {
+                            djstest.fail("unexpected exception for " + testDescription(test) + ": " + djstest.toString(err));
+                        }
+                        doneAfterAllTests();
+                    }
+                }, thenFailTest);
+            });
+        });
+    });
+
+    djstest.addTest(function createDataCacheTest() {
+        var cache;
+
+        // Verify the defaults.
+        cache = odatajs.cache.createDataCache({ name: "name", source: "src" });
+
+        djstest.assertAreEqual(cache.onidle, undefined, "onidle is undefined");
+
+        // Verify specific values.
+        cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: 3, idle: 123 });
+
+        djstest.assertAreEqual(cache.onidle, 123, "onidle is as specified");
+
+        // Verify 0 pageSize 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 0, prefetchSize: 3, idle: 123 });
+        }, "zero pageSize");
+
+        // Verify negative pageSize
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: -2, prefetchSize: 3, idle: 123 });
+        }, "negative pageSize");
+
+        // Verify NaN pageSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: "2", prefetchSize: 3, idle: 123 });
+        }, "NaN pageSize");
+
+        // Verify NaN cacheSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: "1", pageSize: 2, prefetchSize: 3, idle: 123 });
+        }, "NaN cacheSize");
+
+        // Verify NaN prefetchSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: "3", idle: 123 });
+        }, "NaN prefetchSize");
+
+        // Verify undefined name 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "undefined name");
+
+        // Verify null name 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: null, source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "null name");
+
+        // Verify undefined source 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "undefined source");
+
+        djstest.done();
+    });
+
+    djstest.addTest(function createDataCacheWithSourceTest() {
+        var cacheSource = {
+            count: function (success) {
+                djstest.pass("cacheSource.count was called");
+                success(0);
+            },
+
+            read: function (index, count, success, error) {
+                djstest.assertAreEqual(index, 0, "index is the expected one");
+                djstest.assertAreEqual(count, 10, "test is the expected one");
+                djstest.assert(success, "success is defined");
+                djstest.assert(error, "error is defined");
+                djstest.pass("cacheSource.read was called");
+
+                setTimeout(function () {
+                    success([]);
+                }, 0);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
+        cache.count().then(function () {
+            cache.readRange(0, 5).then(function () {
+                djstest.done();
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function cacheInitializationFailTest() {
+        // Tests various failure modes for cache initialization.
+        var failures = ["read-settings", "write-settings", "v2"];
+        var failureIndex = 0;
+
+        var originalStore = odatajs.store.createStore;
+        var restoreStore = function () {
+            odatajs.store.createStore = originalStore;
+        };
+
+        var storeError = { message: "cacheInitializationFailTest error" };
+        odatajs.store.createStore = function (name, mechanism) {
+            return {
+                addOrUpdate: function (key, value, successCallback, errorCallback) {
+                    if (failures[failureIndex] === "write-settings") {
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    } else {
+                        djstest.fail("Error unaccounted for in addOrUpdate for " + failures[failureIndex]);
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    }
+                },
+                read: function (key, successCallback, errorCallback) {
+                    if (failures[failureIndex] === "read-settings") {
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    } else if (failures[failureIndex] === "v2") {
+                        window.setTimeout(function () {
+                            successCallback("K", { version: "2.0" });
+                        }, 2);
+                    } else if (failures[failureIndex] === "write-settings") {
+                        window.setTimeout(function () { successCallback(null, null); }, 2);
+                    } else {
+                        djstest.fail("Error unaccounted for read in " + failures[failureIndex]);
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    }
+                }
+            };
+        };
+
+        var nextFailure = function () {
+            djstest.log("Failure mode: " + failures[failureIndex]);
+            var cache = odatajs.cache.createDataCache({ name: "name", source: "foo", mechanism: "memory", pageSize: 10 });
+            try {
+                // The first readRange should succeed, because the data cache isn't really initialized at this time.
+                cache.readRange(1, 2).then(djstest.failAndDoneCallback("No function should succeed"), function (err) {
+                    djstest.expectException(function () {
+                        cache.readRange(1, 2);
+                    }, "readRange after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.count();
+                    }, "count after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.clear();
+                    }, "clear after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.filterForward(1, 2);
+                    }, "filterForward after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.filterBack(1, 2);
+                    }, "filterBack after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.toObservable();
+                    }, "toObservable after store is invalidated");
+
+                    failureIndex++;
+                    if (failureIndex === failures.length) {
+                        restoreStore();
+                        djstest.done();
+                    } else {
+                        nextFailure();
+                    }
+                });
+            } catch (outerError) {
+                djstest.fail("Unexpected failure for first .readRange: " + window.JSON.stringify(outerError));
+                restoreStore();
+                djstest.done();
+            }
+        };
+
+        nextFailure();
+    });
+
+    djstest.addTest(function createDataCacheWithSourceCallsErrorTest() {
+        var cacheSource = {
+            count: function () {
+                djstest.fail("cacheSource.count was called");
+            },
+
+            read: function (index, count, success, error) {
+                setTimeout(function () {
+                    error({ message: "source error" });
+                }, 0);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
+        cache.readRange(0, 5).then(function () {
+            djstest.fail("unexpected call to then success");
+            djstest.done();
+        }, function (err) {
+            djstest.assertAreEqual(err.message, "source error", "got the expected error");
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function toObservableMissingTest() {
+        createNewCache({ name: "cache", source: "http://temp.org" }).then(function (cache) {
+            var hiddenRx = window.Rx;
+            try {
+                window.Rx = null;
+                var error = null;
+                try {
+                    cache.ToObservable();
+                } catch (err) {
+                    error = err;
+                }
+
+                djstest.assert(error !== null, "error !== null");
+            } finally {
+                window.Rx = hiddenRx;
+            }
+
+            djstest.assert(error !== null, "error !== null");
+            djstest.destroyCacheAndDone(cache);
+        });
+    });
+
+    djstest.addTest(function toObservableSinglePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
+            var lastId = -1;
+            cache.ToObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableCaseSinglePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
+            var lastId = -1;
+            cache.toObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableMultiplePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var callCount = 0;
+            cache.toObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+                callCount += 1;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.assert(callCount > 1, "callCount > 1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableEarlyDisposeTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var callCount = 0;
+            var complete = false;
+            var observer = cache.toObservable().subscribe(function (item) {
+                djstest.assert(complete === false, "complete === false");
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+                callCount += 1;
+                complete = true;
+                observer.Dispose();
+                djstest.done();
+            }, thenFailTest);
+        });
+    });
+
+    djstest.addTest(function toObservableFailureTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var complete = false;
+            window.MockHttpClient.clear().addResponse("*", { statusCode: 500, body: "server error" });
+            window.MockHttpClient.async = true;
+            var savedClient = window.odatajs.oData.net.defaultHttpClient;
+            window.odatajs.oData.net.defaultHttpClient = window.MockHttpClient;
+            cache.toObservable().subscribe(function (item) {
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                djstest.fail("Unexpected call to OnNext");
+            }, function (err) {
+                djstest.assert(complete === false, "complete === false");
+                djstest.assert(err, "err defined");
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                complete = true;
+                djstest.done();
+            }, function (complete) {
+                djstest.fail("Unexpected call to complete. Error handler should be called.");
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                complete = true;
+                djstest.done();
+            });
+        });
+    });
+
+    // DATAJS INTERNAL START
+
+    djstest.addTest(function createDeferredTest() {
+        // Verify basic use of deferred object.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (val1, val2) {
+            djstest.assertAreEqual(val1, 1, "val1 is as specified");
+            djstest.assertAreEqual(val2, 2, "val2 is as specified");
+            djstest.done();
+        });
+        deferred.resolve(1, 2);
+    });
+
+    djstest.addTest(function deferredThenTest() {
+        // Verify then registration and chaining.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (val1, val2) {
+            djstest.assertAreEqual(val1, 1, "val1 is as specified");
+            djstest.assertAreEqual(val2, 2, "val2 is as specified");
+            return "foo";
+        }).then(function (foo) {
+            // See Compatibility Note B in DjsDeferred remarks.
+            djstest.assert(foo !== "foo", "argument for chained 'then' is *not* result of previous call");
+            djstest.assert(foo === 1, "argument for chained 'then' is same as for previous call");
+
+            var other = odatajs.deferred.createDeferred();
+            other.then(null, function (err, msg) {
+                djstest.assertAreEqual("error", err, "err is as specified");
+                djstest.assertAreEqual("message", msg, "msg is as specified");
+
+            }).then(null, function (err, msg) {
+                djstest.log("chained errors are called");
+
+                djstest.assertAreEqual("error", err, "err is as specified");
+                djstest.assertAreEqual("message", msg, "msg is as specified");
+
+                var multiple = odatajs.deferred.createDeferred();
+                var count = 0;
+
+                // See Compatibility Note A in DjsDeferred remarks.
+                multiple.then(function () {
+                    djstest.assertAreEqual(count, 0, "first base registration fires as #0");
+                    count++;
+                }).then(function () {
+                    djstest.assertAreEqual(count, 1, "first chained registration fires as #1");
+                    count++;
+                });
+
+                multiple.then(function () {
+                    djstest.assertAreEqual(count, 2, "second base registration fires as #2");
+                    count++;
+                }).then(function () {
+                    djstest.assertAreEqual(count, 3, "second chained registration fires as #3");
+                    djstest.done();
+                });
+
+                multiple.resolve();
+            });
+            other.reject("error", "message");
+        });
+
+        deferred.resolve(1, 2);
+    });
+
+    djstest.addTest(function deferredResolveTest() {
+        // Resolve with no arguments.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (arg) {
+            djstest.assertAreEqual(arg, undefined, "resolve with no args shows up as undefined");
+
+            // Resolve with no callbacks.
+            var other = odatajs.deferred.createDeferred();
+            other.resolve();
+            djstest.done();
+        });
+
+        deferred.resolve();
+    });
+
+    djstest.addTest(function deferredRejectTest() {
+        // Resolve with no arguments.   
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(null, function (arg) {
+            djstest.assertAreEqual(arg, undefined, "reject with no args shows up as undefined");
+
+            // Resolve with no callbacks.
+            var other = odatajs.deferred.createDeferred();
+            other.reject();
+            djstest.done();
+        });
+
+        deferred.reject();
+    });
+
+    djstest.addTest(function estimateSizeTest() {
+        var tests = [
+            { i: null, e: 8 },
+            { i: undefined, e: 8 },
+            { i: 0, e: 8 },
+            { i: "abc", e: 6 },
+            { i: [1, 2, 3], e: 30 },
+            { i: { a1: null, a2: undefined, a3: 5, a4: "ab", a5: { b1: 5, b2: 6} }, e: 72 },
+            { i: {}, e: 0 }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var test = tests[i];
+            djstest.assertAreEqual(odatajs.cache.estimateSize(test.i), test.e);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function cacheOptionsTunnelTest() {
+        var mockClient = window.MockHttpClient;
+        var doneCalled = false;
+
+        mockClient.clear().setAsync(true).addRequestVerifier("*", function (theRequest) {
+            if (!doneCalled) {
+                doneCalled = true;
+                djstest.assertAreEqual(theRequest.user, "the-user", "theRequest.user");
+                djstest.assertAreEqual(theRequest.password, "the-password", "theRequest.password");
+                djstest.assertAreEqual(theRequest.enableJsonpCallback, false, "theRequest.enableJsonpCallback");
+                djstest.assertAreEqual(theRequest.callbackParameterName, "p", "callbackParameterName");
+                djstest.done();
+            }
+        });
+
+        var cache = odatajs.cache.createDataCache({
+            name: "cacheOptionsTunnel",
+            source: "http://foo-bar/",
+            user: "the-user",
+            password: "the-password",
+            enableJsonpCallback: false,
+            callbackParameterName: "p",
+            httpClient: mockClient
+        });
+
+        cache.readRange(0, 10).then(function (arr) {
+            djstest.fail("unexpected callback into readRange in test cacheOptionsTunnelTest");
+            if (!doneCalled) {
+                doneCalled = true;
+                djstest.done();
+            }
+        });
+    });
+
+    djstest.addTest(function dataCacheHandlesFullStoreTest() {
+
+        var TestStore = function (name) {
+            var that = new window.odatajs.store.MemoryStore(name);
+            that.addOrUpdate = function (key, value, success, error) {
+                if (key === "__settings") {
+                    window.setTimeout(function () {
+                        success(key, value);
+                    }, 0);
+                } else {
+                    window.setTimeout(function () {
+                        error({ name: "QUOTA_EXCEEDED_ERR" });
+                    }, 0);
+                }
+            };
+            return that;
+        };
+
+        TestStore.create = function (name) {
+            return new TestStore(name);
+        };
+
+        TestStore.isSupported = function () {
+            return true;
+        };
+
+        var cacheSource = {
+            identifier: "testSource",
+            count: function (success) {
+                djstest.fail("cacheSource.count was called");
+                success(5);
+            },
+            read: function (index, count, success, error) {
+                djstest.assertAreEqual(index, 0, "index is the expected one");
+                djstest.assertAreEqual(count, 5, "test is the expected one");
+
+                setTimeout(function () {
+                    success({ value: [1, 2, 3, 4, 5] });
+                }, 0);
+            }
+        };
+
+        var originalCreateStore = window.odatajs.store.createStore;
+
+        window.odatajs.store.createStore = function (name, mechanism) {
+            return TestStore(name);
+        };
+
+        try {
+            var cache = odatajs.cache.createDataCache({
+                name: "cache",
+                pageSize: 5,
+                prefetchSize: 0,
+                source: cacheSource,
+                mechanism: "teststore"
+            });
+        } finally {
+            window.odatajs.store.createStore = originalCreateStore;
+        }
+
+        cache.readRange(0, 5).then(function (data) {
+            djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
+            cache.readRange(0, 5).then(function (data) {
+                djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
+                djstest.done();
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    // DATAJS INTERNAL END
+})(this);
\ No newline at end of file


[25/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/datajs-1.1.1.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/datajs-1.1.1.js b/odatajs/demo/scripts/datajs-1.1.1.js
new file mode 100644
index 0000000..339b153
--- /dev/null
+++ b/odatajs/demo/scripts/datajs-1.1.1.js
@@ -0,0 +1,10710 @@
+// Copyright (c) Microsoft.  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.
+
+// odatajs.js
+
+(function (window, undefined) {
+
+    var datajs = window.odatajs || {};
+    var odata = window.OData || {};
+
+    // AMD support
+    if (typeof define === 'function' && define.amd) {
+        define('datajs', datajs);
+        define('OData', odata);
+    } else {
+        window.odatajs = datajs;
+        window.OData = odata;
+    }
+
+    odatajs.version = {
+        major: 1,
+        minor: 1,
+        build: 1
+    };
+
+
+    var activeXObject = function (progId) {
+        /// <summary>Creates a new ActiveXObject from the given progId.</summary>
+        /// <param name="progId" type="String" mayBeNull="false" optional="false">
+        ///    ProgId string of the desired ActiveXObject.
+        /// </param>
+        /// <remarks>
+        ///    This function throws whatever exception might occur during the creation
+        ///    of the ActiveXObject.
+        /// </remarks>
+        /// <returns type="Object">
+        ///     The ActiveXObject instance. Null if ActiveX is not supported by the
+        ///     browser.
+        /// </returns>
+        if (window.ActiveXObject) {
+            return new window.ActiveXObject(progId);
+        }
+        return null;
+    };
+
+    var assigned = function (value) {
+        /// <summary>Checks whether the specified value is different from null and undefined.</summary>
+        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
+        /// <returns type="Boolean">true if the value is assigned; false otherwise.</returns>
+        return value !== null && value !== undefined;
+    };
+
+    var contains = function (arr, item) {
+        /// <summary>Checks whether the specified item is in the array.</summary>
+        /// <param name="arr" type="Array" optional="false" mayBeNull="false">Array to check in.</param>
+        /// <param name="item">Item to look for.</param>
+        /// <returns type="Boolean">true if the item is contained, false otherwise.</returns>
+
+        var i, len;
+        for (i = 0, len = arr.length; i < len; i++) {
+            if (arr[i] === item) {
+                return true;
+            }
+        }
+
+        return false;
+    };
+
+    var defined = function (a, b) {
+        /// <summary>Given two values, picks the first one that is not undefined.</summary>
+        /// <param name="a">First value.</param>
+        /// <param name="b">Second value.</param>
+        /// <returns>a if it's a defined value; else b.</returns>
+        return (a !== undefined) ? a : b;
+    };
+
+    var delay = function (callback) {
+        /// <summary>Delays the invocation of the specified function until execution unwinds.</summary>
+        /// <param name="callback" type="Function">Callback function.</param>
+        if (arguments.length === 1) {
+            window.setTimeout(callback, 0);
+            return;
+        }
+
+        var args = Array.prototype.slice.call(arguments, 1);
+        window.setTimeout(function () {
+            callback.apply(this, args);
+        }, 0);
+    };
+
+
+    var extend = function (target, values) {
+        /// <summary>Extends the target with the specified values.</summary>
+        /// <param name="target" type="Object">Object to add properties to.</param>
+        /// <param name="values" type="Object">Object with properties to add into target.</param>
+        /// <returns type="Object">The target object.</returns>
+
+        for (var name in values) {
+            target[name] = values[name];
+        }
+
+        return target;
+    };
+
+    var find = function (arr, callback) {
+        /// <summary>Returns the first item in the array that makes the callback function true.</summary>
+        /// <param name="arr" type="Array" optional="false" mayBeNull="true">Array to check in.</param>
+        /// <param name="callback" type="Function">Callback function to invoke once per item in the array.</param>
+        /// <returns>The first item that makes the callback return true; null otherwise or if the array is null.</returns>
+
+        if (arr) {
+            var i, len;
+            for (i = 0, len = arr.length; i < len; i++) {
+                if (callback(arr[i])) {
+                    return arr[i];
+                }
+            }
+        }
+        return null;
+    };
+
+    var isArray = function (value) {
+        /// <summary>Checks whether the specified value is an array object.</summary>
+        /// <param name="value">Value to check.</param>
+        /// <returns type="Boolean">true if the value is an array object; false otherwise.</returns>
+
+        return Object.prototype.toString.call(value) === "[object Array]";
+    };
+
+    var isDate = function (value) {
+        /// <summary>Checks whether the specified value is a Date object.</summary>
+        /// <param name="value">Value to check.</param>
+        /// <returns type="Boolean">true if the value is a Date object; false otherwise.</returns>
+
+        return Object.prototype.toString.call(value) === "[object Date]";
+    };
+
+    var isObject = function (value) {
+        /// <summary>Tests whether a value is an object.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <remarks>
+        ///     Per javascript rules, null and array values are objects and will cause this function to return true.
+        /// </remarks>
+        /// <returns type="Boolean">True is the value is an object; false otherwise.</returns>
+
+        return typeof value === "object";
+    };
+
+    var parseInt10 = function (value) {
+        /// <summary>Parses a value in base 10.</summary>
+        /// <param name="value" type="String">String value to parse.</param>
+        /// <returns type="Number">The parsed value, NaN if not a valid value.</returns>
+
+        return parseInt(value, 10);
+    };
+
+    var renameProperty = function (obj, oldName, newName) {
+        /// <summary>Renames a property in an object.</summary>
+        /// <param name="obj" type="Object">Object in which the property will be renamed.</param>
+        /// <param name="oldName" type="String">Name of the property that will be renamed.</param>
+        /// <param name="newName" type="String">New name of the property.</param>
+        /// <remarks>
+        ///    This function will not do anything if the object doesn't own a property with the specified old name.
+        /// </remarks>
+
+        if (obj.hasOwnProperty(oldName)) {
+            obj[newName] = obj[oldName];
+            delete obj[oldName];
+        }
+    };
+
+    var throwErrorCallback = function (error) {
+        /// <summary>Default error handler.</summary>
+        /// <param name="error" type="Object">Error to handle.</param>
+        throw error;
+    };
+
+    var trimString = function (str) {
+        /// <summary>Removes leading and trailing whitespaces from a string.</summary>
+        /// <param name="str" type="String" optional="false" mayBeNull="false">String to trim</param>
+        /// <returns type="String">The string with no leading or trailing whitespace.</returns>
+
+        if (str.trim) {
+            return str.trim();
+        }
+
+        return str.replace(/^\s+|\s+$/g, '');
+    };
+
+    var undefinedDefault = function (value, defaultValue) {
+        /// <summary>Returns a default value in place of undefined.</summary>
+        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
+        /// <param name="defaultValue">Value to return if value is undefined.</param>
+        /// <returns>value if it's defined; defaultValue otherwise.</returns>
+        /// <remarks>
+        /// This should only be used for cases where falsy values are valid;
+        /// otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
+        /// </remarks>
+        return (value !== undefined) ? value : defaultValue;
+    };
+
+    // Regular expression that splits a uri into its components:
+    // 0 - is the matched string.
+    // 1 - is the scheme.
+    // 2 - is the authority.
+    // 3 - is the path.
+    // 4 - is the query.
+    // 5 - is the fragment.
+    var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
+    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
+
+    var getURIInfo = function (uri) {
+        /// <summary>Gets information about the components of the specified URI.</summary>
+        /// <param name="uri" type="String">URI to get information from.</param>
+        /// <returns type="Object">
+        /// An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
+        /// </returns>
+
+        var result = { isAbsolute: false };
+
+        if (uri) {
+            var matches = uriRegEx.exec(uri);
+            if (matches) {
+                var i, len;
+                for (i = 0, len = uriPartNames.length; i < len; i++) {
+                    if (matches[i + 1]) {
+                        result[uriPartNames[i]] = matches[i + 1];
+                    }
+                }
+            }
+            if (result.scheme) {
+                result.isAbsolute = true;
+            }
+        }
+
+        return result;
+    };
+
+    var getURIFromInfo = function (uriInfo) {
+        /// <summary>Builds a URI string from its components.</summary>
+        /// <param name="uriInfo" type="Object"> An object with uri parts (scheme, authority, etc.).</param>
+        /// <returns type="String">URI string.</returns>
+
+        return "".concat(
+            uriInfo.scheme || "",
+            uriInfo.authority || "",
+            uriInfo.path || "",
+            uriInfo.query || "",
+            uriInfo.fragment || "");
+    };
+
+    // Regular expression that splits a uri authority into its subcomponents:
+    // 0 - is the matched string.
+    // 1 - is the userinfo subcomponent.
+    // 2 - is the host subcomponent.
+    // 3 - is the port component.
+    var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
+
+    // Regular expression that matches percentage enconded octects (i.e %20 or %3A);
+    var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
+
+    var normalizeURICase = function (uri) {
+        /// <summary>Normalizes the casing of a URI.</summary>
+        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
+        /// <returns type="String">The URI normalized to lower case.</returns>
+
+        var uriInfo = getURIInfo(uri);
+        var scheme = uriInfo.scheme;
+        var authority = uriInfo.authority;
+
+        if (scheme) {
+            uriInfo.scheme = scheme.toLowerCase();
+            if (authority) {
+                var matches = uriAuthorityRegEx.exec(authority);
+                if (matches) {
+                    uriInfo.authority = "//" +
+                    (matches[1] ? matches[1] + "@" : "") +
+                    (matches[2].toLowerCase()) +
+                    (matches[3] ? ":" + matches[3] : "");
+                }
+            }
+        }
+
+        uri = getURIFromInfo(uriInfo);
+
+        return uri.replace(pctEncodingRegEx, function (str) {
+            return str.toLowerCase();
+        });
+    };
+
+    var normalizeURI = function (uri, base) {
+        /// <summary>Normalizes a possibly relative URI with a base URI.</summary>
+        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
+        /// <param name="base" type="String" mayBeNull="true">Base URI to compose with.</param>
+        /// <returns type="String">The composed URI if relative; the original one if absolute.</returns>
+
+        if (!base) {
+            return uri;
+        }
+
+        var uriInfo = getURIInfo(uri);
+        if (uriInfo.isAbsolute) {
+            return uri;
+        }
+
+        var baseInfo = getURIInfo(base);
+        var normInfo = {};
+        var path;
+
+        if (uriInfo.authority) {
+            normInfo.authority = uriInfo.authority;
+            path = uriInfo.path;
+            normInfo.query = uriInfo.query;
+        } else {
+            if (!uriInfo.path) {
+                path = baseInfo.path;
+                normInfo.query = uriInfo.query || baseInfo.query;
+            } else {
+                if (uriInfo.path.charAt(0) === '/') {
+                    path = uriInfo.path;
+                } else {
+                    path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
+                }
+                normInfo.query = uriInfo.query;
+            }
+            normInfo.authority = baseInfo.authority;
+        }
+
+        normInfo.path = removeDotsFromPath(path);
+
+        normInfo.scheme = baseInfo.scheme;
+        normInfo.fragment = uriInfo.fragment;
+
+        return getURIFromInfo(normInfo);
+    };
+
+    var mergeUriPathWithBase = function (uriPath, basePath) {
+        /// <summary>Merges the path of a relative URI and a base URI.</summary>
+        /// <param name="uriPath" type="String>Relative URI path.</param>
+        /// <param name="basePath" type="String">Base URI path.</param>
+        /// <returns type="String">A string with the merged path.</returns>
+
+        var path = "/";
+        var end;
+
+        if (basePath) {
+            end = basePath.lastIndexOf("/");
+            path = basePath.substring(0, end);
+
+            if (path.charAt(path.length - 1) !== "/") {
+                path = path + "/";
+            }
+        }
+
+        return path + uriPath;
+    };
+
+    var removeDotsFromPath = function (path) {
+        /// <summary>Removes the special folders . and .. from a URI's path.</summary>
+        /// <param name="path" type="string">URI path component.</param>
+        /// <returns type="String">Path without any . and .. folders.</returns>
+
+        var result = "";
+        var segment = "";
+        var end;
+
+        while (path) {
+            if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
+                path = path.replace(/^\.\.?\/?/g, "");
+            } else if (path.indexOf("/..") === 0) {
+                path = path.replace(/^\/\..\/?/g, "/");
+                end = result.lastIndexOf("/");
+                if (end === -1) {
+                    result = "";
+                } else {
+                    result = result.substring(0, end);
+                }
+            } else if (path.indexOf("/.") === 0) {
+                path = path.replace(/^\/\.\/?/g, "/");
+            } else {
+                segment = path;
+                end = path.indexOf("/", 1);
+                if (end !== -1) {
+                    segment = path.substring(0, end);
+                }
+                result = result + segment;
+                path = path.replace(segment, "");
+            }
+        }
+        return result;
+    };
+
+    var convertByteArrayToHexString = function (str) {
+        var arr = [];
+        if (window.atob === undefined) {
+            arr = decodeBase64(str);
+        } else {
+            var binaryStr = window.atob(str);
+            for (var i = 0; i < binaryStr.length; i++) {
+                arr.push(binaryStr.charCodeAt(i));
+            }
+        }
+        var hexValue = "";
+        var hexValues = "0123456789ABCDEF";
+        for (var j = 0; j < arr.length; j++) {
+            var t = arr[j];
+            hexValue += hexValues[t >> 4];
+            hexValue += hexValues[t & 0x0F];
+        }
+        return hexValue;
+    };
+
+    var decodeBase64 = function (str) {
+        var binaryString = "";
+        for (var i = 0; i < str.length; i++) {
+            var base65IndexValue = getBase64IndexValue(str[i]);
+            var binaryValue = "";
+            if (base65IndexValue !== null) {
+                binaryValue = base65IndexValue.toString(2);
+                binaryString += addBase64Padding(binaryValue);
+            }
+        }
+        var byteArray = [];
+        var numberOfBytes = parseInt(binaryString.length / 8, 10);
+        for (i = 0; i < numberOfBytes; i++) {
+            var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
+            byteArray.push(intValue);
+        }
+        return byteArray;
+    };
+
+    var getBase64IndexValue = function (character) {
+        var asciiCode = character.charCodeAt(0);
+        var asciiOfA = 65;
+        var differenceBetweenZanda = 6;
+        if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
+            return asciiCode - asciiOfA;
+        } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
+            return asciiCode - asciiOfA - differenceBetweenZanda;
+        } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
+            return asciiCode + 4;
+        } else if (character == "+") {
+            return 62;
+        } else if (character == "/") {
+            return 63;
+        } else {
+            return null;
+        }
+    };
+
+    var addBase64Padding = function (binaryString) {
+        while (binaryString.length < 6) {
+            binaryString = "0" + binaryString;
+        }
+        return binaryString;
+    };
+
+    var getJsonValueArraryLength = function (data) {
+        if (data && data.value) {
+            return data.value.length;
+        }
+
+        return 0;
+    };
+
+    var sliceJsonValueArray = function (data, start, end) {
+        if (data == undefined || data.value == undefined) {
+            return data;
+        }
+
+        if (start < 0) {
+            start = 0;
+        }
+
+        var length = getJsonValueArraryLength(data);
+        if (length < end) {
+            end = length;
+        }
+
+        var newdata = {};
+        for (var property in data) {
+            if (property == "value") {
+                newdata[property] = data[property].slice(start, end);
+            } else {
+                newdata[property] = data[property];
+            }
+        }
+
+        return newdata;
+    };
+
+    var concatJsonValueArray = function (data, concatData) {
+        if (concatData == undefined || concatData.value == undefined) {
+            return data;
+        }
+
+        if (data == undefined || Object.keys(data).length == 0) {
+            return concatData;
+        }
+
+        if (data.value == undefined) {
+            data.value = concatData.value;
+            return data;
+        }
+
+        data.value = data.value.concat(concatData.value);
+
+        return data;
+    };
+
+
+
+    // URI prefixes to generate smaller code.
+    var http = "http://";
+    var w3org = http + "www.w3.org/";               // http://www.w3.org/
+
+    var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
+    var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
+    var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
+
+    var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
+
+    var hasLeadingOrTrailingWhitespace = function (text) {
+        /// <summary>Checks whether the specified string has leading or trailing spaces.</summary>
+        /// <param name="text" type="String">String to check.</param>
+        /// <returns type="Boolean">true if text has any leading or trailing whitespace; false otherwise.</returns>
+
+        var re = /(^\s)|(\s$)/;
+        return re.test(text);
+    };
+
+    var isWhitespace = function (text) {
+        /// <summary>Determines whether the specified text is empty or whitespace.</summary>
+        /// <param name="text" type="String">Value to inspect.</param>
+        /// <returns type="Boolean">true if the text value is empty or all whitespace; false otherwise.</returns>
+
+        var ws = /^\s*$/;
+        return text === null || ws.test(text);
+    };
+
+    var isWhitespacePreserveContext = function (domElement) {
+        /// <summary>Determines whether the specified element has xml:space='preserve' applied.</summary>
+        /// <param name="domElement">Element to inspect.</param>
+        /// <returns type="Boolean">Whether xml:space='preserve' is in effect.</returns>
+
+        while (domElement !== null && domElement.nodeType === 1) {
+            var val = xmlAttributeValue(domElement, "space", xmlNS);
+            if (val === "preserve") {
+                return true;
+            } else if (val === "default") {
+                break;
+            } else {
+                domElement = domElement.parentNode;
+            }
+        }
+
+        return false;
+    };
+
+    var isXmlNSDeclaration = function (domAttribute) {
+        /// <summary>Determines whether the attribute is a XML namespace declaration.</summary>
+        /// <param name="domAttribute">Element to inspect.</param>
+        /// <returns type="Boolean">
+        ///    True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
+        /// </returns>
+
+        var nodeName = domAttribute.nodeName;
+        return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
+    };
+
+    var safeSetProperty = function (obj, name, value) {
+        /// <summary>Safely set as property in an object by invoking obj.setProperty.</summary>
+        /// <param name="obj">Object that exposes a setProperty method.</param>
+        /// <param name="name" type="String" mayBeNull="false">Property name.</param>
+        /// <param name="value">Property value.</param>
+
+        try {
+            obj.setProperty(name, value);
+        } catch (_) { }
+    };
+
+    var msXmlDom3 = function () {
+        /// <summary>Creates an configures new MSXML 3.0 ActiveX object.</summary>
+        /// <remakrs>
+        ///    This function throws any exception that occurs during the creation
+        ///    of the MSXML 3.0 ActiveX object.
+        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
+
+        var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
+        if (msxml3) {
+            safeSetProperty(msxml3, "ProhibitDTD", true);
+            safeSetProperty(msxml3, "MaxElementDepth", 256);
+            safeSetProperty(msxml3, "AllowDocumentFunction", false);
+            safeSetProperty(msxml3, "AllowXsltScript", false);
+        }
+        return msxml3;
+    };
+
+    var msXmlDom = function () {
+        /// <summary>Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.</summary>
+        /// <remakrs>
+        ///    This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
+        ///    it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
+        ///    happens during the creation of the MSXML 6.0 will be handled by the function while
+        ///    the ones that happend during the creation of the MSXML 3.0 will be thrown.
+        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
+
+        try {
+            var msxml = activeXObject("Msxml2.DOMDocument.6.0");
+            if (msxml) {
+                msxml.async = true;
+            }
+            return msxml;
+        } catch (_) {
+            return msXmlDom3();
+        }
+    };
+
+    var msXmlParse = function (text) {
+        /// <summary>Parses an XML string using the MSXML DOM.</summary>
+        /// <remakrs>
+        ///    This function throws any exception that occurs during the creation
+        ///    of the MSXML ActiveX object.  It also will throw an exception
+        ///    in case of a parsing error.
+        /// <returns type="Object">New MSXML DOMDocument node representing the parsed XML string.</returns>
+
+        var dom = msXmlDom();
+        if (!dom) {
+            return null;
+        }
+
+        dom.loadXML(text);
+        var parseError = dom.parseError;
+        if (parseError.errorCode !== 0) {
+            xmlThrowParserError(parseError.reason, parseError.srcText, text);
+        }
+        return dom;
+    };
+
+    var xmlThrowParserError = function (exceptionOrReason, srcText, errorXmlText) {
+        /// <summary>Throws a new exception containing XML parsing error information.</summary>
+        /// <param name="exceptionOrReason">
+        ///    String indicatin the reason of the parsing failure or
+        ///    Object detailing the parsing error.
+        /// </param>
+        /// <param name="srcText" type="String">
+        ///    String indicating the part of the XML string that caused the parsing error.
+        /// </param>
+        /// <param name="errorXmlText" type="String">XML string for wich the parsing failed.</param>
+
+        if (typeof exceptionOrReason === "string") {
+            exceptionOrReason = { message: exceptionOrReason };
+        }
+        throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
+    };
+
+    var xmlParse = function (text) {
+        /// <summary>Returns an XML DOM document from the specified text.</summary>
+        /// <param name="text" type="String">Document text.</param>
+        /// <returns>XML DOM document.</returns>
+        /// <remarks>This function will throw an exception in case of a parse error.</remarks>
+
+        var domParser = window.DOMParser && new window.DOMParser();
+        var dom;
+
+        if (!domParser) {
+            dom = msXmlParse(text);
+            if (!dom) {
+                xmlThrowParserError("XML DOM parser not supported");
+            }
+            return dom;
+        }
+
+        try {
+            dom = domParser.parseFromString(text, "text/xml");
+        } catch (e) {
+            xmlThrowParserError(e, "", text);
+        }
+
+        var element = dom.documentElement;
+        var nsURI = element.namespaceURI;
+        var localName = xmlLocalName(element);
+
+        // Firefox reports errors by returing the DOM for an xml document describing the problem.
+        if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
+            var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
+            var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
+            xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
+        }
+
+        // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
+        // The error may be localized, so instead we simply check for a header as the
+        // top element or descendant child of the document.
+        if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
+            var reason = "";
+            var siblings = [];
+            var cursor = element.firstChild;
+            while (cursor) {
+                if (cursor.nodeType === 1) {
+                    reason += xmlInnerText(cursor) || "";
+                }
+                siblings.push(cursor.nextSibling);
+                cursor = cursor.firstChild || siblings.shift();
+            }
+            reason += xmlInnerText(element) || "";
+            xmlThrowParserError(reason, "", text);
+        }
+
+        return dom;
+    };
+
+    var xmlQualifiedName = function (prefix, name) {
+        /// <summary>Builds a XML qualified name string in the form of "prefix:name".</summary>
+        /// <param name="prefix" type="String" maybeNull="true">Prefix string.</param>
+        /// <param name="name" type="String">Name string to qualify with the prefix.</param>
+        /// <returns type="String">Qualified name.</returns>
+
+        return prefix ? prefix + ":" + name : name;
+    };
+
+    var xmlAppendText = function (domNode, textNode) {
+        /// <summary>Appends a text node into the specified DOM element node.</summary>
+        /// <param name="domNode">DOM node for the element.</param>
+        /// <param name="text" type="String" mayBeNull="false">Text to append as a child of element.</param>
+        if (hasLeadingOrTrailingWhitespace(textNode.data)) {
+            var attr = xmlAttributeNode(domNode, xmlNS, "space");
+            if (!attr) {
+                attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
+                xmlAppendChild(domNode, attr);
+            }
+            attr.value = "preserve";
+        }
+        domNode.appendChild(textNode);
+        return domNode;
+    };
+
+    var xmlAttributes = function (element, onAttributeCallback) {
+        /// <summary>Iterates through the XML element's attributes and invokes the callback function for each one.</summary>
+        /// <param name="element">Wrapped element to iterate over.</param>
+        /// <param name="onAttributeCallback" type="Function">Callback function to invoke with wrapped attribute nodes.</param>
+
+        var attributes = element.attributes;
+        var i, len;
+        for (i = 0, len = attributes.length; i < len; i++) {
+            onAttributeCallback(attributes.item(i));
+        }
+    };
+
+    var xmlAttributeValue = function (domNode, localName, nsURI) {
+        /// <summary>Returns the value of a DOM element's attribute.</summary>
+        /// <param name="domNode">DOM node for the owning element.</param>
+        /// <param name="localName" type="String">Local name of the attribute.</param>
+        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
+        /// <returns type="String" maybeNull="true">The attribute value, null if not found.</returns>
+
+        var attribute = xmlAttributeNode(domNode, localName, nsURI);
+        return attribute ? xmlNodeValue(attribute) : null;
+    };
+
+    var xmlAttributeNode = function (domNode, localName, nsURI) {
+        /// <summary>Gets an attribute node from a DOM element.</summary>
+        /// <param name="domNode">DOM node for the owning element.</param>
+        /// <param name="localName" type="String">Local name of the attribute.</param>
+        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
+        /// <returns>The attribute node, null if not found.</returns>
+
+        var attributes = domNode.attributes;
+        if (attributes.getNamedItemNS) {
+            return attributes.getNamedItemNS(nsURI || null, localName);
+        }
+
+        return attributes.getQualifiedItem(localName, nsURI) || null;
+    };
+
+    var xmlBaseURI = function (domNode, baseURI) {
+        /// <summary>Gets the value of the xml:base attribute on the specified element.</summary>
+        /// <param name="domNode">Element to get xml:base attribute value from.</param>
+        /// <param name="baseURI" mayBeNull="true" optional="true">Base URI used to normalize the value of the xml:base attribute.</param>
+        /// <returns type="String">Value of the xml:base attribute if found; the baseURI or null otherwise.</returns>
+
+        var base = xmlAttributeNode(domNode, "base", xmlNS);
+        return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
+    };
+
+
+    var xmlChildElements = function (domNode, onElementCallback) {
+        /// <summary>Iterates through the XML element's child DOM elements and invokes the callback function for each one.</summary>
+        /// <param name="element">DOM Node containing the DOM elements to iterate over.</param>
+        /// <param name="onElementCallback" type="Function">Callback function to invoke for each child DOM element.</param>
+
+        xmlTraverse(domNode, /*recursive*/false, function (child) {
+            if (child.nodeType === 1) {
+                onElementCallback(child);
+            }
+            // continue traversing.
+            return true;
+        });
+    };
+
+    var xmlFindElementByPath = function (root, namespaceURI, path) {
+        /// <summary>Gets the descendant element under root that corresponds to the specified path and namespace URI.</summary>
+        /// <param name="root">DOM element node from which to get the descendant element.</param>
+        /// <param name="namespaceURI" type="String">The namespace URI of the element to match.</param>
+        /// <param name="path" type="String">Path to the desired descendant element.</param>
+        /// <returns>The element specified by path and namespace URI.</returns>
+        /// <remarks>
+        ///     All the elements in the path are matched against namespaceURI.
+        ///     The function will stop searching on the first element that doesn't match the namespace and the path.
+        /// </remarks>
+
+        var parts = path.split("/");
+        var i, len;
+        for (i = 0, len = parts.length; i < len; i++) {
+            root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
+        }
+        return root || null;
+    };
+
+    var xmlFindNodeByPath = function (root, namespaceURI, path) {
+        /// <summary>Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.</summary>
+        /// <param name="root">DOM element node from which to get the descendant node.</param>
+        /// <param name="namespaceURI" type="String">The namespace URI of the node to match.</param>
+        /// <param name="path" type="String">Path to the desired descendant node.</param>
+        /// <returns>The node specified by path and namespace URI.</returns>
+        /// <remarks>
+        ///     This function will traverse the path and match each node associated to a path segement against the namespace URI.
+        ///     The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
+        ///
+        ///     The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
+        /// </remarks>
+
+        var lastSegmentStart = path.lastIndexOf("/");
+        var nodePath = path.substring(lastSegmentStart + 1);
+        var parentPath = path.substring(0, lastSegmentStart);
+
+        var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
+        if (node) {
+            if (nodePath.charAt(0) === "@") {
+                return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
+            }
+            return xmlFirstChildElement(node, namespaceURI, nodePath);
+        }
+        return null;
+    };
+
+    var xmlFirstChildElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the child DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
+    };
+
+    var xmlFirstDescendantElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        if (domNode.getElementsByTagNameNS) {
+            var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
+            return result.length > 0 ? result[0] : null;
+        }
+        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
+    };
+
+    var xmlFirstElementMaybeRecursive = function (domNode, namespaceURI, localName, recursive) {
+        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <param name="recursive" type="Boolean">
+        ///     True if the search should include all the descendants of the DOM node.
+        ///     False if the search should be scoped only to the direct children of the DOM node.
+        /// </param>
+        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        var firstElement = null;
+        xmlTraverse(domNode, recursive, function (child) {
+            if (child.nodeType === 1) {
+                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
+                var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
+
+                if (isExpectedNamespace && isExpectedNodeName) {
+                    firstElement = child;
+                }
+            }
+            return firstElement === null;
+        });
+        return firstElement;
+    };
+
+    var xmlInnerText = function (xmlElement) {
+        /// <summary>Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.</summary>
+        /// <param name="domElement">Element to get values for.</param>
+        /// <returns type="String">Text for all direct children.</returns>
+
+        var result = null;
+        var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
+        var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
+        var whitespacePreserveContext;
+
+        xmlTraverse(root, false, function (child) {
+            if (child.nodeType === 3 || child.nodeType === 4) {
+                // isElementContentWhitespace indicates that this is 'ignorable whitespace',
+                // but it's not defined by all browsers, and does not honor xml:space='preserve'
+                // in some implementations.
+                //
+                // If we can't tell either way, we walk up the tree to figure out whether
+                // xml:space is set to preserve; otherwise we discard pure-whitespace.
+                //
+                // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
+                var text = xmlNodeValue(child);
+                var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
+                if (!shouldInclude) {
+                    // Walk up the tree to figure out whether we are in xml:space='preserve' context
+                    // for the cursor (needs to happen only once).
+                    if (whitespacePreserveContext === undefined) {
+                        whitespacePreserveContext = isWhitespacePreserveContext(root);
+                    }
+
+                    shouldInclude = whitespacePreserveContext;
+                }
+
+                if (shouldInclude) {
+                    if (!result) {
+                        result = text;
+                    } else {
+                        result += text;
+                    }
+                }
+            }
+            // Continue traversing?
+            return true;
+        });
+        return result;
+    };
+
+    var xmlLocalName = function (domNode) {
+        /// <summary>Returns the localName of a XML node.</summary>
+        /// <param name="domNode">DOM node to get the value from.</param>
+        /// <returns type="String">localName of domNode.</returns>
+
+        return domNode.localName || domNode.baseName;
+    };
+
+    var xmlNamespaceURI = function (domNode) {
+        /// <summary>Returns the namespace URI of a XML node.</summary>
+        /// <param name="node">DOM node to get the value from.</param>
+        /// <returns type="String">Namespace URI of domNode.</returns>
+
+        return domNode.namespaceURI || null;
+    };
+
+    var xmlNodeValue = function (domNode) {
+        /// <summary>Returns the value or the inner text of a XML node.</summary>
+        /// <param name="node">DOM node to get the value from.</param>
+        /// <returns>Value of the domNode or the inner text if domNode represents a DOM element node.</returns>
+        
+        if (domNode.nodeType === 1) {
+            return xmlInnerText(domNode);
+        }
+        return domNode.nodeValue;
+    };
+
+    var xmlTraverse = function (domNode, recursive, onChildCallback) {
+        /// <summary>Walks through the descendants of the domNode and invokes a callback for each node.</summary>
+        /// <param name="domNode">DOM node whose descendants are going to be traversed.</param>
+        /// <param name="recursive" type="Boolean">
+        ///    True if the traversal should include all the descenants of the DOM node.
+        ///    False if the traversal should be scoped only to the direct children of the DOM node.
+        /// </param>
+        /// <returns type="String">Namespace URI of node.</returns>
+
+        var subtrees = [];
+        var child = domNode.firstChild;
+        var proceed = true;
+        while (child && proceed) {
+            proceed = onChildCallback(child);
+            if (proceed) {
+                if (recursive && child.firstChild) {
+                    subtrees.push(child.firstChild);
+                }
+                child = child.nextSibling || subtrees.shift();
+            }
+        }
+    };
+
+    var xmlSiblingElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the next sibling DOM element of the specified DOM node.</summary>
+        /// <param name="domNode">DOM node from which the next sibling is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's next sibling DOM element, null if there is none.</returns>
+
+        var sibling = domNode.nextSibling;
+        while (sibling) {
+            if (sibling.nodeType === 1) {
+                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
+                var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
+
+                if (isExpectedNamespace && isExpectedNodeName) {
+                    return sibling;
+                }
+            }
+            sibling = sibling.nextSibling;
+        }
+        return null;
+    };
+
+    var xmlDom = function () {
+        /// <summary>Creates a new empty DOM document node.</summary>
+        /// <returns>New DOM document node.</returns>
+        /// <remarks>
+        ///    This function will first try to create a native DOM document using
+        ///    the browsers createDocument function.  If the browser doesn't
+        ///    support this but supports ActiveXObject, then an attempt to create
+        ///    an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
+        ///    for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
+        ///    the browser doesn't support ActiveXObject then an exception will be thrown.
+        /// </remarks>
+
+        var implementation = window.document.implementation;
+        return (implementation && implementation.createDocument) ?
+           implementation.createDocument(null, null, null) :
+           msXmlDom();
+    };
+
+    var xmlAppendChildren = function (parent, children) {
+        /// <summary>Appends a collection of child nodes or string values to a parent DOM node.</summary>
+        /// <param name="parent">DOM node to which the children will be appended.</param>
+        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be appended to the parent.</param>
+        /// <returns>The parent with the appended children or string values.</returns>
+        /// <remarks>
+        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
+        ///    for it and then appended to the parent.
+        /// </remarks>
+
+        if (!isArray(children)) {
+            return xmlAppendChild(parent, children);
+        }
+
+        var i, len;
+        for (i = 0, len = children.length; i < len; i++) {
+            children[i] && xmlAppendChild(parent, children[i]);
+        }
+        return parent;
+    };
+
+    var xmlAppendChild = function (parent, child) {
+        /// <summary>Appends a child node or a string value to a parent DOM node.</summary>
+        /// <param name="parent">DOM node to which the child will be appended.</param>
+        /// <param name="child">Child DOM node or string value to append to the parent.</param>
+        /// <returns>The parent with the appended child or string value.</returns>
+        /// <remarks>
+        ///    If child is a string value, then a new DOM text node is going to be created
+        ///    for it and then appended to the parent.
+        /// </remarks>
+
+        if (child) {
+            if (typeof child === "string") {
+                return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
+            }
+            if (child.nodeType === 2) {
+                parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
+            } else {
+                parent.appendChild(child);
+            }
+        }
+        return parent;
+    };
+
+    var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) {
+        /// <summary>Creates a new DOM attribute node.</summary>
+        /// <param name="dom">DOM document used to create the attribute.</param>
+        /// <param name="prefix" type="String">Namespace prefix.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI.</param>
+        /// <returns>DOM attribute node for the namespace declaration.</returns>
+
+        var attribute =
+            dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
+            dom.createNode(2, qualifiedName, namespaceURI || undefined);
+
+        attribute.value = value || "";
+        return attribute;
+    };
+
+    var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) {
+        /// <summary>Creates a new DOM element node.</summary>
+        /// <param name="dom">DOM document used to create the DOM element.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element.</param>
+        /// <param name="qualifiedName" type="String">Qualified name in the form of "prefix:name" of the new DOM element.</param>
+        /// <param name="children" type="Array" optional="true">
+        ///     Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
+        /// </param>
+        /// <returns>New DOM element.</returns>
+        /// <remarks>
+        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
+        ///    for it and then appended to the new DOM element.
+        /// </remarks>
+
+        var element =
+            dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
+            dom.createNode(1, qualifiedName, nampespaceURI || undefined);
+
+        return xmlAppendChildren(element, children || []);
+    };
+
+    var xmlNewNSDeclaration = function (dom, namespaceURI, prefix) {
+        /// <summary>Creates a namespace declaration attribute.</summary>
+        /// <param name="dom">DOM document used to create the attribute.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI.</param>
+        /// <param name="prefix" type="String">Namespace prefix.</param>
+        /// <returns>DOM attribute node for the namespace declaration.</returns>
+
+        return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
+    };
+
+    var xmlNewFragment = function (dom, text) {
+        /// <summary>Creates a new DOM document fragment node for the specified xml text.</summary>
+        /// <param name="dom">DOM document from which the fragment node is going to be created.</param>
+        /// <param name="text" type="String" mayBeNull="false">XML text to be represented by the XmlFragment.</param>
+        /// <returns>New DOM document fragment object.</returns>
+
+        var value = "<c>" + text + "</c>";
+        var tempDom = xmlParse(value);
+        var tempRoot = tempDom.documentElement;
+        var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
+        var fragment = dom.createDocumentFragment();
+
+        var importedChild = imported.firstChild;
+        while (importedChild) {
+            fragment.appendChild(importedChild);
+            importedChild = importedChild.nextSibling;
+        }
+        return fragment;
+    };
+
+    var xmlNewText = function (dom, text) {
+        /// <summary>Creates new DOM text node.</summary>
+        /// <param name="dom">DOM document used to create the text node.</param>
+        /// <param name="text" type="String">Text value for the DOM text node.</param>
+        /// <returns>DOM text node.</returns>
+
+        return dom.createTextNode(text);
+    };
+
+    var xmlNewNodeByPath = function (dom, root, namespaceURI, prefix, path) {
+        /// <summary>Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.</summary>
+        /// <param name="dom">DOM document used to create the new node.</param>
+        /// <param name="root">DOM element node used as root of the subtree on which the new nodes are going to be created.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element or attribute.</param>
+        /// <param name="namespacePrefix" type="String">Prefix used to qualify the name of the new DOM element or attribute.</param>
+        /// <param name="Path" type="String">Path string describing the location of the new DOM element or attribute from the root element.</param>
+        /// <returns>DOM element or attribute node for the last segment of the path.</returns>
+        /// <remarks>
+        ///     This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
+        ///     for each segment that doesn't have a matching element under root.
+        ///
+        ///     The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
+        ///     will be created.
+        /// </remarks>
+
+        var name = "";
+        var parts = path.split("/");
+        var xmlFindNode = xmlFirstChildElement;
+        var xmlNewNode = xmlNewElement;
+        var xmlNode = root;
+
+        var i, len;
+        for (i = 0, len = parts.length; i < len; i++) {
+            name = parts[i];
+            if (name.charAt(0) === "@") {
+                name = name.substring(1);
+                xmlFindNode = xmlAttributeNode;
+                xmlNewNode = xmlNewAttribute;
+            }
+
+            var childNode = xmlFindNode(xmlNode, namespaceURI, name);
+            if (!childNode) {
+                childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
+                xmlAppendChild(xmlNode, childNode);
+            }
+            xmlNode = childNode;
+        }
+        return xmlNode;
+    };
+
+    var xmlSerialize = function (domNode) {
+        /// <summary>
+        /// Returns the text representation of the document to which the specified node belongs.
+        /// </summary>
+        /// <param name="root">Wrapped element in the document to serialize.</param>
+        /// <returns type="String">Serialized document.</returns>
+
+        var xmlSerializer = window.XMLSerializer;
+        if (xmlSerializer) {
+            var serializer = new xmlSerializer();
+            return serializer.serializeToString(domNode);
+        }
+
+        if (domNode.xml) {
+            return domNode.xml;
+        }
+
+        throw { message: "XML serialization unsupported" };
+    };
+
+    var xmlSerializeDescendants = function (domNode) {
+        /// <summary>Returns the XML representation of the all the descendants of the node.</summary>
+        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
+        /// <returns type="String">The XML representation of all the descendants of the node.</returns>
+
+        var children = domNode.childNodes;
+        var i, len = children.length;
+        if (len === 0) {
+            return "";
+        }
+
+        // Some implementations of the XMLSerializer don't deal very well with fragments that
+        // don't have a DOMElement as their first child. The work around is to wrap all the
+        // nodes in a dummy root node named "c", serialize it and then just extract the text between
+        // the <c> and the </c> substrings.
+
+        var dom = domNode.ownerDocument;
+        var fragment = dom.createDocumentFragment();
+        var fragmentRoot = dom.createElement("c");
+
+        fragment.appendChild(fragmentRoot);
+        // Move the children to the fragment tree.
+        for (i = 0; i < len; i++) {
+            fragmentRoot.appendChild(children[i]);
+        }
+
+        var xml = xmlSerialize(fragment);
+        xml = xml.substr(3, xml.length - 7);
+
+        // Move the children back to the original dom tree.
+        for (i = 0; i < len; i++) {
+            domNode.appendChild(fragmentRoot.childNodes[i]);
+        }
+
+        return xml;
+    };
+
+    var xmlSerializeNode = function (domNode) {
+        /// <summary>Returns the XML representation of the node and all its descendants.</summary>
+        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
+        /// <returns type="String">The XML representation of the node and all its descendants.</returns>
+
+        var xml = domNode.xml;
+        if (xml !== undefined) {
+            return xml;
+        }
+
+        if (window.XMLSerializer) {
+            var serializer = new window.XMLSerializer();
+            return serializer.serializeToString(domNode);
+        }
+
+        throw { message: "XML serialization unsupported" };
+    };
+
+
+
+
+    var forwardCall = function (thisValue, name, returnValue) {
+        /// <summary>Creates a new function to forward a call.</summary>
+        /// <param name="thisValue" type="Object">Value to use as the 'this' object.</param>
+        /// <param name="name" type="String">Name of function to forward to.</param>
+        /// <param name="returnValue" type="Object">Return value for the forward call (helps keep identity when chaining calls).</param>
+        /// <returns type="Function">A new function that will forward a call.</returns>
+
+        return function () {
+            thisValue[name].apply(thisValue, arguments);
+            return returnValue;
+        };
+    };
+
+    var DjsDeferred = function () {
+        /// <summary>Initializes a new DjsDeferred object.</summary>
+        /// <remarks>
+        /// Compability Note A - Ordering of callbacks through chained 'then' invocations
+        ///
+        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+        /// implies that .then() returns a distinct object.
+        ////
+        /// For compatibility with http://api.jquery.com/category/deferred-object/
+        /// we return this same object. This affects ordering, as
+        /// the jQuery version will fire callbacks in registration
+        /// order regardless of whether they occur on the result
+        /// or the original object.
+        ///
+        /// Compability Note B - Fulfillment value
+        ///
+        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+        /// implies that the result of a success callback is the
+        /// fulfillment value of the object and is received by
+        /// other success callbacks that are chained.
+        ///
+        /// For compatibility with http://api.jquery.com/category/deferred-object/
+        /// we disregard this value instead.
+        /// </remarks>
+
+        this._arguments = undefined;
+        this._done = undefined;
+        this._fail = undefined;
+        this._resolved = false;
+        this._rejected = false;
+    };
+
+    DjsDeferred.prototype = {
+        then: function (fulfilledHandler, errorHandler /*, progressHandler */) {
+            /// <summary>Adds success and error callbacks for this deferred object.</summary>
+            /// <param name="fulfilledHandler" type="Function" mayBeNull="true" optional="true">Success callback.</param>
+            /// <param name="errorHandler" type="Function" mayBeNull="true" optional="true">Error callback.</param>
+            /// <remarks>See Compatibility Note A.</remarks>
+
+            if (fulfilledHandler) {
+                if (!this._done) {
+                    this._done = [fulfilledHandler];
+                } else {
+                    this._done.push(fulfilledHandler);
+                }
+            }
+
+            if (errorHandler) {
+                if (!this._fail) {
+                    this._fail = [errorHandler];
+                } else {
+                    this._fail.push(errorHandler);
+                }
+            }
+
+            //// See Compatibility Note A in the DjsDeferred constructor.
+            //// if (!this._next) {
+            ////    this._next = createDeferred();
+            //// }
+            //// return this._next.promise();
+
+            if (this._resolved) {
+                this.resolve.apply(this, this._arguments);
+            } else if (this._rejected) {
+                this.reject.apply(this, this._arguments);
+            }
+
+            return this;
+        },
+
+        resolve: function (/* args */) {
+            /// <summary>Invokes success callbacks for this deferred object.</summary>
+            /// <remarks>All arguments are forwarded to success callbacks.</remarks>
+
+
+            if (this._done) {
+                var i, len;
+                for (i = 0, len = this._done.length; i < len; i++) {
+                    //// See Compability Note B - Fulfillment value.
+                    //// var nextValue =
+                    this._done[i].apply(null, arguments);
+                }
+
+                //// See Compatibility Note A in the DjsDeferred constructor.
+                //// this._next.resolve(nextValue);
+                //// delete this._next;
+
+                this._done = undefined;
+                this._resolved = false;
+                this._arguments = undefined;
+            } else {
+                this._resolved = true;
+                this._arguments = arguments;
+            }
+        },
+
+        reject: function (/* args */) {
+            /// <summary>Invokes error callbacks for this deferred object.</summary>
+            /// <remarks>All arguments are forwarded to error callbacks.</remarks>
+            if (this._fail) {
+                var i, len;
+                for (i = 0, len = this._fail.length; i < len; i++) {
+                    this._fail[i].apply(null, arguments);
+                }
+
+                this._fail = undefined;
+                this._rejected = false;
+                this._arguments = undefined;
+            } else {
+                this._rejected = true;
+                this._arguments = arguments;
+            }
+        },
+
+        promise: function () {
+            /// <summary>Returns a version of this object that has only the read-only methods available.</summary>
+            /// <returns>An object with only the promise object.</returns>
+
+            var result = {};
+            result.then = forwardCall(this, "then", result);
+            return result;
+        }
+    };
+
+    var createDeferred = function () {
+        /// <summary>Creates a deferred object.</summary>
+        /// <returns type="DjsDeferred">
+        /// A new deferred object. If jQuery is installed, then a jQuery
+        /// Deferred object is returned, which provides a superset of features.
+        /// </returns>
+
+        if (window.jQuery && window.jQuery.Deferred) {
+            return new window.jQuery.Deferred();
+        } else {
+            return new DjsDeferred();
+        }
+    };
+
+
+
+
+    var dataItemTypeName = function (value, metadata) {
+        /// <summary>Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property.</summary>
+        /// <param name="value">Value of the data item from which the type name is going to be retrieved.</param>
+        /// <param name="metadata" type="object" optional="true">Object containing metadata about the data tiem.</param>
+        /// <remarks>
+        ///    This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
+        ///    it will try to recover it from the metadata.  If both attempts fail, it will return null.
+        /// </remarks>
+        /// <returns type="String">Data item type name; null if the type name cannot be found within the value or the metadata</returns>
+
+        var valueTypeName = ((value && value.__metadata) || {}).type;
+        return valueTypeName || (metadata ? metadata.type : null);
+    };
+
+    var EDM = "Edm.";
+    var EDM_BINARY = EDM + "Binary";
+    var EDM_BOOLEAN = EDM + "Boolean";
+    var EDM_BYTE = EDM + "Byte";
+    var EDM_DATETIME = EDM + "DateTime";
+    var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
+    var EDM_DECIMAL = EDM + "Decimal";
+    var EDM_DOUBLE = EDM + "Double";
+    var EDM_GUID = EDM + "Guid";
+    var EDM_INT16 = EDM + "Int16";
+    var EDM_INT32 = EDM + "Int32";
+    var EDM_INT64 = EDM + "Int64";
+    var EDM_SBYTE = EDM + "SByte";
+    var EDM_SINGLE = EDM + "Single";
+    var EDM_STRING = EDM + "String";
+    var EDM_TIME = EDM + "Time";
+
+    var EDM_GEOGRAPHY = EDM + "Geography";
+    var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
+    var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
+    var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
+    var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
+    var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
+    var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
+    var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
+
+    var EDM_GEOMETRY = EDM + "Geometry";
+    var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
+    var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
+    var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
+    var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
+    var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
+    var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
+    var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
+
+    var GEOJSON_POINT = "Point";
+    var GEOJSON_LINESTRING = "LineString";
+    var GEOJSON_POLYGON = "Polygon";
+    var GEOJSON_MULTIPOINT = "MultiPoint";
+    var GEOJSON_MULTILINESTRING = "MultiLineString";
+    var GEOJSON_MULTIPOLYGON = "MultiPolygon";
+    var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
+
+    var primitiveEdmTypes = [
+        EDM_STRING,
+        EDM_INT32,
+        EDM_INT64,
+        EDM_BOOLEAN,
+        EDM_DOUBLE,
+        EDM_SINGLE,
+        EDM_DATETIME,
+        EDM_DATETIMEOFFSET,
+        EDM_TIME,
+        EDM_DECIMAL,
+        EDM_GUID,
+        EDM_BYTE,
+        EDM_INT16,
+        EDM_SBYTE,
+        EDM_BINARY
+    ];
+
+    var geometryEdmTypes = [
+        EDM_GEOMETRY,
+        EDM_GEOMETRY_POINT,
+        EDM_GEOMETRY_LINESTRING,
+        EDM_GEOMETRY_POLYGON,
+        EDM_GEOMETRY_COLLECTION,
+        EDM_GEOMETRY_MULTIPOLYGON,
+        EDM_GEOMETRY_MULTILINESTRING,
+        EDM_GEOMETRY_MULTIPOINT
+    ];
+
+    var geographyEdmTypes = [
+        EDM_GEOGRAPHY,
+        EDM_GEOGRAPHY_POINT,
+        EDM_GEOGRAPHY_LINESTRING,
+        EDM_GEOGRAPHY_POLYGON,
+        EDM_GEOGRAPHY_COLLECTION,
+        EDM_GEOGRAPHY_MULTIPOLYGON,
+        EDM_GEOGRAPHY_MULTILINESTRING,
+        EDM_GEOGRAPHY_MULTIPOINT
+    ];
+
+    var forEachSchema = function (metadata, callback) {
+        /// <summary>Invokes a function once per schema in metadata.</summary>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <param name="callback" type="Function">Callback function to invoke once per schema.</param>
+        /// <returns>
+        /// The first truthy value to be returned from the callback; null or the last falsy value otherwise.
+        /// </returns>
+
+        if (!metadata) {
+            return null;
+        }
+
+        if (isArray(metadata)) {
+            var i, len, result;
+            for (i = 0, len = metadata.length; i < len; i++) {
+                result = forEachSchema(metadata[i], callback);
+                if (result) {
+                    return result;
+                }
+            }
+
+            return null;
+        } else {
+            if (metadata.dataServices) {
+                return forEachSchema(metadata.dataServices.schema, callback);
+            }
+
+            return callback(metadata);
+        }
+    };
+
+    var formatMilliseconds = function (ms, ns) {
+        /// <summary>Formats a millisecond and a nanosecond value into a single string.</summary>
+        /// <param name="ms" type="Number" mayBeNull="false">Number of milliseconds to format.</param>
+        /// <param name="ns" type="Number" mayBeNull="false">Number of nanoseconds to format.</param>
+        /// <returns type="String">Formatted text.</returns>
+        /// <remarks>If the value is already as string it's returned as-is.</remarks>
+
+        // Avoid generating milliseconds if not necessary.
+        if (ms === 0) {
+            ms = "";
+        } else {
+            ms = "." + formatNumberWidth(ms.toString(), 3);
+        }
+        if (ns > 0) {
+            if (ms === "") {
+                ms = ".000";
+            }
+            ms += formatNumberWidth(ns.toString(), 4);
+        }
+        return ms;
+    };
+
+    var formatDateTimeOffset = function (value) {
+        /// <summary>Formats a DateTime or DateTimeOffset value a string.</summary>
+        /// <param name="value" type="Date" mayBeNull="false">Value to format.</param>
+        /// <returns type="String">Formatted text.</returns>
+        /// <remarks>If the value is already as string it's returned as-is.</remarks>
+
+        if (typeof value === "string") {
+            return value;
+        }
+
+        var hasOffset = isDateTimeOffset(value);
+        var offset = getCanonicalTimezone(value.__offset);
+        if (hasOffset && offset !== "Z") {
+            // We're about to change the value, so make a copy.
+            value = new Date(value.valueOf());
+
+            var timezone = parseTimezone(offset);
+            var hours = value.getUTCHours() + (timezone.d * timezone.h);
+            var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
+
+            value.setUTCHours(hours, minutes);
+        } else if (!hasOffset) {
+            // Don't suffix a 'Z' for Edm.DateTime values.
+            offset = "";
+        }
+
+        var year = value.getUTCFullYear();
+        var month = value.getUTCMonth() + 1;
+        var sign = "";
+        if (year <= 0) {
+            year = -(year - 1);
+            sign = "-";
+        }
+
+        var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
+
+        return sign +
+            formatNumberWidth(year, 4) + "-" +
+            formatNumberWidth(month, 2) + "-" +
+            formatNumberWidth(value.getUTCDate(), 2) + "T" +
+            formatNumberWidth(value.getUTCHours(), 2) + ":" +
+            formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
+            formatNumberWidth(value.getUTCSeconds(), 2) +
+            ms + offset;
+    };
+
+    var formatDuration = function (value) {
+        /// <summary>Converts a duration to a string in xsd:duration format.</summary>
+        /// <param name="value" type="Object">Object with ms and __edmType properties.</param>
+        /// <returns type="String">String representation of the time object in xsd:duration format.</returns>
+
+        var ms = value.ms;
+
+        var sign = "";
+        if (ms < 0) {
+            sign = "-";
+            ms = -ms;
+        }
+
+        var days = Math.floor(ms / 86400000);
+        ms -= 86400000 * days;
+        var hours = Math.floor(ms / 3600000);
+        ms -= 3600000 * hours;
+        var minutes = Math.floor(ms / 60000);
+        ms -= 60000 * minutes;
+        var seconds = Math.floor(ms / 1000);
+        ms -= seconds * 1000;
+
+        return sign + "P" +
+               formatNumberWidth(days, 2) + "DT" +
+               formatNumberWidth(hours, 2) + "H" +
+               formatNumberWidth(minutes, 2) + "M" +
+               formatNumberWidth(seconds, 2) +
+               formatMilliseconds(ms, value.ns) + "S";
+    };
+
+    var formatNumberWidth = function (value, width, append) {
+        /// <summary>Formats the specified value to the given width.</summary>
+        /// <param name="value" type="Number">Number to format (non-negative).</param>
+        /// <param name="width" type="Number">Minimum width for number.</param>
+        /// <param name="append" type="Boolean">Flag indicating if the value is padded at the beginning (false) or at the end (true).</param>
+        /// <returns type="String">Text representation.</returns>
+        var result = value.toString(10);
+        while (result.length < width) {
+            if (append) {
+                result += "0";
+            } else {
+                result = "0" + result;
+            }
+        }
+
+        return result;
+    };
+
+    var getCanonicalTimezone = function (timezone) {
+        /// <summary>Gets the canonical timezone representation.</summary>
+        /// <param name="timezone" type="String">Timezone representation.</param>
+        /// <returns type="String">An 'Z' string if the timezone is absent or 0; the timezone otherwise.</returns>
+
+        return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
+    };
+
+    var getCollectionType = function (typeName) {
+        /// <summary>Gets the type of a collection type name.</summary>
+        /// <param name="typeName" type="String">Type name of the collection.</param>
+        /// <returns type="String">Type of the collection; null if the type name is not a collection type.</returns>
+
+        if (typeof typeName === "string") {
+            var end = typeName.indexOf(")", 10);
+            if (typeName.indexOf("Collection(") === 0 && end > 0) {
+                return typeName.substring(11, end);
+            }
+        }
+        return null;
+    };
+
+    var invokeRequest = function (request, success, error, handler, httpClient, context) {
+        /// <summary>Sends a request containing OData payload to a server.</summary>
+        /// <param name="request">Object that represents the request to be sent..</param>
+        /// <param name="success">Callback for a successful read operation.</param>
+        /// <param name="error">Callback for handling errors.</param>
+        /// <param name="handler">Handler for data serialization.</param>
+        /// <param name="httpClient">HTTP client layer.</param>
+        /// <param name="context">Context used for processing the request</param>
+
+        return httpClient.request(request, function (response) {
+            try {
+                if (response.headers) {
+                    normalizeHeaders(response.headers);
+                }
+
+                if (response.data === undefined && response.statusCode !== 204) {
+                    handler.read(response, context);
+                }
+            } catch (err) {
+                if (err.request === undefined) {
+                    err.request = request;
+                }
+                if (err.response === undefined) {
+                    err.response = response;
+                }
+                error(err);
+                return;
+            }
+
+            success(response.data, response);
+        }, error);
+    };
+
+    var isBatch = function (value) {
+        /// <summary>Tests whether a value is a batch object in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a batch object; false otherwise.</returns>
+
+        return isComplex(value) && isArray(value.__batchRequests);
+    };
+
+    // Regular expression used for testing and parsing for a collection type.
+    var collectionTypeRE = /Collection\((.*)\)/;
+
+    var isCollection = function (value, typeName) {
+        /// <summary>Tests whether a value is a collection value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
+        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
+
+        var colData = value && value.results || value;
+        return !!colData &&
+            (isCollectionType(typeName)) ||
+            (!typeName && isArray(colData) && !isComplex(colData[0]));
+    };
+
+    var isCollectionType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a collection type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is the name of a collection type; false otherwise.</returns>
+        return collectionTypeRE.test(typeName);
+    };
+
+    var isComplex = function (value) {
+        /// <summary>Tests whether a value is a complex type value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a complex type value; false otherwise.</returns>
+
+        return !!value &&
+            isObject(value) &&
+            !isArray(value) &&
+            !isDate(value);
+    };
+
+    var isDateTimeOffset = function (value) {
+        /// <summary>Checks whether a Date object is DateTimeOffset value</summary>
+        /// <param name="value" type="Date" mayBeNull="false">Value to check.</param>
+        /// <returns type="Boolean">true if the value is a DateTimeOffset, false otherwise.</returns>
+        return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
+    };
+
+    var isDeferred = function (value) {
+        /// <summary>Tests whether a value is a deferred navigation property in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a deferred navigation property; false otherwise.</returns>
+
+        if (!value && !isComplex(value)) {
+            return false;
+        }
+        var metadata = value.__metadata || {};
+        var deferred = value.__deferred || {};
+        return !metadata.type && !!deferred.uri;
+    };
+
+    var isEntry = function (value) {
+        /// <summary>Tests whether a value is an entry object in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is an entry object; false otherwise.</returns>
+
+        return isComplex(value) && value.__metadata && "uri" in value.__metadata;
+    };
+
+    var isFeed = function (value, typeName) {
+        /// <summary>Tests whether a value is a feed value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
+        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
+
+        var feedData = value && value.results || value;
+        return isArray(feedData) && (
+            (!isCollectionType(typeName)) &&
+            (isComplex(feedData[0]))
+        );
+    };
+
+    var isGeographyEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a geography EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a geography EDM type; false otherwise.</returns>
+
+        return contains(geographyEdmTypes, typeName);
+    };
+
+    var isGeometryEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a geometry EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a geometry EDM type; false otherwise.</returns>
+
+        return contains(geometryEdmTypes, typeName);
+    };
+
+    var isNamedStream = function (value) {
+        /// <summary>Tests whether a value is a named stream value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a named stream; false otherwise.</returns>
+
+        if (!value && !isComplex(value)) {
+            return false;
+        }
+        var metadata = value.__metadata;
+        var mediaResource = value.__mediaresource;
+        return !metadata && !!mediaResource && !!mediaResource.media_src;
+    };
+
+    var isPrimitive = function (value) {
+        /// <summary>Tests whether a value is a primitive type value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <remarks>
+        ///    Date objects are considered primitive types by the library.
+        /// </remarks>
+        /// <returns type="Boolean">True is the value is a primitive type value.</returns>
+
+        return isDate(value) ||
+            typeof value === "string" ||
+            typeof value === "number" ||
+            typeof value === "boolean";
+    };
+
+    var isPrimitiveEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a primitive EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a primitive EDM type; false otherwise.</returns>
+
+        return contains(primitiveEdmTypes, typeName);
+    };
+
+    var navigationPropertyKind = function (value, propertyModel) {
+        /// <summary>Gets the kind of a navigation property value.</summary>
+        /// <param name="value">Value of the navigation property.</param>
+        /// <param name="propertyModel" type="Object" optional="true">
+        ///     Object that describes the navigation property in an OData conceptual schema.
+        /// </param>
+        /// <remarks>
+        ///     The returned string is as follows
+        /// </remarks>
+        /// <returns type="String">String value describing the kind of the navigation property; null if the kind cannot be determined.</returns>
+
+        if (isDeferred(value)) {
+            return "deferred";
+        }
+        if (isEntry(value)) {
+            return "entry";
+        }
+        if (isFeed(value)) {
+            return "feed";
+        }
+        if (propertyModel && propertyModel.relationship) {
+            if (value === null || value === undefined || !isFeed(value)) {
+                return "entry";
+            }
+            return "feed";
+        }
+        return null;
+    };
+
+    var lookupProperty = function (properties, name) {
+        /// <summary>Looks up a property by name.</summary>
+        /// <param name="properties" type="Array" mayBeNull="true">Array of property objects as per EDM metadata.</param>
+        /// <param name="name" type="String">Name to look for.</param>
+        /// <returns type="Object">The property object; null if not found.</returns>
+
+        return find(properties, function (property) {
+            return property.name === name;
+        });
+    };
+
+    var lookupInMetadata = function (name, metadata, kind) {
+        /// <summary>Looks up a type object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
+        /// <returns>An type description if the name is found; null otherwise.</returns>
+
+        return (name) ? forEachSchema(metadata, function (schema) {
+            return lookupInSchema(name, schema, kind);
+        }) : null;
+    };
+
+    var lookupEntitySet = function (entitySets, 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(entitySets, function (entitySet) {
+            return entitySet.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>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>A complex type description if the name is found; null otherwise.</returns>
+
+        return lookupInMetadata(name, metadata, "complexType");
+    };
+
+    var lookupEntityType = function (name, metadata) {
+        /// <summary>Looks up an entity type object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity type description if the name is found; null otherwise.</returns>
+
+        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>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity container description if the name is found; null otherwise.</returns>
+
+        return forEachSchema(metadata, function (schema) {
+            return find(schema.entityContainer, function (container) {
+                return parseBool(container.isDefaultEntityContainer);
+            });
+        });
+    };
+
+    var lookupEntityContainer = function (name, metadata) {
+        /// <summary>Looks up an entity container object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity container description if the name is found; null otherwise.</returns>
+
+        return lookupInMetadata(name, metadata, "entityContainer");
+    };
+
+    var lookupFunctionImport = function (functionImports, name) {
+        /// <summary>Looks up a function import by name.</summary>
+        /// <param name="properties" type="Array" mayBeNull="true">Array of function import 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(functionImports, function (functionImport) {
+            return functionImport.name === name;
+        });
+    };
+
+    var lookupNavigationPropertyType = function (navigationProperty, metadata) {
+        /// <summary>Looks up the target entity type for a navigation property.</summary>
+        /// <param name="navigationProperty" type="Object"></param>
+        /// <param name="metadata" type="Object"></param>
+        /// <returns type="String">The entity type name for the specified property, null if not found.</returns>
+
+        var result = null;
+        if (navigationProperty) {
+            var rel = navigationProperty.relationship;
+            var association = forEachSchema(metadata, function (schema) {
+                // The name should be the namespace qualified name in 'ns'.'type' format.
+                var nameOnly = removeNamespace(schema["namespace"], rel);
+                var associations = schema.association;
+                if (nameOnly && associations) {
+                    var i, len;
+                    for (i = 0, len = associations.length; i < len; i++) {
+                        if (associations[i].name === nameOnly) {
+                            return associations[i];
+                        }
+                    }
+                }
+                return null;
+            });
+
+            if (association) {
+                var end = association.end[0];
+                if (end.role !== navigationProperty.toRole) {
+                    end = association.end[1];
+                    // For metadata to be valid, end.role === navigationProperty.toRole now.
+                }
+                result = end.type;
+            }
+        }
+        return result;
+    };
+
+    var lookupNavigationPropertyEntitySet = function (navigationProperty, sourceEntitySetName, metadata) {
+        /// <summary>Looks up the target entityset name for a navigation property.</summary>
+        /// <param name="navigationProperty" type="Object"></param>
+        /// <param name="metadata" type="Object"></param>
+        /// <returns type="String">The entityset name for the specified property, null if not found.</returns>
+
+        if (navigationProperty) {
+            var rel = navigationProperty.relationship;
+            var associationSet = forEachSchema(metadata, function (schema) {
+                var containers = schema.entity

<TRUNCATED>

[10/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/rx.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/rx.js b/odatajs/tests/common/rx.js
new file mode 100644
index 0000000..f71e959
--- /dev/null
+++ b/odatajs/tests/common/rx.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+ 
+// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
+// This code is licensed by Microsoft Corporation under the terms
+// of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
+// See http://go.microsoft.com/fwlink/?LinkId=186234.
+
+(function(){var a;var b;var c=this;var d="Index out of range";if(typeof ProvideCustomRxRootObject =="undefined")b=c.Rx={}; else b=ProvideCustomRxRootObject();var e=function(){};var f=function(){return new Date().getTime();};var g=function(r0,s0){return r0===s0;};var h=function(r0){return r0;};var i=function(r0){return {Dispose:r0};};var j={Dispose:e};b.Disposable={Create:i,Empty:j};var k=b.BooleanDisposable=function(){var r0=false;this.GetIsDisposed=function(){return r0;};this.Dispose=function(){r0=true;};};var l=function(r0){var s0=false;r0.a++;this.Dispose=function(){var t0=false;if(!r0.b){if(!this.c){this.c=true;r0.a--;if(r0.a==0&&r0.d){r0.b=true;t0=true;}}}if(t0)r0.e.Dispose();};};var m=b.RefCountDisposable=function(r0){this.d=false;this.b=false;this.e=r0;this.a=0;this.Dispose=function(){var s0=false;if(!this.b){if(!this.d){this.d=true;if(this.a==0){this.b=true;s0=true;}}}if(s0)this.e.Dispose();};this.GetDisposable=function(){if(this.b)return j; else return new l(this);};};var n
 =b.CompositeDisposable=function(){var r0=new q();for(var s0=0;s0<arguments.length;s0++) r0.Add(arguments[s0]);var t0=false;this.GetCount=function(){return r0.GetCount();};this.Add=function(u0){if(!t0)r0.Add(u0); else u0.Dispose();};this.Remove=function(u0,v0){if(!t0){var w0=r0.Remove(u0);if(!v0&w0)u0.Dispose();}};this.Dispose=function(){if(!t0){t0=true;this.Clear();}};this.Clear=function(){for(var u0=0;u0<r0.GetCount();u0++) r0.GetItem(u0).Dispose();r0.Clear();};};var o=b.MutableDisposable=function(){var r0=false;var s0;this.Get=function(){return s0;},this.Replace=function(t0){if(r0&&t0!==a)t0.Dispose(); else{if(s0!==a)s0.Dispose();s0=t0;}};this.Dispose=function(){if(!r0){r0=true;if(s0!==a)s0.Dispose();}};};var p=function(r0){var s0=[];for(var t0=0;t0<r0.length;t0++) s0.push(r0[t0]);return s0;};var q=b.List=function(r0){var s0=[];var t0=0;var u0=r0!==a?r0:g;this.Add=function(v0){s0[t0]=v0;t0++;};this.RemoveAt=function(v0){if(v0<0||v0>=t0)throw d;if(v0==0){s0.shift();t0--;}else{s0.sp
 lice(v0,1);t0--;}};this.IndexOf=function(v0){for(var w0=0;w0<t0;w0++){if(u0(v0,s0[w0]))return w0;}return -1;};this.Remove=function(v0){var w0=this.IndexOf(v0);if(w0==-1)return false;this.RemoveAt(w0);return true;};this.Clear=function(){s0=[];t0=0;};this.GetCount=function(){return t0;};this.GetItem=function(v0){if(v0<0||v0>=t0)throw d;return s0[v0];};this.SetItem=function(v0,w0){if(v0<0||v0>=t0)throw d;s0[v0]=w0;};this.ToArray=function(){var v0=[];for(var w0=0;w0<this.GetCount();w0++) v0.push(this.GetItem(w0));return v0;};};var r=function(r0){if(r0===null)r0=g;this.f=r0;var s0=4;this.g=new Array(s0);this.h=0;};r.prototype.i=function(r0,s0){return this.f(this.g[r0],this.g[s0])<0;};r.prototype.j=function(r0){if(r0>=this.h||r0<0)return;var s0=r0-1>>1;if(s0<0||s0==r0)return;if(this.i(r0,s0)){var t0=this.g[r0];this.g[r0]=this.g[s0];this.g[s0]=t0;this.j(s0);}};r.prototype.k=function(r0){if(r0===a)r0=0;var s0=2*r0+1;var t0=2*r0+2;var u0=r0;if(s0<this.h&&this.i(s0,u0))u0=s0;if(t0<this.h&&thi
 s.i(t0,u0))u0=t0;if(u0!=r0){var v0=this.g[r0];this.g[r0]=this.g[u0];this.g[u0]=v0;this.k(u0);}};r.prototype.GetCount=function(){return this.h;};r.prototype.Peek=function(){if(this.h==0)throw "Heap is empty.";return this.g[0];};r.prototype.Dequeue=function(){var r0=this.Peek();this.g[0]=this.g[--this.h];delete this.g[this.h];this.k();return r0;};r.prototype.Enqueue=function(r0){var s0=this.h++;this.g[s0]=r0;this.j(s0);};var s=b.Scheduler=function(r0,s0,t0){this.Schedule=r0;this.ScheduleWithTime=s0;this.Now=t0;this.ScheduleRecursive=function(u0){var v0=this;var w0=new n();var x0;x0=function(){u0(function(){var y0=false;var z0=false;var A0;A0=v0.Schedule(function(){x0();if(y0)w0.Remove(A0); else z0=true;});if(!z0){w0.Add(A0);y0=true;}});};w0.Add(v0.Schedule(x0));return w0;};this.ScheduleRecursiveWithTime=function(u0,v0){var w0=this;var x0=new n();var y0;y0=function(){u0(function(z0){var A0=false;var B0=false;var C0;C0=w0.ScheduleWithTime(function(){y0();if(A0)x0.Remove(C0); else B0=tru
 e;},z0);if(!B0){x0.Add(C0);A0=true;}});};x0.Add(w0.ScheduleWithTime(y0,v0));return x0;};};var t=b.VirtualScheduler=function(r0,s0,t0,u0){var v0=new s(function(w0){return this.ScheduleWithTime(w0,0);},function(w0,x0){return this.ScheduleVirtual(w0,u0(x0));},function(){return t0(this.l);});v0.ScheduleVirtual=function(w0,x0){var y0=new k();var z0=s0(this.l,x0);var A0=function(){if(!y0.IsDisposed)w0();};var B0=new y(A0,z0);this.m.Enqueue(B0);return y0;};v0.Run=function(){while(this.m.GetCount()>0){var w0=this.m.Dequeue();this.l=w0.n;w0.o();}};v0.RunTo=function(w0){while(this.m.GetCount()>0&&this.f(this.m.Peek().n,w0)<=0){var x0=this.m.Dequeue();this.l=x0.n;x0.o();}};v0.GetTicks=function(){return this.l;};v0.l=0;v0.m=new r(function(w0,x0){return r0(w0.n,x0.n);});v0.f=r0;return v0;};var u=b.TestScheduler=function(){var r0=new t(function(s0,t0){return s0-t0;},function(s0,t0){return s0+t0;},function(s0){return new Date(s0);},function(s0){if(s0<=0)return 1;return s0;});return r0;};var v=new 
 s(function(r0){return this.ScheduleWithTime(r0,0);},function(r0,s0){var t0=this.Now()+s0;var u0=new y(r0,t0);if(this.m===a){var v0=new w();try{this.m.Enqueue(u0);v0.p();}finally{v0.q();}}else this.m.Enqueue(u0);return u0.r();},f);v.s=function(r0){if(this.m===a){var s0=new w();try{r0();s0.p();}finally{s0.q();}}else r0();};s.CurrentThread=v;var w=function(){v.m=new r(function(r0,s0){try{return r0.n-s0.n;}catch(t0){debugger;}});this.q=function(){v.m=a;};this.p=function(){while(v.m.GetCount()>0){var r0=v.m.Dequeue();if(!r0.t()){while(r0.n-v.Now()>0);if(!r0.t())r0.o();}}};};var x=0;var y=function(r0,s0){this.u=x++;this.o=r0;this.n=s0;this.v=new k();this.t=function(){return this.v.GetIsDisposed();};this.r=function(){return this.v;};};var z=new s(function(r0){r0();return j;},function(r0,s0){while(this.Now<s0);r0();},f);s.Immediate=z;var A=new s(function(r0){var s0=c.setTimeout(r0,0);return i(function(){c.clearTimeout(s0);});},function(r0,s0){var t0=c.setTimeout(r0,s0);return i(function(){c
 .clearTimeout(t0);});},f);s.Timeout=A;var B=b.Observer=function(r0,s0,t0){this.OnNext=r0===a?e:r0;this.OnError=s0===a?function(u0){throw u0;}:s0;this.OnCompleted=t0===a?e:t0;this.AsObserver=function(){var u0=this;return new B(function(v0){u0.OnNext(v0);},function(v0){u0.OnError(v0);},function(){u0.OnCompleted();});};};var C=B.Create=function(r0,s0,t0){return new B(r0,s0,t0);};var D=b.Observable=function(r0){this.w=r0;};var E=D.CreateWithDisposable=function(r0){return new D(r0);};var F=D.Create=function(r0){return E(function(s0){return i(r0(s0));});};var G=function(){return this.Select(function(r0){return r0.Value;});};D.prototype={Subscribe:function(r0,s0,t0){var u0;if(arguments.length==0||arguments.length>1||typeof r0 =="function")u0=new B(r0,s0,t0); else u0=r0;return this.x(u0);},x:function(r0){var s0=false;var t0=new o();var u0=this;v.s(function(){var v0=new B(function(w0){if(!s0)r0.OnNext(w0);},function(w0){if(!s0){s0=true;t0.Dispose();r0.OnError(w0);}},function(){if(!s0){s0=tru
 e;t0.Dispose();r0.OnCompleted();}});t0.Replace(u0.w(v0));});return new n(t0,i(function(){s0=true;}));},Select:function(r0){var s0=this;return E(function(t0){var u0=0;return s0.Subscribe(new B(function(v0){var w0;try{w0=r0(v0,u0++);}catch(x0){t0.OnError(x0);return;}t0.OnNext(w0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},Let:function(r0,s0){if(s0===a)return r0(this);var t0=this;return E(function(u0){var v0=s0();var w0;try{w0=r0(v0);}catch(A0){return L(A0).Subscribe(u0);}var x0=new o();var y0=new o();var z0=new n(y0,x0);x0.Replace(w0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){u0.OnError(A0);z0.Dispose();},function(){u0.OnCompleted();z0.Dispose();}));y0.Replace(t0.Subscribe(v0));return z0;});},MergeObservable:function(){var r0=this;return E(function(s0){var t0=false;var u0=new n();var v0=new o();u0.Add(v0);v0.Replace(r0.Subscribe(function(w0){var x0=new o();u0.Add(x0);x0.Replace(w0.Subscribe(function(y0){s0.OnNext(y0);},function(y0){s0.OnError(y0);},f
 unction(){u0.Remove(x0);if(u0.GetCount()==1&&t0)s0.OnCompleted();}));},function(w0){s0.OnError(w0);},function(){t0=true;if(u0.GetCount()==1)s0.OnCompleted();}));return u0;});},y:function(r0,s0){var t0=p(s0);t0.unshift(this);return r0(t0);},Concat:function(){return this.y(I,arguments);},Merge:function(){return this.y(H,arguments);},Catch:function(){return this.y(P,arguments);},OnErrorResumeNext:function(){return this.y(V,arguments);},Zip:function(r0,s0){var t0=this;return E(function(u0){var v0=false;var w0=[];var x0=[];var y0=false;var z0=false;var A0=new n();var B0=function(C0){A0.Dispose();w0=a;x0=a;u0.OnError(C0);};A0.Add(t0.Subscribe(function(C0){if(z0){u0.OnCompleted();return;}if(x0.length>0){var D0=x0.shift();var E0;try{E0=s0(C0,D0);}catch(F0){A0.Dispose();u0.OnError(F0);return;}u0.OnNext(E0);}else w0.push(C0);},B0,function(){if(z0){u0.OnCompleted();return;}y0=true;}));A0.Add(r0.Subscribe(function(C0){if(y0){u0.OnCompleted();return;}if(w0.length>0){var D0=w0.shift();var E0;try{
 E0=s0(D0,C0);}catch(F0){A0.Dispose();u0.OnError(F0);return;}u0.OnNext(E0);}else x0.push(C0);},B0,function(){if(y0){u0.OnCompleted();return;}z0=true;}));return A0;});},CombineLatest:function(r0,s0){var t0=this;return E(function(u0){var v0=false;var w0=false;var x0=false;var y0;var z0;var A0=false;var B0=false;var C0=new n();var D0=function(E0){C0.Dispose();u0.OnError(E0);};C0.Add(t0.Subscribe(function(E0){if(B0){u0.OnCompleted();return;}if(x0){var F0;try{F0=s0(E0,z0);}catch(G0){C0.Dispose();u0.OnError(G0);return;}u0.OnNext(F0);}y0=E0;w0=true;},D0,function(){if(B0){u0.OnCompleted();return;}A0=true;}));C0.Add(r0.Subscribe(function(E0){if(A0){u0.OnCompleted();return;}if(w0){var F0;try{F0=s0(y0,E0);}catch(G0){C0.Dispose();u0.OnError(G0);return;}u0.OnNext(F0);}z0=E0;x0=true;},D0,function(){if(A0){u0.OnCompleted();return;}B0=true;}));});},Switch:function(){var r0=this;return E(function(s0){var t0=false;var u0=new o();var v0=new o();v0.Replace(r0.Subscribe(function(w0){if(!t0){var x0=new o(
 );x0.Replace(w0.Subscribe(function(y0){s0.OnNext(y0);},function(y0){v0.Dispose();u0.Dispose();s0.OnError(y0);},function(){u0.Replace(a);if(t0)s0.OnCompleted();}));u0.Replace(x0);}},function(w0){u0.Dispose();s0.OnError(w0);},function(){t0=true;if(u0.Get()===a)s0.OnCompleted();}));return new n(v0,u0);});},TakeUntil:function(r0){var s0=this;return E(function(t0){var u0=new n();u0.Add(r0.Subscribe(function(){t0.OnCompleted();u0.Dispose();},function(v0){t0.OnError(v0);},function(){}));u0.Add(s0.Subscribe(t0));return u0;});},SkipUntil:function(r0){var s0=this;return E(function(t0){var u0=true;var v0=new n();v0.Add(r0.Subscribe(function(){u0=false;},function(w0){t0.OnError(w0);},e));v0.Add(s0.Subscribe(new B(function(w0){if(!u0)t0.OnNext(w0);},function(w0){t0.OnError(w0);},function(){if(!u0)t0.OnCompleted();})));return v0;});},Scan1:function(r0){var s0=this;return O(function(){var t0;var u0=false;return s0.Select(function(v0){if(u0)t0=r0(t0,v0); else{t0=v0;u0=true;}return t0;});});},Scan:f
 unction(r0,s0){var t0=this;return O(function(){var u0;var v0=false;return t0.Select(function(w0){if(v0)u0=s0(u0,w0); else{u0=s0(r0,w0);v0=true;}return u0;});});},Scan0:function(r0,s0){var t0=this;return E(function(u0){var v0=r0;var w0=true;return t0.Subscribe(function(x0){if(w0){w0=false;u0.OnNext(v0);}try{v0=s0(v0,x0);}catch(y0){u0.OnError(y0);return;}u0.OnNext(v0);},function(x0){if(w0)u0.OnNext(v0);u0.OnError(x0);},function(){if(w0)u0.OnNext(v0);u0.OnCompleted();});});},Finally:function(r0){var s0=this;return F(function(t0){var u0=s0.Subscribe(t0);return function(){try{u0.Dispose();r0();}catch(v0){r0();throw v0;}};});},Do:function(r0,s0,t0){var u0;if(arguments.length==0||arguments.length>1||typeof r0 =="function")u0=new B(r0,s0!==a?s0:e,t0); else u0=r0;var v0=this;return E(function(w0){return v0.Subscribe(new B(function(x0){try{u0.OnNext(x0);}catch(y0){w0.OnError(y0);return;}w0.OnNext(x0);},function(x0){if(s0!==a)try{u0.OnError(x0);}catch(y0){w0.OnError(y0);return;}w0.OnError(x0);
 },function(){if(t0!==a)try{u0.OnCompleted();}catch(x0){w0.OnError(x0);return;}w0.OnCompleted();}));});},Where:function(r0){var s0=this;return E(function(t0){var u0=0;return s0.Subscribe(new B(function(v0){var w0=false;try{w0=r0(v0,u0++);}catch(x0){t0.OnError(x0);return;}if(w0)t0.OnNext(v0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},Take:function(r0,s0){if(s0===a)s0=z;var t0=this;return E(function(u0){if(r0<=0){t0.Subscribe().Dispose();return N(s0).Subscribe(u0);}var v0=r0;return t0.Subscribe(new B(function(w0){if(v0-->0){u0.OnNext(w0);if(v0==0)u0.OnCompleted();}},function(w0){u0.OnError(w0);},function(){u0.OnCompleted();}));});},GroupBy:function(r0,s0,t0){if(r0===a)r0=h;if(s0===a)s0=h;if(t0===a)t0=function(v0){return v0.toString();};var u0=this;return E(function(v0){var w0={};var x0=new o();var y0=new m(x0);x0.Replace(u0.Subscribe(function(z0){var A0;try{A0=r0(z0);}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}var B0=false;var C0;try
 {var D0=t0(A0);if(w0[D0]===a){C0=new i0();w0[D0]=C0;B0=true;}else C0=w0[D0];}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}if(B0){var E0=E(function(G0){return new n(y0.GetDisposable(),C0.Subscribe(G0));});E0.Key=A0;v0.OnNext(E0);}var F0;try{F0=s0(z0);}catch(G0){for(var H0 in w0) w0[H0].OnError(G0);v0.OnError(G0);return;}C0.OnNext(F0);},function(z0){for(var A0 in w0) w0[A0].OnError(z0);v0.OnError(z0);},function(){for(var z0 in w0) w0[z0].OnCompleted();v0.OnCompleted();}));return y0;});},TakeWhile:function(r0){var s0=this;return E(function(t0){var u0=true;return s0.Subscribe(new B(function(v0){if(u0){try{u0=r0(v0);}catch(w0){t0.OnError(w0);return;}if(u0)t0.OnNext(v0); else t0.OnCompleted();}},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},SkipWhile:function(r0){var s0=this;return E(function(t0){var u0=false;return s0.Subscribe(new B(function(v0){if(!u0)try{u0=!r0(v0);}catch(w0){t0.OnError(w0);return;}if(u0)t0.OnNext(v0);},function(v0){t0.OnE
 rror(v0);},function(){t0.OnCompleted();}));});},Skip:function(r0){var s0=this;return E(function(t0){var u0=r0;return s0.Subscribe(new B(function(v0){if(u0--<=0)t0.OnNext(v0);},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();}));});},SelectMany:function(r0){return this.Select(r0).MergeObservable();},TimeInterval:function(r0){if(r0===a)r0=z;var s0=this;return O(function(){var t0=r0.Now();return s0.Select(function(u0){var v0=r0.Now();var w0=v0-t0;t0=v0;return {Interval:w0,Value:u0};});});},RemoveInterval:G,Timestamp:function(r0){if(r0===a)r0=z;return this.Select(function(s0){return {Timestamp:r0.Now(),Value:s0};});},RemoveTimestamp:G,Materialize:function(){var r0=this;return E(function(s0){return r0.Subscribe(new B(function(t0){s0.OnNext(new h0("N",t0));},function(t0){s0.OnNext(new h0("E",t0));s0.OnCompleted();},function(){s0.OnNext(new h0("C"));s0.OnCompleted();}));});},Dematerialize:function(){return this.SelectMany(function(r0){return r0;});},AsObservable:function(){var r0
 =this;return E(function(s0){return r0.Subscribe(s0);});},Delay:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0=[];var w0=false;var x0=new o();var y0=t0.Materialize().Timestamp().Subscribe(function(z0){if(z0.Value.Kind=="E"){u0.OnError(z0.Value.Value);v0=[];if(w0)x0.Dispose();return;}v0.push({Timestamp:s0.Now()+r0,Value:z0.Value});if(!w0){x0.Replace(s0.ScheduleRecursiveWithTime(function(A0){var B0;do{B0=a;if(v0.length>0&&v0[0].Timestamp<=s0.Now())B0=v0.shift().Value;if(B0!==a)B0.Accept(u0);}while(B0!==a);if(v0.length>0){A0(Math.max(0,v0[0].Timestamp-s0.Now()));w0=true;}else w0=false;},r0));w0=true;}});return new n(y0,x0);});},Throttle:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0;var w0=false;var x0=new o();var y0=0;var z0=t0.Subscribe(function(A0){w0=true;v0=A0;y0++;var B0=y0;x0.Replace(s0.ScheduleWithTime(function(){if(w0&&y0==B0)u0.OnNext(v0);w0=false;},r0));},function(A0){x0.Dispose();u0.OnError(A0);w0=false;y0++;},function(){x0.D
 ispose();if(w0)u0.OnNext(v0);u0.OnCompleted();w0=false;y0++;});return new n(z0,x0);});},Timeout:function(r0,s0,t0){if(t0===a)t0=A;if(s0===a)s0=L("Timeout",t0);var u0=this;return E(function(v0){var w0=new o();var x0=new o();var y0=0;var z0=y0;var A0=false;x0.Replace(t0.ScheduleWithTime(function(){A0=y0==z0;if(A0)w0.Replace(s0.Subscribe(v0));},r0));w0.Replace(u0.Subscribe(function(B0){var C0=0;if(!A0){y0++;C0=y0;v0.OnNext(B0);x0.Replace(t0.ScheduleWithTime(function(){A0=y0==C0;if(A0)w0.Replace(s0.Subscribe(v0));},r0));}},function(B0){if(!A0){y0++;v0.OnError(B0);}},function(){if(!A0){y0++;v0.OnCompleted();}}));return new n(w0,x0);});},Sample:function(r0,s0){if(s0===a)s0=A;var t0=this;return E(function(u0){var v0=false;var w0;var x0=false;var y0=new n();y0.Add(Y(r0,s0).Subscribe(function(z0){if(v0){u0.OnNext(w0);v0=false;}if(x0)u0.OnCompleted();},function(z0){u0.OnError(z0);},function(){u0.OnCompleted();}));y0.Add(t0.Subscribe(function(z0){v0=true;w0=z0;},function(z0){u0.OnError(z0);y0.
 Dispose();},function(){x0=true;}));return y0;});},Repeat:function(r0,s0){var t0=this;if(s0===a)s0=z;if(r0===a)r0=-1;return E(function(u0){var v0=r0;var w0=new o();var x0=new n(w0);var y0=function(z0){w0.Replace(t0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){u0.OnError(A0);},function(){if(v0>0){v0--;if(v0==0){u0.OnCompleted();return;}}z0();}));};x0.Add(s0.ScheduleRecursive(y0));return x0;});},Retry:function(r0,s0){var t0=this;if(s0===a)s0=z;if(r0===a)r0=-1;return E(function(u0){var v0=r0;var w0=new o();var x0=new n(w0);var y0=function(z0){w0.Replace(t0.Subscribe(function(A0){u0.OnNext(A0);},function(A0){if(v0>0){v0--;if(v0==0){u0.OnError(A0);return;}}z0();},function(){u0.OnCompleted();}));};x0.Add(s0.ScheduleRecursive(y0));return x0;});},BufferWithTime:function(r0,s0,t0){if(t0===a)t0=A;if(s0===a)s0=r0;var u0=this;return E(function(v0){var w0=new q();var x0=t0.Now();var y0=function(){var C0=[];for(var D0=0;D0<w0.GetCount();D0++){var E0=w0.GetItem(D0);if(E0.Timestamp-x0>=0)C0.p
 ush(E0.Value);}return C0;};var z0=new n();var A0=function(C0){v0.OnError(C0);};var B0=function(){v0.OnNext(y0());v0.OnCompleted();};z0.Add(u0.Subscribe(function(C0){w0.Add({Value:C0,Timestamp:t0.Now()});},A0,B0));z0.Add(a0(r0,s0,t0).Subscribe(function(C0){var D0=y0();var E0=t0.Now()+s0-r0;while(w0.GetCount()>0&&w0.GetItem(0).Timestamp-E0<=0)w0.RemoveAt(0);v0.OnNext(D0);x0=E0;},A0,B0));return z0;});},BufferWithTimeOrCount:function(r0,s0,t0){if(t0===a)t0=A;var u0=this;return E(function(v0){var w0=0;var x0=new q();var y0=function(){v0.OnNext(x0.ToArray());x0.Clear();w0++;};var z0=new o();var A0;A0=function(C0){var D0=t0.ScheduleWithTime(function(){var E0=false;var F0=0;if(C0==w0){y0();F0=w0;E0=true;}if(E0)A0(F0);},r0);z0.Replace(D0);};A0(w0);var B0=u0.Subscribe(function(C0){var D0=false;var E0=0;x0.Add(C0);if(x0.GetCount()==s0){y0();E0=w0;D0=true;}if(D0)A0(E0);},function(C0){v0.OnError(C0);x0.Clear();},function(){v0.OnNext(x0.ToArray());w0++;v0.OnCompleted();x0.Clear();});return new n(
 B0,z0);});},BufferWithCount:function(r0,s0){if(s0===a)s0=r0;var t0=this;return E(function(u0){var v0=[];var w0=0;return t0.Subscribe(function(x0){if(w0==0)v0.push(x0); else w0--;var y0=v0.length;if(y0==r0){var z0=v0;v0=[];var A0=Math.min(s0,y0);for(var B0=A0;B0<y0;B0++) v0.push(z0[B0]);w0=Math.max(0,s0-r0);u0.OnNext(z0);}},function(x0){u0.OnError(x0);},function(){if(v0.length>0)u0.OnNext(v0);u0.OnCompleted();});});},StartWith:function(r0,s0){if(!(r0 instanceof Array))r0=[r0];if(s0===a)s0=z;var t0=this;return E(function(u0){var v0=new n();var w0=0;v0.Add(s0.ScheduleRecursive(function(x0){if(w0<r0.length){u0.OnNext(r0[w0]);w0++;x0();}else v0.Add(t0.Subscribe(u0));}));return v0;});},DistinctUntilChanged:function(r0,s0){if(r0===a)r0=h;if(s0===a)s0=g;var t0=this;return E(function(u0){var v0;var w0=false;return t0.Subscribe(function(x0){var y0;try{y0=r0(x0);}catch(A0){u0.OnError(A0);return;}var z0=false;if(w0)try{z0=s0(v0,y0);}catch(A0){u0.OnError(A0);return;}if(!w0||!z0){w0=true;v0=y0;u0
 .OnNext(x0);}},function(x0){u0.OnError(x0);},function(){u0.OnCompleted();});});},Publish:function(r0){if(r0===a)return new q0(this,new i0());var s0=this;return E(function(t0){var u0=new q0(s0,new i0());return new n(r0(u0).Subscribe(B),u0.Connect());});},Prune:function(r0,s0){if(s0===a)s0=z;if(r0===a)return new q0(this,new k0(s0));var t0=this;return E(function(u0){var v0=new q0(t0,new k0(s0));return new n(r0(v0).Subscribe(B),v0.Connect());});},Replay:function(r0,s0,t0,u0){if(u0===a)u0=v;if(r0===a)return new q0(this,new m0(s0,t0,u0));var v0=this;return E(function(w0){var x0=new q0(v0,new m0(s0,t0,u0));return new n(r0(x0).Subscribe(B),x0.Connect());});},SkipLast:function(r0){var s0=this;return E(function(t0){var u0=[];return s0.Subscribe(function(v0){u0.push(v0);if(u0.length>r0)t0.OnNext(u0.shift());},function(v0){t0.OnError(v0);},function(){t0.OnCompleted();});});},TakeLast:function(r0){var s0=this;return E(function(t0){var u0=[];return s0.Subscribe(function(v0){u0.push(v0);if(u0.leng
 th>r0)u0.shift();},function(v0){t0.OnError(v0);},function(){while(u0.length>0)t0.OnNext(u0.shift());t0.OnCompleted();});});}};var H=D.Merge=function(r0,s0){if(s0===a)s0=z;return J(r0,s0).MergeObservable();};var I=D.Concat=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();var v0=0;var w0=s0.ScheduleRecursive(function(x0){if(v0<r0.length){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},function(A0){t0.OnError(A0);},x0));}else t0.OnCompleted();});return new n(u0,w0);});};var J=D.FromArray=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=0;return s0.ScheduleRecursive(function(v0){if(u0<r0.length){t0.OnNext(r0[u0++]);v0();}else t0.OnCompleted();});});};var K=D.Return=function(r0,s0){if(s0===a)s0=z;return E(function(t0){return s0.Schedule(function(){t0.OnNext(r0);t0.OnCompleted();});});};var L=D.Throw=function(r0,s0){if(s0===a)s0=z;return E(function(t0){return s0.Schedule(function(){t0.OnError(r0);});});};v
 ar M=D.Never=function(){return E(function(r0){return j;});};var N=D.Empty=function(r0){if(r0===a)r0=z;return E(function(s0){return r0.Schedule(function(){s0.OnCompleted();});});};var O=D.Defer=function(r0){return E(function(s0){var t0;try{t0=r0();}catch(u0){s0.OnError(u0);return j;}return t0.Subscribe(s0);});};var P=D.Catch=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();var v0=0;var w0=s0.ScheduleRecursive(function(x0){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},function(A0){if(v0<r0.length)x0(); else t0.OnError(A0);},function(){t0.OnCompleted();}));});return new n(u0,w0);});};var Q=D.Using=function(r0,s0){return E(function(t0){var u0;var v0=j;try{var w0=r0();if(w0!==a)v0=w0;u0=s0(w0);}catch(x0){return new n(Throw(x0).Subscribe(t0),v0);}return new n(u0.Subscribe(t0),v0);});};var R=D.Range=function(r0,s0,t0){if(t0===a)t0=z;var u0=r0+s0-1;return T(r0,function(v0){return v0<=u0;},function(v0){return v0+1;},h
 ,t0);};var S=D.Repeat=function(r0,s0,t0){if(t0===a)t0=z;if(s0===a)s0=-1;var u0=s0;return E(function(v0){return t0.ScheduleRecursive(function(w0){v0.OnNext(r0);if(u0>0){u0--;if(u0==0){v0.OnCompleted();return;}}w0();});});};var T=D.Generate=function(r0,s0,t0,u0,v0){if(v0===a)v0=z;return E(function(w0){var x0=r0;var y0=true;return v0.ScheduleRecursive(function(z0){var A0=false;var B0;try{if(y0)y0=false; else x0=t0(x0);A0=s0(x0);if(A0)B0=u0(x0);}catch(C0){w0.OnError(C0);return;}if(A0){w0.OnNext(B0);z0();}else w0.OnCompleted();});});};var U=D.GenerateWithTime=function(r0,s0,t0,u0,v0,w0){if(w0===a)w0=A;return new E(function(x0){var y0=r0;var z0=true;var A0=false;var B0;var C0;return w0.ScheduleRecursiveWithTime(function(D0){if(A0)x0.OnNext(B0);try{if(z0)z0=false; else y0=t0(y0);A0=s0(y0);if(A0){B0=u0(y0);C0=v0(y0);}}catch(E0){x0.OnError(E0);return;}if(A0)D0(C0); else x0.OnCompleted();},0);});};var V=D.OnErrorResumeNext=function(r0,s0){if(s0===a)s0=z;return E(function(t0){var u0=new o();va
 r v0=0;var w0=s0.ScheduleRecursive(function(x0){if(v0<r0.length){var y0=r0[v0];v0++;var z0=new o();u0.Replace(z0);z0.Replace(y0.Subscribe(function(A0){t0.OnNext(A0);},x0,x0));}else t0.OnCompleted();});return new n(u0,w0);});};var W=D.Amb=function(){var r0=arguments;return E(function(s0){var t0=new n();var u0=new o();u0.Replace(t0);var v0=false;for(var w0=0;w0<r0.length;w0++){var x0=r0[w0];var y0=new o();var z0=new B(function(A0){if(!v0){t0.Remove(this.z,true);t0.Dispose();u0.Replace(this.z);v0=true;}s0.OnNext(A0);},function(A0){s0.OnError(A0);u0.Dispose();},function(){s0.OnCompleted();u0.Dispose();});z0.z=y0;y0.Replace(x0.Subscribe(z0));t0.Add(y0);}return u0;});};var X=D.ForkJoin=function(){var r0=arguments;return E(function(s0){var t0=[];var u0=[];var v0=[];var w0=new n();for(var x0=0;x0<r0.length;x0++) (function(y0){w0.Add(r0[y0].Subscribe(function(z0){t0[y0]=true;v0[y0]=z0;},function(z0){s0.OnError(z0);},function(z0){if(!t0[y0]){s0.OnCompleted();v0=a;t0=a;return;}u0[y0]=true;var 
 A0=true;for(var B0=0;B0<r0.length;B0++){if(!u0[B0])A0=false;}if(A0){s0.OnNext(v0);s0.OnCompleted();v0=a;u0=a;t0=a;}}));})(x0);return w0;});};var Y=D.Interval=function(r0,s0){return a0(r0,r0,s0);};var Z=function(r0){return Math.max(0,r0);};var a0=D.Timer=function(r0,s0,t0){if(t0===a)t0=A;if(r0===a)return M();if(r0 instanceof Date)return O(function(){return D.Timer(r0-new Date(),s0,t0);});var u0=Z(r0);if(s0===a)return E(function(w0){return t0.ScheduleWithTime(function(){w0.OnNext(0);w0.OnCompleted();},u0);});var v0=Z(s0);return E(function(w0){var x0=0;return t0.ScheduleRecursiveWithTime(function(y0){w0.OnNext(x0++);y0(v0);},u0);});};var b0=D.While=function(r0,s0){return E(function(t0){var u0=new o();var v0=new n(u0);v0.Add(z.ScheduleRecursive(function(w0){var x0;try{x0=r0();}catch(y0){t0.OnError(y0);return;}if(x0)u0.Replace(s0.Subscribe(function(y0){t0.OnNext(y0);},function(y0){t0.OnError(y0);},function(){w0();})); else t0.OnCompleted();}));return v0;});};var c0=D.If=function(r0,s0,t0
 ){if(t0===a)t0=N();return O(function(){return r0()?s0:t0;});};var d0=D.DoWhile=function(r0,s0){return I([r0,b0(s0,r0)]);};var e0=D.Case=function(r0,s0,t0,u0){if(u0===a)u0=z;if(t0===a)t0=N(u0);return O(function(){var v0=s0[r0()];if(v0===a)v0=t0;return v0;});};var f0=D.For=function(r0,s0){return E(function(t0){var u0=new n();var v0=0;u0.Add(z.ScheduleRecursive(function(w0){if(v0<r0.length){var x0;try{x0=s0(r0[v0]);}catch(y0){t0.OnError(y0);return;}u0.Add(x0.Subscribe(function(y0){t0.OnNext(y0);},function(y0){t0.OnError(y0);},function(){v0++;w0();}));}else t0.OnCompleted();}));return u0;});};var g0=D.Let=function(r0,s0){return O(function(){return s0(r0);});};var h0=b.Notification=function(r0,s0){this.Kind=r0;this.Value=s0;this.toString=function(){return this.Kind+": "+this.Value;};this.Accept=function(t0){switch(this.Kind){case "N":t0.OnNext(this.Value);break;case "E":t0.OnError(this.Value);break;case "C":t0.OnCompleted();break;}return j;};this.w=function(t0){var u0=this.Accept(t0);if(
 r0=="N")t0.OnCompleted();return u0;};};h0.prototype=new D;var i0=b.Subject=function(){var r0=new q();var s0=false;this.OnNext=function(t0){if(!s0){var u0=r0.ToArray();for(var v0=0;v0<u0.length;v0++){var w0=u0[v0];w0.OnNext(t0);}}};this.OnError=function(t0){if(!s0){var u0=r0.ToArray();for(var v0=0;v0<u0.length;v0++){var w0=u0[v0];w0.OnError(t0);}s0=true;r0.Clear();}};this.OnCompleted=function(){if(!s0){var t0=r0.ToArray();for(var u0=0;u0<t0.length;u0++){var v0=t0[u0];v0.OnCompleted();}s0=true;r0.Clear();}};this.w=function(t0){if(!s0){r0.Add(t0);return i(function(){r0.Remove(t0);});}else return j;};};i0.prototype=new D;for(var j0 in B.prototype) i0.prototype[j0]=B.prototype[j0];var k0=b.AsyncSubject=function(r0){var s0=new q();var t0;var u0=false;if(r0===a)r0=z;this.OnNext=function(v0){if(!u0)t0=new h0("N",v0);};this.OnError=function(v0){if(!u0){t0=new h0("E",v0);var w0=s0.ToArray();for(var x0=0;x0<w0.length;x0++){var y0=w0[x0];if(y0!==a)y0.OnError(v0);}u0=true;s0.Clear();}};this.OnCo
 mpleted=function(){if(!u0){if(t0===a)t0=new h0("C");var v0=s0.ToArray();for(var w0=0;w0<v0.length;w0++){var x0=v0[w0];if(x0!==a)t0.w(x0);}u0=true;s0.Clear();}};this.w=function(v0){if(!u0){s0.Add(v0);return i(function(){s0.Remove(v0);});}else return r0.Schedule(function(){t0.w(v0);});};};k0.prototype=new i0;var l0=b.BehaviorSubject=function(r0,s0){var t0=new m0(1,-1,s0);t0.OnNext(r0);return t0;};var m0=b.ReplaySubject=function(r0,s0,t0){var u0=new q();var v0=new q();var w0=false;if(t0===a)t0=v;var x0=s0>0;var y0=function(z0,A0){v0.Add({Value:new h0(z0,A0),Timestamp:t0.Now()});};this.A=function(){if(r0!==a)while(v0.GetCount()>r0)v0.RemoveAt(0);if(x0)while(v0.GetCount()>0&&t0.Now()-v0.GetItem(0).Timestamp>s0)v0.RemoveAt(0);};this.OnNext=function(z0){if(!w0){var A0=u0.ToArray();for(var B0=0;B0<A0.length;B0++){var C0=A0[B0];C0.OnNext(z0);}y0("N",z0);}};this.OnError=function(z0){if(!w0){var A0=u0.ToArray();for(var B0=0;B0<A0.length;B0++){var C0=A0[B0];C0.OnError(z0);}w0=true;u0.Clear();y0
 ("E",z0);}};this.OnCompleted=function(){if(!w0){var z0=u0.ToArray();for(var A0=0;A0<z0.length;A0++){var B0=z0[A0];B0.OnCompleted();}w0=true;u0.Clear();y0("C");}};this.w=function(z0){var A0=new n0(this,z0);var B0=new n(A0);var C0=this;B0.Add(t0.Schedule(function(){if(!A0.B){C0.A();for(var D0=0;D0<v0.GetCount();D0++) v0.GetItem(D0).Value.Accept(z0);u0.Add(z0);A0.C=true;}}));return B0;};this.D=function(z0){u0.Remove(z0);};};m0.prototype=new i0;var n0=function(r0,s0){this.E=r0;this.F=s0;this.C=false;this.B=false;this.Dispose=function(){if(this.C)this.E.D(this.F);this.B=true;};};var o0=D.ToAsync=function(r0,s0){if(s0===a)s0=A;return function(){var t0=new k0(s0);var u0=function(){var x0;try{x0=r0.apply(this,arguments);}catch(y0){t0.OnError(y0);return;}t0.OnNext(x0);t0.OnCompleted();};var v0=this;var w0=p(arguments);s0.Schedule(function(){u0.apply(v0,w0);});return t0;};};var p0=D.Start=function(r0,s0,t0,u0){if(t0===a)t0=[];return o0(r0,u0).apply(s0,t0);};var q0=b.ConnectableObservable=func
 tion(r0,s0){if(s0===a)s0=new i0();this.E=s0;this.G=r0;this.H=false;this.Connect=function(){var t0;var u0=false;if(!this.H){this.H=true;var v0=this;t0=new n(i(function(){v0.H=false;}));this.I=t0;t0.Add(r0.Subscribe(this.E));}return this.I;};this.w=function(t0){return this.E.Subscribe(t0);};this.RefCount=function(){var t0=0;var u0=this;var v0;return F(function(w0){var x0=false;t0++;x0=t0==1;var y0=u0.Subscribe(w0);if(x0)v0=u0.Connect();return function(){y0.Dispose();t0--;if(t0==0)v0.Dispose();};});};};q0.prototype=new D;})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/datajs-cache-large-collection-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/datajs-cache-large-collection-functional-tests.html b/odatajs/tests/datajs-cache-large-collection-functional-tests.html
new file mode 100644
index 0000000..475deff
--- /dev/null
+++ b/odatajs/tests/datajs-cache-large-collection-functional-tests.html
@@ -0,0 +1,53 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<html>
+<head>
+    <title>datajs.cache and datajs.store full local store tests</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
+    <!--<script type="text/javascript" src="common/common.js"></script>-->
+
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/djstest-browser.js"></script>
+    <script type="text/javascript" src="common/CacheOracle.js"></script>
+    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    
+    <script type="text/javascript" src="datajs-cache-large-collection-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache and datajs.store full local store 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/d5ec5557/odatajs/tests/datajs-cache-large-collection-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/datajs-cache-large-collection-functional-tests.js b/odatajs/tests/datajs-cache-large-collection-functional-tests.js
new file mode 100644
index 0000000..557510e
--- /dev/null
+++ b/odatajs/tests/datajs-cache-large-collection-functional-tests.js
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    window.odatajs.oData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var largeCollectionFeed = "./endpoints/LargeCollectionService.svc/Customers";
+    var itemsInCollection = 2 * 1024 * 1024;
+
+    var cleanDomStorage = function (done) {
+        /* Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
+         *  setup and teardown methods to be consistent with indexedDb's cleanup method.
+         * @param {Function} done - Function to be called after DOM storage is cleared.
+         */
+        if (window.localStorage) {
+            window.localStorage.clear();
+        }
+        done();
+    };
+
+    var cleanIndexedDb = function (done) {
+        /** Cleans all the data saved in the browser's IndexedDb Storage.
+         * @param {Function} done - Function to be called after DOM storage is cleared.
+         */
+        var caches = this.caches;
+
+        djstest.cleanStoreOnIndexedDb(caches, done);
+    };
+
+    var makeUnexpectedErrorHandler = function () {
+        return function (err) {
+            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        };
+    };
+
+    var storageMechanisms = {
+        indexeddb: { cleanup: cleanIndexedDb },
+        dom: { cleanup: cleanDomStorage }
+    };
+
+    var cleanupAllStorage = function(done) {
+        /** Cleans up all available storage mechanisms in the browser.
+         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
+         */
+        var that = this;
+        var storeCleanup = [];
+
+        $.each(CacheOracle.mechanisms, function(_, mechanism) {
+            if (CacheOracle.isMechanismAvailable(mechanism)) {
+                storeCleanup.push(function(done) {
+                    if (storageMechanisms[mechanism]) {
+                        storageMechanisms[mechanism].cleanup.call(that, done);
+                    } else {
+                        done();
+                    }
+                });
+            }
+        });
+
+        djstest.asyncDo(storeCleanup, done);
+    };
+
+
+    module("Functional", {
+        setup: function () {
+            this.observableHttpClient = new ObservableHttpClient();
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
+            this.caches = [];
+            var that = this;
+
+            djstest.wait(function (done) {
+                cleanupAllStorage.call(that, done);
+            });
+        },
+
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
+            var clearActions = [];
+            var that = this;
+
+            $.each(this.caches, function (_, cacheObject) {
+                cacheObject.cache.onidle = undefined;
+
+                clearActions.push(function (done) {
+                    cacheObject.cache.clear().then(function () {
+                        done();
+                    },
+                        function (err) {
+                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
+                        });
+                });
+            });
+
+            djstest.wait(function (done) {
+                djstest.asyncDo(clearActions, function () {
+                    cleanupAllStorage.call(that, function () {
+                        that.caches = [];
+                        done();
+                    });
+                });
+            });
+        }
+    });
+
+    $.each(["dom", "indexeddb"], function (_, mechanism) {
+        if (CacheOracle.isMechanismAvailable(mechanism)) {
+            $.each([-1, 10 * 1024 * 1024, 1024 * 10248], function (_, cacheSize) {
+                var prefetchParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 5, pageSize: 1024, prefetchSize: -1, cacheSize: cacheSize };
+                djstest.addTest(function (params) {
+
+                    djstest.assertsExpected(3);
+                    var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+                        mechanism: params.mechanism, cacheSize: params.cacheSize
+                    };
+
+                    var cache = odatajs.cache.createDataCache(options);
+                    this.caches.push({ name: options.name,
+                        cache: cache
+                    });
+
+                    cache.onidle = function () {
+                        djstest.assert(true, "onidle Called");
+                        djstest.done();
+                    };
+
+                    var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+                    var session = this.observableHttpClient.newSession();
+
+                    cache.readRange(params.skip, params.take).then(function (data) {
+                        var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+                        cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests with prefetch", false, true);
+                        window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                        });
+                    }, function (err) {
+                        makeUnexpectedErrorHandler(err)();
+                    });
+                }, "readRange and prefetch all to fill store on " + prefetchParameters.mechanism + " with cacheSize=" + prefetchParameters.cacheSize, prefetchParameters, 600000);
+
+                $.each([500, 1024 * 10 /*Test reduced from 100 to 10 to work around slow running script error in IE8 and Safari (bug 2200)*/], function (_, pageSize) {
+                    var largeReadParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 1024, pageSize: pageSize, prefetchSize: 0, cacheSize: cacheSize };
+                    djstest.addTest(function (params) {
+
+                        djstest.assertsExpected(2);
+                        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+                            mechanism: params.mechanism, cacheSize: params.cacheSize
+                        };
+
+                        var cache = odatajs.cache.createDataCache(options);
+                        this.caches.push({ name: options.name, cache: cache });
+
+                        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+                        var session = this.observableHttpClient.newSession();
+
+                        cache.readRange(params.skip, params.take).then(function (data) {
+                            var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+                            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests without prefetch", false, false);
+                            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                                djstest.done();
+                            });
+                        }, function (err) {
+                            makeUnexpectedErrorHandler(err)();
+                            djstest.done();
+                        });
+                    }, "readRange of skip=" + largeReadParameters.skip + " take=" + largeReadParameters.take + " cacheSize=" + largeReadParameters.cacheSize + " and pageSize=" + largeReadParameters.pageSize +
+                        " to fill store on " + largeReadParameters.mechanism, largeReadParameters, 600000);
+                });
+            });
+        }
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/datajs-cache-long-haul-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/datajs-cache-long-haul-tests.html b/odatajs/tests/datajs-cache-long-haul-tests.html
new file mode 100644
index 0000000..3e02e32
--- /dev/null
+++ b/odatajs/tests/datajs-cache-long-haul-tests.html
@@ -0,0 +1,194 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData Long Haul Tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/Instrument.js"></script>
+    <script type="text/javascript">
+        var cache;
+        var clearBetweenReads;
+        var currentRunTimeMS;
+        var failureCount;
+        var hourMS = 60 * 60 * 1000;
+        var goalRunTimeMS = hourMS;
+        var isTotalIncreaseHigh;
+        var itemsInCollection = 16;
+        var iterationsRun;
+        var memoryDelta = 5000000;
+        var getBrowserMemorySize;
+        var startMemorySize;
+        var startTimeMs = 0;
+        var testFeed = "http://odata.netflix.com/Catalog/Titles";
+
+        var makeUnexpectedErrorHandler = function () {
+            return function (err) {
+                failureCount++;
+                if (failureCount < 50) {
+                    $("#errors").append("<p>Iteration: " + iterationsRun + " Error reading cache: " + err.message + "<p>");
+                }
+            };
+        };
+
+        var checkMemoryIncrease = function (memorySizeBefore) {
+            getBrowserMemorySize(function (memorySizeAfter) {
+                var incrementalIncreaseInMemory = memorySizeAfter - memorySizeBefore;
+                var totalIncreaseInMemory = memorySizeAfter - startMemorySize;
+                if (incrementalIncreaseInMemory > memoryDelta) {
+                    failureCount++;
+                    if (failureCount < 50) {
+                        $("#errors").append("<p>Iteration: " + iterationsRun + " Memory usage increase in read: " + incrementalIncreaseInMemory + "<p>");
+                    }
+                }
+
+                if (totalIncreaseInMemory > memoryDelta && !isTotalIncreaseHigh) {
+                    isTotalIncreaseHigh = true;
+                    failureCount++;
+                    if (failureCount < 50) {
+                        $("#errors").append("<p>Iteration: " + iterationsRun + " Total memory usage increase over duration: " + totalIncreaseInMemory + "<p>");
+                    }
+                }
+
+                iterationsRun++;
+                nextIteration();
+            });
+        };
+
+        var readRangePrefetchTest = function () {
+            var readPage = 6;
+
+            getBrowserMemorySize(function (memorySizeBefore) {
+                callReadRangeRepeatedly(0, readPage, function () { checkMemoryIncrease(memorySizeBefore) });
+            });
+        };
+
+        var callReadRangeRepeatedly = function (index, count, done) {
+            /** Calls readRange over the whole collection and done when all items have been read.
+             * @param {Integer} index - Index to start the read.
+             * @param {String} count - The count of each readRange.
+             * @param {Function} done - Function to be called when all items in collection have been read.
+            var cacheRead = function () {
+                cache.readRange(index, count).then(function () {
+                    if (index < itemsInCollection) {
+                        index += count;
+                        callReadRangeRepeatedly(index, count, done);
+                    }
+                    else {
+                        done();
+                    }
+                }, makeUnexpectedErrorHandler(cache));
+            };
+
+            if (clearBetweenReads) {
+                cache.clear().then(cacheRead(), makeUnexpectedErrorHandler(cache));
+            }
+            else {
+                cacheRead(); 
+            }
+        }
+
+        function startTest() {
+            var prefetchSize =
+                $('input[name=PrefetchEnabled]').attr('checked') ? -1 : 0;
+            clearBetweenReads = $('input[name=ClearBetweenReads]').attr('checked');
+            var inputHours = parseFloat($('#time').val());
+
+            if (inputHours !== undefined && typeof inputHours === "number" && !isNaN(inputHours) && isFinite(inputHours) && inputHours > 0) {
+                goalRunTimeMS = hourMS * inputHours;
+            }
+            OData.defaultHttpClient.enableJsonpCallback = true;
+            cache = datajs.cache.createDataCache({ name: "cache" + new Date().valueOf(), source: testFeed, pageSize: 5, prefetchSize: prefetchSize });
+            failureCount = 0;
+            iterationsRun = 0;
+            currentRunTimeMS = 0;
+            isTotalIncreaseHigh = false;
+            $("#errors").empty();
+            getBrowserMemorySize = Instrument.getBrowserMemorySize;
+            getBrowserMemorySize(function (memorySizeStart) {
+                startMemorySize = memorySizeStart;
+                $("#starting-memory").text("Starting memory size: " + startMemorySize);
+            });
+            startTimeMs = new Date().getTime();
+
+            nextIteration();
+        }
+
+        function nextIteration() {
+            currentRunTimeMS = new Date().getTime() - startTimeMs;
+            if (currentRunTimeMS > goalRunTimeMS) {
+                getBrowserMemorySize(function (memorySizeAfter) {
+                    $("#stress-status").text("Tests complete. Iterations: " + iterationsRun + " Failures: " + failureCount +
+                    " Start memory: " + startMemorySize + " End memory: " + memorySizeAfter);
+                });
+
+                cache.clear();
+                return;
+            }
+
+            if (iterationsRun % 100 === 0) {
+                getBrowserMemorySize(function (memorySizeAfter) {
+                    var text = "Running tests (iterationsRun=" + iterationsRun;
+                    text += ", Time run: " + currentRunTimeMS + "ms";
+                    text += ", Remaining time: " + (goalRunTimeMS - currentRunTimeMS) + "ms";
+                    text += "). Failures: " + failureCount;
+                    text += " Current memory size: " + memorySizeAfter;
+                    $("#stress-status").text(text);
+                });
+            }
+
+            readRangePrefetchTest();
+        }
+
+        $(document).ready(function () {
+            $("#start-button").click(startTest);
+        });
+    </script>
+</head>
+<body>
+    <h1>
+        OData Long Haul</h1>
+    <p>
+        Repeatedly runs an action and checks the memory usage.
+    </p>
+    <p>
+        <input name="time" id="time" type="text" />Length of time to run test</p>
+    <p>
+        <input type="checkbox" name="PrefetchEnabled" value="false" />Prefetch Enabled</p>
+    <p>
+        <input type="checkbox" name="ClearBetweenReads" value="false" />Clear Between Reads</p>
+    <button id='start-button'>
+        Start</button>
+    <p id='errors'>
+    </p>
+    <p id='stress-status'>
+    </p>
+    <p id='starting-memory'>
+    </p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/datajs-startup-perf-test.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/datajs-startup-perf-test.html b/odatajs/tests/datajs-startup-perf-test.html
new file mode 100644
index 0000000..f69684a
--- /dev/null
+++ b/odatajs/tests/datajs-startup-perf-test.html
@@ -0,0 +1,109 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!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" />
+    <title>datajs startup perf test</title>
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/Instrument.js"></script>
+
+    <script type="text/javascript">
+        $(window).load(function () {
+            djstest.addTest(function startupTimeAndMemory() {
+                var durationLimit = 500;
+                var memorySizeDeltaLimit = 5000000;
+
+                var filename = "../build/odatajs-4.0.0-beta-01.js";
+                var getBrowserMemorySize = Instrument.getBrowserMemorySize;
+
+                $.ajax({
+                    url: "../src/" + filename,
+                    dataType: "text",
+                    success: function (script) {
+                        getBrowserMemorySize(function (memorySizeBefore) {
+                            var duration = new Date();
+                            eval(script);
+                            duration = new Date() - duration;
+                            getBrowserMemorySize(function (memorySizeAfter) {
+                                var memorySizeDelta = memorySizeAfter - memorySizeBefore;
+                                djstest.assert(duration < durationLimit, duration + " ms (limit " + durationLimit + " ms)");
+                                djstest.assert(memorySizeDelta < memorySizeDeltaLimit,
+                                    memorySizeDelta + " bytes (limit " + memorySizeDeltaLimit + " bytes, initial " + memorySizeBefore + " bytes)");
+
+                                djstest.done();
+                            });
+                        });
+                    },
+                    error: function () {
+                        // See if we are running the dev build
+                        $.ajax({
+                            url: "../src/odata.js",
+                            dataType: "text",
+                            success: function () {
+                                djstest.pass("Running on dev build, no measurement taken");
+                                djstest.done();
+                            },
+                            error: function (jqXHR, textStatus, errorThrown) {
+                                djstest.fail("Request failed: " + jqXHR.responseText);
+                                djstest.done();
+                            }
+                        });
+                    }
+                });
+            });
+        });
+    </script>
+</head>
+<body>
+    <h1 id="qunit-header">datajs startup perf test</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/d5ec5557/odatajs/tests/e2etest/Test.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/e2etest/Test.html b/odatajs/tests/e2etest/Test.html
new file mode 100644
index 0000000..265c1da
--- /dev/null
+++ b/odatajs/tests/e2etest/Test.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>odatajs side-by-side test (V3 & V4)</title>
+    <script type="text/javascript" src="../../demo/scripts/datajs-1.1.2.js"></script>
+    <script type="text/javascript" src="../../build/datajs-2.0.0.js"></script>
+</head>
+<body>
+    <h3>
+        Test V3 and V4 running side by side...</h3>
+    <div id="msg">
+    </div>
+    <script type="text/javascript">
+
+        var headers = { "Content-Type": "application/json", Accept: "application/json" };
+        var request = {
+            requestUri: "../endpoints/FoodStoreDataServiceV4.svc/Foods",
+            method: "GET",
+            headers: headers,
+            data: null
+        };
+
+        OData.request(request, function (data, response) {
+            document.getElementById('msg').innerHTML += ("<div>datajs V3 testing failed.</div>");
+        }, function (err) {
+            if ((err.response.statusCode == '200') && (err.response.body.indexOf('}', err.response.body.length - 1) == err.response.body.length - 1) && err.response.headers['Content-Type'] == "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8") {
+                document.getElementById('msg').innerHTML += ("<div>datajs V3 testing pass!</div>");
+            } else {
+                document.getElementById('msg').innerHTML += ("<div>datajs V3 testing failed.</div>");
+            }
+        });
+
+        odatajs.oData.request(request, function (data, response) {
+            if ((response.statusCode == '200') && (response.body.indexOf('}', response.body.length - 1) == response.body.length - 1) && response.headers['Content-Type'] == "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8") {
+                document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing pass!</div>");
+            } else {
+                document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing failed.</div>");
+            }
+        }, function (err) {
+            document.getElementById('msg').innerHTML += ("<div>odatajs V4 testing failed.</div>");
+        });
+    </script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/BasicAuthDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/BasicAuthDataService.svc b/odatajs/tests/endpoints/BasicAuthDataService.svc
new file mode 100644
index 0000000..e059314
--- /dev/null
+++ b/odatajs/tests/endpoints/BasicAuthDataService.svc
@@ -0,0 +1,124 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.BasicAuthDataService" %>
+/*
+ * 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.
+ */
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Web;
+    using System.Text;
+    using System.Web;
+
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class BasicAuthDataService : DataService<BasicAuthDataSource>
+    {
+        const string Username = "djsUser";
+        const string Password = "djsPassword";
+        
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+        }
+
+        public BasicAuthDataService()
+            : base()
+        {
+            this.ProcessingPipeline.ProcessingRequest += OnRequest;
+        }
+
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+
+        private static void UnauthorizedRequest(DataServiceOperationContext context)
+        {
+            context.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"DataJS.Tests\"";
+            throw new DataServiceException(401, "401 Unauthorized");
+        }
+
+        private void OnRequest(object sender, DataServiceProcessingPipelineEventArgs e)
+        {
+            string authHeader = e.OperationContext.RequestHeaders["Authorization"];
+            
+            // Validate the Authorization header
+            if (authHeader == null || !authHeader.StartsWith("Basic"))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+
+            // Decode the username and password from the header
+            string base64Credentials = authHeader.Substring(6);
+            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(':');
+            if (credentials.Length != 2 || !(credentials[0].Equals(Username) && credentials[1].Equals(Password)))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+        }
+    }
+
+    public class BasicAuthDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Customer> Customers
+        {
+            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+            foreach (int i in Enumerable.Range(1, 16))
+            {
+                customers.Add(new Customer()
+                {
+                    ID = i,
+                    Name = "Customer " + i
+                });
+            }
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Customer
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/CustomAnnotations.xml
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/CustomAnnotations.xml b/odatajs/tests/endpoints/CustomAnnotations.xml
new file mode 100644
index 0000000..ebf4e26
--- /dev/null
+++ b/odatajs/tests/endpoints/CustomAnnotations.xml
@@ -0,0 +1,121 @@
+<!--/*
+ * 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.
+*/
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
+  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
+    <Schema xmlns="http://schemas.microsoft.com/ado/2007/05/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:mcns="http://MyCustomNamespace.com"
+             Namespace="DataJS.Tests">
+      <EntityType Name="MappedEntry" mcns:MyCustomAnnotation="My custom attribute.">
+        <Key mcns:MyCustomAnnotation="//">
+          <PropertyRef Name="ID" mcns:MyCustomAnnotation="  "/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author" m:FC_KeepInContent_5="false" m:FC_SourcePath_5="Contributor/Name" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorName" m:FC_KeepInContent_4="false" m:FC_SourcePath_4="Contributor/Email" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorEmail" m:FC_KeepInContent_3="false" m:FC_SourcePath_3="Uri" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationAuthorUri" m:FC_KeepInContent_2="false" m:FC_SourcePath_2="Name" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorName" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Email" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorEmail" m:FC_KeepInContent="false" m:FC_SourcePath="Contributor/Uri" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationContributorUri"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished"/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="false" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author" mcns:MyCustomAnnotation="">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=""/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor"/>
+      </ComplexType>
+      <ComplexType Name="Contributor">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=" "/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="true"/>
+      </ComplexType>
+      <ComplexType Name="Location">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single" mcns:MyCustomAnnotation="27"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="ReplicatedEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author2" m:FC_KeepInContent_5="true" m:FC_SourcePath_5="Contributor/Uri" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorUri" m:FC_KeepInContent_4="true" m:FC_SourcePath_4="Contributor/Name" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorName" m:FC_KeepInContent_3="true" m:FC_SourcePath_3="Contributor/Email" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationContributorEmail" m:FC_KeepInContent_2="true" m:FC_SourcePath_2="Uri" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorUri" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Name" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorName" m:FC_KeepInContent="true" m:FC_SourcePath="Email" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationAuthorEmail" mcns:MyCustomAnnotation="b>100/b>"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished" mcns:MyCustomAnnotation=" . "/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary" mcns:MyCustomAnnotation="/Property"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location2" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="true" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor2"/>
+      </ComplexType>
+      <ComplexType Name="Contributor2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+      </ComplexType>
+      <ComplexType Name="Location2">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="DerivedEntry" m:FC_KeepInContent="false" m:FC_SourcePath="MappedInDerivedField" m:FC_TargetPath="mappedField/@mappedInDerived" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy" BaseType="DataJS.Tests.BaseEntry">
+        <Property Name="UnmappedConcreteField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedConcreteField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField/@mappedConcrete" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityType Name="BaseEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedInDerivedField" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="false"/>
+        <Property Name="MappedField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityContainer Name="EpmDataSource" m:IsDefaultEntityContainer="true" mcns:MyCustomAnnotation="0">
+        <EntitySet Name="MappedEntries" EntityType="DataJS.Tests.MappedEntry"/>
+        <EntitySet Name="ReplicatedEntries" EntityType="DataJS.Tests.ReplicatedEntry"/>
+        <EntitySet Name="HierarchicalEntries" EntityType="DataJS.Tests.BaseEntry"/>
+        <FunctionImport Name="ResetData" m:HttpMethod="POST" mcns:MyCustomAnnotation="null"/>
+      </EntityContainer>
+      <mcns:EmptyElement></mcns:EmptyElement>
+      <mcns:ParentCustomElement mcns:MyCustomAnnotation="annotation" mcns:MySecondCustomAnnotation="annotation 2">
+        <mcns:CustomChildElement1>Custom metadata 1.</mcns:CustomChildElement1>
+        <mcns:CustomChildElement2>Custom metadata 2.</mcns:CustomChildElement2>
+      </mcns:ParentCustomElement>
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/CustomDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/CustomDataService.svc b/odatajs/tests/endpoints/CustomDataService.svc
new file mode 100644
index 0000000..67fcfd0
--- /dev/null
+++ b/odatajs/tests/endpoints/CustomDataService.svc
@@ -0,0 +1,85 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory"
+    Service="DataJS.Tests.CustomDataService" %>
+
+
+using System.Collections;
+using System.IO;
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// Custom data service that does not use OData
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class CustomDataService
+    {
+        static readonly Item[] data = Enumerable.Range(0, 16).Select(i => new Item
+        {
+            ID = i,
+            Name = "Item " + i
+        }).ToArray();
+
+        // This uses the same URI template as OData so that the CacheOracle can be reused
+        [OperationContract]
+        [WebGet(UriTemplate = "ReadRange?$skip={skip}&$top={top}")]
+        public Stream ReadRange(int skip, int top)
+        {
+            IEnumerable selectData = data.Skip(skip).Take(top);
+            Dictionary<string, object> result = new Dictionary<string, object>();
+            List<Dictionary<string, string>> value = new List<Dictionary<string, string>>(); 
+            foreach (Item d in selectData)
+            {
+                Dictionary<string, string> item = new Dictionary<string, string>();
+                item.Add("ID", d.ID.ToString());
+                item.Add("Name", d.Name);
+                value.Add(item);
+            }
+            
+            result.Add("value", value);
+            return ReaderUtils.ConvertDictionarytoJsonlightStream(result);
+        }
+
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public int Count()
+        {
+            return data.Count();
+        }
+    }
+
+    public class Item
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file


[43/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/json.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/json.js b/datajs/src/lib/odata/json.js
deleted file mode 100644
index 224e881..0000000
--- a/datajs/src/lib/odata/json.js
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module odata/json */
-
-
-
-var utils        = require('./../datajs.js').utils;
-var oDataUtils   = require('./utils.js');
-var oDataHandler = require('./handler.js');
-
-var odataNs = "odata";
-var odataAnnotationPrefix = odataNs + ".";
-var contextUrlAnnotation = "@" + odataAnnotationPrefix + "context";
-
-var assigned = utils.assigned;
-var defined = utils.defined;
-var isArray = utils.isArray;
-//var isDate = utils.isDate;
-var isObject = utils.isObject;
-//var normalizeURI = utils.normalizeURI;
-var parseInt10 = utils.parseInt10;
-var getFormatKind = utils.getFormatKind;
-
-var formatDateTimeOffset = oDataUtils.formatDateTimeOffset;
-var formatDuration = oDataUtils.formatDuration;
-var formatNumberWidth = oDataUtils.formatNumberWidth;
-var getCanonicalTimezone = oDataUtils.getCanonicalTimezone;
-var handler = oDataUtils.handler;
-var isComplex = oDataUtils.isComplex;
-var isPrimitive = oDataUtils.isPrimitive;
-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 XXXparseDateTime = oDataUtils.XXXparseDateTime;
-
-var isPrimitiveEdmType = oDataUtils.isPrimitiveEdmType;
-var isGeographyEdmType = oDataUtils.isGeographyEdmType;
-var isGeometryEdmType = oDataUtils.isGeometryEdmType;
-
-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);
-
-
-// The regular expression corresponds to something like this:
-// /Date(123+60)/
-//
-// This first number is date ticks, the + may be a - and is optional,
-// with the second number indicating a timezone offset in minutes.
-//
-// On the wire, the leading and trailing forward slashes are
-// escaped without being required to so the chance of collisions is reduced;
-// however, by the time we see the objects, the characters already
-// look like regular forward slashes.
-var jsonDateRE = /^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/;
-
-/** Formats the given minutes into (+/-)hh:mm format.
- * @param {Number} minutes - Number of minutes to format.
- * @returns {String} The minutes in (+/-)hh:mm format.
- */
-function minutesToOffset(minutes) {
-
-    var sign;
-    if (minutes < 0) {
-        sign = "-";
-        minutes = -minutes;
-    } else {
-        sign = "+";
-    }
-
-    var hours = Math.floor(minutes / 60);
-    minutes = minutes - (60 * hours);
-
-    return sign + formatNumberWidth(hours, 2) + ":" + formatNumberWidth(minutes, 2);
-}
-
-/** Parses the JSON Date representation into a Date object.
- * @param {String} value - String value.
- * @returns {Date} A Date object if the value matches one; falsy otherwise.
- */
-function parseJsonDateString(value) {
-
-    var arr = value && jsonDateRE.exec(value);
-    if (arr) {
-        // 0 - complete results; 1 - ticks; 2 - sign; 3 - minutes
-        var result = new Date(parseInt10(arr[1]));
-        if (arr[2]) {
-            var mins = parseInt10(arr[3]);
-            if (arr[2] === "-") {
-                mins = -mins;
-            }
-
-            // The offset is reversed to get back the UTC date, which is
-            // what the API will eventually have.
-            var current = result.getUTCMinutes();
-            result.setUTCMinutes(current - mins);
-            result.__edmType = "Edm.DateTimeOffset";
-            result.__offset = minutesToOffset(mins);
-        }
-        if (!isNaN(result.valueOf())) {
-            return result;
-        }
-    }
-
-    // Allow undefined to be returned.
-}
-
-// Some JSON implementations cannot produce the character sequence \/
-// which is needed to format DateTime and DateTimeOffset into the
-// JSON string representation defined by the OData protocol.
-// See the history of this file for a candidate implementation of
-// a 'formatJsonDateString' function.
-
-/** Parses a JSON OData payload.
- * @param handler - This handler.
- * @param text - Payload text (this parser also handles pre-parsed objects).
- * @param {Object} context - Object with parsing context.
- * @return An object representation of the OData payload.</returns>
- */
-function jsonParser(handler, text, context) {
-
-    var recognizeDates = defined(context.recognizeDates, handler.recognizeDates);
-    var model = context.metadata;
-    var json = (typeof text === "string") ? JSON.parse(text) : text;
-    var metadataContentType;
-    if (assigned(context.contentType) && assigned(context.contentType.properties)) {
-        metadataContentType = context.contentType.properties["odata.metadata"]; //TODO convert to lower before comparism
-    }
-
-    var payloadFormat = getFormatKind(metadataContentType, 1); // none: 0, minimal: 1, full: 2
-
-    // No errors should be throw out if we could not parse the json payload, instead we should just return the original json object.
-    if (payloadFormat === 0) {
-        return json;
-    }
-    else if (payloadFormat === 1) {
-        return readPayloadMinimal(json, model, recognizeDates);
-    }
-    else if (payloadFormat === 2) {
-        // to do: using the EDM Model to get the type of each property instead of just guessing.
-        return readPayloadFull(json, model, recognizeDates);
-    }
-    else {
-        return json;
-    }
-}
-
-
-function addType(data, name, value ) {
-    var fullName = name + '@odata.type';
-
-    if ( data[fullName] === undefined) {
-        data[fullName] = value;
-    }
-}
-
-function addTypeNoEdm(data, name, value ) {
-    var fullName = name + '@odata.type';
-
-    if ( data[fullName] === undefined) {
-        if ( value.substring(0,4)==='Edm.') {
-            data[fullName] = value.substring(4);
-        } else {
-            data[fullName] = value;
-        }
-
-    }
-}
-
-function addTypeColNoEdm(data, name, value ) {
-    var fullName = name + '@odata.type';
-
-    if ( data[fullName] === undefined) {
-        if ( value.substring(0,4)==='Edm.') {
-            data[fullName] = 'Collection('+value.substring(4)+ ')';
-        } else {
-            data[fullName] = 'Collection('+value+ ')';
-        }
-    }
-}
-
-
-/* Adds typeinformation for String, Boolean and numerical EDM-types. 
- * The type is determined from the odata-json-format-v4.0.doc specification
- * @param data - Date which will be extendet
- * @param {Boolean} recognizeDates - True if strings formatted as datetime values should be treated as datetime values. False otherwise.
- * @returns An object representation of the OData payload.
- */
-function readPayloadFull(data, model, recognizeDates) {
-    var type;
-    if (utils.isObject(data)) {
-        for (var key in data) {
-            if (data.hasOwnProperty(key)) {
-                if (key.indexOf('@') === -1) {
-                    if (utils.isArray(data[key])) {
-                        for (var i = 0; i < data[key].length; ++i) {
-                            readPayloadFull(data[key][i], model, recognizeDates);
-                        }
-                    } else if (utils.isObject(data[key])) {
-                        if (data[key] !== null) {
-                            //don't step into geo.. objects
-                            var isGeo = false;
-                            type = data[key+'@odata.type'];
-                            if (type && (isGeographyEdmType(type) || isGeometryEdmType(type))) {
-                                // is gemometry type
-                            } else {
-                                readPayloadFull(data[key], model, recognizeDates);
-                            }
-                        }
-                    } else {
-                        type = data[key + '@odata.type'];
-
-                        // On .Net OData library, some basic EDM type is omitted, e.g. Edm.String, Edm.Int, and etc.
-                        // For the full metadata payload, we need to full fill the @data.type for each property if it is missing. 
-                        // We do this is to help the OlingoJS consumers to easily get the type of each property.
-                        if (!assigned(type)) {
-                            // Guessing the "type" from the type of the value is not the right way here. 
-                            // To do: we need to get the type from metadata instead of guessing. 
-                            var typeFromObject = typeof data[key];
-                            if (typeFromObject === 'string') {
-                                addType(data, key, '#String');
-                            } else if (typeFromObject === 'boolean') {
-                                addType(data, key, '#Boolean');
-                            } else if (typeFromObject === 'number') {
-                                if (data[key] % 1 === 0) { // has fraction 
-                                    addType(data, key, '#Int32'); // the biggst integer
-                                } else {
-                                    addType(data, key, '#Decimal'); // the biggst float single,doulbe,decimal
-                                }
-                            }
-                        }
-                        else {
-                            if (recognizeDates) {
-                                convertDatesNoEdm(data, key, type.substring(1));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    return data;
-}
-
-/** Serializes the data by returning its string representation.
- * @param handler - This handler.
- * @param data - Data to serialize.
- * @param {Object} context - Object with serialization context.
- * @returns {String} The string representation of data.
- */
-function jsonSerializer(handler, data, context) {
-
-    var dataServiceVersion = context.dataServiceVersion || "4.0";
-    var cType = context.contentType = context.contentType || jsonContentType;
-
-    if (cType && cType.mediaType === jsonContentType.mediaType) {
-        context.dataServiceVersion = maxVersion(dataServiceVersion, "4.0");
-        var newdata = formatJsonRequestPayload(data);
-        if (newdata) {
-            return JSON.stringify(newdata);
-        }
-    }
-
-    return undefined;
-}
-
-function formatJsonRequestPayload(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] = formatJsonRequestPayload(data[i]);
-        }
-
-        return newArrayData;
-    }
-
-    var newdata = {};
-    for (var property in data) {
-        if (isJsonSerializableProperty(property)) {
-            newdata[property] = formatJsonRequestPayload(data[property]);
-        }
-    }
-
-    return newdata;
-}
-
-/** JSON replacer function for converting a value to its JSON representation.
- * @param {Object} value - Value to convert.</param>
- * @returns {String} JSON representation of the input value.
- * This method is used during JSON serialization and invoked only by the JSON.stringify function.
- * It should never be called directly.
- */
-function jsonReplacer(_, value) {
-    
-
-    if (value && value.__edmType === "Edm.Time") {
-        return formatDuration(value);
-    } else {
-        return value;
-    }
-}
-
-
-/** Creates an object containing information for the json payload.
- * @param {String} kind - JSON payload kind, one of the PAYLOADTYPE_XXX constant values.
- * @param {String} typeName - Type name of the JSON payload.
- * @returns {Object} Object with kind and type fields.
- */
-function jsonMakePayloadInfo(kind, type) {
-
-    /// TODO docu
-    /// <field name="kind" type="String">Kind of the JSON payload. One of the PAYLOADTYPE_XXX constant values.</field>
-    /// <field name="type" type="String">Data type of the JSON payload.</field>
-
-    return { kind: kind, type: type || null };
-}
-
-/** Creates an object containing information for the context
- * TODO check dou layout
- * @returns {Object} Object with type information
- * @returns {Object.detectedPayloadKind(optional)}  see constants starting with PAYLOADTYPE_
- * @returns {Object.deltaKind(optional)}  deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
- * @returns {Object.typeName(optional)}  name of the type
- * @returns {Object.type(optional)}  object containing type information for entity- and complex-types ( null if a typeName is a primitive)
-*/
-function parseContextUriFragment( 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("/");
-    var type;
-    
-    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;
-
-                    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;
-                }
-            }
-
-
-            if (jsonIsPrimitiveType(fragment)) {
-                ret.typeName = fragment;
-                ret.type = null;
-                ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
-                continue;
-            }
-
-            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;
-            }
-
-            
-
-            //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;
-                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) {
-                    //PAYLOADTYPE_COLLECTION
-                    ret.typeName = property.type;
-                    
-                    
-                    if (utils.startsWith(property.type, 'Collection')) {
-                        ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
-                        var tmp12 =  property.type.substring(10+1,property.type.length - 1);
-                        ret.typeName = tmp12;
-                        ret.type = lookupComplexType(tmp12, model);    
-                        ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
-                    } else {
-                        ret.type = lookupComplexType(property.type, model);    
-                        ret.detectedPayloadKind = PAYLOADTYPE_PROPERTY;
-                    }    
-
-                    ret.name = fragment;
-                    // 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;
-}
-
-/** Infers the information describing the JSON payload from its metadata annotation, structure, and data model.
- * @param {Object} data - Json response payload object.
- * @param {Object} model - Object describing an OData conceptual schema.
- * 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 payload.
- * @return Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
-*/
-function createPayloadInfo(data, model) {
-    
-
-    var metadataUri = data[contextUrlAnnotation];
-    if (!metadataUri || typeof metadataUri !== "string") {
-        return null;
-    }
-
-    var fragmentStart = metadataUri.lastIndexOf("#");
-    if (fragmentStart === -1) {
-        return jsonMakePayloadInfo(PAYLOADTYPE_SVCDOC);
-    }
-
-    var fragment = metadataUri.substring(fragmentStart + 1);
-    return parseContextUriFragment(fragment,model);
-}
-
-/** Processe a JSON response payload with metadata-minimal
- * @param {Object} data - Json response payload object
- * @param {Object} model - Object describing an OData conceptual schema
- * @param {Boolean} recognizeDates - Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.
- * @returns {Object} Object in the library's representation.
- */
-function readPayloadMinimal(data, model, recognizeDates) {
-
-    if (!assigned(model) || isArray(model)) {
-        return data;
-    }
-
-    var baseURI = data[contextUrlAnnotation];
-    var payloadInfo = createPayloadInfo(data, model);
-
-    switch (payloadInfo.detectedPayloadKind) {
-        case PAYLOADTYPE_VALUE:
-            return readPayloadMinimalProperty(data, model, payloadInfo, baseURI, recognizeDates);
-        case PAYLOADTYPE_FEED:
-            return readPayloadMinimalFeed(data, model, payloadInfo, baseURI, recognizeDates);
-        case PAYLOADTYPE_ENTRY:
-            return readPayloadMinimalEntry(data, model, payloadInfo, baseURI, recognizeDates);
-        case PAYLOADTYPE_COLLECTION:
-            return readPayloadMinimalCollection(data, model, payloadInfo, baseURI, recognizeDates);
-        case PAYLOADTYPE_PROPERTY:
-            return readPayloadMinimalProperty(data, model, payloadInfo, baseURI, recognizeDates);
-        case PAYLOADTYPE_SVCDOC:
-            return data;
-        case PAYLOADTYPE_LINKS:
-            return data;
-    }
-
-    return data;
-}
-
-/** Gets the key of an entry.
- * @param {Object} data - JSON entry.
- *
- * @returns {string} Entry instance key.
- */
-function jsonGetEntryKey(data, entityModel) {
-
-    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;
-}
-
-function readPayloadMinimalProperty(data, model, collectionInfo, baseURI, recognizeDates) {
-    if (collectionInfo.type !== null) {
-        readPayloadMinimalObject(data, collectionInfo, baseURI, model, recognizeDates);
-    } else {
-        addTypeNoEdm(data,'value', collectionInfo.typeName);
-        //data['value@odata.type'] = '#'+collectionInfo.typeName;
-    }
-    return data;
-}
-
-function readPayloadMinimalCollection(data, model, collectionInfo, baseURI, recognizeDates) {
-    //data['@odata.type'] = '#Collection('+collectionInfo.typeName + ')';
-    addTypeColNoEdm(data,'', collectionInfo.typeName);
-
-    if (collectionInfo.type !== null) {
-        var entries = [];
-
-        var items = data.value;
-        for (i = 0, len = items.length; i < len; i++) {
-            var item = items[i];
-            if ( defined(item['@odata.type'])) { // in case of mixed collections
-                var typeName = item['@odata.type'].substring(1);
-                var type = lookupEntityType( typeName, model);
-                var entryInfo = {
-                    contentTypeOdata : collectionInfo.contentTypeOdata,
-                    detectedPayloadKind : collectionInfo.detectedPayloadKind,
-                    name : collectionInfo.name,
-                    type : type,
-                    typeName : typeName
-                };
-
-                entry = readPayloadMinimalObject(item, entryInfo, baseURI, model, recognizeDates);
-            } else {
-                entry = readPayloadMinimalObject(item, collectionInfo, baseURI, model, recognizeDates);
-            }
-            
-            entries.push(entry);
-        }
-        data.value = entries;
-    }
-    return data;
-}
-
-function readPayloadMinimalFeed(data, model, feedInfo, baseURI, recognizeDates) {
-    var entries = [];
-    var items = data.value;
-    for (i = 0, len = items.length; i < len; i++) {
-        var item = items[i];
-        if ( defined(item['@odata.type'])) { // in case of mixed feeds
-            var typeName = item['@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 = readPayloadMinimalObject(item, entryInfo, baseURI, model, recognizeDates);
-        } else {
-            entry = readPayloadMinimalObject(item, feedInfo, baseURI, model, recognizeDates);
-        }
-        
-        entries.push(entry);
-    }
-    data.value = entries;
-    return data;
-}
-
-function readPayloadMinimalEntry(data, model, entryInfo, baseURI, recognizeDates) {
-    return readPayloadMinimalObject(data, entryInfo, baseURI, model, recognizeDates);
-}
-
-/** Formats a value according to Uri literal format
- * @param value - Value to be formatted.
- * @param type - Edm type of the value
- * @returns {string} Value after formatting
- */
-function formatLiteral(value, type) {
-
-    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;
-    }
-}
-
-function formatRowLiteral(value, type) {
-    switch (type) {
-        case "Edm.Binary":
-            return convertByteArrayToHexString(value);
-        default:
-            return value;
-    }
-}
-
-function convertDates(data, propertyName,type) {
-    if (type === 'Edm.Date') {
-        data[propertyName] = oDataUtils.parseDate(data[propertyName], true);
-    } else if (type === 'Edm.DateTimeOffset') {
-        data[propertyName] = oDataUtils.parseDateTimeOffset(data[propertyName], true);
-    } else if (type === 'Edm.Duration') {
-        data[propertyName] = oDataUtils.parseDuration(data[propertyName], true);
-    } else if (type === 'Edm.Time') {
-        data[propertyName] = oDataUtils.parseTime(data[propertyName], true);
-    }
-}
-
-function convertDatesNoEdm(data, propertyName,type) {
-    if (type === 'Date') {
-        data[propertyName] = oDataUtils.parseDate(data[propertyName], true);
-    } else if (type === 'DateTimeOffset') {
-        data[propertyName] = oDataUtils.parseDateTimeOffset(data[propertyName], true);
-    } else if (type === 'Duration') {
-        data[propertyName] = oDataUtils.parseDuration(data[propertyName], true);
-    } else if (type === 'Time') {
-        data[propertyName] = oDataUtils.parseTime(data[propertyName], true);
-    }
-}
-
-function checkProperties(data, objectInfoType, baseURI, model, recognizeDates) {
-    for (var name in data) {
-        if (name.indexOf("@") === -1) {
-            var curType = objectInfoType;
-            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 ( isArray(propertyValue)) {
-                //data[name+'@odata.type'] = '#' + property.type;
-                if (isCollectionType(property.type)) {
-                    addTypeColNoEdm(data,name,property.type.substring(11,property.type.length-1));
-                } else {
-                    addTypeNoEdm(data,name,property.type);
-                }
-
-
-                for ( var i = 0; i < propertyValue.length; i++) {
-                    readPayloadMinimalComplexObject(propertyValue[i], property, baseURI, model, recognizeDates);
-                }
-            } else if (isObject(propertyValue) && (propertyValue !== null)) {
-                readPayloadMinimalComplexObject(propertyValue, property, baseURI, model, recognizeDates);
-            } else {
-                //data[name+'@odata.type'] = '#' + property.type;
-                addTypeNoEdm(data,name,property.type);
-                if (recognizeDates) {
-                    convertDates(data, name, property.type);
-                }
-            }
-        }
-    }
-}
-
-function readPayloadMinimalComplexObject(data, property, baseURI, model, recognizeDates) {
-    var type = property.type;
-    if (isCollectionType(property.type)) {
-        type =property.type.substring(11,property.type.length-1);
-    }
-
-    //data['@odata.type'] = '#'+type;
-    addType(data,'',property.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
-    }
-  
-    checkProperties(data, propertyType, baseURI, model, recognizeDates);
-}
-
-function readPayloadMinimalObject(data, objectInfo, baseURI, model, recognizeDates) {
-    //data['@odata.type'] = '#'+objectInfo.typeName;
-    addType(data,'',objectInfo.typeName);
-
-    var keyType = objectInfo.type;
-    while ((defined(keyType)) && ( keyType.key === undefined) && (keyType.baseType !== undefined)) {
-        keyType = lookupEntityType(keyType.baseType, model);
-    }
-
-    //if ((keyType !== undefined) && (keyType.key !== undefined)) { 
-    if (keyType.key !== undefined) { 
-        var lastIdSegment = objectInfo.name + jsonGetEntryKey(data, keyType);
-        data['@odata.id'] = baseURI.substring(0, baseURI.lastIndexOf("$metadata")) + lastIdSegment;
-        data['@odata.editLink'] = lastIdSegment;
-    }
-
-    var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
-    //json ComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
-
-    checkProperties(data, objectInfo.type, baseURI, model, recognizeDates);
-    
-    return data;
-}
-
-var jsonSerializableMetadata = ["@odata.id", "@odata.type"];
-
-function isJsonSerializableProperty(property) {
-    if (!property) {
-        return false;
-    }
-
-    if (property.indexOf("@odata.") == -1) {
-        return true;
-    } 
-
-    var i, len;
-    for (i = 0, len = jsonSerializableMetadata.length; i < len; i++) {
-        var name = jsonSerializableMetadata[i];
-        if (property.indexOf(name) != -1) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/** Determines whether a type name is a primitive type in a JSON payload.
- * @param {String} typeName - Type name to test.
- * @returns {Boolean} True if the type name an EDM primitive type or an OData spatial type; false otherwise.
- */
-function jsonIsPrimitiveType(typeName) {
-
-    return isPrimitiveEdmType(typeName) || isGeographyEdmType(typeName) || isGeometryEdmType(typeName);
-}
-
-
-var jsonHandler = oDataHandler.handler(jsonParser, jsonSerializer, jsonMediaType, MAX_DATA_SERVICE_VERSION);
-jsonHandler.recognizeDates = false;
-
-
-
-exports.createPayloadInfo = createPayloadInfo;
-exports.jsonHandler = jsonHandler;
-exports.jsonParser = jsonParser;
-exports.jsonSerializer = jsonSerializer;
-exports.parseJsonDateString = parseJsonDateString;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/metadata.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/metadata.js b/datajs/src/lib/odata/metadata.js
deleted file mode 100644
index 5ad70b6..0000000
--- a/datajs/src/lib/odata/metadata.js
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module odata/metadata */
-
-var utils    = require('./../datajs.js').utils;
-var oDSxml    = require('./../datajs.js').xml;
-var odataHandler    = require('./handler.js');
-
-
-
-// imports 
-var contains = utils.contains;
-var normalizeURI = utils.normalizeURI;
-var xmlAttributes = oDSxml.xmlAttributes;
-var xmlChildElements = oDSxml.xmlChildElements;
-var xmlFirstChildElement = oDSxml.xmlFirstChildElement;
-var xmlInnerText = oDSxml.xmlInnerText;
-var xmlLocalName = oDSxml.xmlLocalName;
-var xmlNamespaceURI = oDSxml.xmlNamespaceURI;
-var xmlNS = oDSxml.xmlNS;
-var xmlnsNS = oDSxml.xmlnsNS;
-var xmlParse = oDSxml.xmlParse;
-
-var ado = oDSxml.http + "docs.oasis-open.org/odata/";      // http://docs.oasis-open.org/odata/
-var adoDs = ado + "ns";                             // http://docs.oasis-open.org/odata/ns
-var edmxNs = adoDs + "/edmx";                       // http://docs.oasis-open.org/odata/ns/edmx
-var edmNs1 = adoDs + "/edm";                        // http://docs.oasis-open.org/odata/ns/edm
-var odataMetaXmlNs = adoDs + "/metadata";           // http://docs.oasis-open.org/odata/ns/metadata
-var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
-
-var xmlMediaType = "application/xml";
-
-/** Creates an object that describes an element in an schema.
- * @param {Array} attributes - List containing the names of the attributes allowed for this element.
- * @param {Array} elements - List containing the names of the child elements allowed for this element.
- * @param {Boolean} text - Flag indicating if the element's text value is of interest or not.
- * @param {String} ns - Namespace to which the element belongs to.
- * If a child element name ends with * then it is understood by the schema that that child element can appear 0 or more times.
- * @returns {Object} Object with attributes, elements, text, and ns fields.
- */
-function schemaElement(attributes, elements, text, ns) {
-
-    return {
-        attributes: attributes,
-        elements: elements,
-        text: text || false,
-        ns: ns
-    };
-}
-
-// It's assumed that all elements may have Documentation children and Annotation elements.
-// See http://docs.oasis-open.org/odata/odata/v4.0/cs01/part3-csdl/odata-v4.0-cs01-part3-csdl.html for a CSDL reference.
-var schema = {
-    elements: {
-        Action: schemaElement(
-        /*attributes*/["Name", "IsBound", "EntitySetPath"],
-        /*elements*/["ReturnType", "Parameter*", "Annotation*"]
-        ),
-        ActionImport: schemaElement(
-        /*attributes*/["Name", "Action", "EntitySet", "Annotation*"]
-        ),
-        Annotation: schemaElement(
-        /*attributes*/["Term", "Qualifier", "Binary", "Bool", "Date", "DateTimeOffset", "Decimal", "Duration", "EnumMember", "Float", "Guid", "Int", "String", "TimeOfDay", "AnnotationPath", "NavigationPropertyPath", "Path", "PropertyPath", "UrlRef"],
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
-        ),
-        AnnotationPath: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Annotations: schemaElement(
-        /*attributes*/["Target", "Qualifier"],
-        /*elements*/["Annotation*"]
-        ),
-        Apply: schemaElement(
-        /*attributes*/["Function"],
-        /*elements*/["String*", "Path*", "LabeledElement*", "Annotation*"]
-        ),
-        And: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Or: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Not: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Eq: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Ne: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Gt: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Ge: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Lt: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Le: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Binary: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Bool: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Cast: schemaElement(
-        /*attributes*/["Type"],
-        /*elements*/["Path*", "Annotation*"]
-        ),
-        Collection: schemaElement(
-        /*attributes*/null,
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*"]
-        ),
-        ComplexType: schemaElement(
-        /*attributes*/["Name", "BaseType", "Abstract", "OpenType"],
-        /*elements*/["Property*", "NavigationProperty*", "Annotation*"]
-        ),
-        Date: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        DateTimeOffset: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Decimal: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Duration: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        EntityContainer: schemaElement(
-        /*attributes*/["Name", "Extends"],
-        /*elements*/["EntitySet*", "Singleton*", "ActionImport*", "FunctionImport*", "Annotation*"]
-        ),
-        EntitySet: schemaElement(
-        /*attributes*/["Name", "EntityType", "IncludeInServiceDocument"],
-        /*elements*/["NavigationPropertyBinding*", "Annotation*"]
-        ),
-        EntityType: schemaElement(
-        /*attributes*/["Name", "BaseType", "Abstract", "OpenType", "HasStream"],
-        /*elements*/["Key*", "Property*", "NavigationProperty*", "Annotation*"]
-        ),
-        EnumMember: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        EnumType: schemaElement(
-        /*attributes*/["Name", "UnderlyingType", "IsFlags"],
-        /*elements*/["Member*"]
-        ),
-        Float: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Function: schemaElement(
-        /*attributes*/["Name", "IsBound", "IsComposable", "EntitySetPath"],
-        /*elements*/["ReturnType", "Parameter*", "Annotation*"]
-        ),
-        FunctionImport: schemaElement(
-        /*attributes*/["Name", "Function", "EntitySet", "IncludeInServiceDocument", "Annotation*"]
-        ),
-        Guid: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        If: schemaElement(
-        /*attributes*/null,
-        /*elements*/["Path*", "String*", "Annotation*"]
-        ),
-        Int: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        IsOf: schemaElement(
-        /*attributes*/["Type", "MaxLength", "Precision", "Scale", "Unicode", "SRID", "DefaultValue", "Annotation*"],
-        /*elements*/["Path*"]
-        ),
-        Key: schemaElement(
-        /*attributes*/null,
-        /*elements*/["PropertyRef*"]
-        ),
-        LabeledElement: schemaElement(
-        /*attributes*/["Name"],
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
-        ),
-        LabeledElementReference: schemaElement(
-        /*attributes*/["Term"],
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*"]
-        ),
-        Member: schemaElement(
-        /*attributes*/["Name", "Value"],
-        /*element*/["Annotation*"]
-        ),
-        NavigationProperty: schemaElement(
-        /*attributes*/["Name", "Type", "Nullable", "Partner", "ContainsTarget"],
-        /*elements*/["ReferentialConstraint*", "OnDelete*", "Annotation*"]
-        ),
-        NavigationPropertyBinding: schemaElement(
-        /*attributes*/["Path", "Target"]
-        ),
-        NavigationPropertyPath: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Null: schemaElement(
-        /*attributes*/null,
-        /*elements*/["Annotation*"]
-        ),
-        OnDelete: schemaElement(
-        /*attributes*/["Action"],
-        /*elements*/["Annotation*"]
-        ),
-        Path: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Parameter: schemaElement(
-        /*attributes*/["Name", "Type", "Nullable", "MaxLength", "Precision", "Scale", "SRID"],
-        /*elements*/["Annotation*"]
-        ),
-        Property: schemaElement(
-        /*attributes*/["Name", "Type", "Nullable", "MaxLength", "Precision", "Scale", "Unicode", "SRID", "DefaultValue"],
-        /*elements*/["Annotation*"]
-        ),
-        PropertyPath: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        PropertyRef: schemaElement(
-        /*attributes*/["Name", "Alias"]
-        ),
-        PropertyValue: schemaElement(
-        /*attributes*/["Property", "Path"],
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
-        ),
-        Record: schemaElement(
-        /*attributes*/null,
-        /*Elements*/["PropertyValue*", "Property*", "Annotation*"]
-        ),
-        ReferentialConstraint: schemaElement(
-        /*attributes*/["Property", "ReferencedProperty", "Annotation*"]
-        ),
-        ReturnType: schemaElement(
-        /*attributes*/["Type", "Nullable", "MaxLength", "Precision", "Scale", "SRID"]
-        ),
-        String: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        Schema: schemaElement(
-        /*attributes*/["Namespace", "Alias"],
-        /*elements*/["Action*", "Annotations*", "Annotation*", "ComplexType*", "EntityContainer", "EntityType*", "EnumType*", "Function*", "Term*", "TypeDefinition*", "Annotation*"]
-        ),
-        Singleton: schemaElement(
-        /*attributes*/["Name", "Type"],
-        /*elements*/["NavigationPropertyBinding*", "Annotation*"]
-        ),
-        Term: schemaElement(
-        /*attributes*/["Name", "Type", "BaseTerm", "DefaultValue ", "AppliesTo", "Nullable", "MaxLength", "Precision", "Scale", "SRID"],
-        /*elements*/["Annotation*"]
-        ),
-        TimeOfDay: schemaElement(
-        /*attributes*/null,
-        /*elements*/null,
-        /*text*/true
-        ),
-        TypeDefinition: schemaElement(
-        /*attributes*/["Name", "UnderlyingType", "MaxLength", "Unicode", "Precision", "Scale", "SRID"],
-        /*elements*/["Annotation*"]
-        ),
-        UrlRef: schemaElement(
-        /*attributes*/null,
-        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
-        ),
-
-        // See http://msdn.microsoft.com/en-us/library/dd541238(v=prot.10) for an EDMX reference.
-        Edmx: schemaElement(
-        /*attributes*/["Version"],
-        /*elements*/["DataServices", "Reference*"],
-        /*text*/false,
-        /*ns*/edmxNs
-        ),
-        DataServices: schemaElement(
-        /*attributes*/["m:MaxDataServiceVersion", "m:DataServiceVersion"],
-        /*elements*/["Schema*"],
-        /*text*/false,
-        /*ns*/edmxNs
-        ),
-        Reference: schemaElement(
-        /*attributes*/["Uri"],
-        /*elements*/["Include*", "IncludeAnnotations*", "Annotation*"]
-        ),
-        Include: schemaElement(
-        /*attributes*/["Namespace", "Alias"]
-        ),
-        IncludeAnnotations: schemaElement(
-        /*attributes*/["TermNamespace", "Qualifier", "TargetNamespace"]
-        )
-    }
-};
-
-
-/** Converts a Pascal-case identifier into a camel-case identifier.
- * @param {String} text - Text to convert.
- * @returns {String} Converted text.
- * If the text starts with multiple uppercase characters, it is left as-is.</remarks>
- */
-function scriptCase(text) {
-
-    if (!text) {
-        return text;
-    }
-
-    if (text.length > 1) {
-        var firstTwo = text.substr(0, 2);
-        if (firstTwo === firstTwo.toUpperCase()) {
-            return text;
-        }
-
-        return text.charAt(0).toLowerCase() + text.substr(1);
-    }
-
-    return text.charAt(0).toLowerCase();
-}
-
-/** Gets the schema node for the specified element.
- * @param {Object} parentSchema - Schema of the parent XML node of 'element'.
- * @param candidateName - XML element name to consider.
- * @returns {Object} The schema that describes the specified element; null if not found.
- */
-function getChildSchema(parentSchema, candidateName) {
-
-    var elements = parentSchema.elements;
-    if (!elements) {
-        return null;
-    }
-
-    var i, len;
-    for (i = 0, len = elements.length; i < len; i++) {
-        var elementName = elements[i];
-        var multipleElements = false;
-        if (elementName.charAt(elementName.length - 1) === "*") {
-            multipleElements = true;
-            elementName = elementName.substr(0, elementName.length - 1);
-        }
-
-        if (candidateName === elementName) {
-            var propertyName = scriptCase(elementName);
-            return { isArray: multipleElements, propertyName: propertyName };
-        }
-    }
-
-    return null;
-}
-
-/** Checks whether the specifies namespace URI is one of the known CSDL namespace URIs.
- * @param {String} nsURI - Namespace URI to check.
- * @returns {Boolean} true if nsURI is a known CSDL namespace; false otherwise.
- */
-function isEdmNamespace(nsURI) {
-
-    return nsURI === edmNs1;
-}
-
-/** Parses a CSDL document.
- * @param element - DOM element to parse.
- * @returns {Object} An object describing the parsed element.
- */
-function parseConceptualModelElement(element) {
-
-    var localName = xmlLocalName(element);
-    var nsURI = xmlNamespaceURI(element);
-    var elementSchema = schema.elements[localName];
-    if (!elementSchema) {
-        return null;
-    }
-
-    if (elementSchema.ns) {
-        if (nsURI !== elementSchema.ns) {
-            return null;
-        }
-    } else if (!isEdmNamespace(nsURI)) {
-        return null;
-    }
-
-    var item = {};
-    var attributes = elementSchema.attributes || [];
-    xmlAttributes(element, function (attribute) {
-
-        var localName = xmlLocalName(attribute);
-        var nsURI = xmlNamespaceURI(attribute);
-        var value = attribute.value;
-
-        // Don't do anything with xmlns attributes.
-        if (nsURI === xmlnsNS) {
-            return;
-        }
-
-        // Currently, only m: for metadata is supported as a prefix in the internal schema table,
-        // un-prefixed element names imply one a CSDL element.
-        var schemaName = null;
-        var handled = false;
-        if (isEdmNamespace(nsURI) || nsURI === null) {
-            schemaName = "";
-        } else if (nsURI === odataMetaXmlNs) {
-            schemaName = "m:";
-        }
-
-        if (schemaName !== null) {
-            schemaName += localName;
-
-            if (contains(attributes, schemaName)) {
-                item[scriptCase(localName)] = value;
-            }
-        }
-
-    });
-
-    xmlChildElements(element, function (child) {
-        var localName = xmlLocalName(child);
-        var childSchema = getChildSchema(elementSchema, localName);
-        if (childSchema) {
-            if (childSchema.isArray) {
-                var arr = item[childSchema.propertyName];
-                if (!arr) {
-                    arr = [];
-                    item[childSchema.propertyName] = arr;
-                }
-                arr.push(parseConceptualModelElement(child));
-            } else {
-                item[childSchema.propertyName] = parseConceptualModelElement(child);
-            }
-        } 
-    });
-
-    if (elementSchema.text) {
-        item.text = xmlInnerText(element);
-    }
-
-    return item;
-}
-
-/** Parses a metadata document.
- * @param handler - This handler.
- * @param {String} text - Metadata text.
- * @returns An object representation of the conceptual model.</returns>
- */
-function metadataParser(handler, text) {
-
-    var doc = xmlParse(text);
-    var root = xmlFirstChildElement(doc);
-    return parseConceptualModelElement(root) || undefined;
-}
-
-
-
-exports.metadataHandler = odataHandler.handler(metadataParser, null, xmlMediaType, MAX_DATA_SERVICE_VERSION);
-
-exports.schema = schema;
-exports.scriptCase = scriptCase;
-exports.getChildSchema = getChildSchema;
-exports.parseConceptualModelElement = parseConceptualModelElement;
-exports.metadataParser = metadataParser;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/net.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/net.js b/datajs/src/lib/odata/net.js
deleted file mode 100644
index 9821892..0000000
--- a/datajs/src/lib/odata/net.js
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module odata/net */
-
-
-
-var utils    = require('./../datajs.js').utils;
-// Imports.
-
-var defined = utils.defined;
-var delay = utils.delay;
-
-var ticks = 0;
-
-/* Checks whether the specified request can be satisfied with a JSONP request.
- * @param request - Request object to check.
- * @returns {Boolean} true if the request can be satisfied; false otherwise.
-
- * Requests that 'degrade' without changing their meaning by going through JSONP
- * are considered usable.
- *
- * We allow data to come in a different format, as the servers SHOULD honor the Accept
- * request but may in practice return content with a different MIME type.
- */
-function canUseJSONP(request) {
-    
-    if (request.method && request.method !== "GET") {
-        return false;
-    }
-
-    return true;
-}
-
-/** Creates an IFRAME tag for loading the JSONP script
- * @param {String} url - The source URL of the script
- * @returns {HTMLElement} The IFRAME tag
- */
-function createIFrame(url) {
-    var iframe = window.document.createElement("IFRAME");
-    iframe.style.display = "none";
-
-    var attributeEncodedUrl = url.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
-    var html = "<html><head><script type=\"text/javascript\" src=\"" + attributeEncodedUrl + "\"><\/script><\/head><body><\/body><\/html>";
-
-    var body = window.document.getElementsByTagName("BODY")[0];
-    body.appendChild(iframe);
-
-    writeHtmlToIFrame(iframe, html);
-    return iframe;
-};
-
-/** Creates a XmlHttpRequest object.
- * @returns {XmlHttpRequest} XmlHttpRequest object.
- */
-function createXmlHttpRequest() {
-    if (window.XMLHttpRequest) {
-        return new window.XMLHttpRequest();
-    }
-    var exception;
-    if (window.ActiveXObject) {
-        try {
-            return new window.ActiveXObject("Msxml2.XMLHTTP.6.0");
-        } catch (_) {
-            try {
-                return new window.ActiveXObject("Msxml2.XMLHTTP.3.0");
-            } catch (e) {
-                exception = e;
-            }
-        }
-    } else {
-        exception = { message: "XMLHttpRequest not supported" };
-    }
-    throw exception;
-}
-
-/** Checks whether the specified URL is an absolute URL.
- * @param {String} url - URL to check.
- * @returns {Boolean} true if the url is an absolute URL; false otherwise.
-*/
-function isAbsoluteUrl(url) {
-    return url.indexOf("http://") === 0 ||
-        url.indexOf("https://") === 0 ||
-        url.indexOf("file://") === 0;
-}
-
-/** Checks whether the specified URL is local to the current context.
- * @param {String} url - URL to check.
- * @returns {Boolean} true if the url is a local URL; false otherwise.
- */
-function isLocalUrl(url) {
-
-    if (!isAbsoluteUrl(url)) {
-        return true;
-    }
-
-    // URL-embedded username and password will not be recognized as same-origin URLs.
-    var location = window.location;
-    var locationDomain = location.protocol + "//" + location.host + "/";
-    return (url.indexOf(locationDomain) === 0);
-}
-
-/** Removes a callback used for a JSONP request.
- * @param {String} name - Function name to remove.
- * @param {Number} tick - Tick count used on the callback.
- */
-function removeCallback(name, tick) {
-    try {
-        delete window[name];
-    } catch (err) {
-        window[name] = undefined;
-        if (tick === ticks - 1) {
-            ticks -= 1;
-        }
-    }
-};
-
-/** Removes an iframe.
- * @param {Object} iframe - The iframe to remove.
- * @returns {Object} Null value to be assigned to iframe reference.
- */
-function removeIFrame(iframe) {
-    if (iframe) {
-        writeHtmlToIFrame(iframe, "");
-        iframe.parentNode.removeChild(iframe);
-    }
-
-    return null;
-};
-
-/** Reads response headers into array.
- * @param {XMLHttpRequest} xhr - HTTP request with response available.
- * @param {Array} headers - Target array to fill with name/value pairs.
- */
-function readResponseHeaders(xhr, headers) {
-
-    var responseHeaders = xhr.getAllResponseHeaders().split(/\r?\n/);
-    var i, len;
-    for (i = 0, len = responseHeaders.length; i < len; i++) {
-        if (responseHeaders[i]) {
-            var header = responseHeaders[i].split(": ");
-            headers[header[0]] = header[1];
-        }
-    }
-}
-
-/** Writes HTML to an IFRAME document.
- * @param {HTMLElement} iframe - The IFRAME element to write to.
- * @param {String} html - The HTML to write.
- */
-function writeHtmlToIFrame(iframe, html) {
-    var frameDocument = (iframe.contentWindow) ? iframe.contentWindow.document : iframe.contentDocument.document;
-    frameDocument.open();
-    frameDocument.write(html);
-    frameDocument.close();
-}
-
-exports.defaultHttpClient = {
-    callbackParameterName: "$callback",
-
-    formatQueryString: "$format=json",
-
-    enableJsonpCallback: false,
-
-    /** Performs a network request.
-     * @param {Object} request - Request description
-     * @param {Function} success - Success callback with the response object.
-     * @param {Function} error - Error callback with an error object.
-     * @returns {Object} Object with an 'abort' method for the operation.
-     */
-    request: function (request, success, error) {
-
-        var result = {};
-        var xhr = null;
-        var done = false;
-        var iframe;
-
-        result.abort = function () {
-            iframe = removeIFrame(iframe);
-            if (done) {
-                return;
-            }
-
-            done = true;
-            if (xhr) {
-                xhr.abort();
-                xhr = null;
-            }
-
-            error({ message: "Request aborted" });
-        };
-
-        var handleTimeout = function () {
-            iframe = removeIFrame(iframe);
-            if (!done) {
-                done = true;
-                xhr = null;
-                error({ message: "Request timed out" });
-            }
-        };
-
-        var name;
-        var url = request.requestUri;
-        var enableJsonpCallback = defined(request.enableJsonpCallback, this.enableJsonpCallback);
-        var callbackParameterName = defined(request.callbackParameterName, this.callbackParameterName);
-        var formatQueryString = defined(request.formatQueryString, this.formatQueryString);
-        if (!enableJsonpCallback || isLocalUrl(url)) {
-
-            xhr = createXmlHttpRequest();
-            xhr.onreadystatechange = function () {
-                if (done || xhr === null || xhr.readyState !== 4) {
-                    return;
-                }
-
-                // Workaround for XHR behavior on IE.
-                var statusText = xhr.statusText;
-                var statusCode = xhr.status;
-                if (statusCode === 1223) {
-                    statusCode = 204;
-                    statusText = "No Content";
-                }
-
-                var headers = [];
-                readResponseHeaders(xhr, headers);
-
-                var response = { requestUri: url, statusCode: statusCode, statusText: statusText, headers: headers, body: xhr.responseText };
-
-                done = true;
-                xhr = null;
-                if (statusCode >= 200 && statusCode <= 299) {
-                    success(response);
-                } else {
-                    error({ message: "HTTP request failed", request: request, response: response });
-                }
-            };
-
-            xhr.open(request.method || "GET", url, true, request.user, request.password);
-
-            // Set the name/value pairs.
-            if (request.headers) {
-                for (name in request.headers) {
-                    xhr.setRequestHeader(name, request.headers[name]);
-                }
-            }
-
-            // Set the timeout if available.
-            if (request.timeoutMS) {
-                xhr.timeout = request.timeoutMS;
-                xhr.ontimeout = handleTimeout;
-            }
-
-            xhr.send(request.body);
-        } else {
-            if (!canUseJSONP(request)) {
-                throw { message: "Request is not local and cannot be done through JSONP." };
-            }
-
-            var tick = ticks;
-            ticks += 1;
-            var tickText = tick.toString();
-            var succeeded = false;
-            var timeoutId;
-            name = "handleJSONP_" + tickText;
-            window[name] = function (data) {
-                iframe = removeIFrame(iframe);
-                if (!done) {
-                    succeeded = true;
-                    window.clearTimeout(timeoutId);
-                    removeCallback(name, tick);
-
-                    // Workaround for IE8 and IE10 below where trying to access data.constructor after the IFRAME has been removed
-                    // throws an "unknown exception"
-                    if (window.ActiveXObject) {
-                        data = window.JSON.parse(window.JSON.stringify(data));
-                    }
-
-
-                    var headers;
-                    if (!formatQueryString || formatQueryString == "$format=json") {
-                        headers = { "Content-Type": "application/json;odata.metadata=minimal", "OData-Version": "4.0" };
-                    } else {
-                        // the formatQueryString should be in the format of "$format=xxx", xxx should be one of the application/json;odata.metadata=minimal(none or full)
-                        // set the content-type with the string xxx which stars from index 8.
-                        headers = { "Content-Type": formatQueryString.substring(8), "OData-Version": "4.0" };
-                    }
-
-                    // Call the success callback in the context of the parent window, instead of the IFRAME
-                    delay(function () {
-                        removeIFrame(iframe);
-                        success({ body: data, statusCode: 200, headers: headers });
-                    });
-                }
-            };
-
-            // Default to two minutes before timing out, 1000 ms * 60 * 2 = 120000.
-            var timeoutMS = (request.timeoutMS) ? request.timeoutMS : 120000;
-            timeoutId = window.setTimeout(handleTimeout, timeoutMS);
-
-            var queryStringParams = callbackParameterName + "=parent." + name;
-            if (formatQueryString) {
-                queryStringParams += "&" + formatQueryString;
-            }
-
-            var qIndex = url.indexOf("?");
-            if (qIndex === -1) {
-                url = url + "?" + queryStringParams;
-            } else if (qIndex === url.length - 1) {
-                url = url + queryStringParams;
-            } else {
-                url = url + "&" + queryStringParams;
-            }
-
-            iframe = createIFrame(url);
-        }
-
-        return result;
-    }
-};
-
-
-
-exports.canUseJSONP = canUseJSONP;
-exports.isAbsoluteUrl = isAbsoluteUrl;
-exports.isLocalUrl = isLocalUrl;
\ No newline at end of file


[32/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-functional-tests.js b/datajs/tests/odata-cache-functional-tests.js
deleted file mode 100644
index ac63460..0000000
--- a/datajs/tests/odata-cache-functional-tests.js
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var CustomDataSource = function (baseUri) {
-        this.baseUri = baseUri;
-    };
-
-    CustomDataSource.prototype.read = function (index, count, success, error) {
-        var that = this;
-        var url = this.baseUri + "?$skip=" + index + "&$top=" + count;
-        $(this).triggerHandler("request", { requestUri: url });
-        $.ajax({
-            url: url,
-            dataType: "json",
-            success: function (results) {
-                $(that).triggerHandler("success", { data: results });
-                success(results);
-            },
-            error: error
-        });
-    };
-
-    CustomDataSource.prototype.count = function (success, error) {
-        $.ajax({
-            url: "./endpoints/CustomDataService.svc/Count",
-            dataType: "json",
-            success: success,
-            error: error
-        });
-    },
-    CustomDataSource.prototype.toString = function () {
-        return this.baseUri;
-    };
-
-    var sources = [
-        { source: "./endpoints/FoodStoreDataServiceV4.svc/Foods", countSupported: true },
-        { source: new CustomDataSource("./endpoints/CustomDataService.svc/ReadRange"), countSupported: true }
-    ];
-
-    var itemsInCollection = 16;
-
-    // Cache config variations for single readRange with fixed skip/take that spans the entire collection
-    var pageSizes = [
-        1,
-        4,  // factor of total, <= server page size
-        5,  // non-factor of total, <= server page size
-        6,  // non-factor of total, > server page size
-        8,  // factor of total, > server page size
-        itemsInCollection,
-        itemsInCollection + 1
-    ];
-
-    var cacheSizes = [
-        -5,           // All you can store 
-         0,           // Store nothing
-         1024,        // 1 KB
-         2.5 * 1024,  // 2.5 KB
-         100 * 1024,  // 10 KB
-         512 * 1024,  // 512 KB
-         100 * 1024 * 1024, // 100 MB
-         undefined    // Default to 1 MB
-    ];
-
-    // Skip/take variations for single readRange with fixed cache config
-    var fixedPageSize = 6;
-
-    var skipValues = [
-        0,
-        fixedPageSize - 1,
-        fixedPageSize,
-        fixedPageSize + 1,
-        fixedPageSize * 2,
-        itemsInCollection + 1,
-        itemsInCollection + fixedPageSize + 1
-    ];
-
-    var takeValues = [
-        0,
-        fixedPageSize - 1,
-        fixedPageSize,
-        fixedPageSize + 1,
-        fixedPageSize * 2,
-        itemsInCollection + 1
-    ];
-
-    // Skip/take variations for multiple readRanges with fixed cache config
-    var multipleReads = [
-        { skip: 1, take: 2 },   // page 1
-        {skip: 2, take: 7 },   // page 1, 2
-        {skip: 3, take: 10 },  // page 1, 2, 3
-        {skip: 6, take: 2}    // page 2
-    ];
-
-    var invalidSkipValues = [-5, NaN, undefined, Infinity, "not a valid value"];
-    var invalidTakeValues = [-5, NaN, undefined, Infinity, "not a valid value"];
-    var invalidPageSizes = [-5, NaN, Infinity, 0, "not a valid value"];
-
-    // Prefetchsize variations for a single readRange
-    var prefetchSizes = [
-        -5,
-        1,
-        5,
-        itemsInCollection,
-        itemsInCollection + 1
-    ];
-
-    var expectException = function (cache) {
-        djstest.assert(false, "We should not get here because the an exception is expected.");
-        djstest.destroyCacheAndDone(cache);
-    };
-
-    var makeUnexpectedErrorHandler = function (cache) {
-        return function (err) {
-            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-            if (cache) {
-                djstest.destroyCacheAndDone(cache);
-            } else {
-                djstest.done();
-            }
-        };
-    };
-
-    var validateExpectedRange = function (cache, data, source, skipValue, takeValue, finished) {
-        /** Validates the data returned by readRange
-         * @param {Object} cache - The cache object
-         * @param {Object} data - The data returned by the cache
-         * @param {Object} source - The base URI of the feed, or the custom data source
-         * @param {Integer} skipValue - The skip value
-         * @param {Integer} takeValue - The take value
-         * @param {Function} finished - Callback function called after data is verified
-         */
-        var assertData = function (expectedData) {
-            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-            finished();
-        };
-
-        if (typeof source === "string") {
-            var expectedRangeUrl = source + "?$skip=" + skipValue + "&$top=" + takeValue;
-            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, assertData);
-        } else {
-            source.read(skipValue, takeValue, assertData);
-        }
-    };
-
-    var onidleValidation = function () {
-        djstest.assert(true, "expected call to onidle");
-        djstest.done();
-    };
-
-    var createSingleReadTestName = function (params) {
-        return "Testing readRange of " + params.source + " [skip " + params.skip + " take " + params.take + "] with pageSize " +
-            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
-    };
-
-    var createMultipleReadTestName = function (params) {
-        return "Testing readRange of " + params.source + " [skip " + params.firstSkip + " take " + params.firstTake + ", " +
-            (params.destroyCacheBetweenReads ? "cache.destroy(), " : "") +
-            "skip " + params.secondSkip + " take " + params.secondTake + "] with pageSize " +
-            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
-    };
-
-    var dataCacheSingleReadRangeTest = function (params) {
-        djstest.assertsExpected(2);
-        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
-
-        if (params.mechanism) {
-            options.mechanism = params.mechanism;
-        }
-
-        var cache = this.createAndAddCache(options);
-        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
-        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
-        cache.readRange(params.skip, params.take).then(function (data) {
-            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
-            validateExpectedRange(cache, data, params.source, params.skip, params.take, function () {
-                djstest.destroyCacheAndDone(cache);
-            });
-        }, makeUnexpectedErrorHandler(cache));
-    };
-
-    var dataCacheParallelReadRangeTest = function (params) {
-        djstest.assertsExpected(2);
-        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
-
-        var cache = this.createAndAddCache(options);
-
-        var firstReadRange = function (finished) {
-            cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
-                validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, finished);
-            }, makeUnexpectedErrorHandler(cache));
-        };
-
-        var secondReadRange = function (finished) {
-            cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
-                validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, finished);
-            }, makeUnexpectedErrorHandler(cache));
-        };
-
-        djstest.asyncDo([firstReadRange, secondReadRange], function () {
-            djstest.destroyCacheAndDone(cache);
-        });
-    };
-
-    var dataCacheSerialReadRangeTest = function (params) {
-        djstest.assertsExpected(4);
-        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
-
-        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
-        var secondRead = function () {
-            session.clear();
-            cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
-                cacheOracle.verifyRequests(session.requests, session.responses, params.secondSkip, params.secondTake, "Second readRange requests");
-                validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, djstest.done);
-            }, makeUnexpectedErrorHandler(cache));
-        };
-
-        var cache = this.createAndAddCache(options);
-        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
-        cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
-            cacheOracle.verifyRequests(session.requests, session.responses, params.firstSkip, params.firstTake, "First readRange requests");
-            validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, function () {
-                if (params.destroyCacheBetweenReads === true) {
-                    cache.clear().then(function () {
-                        cacheOracle.clear();
-                        secondRead();
-                    }, function (err) {
-                        djstest.fail("Error destroying the cache: " + djstest.toString(err));
-                    });
-                } else {
-                    secondRead();
-                }
-            });
-        }, makeUnexpectedErrorHandler(cache));
-    };
-
-    var dataCachePrefetchTest = function (params) {
-        djstest.assertsExpected(2);
-        var options = {
-            name: "cache" + new Date().valueOf(),
-            source: params.source,
-            pageSize: params.pageSize,
-            prefetchSize: params.prefetchSize,
-            cacheSize: params.cacheSize,
-            user: params.user,
-            password: params.password
-        };
-
-        var cache = this.createAndAddCache(options);
-        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
-        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
-
-        cache.readRange(params.skip, params.take).then(function (data) {
-            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
-            session.clear();
-        }, makeUnexpectedErrorHandler(cache));
-
-        cache.onidle = function () {
-            var prefetchSize = params.prefetchSize < 0 ? itemsInCollection : params.prefetchSize;
-            cacheOracle.verifyRequests(session.requests, session.responses, params.skip + params.take, prefetchSize, "prefetch requests", false, true);
-            cache.onidle = false;
-            djstest.destroyCacheAndDone(cache);
-        };
-    };
-
-    var cleanDomStorage = function (done) {
-        /** Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
-         * setup and teardown methods to be consistent with indexedDb's cleanup method.
-         * @param {Function} done - Function to be called after DOM storage is cleared.
-         */
-                 if (window.localStorage) {
-            window.localStorage.clear();
-        }
-        done();
-    };
-
-    var cleanIndexedDb = function (done) {
-        /** Cleans all the data saved in the browser's IndexedDb Storage.
-         * @param {Function} done - Function to be called after indexedDb is cleared.
-         */
-        var caches = this.caches;
-
-        djstest.cleanStoreOnIndexedDb(caches, done);
-    };
-
-    var cleanupAllStorage = function (done) {
-        /** Cleans up all available storage mechanisms in the browser.
-         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
-         */
-        var that = this;
-        var storeCleanup = [];
-
-        $.each(CacheOracle.mechanisms, function (_, mechanism) {
-            if (CacheOracle.isMechanismAvailable(mechanism)) {
-                storeCleanup.push(function (done) {
-                    if (storageMechanisms[mechanism]) {
-                        storageMechanisms[mechanism].cleanup.call(that, done);
-                    } else {
-                        done();
-                    }
-                });
-            }
-        });
-
-        djstest.asyncDo(storeCleanup, done);
-    };
-
-    var storageMechanisms = {
-        indexeddb: { cleanup: cleanIndexedDb },
-        dom: { cleanup: cleanDomStorage },
-        memory: { cleanup: function (done) { done(); } },
-        best: { cleanup: function (done) { done(); } }
-    };
-
-    module("Functional", {
-        setup: function () {
-            this.createAndAddCache = function (options) {
-                /** Returns a cache created from the options object and 
-                 * @param {Object} options - Object to create a cache from. 
-                 */
-                var cache = odatajs.cache.createDataCache(options);
-                this.caches.push({ name: options.name, cache: cache });
-                return cache;
-            };
-
-            this.observableHttpClient = new ObservableHttpClient();
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
-            this.caches = [];
-            var that = this;
-
-            djstest.wait(function (done) {
-                cleanupAllStorage.call(that, done);
-            });
-        },
-
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
-            var clearActions = [];
-            var that = this;
-
-            $.each(this.caches, function (_, cacheObject) {
-                cacheObject.cache.onidle = undefined;
-
-                clearActions.push(function (done) {
-                    cacheObject.cache.clear().then(function () {
-                        done();
-                    },
-                        function (err) {
-                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
-                        })
-                });
-            });
-
-            djstest.wait(function (done) {
-                djstest.asyncDo(clearActions, function () {
-                    cleanupAllStorage.call(that, function () {
-                        that.caches = [];
-                        done();
-                    });
-                });
-            });
-        }
-    });
-
-    $.each(CacheOracle.mechanisms, function (_, mechanism) {
-        var parameters = { mechanism: mechanism, source: sources[1].source, take: 5, skip: 0, pageSize: 5, prefetchSize: 5 };
-        if (CacheOracle.isMechanismAvailable(mechanism)) {
-            djstest.addTest(dataCacheSingleReadRangeTest, "Specified mechanism: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
-        }
-        else {
-            djstest.addTest(function (params) {
-                djstest.assertsExpected(1);
-                var options = { name: "cache" + new Date().valueOf(), mechanism: params.mechanism, source: params.source };
-                try {
-                    var cache = this.createAndAddCache(options);
-                    expectException(cache);
-                }
-                catch (e) {
-                    if (mechanism === "indexeddb") {
-                        djstest.assertAreEqual(e.message, "IndexedDB is not supported on this browser", "Validating expected error");
-                    } else if (mechanism === "dom") {
-                        djstest.assertAreEqual(e.message, "Web Storage not supported by the browser", "Validating expected error");
-                    } else {
-                        djstest.fail("Creating cache with mechanism " + mechanism + " should not fail: " + djstest.toString(e));
-                    }
-
-                    djstest.done();
-                }
-            }, "Invalid mechanism for browser: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
-        }
-    });
-
-    $.each(sources, function (_, sourceObject) {
-        $.each(pageSizes, function (_, pageSizeValue) {
-            $.each(cacheSizes, function (_, cacheSizeValue) {
-                var parameters = { source: sourceObject.source, skip: 0, take: itemsInCollection, pageSize: pageSizeValue, prefetchSize: 0, cacheSize: cacheSizeValue };
-                djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
-            });
-        });
-
-        $.each(skipValues, function (_, skipValue) {
-            $.each(takeValues, function (_, takeValue) {
-                var parameters = { source: sourceObject.source, take: takeValue, skip: skipValue, pageSize: 4, prefetchSize: 0, cacheSize: 0 };
-                djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
-            });
-        });
-
-        $.each(multipleReads, function (_, firstRange) {
-            $.each(multipleReads, function (_, secondRange) {
-                var parallelReadParams = { source: sourceObject.source, firstTake: firstRange.take, firstSkip: firstRange.skip, secondTake: secondRange.take, secondSkip: secondRange.skip, pageSize: 5, prefetchSize: 0, cacheSize: 0 };
-                djstest.addTest(dataCacheParallelReadRangeTest, "Parallel: " + createMultipleReadTestName(parallelReadParams), parallelReadParams);
-
-                $.each([false, true], function (_, destroyCacheBetweenReads) {
-                    var serialReadParams = $.extend({}, parallelReadParams, { destroyCacheBetweenReads: destroyCacheBetweenReads });
-                    djstest.addTest(dataCacheSerialReadRangeTest, "Serial: " + createMultipleReadTestName(serialReadParams), serialReadParams);
-                });
-            });
-        });
-
-        var getInvalidValueErrorMessage = function (invalidValue, parameterName) {
-            /** Returns the expected error message for the specified invalid value.
-             * @param {Object} invalidValue - invalid value (anything other than zero or positive integer) to determine the error message from.
-             * @param {String} parameterName - The name of the parameter being verified.
-             * @returns {String} Error message expected.
-             */
-            return (invalidValue === undefined || typeof invalidValue !== "number") ?
-                        "'" + parameterName + "' must be a number." :
-                        "'" + parameterName + "' must be greater than or equal to zero.";
-        };
-
-        $.each(invalidSkipValues, function (_, invalidSkipValue) {
-            var parameters = { source: sourceObject.source, skip: invalidSkipValue, take: 1 };
-            djstest.addTest(function (params) {
-                djstest.assertsExpected(1);
-                var options = { name: "cache" + new Date().valueOf(), source: params.source };
-                var cache = this.createAndAddCache(options);
-                try {
-                    cache.readRange(params.skip, params.take);
-                    expectException(cache);
-                } catch (e) {
-                    djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidSkipValue, "index"), "Error message validation");
-                    djstest.destroyCacheAndDone(cache);
-                }
-            }, "Invalid skip: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        $.each(invalidTakeValues, function (_, invalidTakeValue) {
-            var parameters = { source: sourceObject.source, skip: 0, take: invalidTakeValue };
-            djstest.addTest(function (params) {
-                djstest.assertsExpected(1);
-                var options = { name: "cache" + new Date().valueOf(), source: params.source };
-                var cache = this.createAndAddCache(options);
-                try {
-                    cache.readRange(params.skip, params.take);
-                    expectException(cache);
-                } catch (e) {
-                    djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidTakeValue, "count"), "Error message validation");
-                    djstest.destroyCacheAndDone(cache);
-                }
-            }, "Invalid take: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        $.each(invalidPageSizes, function (_, invalidPageSize) {
-            var parameters = { source: sourceObject.source, skip: 0, take: 5, pageSize: invalidPageSize };
-            djstest.addTest(function (params) {
-                var options = { name: "cache", source: params.source, pageSize: params.pageSize };
-                try {
-                    var cache = this.createAndAddCache(options);
-                    expectException(cache);
-                } catch (e) {
-                    var expectedError = typeof invalidPageSize === "number" ? "'pageSize' must be greater than zero." : getInvalidValueErrorMessage(invalidPageSize, "pageSize");
-                    djstest.assertAreEqual(e.message, expectedError, "Error message validation");
-                }
-                djstest.done();
-            }, "Invalid pageSize: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        $.each(pageSizes, function (_, pageSize) {
-            $.each(cacheSizes, function (_, cacheSize) {
-                var parameters = { source: sourceObject.source, skip: 0, take: pageSize, pageSize: pageSize, prefetchSize: -1, cacheSize: cacheSize };
-                djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
-            });
-        });
-
-        $.each(skipValues, function (_, skipValue) {
-            var parameters = { source: sourceObject.source, skip: skipValue, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
-            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        $.each(takeValues, function (_, takeValue) {
-            var parameters = { source: sourceObject.source, skip: 0, take: takeValue, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
-            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        $.each(prefetchSizes, function (_, prefetchSize) {
-            var parameters = { source: sourceObject.source, skip: 0, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: prefetchSize, cacheSize: -1 };
-            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
-        });
-
-        var fixedPrefetchSize = 5;
-
-        djstest.addTest(function (params) {
-            djstest.assertsExpected(1);
-            var cache = this.createAndAddCache({
-                name: "cache" + new Date().valueOf(),
-                source: params.source,
-                prefetchSize: fixedPrefetchSize,
-                idle: onidleValidation,
-                pageSize: 2,
-                mechanism: "memory"
-            });
-            cache.readRange(0, 5);
-
-        }, "onidle in constructor, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
-
-        djstest.addTest(function (params) {
-            djstest.assertsExpected(1);
-            var cache = this.createAndAddCache({
-                name: "cache" + new Date().valueOf(),
-                source: params.source,
-                prefetchSize: fixedPrefetchSize,
-                pageSize: 2,
-                mechanism: "memory"
-            });
-            cache.onidle = onidleValidation;
-            cache.readRange(0, 5);
-        }, "onidle, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
-
-        djstest.addTest(function (params) {
-            djstest.assertsExpected(1);
-            var cache = this.createAndAddCache({
-                name: "cache" + new Date().valueOf(),
-                source: params.source,
-                prefetchSize: fixedPrefetchSize,
-                idle: function () { djstest.assert(false, "unexpected onidle call") },
-                pageSize: 2,
-                mechanism: "memory"
-            });
-            cache.onidle = onidleValidation;
-            cache.readRange(0, 5);
-        }, "onidle override, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
-
-        djstest.addTest(function (params) {
-            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: -1 });
-            var observableSource = typeof params.source === "string" ? this.observableHttpClient : params.source;
-            cache.readRange(0, 1).then(function (data) {
-                // Let one prefetch request go out, to make sure the prefetcher is started, and then destroy the cache
-                $(observableSource).one("success", function () {
-                    var session = new Session(observableSource);
-                    cache.clear().then(function () {
-                        setTimeout(function () {
-                            djstest.assertAreEqualDeep(session.requests, [], "Verify no prefetch requests are sent out after cache.clear() callback");
-                            djstest.done();
-                        }, 1000);
-                    }, function (err) {
-                        djstest.fail("Error destroying the cache: " + djstest.toString(err));
-                    });
-                });
-            });
-        }, "Testing cache.clear() halts the prefetcher" + sourceObject.source, { source: sourceObject.source });
-
-        djstest.addTest(function (params) {
-            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source });
-            if (params.countSupported) {
-                cache.count().then(function (count) {
-                    djstest.assertAreEqual(count, itemsInCollection, "All items accounted for");
-                    djstest.destroyCacheAndDone(cache);
-                }, makeUnexpectedErrorHandler(cache));
-            }
-            else {
-                cache.count().then(function (count) {
-                    djstest.assert(false, "Success should not be called, count not supported");
-                    djstest.destroyCacheAndDone(cache);
-                }, function (err) {
-                    djstest.assertAreEqual(err.message, "HTTP request failed", "Validating expected error");
-                    djstest.destroyCacheAndDone(cache);
-                });
-            }
-        }, "Testing cache.count() on " + sourceObject.source, { source: sourceObject.source, countSupported: sourceObject.countSupported });
-
-        djstest.addTest(function (params) {
-            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
-            var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
-            cache.readRange(0, 1).cancel();
-            setTimeout(function () {
-                djstest.assertAreEqualDeep(session.requests, [], "Verify no requests are sent out after readRange is cancelled");
-                djstest.done();
-            }, 1000);
-        }, "Testing cancel()" + sourceObject.source, { source: sourceObject.source });
-
-        djstest.addTest(function (params) {
-            djstest.assertsExpected(1);
-            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
-            cache.clear().then(function () {
-                cache.clear().then(function () {
-                    djstest.pass("Second clear succeeded");
-                    djstest.done();
-                }, makeUnexpectedErrorHandler(cache));
-            }, makeUnexpectedErrorHandler(cache));
-        }, "Testing .clear().then(cache.clear())" + sourceObject.source, { source: sourceObject.source });
-    });
-
-    var params = {
-        source: "./endpoints/BasicAuthDataService.svc/Customers",
-        skip: 0,
-        take: 5,
-        pageSize: 5,
-        prefetchSize: -1,
-        cacheSize: -1,
-        user: "djsUser",
-        password: "djsPassword"
-    };
-    djstest.addTest(dataCachePrefetchTest, createSingleReadTestName(params), params);
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-rx-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-rx-functional-tests.html b/datajs/tests/odata-cache-rx-functional-tests.html
deleted file mode 100644
index aab512c..0000000
--- a/datajs/tests/odata-cache-rx-functional-tests.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>>datajs.cache toObservable() tests</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
-    <script type="text/javascript" src="common/rx.js"></script>
-    <script type="text/javascript" src="odata-cache-rx-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache toObservable() tests</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-rx-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-rx-functional-tests.js b/datajs/tests/odata-cache-rx-functional-tests.js
deleted file mode 100644
index 453e586..0000000
--- a/datajs/tests/odata-cache-rx-functional-tests.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var feeds = [
-        { uri: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
-    ];
-
-    var itemsInCollection = 16;
-    var pageSizes = [
-        1,
-        4,  // factor of total, <= server page size
-        5,  // non-factor of total, <= server page size
-        6,  // non-factor of total, > server page size
-        8,  // factor of total, > server page size
-        itemsInCollection,
-        itemsInCollection + 1
-    ];
-
-    var operatorTests = [
-        function (observable) { return observable.Take(0); },
-        function (observable) { return observable.Take(1); },
-        function (observable) { return observable.Skip(1); },
-        function (observable) { return observable.Skip(2).Take(4); },
-        function (observable) { return observable.Select(function (item) { return item.Name; }); },
-        function (observable) { return observable.Where(function (item) { return item.FoodID % 2 === 1; }); }
-    ];
-
-    var assertObservables = function (actual, expected, done) {
-        /** Asserts two finite observables generate the same sequence
-         * @param {IObservable} actual - The actual observable
-         * @param {IObservable} expected - The expected observable
-         * @param {Function} done - The callback function when asserts are done
-         */
-        var toArray = function (observable, callback) {
-            var arr = [];
-            observable.Subscribe(
-                function (item) { arr.push(item); },
-                function (err) { arr.push({ "__error__": err }); },
-                function () { callback(arr); });
-        };
-
-        toArray(actual, function (actualSequence) {
-            toArray(expected, function (expectedSequence) {
-                djstest.assertAreEqualDeep(actualSequence, expectedSequence, "Verify observable sequence");
-                done();
-            });
-        });
-    };
-
-    module("Functional");
-    $.each(feeds, function (_, feed) {
-        $.each(pageSizes, function (_, pageSize) {
-            $.each(operatorTests, function (_, operator) {
-                var params = { feedUri: feed.uri, pageSize: pageSize, operator: operator };
-                djstest.addTest(function (params) {
-                    djstest.assertsExpected(1);
-                    var options = { name: "cache" + new Date().valueOf(), source: params.feedUri, pageSize: params.pageSize, prefetchSize: 0 };
-                    var cache = odatajs.cache.createDataCache(options);
-
-                    ODataReadOracle.readJsonAcrossServerPages(params.feedUri, function (collection) {
-                        assertObservables(params.operator(cache.toObservable()), params.operator(window.Rx.Observable.FromArray(collection.value)), function () {
-                            djstest.destroyCacheAndDone(cache);
-                        });
-                    });
-                }, "feed: " + params.feedUri + ", pageSize: " + params.pageSize + ", operator: " + params.operator.toString(), params);
-            });
-        });
-    });
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-fuzz.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-fuzz.html b/datajs/tests/odata-fuzz.html
deleted file mode 100644
index 270e153..0000000
--- a/datajs/tests/odata-fuzz.html
+++ /dev/null
@@ -1,557 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData Fuzzing Tests</title>
-    <meta http-equiv="cache-control" content="no-cache" />
-    <meta http-equiv="pragma" content="no-cache" />
-    <meta http-equiv="expires" content="-1" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript">
-
-        var testCsdl = '' +
-        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
-        '<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">\r\n' +
-        '  <edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="2.0">\r\n' +
-        '    <Schema Namespace="TestCatalog.Model" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">\r\n' +
-        '      <EntityType Name="Genre">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
-        '        <NavigationProperty Name="Titles" Relationship="TestCatalog.Model.TitleGenres" FromRole="Genres" ToRole="Titles" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Language">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
-        '        <NavigationProperty Name="Titles" Relationship="TestCatalog.Model.TitleLanguages" FromRole="Language" ToRole="Titles" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Person">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.Int32" Nullable="false" />\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="true" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
-        '        <NavigationProperty Name="Awards" Relationship="TestCatalog.Model.FK_TitleAward_Person" FromRole="People" ToRole="TitleAwards" />\r\n' +
-        '        <NavigationProperty Name="TitlesActedIn" Relationship="TestCatalog.Model.TitleActors" FromRole="People" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="TitlesDirected" Relationship="TestCatalog.Model.TitleDirectors" FromRole="People" ToRole="Titles" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="TitleAudioFormat">\r\n' +
-        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Language" /><PropertyRef Name="Format" /></Key>\r\n' +
-        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
-        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Language" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleAudioFormat_Title" FromRole="TitleAudioFormats" ToRole="Titles" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="TitleAward">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.Guid" Nullable="false" />\r\n' +
-        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Category" Type="Edm.String" Nullable="false" MaxLength="60" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Year" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Won" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleAward_Title" FromRole="TitleAwards" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="Person" Relationship="TestCatalog.Model.FK_TitleAward_Person" FromRole="TitleAwards" ToRole="People" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Title" m:HasStream="true">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
-        '        <Property Name="Synopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="html" />\r\n' +
-        '        <Property Name="ShortSynopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="AverageRating" Type="Edm.Double" Nullable="true" />\r\n' +
-        '        <Property Name="ReleaseYear" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Url" Type="Edm.String" Nullable="true" MaxLength="200" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="DateModified" Type="Edm.DateTime" Nullable="false" ConcurrencyMode="Fixed" m:FC_TargetPath="SyndicationUpdated" m:FC_KeepInContent="false" />\r\n' +
-        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="8" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="BoxArt" Type="TestCatalog.Model.BoxArt" Nullable="false" />\r\n' +
-        '        <Property Name="ShortName" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
-        '        <Property Name="Instant" Type="TestCatalog.Model.InstantAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="Dvd" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="BluRay" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="TinyUrl" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
-        '        <Property Name="WebsiteUrl" Type="Edm.String" Nullable="true" MaxLength="200" />\r\n' +
-        '        <Property Name="TestApiId" Type="Edm.String" Nullable="false" MaxLength="200" />\r\n' +
-        '        <NavigationProperty Name="AudioFormats" Relationship="TestCatalog.Model.FK_TitleAudioFormat_Title" FromRole="Titles" ToRole="TitleAudioFormats" />\r\n' +
-        '        <NavigationProperty Name="Awards" Relationship="TestCatalog.Model.FK_TitleAward_Title" FromRole="Titles" ToRole="TitleAwards" />\r\n' +
-        '        <NavigationProperty Name="Disc" Relationship="TestCatalog.Model.FK_Title_Disc" FromRole="Titles1" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="Movie" Relationship="TestCatalog.Model.FK_Title_Movie" FromRole="Titles1" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="Season" Relationship="TestCatalog.Model.FK_Title_Season" FromRole="Titles1" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="Series" Relationship="TestCatalog.Model.FK_Title_Series" FromRole="Titles1" ToRole="Titles" />\r\n' +
-        '        <NavigationProperty Name="ScreenFormats" Relationship="TestCatalog.Model.FK_TitleScreenFormat_Title" FromRole="Titles" ToRole="TitleScreenFormats" />\r\n' +
-        '        <NavigationProperty Name="Cast" Relationship="TestCatalog.Model.TitleActors" FromRole="Titles" ToRole="People" />\r\n' +
-        '        <NavigationProperty Name="Languages" Relationship="TestCatalog.Model.TitleLanguages" FromRole="Titles" ToRole="Language" />\r\n' +
-        '        <NavigationProperty Name="Directors" Relationship="TestCatalog.Model.TitleDirectors" FromRole="Titles" ToRole="People" />\r\n' +
-        '        <NavigationProperty Name="Genres" Relationship="TestCatalog.Model.TitleGenres" FromRole="Titles" ToRole="Genres" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <ComplexType Name="BoxArt">\r\n' +
-        '        <Property Name="SmallUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="MediumUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="LargeUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="HighDefinitionUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <ComplexType Name="InstantAvailability">\r\n' +
-        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="HighDefinitionAvailable" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <ComplexType Name="DeliveryFormatAvailability">\r\n' +
-        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <EntityType Name="TitleScreenFormat">\r\n' +
-        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Format" /></Key>\r\n' +
-        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
-        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleScreenFormat_Title" FromRole="TitleScreenFormats" ToRole="Titles" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <Association Name="FK_TitleAudioFormat_Title">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
-        '        <End Role="TitleAudioFormats" Type="TestCatalog.Model.TitleAudioFormat" Multiplicity="*" />\r\n' +
-        '        <ReferentialConstraint>\r\n' +
-        '          <Principal Role="Titles"><PropertyRef Name="Id" /></Principal>\r\n' +
-        '          <Dependent Role="TitleAudioFormats"><PropertyRef Name="TitleId" /></Dependent>\r\n' +
-        '        </ReferentialConstraint>\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_TitleAward_Title">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
-        '        <End Role="TitleAwards" Type="TestCatalog.Model.TitleAward" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_TitleAward_Person">\r\n' +
-        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="0..1" />\r\n' +
-        '        <End Role="TitleAwards" Type="TestCatalog.Model.TitleAward" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_Title_Disc">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
-        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_Title_Movie">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
-        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_Title_Season">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
-        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_Title_Series">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
-        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="FK_TitleScreenFormat_Title">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
-        '        <End Role="TitleScreenFormats" Type="TestCatalog.Model.TitleScreenFormat" Multiplicity="*" />\r\n' +
-        '        <ReferentialConstraint>\r\n' +
-        '          <Principal Role="Titles"><PropertyRef Name="Id" /></Principal>\r\n' +
-        '          <Dependent Role="TitleScreenFormats"><PropertyRef Name="TitleId" /></Dependent>\r\n' +
-        '        </ReferentialConstraint>\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="TitleActors">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="TitleLanguages">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '        <End Role="Language" Type="TestCatalog.Model.Language" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="TitleDirectors">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '      <Association Name="TitleGenres">\r\n' +
-        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
-        '        <End Role="Genres" Type="TestCatalog.Model.Genre" Multiplicity="*" />\r\n' +
-        '      </Association>\r\n' +
-        '    </Schema>\r\n' +
-        '    <Schema Namespace="Test.Catalog" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">\r\n' +
-        '      <EntityContainer Name="TestCatalog" m:IsDefaultEntityContainer="true">\r\n' +
-        '        <FunctionImport Name="Movies" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
-        '        <FunctionImport Name="Series" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
-        '        <FunctionImport Name="Seasons" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
-        '        <FunctionImport Name="Discs" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
-        '        <FunctionImport Name="Episodes" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
-        '        <EntitySet Name="Genres" EntityType="TestCatalog.Model.Genre" />\r\n' +
-        '        <EntitySet Name="Languages" EntityType="TestCatalog.Model.Language" />\r\n' +
-        '        <EntitySet Name="People" EntityType="TestCatalog.Model.Person" />\r\n' +
-        '        <EntitySet Name="TitleAudioFormats" EntityType="TestCatalog.Model.TitleAudioFormat" />\r\n' +
-        '        <EntitySet Name="TitleAwards" EntityType="TestCatalog.Model.TitleAward" />\r\n' +
-        '        <EntitySet Name="Titles" EntityType="TestCatalog.Model.Title" />\r\n' +
-        '        <EntitySet Name="TitleScreenFormats" EntityType="TestCatalog.Model.TitleScreenFormat" />\r\n' +
-        '        <AssociationSet Name="FK_TitleAudioFormat_Title" Association="TestCatalog.Model.FK_TitleAudioFormat_Title">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="TitleAudioFormats" EntitySet="TitleAudioFormats" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_TitleAward_Title" Association="TestCatalog.Model.FK_TitleAward_Title">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="TitleAwards" EntitySet="TitleAwards" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_TitleAward_Person" Association="TestCatalog.Model.FK_TitleAward_Person">\r\n' +
-        '          <End Role="People" EntitySet="People" />\r\n' +
-        '          <End Role="TitleAwards" EntitySet="TitleAwards" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_Title_Disc" Association="TestCatalog.Model.FK_Title_Disc">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_Title_Movie" Association="TestCatalog.Model.FK_Title_Movie">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_Title_Season" Association="TestCatalog.Model.FK_Title_Season">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_Title_Series" Association="TestCatalog.Model.FK_Title_Series">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="FK_TitleScreenFormat_Title" Association="TestCatalog.Model.FK_TitleScreenFormat_Title">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="TitleScreenFormats" EntitySet="TitleScreenFormats" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="TitleActors" Association="TestCatalog.Model.TitleActors">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="People" EntitySet="People" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="TitleLanguages" Association="TestCatalog.Model.TitleLanguages">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Language" EntitySet="Languages" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="TitleDirectors" Association="TestCatalog.Model.TitleDirectors">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="People" EntitySet="People" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '        <AssociationSet Name="TitleGenres" Association="TestCatalog.Model.TitleGenres">\r\n' +
-        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
-        '          <End Role="Genres" EntitySet="Genres" />\r\n' +
-        '        </AssociationSet>\r\n' +
-        '      </EntityContainer>\r\n' +
-        '    </Schema>\r\n' +
-        '  </edmx:DataServices>\r\n' +
-        '</edmx:Edmx>\r\n' +
-        '';
-
-
-        var iterationsRemaining = 0;
-        var iterationsPerRun = 100000;
-        var failureCount = 0;
-        var canary = false;
-
-        function canaryFn() {
-            canary = true;
-        }
-
-        var buildSumAndNormalize = function (table) {
-            // Sum all weights.
-            var total = 0;
-            for (var i = 0; i < table.length; i++) {
-                total += table[i].w;
-            }
-
-            // Record a normalized weight (nw) and the step-ladder threshold.
-            var last = 0;
-            for (var i = 0; i < table.length; i++) {
-                table[i].nw = (table[i].w / total);
-
-                last += table[i].nw;
-                table[i].sl = last;
-            }
-
-            table.total = total;
-        };
-
-        var randomFromWeighted = function (table) {
-            if (table.total === undefined) {
-                buildSumAndNormalize(table);
-            }
-
-            var number = Math.random();
-            for (var i = 0; i < table.length; i++) {
-                if (number < table[i].sl) {
-                    return table[i].v;
-                }
-            }
-
-            return table[table.length - 1].v;
-        };
-
-        // Create a table with relative weight w and value v for text generation.
-        var fuzzingTextTable = [
-            { w: 3, v: "canary=true" },
-            { w: 2, v: "canary=true;" },
-            { w: 3, v: "canary=1" },
-            { w: 1, v: "window.canary=1" },
-            { w: 2, v: "canary=[]" },
-            { w: 2, v: "canary={}" },
-            { w: 1, v: "canaryFn" },
-            { w: 2, v: "canaryFn()" }
-        ];
-
-        var fuzzingTextOpTable = [
-            { w: 1, v: "replace" },
-            { w: 3, v: "insert" }
-        ];
-
-        var fuzzText = function (text) {
-            /** Fuzzes the specified string.
-             * @param {String} text - Text to fuzz.
-             * @returns {String} The fuzzes text.
-
-            var location = Math.round(Math.random() * text.length - 1);
-            var content = randomFromWeighted(fuzzingTextTable);
-            var op = randomFromWeighted(fuzzingTextOpTable);
-            if (op === "replace") {
-                text = text.substr(0, location) + content + text.substr(location + content.length);
-            } else if (op === "insert") {
-                text = text.substr(0, location) + content + text.substr(location);
-            }
-
-            return text;
-        };
-
-        var rarely = function (rare, common) {
-            if (Math.random() < 0.1) {
-                return rare;
-            } else {
-                return common;
-            }
-        };
-
-        var gibberish = function () {
-            var len = Math.random() * 100;
-            var result = "";
-            for (var i = 0; i < len; i++) {
-                result += String.fromCharCode(Math.round(Math.random() * 65000));
-            }
-
-            return result;
-        }
-
-        var generateResponse = function (suggestedContentType, body) {
-            var url = rarely(null, "http://foo/bar");
-            var statusCode = rarely((Math.random() * 1000).toString().substr(0, 3), 200);
-            var statusText = rarely(gibberish(), "OK");
-            var headers = [];
-            headers["Content-Length"] = rarely(Math.random() * 200, undefined);
-            headers["Content-Type"] = rarely("foo bar baz", suggestedContentType);
-
-            var response = { requestUri: url, statusCode: statusCode, statusText: statusText, headers: headers, body: body };
-            return response;
-        };
-
-        var generateRandom = function () {
-            var body = gibberish();
-            return generateResponse("application/octet-stream", body);
-        };
-
-        var generateServiceDoc = function() {
-            var body = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r\n' +
-                        '<service xml:base="http://services.odata.org/OData/OData.svc/"  xmlns:atom="http://www.w3.org/2005/Atom" ' +
-                        ' xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">' +
-                        '<workspace><atom:title>Default</atom:title> <collection href="Products"><atom:title>Products</atom:title></collection>' +
-                        '<collection href="Categories"><atom:title>Categories</atom:title> </collection><collection href="Suppliers"><atom:title>Suppliers</atom:title> </collection></workspace></service>';
-            body = fuzzText(body);
-            return generateResponse("application/atomsvc+xml", body);
-        };
-
-        var generateMetadata = function () {
-            var body = testCsdl;
-            body = fuzzText(body);
-            return generateResponse("application/xml", body);
-        };
-
-        var generateError = function () {
-            var body = testCsdl;
-            body = fuzzText(body);
-            return generateResponse("application/xml", body);
-        };
-
-        var generatePlainText = function () {
-            var body = gibberish();
-            return generateResponse("plain/text", body);
-        };
-
-        var generateBatch = function () {
-            var body = gibberish();
-            return generateResponse("multipart/mixed; boundary=batch(123)", body);
-        };
-
-        var generateXml = function () {
-            // TODO: consider doing something about an XHTML section here
-            var body = '' +
-                '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
-                '<feed xml:base=http://services.odata.org/OData/OData.svc/' +
-                '     xmlns:d=http://schemas.microsoft.com/ado/2007/08/dataservices' +
-                '     xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata' +
-                '     xmlns="http://www.w3.org/2005/Atom">' +
-                '  <title type="text">Categories</title>' +
-                '  <id>http://services.odata.org/OData/OData.svc/Categories</id>' +
-                '  <updated>2010-03-10T08:38:14Z</updated>' +
-                '  <link rel="self" title="Categories" href="Categories" />' +
-                '  <entry>' +
-                '    <id>http://services.odata.org/OData/OData.svc/Categories(0)</id>' +
-                '    <title type="text">Food</title>' +
-                '    <updated>2010-03-10T08:38:14Z</updated>' +
-                '    <author><name /></author>' +
-                '    <link rel="edit" title="Category" href="Categories(0)" />' +
-                '    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products"' +
-                '            type="application/atom+xml;type=feed"' +
-                '            title="Products" href="Categories(0)/Products" />' +
-                '    <category term="ODataDemo.Category"' +
-                '            scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />' +
-                '    <content type="application/xml">' +
-                '      <m:properties>' +
-                '        <d:ID m:type="Edm.Int32">0</d:ID>' +
-                '        <d:Name>Food</d:Name>' +
-                '        <d:AverageRating m:type="Edm.Double">3.6</d:AverageRating>' +
-                '        <d:AvailableFrom m:type="Edm.DateTime">1999-03-23T00:00:00</d:AvailableFrom>' +
-                '        <d:Name>Food</d:Name>' +
-                '      </m:properties>' +
-                '    </content>' +
-                '  </entry>' +
-                '  <!-- <entry> elements representing additional Categories go here -->' +
-                '</feed>';
-            return generateResponse("application/atom+xml", body);
-        };
-
-        var generateJson = function () {
-            var body =  '{ "d" : { ' +
-                        '"results": [ ' +
-                        '{ ' +
-                        '"__metadata": {  ' +
-                        '"uri": "http://services.odata.org/OData/OData.svc/Categories(0)",  ' +
-                        '"type": "DataServiceProviderDemo.Category" ' +
-                        '}, ' +
-                        '"ID": 0, ' +
-                        '"Name": "Food", ' +
-                        '"SomeDate": "Date(123)", ' +
-                        '"Products": { ' +
-                        '"__deferred": { ' +
-                        '"uri": "http://services.odata.org/OData/OData.svc/Categories(0)/Products" ' +
-                        '} } } ], ' +
-                        '"__count": "3", ' +
-                        '"__next": "http://services.odata.org/OData/OData.svc$skiptoken=12" ' +
-                        '} } ' +
-                        '';
-            return generateResponse("application/json", body);
-        };
-
-        // Create a table with relative weight w and value v for response generation.
-        var formatTable = [
-            { w:  1, v: generateRandom },
-            { w:  2, v: generateError },
-            { w:  5, v: generatePlainText },
-            { w:  5, v: generateServiceDoc },
-            { w: 10, v: generateBatch },
-            { w: 10, v: generateMetadata },
-            { w: 40, v: generateXml },
-            { w: 80, v: generateJson }
-        ];
-
-        var fakeHttpClient = {
-            request: function (request, success, error) {
-                /** Performs a network request.
-                 * @param {Function} success - Success callback with the response object.
-                 * @param {Function} error - Error callback with an error object.
-                 * @returns {Object} Object with an 'abort' method for the operation.
-
-                var shouldError = rarely(true, false);
-                var format = randomFromWeighted(formatTable);
-                var response = format();
-
-                window.setTimeout(function () {
-                    if (shouldError) {
-                        error(response);
-                    } else {
-                        success(response);
-                    }
-                }, 1);
-
-                return {};
-            }
-        };
-
-        var startTimeMs = 0;
-
-        function startTest() {
-            failureCount = 0;
-            startTimeMs = new Date().getTime();
-            iterationsRemaining = iterationsPerRun;
-            nextIteration();
-        }
-
-        function readCallback() {
-            // Success or failure don't actually matter.
-            if (canary === true) {
-                canary = false;
-                failureCount++;
-            }
-
-            iterationsRemaining--;
-            nextIteration();
-        }
-
-        function nextIteration() {
-            if (iterationsRemaining === 0) {
-                $("#fuzz-status").text("Tests complete. Failures: #" + failureCount);
-                return;
-            }
-
-            if (iterationsRemaining % 50 === 0) {
-                var text = "Running tests (pending=" + iterationsRemaining + " of " + iterationsPerRun;
-                if (iterationsRemaining !== iterationsPerRun) {
-                    var currentTimeMs = new Date().getTime();
-                    var averageTestTimeMs = (iterationsPerRun - iterationsRemaining) / (currentTimeMs - startTimeMs);
-                    var remainingTimeMs = iterationsRemaining * averageTestTimeMs;
-                    text += ", ETA: " + remainingTimeMs + "ms, avg " + averageTestTimeMs + "ms";
-                }
-
-                text += "). Failures: #" + failureCount;
-                $("#fuzz-status").text(text);
-            }
-
-            OData.read("url", readCallback, readCallback, undefined, fakeHttpClient);
-        }
-
-        $(document).ready(function () {
-            $("#start-button").click(startTest);
-        });
-    </script>
-
-</head>
-<body>
-<h1>OData Fuzzing Tests</h1>
-<p>
-This page fuzzes the OData parsers in the datajs library.
-</p>
-<button id='start-button'>Start</button>
-<p id='fuzz-status'>&nbsp;</p>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-handler-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-handler-tests.js b/datajs/tests/odata-handler-tests.js
deleted file mode 100644
index aa824c7..0000000
--- a/datajs/tests/odata-handler-tests.js
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-// odata-handler-tests.js
-
-(function (window, undefined) {
-
-    var dataServiceVersion = "4.0";
-    var endpoint = "./endpoints/FoodStoreDataServiceV4.svc";
-    var mimeType = "application/json;odata.metadata=minimal";
-    var headers = {
-                "Content-Type": mimeType,
-                Accept: mimeType,
-                "OData-Version": "4.0"
-            };
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    djstest.addTest(function createUpdateDeleteTest() {
-        // This is a simple create-update-delete cycle as a high-level test.
-
-        var serviceUri = "./endpoints/FoodStoreDataServiceV4.svc/";
-        var baseUri = serviceUri + "Categories";
-        var testItem;
-        var handledData = { CategoryID: 1001, Name: "Name #1001" };
-        var uri;
-
-        var itemCreatedCallback = function (data, response) {
-            djstest.assert(response.headers["Location"], "location URL in the headers");
-            djstest.assert(data.Name, "Name #1001");
-            
-            uri = response.headers["Location"];
-            testItem = handledData;
-            testItem.Name = "Updated name";
-            
-            odatajs.oData.request({
-                method: "PUT",
-                data: testItem,
-                requestUri: uri,
-            }, itemUpdatedCallback);
-        };
-
-        var itemUpdatedCallback = function (data, response) {
-            djstest.assertAreEqual(response.statusCode, 204, "Expecting no content on update");
-            odatajs.oData.request({
-                method: "DELETE",
-                requestUri: uri
-            }, itemDeletedCallback);
-        };
-
-        var itemDeletedCallback = function (data, response) {
-            djstest.done();
-        };
-
-        $.post(serviceUri + "ResetData", function () {
-            odatajs.oData.request({
-                requestUri: baseUri,
-                method: "POST",
-                data: { CategoryID: 1001, Name: "Name #1001" }
-            }, itemCreatedCallback);
-        });
-    });
-
-    djstest.addTest(function errorHandlerTest() {
-        djstest.assertsExpected(1);
-        odatajs.oData.read("./endpoints/FoodStoreDataServiceV4.svc/Categories?$reserved-misused=true",
-            function (data) {
-                djstest.fail("expected an error callback");
-                djstest.done();
-            },
-            function (err) {
-                djstest.assert(err.response.body, "err.response.body is assigned");
-                djstest.done();
-            });
-    });
-
-    djstest.addTest(function textHandlerParseTest() {
-        djstest.assertsExpected(1);
-        MockHttpClient.clear().addResponse("textHandlerParseTest", {
-            statusCode: 200,
-            body: " text ",
-            headers: { "Content-Type": "text/plain" }
-        });
-        odatajs.oData.read("textHandlerParseTest", function (data) {
-            djstest.assertAreEqual(data, " text ", "data matches");
-            djstest.done();
-        }, function (err) {
-            djstest.fail("expected success");
-            djstest.done();
-        }, undefined, MockHttpClient);
-    });
-
-    djstest.addTest(function textHandlerParseEmptyTest() {
-        djstest.assertsExpected(1);
-        MockHttpClient.clear().addResponse("textHandlerParseTest", {
-            statusCode: 200,
-            body: "",
-            headers: { "Content-Type": "text/plain" }
-        });
-        odatajs.oData.read("textHandlerParseTest", function (data) {
-            djstest.assertAreEqual(data, "", "data matches");
-            djstest.done();
-        }, function (err) {
-            djstest.fail("expected success");
-            djstest.done();
-        }, undefined, MockHttpClient);
-    });
-
-    djstest.addTest(function textHandlerSerializeTest() {
-        djstest.assertsExpected(1);
-        MockHttpClient.clear().addRequestVerifier("uri", function (request) {
-            djstest.assertAreEqual(request.body, "text", "text in request");
-        }).addResponse("uri", { statusCode: 200, body: "", headers: { "Content-Type": "text/plain"} });
-        odatajs.oData.request({ requestUri: "uri", method: "POST", data: "text", headers: { "Content-Type": "text/plain"} }, function (data) {
-            djstest.done();
-        }, function (err) {
-            djstest.fail("expected success");
-            djstest.done();
-        }, undefined, MockHttpClient);
-    });
-
-    djstest.addTest(function textHandlerSerializeBlankTest() {
-        djstest.assertsExpected(1);
-        MockHttpClient.clear().addRequestVerifier("uri", function (request) {
-            djstest.assertAreEqual(request.body, "", "text in request");
-        }).addResponse("uri", { statusCode: 200, body: "", headers: { "Content-Type": "text/plain"} });
-        odatajs.oData.request({ requestUri: "uri", method: "POST", data: "", headers: { "Content-Type": "text/plain"} }, function (data) {
-            djstest.done();
-        }, function (err) {
-            djstest.fail("expected success");
-            djstest.done();
-        }, undefined, MockHttpClient);
-    });
-
-    // DATAJS INTERNAL START
-    djstest.addTest(function handlerReadTest() {
-        var tests = [
-            {
-                response: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: "response 0" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
-            },
-            {
-                response: { headers: { "Content-Type": "application/json" }, body: "response 1" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "" }
-            },
-            {
-                response: { headers: { "Content-Type": "otherMediaType" }, body: "response 2" },
-                shouldHit: false,
-                context: { contentType: window.odatajs.oData.handler.contentType("otherMediaType"), dataServiceVersion: "" }
-            },
-            {
-                response: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: "response 3" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
-            },
-            {
-                response: { body: "response 4" },
-                shouldHit: false,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "" }
-            },
-            {
-                response: null,
-                shouldHit: false,
-                context: {}
-            },
-            {
-                response: undefined,
-                shouldHit: false,
-                context: {}
-            }
-        ];
-
-        var i;
-        var test;
-        var testRead = function (handler, body, context) {
-            djstest.assert(test.shouldHit, "method should be hit on item #" + i);
-            djstest.assertAreEqual(handler, testHandler, "handler matches target on item #" + i);
-            djstest.assertAreEqualDeep(context, test.context, "context matches target on item #" + i);
-            djstest.assertAreEqual(body, test.response.body, "body matches target on item #" + i);
-            return body;
-        };
-
-        var testHandler = window.odatajs.oData.handler.handler(testRead, null, "application/json", "4.0");
-
-        var len, expectedAssertCount = 0;
-        for (i = 0, len = tests.length; i < len; i++) {
-            test = tests[i];
-            test.context.handler = testHandler;
-            test.context.response = test.response;
-            if (test.shouldHit) {
-                expectedAssertCount += 4;
-            }
-
-            testHandler.read(test.response, {});
-        }
-
-        djstest.assertsExpected(expectedAssertCount);
-        djstest.done();
-    });
-
-    djstest.addTest(function handlerWriteTest() {
-        var tests = [
-            {
-                request: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, data: "request 0" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
-            },
-            {
-                request: { headers: { "Content-Type": "application/json" }, data: "request 1" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: undefined }
-            },
-            {
-                request: { headers: { "Content-Type": "otherMediaType" }, data: "request 2" },
-                shouldHit: false,
-                context: { contentType: window.odatajs.oData.handler.contentType("otherMediaType"), dataServiceVersion: undefined }
-            },
-            {
-                request: { headers: {}, data: "request 3" },
-                shouldHit: true,
-                context: { contentType: null, dataServiceVersion: undefined }
-            },
-            {
-                request: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, data: "request 4" },
-                shouldHit: true,
-                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
-            },
-            {
-                request: null,
-                shouldHit: false,
-                context: {}
-            },
-            {
-                request: undefined,
-                shouldHit: false,
-                context: {}
-            }
-        ];
-
-        var test;
-        var testWrite = function (handler, data, context) {
-            djstest.assert(test.shouldHit, "method should be hit");
-            djstest.assertAreEqual(handler, testHandler, "handler matches target");
-            djstest.assertAreEqualDeep(context, test.context, "context matches target");
-            djstest.assertAreEqual(data, test.request.data, "body matches target");
-            return data;
-        };
-
-        var testHandler = window.odatajs.oData.handler.handler(null, testWrite, "application/json", "4.0");
-
-        var i, len, expectedAssertCount = 0;
-        for (i = 0, len = tests.length; i < len; i++) {
-            test = tests[i];
-            test.context.handler = testHandler;
-            test.context.request = test.request;
-            if (test.shouldHit) {
-                expectedAssertCount += 4;
-            }
-            testHandler.write(test.request);
-        }
-
-        djstest.assertsExpected(expectedAssertCount);
-        djstest.done();
-    });
-
-    djstest.addTest(function handlerWriteUpdatesRequestContentTypeTest() {
-        var testWrite = function (handler, data, context) {
-            context.contentType = window.odatajs.oData.handler.contentType("my new content type");
-            return data;
-        };
-
-        var testHandler = window.odatajs.oData.handler.handler(null, testWrite, "application/json", "4.0");
-
-        var tests = [
-            { request: { headers: { "Content-Type": "application/json" }, data: "request 0" }, expected: "application/json" },
-            { request: { headers: {}, data: "request 1" }, expected: "my new content type" }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            testHandler.write(tests[i].request);
-            djstest.assertAreEqual(tests[i].request.headers["Content-Type"], tests[i].expected, "request content type is the expected");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function contentTypeTest() {
-        var tests = [
-            { contentType: "application/json;param1=value1;param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
-            { contentType: "application/json; param1=value1; param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
-            { contentType: "application/json;param1=value1; param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
-            { contentType: "application/json; param1=value1;param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
-            { contentType: "application/json", expected: { mediaType: "application/json", properties: {}} },
-            { contentType: ";param1=value1;param2=value2", expected: { mediaType: "", properties: { param1: "value1", param2: "value2"}} }
-        ];
-
-        var i, len, cTypeString;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var actual = window.odatajs.oData.handler.contentType(tests[i].contentType);
-            djstest.assertAreEqual(actual.mediaType, tests[i].expected.mediaType, "Content type media type is parsed correctly");
-            djstest.assertAreEqualDeep(actual.properties, tests[i].expected.properties, "Content type properties are parsed correctly");
-        }
-
-        djstest.assert(! window.odatajs.oData.handler.contentType(undefined), "contentType returns undefined for undefined input");
-        djstest.assert(! window.odatajs.oData.handler.contentType(null), "contentType returns undefined for null input");
-
-        djstest.done();
-    });
-
-    djstest.addTest(function contentTypeToStringTest() {
-        var tests = [
-            { contentType: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"} }, expected: "application/json;param1=value1;param2=value2" },
-            { contentType: { mediaType: "application/json", properties: {} }, expected: "application/json" },
-            { contentType: { mediaType: "", properties: { param1: "value1", param2: "value2"} }, expected: ";param1=value1;param2=value2" }
-        ];
-
-        var i, len, cTypeString;
-        for (i = 0, len = tests.length; i < len; i++) {
-            cTypeString = window.odatajs.oData.handler.contentTypeToString(tests[i].contentType);
-            djstest.assertAreEqual(cTypeString, tests[i].expected, "contentTypeToString returns the correct contentType string");
-        }
-
-        djstest.done();
-    });
-    
-    djstest.addTest(function readServiceDocumentTest(headers) {
-        odatajs.oData.request({
-            requestUri: endpoint,
-            method: "GET",
-            headers: headers
-        }, function (data, response) {
-            djstest.assertAreEqual(data.value[0].name, "Categories", "Verify .name");
-            djstest.assertAreEqual(data.value[0].kind, "EntitySet", "Verify .kind");
-            djstest.assertAreEqual(data.value[0].url, "Categories", "Verify .url");
-
-            djstest.assertAreEqual(data.value[1].name, "Foods", "Verify .name");
-            djstest.assertAreEqual(data.value[1].kind, "EntitySet", "Verify .kind");
-            djstest.assertAreEqual(data.value[1].url, "Foods", "Verify .url");
-            djstest.done();
-        }, unexpectedErrorHandler);
-     });
-          
-    // DATAJS INTERNAL END
-})(this);
\ No newline at end of file


[27/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-tests.js b/datajs/tests/odata-tests.js
deleted file mode 100644
index 0e6e951..0000000
--- a/datajs/tests/odata-tests.js
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-tests.js
-(function (window, undefined) {
-    var northwindService = "http://services.odata.org/Northwind/Northwind.svc/";
-    var localFeed = "./endpoints/FoodStoreDataService.svc/Foods";
-    var northwindFeed = northwindService + "Suppliers";
-
-    var countIFrames = function () {
-        /** Count the number of IFRAMES in the page
-         * @returns {Integer} The number of IFRAMES
-         */
-        return document.getElementsByTagName("IFRAME").length;
-    }
-
-    module("Unit");
-
-    var originalEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
-
-    var restoreJsonpCallback = function () {
-        /** Restores OData.defaultHttpClient.enableJsonpCallback to the library default.
-        */
-        OData.defaultHttpClient.enableJsonpCallback = originalEnableJsonpCallback;
-    };
-
-    djstest.addTest(function checkApiTest() {
-        var internals = window.odatajs.oData.canUseJSONP !== undefined;
-        if (internals) {
-            // Don't even bother - there is a very long list for inter-module communication.
-            // {targetName: "OData", names: "..." }
-            djstest.pass("Do not test public api's when internals are visible");
-        } else {
-            var apis = [
-                { targetName: "datajs", names: "createDataCache,createStore,defaultStoreMechanism" },
-                { targetName: "OData", names: "batchHandler,defaultError,defaultHandler,defaultHttpClient,defaultMetadata,defaultSuccess,jsonHandler,metadataHandler,read,request,textHandler,xmlHandler,parseMetadata" }
-            ];
-
-            for (var i = 0; i < apis.length; i++) {
-                var target = window[apis[i].targetName];
-
-                var actuals = [];
-                for (var actual in target) {
-                    actuals.push(actual);
-                }
-
-                actuals.sort();
-
-                var names = apis[i].names.split(",");
-                names.sort();
-
-                djstest.assertAreEqual(actuals.join(), names.join(), "actual names for " + apis[i].targetName);
-            }
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function simpleLocalReadTest() {
-        odatajs.oData.read(localFeed, function (data, request) {
-            djstest.assert(data !== null, "data !== null");
-            djstest.assert(request !== null, "request !== null");
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function simpleLocalReadWithRequestTest() {
-        odatajs.oData.read({ requestUri: localFeed, headers: { Accept: "application/json"} }, function (data, response) {
-            djstest.assert(data !== null, "data !== null");
-            djstest.assert(response !== null, "response !== null");
-            djstest.assertAreEqual(data, response.data, "data === response.data");
-
-            // Typically application/json;charset=utf-8, but browser may change the request charset (and thus response).
-            var contentType = response.headers["Content-Type"];
-            contentType = contentType.split(';')[0];
-            djstest.assertAreEqual(contentType, "application/json", 'contentType === "application/json"');
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function simpleReadTest() {
-        var oldEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
-        OData.defaultHttpClient.enableJsonpCallback = true;
-
-        var iframesBefore = countIFrames();
-        odatajs.oData.read(northwindService + "Regions", function (data, request) {
-            djstest.assert(data !== null, "data !== null");
-            djstest.assert(request !== null, "request !== null");
-
-            // IFRAME recycling does not work in Opera because as soon as the IFRAME is added to the body, all variables
-            // go out of scope
-            if (!window.opera) {
-                djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra IFRAMEs (baseline: " + iframesBefore + ")");
-            }
-
-            OData.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function simpleReadWithParamsTest() {
-        OData.defaultHttpClient.enableJsonpCallback = true;
-        odatajs.oData.read(northwindFeed + "?$top=3", function (data, request) {
-            djstest.assert(data !== null, "data !== null");
-            djstest.assert(request !== null, "request !== null");
-            restoreJsonpCallback();
-            djstest.done();
-        }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
-    });
-
-    djstest.addTest(function simpleReadWithNoParamsTest() {
-        OData.defaultHttpClient.enableJsonpCallback = true;
-        odatajs.oData.read(northwindFeed + "?", function (data, request) {
-            djstest.assert(data !== null, "data !== null");
-            djstest.assert(request !== null, "request !== null");
-            restoreJsonpCallback();
-            djstest.done();
-        }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
-    });
-
-    djstest.addTest(function jsonpTimeoutTest() {
-        // Verifies that JSONP will timeout, and that the
-        // enableJsonpCallback flag can be set on the request itself.
-        var iframesBefore = countIFrames();
-        odatajs.oData.request({
-            requestUri: northwindFeed + "?$fail=true",
-            timeoutMS: 100,
-            enableJsonpCallback: true
-        }, function (data, request) {
-            djstest.fail("expected an error callback");
-            djstest.done();
-        }, function (err) {
-            djstest.assert(err.message.indexOf("timeout") !== 1, "err.message[" + err.message + "].indexOf('timeout') !== 1");
-            djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra script tags (baseline: " + iframesBefore + ")");
-            djstest.done();
-        });
-    });
-
-    djstest.addTest(function requestDefaultsTest() {
-        // Save current defaults.
-        var oldError = OData.defaultError;
-        var oldSuccess = OData.defaultSuccess;
-        var oldDefaultHandler = OData.defaultHandler;
-        var oldHttpClient = OData.defaultHttpClient;
-
-        OData.defaultSuccess = function (data, response) {
-            djstest.assertAreEqual(response.statusCode, 299, "success method reached when expected");
-        };
-
-        OData.defaultError = function (error) {
-            var response = error.response;
-            djstest.assertAreEqual(response.statusCode, 500, "error method reached when expected");
-        };
-
-        OData.defaultHandler = {
-            read: function (response) {
-                djstest.assertAreEqual(response.statusCode, 299, "default handler read method reached when expected");
-            },
-            accept: "test accept string"
-        };
-
-        OData.defaultHttpClient = MockHttpClient.clear();
-
-        var testUris = [
-            "requestDefaultsTest/request",
-            "requestDefaultsTest/request1",
-            "requestDefaultsTest/error"
-        ];
-
-        MockHttpClient.addRequestVerifier(testUris[0], function (request) {
-            djstest.assertAreEqual(request.method, "GET", "request.method is GET");
-            djstest.assert(request.headers, "request.headers is defined and not null");
-            djstest.assertAreEqual(request.headers.Accept, "test accept string");
-        });
-
-        MockHttpClient.addResponse(testUris[1], { statusCode: 299, body: "test response" });
-        MockHttpClient.addResponse(testUris[2], { statusCode: 500, body: "error response" });
-
-        try {
-            var i, len;
-            for (i = 0, len = testUris.length; i < len; i++) {
-                odatajs.oData.request({ requestUri: testUris[i] });
-            }
-        }
-        finally {
-            // Restore defaults.
-            OData.defaultError = oldError;
-            OData.defaultSuccess = oldSuccess;
-            OData.defaultHandler = oldDefaultHandler;
-            OData.defaultHttpClient = oldHttpClient;
-        }
-
-        djstest.assertsExpected(6);
-        djstest.done();
-    });
-
-    djstest.addTest(function requestUpdateTest() {
-        // Save current defaults.
-        var testHandler = {
-            read: function (response) {
-                response.data = response.body;
-            },
-            write: function (request) {
-                djstest.assertAreEqual(request.method, "POST", "handler write method, request has the correct method");
-            }
-        };
-
-        var testSuccess = function (data, response) {
-            djstest.assertAreEqual(data, "test response", "success callback has the correct data");
-            djstest.assertAreEqual(response.status, 200, "success method reached when expected");
-        };
-
-        var testError = function (error) {
-            var response = error.response;
-            djstest.assertAreEqual(response.status, 500, "error method reached when expected");
-        };
-
-        MockHttpClient.addResponse("requestUpdateTest", { status: 200, body: "test response" });
-        MockHttpClient.addResponse("requestUpdateTest", { status: 500, body: "error response" });
-
-        odatajs.oData.request({ requestUri: "requestUpdateTest", method: "POST" }, testSuccess, testError, testHandler, MockHttpClient);
-
-        djstest.done();
-    });
-
-    djstest.addTest(function parseMetadataTest() {
-        var metadata = '<?xml version="1.0" encoding="utf-8"?>' +
-            '<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">' +
-            '<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">' +
-            '<Schema Namespace="ODataDemo" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">' +
-                '<EntityType Name="Product">' +
-                    '<Key><PropertyRef Name="ID" /></Key>' +
-                    '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
-                    '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
-                    '<Property Name="Description" Type="Edm.String" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
-                    '<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false" />' +
-                    '<Property Name="DiscontinuedDate" Type="Edm.DateTime" />' +
-                    '<Property Name="Rating" Type="Edm.Int32" Nullable="false" />' +
-                    '<Property Name="Price" Type="Edm.Decimal" Nullable="false" />' +
-                    '<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Category_Products" FromRole="Product_Category" />' +
-                '</EntityType>' +
-                '<EntityType Name="Category">' +
-                    '<Key>' +
-                        '<PropertyRef Name="ID" />' +
-                    '</Key>' +
-                    '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
-                    '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true" />' +
-                    '<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Product_Category" FromRole="Category_Products" />' +
-                '</EntityType>' +
-                '<Association Name="Product_Category_Category_Products"><End Type="ODataDemo.Category" Role="Category_Products" Multiplicity="0..1" />' +
-                    '<End Type="ODataDemo.Product" Role="Product_Category" Multiplicity="*" />' +
-                '</Association>' +
-                '<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">' +
-                    '<EntitySet Name="Products" EntityType="ODataDemo.Product" />' +
-                    '<EntitySet Name="Categories" EntityType="ODataDemo.Category" />' +
-                    '<FunctionImport Name="Discount" IsBindable="true" m:IsAlwaysBindable="true">' +
-                        '<Parameter Name="product" Type="ODataDemo.Product" />' +
-                        '<Parameter Name="discountPercentage" Type="Edm.Int32" Nullable="false" />' +
-                    '</FunctionImport>' +
-                    '<AssociationSet Name="Products_Category_Categories" Association="ODataDemo.Product_Category_Category_Products">' +
-                        '<End Role="Product_Category" EntitySet="Products" />' +
-                        '<End Role="Category_Products" EntitySet="Categories" />' +
-                    '</AssociationSet>' +
-                '</EntityContainer>' +
-             '</Schema></edmx:DataServices></edmx:Edmx>';
-
-        var parsedMetadata = OData.parseMetadata(metadata);
-        var expected =
-        {
-            "version": "1.0",
-            "dataServices":
-            {
-                "maxDataServiceVersion": "4.0",
-                "dataServiceVersion": "4.0",
-                "schema": [
-                    {
-                        "namespace": "ODataDemo",
-                        "entityType": [
-                            {
-                                "name": "Product",
-                                "key": { "propertyRef": [{ "name": "ID"}] },
-                                "property": [
-                                    { "name": "ID", "nullable": "false", "type": "Edm.Int32" },
-                                    { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle" },
-                                    { "name": "Description", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationSummary" },
-                                    { "name": "ReleaseDate", "nullable": "false", "type": "Edm.DateTime" }, { "name": "DiscontinuedDate", "type": "Edm.DateTime" },
-                                    { "name": "Rating", "nullable": "false", "type": "Edm.Int32" }, { "name": "Price", "nullable": "false", "type": "Edm.Decimal"}],
-                                "navigationProperty": [
-                                    { "name": "Category", "fromRole": "Product_Category", "toRole": "Category_Products", "relationship": "ODataDemo.Product_Category_Category_Products" }
-                                ]
-                            }, {
-                                "name": "Category",
-                                "key": { "propertyRef": [{ "name": "ID"}] },
-                                "property": [{ "name": "ID", "nullable": "false", "type": "Edm.Int32" }, { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "true", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle"}],
-                                "navigationProperty": [{ "name": "Products", "fromRole": "Category_Products", "toRole": "Product_Category", "relationship": "ODataDemo.Product_Category_Category_Products"}]
-                            }],
-                        "association": [{ "name": "Product_Category_Category_Products", "end": [{ "type": "ODataDemo.Category", "multiplicity": "0..1", "role": "Category_Products" }, { "type": "ODataDemo.Product", "multiplicity": "*", "role": "Product_Category"}]}],
-                        "entityContainer": [{ "name": "DemoService", "isDefaultEntityContainer": "true", "entitySet": [{ "name": "Products", "entityType": "ODataDemo.Product" }, { "name": "Categories", "entityType": "ODataDemo.Category"}], "functionImport": [{ "name": "Discount", "isAlwaysBindable": "true", "isBindable": "true", "parameter": [{ "name": "product", "type": "ODataDemo.Product" }, { "name": "discountPercentage", "nullable": "false", "type": "Edm.Int32"}]}], "associationSet": [{ "name": "Products_Category_Categories", "association": "ODataDemo.Product_Category_Category_Products", "end": [{ "role": "Product_Category", "entitySet": "Products" }, { "role": "Category_Products", "entitySet": "Categories"}]}]}]
-                    }]
-            }
-        };
-        djstest.assertAreEqualDeep(expected, parsedMetadata, "metadata should be parsed to datajs format");
-        djstest.done();
-    });
-
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-xml-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-xml-tests.js b/datajs/tests/odata-xml-tests.js
deleted file mode 100644
index 465b42b..0000000
--- a/datajs/tests/odata-xml-tests.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-xml-tests.js
-
-(function (window, undefined) {
-
-    // DATAJS INTERNAL START
-
-    djstest.addTest(function getURIInfoTest() {
-        var tests = [
-            { input: "https://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "https:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
-            { input: "http://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "http:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
-            { input: "https:", expected: { scheme: "https:", isAbsolute: true} },
-            { input: "http:", expected: { scheme: "http:", isAbsolute: true} },
-            { input: "//host.com", expected: { authority: "//host.com", isAbsolute: false} },
-            { input: "path1", expected: { path: "path1", isAbsolute: false} },
-            { input: "?query", expected: { query: "?query", isAbsolute: false} },
-            { input: "#fragment", expected: { fragment: "#fragment", isAbsolute: false} },
-            { input: undefined, expected: { isAbsolute: false} },
-            { input: "", expected: { isAbsolute: false} },
-            { input: null, expected: { isAbsolute: false} }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var actual = odatajs.utils.getURIInfo(tests[i].input);
-            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected URI parts");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function normalizeURICaseTest() {
-        var tests = [
-            { uri: "hTTp://HOST.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment", expected: "http://host.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment" },
-            { uri: "http://fabrikam%20user%3AHisPassWord@www.FaBriKAM.com:5895/Path%3A%201?q1=hi%20%3Ato%20you", expected: "http://fabrikam%20user%3aHisPassWord@www.fabrikam.com:5895/Path%3a%201?q1=hi%20%3ato%20you" },
-            { uri: "/PATH1/PATH2?P1=AbC#fraGment", expected: "/PATH1/PATH2?P1=AbC#fraGment" },
-            { uri: "HttP://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/"), expected: "http://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/").toLowerCase() }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var actual = odatajs.utils.normalizeURICase(tests[i].uri, tests[i].base);
-            djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected URI");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function normalizeURITest() {
-        var tests = [
-            { uri: "http://host.com/path1#fragment", base: "http://base", expected: "http://host.com/path1#fragment" },
-            { uri: "//host.com/path1?p1=0", base: "http://base?p2=1", expected: "http://host.com/path1?p1=0" },
-            { uri: "?p1=0#fragment", base: "http://base/basepath", expected: "http://base/basepath?p1=0#fragment" },
-            { uri: "?p1=0#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p1=0#fragment" },
-            { uri: "#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p2=1#fragment" },
-            { uri: "/path1/path2?p1=0", base: "http://base/basePath", expected: "http://base/path1/path2?p1=0" },
-            { uri: "path1/path2?p1=0", base: "http://base/basepath", expected: "http://base/path1/path2?p1=0" },
-            { uri: "path1/path2?p1=0", base: "http://base/basepath/basepath2", expected: "http://base/basepath/path1/path2?p1=0" },
-            { uri: "", base: "http://base/basepath?p1=0#fragment", expected: "http://base/basepath?p1=0" },
-            { uri: "path1/path2?p1=0", base: "", expected: "path1/path2?p1=0" },
-            { uri: "/a/b/c/./../../g", base: "http://base/basepath", expected: "http://base/a/g" },
-            { uri: "a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
-            { uri: "../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
-            { uri: "./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
-            { uri: "/../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
-            { uri: "/./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var actual = odatajs.utils.normalizeURI(tests[i].uri, tests[i].base);
-            djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected normalized URI");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlParseTest() {
-        var xml = '<root xmlns:n1="http://namespace1" xml:base="http://base.org" />';
-        var root = odatajs.xml.xmlParse(xml);
-        djstest.assert(root, "xml._parse didn't return a xml dom object");
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlbaseURITest() {
-        var xml = "\
-         <root xmlns:n1=\"http://namespace1\" \r\n\
-               xml:base=\"http://base.org\"> \r\n\
-           <element base=\"this is not a xml base attribute\" /> \r\n\
-         </root>\r\n";
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-        var child = odatajs.xml.xmlFirstChildElement(root);
-
-        djstest.assertAreEqual(odatajs.xml.xmlBaseURI(root), "http://base.org", "xml._baseURI didn't return the expected value");
-        djstest.assert(!odatajs.xml.xmlBaseURI(child), "xml._baseURI returned a value when it wasn't expected");
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlAttributeValueTest() {
-        var xml = "\
-     <root xmlns:n1=\"http://namespace1\" \r\n\
-           xml:base=\"http://base.org\"> \r\n\
-        <element attribute=\"value\" n1:nsAttribute=\"nsValue\" /> \r\n\
-     </root> \r\n";
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-        var child = odatajs.xml.xmlFirstChildElement(root);
-
-        djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "attribute"), "value", "xml._attribute didn't return the expected value for attribute");
-        djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "nsAttribute", "http://namespace1"), "nsValue", "xml._attribute didn't return the expected value for nsAttribute");
-        djstest.assert(!odatajs.xml.xmlAttributeValue(child, "nsAttribute"), "xml._attribute returned a value for nsAttribute without specifying a namespace");
-
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlLocalNameTest() {
-        var xml = "<root xmlns:n1=\"http://namespace1\" /> \r\n";
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-
-        djstest.assertAreEqual(odatajs.xml.xmlLocalName(root), "root", "xml._localName didn't return the expected localName of the root element");
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlFirstChildElement() {
-        var xml = "\
-         <root xmlns:n1=\"http://namespace1\" \r\n\
-               xml:base=\"http://base.org\"> \r\n\
-           <element1 /> \r\n\
-           <element2 /> \r\n\
-         </root>\r\n";
-
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-        var child = odatajs.xml.xmlFirstChildElement(root);
-
-        djstest.assertAreEqual(odatajs.xml.xmlLocalName(child), "element1", "xml.firstElement returned didn't return the expected element");
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlChildElementsTest() {
-        var xml = "\
-         <root xmlns:n1=\"http://namespace1\" \r\n\
-               xml:base=\"http://base.org\"> \r\n\
-           <element1 /> \r\n\
-           <element2 xml:base=\"http://otherBase.org\" /> \r\n\
-           <n1:element3 xml:base=\"path1/path2\" /> \r\n\
-         </root>\r\n";
-
-        var expected = [
-            { localName: "element1", nsURI: null },
-            { localName: "element2", nsURI: null },
-            { localName: "element3", nsURI: "http://namespace1" }
-        ];
-
-        var actual = [];
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-    
-        odatajs.xml.xmlChildElements(root, function (child) {
-            djstest.log("in child elements callback");
-            actual.push({
-                localName: odatajs.xml.xmlLocalName(child),
-                nsURI: odatajs.xml.xmlNamespaceURI(child)
-            });
-        });
-
-        djstest.assertAreEqualDeep(actual, expected, "xml.childElements didn't return the expected elements");
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlAttributesTest() {
-        var xml = "\
-         <root xmlns:n1=\"http://namespace1\" \r\n\
-               xml:base=\"http://base.org\" \r\n\
-               attribute=\"value\" \r\n\
-               n1:nsAttribute=\"nsValue\" />\r\n";
-
-        var expected = {
-            n1: { localName: "n1", nsURI: "http://www.w3.org/2000/xmlns/", value: "http://namespace1" },
-            base: { localName: "base", nsURI: "http://www.w3.org/XML/1998/namespace", value: "http://base.org" },
-            attribute: { localName: "attribute", nsURI: null, value: "value" },
-            nsAttribute: { localName: "nsAttribute", nsURI: "http://namespace1", value: "nsValue" }
-        };
-
-        var actual = {};
-
-        var doc = odatajs.xml.xmlParse(xml);
-        var root = odatajs.xml.xmlFirstChildElement(doc);
-
-        odatajs.xml.xmlAttributes(root, function (attribute) {
-            djstest.log("in child elements callback");
-            var localName = odatajs.xml.xmlLocalName(attribute);
-            actual[localName] = {
-                localName: localName, 
-                nsURI: odatajs.xml.xmlNamespaceURI(attribute),
-                value: attribute.value
-            };
-        });
-
-        djstest.assertAreEqualDeep(actual, expected, "xml.attributes returned didn't return the expected attributes");
-        djstest.done();
-    });
-
-    djstest.addTest(function hasLeadingOrTrailingWhitespaceTest() {
-        // tests are in text / expected format.
-        var tests = [
-            { t: "", r: false },
-            { t: " ", r: true },
-            { t: "text", r: false },
-            { t: "text with spaces", r: false },
-            { t: "not \r\n really", r: false },
-            { t: " at start", r: true },
-            { t: "at end ", r: true },
-            { t: "end\r", r: true },
-            { t: "end\n", r: true },
-            { t: "end\r\n", r: true }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var result = odatajs.xml.hasLeadingOrTrailingWhitespace(tests[i].t);
-            djstest.assertAreEqual(result, tests[i].r, "match for " + tests[i].t);
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function xmlInnerTextTest() {
-        // Tests are in test / expected format.
-        var tests = [
-            { t: "<t>text</t>", r: "text" },
-            { t: "<t>text with a <![CDATA[cdata block]]></t>", r: "text with a cdata block" },
-            { t: "<t> text </t>", r: " text " },
-            { t: "<t> </t>", r: null },
-            { t: "<t> <b>text</b> </t>", r: null },
-            { t: "<t> preceding</t>", r: " preceding" },
-            { t: "<t xml:space='preserve'> <b>text</b> </t>", r: "  " },
-            { t: "<t xml:space='default'> <b>text</b> </t>", r: null}
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var test = tests[i];
-            var doc = odatajs.xml.xmlParse(test.t);
-            var actual = odatajs.xml.xmlInnerText(doc);
-            djstest.assertAreEqual(actual, test.r, "test for [" + test.t + "]");
-        }
-
-        djstest.done();
-    });
-
-    // DATAJS INTERNAL END
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/run-tests.wsf
----------------------------------------------------------------------
diff --git a/datajs/tests/run-tests.wsf b/datajs/tests/run-tests.wsf
deleted file mode 100644
index 263bae0..0000000
--- a/datajs/tests/run-tests.wsf
+++ /dev/null
@@ -1,435 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<job>
-    <runtime>
-        <description>Test driver for running datajs tests - run from the same directory as the script</description>
-        <comment>
-            Result codes:
-            0 - success
-            1 - failed to launch tests
-            2 - tests failed
-        </comment>
-    </runtime>
-    <script language="JScript" src="test-list.js" />
-    <script language="JScript">
-
-        var exitCode;
-        var fso = WScript.CreateObject("Scripting.FileSystemObject");
-        var shell = WScript.CreateObject("WScript.Shell");
-
-        function attempt(action, interval, maxAttempts) {
-            /// <summary>Attempt an action at an interval, optionally for a maximum number of attempts</summary>
-            /// <param name="action">Action callback; should return boolean whether it succeeded</param>
-            /// <param name="interval">Interval (milliseconds) between attempts</param>
-            /// <param name="maxAttempts">(Optional) Maximum number of attempts. Infinite if undefined.</param>
-            /// <returns>Whether the action succeeded</returns>
-            var done = false;
-            var attempts = 0;
-            while (!done) {
-                var success = action();
-                if (maxAttempts !== undefined) {
-                    attempts++;
-                }
-                done = success === true || (maxAttempts !== undefined && attempts >= maxAttempts);
-                if (!done) {
-                    WScript.Sleep(interval);
-                }
-            }
-
-            return success;
-        }
-
-        function parseJson(text) {
-            /// <summary>Parses a JSON document, removes the 'd' wrapper.</summary>
-            try {
-                return eval("(" + text + ")").d;
-            } catch (e) {
-                throw { message: "Error parsing JSON: [" + text + "]" };
-            }
-        }
-
-        function SaveTextToFile(content, path) {
-            /// <summary>Saves text content into a file.</summary>
-            /// <param name="content" type="String">Content to save.</param>
-            /// <param name="path" type="String">Path of file to save into.</param>
-            var ForReading = 1, ForWriting = 2;
-            var file = fso.OpenTextFile(path, ForWriting, true, -1 /* open as unicode */);
-            file.Write(content);
-            file.Close();
-        }
-
-        function GetUrlSync(url) {
-            var xhr;
-            xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
-            xhr.open("GET", url, false);
-            xhr.send();
-            return xhr.responseText;
-        }
-
-        function LaunchBrowser(browsers, serviceRoot, followingPages, url, testRunId, outputDirectory) {
-            /// <summary>Launches a browsers and waits until the service tells us the run is complete.</summary>
-            /// <param name="browsers">Browsers to run.</param>
-            /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
-            /// <param name="followingPages" type="Array">Array of pages that should follow the given url.</param>
-            /// <param name="url" type="String">URL of the page to start the browser on.</param>
-            /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
-            /// <param name="outputDirectory" type="String">Directory in which to output screenshots.</param>
-
-            for (browserName in browsers) {
-                var xhr;
-                var markInProgressUrl = serviceRoot + "MarkInProgress?testRunId=" + testRunId;
-                GetUrlSync(markInProgressUrl);
-
-                // Add all the pages that follow the given URL.
-                if (followingPages && followingPages.length > 0) {
-                    var addFilesUrl = serviceRoot + "AddTestPages?testRunId=" + testRunId + "&pages=" + followingPages.join();
-                    GetUrlSync(addFilesUrl);
-                }
-
-                var setPrefixUrl = serviceRoot + "SetTestNamePrefix?testRunId=" + testRunId + "&prefix=" + browserName + "-";
-                GetUrlSync(setPrefixUrl);
-
-                exitCode = 0;
-                var response;
-
-                // Only the first location found from the browsers array is used. If none of the listed locations of the browser exist and the browser argument was 
-                // explicitly used then an exception is thrown.
-                var browserFound = false;
-                for (var i = 0; i < browsers[browserName].length && !browserFound; i++) {
-                    var path = shell.ExpandEnvironmentStrings(browsers[browserName][i]);
-                    if (fso.FileExists(path)) {
-                        browserFound = true;
-
-                        WScript.Echo("Navigating to " + url + " with " + path);
-                        var browser = shell.Exec("\"" + path + "\" " + url);
-
-                        var checkRunUrl = serviceRoot + "IsTestRunInProgress?testRunId=" + testRunId;
-                        WScript.Echo("Monitoring status on " + checkRunUrl);
-
-                        var interval = 2000;
-                        var maxAttempts = WScript.Arguments.Named.Exists("timeout") ? Math.floor((WScript.Arguments.Named.Item("timeout") / interval) * 1000) : undefined;
-                        var success = attempt(function () {
-                            return parseJson(GetUrlSync(checkRunUrl)) !== true;
-                        }, interval, maxAttempts);
-                        if (!success) {
-                            WScript.Echo("Timed out waiting for test to complete");
-                            exitCode = 2;
-                        }
-
-                        RunCommand("taskkill.exe /pid " + browser.ProcessID, true);
-                    }
-                }
-
-                // If the "/browsers" argument was explicitly used and all location have been checked, then throw an exception.
-                if (!browserFound) {
-                    var message = "Unable to find browser at: " + path;
-                    if (WScript.Arguments.Named.Exists("browsers")) {
-                        throw { message: message };
-                    } else {
-                        WScript.Echo(message);
-                    }
-                }
-            }
-        }
-
-        function WriteTestRunResults(serviceRoot, testRunId, outputDirectory) {
-            /// <summary>Writes the results of the test run to disk and updates the overall status.</summary>
-            /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
-            /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
-            /// <param name="outputDirectory" type="String">Directory in which to write test result files.</param>
-
-            var getResultsUrl = serviceRoot + "GetTestRunResults?testRunId=" + testRunId;
-            WScript.Echo("Querying " + getResultsUrl);
-
-            var response = GetUrlSync(getResultsUrl);
-
-            var resultsPath = outputDirectory + "\\results.trx";
-            WScript.Echo("Writing results.trx file to " + resultsPath);
-            SaveTextToFile(response, resultsPath);
-
-            var xml = new ActiveXObject("Msxml2.DOMDocument.6.0");
-            xml.loadXML(response);
-            xml.setProperty("SelectionNamespaces", "xmlns:trx='http://microsoft.com/schemas/VisualStudio/TeamTest/2010'");
-            xml.setProperty("SelectionLanguage", "XPath");
-            var resultNode = xml.selectSingleNode("/trx:TestRun/trx:ResultSummary");
-            if (resultNode === null) {
-                throw { message: "Unable to find results summary" };
-            }
-
-            var outcome = resultNode.getAttribute("outcome");
-            if (outcome !== "Passed") {
-                WScript.Echo("Outcome: " + outcome);
-                var failedTests = xml.selectNodes("/trx:TestRun/trx:Results/trx:UnitTestResult[@outcome != 'Passed']/@testName");
-                for (var i = 0; i < failedTests.length; i++) {
-                    WScript.Echo("  Failed test: " + failedTests[i].value);
-                }
-                exitCode = 2;
-            } else {
-                WScript.Echo("All tests passed.");
-            }
-        }
-
-        function CheckUrl(url) {
-            var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
-            xhr.open("GET", url, false);
-            var success = false;
-            try {
-                xhr.send();
-                success = (xhr.status === 200);
-                if (!success) {
-                    WScript.Echo("status: " + xhr.status + " - " + xhr.statusText);
-                }
-            } catch (err) {
-                WScript.Echo("error: " + err.message);
-            }
-
-            return success;
-        }
-
-        function ExpandWildcard(path) {
-            var wcRegEx = /\\\*\*?\\/;
-            var wcMatch = wcRegEx.exec(path);
-
-            var paths = [];
-            if (wcMatch !== null) {
-                var recursive = wcMatch[0] === "\\**\\";
-                var basePath = path.substring(0, wcMatch.index);
-                var relativePath = path.substring(wcMatch.index + wcMatch[0].length);
-
-                if (fso.FolderExists(basePath)) {
-                    var folder = fso.GetFolder(basePath);
-                    var subFolders = new Enumerator(folder.SubFolders);
-
-                    paths = paths.concat(ExpandWildcard(basePath + "\\" + relativePath));
-
-                    for (; !subFolders.atEnd(); subFolders.moveNext()) {
-                        var expandedPath = subFolders.item().Path + "\\"
-                        if (recursive) {
-                            expandedPath += "**\\";
-                        }
-                        expandedPath += path.substring(wcMatch.index + wcMatch[0].length);
-                        paths = paths.concat(ExpandWildcard(expandedPath));
-                    }
-                }
-            } else {
-                paths.push(path);
-            }
-            return paths;
-        }
-
-        function FindFirstPath(candidates) {
-            /// <summary>Finds the first path present from a candidate list.</summary>
-            /// <param name="candidates" type="Array">Array of paths (possibly with environment variables).</param>
-            /// <returns type="String">The first folder on disk found; null if none are present.</returns>
-
-            var paths = [];
-
-            for (var i = 0; i < candidates.length; i++) {
-                var path = shell.ExpandEnvironmentStrings(candidates[i]);
-                paths = paths.concat(ExpandWildcard(path));
-            }
-
-            for (var i = 0; i < paths.length; i++) {
-                if (fso.FolderExists(paths[i]) || fso.FileExists(paths[i])) {
-                    return paths[i];
-                }
-            }
-            return null;
-        }
-
-        function RunCommand(command, waitForExit, expectedExitCode) {
-            /// <summary>Runs a command or program</summary>
-            /// <param name="command" type="String">Command to run</param>
-            /// <param name="waitForExit" type="Boolean">Whether to wait for program to exit</param>
-            /// <param name="expectedExitCode" type="Integer">If waitForExit is true, throw if the exit code is not expected</param>
-            /// <returns type="Integer">The exitcode if waitForExit is true; always 0 if waitForExit is false</returns>
-            WScript.Echo("[cmd] " + command);
-            var exitCode = shell.Run(command, 0, waitForExit);
-            if (expectedExitCode !== undefined && exitCode !== expectedExitCode) {
-                throw { message: "Process exited with unexpected exit code. (Expected: " + expectedExitCode + ", Actual: " + exitCode + ")" };
-            } else {
-                return exitCode;
-            }
-        }
-
-        function SetupWebDevServer() {
-            /// <summary>Starts up IIS Express if it's not running.</summary>
-            /// <returns type="String">The URL to the server root.</returns>
-            var siteName = "DataJS Development Site";
-            var appName = "datajs";
-            var port = "8989";
-            var result = "http://" + shell.ExpandEnvironmentStrings("%COMPUTERNAME%").toLowerCase() + ":" + port + "/" + appName + "/";
-            var url = result + "tests/common/TestLogger.svc";
-
-            var success = CheckUrl(url);
-
-            if (!success) {
-                // Assume that we need to launch this.
-                var src = fso.GetAbsolutePathName("..");
-
-                var folder = FindFirstPath([
-                    "%ProgramFiles(x86)%\\IIS Express",
-                    "%ProgramFiles%\\IIS Express"]);    
-
-                if (!folder) {
-                    throw { message: "Unable to find path to IIS Express" };
-                }
-
-                var appCmd = "\"" + folder + "\\appcmd.exe\"";
-                var iisExpress = "\"" + folder + "\\iisexpress.exe\"";
-
-                // Delete site if it already exists
-                WScript.Echo("Checking if site '" + siteName + "' already exists...");
-                if (RunCommand(appCmd + " list site \"" + siteName + "\"", true) === 0) {
-                    WScript.Echo("Deleting existing site '" + siteName + "'...");
-                    RunCommand(appCmd + " delete site \"" + siteName + "\"", true, 0);
-                }
-
-                // Create site and app
-                WScript.Echo("Creating site '" + siteName + "'...");
-                RunCommand(appCmd + " add site /name:\"" + siteName + "\" /bindings:http/*:" + port + ": /physicalPath:%IIS_BIN%\\AppServer\\empty_wwwroot", true, 0);
-
-                WScript.Echo("Creating application '" + appName + "'...");
-                RunCommand(appCmd + " add app /site.name:\"" + siteName + "\" /path:\"/" + appName + "\" /physicalPath:\"" + src + "\"", true, 0);
-
-                // Start the server
-                WScript.Echo("Starting IIS Express server...");
-                RunCommand(iisExpress + " /site:\"" + siteName + "\" /trace:error");
-
-                WScript.Sleep(2 * 1000);
-                success = attempt(function () {
-                    WScript.Echo("Waiting for server to come up, looking for " + url + " ...");
-                    return CheckUrl(url);
-                }, 5 * 1000, 3);
-
-                if (!success) {
-                    throw { message: "Unable to verify the URL at " + url };
-                }
-            }
-            return result;
-        }
-
-        function CreateTestRunId(serviceRoot) {
-            /// <summary>Creates a new test run ID from the service.</summary>
-            /// <param name="serviceRoot" type="String">Root of logger service.</param>
-            /// <returns type="String">The test run ID created.</returns>
-            var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
-            var url = serviceRoot + "CreateTestRun";
-            xhr.open("GET", url, false);
-            WScript.Echo("URL: " + url);
-            xhr.send();
-
-            var response = xhr.responseText;
-            var result = parseJson(response);
-            return result;
-        }
-
-        function GetBrowsers() {
-            /// <summary>Gets the browsers that should be used for running the tests.</summary>
-            /// <returns type="Object">Dictionary object containing the browser and its executable path as key value pairs.</returns>
-            var localAppData = fso.FolderExists(shell.ExpandEnvironmentStrings("%LOCALAPPDATA%")) ? "%LOCALAPPDATA%" : "%USERPROFILE%\\Local Settings\\Application Data";
-            var programFiles = fso.FolderExists(shell.ExpandEnvironmentStrings("%ProgramFiles(x86)%")) ? "%ProgramFiles(x86)%" : "%ProgramFiles%";
-            var browsers = {
-                IE8: [programFiles + "\\Internet Explorer\\iexplore.exe"],
-                Firefox4: [programFiles + "\\Mozilla Firefox\\firefox.exe"],
-                Chrome: [programFiles + "\\Google\\Chrome\\Application\\chrome.exe", localAppData + "\\Google\\Chrome\\Application\\chrome.exe"],
-                Safari5: [programFiles + "\\Safari\\safari.exe"],
-                Opera: [programFiles + "\\Opera\\opera.exe"]
-            };
-
-            var browsersToRun = {};
-
-            if (WScript.Arguments.Named.Exists("browsers")) {
-                browserNames = WScript.Arguments.Named.Item("browsers").split(',');
-                for (i in browserNames) {
-                    var browserName = browserNames[i];
-                    if (browsers[browserName]) {
-                        browsersToRun[browserName] = browsers[browserName];
-                    } else {
-                        throw { message: "Unknown browser: " + browserName };
-                    }
-                }
-            }
-            else {
-                browsersToRun = browsers;
-            }
-
-            return browsersToRun;
-        }
-
-        function GetTestFilesList() {
-            /// <summary>Gets the list of test files that are going to be executed in the test run.</summary>
-            /// <returns type="Array">The list of test files.</returns>
-            var testFilesList = null;
-            if (WScript.Arguments.Named.Exists("testFiles")) {
-                testFilesList = WScript.Arguments.Named.Item("testFiles").split(',');
-            }
-
-            if (testFilesList === null) {
-                testFilesList = getAllTestFiles();
-            }
-
-            WScript.Echo("Test files to be executed: " + testFilesList.toString());
-            return testFilesList;
-        }
-
-        function GetOutputDirectory() {
-            /// <summary>Gets the test run output directory.</summary>
-            /// <returns type="String">Output directory.</returns>
-            var result;
-            if (WScript.Arguments.Named.Exists("outputDirectory")) {
-                result = WScript.Arguments.Named.Item("outputDirectory");
-            } else {
-                result = shell.ExpandEnvironmentStrings("%DJSOUT%\\JSLib.sln\\tests");
-            }
-
-
-            return result;
-        }
-
-        try {
-            var root = SetupWebDevServer();
-            var serviceRoot = root + "tests/common/TestLogger.svc/";
-            var testRunId = CreateTestRunId(serviceRoot);
-            WScript.Echo("Test Run ID: " + testRunId);
-
-            var testFilesList = GetTestFilesList();
-            var browsers = GetBrowsers();
-            var outputDirectory = GetOutputDirectory();
-
-            if (testFilesList.length > 0) {
-                var url = root + "tests/" + testFilesList[0] + "?testRunId=" + testRunId;
-                LaunchBrowser(browsers, serviceRoot, testFilesList.splice(1, testFilesList.length), url, testRunId, outputDirectory);
-                WriteTestRunResults(serviceRoot, testRunId, outputDirectory);
-            }
-            else {
-                WScript.Echo("No test files specified to run.");
-            }
-        } catch (e) {
-            WScript.Echo("Error running tests");
-            for (var p in e) WScript.Echo(p + ": " + e[p]);
-            exitCode = 1;
-        }
-
-        WScript.Quit(exitCode);
-
-    </script>
-</job>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/store-indexeddb-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/store-indexeddb-tests.js b/datajs/tests/store-indexeddb-tests.js
deleted file mode 100644
index 47690a4..0000000
--- a/datajs/tests/store-indexeddb-tests.js
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-// store-indexeddb-tests.js
-
-(function (window, undefined) {
-    // DATAJS INTERNAL START
-    var unexpectedSuccess = function (key, value) {
-        djstest.fail("Unexpected call to success handler: key = " + key + ", value = " + value);
-        djstest.done();
-    };
-
-    var unexpectedError = function (e) {
-        djstest.fail("Unexpected call to error handler: " + djstest.toString(e));
-        djstest.done();
-    };
-
-    var storeCounter = 0;
-    var storeName = "test";
-
-    var getNextStoreName = function () {
-        storeCounter++;
-        return getCurrentStoreName();
-    };
-
-    var getCurrentStoreName = function(){
-        return storeName + storeCounter;
-    };
-
-    var oldWindowOnError;
-
-    if (djstest.indexedDB) {
-        module("Unit", {
-            setup: function () {
-                djstest.wait(function (done) {
-                    djstest.cleanStoreOnIndexedDb([{ name: getNextStoreName() }], done);
-                });
-
-                // FireFox 7.0.1 bubbles an error event when there is an IndexedDB error, even when the error has been handled graciously.
-                // This is a work around to keep QUnit from reporting false failures in IndexedDB negative tests.
-                oldWindowOnError = window.onerror;
-                window.onerror = null;
-            },
-            teardown: function () {
-                var store = this.store;
-                if (store) {
-                    store.close();
-                }
-
-                djstest.wait(function (done) {
-                    djstest.cleanStoreOnIndexedDb([store], done);
-                });
-
-
-                // Restore QUnit's onerror handler.
-                window.onerror = oldWindowOnError;
-            }
-        });
-
-        djstest.addTest(function testIndexedDBStoreConstructor() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            djstest.assertAreEqual(store.name, getCurrentStoreName());
-            djstest.assertAreEqual(store.mechanism, "indexeddb");
-            djstest.done();
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddGet() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                djstest.assertAreEqual(key, "key");
-                djstest.assertAreEqual(value, "value");
-                store.read("key", function (key, value) {
-                    djstest.assertAreEqual(key, "key");
-                    djstest.assertAreEqual(value, "value");
-                    djstest.done();
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddUpdateGet() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.update("key", "value2", function (key, value) {
-                    djstest.assertAreEqual(key, "key");
-                    djstest.assertAreEqual(value, "value2");
-                    store.read("key", function (key, value) {
-                        djstest.assertAreEqual(key, "key");
-                        djstest.assertAreEqual(value, "value2");
-                        djstest.done();
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddOrUpdateGet() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.addOrUpdate("key", "value", function (key, value) {
-                djstest.assertAreEqual(key, "key");
-                djstest.assertAreEqual(value, "value");
-                store.addOrUpdate("key", "value2", function (key, value) {
-                    djstest.assertAreEqual(key, "key");
-                    djstest.assertAreEqual(value, "value2");
-                    store.read("key", function (key, value) {
-                        djstest.assertAreEqual(key, "key");
-                        djstest.assertAreEqual(value, "value2");
-                        djstest.done();
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddRemoveContains() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.contains("key", function (result) {
-                    djstest.assert(result);
-                    store.remove("key", function () {
-                        djstest.pass("key removed");
-                        store.contains("key", function (result) {
-                            djstest.assert(!result);
-                            djstest.done();
-                        }, unexpectedError);
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddConsecutiveGetAllKeys() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.add("key2", "value2", function (key, value) {
-                    store.add("key3", "value3", function (key, value) {
-                        store.getAllKeys(function (keys) {
-                            djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
-                            djstest.done();
-                        }, unexpectedError);
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddArrayClear() {
-            var addedKeys = ["key", "key2", "key3"];
-            var addedValues = ["value", "value2", "value3"];
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add(addedKeys, addedValues, function (keys, values) {
-                djstest.assertAreEqualDeep(keys, addedKeys);
-                djstest.assertAreEqualDeep(values, addedValues);
-                store.clear(function () {
-                    store.getAllKeys(function (keys) {
-                        djstest.assertAreEqualDeep(keys, []);
-                        djstest.done();
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddArrayUpdateArrayGetArray() {
-            var addedKeys = ["key", "key2", "key3"];
-            var addedValues = ["value", "value2", "value3"];
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add(addedKeys, addedValues, function (keys, values) {
-                djstest.assertAreEqualDeep(keys, addedKeys);
-                djstest.assertAreEqualDeep(values, addedValues);
-                var updatedKeys = ["key", "key3"];
-                var updatedValues = ["newValue", "newValue3"];
-                store.update(updatedKeys, updatedValues, function (keys, values) {
-                    djstest.assertAreEqualDeep(keys, updatedKeys);
-                    djstest.assertAreEqualDeep(values, updatedValues);
-                    store.read(addedKeys, function (keys, values) {
-                        djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
-                        djstest.assertAreEqualDeep(values, ["newValue", "value2", "newValue3"]);
-                        djstest.done();
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddOrUpdateArrayGetArray() {
-            var expectedKeys = ["key", "key2", "key3"];
-            var expectedValues = ["value", "value2", "value3"];
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key2", "value", function (key, value) {
-                store.addOrUpdate(expectedKeys, expectedValues, function (keys, values) {
-                    djstest.assertAreEqualDeep(keys, expectedKeys);
-                    djstest.assertAreEqualDeep(values, expectedValues);
-                    store.read(keys, function (keys, values) {
-                        djstest.assertAreEqualDeep(values, expectedValues);
-                        djstest.done();
-                    }, unexpectedError);
-                }, unexpectedError);
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddDuplicate() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.add("key", "value2", unexpectedSuccess, function (err) {
-                    djstest.pass("Error callback called as expected");
-                    djstest.done();
-                });
-            }, unexpectedError);
-        });
-
-        djstest.addTest(function testIndexedDBStoreAddArrayDuplicate() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add(["key", "key2", "key"], ["value", "value2", "value3"], unexpectedSuccess, function (err) {
-                djstest.pass("Error callback called as expected");
-                djstest.done();
-            });
-        });
-
-        djstest.addTest(function testIndexedDBStoreGetArrayNonExistent() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.read(["key", "badkey"], function (keys, values) {
-                    djstest.assertAreEqualDeep(keys, ["key", "badkey"]);
-                    djstest.assertAreEqualDeep(values, ["value", undefined]);
-                    djstest.done();
-                }, unexpectedError);
-            });
-        });
-
-        djstest.addTest(function testIndexedDBStoreUpdateNonExistent() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.update("badkey", "badvalue", unexpectedSuccess, function (err) {
-                djstest.pass("Error callback called as expected");
-                djstest.done();
-            });
-        });
-
-        djstest.addTest(function testIndexedDBStoreUpdateArrayNonExistent() {
-            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
-            store.add("key", "value", function (key, value) {
-                store.update(["key", "badkey"], ["value", "badvalue"], unexpectedSuccess, function (err) {
-                    djstest.pass("Error callback called as expected");
-                    store.read("key", function (key, value) {
-                        djstest.assertAreEqual(value, "value", "value was not changed");
-                        djstest.done();
-                    }), unexpectedError;
-                });
-            }, unexpectedError);
-        });
-    }
-    // DATAJS INTERNAL END
-})(this);
\ No newline at end of file


[09/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/EpmDataService.svc b/odatajs/tests/endpoints/EpmDataService.svc
new file mode 100644
index 0000000..316c9ae
--- /dev/null
+++ b/odatajs/tests/endpoints/EpmDataService.svc
@@ -0,0 +1,336 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.EpmDataService" %>
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// A data service that uses EPM
+    /// </summary>
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class EpmDataService : DataService<EpmDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+
+        }
+        
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+    }
+
+    public class EpmDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<MappedEntry> MappedEntries
+        {
+            get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<ReplicatedEntry> ReplicatedEntries
+        {
+            get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<BaseEntry> HierarchicalEntries
+        {
+            get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            MappedEntry[] mappedEntries = new MappedEntry[]
+            {
+                new MappedEntry
+                {
+                    ID = 0,
+                    UnmappedField = "Unmapped0",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail0",
+                        Name = "AuthorName0",
+                        Uri = "http://www.example.com/AuthorUri",
+                        Contributor = new Contributor
+                        {
+                            Email = "ContributorEmail0",
+                            Name = "ContributorName0",
+                            Uri = "http://www.example.com/ContributorUri",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights0",
+                    Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
+                    Title = "Title<b>0</b>",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement0",
+                    CustomAttribute = "CustomAttribute0",
+                    NestedElement1 = "NestedElement1_0",
+                    NestedElement2 = "NestedElement2_0",
+                    CommonAttribute1 = "CommonAttribute1_0",
+                    CommonAttribute2 = "CommonAttribute2_0",
+                    Location = new Location
+                    {
+                        Lat = 3.14f,
+                        Long = 2.72f
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 1,
+                    UnmappedField = null,
+                    Author = new Author
+                    {
+                        Email = null,
+                        Name = string.Empty,
+                        Uri = "http://www.example.com/AuthorUri1",
+                        Contributor = new Contributor
+                        {
+                            Email = null,
+                            Name = string.Empty,
+                            Uri = "http://www.example.com/ContributorUri1",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = null,
+                    Summary = "",
+                    Title = "Title<i>1</i>",
+                    Updated = "2111-01-01T00:00:00-08:00",
+                    CustomElement = null,
+                    NestedElement1 = string.Empty,
+                    NestedElement2 = "NestedElement2_1",
+                    CustomAttribute = null,
+                    CommonAttribute1 = string.Empty,
+                    CommonAttribute2 = "CommonAttribute2_1",
+                    Location = new Location
+                    {
+                        Lat = float.MaxValue,
+                        Long = float.MinValue
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 2,
+                    UnmappedField = "Unmapped2",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail2",
+                        Name = "AuthorName2",
+                        Uri = "http://www.example.com/AuthorUri2",
+                        Contributor = null
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights2",
+                    Summary = "Summary2",
+                    Title = "Title2",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement2",
+                    CustomAttribute = "CustomAttribute2",
+                    NestedElement1 = "NestedElement1_2",
+                    NestedElement2 = "NestedElement2_2",
+                    CommonAttribute1 = "CommonAttribute1_2",
+                    CommonAttribute2 = "CommonAttribute2_2",
+                    Location = null
+                },
+            };
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
+
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
+            {
+                ID = item.ID,
+                UnmappedField = item.UnmappedField,
+                Author = item.Author == null ? null : new Author2
+                {
+                    Email = item.Author.Email,
+                    Name = item.Author.Name,
+                    Uri = item.Author.Uri,
+                    Contributor = item.Author.Contributor == null ? null : new Contributor2
+                    {
+                        Name = item.Author.Contributor.Name,
+                        Email = item.Author.Contributor.Email,
+                        Uri = item.Author.Contributor.Uri
+                    },
+                },
+                Published = item.Published,
+                Rights = item.Rights,
+                Summary = item.Summary,
+                Title = item.Title,
+                Updated = item.Updated,
+                CustomElement = item.CustomElement,
+                CustomAttribute = item.CustomAttribute,
+                NestedElement1 = item.NestedElement1,
+                NestedElement2 = item.NestedElement2,
+                CommonAttribute1 = item.CommonAttribute1,
+                CommonAttribute2 = item.CommonAttribute2,
+                Location = item.Location == null ? null : new Location2
+                {
+                    Lat = item.Location.Lat,
+                    Long = item.Location.Long
+                }
+            }));
+
+            BaseEntry[] hierarchicalEntries = new BaseEntry[]
+            {
+                new BaseEntry
+                {
+                    ID = 0,
+                    MappedField = "MappedField0",
+                    MappedInDerivedField = "MappedInDerivedField0",
+                    UnmappedField = "UnmappedField0"
+                },
+                new DerivedEntry
+                {
+                    ID = 1,
+                    MappedField = "MappedField1",
+                    MappedInDerivedField = "MappedInDerivedField1",
+                    UnmappedField = "UnmappedField1",
+                    MappedConcreteField = "MappedConcreteField1",
+                    UnmappedConcreteField = "UnmappedConcreteField1"
+                },
+            };
+            Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Author
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor Contributor { get; set; }
+    }
+
+    public class Contributor
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+    
+    public class Location
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+
+    public class Author2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor2 Contributor { get; set; }
+    }
+
+    public class Contributor2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+
+    public class Location2
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+    
+    public class MappedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location Location { get; set; }
+    }
+
+    public class ReplicatedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author2 Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location2 Location { get; set; }
+    }
+    
+    public class BaseEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public string MappedInDerivedField { get; set; }
+        public string MappedField { get; set; }
+    }
+    
+    public class DerivedEntry : BaseEntry
+    {
+        public string UnmappedConcreteField { get; set; }
+        public string MappedConcreteField { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/ErrorDataService.svc b/odatajs/tests/endpoints/ErrorDataService.svc
new file mode 100644
index 0000000..052a2df
--- /dev/null
+++ b/odatajs/tests/endpoints/ErrorDataService.svc
@@ -0,0 +1,78 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.ErrorDataService" %>
+
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+
+    /// <summary>
+    /// A data service that contains in-stream errors
+    /// </summary>
+    public class ErrorDataService : DataService<ErrorDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+        }
+    }
+
+    public class ErrorDataSource
+    {
+        public IQueryable<ErrorType> Entities
+        {
+            get
+            {
+                ErrorType[] entities = new ErrorType[]
+                {
+                    new ErrorType(() => 0),
+                    new ErrorType(() => { throw new ApplicationException(); })
+                };
+
+                return entities.AsQueryable();
+            }
+        }
+    }
+    
+    public class ErrorType
+    {
+        Func<int> generateID;
+        
+        public ErrorType(Func<int> generateID)
+        {
+            this.generateID = generateID;
+        }
+        
+        public int ID
+        {
+            get { return this.generateID(); }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/FoodStoreDataServiceV4.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/FoodStoreDataServiceV4.svc b/odatajs/tests/endpoints/FoodStoreDataServiceV4.svc
new file mode 100644
index 0000000..ac1cfe7
--- /dev/null
+++ b/odatajs/tests/endpoints/FoodStoreDataServiceV4.svc
@@ -0,0 +1,590 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.V4.FoodStoreDataService" %>
+
+namespace DataJS.Tests.V4
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using Microsoft.OData.Service.Providers;
+    using System.Linq;
+    using System.ServiceModel.Web;
+    using System.Web;
+    using System.IO;
+    using Microsoft.Spatial;
+    
+    /// <summary>
+    /// Provides a service similar to FoodStoreDataService, but uses V4 and WCF Data Services 6.0.0-beta1
+    /// features.
+    /// </summary>
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class FoodStoreDataService : DataService<FoodContainer>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.UseVerboseErrors = true;
+            // Set Foods page size to 5 for cache testing
+            config.SetEntitySetPageSize("Foods", 5);
+            // Make the Categories set paged to have a paged feed
+            config.SetEntitySetPageSize("Categories", 1);
+        }
+        
+        [WebInvoke]
+        public string ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+            return "Data Reset";
+        }
+
+        [WebGet]
+        public IQueryable<string> FoodsAvailable()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Name);
+        }
+
+        [WebGet]
+        public IQueryable<Package> PackagingTypes()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
+        }
+
+        [WebGet]
+        public string UserNameAndPassword()
+        {
+            var request = WebOperationContext.Current.IncomingRequest;
+            string authorization = request.Headers["Authorization"];
+            if (String.IsNullOrEmpty(authorization))
+            {
+                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
+                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
+            }
+
+            return authorization;
+        }
+    }
+
+    public class FoodContainer : ReflectionDataContext, IUpdatable, IDataServiceStreamProvider2
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Category> Categories
+        {
+            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
+        }
+        
+        public IQueryable<Food> Foods
+        {
+            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            var builder = SpatialImplementation.CurrentImplementation.CreateBuilder();
+            builder.GeometryPipeline.SetCoordinateSystem(CoordinateSystem.DefaultGeography);
+            builder.GeometryPipeline.BeginGeometry(SpatialType.Collection);
+            builder.GeometryPipeline.BeginFigure(new GeometryPosition(5.0, 5.0));
+            builder.GeometryPipeline.EndFigure();
+            builder.GeometryPipeline.EndGeometry();
+            
+            int i = 0;
+            Category[] categories = new Category[]
+            {
+                new Category { CategoryID = i++, Name = "Baking Supplies" },
+                new Category { CategoryID = i++, Name = "Condiments" },
+                new Category { CategoryID = i++, Name = "Empty Category" }
+            };
+            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
+            
+            i = 0;
+            Food[] foods = new Food[]
+            {            
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "flour",
+                    UnitPrice = .19999,
+                    ServingSize = 1,
+                    MeasurementUnit = "Cup",
+                    ProteinGrams = 3,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 20,
+                    CaloriesPerServing = 140,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
+                    ItemGUID = new Guid("27272727272727272727272727272727"),
+                    Weight = 10f,
+                    AvailableUnits = 1,
+                    
+                    Packaging = new Package(){
+                        Type = null, 
+                        Color = String.Empty, 
+                        NumberPerPackage = int.MaxValue, 
+                        RequiresRefridgeration = false, 
+                        PackageDimensions = new Dimensions()
+                        {
+                            Length = Decimal.MaxValue, 
+                            Height = Int16.MaxValue, 
+                            Width = Int64.MaxValue, 
+                            Volume = double.MaxValue,   
+                        },
+                        ShipDate = new DateTime(2000, 12, 29)
+                    },
+                    
+                    CookedSize = new CookedDimensions()
+                    {
+                        Height = 1,
+                        Length = 2,
+                        Width = 3,
+                        Volume = 1 * 2 * 3
+                    },
+                    
+                    Category = categories[0],
+                    
+                    AlternativeNames = new List<string>() {"ground cereal", "ground grain"},
+                    
+                    Providers = new List<Provider> {
+                        new Provider() { 
+                             Name= "Flour Provider", 
+                             Aliases = new List<string>() {"fp1", "flour provider1"},
+                             Details = new ProviderDetails() {
+                                 Telephone= "555-555-555",
+                                 PreferredCode = 1001
+                             }
+                        },
+                        new Provider() { 
+                             Name= "Ground Grains", 
+                             Aliases = new List<string>()
+                        }
+                    },
+                    
+                    SpatialData = (GeometryCollection)builder.ConstructedGeometry 
+                },
+                
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "sugar",
+                    UnitPrice = .2,
+                    ServingSize = 1,
+                    MeasurementUnit = "tsp",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 4,
+                    CaloriesPerServing = 16,
+                    IsAvailable = false,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
+                    Weight = 0.1f,
+                    AvailableUnits = 0,
+
+                    Packaging = new Package(){
+                        Type = " ",
+                        Color = "BLUE",
+                        NumberPerPackage = int.MinValue,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = Decimal.MinValue,
+                            Height = Int16.MinValue,
+                            Width = Int64.MinValue,
+                            Volume = double.MinValue,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = categories[1],
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "1 Chicken Egg",
+                    UnitPrice = 0.55,
+                    MeasurementUnit = null,
+                    ServingSize = 1,
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 1,
+                    CaloriesPerServing = 70,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("00000000000000000000000000000000"),
+                    Weight = 0,
+                    AvailableUnits = -128,
+                    
+                    Packaging = new Package(){
+                        Type = "18     - Carton",
+                        Color = " brown ",
+                        NumberPerPackage = 0,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = null,
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = null,
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "Brown Sugar",
+                    UnitPrice = 1.6,
+                    ServingSize = 1,
+                    MeasurementUnit = "TSP.",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 5, 
+                    CaloriesPerServing = 16,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 4.5f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Cobb Salad",
+                    UnitPrice = 1.99,
+                    ServingSize = -1,
+                    MeasurementUnit = "cups",
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 3, 
+                    CaloriesPerServing = 5,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 5.674f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                    Instructions = "1.) Open 2.) Eat",
+                    NumberOfIngredients = 4,
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Lasagna",
+                    UnitPrice = 0,
+                    ServingSize = 8,
+                    MeasurementUnit = " servings",
+                    ProteinGrams = 100,
+                    FatGrams = 4,
+                    CarbohydrateGrams = 27, 
+                    CaloriesPerServing = 389,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(1904, 2, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 0,
+                    AvailableUnits = 4,
+                    Packaging = new Package(){
+                        Type = "box",
+                        Color = " 1 ",
+                        NumberPerPackage = 1,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = 3,
+                            Height = 1,
+                            Width = 5,
+                            Volume = 1.5,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    Category = categories[0],
+                    Instructions = "Bake in oven",
+                    NumberOfIngredients = 15,
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Chocolate"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Pizza"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Avocados"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Quinoa"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Oatmeal"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Peanut Butter"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Banana"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Yam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Clam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Spam"
+                }
+            };
+            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
+
+            categories[0].Foods.Add(foods[0]);
+            categories[1].Foods.Add(foods[2]);
+            categories[1].Foods.Add(foods[3]);
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+
+        public Stream GetReadStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            return new MemoryStream();
+        }
+
+        public Uri GetReadStreamUri(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            if (streamProperty.Name == "Icon")
+            {
+                return null;
+            }
+            return new Uri(operationContext.AbsoluteServiceUri, streamProperty.Name);
+        }
+
+        public string GetStreamContentType(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            if (streamProperty.Name == "Icon")
+            {
+                return "image/gif";
+            }
+            return "image/png";
+        }
+
+        public string GetStreamETag(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            return "W/\"123456789\"";
+        }
+
+        public Stream GetWriteStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            return new MemoryStream();
+        }
+
+        public void DeleteStream(object entity, DataServiceOperationContext operationContext)
+        {
+            // do nothing.
+        }
+
+        public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public int StreamBufferSize
+        {
+            get { return 1024; }
+        }
+    }
+
+    /// <summary>
+    /// The Category class is a simple class with V1-compatible feed customizations.
+    /// </summary>
+    public class Category
+    {
+        public Category()
+        {
+            this.Foods = new List<Food>();
+        }
+        
+        public int CategoryID { get; set; }
+        public string Name { get; set; }
+        public List<Food> Foods { get; set; }
+    }
+    
+    /// <summary>
+    /// The Food class has a mixture of V1-compatible and incompatible feed
+    /// customizations (thus it's V2), and custom mappings.
+    /// </summary>
+    public class Food
+    {
+        private List<string> alternativeNames = new List<string>();
+        private List<Provider> providers = new List<Provider>();
+        
+        // Primitive types
+        public int FoodID { get; set; }
+        public string Name { get; set; }
+        public double UnitPrice { get; set; }
+        public Decimal ServingSize { get; set; }
+        public string MeasurementUnit { get; set; }
+        public Byte ProteinGrams { get; set; }
+        public Int16 FatGrams { get; set; }
+        public Int32 CarbohydrateGrams { get; set; }
+        public Int64 CaloriesPerServing { get; set; }
+        public Boolean IsAvailable { get; set; }
+        public DateTime ExpirationDate { get; set; }
+        public Guid ItemGUID { get; set; }
+        public Single Weight { get; set; }
+        public sbyte AvailableUnits { get; set; }
+
+        // Complex types
+        public Package Packaging { get; set; }
+        public CookedDimensions CookedSize { get; set; }
+
+        // Navigation properties
+        public Category Category { get; set; }
+
+        // Collection properties
+        public List<string> AlternativeNames
+        {
+            get { return alternativeNames; }
+            set { alternativeNames = value; }
+        }
+
+        public List<Provider> Providers
+        {
+            get { return providers; }
+            set { providers = value; }
+        }
+
+        public GeometryCollection SpatialData
+        {
+            get;
+            set;
+        }
+        
+    }
+
+    public class Provider
+    {
+        public string Name { get; set; }
+        public List<string> Aliases { get; set; }
+        public ProviderDetails Details { get; set; }
+    }
+
+    public class ProviderDetails
+    {
+        public string Telephone { get; set; }
+        public int PreferredCode { get; set; }
+    }
+    
+    public class Package
+    {
+        public string Type { get; set; }
+        public string Color { get; set; }
+        public int NumberPerPackage { get; set; }
+        public Boolean RequiresRefridgeration { get; set; }
+        public DateTime ShipDate { get; set; }
+        public Dimensions PackageDimensions { get; set; }
+    }
+
+    public class Dimensions
+    {
+        public Decimal Length { get; set; }
+        public Int16 Height { get; set; }
+        public Int64 Width { get; set; }
+        public double Volume { get; set; }
+    }
+
+    public class CookedDimensions
+    {
+        public Decimal Length { get; set; }
+        public Int16 Height { get; set; }
+        public Int64 Width { get; set; }
+        public double Volume { get; set; }
+    }
+
+    public class PreparedFood : Food
+    {
+        public string Instructions { get; set; }
+        public float NumberOfIngredients { get; set; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/LargeCollectionService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/LargeCollectionService.svc b/odatajs/tests/endpoints/LargeCollectionService.svc
new file mode 100644
index 0000000..bfbd3ef
--- /dev/null
+++ b/odatajs/tests/endpoints/LargeCollectionService.svc
@@ -0,0 +1,113 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.LargeCollectionService" %>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Web;
+    using System.Web;
+
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class LargeCollectionService : DataService<LargeCollection>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.UseVerboseErrors = true;
+        }
+
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+    }
+
+    public class LargeCollection : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Customer> Customers
+        {
+            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+        }
+
+        public IQueryable<Supplier> Suppliers
+        {
+            get { return this.GetResourceSetEntities<Supplier>("Suppliers").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+            foreach (int i in Enumerable.Range(1, 2 * 1024 * 1024))
+            {
+                customers.Add(new Customer()
+                {
+                    ID = i,
+                    Name = "Customer " + i
+                });
+            }
+
+            IList<Supplier> suppliers = this.GetResourceSetEntities<Supplier>("Suppliers");
+            foreach (int i in Enumerable.Range(1, 5000))
+            {
+                suppliers.Add(new Supplier()
+                {
+                    ID = i,
+                    Name = "Supplier " + i
+                });
+            }
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Customer
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+
+    public class Supplier
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/endpoints/web.config
----------------------------------------------------------------------
diff --git a/odatajs/tests/endpoints/web.config b/odatajs/tests/endpoints/web.config
new file mode 100644
index 0000000..116a567
--- /dev/null
+++ b/odatajs/tests/endpoints/web.config
@@ -0,0 +1,46 @@
+<?xml version='1.0'?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+-->
+<configuration>
+  <system.web>
+    <compilation debug='true'>
+      <assemblies>
+        <add assembly='System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
+        <add assembly='System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
+        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+      </assemblies>
+    </compilation>
+  </system.web>
+  <system.codedom>
+    <compilers>
+      <compiler language='c#;cs;csharp' extension='.cs' type='Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>
+        <providerOption name='CompilerVersion' value='v4.0' />
+      </compiler>
+    </compilers>
+  </system.codedom>
+</configuration>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/node-test-setup.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/node-test-setup.js b/odatajs/tests/node-test-setup.js
new file mode 100644
index 0000000..50fcac2
--- /dev/null
+++ b/odatajs/tests/node-test-setup.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+*/
+//Creates the global objects
+
+//tools
+djstest = require("./common/djstest.js");
+MockHttpClient = require("./common/MockHttpClient.js").init({});
+
+//lib
+datajs = require('./../src/lib/datajs.js');
+OData = require('./../src/lib/odata.js');
+
+
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-batch-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-batch-functional-tests.html b/odatajs/tests/odata-batch-functional-tests.html
new file mode 100644
index 0000000..4f79204
--- /dev/null
+++ b/odatajs/tests/odata-batch-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>batch tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>  
+    <script type="text/javascript" src="common/common.js"></script> 
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-batch-functional-tests.js"></script>
+</head>
+<body>
+    <h1 id="qunit-header">batch 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/d5ec5557/odatajs/tests/odata-batch-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-batch-functional-tests.js b/odatajs/tests/odata-batch-functional-tests.js
new file mode 100644
index 0000000..328bb66
--- /dev/null
+++ b/odatajs/tests/odata-batch-functional-tests.js
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var determineExpected = function (batchRequests) {
+        var expected = 0;
+        $.each(batchRequests, function (_, batchRequest) {
+            // 2 assertions per request: response code and data
+            if (batchRequest.__changeRequests) {
+                expected += batchRequest.__changeRequests.length * 2;
+            } else {
+                expected += 2;
+            }
+        });
+
+        // 2 more assertions than the number of requests in batch: response code and batch response length
+        return expected + 2;
+    };
+
+    var verifyBatchRequest = function (serviceRoot, batchRequests, elementTypes, done) {
+        odatajs.oData.request({ requestUri: serviceRoot + "/$batch", method: "POST", data: { __batchRequests: batchRequests} },
+            function (data, response) {
+                djstest.assertAreEqual(response.statusCode, httpStatusCode.accepted, "Verify response code");
+                djstest.assertAreEqual(data.__batchResponses.length, batchRequests.length, "Verify batch response count");
+                verifyBatchResponses(batchRequests, elementTypes, serviceRoot, data.__batchResponses, done);
+            },
+            unexpectedErrorHandler, OData.batch.batchHandler);
+    };
+
+    var verifyBatchResponses = function (batchRequests, elementTypes, serviceRoot, batchResponses, done) {
+        forEachAsync(batchRequests, function (index, batchRequest, doneOne) {
+            if (batchRequest.requestUri) {
+                var readFeedOrEntry = elementTypes[index] == "feed" ? ODataReadOracle.readFeed : ODataReadOracle.readEntry;
+                djstest.assertAreEqual(batchResponses[index].statusCode, httpStatusCode.ok, "Verify response code for: GET " + batchRequest.requestUri);
+                readFeedOrEntry(serviceRoot + "/" + batchRequest.requestUri, function (expectedData) {
+                    djstest.assertAreEqualDeep(batchResponses[index].data, expectedData, "Verify data for: GET " + batchRequest.requestUri);
+                    doneOne();
+                }, batchRequests[index].headers.Accept);
+            }
+            else if (batchRequest.__changeRequests) {
+                verifyChangeResponses(batchRequest.__changeRequests, batchResponses[index].__changeResponses, function () { doneOne(); });
+            }
+        }, done);
+    }
+
+    var verifyChangeResponses = function (changeRequests, changeResponses, done) {
+        forEachAsync(changeRequests, function (index, changeRequest, doneOne) {
+            var httpOperation = changeRequest.method + " " + changeRequest.requestUri;
+            var changeResponse = changeResponses[index];
+
+            if (changeRequest.method == "POST") {
+                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.created, "Verify response code for: " + httpOperation);
+                ODataReadOracle.readEntry(changeResponse.headers["Location"], function (expectedData) {
+                    djstest.assertAreEqualDeep(changeResponse.data, expectedData, "Verify response data for: " + httpOperation);
+                    doneOne();
+                }, changeRequest.headers.Accept);
+            }
+            else if (changeRequest.method == "PUT") {
+                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
+                djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
+                doneOne();
+            }
+            else if (changeRequest.method == "DELETE") {
+                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
+                djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
+                doneOne();
+            }
+        }, done);
+    }
+
+    var forEachAsync = function (array, callback, done) {
+        var count = 0;
+        var doneOne = function () {
+            count++;
+            if (count == array.length) {
+                done();
+            }
+        }
+
+        $.each(array, function (index, element) { callback(index, element, doneOne); });
+    };
+
+    var cloneHeadersWithContentId = function (mimeHeaders, count) {
+        var headers = djstest.clone(mimeHeaders);
+        headers["Content-ID"] = count;
+        return headers;
+    };
+
+    var service = "./endpoints/FoodStoreDataServiceV4.svc";
+    var batchUri = service + "/$batch";
+
+    var httpStatusCode = {
+        ok: 200,
+        created: 201,
+        accepted: 202,
+        noContent: 204
+    };
+
+    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
+
+    module("Functional", {
+        setup: function () {
+            djstest.wait(function (done) {
+                $.post(service + "/ResetData", done);
+            });
+        }
+    });
+
+    $.each(mimeTypes, function (_, mimeType) {
+        var acceptHeaders = mimeType ? { Accept: mimeType} : undefined;
+        var mimeHeaders = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
+
+        djstest.addTest(function multipleRetrieves(acceptHeaders) {
+            var uriSegments = ["Foods(0)", "Foods?$filter=FoodID eq 1", "Foods?$top=2"];
+            var elementTypes = ["entry", "feed", "feed"];
+
+            var batchRequests = $.map(uriSegments, function (uriSegment) {
+                return { requestUri: uriSegment, method: "GET", headers: acceptHeaders }
+            });
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Multiple retrieves: mimeType = " + mimeType, acceptHeaders);
+
+        djstest.addTest(function multipleChangesets(params) {
+            var batchRequests = [
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
+                                { CategoryID: 42, Name: "New Category" }
+                            }
+                        ]
+                    },
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
+                                { CategoryID: 1, Name: "Updated Category" }
+                            },
+                            { requestUri: "Categories(0)", method: "DELETE", headers: cloneHeadersWithContentId(params.mimeHeaders, 3) }
+                        ]
+                    }
+                ];
+            var elementTypes = [null, null];
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Multiple changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+        djstest.addTest(function multipleRetrievesAndChangesets(params) {
+            // Header needs to be cloned because it is mutable; this means that after processing one request in the batch
+            // the header object will be modified
+            var batchRequests = [
+                    { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+                    { requestUri: "Foods?$filter=FoodID eq 1", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
+                                { CategoryID: 42, Name: "New Category" }
+                            }
+                        ]
+                    },
+                    { requestUri: "Foods?$top=2", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
+                                { CategoryID: 1, Name: "Updated Category" }
+                            },
+                            { requestUri: "Categories(0)", method: "DELETE", headers: cloneHeadersWithContentId(params.mimeHeaders, 3) }
+                        ]
+                    }
+                ];
+            var elementTypes = ["entry", "feed", null, "feed", null];
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Multiple retrieves and changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+        djstest.addTest(function singleRetrieve(acceptHeaders) {
+            var batchRequests = [{ requestUri: "Foods(2)", method: "GET", headers: acceptHeaders}];
+            var elementTypes = ["entry"];
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Single retrieve: mimeType = " + mimeType, acceptHeaders);
+
+        djstest.addTest(function singleChangeset(params) {
+            var batchRequests = [
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
+                                { CategoryID: 42, Name: "New Category" }
+                            },
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
+                                { CategoryID: 1, Name: "Updated Category" }
+                            }
+                        ]
+                    }
+                ];
+            var elementTypes = [null];
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Single changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+        djstest.addTest(function singleRetrieveAndChangeset(params) {
+            var batchRequests = [
+                    { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+                    {
+                        __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
+                                { CategoryID: 42, Name: "New Category" }
+                            },
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
+                                { CategoryID: 1, Name: "Updated Category" }
+                            }
+                        ]
+                    }
+                ];
+            var elementTypes = ["entry", null];
+
+            djstest.assertsExpected(determineExpected(batchRequests));
+            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+        }, "Single retrieve and changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+        djstest.addTest(function retrieveInsideChangeset(params) {
+
+            var batchRequests = [
+                    { requestUri: "Foods(0)", method: "GET" },
+                    { __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data: { CategoryID: 42, Name: "New Category"} },
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data: { CategoryID: 1, Name: "Updated Category"} }
+                        ]
+                    },
+                    { requestUri: "Foods(1)", method: "GET" },
+                    { __changeRequests: [
+                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 3), data: { CategoryID: 42, Name: "New Category"} },
+                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 4), data: { CategoryID: 1, Name: "Updated Category"} },
+                            { requestUri: "Foods", method: "GET" }
+                        ]
+                    }
+                ];
+
+            odatajs.oData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
+            function (data, response) {
+                var batchResponses = data.__batchResponses;
+                var error = batchResponses[3].__changeResponses[0];
+                djstest.assert(error.response.body.indexOf("An error occurred while processing this request.") > -1, "Response contains expected message");
+                // Verify that the responses prior to the error are the expected ones.
+                batchRequests.splice(3, 1);
+                batchResponses.splice(3, 1);
+                verifyBatchResponses(batchRequests, ["entry", null], service, batchResponses, function () { djstest.done(); });
+            }, unexpectedErrorHandler, OData.batch.batchHandler);
+        }, "Retrieve inside changeset: mimeType = " + mimeType, {mimeHeaders: mimeHeaders });
+    });
+
+    /*On Odata V4 spec, the POST/PUT/Delete operations are allowed outside of changesets.*/
+    djstest.addTest(function updateOutsideChangeset() {
+        var batchRequests = [{ requestUri: "Categories", method: "POST", data: { CategoryID: 42, Name: "New Category"}}];
+
+        djstest.assertsExpected(1);
+        odatajs.oData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
+            function (data, response) {
+                djstest.assert(response.body.indexOf("An error occurred while processing this request.") == -1, "Verify that there is no error occurred.");
+                djstest.done();
+            }, unexpectedErrorHandler, OData.batch.batchHandler
+        );
+    }, "Update outside changeset");
+})(this);
\ No newline at end of file


[02/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-tests.js b/odatajs/tests/odata-tests.js
new file mode 100644
index 0000000..0e6e951
--- /dev/null
+++ b/odatajs/tests/odata-tests.js
@@ -0,0 +1,322 @@
+/*
+ * 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) {
+    var northwindService = "http://services.odata.org/Northwind/Northwind.svc/";
+    var localFeed = "./endpoints/FoodStoreDataService.svc/Foods";
+    var northwindFeed = northwindService + "Suppliers";
+
+    var countIFrames = function () {
+        /** Count the number of IFRAMES in the page
+         * @returns {Integer} The number of IFRAMES
+         */
+        return document.getElementsByTagName("IFRAME").length;
+    }
+
+    module("Unit");
+
+    var originalEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
+
+    var restoreJsonpCallback = function () {
+        /** Restores OData.defaultHttpClient.enableJsonpCallback to the library default.
+        */
+        OData.defaultHttpClient.enableJsonpCallback = originalEnableJsonpCallback;
+    };
+
+    djstest.addTest(function checkApiTest() {
+        var internals = window.odatajs.oData.canUseJSONP !== undefined;
+        if (internals) {
+            // Don't even bother - there is a very long list for inter-module communication.
+            // {targetName: "OData", names: "..." }
+            djstest.pass("Do not test public api's when internals are visible");
+        } else {
+            var apis = [
+                { targetName: "datajs", names: "createDataCache,createStore,defaultStoreMechanism" },
+                { targetName: "OData", names: "batchHandler,defaultError,defaultHandler,defaultHttpClient,defaultMetadata,defaultSuccess,jsonHandler,metadataHandler,read,request,textHandler,xmlHandler,parseMetadata" }
+            ];
+
+            for (var i = 0; i < apis.length; i++) {
+                var target = window[apis[i].targetName];
+
+                var actuals = [];
+                for (var actual in target) {
+                    actuals.push(actual);
+                }
+
+                actuals.sort();
+
+                var names = apis[i].names.split(",");
+                names.sort();
+
+                djstest.assertAreEqual(actuals.join(), names.join(), "actual names for " + apis[i].targetName);
+            }
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function simpleLocalReadTest() {
+        odatajs.oData.read(localFeed, function (data, request) {
+            djstest.assert(data !== null, "data !== null");
+            djstest.assert(request !== null, "request !== null");
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function simpleLocalReadWithRequestTest() {
+        odatajs.oData.read({ requestUri: localFeed, headers: { Accept: "application/json"} }, function (data, response) {
+            djstest.assert(data !== null, "data !== null");
+            djstest.assert(response !== null, "response !== null");
+            djstest.assertAreEqual(data, response.data, "data === response.data");
+
+            // Typically application/json;charset=utf-8, but browser may change the request charset (and thus response).
+            var contentType = response.headers["Content-Type"];
+            contentType = contentType.split(';')[0];
+            djstest.assertAreEqual(contentType, "application/json", 'contentType === "application/json"');
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function simpleReadTest() {
+        var oldEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
+        OData.defaultHttpClient.enableJsonpCallback = true;
+
+        var iframesBefore = countIFrames();
+        odatajs.oData.read(northwindService + "Regions", function (data, request) {
+            djstest.assert(data !== null, "data !== null");
+            djstest.assert(request !== null, "request !== null");
+
+            // IFRAME recycling does not work in Opera because as soon as the IFRAME is added to the body, all variables
+            // go out of scope
+            if (!window.opera) {
+                djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra IFRAMEs (baseline: " + iframesBefore + ")");
+            }
+
+            OData.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function simpleReadWithParamsTest() {
+        OData.defaultHttpClient.enableJsonpCallback = true;
+        odatajs.oData.read(northwindFeed + "?$top=3", function (data, request) {
+            djstest.assert(data !== null, "data !== null");
+            djstest.assert(request !== null, "request !== null");
+            restoreJsonpCallback();
+            djstest.done();
+        }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
+    });
+
+    djstest.addTest(function simpleReadWithNoParamsTest() {
+        OData.defaultHttpClient.enableJsonpCallback = true;
+        odatajs.oData.read(northwindFeed + "?", function (data, request) {
+            djstest.assert(data !== null, "data !== null");
+            djstest.assert(request !== null, "request !== null");
+            restoreJsonpCallback();
+            djstest.done();
+        }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
+    });
+
+    djstest.addTest(function jsonpTimeoutTest() {
+        // Verifies that JSONP will timeout, and that the
+        // enableJsonpCallback flag can be set on the request itself.
+        var iframesBefore = countIFrames();
+        odatajs.oData.request({
+            requestUri: northwindFeed + "?$fail=true",
+            timeoutMS: 100,
+            enableJsonpCallback: true
+        }, function (data, request) {
+            djstest.fail("expected an error callback");
+            djstest.done();
+        }, function (err) {
+            djstest.assert(err.message.indexOf("timeout") !== 1, "err.message[" + err.message + "].indexOf('timeout') !== 1");
+            djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra script tags (baseline: " + iframesBefore + ")");
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function requestDefaultsTest() {
+        // Save current defaults.
+        var oldError = OData.defaultError;
+        var oldSuccess = OData.defaultSuccess;
+        var oldDefaultHandler = OData.defaultHandler;
+        var oldHttpClient = OData.defaultHttpClient;
+
+        OData.defaultSuccess = function (data, response) {
+            djstest.assertAreEqual(response.statusCode, 299, "success method reached when expected");
+        };
+
+        OData.defaultError = function (error) {
+            var response = error.response;
+            djstest.assertAreEqual(response.statusCode, 500, "error method reached when expected");
+        };
+
+        OData.defaultHandler = {
+            read: function (response) {
+                djstest.assertAreEqual(response.statusCode, 299, "default handler read method reached when expected");
+            },
+            accept: "test accept string"
+        };
+
+        OData.defaultHttpClient = MockHttpClient.clear();
+
+        var testUris = [
+            "requestDefaultsTest/request",
+            "requestDefaultsTest/request1",
+            "requestDefaultsTest/error"
+        ];
+
+        MockHttpClient.addRequestVerifier(testUris[0], function (request) {
+            djstest.assertAreEqual(request.method, "GET", "request.method is GET");
+            djstest.assert(request.headers, "request.headers is defined and not null");
+            djstest.assertAreEqual(request.headers.Accept, "test accept string");
+        });
+
+        MockHttpClient.addResponse(testUris[1], { statusCode: 299, body: "test response" });
+        MockHttpClient.addResponse(testUris[2], { statusCode: 500, body: "error response" });
+
+        try {
+            var i, len;
+            for (i = 0, len = testUris.length; i < len; i++) {
+                odatajs.oData.request({ requestUri: testUris[i] });
+            }
+        }
+        finally {
+            // Restore defaults.
+            OData.defaultError = oldError;
+            OData.defaultSuccess = oldSuccess;
+            OData.defaultHandler = oldDefaultHandler;
+            OData.defaultHttpClient = oldHttpClient;
+        }
+
+        djstest.assertsExpected(6);
+        djstest.done();
+    });
+
+    djstest.addTest(function requestUpdateTest() {
+        // Save current defaults.
+        var testHandler = {
+            read: function (response) {
+                response.data = response.body;
+            },
+            write: function (request) {
+                djstest.assertAreEqual(request.method, "POST", "handler write method, request has the correct method");
+            }
+        };
+
+        var testSuccess = function (data, response) {
+            djstest.assertAreEqual(data, "test response", "success callback has the correct data");
+            djstest.assertAreEqual(response.status, 200, "success method reached when expected");
+        };
+
+        var testError = function (error) {
+            var response = error.response;
+            djstest.assertAreEqual(response.status, 500, "error method reached when expected");
+        };
+
+        MockHttpClient.addResponse("requestUpdateTest", { status: 200, body: "test response" });
+        MockHttpClient.addResponse("requestUpdateTest", { status: 500, body: "error response" });
+
+        odatajs.oData.request({ requestUri: "requestUpdateTest", method: "POST" }, testSuccess, testError, testHandler, MockHttpClient);
+
+        djstest.done();
+    });
+
+    djstest.addTest(function parseMetadataTest() {
+        var metadata = '<?xml version="1.0" encoding="utf-8"?>' +
+            '<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">' +
+            '<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">' +
+            '<Schema Namespace="ODataDemo" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">' +
+                '<EntityType Name="Product">' +
+                    '<Key><PropertyRef Name="ID" /></Key>' +
+                    '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
+                    '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
+                    '<Property Name="Description" Type="Edm.String" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
+                    '<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false" />' +
+                    '<Property Name="DiscontinuedDate" Type="Edm.DateTime" />' +
+                    '<Property Name="Rating" Type="Edm.Int32" Nullable="false" />' +
+                    '<Property Name="Price" Type="Edm.Decimal" Nullable="false" />' +
+                    '<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Category_Products" FromRole="Product_Category" />' +
+                '</EntityType>' +
+                '<EntityType Name="Category">' +
+                    '<Key>' +
+                        '<PropertyRef Name="ID" />' +
+                    '</Key>' +
+                    '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
+                    '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true" />' +
+                    '<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Product_Category" FromRole="Category_Products" />' +
+                '</EntityType>' +
+                '<Association Name="Product_Category_Category_Products"><End Type="ODataDemo.Category" Role="Category_Products" Multiplicity="0..1" />' +
+                    '<End Type="ODataDemo.Product" Role="Product_Category" Multiplicity="*" />' +
+                '</Association>' +
+                '<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">' +
+                    '<EntitySet Name="Products" EntityType="ODataDemo.Product" />' +
+                    '<EntitySet Name="Categories" EntityType="ODataDemo.Category" />' +
+                    '<FunctionImport Name="Discount" IsBindable="true" m:IsAlwaysBindable="true">' +
+                        '<Parameter Name="product" Type="ODataDemo.Product" />' +
+                        '<Parameter Name="discountPercentage" Type="Edm.Int32" Nullable="false" />' +
+                    '</FunctionImport>' +
+                    '<AssociationSet Name="Products_Category_Categories" Association="ODataDemo.Product_Category_Category_Products">' +
+                        '<End Role="Product_Category" EntitySet="Products" />' +
+                        '<End Role="Category_Products" EntitySet="Categories" />' +
+                    '</AssociationSet>' +
+                '</EntityContainer>' +
+             '</Schema></edmx:DataServices></edmx:Edmx>';
+
+        var parsedMetadata = OData.parseMetadata(metadata);
+        var expected =
+        {
+            "version": "1.0",
+            "dataServices":
+            {
+                "maxDataServiceVersion": "4.0",
+                "dataServiceVersion": "4.0",
+                "schema": [
+                    {
+                        "namespace": "ODataDemo",
+                        "entityType": [
+                            {
+                                "name": "Product",
+                                "key": { "propertyRef": [{ "name": "ID"}] },
+                                "property": [
+                                    { "name": "ID", "nullable": "false", "type": "Edm.Int32" },
+                                    { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle" },
+                                    { "name": "Description", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationSummary" },
+                                    { "name": "ReleaseDate", "nullable": "false", "type": "Edm.DateTime" }, { "name": "DiscontinuedDate", "type": "Edm.DateTime" },
+                                    { "name": "Rating", "nullable": "false", "type": "Edm.Int32" }, { "name": "Price", "nullable": "false", "type": "Edm.Decimal"}],
+                                "navigationProperty": [
+                                    { "name": "Category", "fromRole": "Product_Category", "toRole": "Category_Products", "relationship": "ODataDemo.Product_Category_Category_Products" }
+                                ]
+                            }, {
+                                "name": "Category",
+                                "key": { "propertyRef": [{ "name": "ID"}] },
+                                "property": [{ "name": "ID", "nullable": "false", "type": "Edm.Int32" }, { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "true", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle"}],
+                                "navigationProperty": [{ "name": "Products", "fromRole": "Category_Products", "toRole": "Product_Category", "relationship": "ODataDemo.Product_Category_Category_Products"}]
+                            }],
+                        "association": [{ "name": "Product_Category_Category_Products", "end": [{ "type": "ODataDemo.Category", "multiplicity": "0..1", "role": "Category_Products" }, { "type": "ODataDemo.Product", "multiplicity": "*", "role": "Product_Category"}]}],
+                        "entityContainer": [{ "name": "DemoService", "isDefaultEntityContainer": "true", "entitySet": [{ "name": "Products", "entityType": "ODataDemo.Product" }, { "name": "Categories", "entityType": "ODataDemo.Category"}], "functionImport": [{ "name": "Discount", "isAlwaysBindable": "true", "isBindable": "true", "parameter": [{ "name": "product", "type": "ODataDemo.Product" }, { "name": "discountPercentage", "nullable": "false", "type": "Edm.Int32"}]}], "associationSet": [{ "name": "Products_Category_Categories", "association": "ODataDemo.Product_Category_Category_Products", "end": [{ "role": "Product_Category", "entitySet": "Products" }, { "role": "Category_Products", "entitySet": "Categories"}]}]}]
+                    }]
+            }
+        };
+        djstest.assertAreEqualDeep(expected, parsedMetadata, "metadata should be parsed to datajs format");
+        djstest.done();
+    });
+
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-xml-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-xml-tests.js b/odatajs/tests/odata-xml-tests.js
new file mode 100644
index 0000000..465b42b
--- /dev/null
+++ b/odatajs/tests/odata-xml-tests.js
@@ -0,0 +1,275 @@
+/*
+ * 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-xml-tests.js
+
+(function (window, undefined) {
+
+    // DATAJS INTERNAL START
+
+    djstest.addTest(function getURIInfoTest() {
+        var tests = [
+            { input: "https://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "https:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
+            { input: "http://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "http:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
+            { input: "https:", expected: { scheme: "https:", isAbsolute: true} },
+            { input: "http:", expected: { scheme: "http:", isAbsolute: true} },
+            { input: "//host.com", expected: { authority: "//host.com", isAbsolute: false} },
+            { input: "path1", expected: { path: "path1", isAbsolute: false} },
+            { input: "?query", expected: { query: "?query", isAbsolute: false} },
+            { input: "#fragment", expected: { fragment: "#fragment", isAbsolute: false} },
+            { input: undefined, expected: { isAbsolute: false} },
+            { input: "", expected: { isAbsolute: false} },
+            { input: null, expected: { isAbsolute: false} }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var actual = odatajs.utils.getURIInfo(tests[i].input);
+            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected URI parts");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function normalizeURICaseTest() {
+        var tests = [
+            { uri: "hTTp://HOST.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment", expected: "http://host.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment" },
+            { uri: "http://fabrikam%20user%3AHisPassWord@www.FaBriKAM.com:5895/Path%3A%201?q1=hi%20%3Ato%20you", expected: "http://fabrikam%20user%3aHisPassWord@www.fabrikam.com:5895/Path%3a%201?q1=hi%20%3ato%20you" },
+            { uri: "/PATH1/PATH2?P1=AbC#fraGment", expected: "/PATH1/PATH2?P1=AbC#fraGment" },
+            { uri: "HttP://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/"), expected: "http://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/").toLowerCase() }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var actual = odatajs.utils.normalizeURICase(tests[i].uri, tests[i].base);
+            djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected URI");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function normalizeURITest() {
+        var tests = [
+            { uri: "http://host.com/path1#fragment", base: "http://base", expected: "http://host.com/path1#fragment" },
+            { uri: "//host.com/path1?p1=0", base: "http://base?p2=1", expected: "http://host.com/path1?p1=0" },
+            { uri: "?p1=0#fragment", base: "http://base/basepath", expected: "http://base/basepath?p1=0#fragment" },
+            { uri: "?p1=0#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p1=0#fragment" },
+            { uri: "#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p2=1#fragment" },
+            { uri: "/path1/path2?p1=0", base: "http://base/basePath", expected: "http://base/path1/path2?p1=0" },
+            { uri: "path1/path2?p1=0", base: "http://base/basepath", expected: "http://base/path1/path2?p1=0" },
+            { uri: "path1/path2?p1=0", base: "http://base/basepath/basepath2", expected: "http://base/basepath/path1/path2?p1=0" },
+            { uri: "", base: "http://base/basepath?p1=0#fragment", expected: "http://base/basepath?p1=0" },
+            { uri: "path1/path2?p1=0", base: "", expected: "path1/path2?p1=0" },
+            { uri: "/a/b/c/./../../g", base: "http://base/basepath", expected: "http://base/a/g" },
+            { uri: "a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
+            { uri: "../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
+            { uri: "./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
+            { uri: "/../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
+            { uri: "/./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var actual = odatajs.utils.normalizeURI(tests[i].uri, tests[i].base);
+            djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected normalized URI");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlParseTest() {
+        var xml = '<root xmlns:n1="http://namespace1" xml:base="http://base.org" />';
+        var root = odatajs.xml.xmlParse(xml);
+        djstest.assert(root, "xml._parse didn't return a xml dom object");
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlbaseURITest() {
+        var xml = "\
+         <root xmlns:n1=\"http://namespace1\" \r\n\
+               xml:base=\"http://base.org\"> \r\n\
+           <element base=\"this is not a xml base attribute\" /> \r\n\
+         </root>\r\n";
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+        var child = odatajs.xml.xmlFirstChildElement(root);
+
+        djstest.assertAreEqual(odatajs.xml.xmlBaseURI(root), "http://base.org", "xml._baseURI didn't return the expected value");
+        djstest.assert(!odatajs.xml.xmlBaseURI(child), "xml._baseURI returned a value when it wasn't expected");
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlAttributeValueTest() {
+        var xml = "\
+     <root xmlns:n1=\"http://namespace1\" \r\n\
+           xml:base=\"http://base.org\"> \r\n\
+        <element attribute=\"value\" n1:nsAttribute=\"nsValue\" /> \r\n\
+     </root> \r\n";
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+        var child = odatajs.xml.xmlFirstChildElement(root);
+
+        djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "attribute"), "value", "xml._attribute didn't return the expected value for attribute");
+        djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "nsAttribute", "http://namespace1"), "nsValue", "xml._attribute didn't return the expected value for nsAttribute");
+        djstest.assert(!odatajs.xml.xmlAttributeValue(child, "nsAttribute"), "xml._attribute returned a value for nsAttribute without specifying a namespace");
+
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlLocalNameTest() {
+        var xml = "<root xmlns:n1=\"http://namespace1\" /> \r\n";
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+
+        djstest.assertAreEqual(odatajs.xml.xmlLocalName(root), "root", "xml._localName didn't return the expected localName of the root element");
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlFirstChildElement() {
+        var xml = "\
+         <root xmlns:n1=\"http://namespace1\" \r\n\
+               xml:base=\"http://base.org\"> \r\n\
+           <element1 /> \r\n\
+           <element2 /> \r\n\
+         </root>\r\n";
+
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+        var child = odatajs.xml.xmlFirstChildElement(root);
+
+        djstest.assertAreEqual(odatajs.xml.xmlLocalName(child), "element1", "xml.firstElement returned didn't return the expected element");
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlChildElementsTest() {
+        var xml = "\
+         <root xmlns:n1=\"http://namespace1\" \r\n\
+               xml:base=\"http://base.org\"> \r\n\
+           <element1 /> \r\n\
+           <element2 xml:base=\"http://otherBase.org\" /> \r\n\
+           <n1:element3 xml:base=\"path1/path2\" /> \r\n\
+         </root>\r\n";
+
+        var expected = [
+            { localName: "element1", nsURI: null },
+            { localName: "element2", nsURI: null },
+            { localName: "element3", nsURI: "http://namespace1" }
+        ];
+
+        var actual = [];
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+    
+        odatajs.xml.xmlChildElements(root, function (child) {
+            djstest.log("in child elements callback");
+            actual.push({
+                localName: odatajs.xml.xmlLocalName(child),
+                nsURI: odatajs.xml.xmlNamespaceURI(child)
+            });
+        });
+
+        djstest.assertAreEqualDeep(actual, expected, "xml.childElements didn't return the expected elements");
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlAttributesTest() {
+        var xml = "\
+         <root xmlns:n1=\"http://namespace1\" \r\n\
+               xml:base=\"http://base.org\" \r\n\
+               attribute=\"value\" \r\n\
+               n1:nsAttribute=\"nsValue\" />\r\n";
+
+        var expected = {
+            n1: { localName: "n1", nsURI: "http://www.w3.org/2000/xmlns/", value: "http://namespace1" },
+            base: { localName: "base", nsURI: "http://www.w3.org/XML/1998/namespace", value: "http://base.org" },
+            attribute: { localName: "attribute", nsURI: null, value: "value" },
+            nsAttribute: { localName: "nsAttribute", nsURI: "http://namespace1", value: "nsValue" }
+        };
+
+        var actual = {};
+
+        var doc = odatajs.xml.xmlParse(xml);
+        var root = odatajs.xml.xmlFirstChildElement(doc);
+
+        odatajs.xml.xmlAttributes(root, function (attribute) {
+            djstest.log("in child elements callback");
+            var localName = odatajs.xml.xmlLocalName(attribute);
+            actual[localName] = {
+                localName: localName, 
+                nsURI: odatajs.xml.xmlNamespaceURI(attribute),
+                value: attribute.value
+            };
+        });
+
+        djstest.assertAreEqualDeep(actual, expected, "xml.attributes returned didn't return the expected attributes");
+        djstest.done();
+    });
+
+    djstest.addTest(function hasLeadingOrTrailingWhitespaceTest() {
+        // tests are in text / expected format.
+        var tests = [
+            { t: "", r: false },
+            { t: " ", r: true },
+            { t: "text", r: false },
+            { t: "text with spaces", r: false },
+            { t: "not \r\n really", r: false },
+            { t: " at start", r: true },
+            { t: "at end ", r: true },
+            { t: "end\r", r: true },
+            { t: "end\n", r: true },
+            { t: "end\r\n", r: true }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var result = odatajs.xml.hasLeadingOrTrailingWhitespace(tests[i].t);
+            djstest.assertAreEqual(result, tests[i].r, "match for " + tests[i].t);
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function xmlInnerTextTest() {
+        // Tests are in test / expected format.
+        var tests = [
+            { t: "<t>text</t>", r: "text" },
+            { t: "<t>text with a <![CDATA[cdata block]]></t>", r: "text with a cdata block" },
+            { t: "<t> text </t>", r: " text " },
+            { t: "<t> </t>", r: null },
+            { t: "<t> <b>text</b> </t>", r: null },
+            { t: "<t> preceding</t>", r: " preceding" },
+            { t: "<t xml:space='preserve'> <b>text</b> </t>", r: "  " },
+            { t: "<t xml:space='default'> <b>text</b> </t>", r: null}
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var test = tests[i];
+            var doc = odatajs.xml.xmlParse(test.t);
+            var actual = odatajs.xml.xmlInnerText(doc);
+            djstest.assertAreEqual(actual, test.r, "test for [" + test.t + "]");
+        }
+
+        djstest.done();
+    });
+
+    // DATAJS INTERNAL END
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/run-tests.wsf
----------------------------------------------------------------------
diff --git a/odatajs/tests/run-tests.wsf b/odatajs/tests/run-tests.wsf
new file mode 100644
index 0000000..263bae0
--- /dev/null
+++ b/odatajs/tests/run-tests.wsf
@@ -0,0 +1,435 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<job>
+    <runtime>
+        <description>Test driver for running datajs tests - run from the same directory as the script</description>
+        <comment>
+            Result codes:
+            0 - success
+            1 - failed to launch tests
+            2 - tests failed
+        </comment>
+    </runtime>
+    <script language="JScript" src="test-list.js" />
+    <script language="JScript">
+
+        var exitCode;
+        var fso = WScript.CreateObject("Scripting.FileSystemObject");
+        var shell = WScript.CreateObject("WScript.Shell");
+
+        function attempt(action, interval, maxAttempts) {
+            /// <summary>Attempt an action at an interval, optionally for a maximum number of attempts</summary>
+            /// <param name="action">Action callback; should return boolean whether it succeeded</param>
+            /// <param name="interval">Interval (milliseconds) between attempts</param>
+            /// <param name="maxAttempts">(Optional) Maximum number of attempts. Infinite if undefined.</param>
+            /// <returns>Whether the action succeeded</returns>
+            var done = false;
+            var attempts = 0;
+            while (!done) {
+                var success = action();
+                if (maxAttempts !== undefined) {
+                    attempts++;
+                }
+                done = success === true || (maxAttempts !== undefined && attempts >= maxAttempts);
+                if (!done) {
+                    WScript.Sleep(interval);
+                }
+            }
+
+            return success;
+        }
+
+        function parseJson(text) {
+            /// <summary>Parses a JSON document, removes the 'd' wrapper.</summary>
+            try {
+                return eval("(" + text + ")").d;
+            } catch (e) {
+                throw { message: "Error parsing JSON: [" + text + "]" };
+            }
+        }
+
+        function SaveTextToFile(content, path) {
+            /// <summary>Saves text content into a file.</summary>
+            /// <param name="content" type="String">Content to save.</param>
+            /// <param name="path" type="String">Path of file to save into.</param>
+            var ForReading = 1, ForWriting = 2;
+            var file = fso.OpenTextFile(path, ForWriting, true, -1 /* open as unicode */);
+            file.Write(content);
+            file.Close();
+        }
+
+        function GetUrlSync(url) {
+            var xhr;
+            xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+            xhr.open("GET", url, false);
+            xhr.send();
+            return xhr.responseText;
+        }
+
+        function LaunchBrowser(browsers, serviceRoot, followingPages, url, testRunId, outputDirectory) {
+            /// <summary>Launches a browsers and waits until the service tells us the run is complete.</summary>
+            /// <param name="browsers">Browsers to run.</param>
+            /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
+            /// <param name="followingPages" type="Array">Array of pages that should follow the given url.</param>
+            /// <param name="url" type="String">URL of the page to start the browser on.</param>
+            /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
+            /// <param name="outputDirectory" type="String">Directory in which to output screenshots.</param>
+
+            for (browserName in browsers) {
+                var xhr;
+                var markInProgressUrl = serviceRoot + "MarkInProgress?testRunId=" + testRunId;
+                GetUrlSync(markInProgressUrl);
+
+                // Add all the pages that follow the given URL.
+                if (followingPages && followingPages.length > 0) {
+                    var addFilesUrl = serviceRoot + "AddTestPages?testRunId=" + testRunId + "&pages=" + followingPages.join();
+                    GetUrlSync(addFilesUrl);
+                }
+
+                var setPrefixUrl = serviceRoot + "SetTestNamePrefix?testRunId=" + testRunId + "&prefix=" + browserName + "-";
+                GetUrlSync(setPrefixUrl);
+
+                exitCode = 0;
+                var response;
+
+                // Only the first location found from the browsers array is used. If none of the listed locations of the browser exist and the browser argument was 
+                // explicitly used then an exception is thrown.
+                var browserFound = false;
+                for (var i = 0; i < browsers[browserName].length && !browserFound; i++) {
+                    var path = shell.ExpandEnvironmentStrings(browsers[browserName][i]);
+                    if (fso.FileExists(path)) {
+                        browserFound = true;
+
+                        WScript.Echo("Navigating to " + url + " with " + path);
+                        var browser = shell.Exec("\"" + path + "\" " + url);
+
+                        var checkRunUrl = serviceRoot + "IsTestRunInProgress?testRunId=" + testRunId;
+                        WScript.Echo("Monitoring status on " + checkRunUrl);
+
+                        var interval = 2000;
+                        var maxAttempts = WScript.Arguments.Named.Exists("timeout") ? Math.floor((WScript.Arguments.Named.Item("timeout") / interval) * 1000) : undefined;
+                        var success = attempt(function () {
+                            return parseJson(GetUrlSync(checkRunUrl)) !== true;
+                        }, interval, maxAttempts);
+                        if (!success) {
+                            WScript.Echo("Timed out waiting for test to complete");
+                            exitCode = 2;
+                        }
+
+                        RunCommand("taskkill.exe /pid " + browser.ProcessID, true);
+                    }
+                }
+
+                // If the "/browsers" argument was explicitly used and all location have been checked, then throw an exception.
+                if (!browserFound) {
+                    var message = "Unable to find browser at: " + path;
+                    if (WScript.Arguments.Named.Exists("browsers")) {
+                        throw { message: message };
+                    } else {
+                        WScript.Echo(message);
+                    }
+                }
+            }
+        }
+
+        function WriteTestRunResults(serviceRoot, testRunId, outputDirectory) {
+            /// <summary>Writes the results of the test run to disk and updates the overall status.</summary>
+            /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
+            /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
+            /// <param name="outputDirectory" type="String">Directory in which to write test result files.</param>
+
+            var getResultsUrl = serviceRoot + "GetTestRunResults?testRunId=" + testRunId;
+            WScript.Echo("Querying " + getResultsUrl);
+
+            var response = GetUrlSync(getResultsUrl);
+
+            var resultsPath = outputDirectory + "\\results.trx";
+            WScript.Echo("Writing results.trx file to " + resultsPath);
+            SaveTextToFile(response, resultsPath);
+
+            var xml = new ActiveXObject("Msxml2.DOMDocument.6.0");
+            xml.loadXML(response);
+            xml.setProperty("SelectionNamespaces", "xmlns:trx='http://microsoft.com/schemas/VisualStudio/TeamTest/2010'");
+            xml.setProperty("SelectionLanguage", "XPath");
+            var resultNode = xml.selectSingleNode("/trx:TestRun/trx:ResultSummary");
+            if (resultNode === null) {
+                throw { message: "Unable to find results summary" };
+            }
+
+            var outcome = resultNode.getAttribute("outcome");
+            if (outcome !== "Passed") {
+                WScript.Echo("Outcome: " + outcome);
+                var failedTests = xml.selectNodes("/trx:TestRun/trx:Results/trx:UnitTestResult[@outcome != 'Passed']/@testName");
+                for (var i = 0; i < failedTests.length; i++) {
+                    WScript.Echo("  Failed test: " + failedTests[i].value);
+                }
+                exitCode = 2;
+            } else {
+                WScript.Echo("All tests passed.");
+            }
+        }
+
+        function CheckUrl(url) {
+            var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+            xhr.open("GET", url, false);
+            var success = false;
+            try {
+                xhr.send();
+                success = (xhr.status === 200);
+                if (!success) {
+                    WScript.Echo("status: " + xhr.status + " - " + xhr.statusText);
+                }
+            } catch (err) {
+                WScript.Echo("error: " + err.message);
+            }
+
+            return success;
+        }
+
+        function ExpandWildcard(path) {
+            var wcRegEx = /\\\*\*?\\/;
+            var wcMatch = wcRegEx.exec(path);
+
+            var paths = [];
+            if (wcMatch !== null) {
+                var recursive = wcMatch[0] === "\\**\\";
+                var basePath = path.substring(0, wcMatch.index);
+                var relativePath = path.substring(wcMatch.index + wcMatch[0].length);
+
+                if (fso.FolderExists(basePath)) {
+                    var folder = fso.GetFolder(basePath);
+                    var subFolders = new Enumerator(folder.SubFolders);
+
+                    paths = paths.concat(ExpandWildcard(basePath + "\\" + relativePath));
+
+                    for (; !subFolders.atEnd(); subFolders.moveNext()) {
+                        var expandedPath = subFolders.item().Path + "\\"
+                        if (recursive) {
+                            expandedPath += "**\\";
+                        }
+                        expandedPath += path.substring(wcMatch.index + wcMatch[0].length);
+                        paths = paths.concat(ExpandWildcard(expandedPath));
+                    }
+                }
+            } else {
+                paths.push(path);
+            }
+            return paths;
+        }
+
+        function FindFirstPath(candidates) {
+            /// <summary>Finds the first path present from a candidate list.</summary>
+            /// <param name="candidates" type="Array">Array of paths (possibly with environment variables).</param>
+            /// <returns type="String">The first folder on disk found; null if none are present.</returns>
+
+            var paths = [];
+
+            for (var i = 0; i < candidates.length; i++) {
+                var path = shell.ExpandEnvironmentStrings(candidates[i]);
+                paths = paths.concat(ExpandWildcard(path));
+            }
+
+            for (var i = 0; i < paths.length; i++) {
+                if (fso.FolderExists(paths[i]) || fso.FileExists(paths[i])) {
+                    return paths[i];
+                }
+            }
+            return null;
+        }
+
+        function RunCommand(command, waitForExit, expectedExitCode) {
+            /// <summary>Runs a command or program</summary>
+            /// <param name="command" type="String">Command to run</param>
+            /// <param name="waitForExit" type="Boolean">Whether to wait for program to exit</param>
+            /// <param name="expectedExitCode" type="Integer">If waitForExit is true, throw if the exit code is not expected</param>
+            /// <returns type="Integer">The exitcode if waitForExit is true; always 0 if waitForExit is false</returns>
+            WScript.Echo("[cmd] " + command);
+            var exitCode = shell.Run(command, 0, waitForExit);
+            if (expectedExitCode !== undefined && exitCode !== expectedExitCode) {
+                throw { message: "Process exited with unexpected exit code. (Expected: " + expectedExitCode + ", Actual: " + exitCode + ")" };
+            } else {
+                return exitCode;
+            }
+        }
+
+        function SetupWebDevServer() {
+            /// <summary>Starts up IIS Express if it's not running.</summary>
+            /// <returns type="String">The URL to the server root.</returns>
+            var siteName = "DataJS Development Site";
+            var appName = "datajs";
+            var port = "8989";
+            var result = "http://" + shell.ExpandEnvironmentStrings("%COMPUTERNAME%").toLowerCase() + ":" + port + "/" + appName + "/";
+            var url = result + "tests/common/TestLogger.svc";
+
+            var success = CheckUrl(url);
+
+            if (!success) {
+                // Assume that we need to launch this.
+                var src = fso.GetAbsolutePathName("..");
+
+                var folder = FindFirstPath([
+                    "%ProgramFiles(x86)%\\IIS Express",
+                    "%ProgramFiles%\\IIS Express"]);    
+
+                if (!folder) {
+                    throw { message: "Unable to find path to IIS Express" };
+                }
+
+                var appCmd = "\"" + folder + "\\appcmd.exe\"";
+                var iisExpress = "\"" + folder + "\\iisexpress.exe\"";
+
+                // Delete site if it already exists
+                WScript.Echo("Checking if site '" + siteName + "' already exists...");
+                if (RunCommand(appCmd + " list site \"" + siteName + "\"", true) === 0) {
+                    WScript.Echo("Deleting existing site '" + siteName + "'...");
+                    RunCommand(appCmd + " delete site \"" + siteName + "\"", true, 0);
+                }
+
+                // Create site and app
+                WScript.Echo("Creating site '" + siteName + "'...");
+                RunCommand(appCmd + " add site /name:\"" + siteName + "\" /bindings:http/*:" + port + ": /physicalPath:%IIS_BIN%\\AppServer\\empty_wwwroot", true, 0);
+
+                WScript.Echo("Creating application '" + appName + "'...");
+                RunCommand(appCmd + " add app /site.name:\"" + siteName + "\" /path:\"/" + appName + "\" /physicalPath:\"" + src + "\"", true, 0);
+
+                // Start the server
+                WScript.Echo("Starting IIS Express server...");
+                RunCommand(iisExpress + " /site:\"" + siteName + "\" /trace:error");
+
+                WScript.Sleep(2 * 1000);
+                success = attempt(function () {
+                    WScript.Echo("Waiting for server to come up, looking for " + url + " ...");
+                    return CheckUrl(url);
+                }, 5 * 1000, 3);
+
+                if (!success) {
+                    throw { message: "Unable to verify the URL at " + url };
+                }
+            }
+            return result;
+        }
+
+        function CreateTestRunId(serviceRoot) {
+            /// <summary>Creates a new test run ID from the service.</summary>
+            /// <param name="serviceRoot" type="String">Root of logger service.</param>
+            /// <returns type="String">The test run ID created.</returns>
+            var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+            var url = serviceRoot + "CreateTestRun";
+            xhr.open("GET", url, false);
+            WScript.Echo("URL: " + url);
+            xhr.send();
+
+            var response = xhr.responseText;
+            var result = parseJson(response);
+            return result;
+        }
+
+        function GetBrowsers() {
+            /// <summary>Gets the browsers that should be used for running the tests.</summary>
+            /// <returns type="Object">Dictionary object containing the browser and its executable path as key value pairs.</returns>
+            var localAppData = fso.FolderExists(shell.ExpandEnvironmentStrings("%LOCALAPPDATA%")) ? "%LOCALAPPDATA%" : "%USERPROFILE%\\Local Settings\\Application Data";
+            var programFiles = fso.FolderExists(shell.ExpandEnvironmentStrings("%ProgramFiles(x86)%")) ? "%ProgramFiles(x86)%" : "%ProgramFiles%";
+            var browsers = {
+                IE8: [programFiles + "\\Internet Explorer\\iexplore.exe"],
+                Firefox4: [programFiles + "\\Mozilla Firefox\\firefox.exe"],
+                Chrome: [programFiles + "\\Google\\Chrome\\Application\\chrome.exe", localAppData + "\\Google\\Chrome\\Application\\chrome.exe"],
+                Safari5: [programFiles + "\\Safari\\safari.exe"],
+                Opera: [programFiles + "\\Opera\\opera.exe"]
+            };
+
+            var browsersToRun = {};
+
+            if (WScript.Arguments.Named.Exists("browsers")) {
+                browserNames = WScript.Arguments.Named.Item("browsers").split(',');
+                for (i in browserNames) {
+                    var browserName = browserNames[i];
+                    if (browsers[browserName]) {
+                        browsersToRun[browserName] = browsers[browserName];
+                    } else {
+                        throw { message: "Unknown browser: " + browserName };
+                    }
+                }
+            }
+            else {
+                browsersToRun = browsers;
+            }
+
+            return browsersToRun;
+        }
+
+        function GetTestFilesList() {
+            /// <summary>Gets the list of test files that are going to be executed in the test run.</summary>
+            /// <returns type="Array">The list of test files.</returns>
+            var testFilesList = null;
+            if (WScript.Arguments.Named.Exists("testFiles")) {
+                testFilesList = WScript.Arguments.Named.Item("testFiles").split(',');
+            }
+
+            if (testFilesList === null) {
+                testFilesList = getAllTestFiles();
+            }
+
+            WScript.Echo("Test files to be executed: " + testFilesList.toString());
+            return testFilesList;
+        }
+
+        function GetOutputDirectory() {
+            /// <summary>Gets the test run output directory.</summary>
+            /// <returns type="String">Output directory.</returns>
+            var result;
+            if (WScript.Arguments.Named.Exists("outputDirectory")) {
+                result = WScript.Arguments.Named.Item("outputDirectory");
+            } else {
+                result = shell.ExpandEnvironmentStrings("%DJSOUT%\\JSLib.sln\\tests");
+            }
+
+
+            return result;
+        }
+
+        try {
+            var root = SetupWebDevServer();
+            var serviceRoot = root + "tests/common/TestLogger.svc/";
+            var testRunId = CreateTestRunId(serviceRoot);
+            WScript.Echo("Test Run ID: " + testRunId);
+
+            var testFilesList = GetTestFilesList();
+            var browsers = GetBrowsers();
+            var outputDirectory = GetOutputDirectory();
+
+            if (testFilesList.length > 0) {
+                var url = root + "tests/" + testFilesList[0] + "?testRunId=" + testRunId;
+                LaunchBrowser(browsers, serviceRoot, testFilesList.splice(1, testFilesList.length), url, testRunId, outputDirectory);
+                WriteTestRunResults(serviceRoot, testRunId, outputDirectory);
+            }
+            else {
+                WScript.Echo("No test files specified to run.");
+            }
+        } catch (e) {
+            WScript.Echo("Error running tests");
+            for (var p in e) WScript.Echo(p + ": " + e[p]);
+            exitCode = 1;
+        }
+
+        WScript.Quit(exitCode);
+
+    </script>
+</job>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/store-indexeddb-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/store-indexeddb-tests.js b/odatajs/tests/store-indexeddb-tests.js
new file mode 100644
index 0000000..47690a4
--- /dev/null
+++ b/odatajs/tests/store-indexeddb-tests.js
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+ 
+// store-indexeddb-tests.js
+
+(function (window, undefined) {
+    // DATAJS INTERNAL START
+    var unexpectedSuccess = function (key, value) {
+        djstest.fail("Unexpected call to success handler: key = " + key + ", value = " + value);
+        djstest.done();
+    };
+
+    var unexpectedError = function (e) {
+        djstest.fail("Unexpected call to error handler: " + djstest.toString(e));
+        djstest.done();
+    };
+
+    var storeCounter = 0;
+    var storeName = "test";
+
+    var getNextStoreName = function () {
+        storeCounter++;
+        return getCurrentStoreName();
+    };
+
+    var getCurrentStoreName = function(){
+        return storeName + storeCounter;
+    };
+
+    var oldWindowOnError;
+
+    if (djstest.indexedDB) {
+        module("Unit", {
+            setup: function () {
+                djstest.wait(function (done) {
+                    djstest.cleanStoreOnIndexedDb([{ name: getNextStoreName() }], done);
+                });
+
+                // FireFox 7.0.1 bubbles an error event when there is an IndexedDB error, even when the error has been handled graciously.
+                // This is a work around to keep QUnit from reporting false failures in IndexedDB negative tests.
+                oldWindowOnError = window.onerror;
+                window.onerror = null;
+            },
+            teardown: function () {
+                var store = this.store;
+                if (store) {
+                    store.close();
+                }
+
+                djstest.wait(function (done) {
+                    djstest.cleanStoreOnIndexedDb([store], done);
+                });
+
+
+                // Restore QUnit's onerror handler.
+                window.onerror = oldWindowOnError;
+            }
+        });
+
+        djstest.addTest(function testIndexedDBStoreConstructor() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            djstest.assertAreEqual(store.name, getCurrentStoreName());
+            djstest.assertAreEqual(store.mechanism, "indexeddb");
+            djstest.done();
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddGet() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                djstest.assertAreEqual(key, "key");
+                djstest.assertAreEqual(value, "value");
+                store.read("key", function (key, value) {
+                    djstest.assertAreEqual(key, "key");
+                    djstest.assertAreEqual(value, "value");
+                    djstest.done();
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddUpdateGet() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.update("key", "value2", function (key, value) {
+                    djstest.assertAreEqual(key, "key");
+                    djstest.assertAreEqual(value, "value2");
+                    store.read("key", function (key, value) {
+                        djstest.assertAreEqual(key, "key");
+                        djstest.assertAreEqual(value, "value2");
+                        djstest.done();
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddOrUpdateGet() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.addOrUpdate("key", "value", function (key, value) {
+                djstest.assertAreEqual(key, "key");
+                djstest.assertAreEqual(value, "value");
+                store.addOrUpdate("key", "value2", function (key, value) {
+                    djstest.assertAreEqual(key, "key");
+                    djstest.assertAreEqual(value, "value2");
+                    store.read("key", function (key, value) {
+                        djstest.assertAreEqual(key, "key");
+                        djstest.assertAreEqual(value, "value2");
+                        djstest.done();
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddRemoveContains() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.contains("key", function (result) {
+                    djstest.assert(result);
+                    store.remove("key", function () {
+                        djstest.pass("key removed");
+                        store.contains("key", function (result) {
+                            djstest.assert(!result);
+                            djstest.done();
+                        }, unexpectedError);
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddConsecutiveGetAllKeys() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.add("key2", "value2", function (key, value) {
+                    store.add("key3", "value3", function (key, value) {
+                        store.getAllKeys(function (keys) {
+                            djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
+                            djstest.done();
+                        }, unexpectedError);
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddArrayClear() {
+            var addedKeys = ["key", "key2", "key3"];
+            var addedValues = ["value", "value2", "value3"];
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add(addedKeys, addedValues, function (keys, values) {
+                djstest.assertAreEqualDeep(keys, addedKeys);
+                djstest.assertAreEqualDeep(values, addedValues);
+                store.clear(function () {
+                    store.getAllKeys(function (keys) {
+                        djstest.assertAreEqualDeep(keys, []);
+                        djstest.done();
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddArrayUpdateArrayGetArray() {
+            var addedKeys = ["key", "key2", "key3"];
+            var addedValues = ["value", "value2", "value3"];
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add(addedKeys, addedValues, function (keys, values) {
+                djstest.assertAreEqualDeep(keys, addedKeys);
+                djstest.assertAreEqualDeep(values, addedValues);
+                var updatedKeys = ["key", "key3"];
+                var updatedValues = ["newValue", "newValue3"];
+                store.update(updatedKeys, updatedValues, function (keys, values) {
+                    djstest.assertAreEqualDeep(keys, updatedKeys);
+                    djstest.assertAreEqualDeep(values, updatedValues);
+                    store.read(addedKeys, function (keys, values) {
+                        djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
+                        djstest.assertAreEqualDeep(values, ["newValue", "value2", "newValue3"]);
+                        djstest.done();
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddOrUpdateArrayGetArray() {
+            var expectedKeys = ["key", "key2", "key3"];
+            var expectedValues = ["value", "value2", "value3"];
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key2", "value", function (key, value) {
+                store.addOrUpdate(expectedKeys, expectedValues, function (keys, values) {
+                    djstest.assertAreEqualDeep(keys, expectedKeys);
+                    djstest.assertAreEqualDeep(values, expectedValues);
+                    store.read(keys, function (keys, values) {
+                        djstest.assertAreEqualDeep(values, expectedValues);
+                        djstest.done();
+                    }, unexpectedError);
+                }, unexpectedError);
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddDuplicate() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.add("key", "value2", unexpectedSuccess, function (err) {
+                    djstest.pass("Error callback called as expected");
+                    djstest.done();
+                });
+            }, unexpectedError);
+        });
+
+        djstest.addTest(function testIndexedDBStoreAddArrayDuplicate() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add(["key", "key2", "key"], ["value", "value2", "value3"], unexpectedSuccess, function (err) {
+                djstest.pass("Error callback called as expected");
+                djstest.done();
+            });
+        });
+
+        djstest.addTest(function testIndexedDBStoreGetArrayNonExistent() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.read(["key", "badkey"], function (keys, values) {
+                    djstest.assertAreEqualDeep(keys, ["key", "badkey"]);
+                    djstest.assertAreEqualDeep(values, ["value", undefined]);
+                    djstest.done();
+                }, unexpectedError);
+            });
+        });
+
+        djstest.addTest(function testIndexedDBStoreUpdateNonExistent() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.update("badkey", "badvalue", unexpectedSuccess, function (err) {
+                djstest.pass("Error callback called as expected");
+                djstest.done();
+            });
+        });
+
+        djstest.addTest(function testIndexedDBStoreUpdateArrayNonExistent() {
+            var store = this.store = window.odatajs.store.IndexedDBStore.create(getCurrentStoreName());
+            store.add("key", "value", function (key, value) {
+                store.update(["key", "badkey"], ["value", "badvalue"], unexpectedSuccess, function (err) {
+                    djstest.pass("Error callback called as expected");
+                    store.read("key", function (key, value) {
+                        djstest.assertAreEqual(value, "value", "value was not changed");
+                        djstest.done();
+                    }), unexpectedError;
+                });
+            }, unexpectedError);
+        });
+    }
+    // DATAJS INTERNAL END
+})(this);
\ No newline at end of file


[42/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/utils.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/utils.js b/datajs/src/lib/odata/utils.js
deleted file mode 100644
index efaea05..0000000
--- a/datajs/src/lib/odata/utils.js
+++ /dev/null
@@ -1,1261 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- /** @module odata/utils */
-
-var utils    = require('./../datajs.js').utils;
-
-// Imports
-var assigned = utils.assigned;
-var contains = utils.contains;
-var find = utils.find;
-var isArray = utils.isArray;
-var isDate = utils.isDate;
-var isObject = utils.isObject;
-var parseInt10 = utils.parseInt10;
-
-
-/** Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property
- * @param {string} value - Value of the data item from which the type name is going to be retrieved.
- * @param {object} [metadata] - Object containing metadata about the data tiem.
- * @returns {string} Data item type name; null if the type name cannot be found within the value or the metadata
- * This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
- * it will try to recover it from the metadata.  If both attempts fail, it will return null.
- */
-var dataItemTypeName = function (value, metadata) {
-    var valueTypeName = ((value && value.__metadata) || {}).type;
-    return valueTypeName || (metadata ? metadata.type : null);
-};
-
-var EDM = "Edm.";
-var EDM_BINARY = EDM + "Binary";
-var EDM_BOOLEAN = EDM + "Boolean";
-var EDM_BYTE = EDM + "Byte";
-var EDM_DATETIME = EDM + "DateTime";
-var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
-var EDM_DECIMAL = EDM + "Decimal";
-var EDM_DOUBLE = EDM + "Double";
-var EDM_GUID = EDM + "Guid";
-var EDM_INT16 = EDM + "Int16";
-var EDM_INT32 = EDM + "Int32";
-var EDM_INT64 = EDM + "Int64";
-var EDM_SBYTE = EDM + "SByte";
-var EDM_SINGLE = EDM + "Single";
-var EDM_STRING = EDM + "String";
-var EDM_TIME = EDM + "Time";
-
-var GEOGRAPHY = "Geography";
-var EDM_GEOGRAPHY = EDM + GEOGRAPHY;
-var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
-var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
-var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
-var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
-var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
-var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
-var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
-
-var GEOGRAPHY_POINT = GEOGRAPHY + "Point";
-var GEOGRAPHY_LINESTRING = GEOGRAPHY + "LineString";
-var GEOGRAPHY_POLYGON = GEOGRAPHY + "Polygon";
-var GEOGRAPHY_COLLECTION = GEOGRAPHY + "Collection";
-var GEOGRAPHY_MULTIPOLYGON = GEOGRAPHY + "MultiPolygon";
-var GEOGRAPHY_MULTILINESTRING = GEOGRAPHY + "MultiLineString";
-var GEOGRAPHY_MULTIPOINT = GEOGRAPHY + "MultiPoint";
-
-var GEOMETRY = "Geometry";
-var EDM_GEOMETRY = EDM + GEOMETRY;
-var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
-var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
-var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
-var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
-var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
-var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
-var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
-
-var GEOMETRY_POINT = GEOMETRY + "Point";
-var GEOMETRY_LINESTRING = GEOMETRY + "LineString";
-var GEOMETRY_POLYGON = GEOMETRY + "Polygon";
-var GEOMETRY_COLLECTION = GEOMETRY + "Collection";
-var GEOMETRY_MULTIPOLYGON = GEOMETRY + "MultiPolygon";
-var GEOMETRY_MULTILINESTRING = GEOMETRY + "MultiLineString";
-var GEOMETRY_MULTIPOINT = GEOMETRY + "MultiPoint";
-
-var GEOJSON_POINT = "Point";
-var GEOJSON_LINESTRING = "LineString";
-var GEOJSON_POLYGON = "Polygon";
-var GEOJSON_MULTIPOINT = "MultiPoint";
-var GEOJSON_MULTILINESTRING = "MultiLineString";
-var GEOJSON_MULTIPOLYGON = "MultiPolygon";
-var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
-
-var primitiveEdmTypes = [
-    EDM_STRING,
-    EDM_INT32,
-    EDM_INT64,
-    EDM_BOOLEAN,
-    EDM_DOUBLE,
-    EDM_SINGLE,
-    EDM_DATETIME,
-    EDM_DATETIMEOFFSET,
-    EDM_TIME,
-    EDM_DECIMAL,
-    EDM_GUID,
-    EDM_BYTE,
-    EDM_INT16,
-    EDM_SBYTE,
-    EDM_BINARY
-];
-
-var geometryEdmTypes = [
-    EDM_GEOMETRY,
-    EDM_GEOMETRY_POINT,
-    EDM_GEOMETRY_LINESTRING,
-    EDM_GEOMETRY_POLYGON,
-    EDM_GEOMETRY_COLLECTION,
-    EDM_GEOMETRY_MULTIPOLYGON,
-    EDM_GEOMETRY_MULTILINESTRING,
-    EDM_GEOMETRY_MULTIPOINT
-];
-
-var geometryTypes = [
-    GEOMETRY,
-    GEOMETRY_POINT,
-    GEOMETRY_LINESTRING,
-    GEOMETRY_POLYGON,
-    GEOMETRY_COLLECTION,
-    GEOMETRY_MULTIPOLYGON,
-    GEOMETRY_MULTILINESTRING,
-    GEOMETRY_MULTIPOINT
-];
-
-var geographyEdmTypes = [
-    EDM_GEOGRAPHY,
-    EDM_GEOGRAPHY_POINT,
-    EDM_GEOGRAPHY_LINESTRING,
-    EDM_GEOGRAPHY_POLYGON,
-    EDM_GEOGRAPHY_COLLECTION,
-    EDM_GEOGRAPHY_MULTIPOLYGON,
-    EDM_GEOGRAPHY_MULTILINESTRING,
-    EDM_GEOGRAPHY_MULTIPOINT
-];
-
-var geographyTypes = [
-    GEOGRAPHY,
-    GEOGRAPHY_POINT,
-    GEOGRAPHY_LINESTRING,
-    GEOGRAPHY_POLYGON,
-    GEOGRAPHY_COLLECTION,
-    GEOGRAPHY_MULTIPOLYGON,
-    GEOGRAPHY_MULTILINESTRING,
-    GEOGRAPHY_MULTIPOINT
-];
-
-/** Invokes a function once per schema in metadata.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @param {Function} callback - Callback function to invoke once per schema.
- * @returns The first truthy value to be returned from the callback; null or the last falsy value otherwise.
- */
-function forEachSchema(metadata, callback) {
-    
-
-    if (!metadata) {
-        return null;
-    }
-
-    if (isArray(metadata)) {
-        var i, len, result;
-        for (i = 0, len = metadata.length; i < len; i++) {
-            result = forEachSchema(metadata[i], callback);
-            if (result) {
-                return result;
-            }
-        }
-
-        return null;
-    } else {
-        if (metadata.dataServices) {
-            return forEachSchema(metadata.dataServices.schema, callback);
-        }
-
-        return callback(metadata);
-    }
-}
-
-/** Formats a millisecond and a nanosecond value into a single string.
- * @param {Numaber} ms - Number of milliseconds to format.</param>
- * @param {Numaber} ns - Number of nanoseconds to format.</param>
- * @returns {String} Formatted text.
- * If the value is already as string it's returned as-is.</remarks>
- */
-function formatMilliseconds(ms, ns) {
-
-    // Avoid generating milliseconds if not necessary.
-    if (ms === 0) {
-        ms = "";
-    } else {
-        ms = "." + formatNumberWidth(ms.toString(), 3);
-    }
-    if (ns > 0) {
-        if (ms === "") {
-            ms = ".000";
-        }
-        ms += formatNumberWidth(ns.toString(), 4);
-    }
-    return ms;
-}
-
-function formatDateTimeOffsetJSON(value) {
-    return "\/Date(" + value.getTime() + ")\/";
-}
-
-/** Formats a DateTime or DateTimeOffset value a string.
- * @param {Date} value - Value to format
- * @returns {String} Formatted text.
- * If the value is already as string it's returned as-is
-´*/
-function formatDateTimeOffset(value) {
-
-    if (typeof value === "string") {
-        return value;
-    }
-
-    var hasOffset = isDateTimeOffset(value);
-    var offset = getCanonicalTimezone(value.__offset);
-    if (hasOffset && offset !== "Z") {
-        // We're about to change the value, so make a copy.
-        value = new Date(value.valueOf());
-
-        var timezone = parseTimezone(offset);
-        var hours = value.getUTCHours() + (timezone.d * timezone.h);
-        var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
-
-        value.setUTCHours(hours, minutes);
-    } else if (!hasOffset) {
-        // Don't suffix a 'Z' for Edm.DateTime values.
-        offset = "";
-    }
-
-    var year = value.getUTCFullYear();
-    var month = value.getUTCMonth() + 1;
-    var sign = "";
-    if (year <= 0) {
-        year = -(year - 1);
-        sign = "-";
-    }
-
-    var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
-
-    return sign +
-        formatNumberWidth(year, 4) + "-" +
-        formatNumberWidth(month, 2) + "-" +
-        formatNumberWidth(value.getUTCDate(), 2) + "T" +
-        formatNumberWidth(value.getUTCHours(), 2) + ":" +
-        formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
-        formatNumberWidth(value.getUTCSeconds(), 2) +
-        ms + offset;
-}
-
-/** Converts a duration to a string in xsd:duration format.
- * @param {Object} value - Object with ms and __edmType properties.
- * @returns {String} String representation of the time object in xsd:duration format.
- */
-function formatDuration(value) {
-
-    var ms = value.ms;
-
-    var sign = "";
-    if (ms < 0) {
-        sign = "-";
-        ms = -ms;
-    }
-
-    var days = Math.floor(ms / 86400000);
-    ms -= 86400000 * days;
-    var hours = Math.floor(ms / 3600000);
-    ms -= 3600000 * hours;
-    var minutes = Math.floor(ms / 60000);
-    ms -= 60000 * minutes;
-    var seconds = Math.floor(ms / 1000);
-    ms -= seconds * 1000;
-
-    return sign + "P" +
-           formatNumberWidth(days, 2) + "DT" +
-           formatNumberWidth(hours, 2) + "H" +
-           formatNumberWidth(minutes, 2) + "M" +
-           formatNumberWidth(seconds, 2) +
-           formatMilliseconds(ms, value.ns) + "S";
-}
-
-/** Formats the specified value to the given width.
- * @param {Number} value - Number to format (non-negative).
- * @param {Number} width - Minimum width for number.
- * @param {Boolean} append - Flag indicating if the value is padded at the beginning (false) or at the end (true).
- * @returns {String} Text representation.
- */
-function formatNumberWidth(value, width, append) {
-    var result = value.toString(10);
-    while (result.length < width) {
-        if (append) {
-            result += "0";
-        } else {
-            result = "0" + result;
-        }
-    }
-
-    return result;
-}
-
-/** Gets the canonical timezone representation.
- * @param {String} timezone - Timezone representation.
- * @returns {String} An 'Z' string if the timezone is absent or 0; the timezone otherwise.
- */
-function getCanonicalTimezone(timezone) {
-
-    return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
-}
-
-/** Gets the type of a collection type name.
- * @param {String} typeName - Type name of the collection.
- * @returns {String} Type of the collection; null if the type name is not a collection type.
- */
-function getCollectionType(typeName) {
-
-    if (typeof typeName === "string") {
-        var end = typeName.indexOf(")", 10);
-        if (typeName.indexOf("Collection(") === 0 && end > 0) {
-            return typeName.substring(11, end);
-        }
-    }
-    return null;
-}
-
-/** Sends a request containing OData payload to a server.
-* @param request - Object that represents the request to be sent..
-* @param success - Callback for a successful read operation.
-* @param error - Callback for handling errors.
-* @param handler - Handler for data serialization.
-* @param httpClient - HTTP client layer.
-* @param context - Context used for processing the request
-*/
-function invokeRequest(request, success, error, handler, httpClient, context) {
-
-    return httpClient.request(request, function (response) {
-        try {
-            if (response.headers) {
-                normalizeHeaders(response.headers);
-            }
-
-            if (response.data === undefined && response.statusCode !== 204) {
-                handler.read(response, context);
-            }
-        } catch (err) {
-            if (err.request === undefined) {
-                err.request = request;
-            }
-            if (err.response === undefined) {
-                err.response = response;
-            }
-            error(err);
-            return;
-        }
-        // errors in success handler for sync requests result in error handler calls. So here we fix this. 
-        try {
-            success(response.data, response);
-        } catch (err) {
-            err.bIsSuccessHandlerError = true;
-            throw err;
-        }
-    }, error);
-}
-
-/** Tests whether a value is a batch object in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is a batch object; false otherwise.
- */
-function isBatch(value) {
-
-    return isComplex(value) && isArray(value.__batchRequests);
-}
-
-// Regular expression used for testing and parsing for a collection type.
-var collectionTypeRE = /Collection\((.*)\)/;
-
-/** Tests whether a value is a collection value in the library's internal representation.
- * @param value - Value to test.
- * @param {Sting} typeName - Type name of the value. This is used to disambiguate from a collection property value.
- * @returns {Boolean} True is the value is a feed value; false otherwise.
- */
-function isCollection(value, typeName) {
-
-    var colData = value && value.results || value;
-    return !!colData &&
-        (isCollectionType(typeName)) ||
-        (!typeName && isArray(colData) && !isComplex(colData[0]));
-}
-
-/** Checks whether the specified type name is a collection type.
- * @param {String} typeName - Name of type to check.
- * @returns {Boolean} True if the type is the name of a collection type; false otherwise.
- */
-function isCollectionType(typeName) {
-    return collectionTypeRE.test(typeName);
-}
-
-/** Tests whether a value is a complex type value in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is a complex type value; false otherwise.
- */
-function isComplex(value) {
-
-    return !!value &&
-        isObject(value) &&
-        !isArray(value) &&
-        !isDate(value);
-}
-
-/** Checks whether a Date object is DateTimeOffset value
- * @param {Date} value - Value to check
- * @returns {Boolean} true if the value is a DateTimeOffset, false otherwise.
- */
-function isDateTimeOffset(value) {
-    return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
-}
-
-/** Tests whether a value is a deferred navigation property in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is a deferred navigation property; false otherwise.
- */
-function isDeferred(value) {
-
-    if (!value && !isComplex(value)) {
-        return false;
-    }
-    var metadata = value.__metadata || {};
-    var deferred = value.__deferred || {};
-    return !metadata.type && !!deferred.uri;
-}
-
-/** Tests whether a value is an entry object in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is an entry object; false otherwise.
- */
-function isEntry(value) {
-
-    return isComplex(value) && value.__metadata && "uri" in value.__metadata;
-}
-
-/** Tests whether a value is a feed value in the library's internal representation.
- * @param value - Value to test.
- * @param {Sting} typeName - Type name of the value. This is used to disambiguate from a collection property value.
- * @returns {Boolean} True is the value is a feed value; false otherwise.
- */
-function isFeed(value, typeName) {
-
-    var feedData = value && value.results || value;
-    return isArray(feedData) && (
-        (!isCollectionType(typeName)) &&
-        (isComplex(feedData[0]))
-    );
-}
-
-/** Checks whether the specified type name is a geography EDM type.
- * @param {String} typeName - Name of type to check.
- * @returns {Boolean} True if the type is a geography EDM type; false otherwise.
- */
-function isGeographyEdmType(typeName) {
-
-    //check with edm
-    var ret = contains(geographyEdmTypes, typeName) || 
-        (typeName.indexOf('.') === -1 && contains(geographyTypes, typeName));
-    return ret; 
-        
-}
-
-/** Checks whether the specified type name is a geometry EDM type.
- * @param {String} typeName - Name of type to check.
- * @returns {Boolean} True if the type is a geometry EDM type; false otherwise.
- */
-function isGeometryEdmType(typeName) {
-
-    var ret = contains(geometryEdmTypes, typeName) ||
-        (typeName.indexOf('.') === -1 && contains(geometryTypes, typeName));
-    return ret; 
-}
-
-/** Tests whether a value is a named stream value in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is a named stream; false otherwise.
- */
-function isNamedStream(value) {
-
-    if (!value && !isComplex(value)) {
-        return false;
-    }
-    var metadata = value.__metadata;
-    var mediaResource = value.__mediaresource;
-    return !metadata && !!mediaResource && !!mediaResource.media_src;
-}
-
-/** Tests whether a value is a primitive type value in the library's internal representation.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is a primitive type value.
- * Date objects are considered primitive types by the library.
- */
-function isPrimitive(value) {
-
-    return isDate(value) ||
-        typeof value === "string" ||
-        typeof value === "number" ||
-        typeof value === "boolean";
-}
-
-/** Checks whether the specified type name is a primitive EDM type.
- * @param {String} typeName - Name of type to check.
- * @returns {Boolean} True if the type is a primitive EDM type; false otherwise.
- */
-function isPrimitiveEdmType(typeName) {
-
-    return contains(primitiveEdmTypes, typeName);
-}
-
-/** Gets the kind of a navigation property value.
- * @param value - Value of the navigation property.
- * @param {Object} [propertyModel] - Object that describes the navigation property in an OData conceptual schema.
- * @returns {String} String value describing the kind of the navigation property; null if the kind cannot be determined.
- */
-function navigationPropertyKind(value, propertyModel) {
-
-    if (isDeferred(value)) {
-        return "deferred";
-    }
-    if (isEntry(value)) {
-        return "entry";
-    }
-    if (isFeed(value)) {
-        return "feed";
-    }
-    if (propertyModel && propertyModel.relationship) {
-        if (value === null || value === undefined || !isFeed(value)) {
-            return "entry";
-        }
-        return "feed";
-    }
-    return null;
-}
-
-/** Looks up a property by name.
- * @param {Array} properties - Array of property objects as per EDM metadata (may be null)
- * @param {String} name - Name to look for.
- * @returns {Object} The property object; null if not found.
- */
-function lookupProperty(properties, name) {
-
-    return find(properties, function (property) {
-        return property.name === name;
-    });
-}
-
-/** Looks up a type object by name.
- * @param {String} name - Name, possibly null or empty.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @param {String} kind - Kind of object to look for as per EDM metadata.
- * @returns An type description if the name is found; null otherwise
- */
-function lookupInMetadata(name, metadata, kind) {
-
-    return (name) ? forEachSchema(metadata, function (schema) {
-        return lookupInSchema(name, schema, kind);
-    }) : null;
-}
-
-/** Looks up a entity set by name.
- * @param {Array} properties - Array of entity set objects as per EDM metadata( may be null)
- * @param {String} name - Name to look for.
- * @returns {Object} The entity set object; null if not found.
- */
-function lookupEntitySet(entitySets, name) {
-
-    return find(entitySets, function (entitySet) {
-        return entitySet.name === name;
-    });
-}
-
-/** Looks up a entity set by name.
- * @param {Array} properties - Array of entity set objects as per EDM metadata (may be null)
- * @param {String} name - Name to look for.
- * @returns {Object} The entity set object; null if not found.
- */
-function lookupSingleton(singletons, name) {
-
-    return find(singletons, function (singleton) {
-        return singleton.name === name;
-    });
-}
-
-/** Looks up a complex type object by name.
- * @param {String} name - Name, possibly null or empty.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @returns A complex type description if the name is found; null otherwise.</returns>
- */
-function lookupComplexType(name, metadata) {
-
-    return lookupInMetadata(name, metadata, "complexType");
-}
-
-/** Looks up an entity type object by name.
- * @param {String} name - Name, possibly null or empty.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @returns An entity type description if the name is found; null otherwise.</returns>
- */
-function lookupEntityType(name, metadata) {
-
-    return lookupInMetadata(name, metadata, "entityType");
-}
-
-
-/** Looks up an
- * @param {String} name - Name, possibly null or empty.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @returns An entity container description if the name is found; null otherwise.</returns>
- */
-function lookupDefaultEntityContainer(metadata) {
-
-    return forEachSchema(metadata, function (schema) {
-        if (isObject(schema.entityContainer)) { 
-            return schema.entityContainer;
-        }
-    });
-}
-
-/** Looks up an entity container object by name.
- * @param {String} name - Name, possibly null or empty.
- * @param metadata - Metadata store; one of edmx, schema, or an array of any of them.
- * @returns An entity container description if the name is found; null otherwise.</returns>
- */
-function lookupEntityContainer(name, metadata) {
-
-    return lookupInMetadata(name, metadata, "entityContainer");
-}
-
-/** Looks up a function import by name.
- * @param {Array} properties - Array of function import objects as per EDM metadata (May be null)
- * @param {String} name - Name to look for.
- * @returns {Object} The entity set object; null if not found.
- */
-function lookupFunctionImport(functionImports, name) {
-    return find(functionImports, function (functionImport) {
-        return functionImport.name === name;
-    });
-}
-
-/** Looks up the target entity type for a navigation property.
- * @param {Object} navigationProperty - 
- * @param {Object} metadata - 
- * @returns {String} The entity type name for the specified property, null if not found.
- */
-function lookupNavigationPropertyType(navigationProperty, metadata) {
-
-    var result = null;
-    if (navigationProperty) {
-        var rel = navigationProperty.relationship;
-        var association = forEachSchema(metadata, function (schema) {
-            // The name should be the namespace qualified name in 'ns'.'type' format.
-            var nameOnly = removeNamespace(schema.namespace, rel);
-            var associations = schema.association;
-            if (nameOnly && associations) {
-                var i, len;
-                for (i = 0, len = associations.length; i < len; i++) {
-                    if (associations[i].name === nameOnly) {
-                        return associations[i];
-                    }
-                }
-            }
-            return null;
-        });
-
-        if (association) {
-            var end = association.end[0];
-            if (end.role !== navigationProperty.toRole) {
-                end = association.end[1];
-                // For metadata to be valid, end.role === navigationProperty.toRole now.
-            }
-            result = end.type;
-        }
-    }
-    return result;
-}
-
-/** Looks up the target entityset name for a navigation property.
- * @param {Object} navigationProperty - 
- * @param {Object} metadata - 
- * @returns {String} The entityset name for the specified property, null if not found.
- */
-function lookupNavigationPropertyEntitySet(navigationProperty, sourceEntitySetName, metadata) {
-
-    if (navigationProperty) {
-        var rel = navigationProperty.relationship;
-        var associationSet = forEachSchema(metadata, function (schema) {
-            var containers = schema.entityContainer;
-            for (var i = 0; i < containers.length; i++) {
-                var associationSets = containers[i].associationSet;
-                if (associationSets) {
-                    for (var j = 0; j < associationSets.length; j++) {
-                        if (associationSets[j].association == rel) {
-                            return associationSets[j];
-                        }
-                    }
-                }
-            }
-            return null;
-        });
-        if (associationSet && associationSet.end[0] && associationSet.end[1]) {
-            return (associationSet.end[0].entitySet == sourceEntitySetName) ? associationSet.end[1].entitySet : associationSet.end[0].entitySet;
-        }
-    }
-    return null;
-}
-
-/** Gets the entitySet info, container name and functionImports for an entitySet
- * @param {Object} navigationProperty - 
- * @param {Object} metadata - 
- * @returns {Object} The info about the entitySet.
- */
-function getEntitySetInfo(entitySetName, metadata) {
-
-    var info = forEachSchema(metadata, function (schema) {
-        var container = schema.entityContainer;
-        var entitySets = container.entitySet;
-        if (entitySets) {
-            for (var j = 0; j < entitySets.length; j++) {
-                if (entitySets[j].name == entitySetName) {
-                    return { entitySet: entitySets[j], containerName: container.name, functionImport: container.functionImport };
-                }
-            }
-        }
-        return null;
-    });
-
-    return info;
-}
-
-/** Given an expected namespace prefix, removes it from a full name.
- * @param {String} ns - Expected namespace.
- * @param {String} fullName - Full name in 'ns'.'name' form.
- * @returns {String} The local name, null if it isn't found in the expected namespace.
- */
-function removeNamespace(ns, fullName) {
-
-    if (fullName.indexOf(ns) === 0 && fullName.charAt(ns.length) === ".") {
-        return fullName.substr(ns.length + 1);
-    }
-
-    return null;
-}
-
-/** Looks up a schema object by name.
- * @param {String} name - Name (assigned).
- * @param schema - Schema object as per EDM metadata.
- * @param {String} kind - Kind of object to look for as per EDM metadata.
- * @returns An entity type description if the name is found; null otherwise.</returns>
- */
-function lookupInSchema(name, schema, kind) {
-
-    if (name && schema) {
-        // The name should be the namespace qualified name in 'ns'.'type' format.
-        var nameOnly = removeNamespace(schema.namespace, name);
-        if (nameOnly) {
-            return find(schema[kind], function (item) {
-                return item.name === nameOnly;
-            });
-        }
-    }
-    return null;
-}
-
-/** Compares to version strings and returns the higher one.
- * @param {String} left - Version string in the form "major.minor.rev"
- * @param {String} right - Version string in the form "major.minor.rev"
- * @returns {String} The higher version string.
- */
-function maxVersion(left, right) {
-
-    if (left === right) {
-        return left;
-    }
-
-    var leftParts = left.split(".");
-    var rightParts = right.split(".");
-
-    var len = (leftParts.length >= rightParts.length) ?
-        leftParts.length :
-        rightParts.length;
-
-    for (var i = 0; i < len; i++) {
-        var leftVersion = leftParts[i] && parseInt10(leftParts[i]);
-        var rightVersion = rightParts[i] && parseInt10(rightParts[i]);
-        if (leftVersion > rightVersion) {
-            return left;
-        }
-        if (leftVersion < rightVersion) {
-            return right;
-        }
-    }
-}
-
-var normalHeaders = {
-    // Headers shared by request and response
-    "content-type": "Content-Type",
-    "content-encoding": "Content-Encoding",
-    "content-length": "Content-Length",
-    "odata-version": "OData-Version",
-    
-    // Headers used by request
-    "accept": "Accept",
-    "accept-charset": "Accept-Charset",
-    "if-match": "If-Match",
-    "if-none-match": "If-None-Match",
-    "odata-isolation": "OData-Isolation",
-    "odata-maxversion": "OData-MaxVersion",
-    "prefer": "Prefer",
-    "content-id": "Content-ID",
-    "content-transfer-encoding": "Content-Transfer-Encoding",
-    
-    // Headers used by response
-    "etag": "ETag",
-    "location": "Location",
-    "odata-entityid": "OData-EntityId",
-    "preference-applied": "Preference-Applied",
-    "retry-after": "Retry-After"
-};
-
-/** Normalizes headers so they can be found with consistent casing.
- * @param {Object} headers - Dictionary of name/value pairs.
- */
-function normalizeHeaders(headers) {
-
-    for (var name in headers) {
-        var lowerName = name.toLowerCase();
-        var normalName = normalHeaders[lowerName];
-        if (normalName && name !== normalName) {
-            var val = headers[name];
-            delete headers[name];
-            headers[normalName] = val;
-        }
-    }
-}
-
-/** Parses a string into a boolean value.
- * @param propertyValue - Value to parse.
- * @returns {Boolean} true if the property value is 'true'; false otherwise.
- */
-function parseBool(propertyValue) {
-
-    if (typeof propertyValue === "boolean") {
-        return propertyValue;
-    }
-
-    return typeof propertyValue === "string" && propertyValue.toLowerCase() === "true";
-}
-
-
-// The captured indices for this expression are:
-// 0     - complete input
-// 1,2,3 - year with optional minus sign, month, day
-// 4,5,6 - hours, minutes, seconds
-// 7     - optional milliseconds
-// 8     - everything else (presumably offset information)
-var parseDateTimeRE = /^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/;
-
-/** Parses a string into a DateTime value.
- * @param {String} value - Value to parse.
- * @param {Boolean} withOffset - Whether offset is expected.
- * @returns {Date} The parsed value.
- */
-function parseDateTimeMaybeOffset(value, withOffset, nullOnError) {
-
-    // We cannot parse this in cases of failure to match or if offset information is specified.
-    var parts = parseDateTimeRE.exec(value);
-    var offset = (parts) ? getCanonicalTimezone(parts[8]) : null;
-
-    if (!parts || (!withOffset && offset !== "Z")) {
-        if (nullOnError) {
-            return null;
-        }
-        throw { message: "Invalid date/time value" };
-    }
-
-    // Pre-parse years, account for year '0' being invalid in dateTime.
-    var year = parseInt10(parts[1]);
-    if (year <= 0) {
-        year++;
-    }
-
-    // Pre-parse optional milliseconds, fill in default. Fail if value is too precise.
-    var ms = parts[7];
-    var ns = 0;
-    if (!ms) {
-        ms = 0;
-    } else {
-        if (ms.length > 7) {
-            if (nullOnError) {
-                return null;
-            }
-            throw { message: "Cannot parse date/time value to given precision." };
-        }
-
-        ns = formatNumberWidth(ms.substring(3), 4, true);
-        ms = formatNumberWidth(ms.substring(0, 3), 3, true);
-
-        ms = parseInt10(ms);
-        ns = parseInt10(ns);
-    }
-
-    // Pre-parse other time components and offset them if necessary.
-    var hours = parseInt10(parts[4]);
-    var minutes = parseInt10(parts[5]);
-    var seconds = parseInt10(parts[6]) || 0;
-    if (offset !== "Z") {
-        // The offset is reversed to get back the UTC date, which is
-        // what the API will eventually have.
-        var timezone = parseTimezone(offset);
-        var direction = -(timezone.d);
-        hours += timezone.h * direction;
-        minutes += timezone.m * direction;
-    }
-
-    // Set the date and time separately with setFullYear, so years 0-99 aren't biased like in Date.UTC.
-    var result = new Date();
-    result.setUTCFullYear(
-        year,                       // Year.
-        parseInt10(parts[2]) - 1,   // Month (zero-based for Date.UTC and setFullYear).
-        parseInt10(parts[3])        // Date.
-        );
-    result.setUTCHours(hours, minutes, seconds, ms);
-
-    if (isNaN(result.valueOf())) {
-        if (nullOnError) {
-            return null;
-        }
-        throw { message: "Invalid date/time value" };
-    }
-
-    if (withOffset) {
-        result.__edmType = "Edm.DateTimeOffset";
-        result.__offset = offset;
-    }
-
-    if (ns) {
-        result.__ns = ns;
-    }
-
-    return result;
-}
-
-/** Parses a string into a Date object.
- * @param {String} propertyValue - Value to parse.
- * @returns {Date} The parsed with year, month, day set, time values are set to 0
- */
-function parseDate(propertyValue, nullOnError) {
-    var parts = propertyValue.split('-');
-
-    if (parts.length != 3 && nullOnError) {
-        return null;
-    }
-    return new Date(
-        parseInt10(parts[0]),       // Year.
-        parseInt10(parts[1]) - 1,   // Month (zero-based for Date.UTC and setFullYear).
-        parseInt10(parts[2],
-        0,0,0,0)        // Date.
-        );
-
-}
-
-var parseTimeOfDayRE = /^(\d+):(\d+)(:(\d+)(.(\d+))?)?$/;
-
-function parseTimeOfDay(propertyValue, nullOnError) {
-    var parts = parseTimeOfDayRE.exec(propertyValue);
-
-
-    return {
-        'h' :parseInt10(parts[1]),
-        'm' :parseInt10(parts[2]),
-        's' :parseInt10(parts[4]),
-        'ms' :parseInt10(parts[6]),
-     };
-}
-
-/** Parses a string into a DateTimeOffset value.
- * @param {String} propertyValue - Value to parse.
- * @returns {Date} The parsed value.
-
-
- * The resulting object is annotated with an __edmType property and
- * an __offset property reflecting the original intended offset of
- * the value. The time is adjusted for UTC time, as the current
- * timezone-aware Date APIs will only work with the local timezone.
- */
-function parseDateTimeOffset(propertyValue, nullOnError) {
-    
-
-    return parseDateTimeMaybeOffset(propertyValue, true, nullOnError);
-}
-
-// The captured indices for this expression are:
-// 0       - complete input
-// 1       - direction
-// 2,3,4   - years, months, days
-// 5,6,7,8 - hours, minutes, seconds, miliseconds
-
-var parseTimeRE = /^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/;
-
-function isEdmDurationValue(value) {
-    parseTimeRE.test(value);
-}
-
-/** Parses a string in xsd:duration format.
- * @param {String} duration - Duration value.
-
- * This method will throw an exception if the input string has a year or a month component.
-
- * @returns {Object} Object representing the time
- */
-function parseDuration(duration) {
-
-    var parts = parseTimeRE.exec(duration);
-
-    if (parts === null) {
-        throw { message: "Invalid duration value." };
-    }
-
-    var years = parts[2] || "0";
-    var months = parts[3] || "0";
-    var days = parseInt10(parts[4] || 0);
-    var hours = parseInt10(parts[5] || 0);
-    var minutes = parseInt10(parts[6] || 0);
-    var seconds = parseFloat(parts[7] || 0);
-
-    if (years !== "0" || months !== "0") {
-        throw { message: "Unsupported duration value." };
-    }
-
-    var ms = parts[8];
-    var ns = 0;
-    if (!ms) {
-        ms = 0;
-    } else {
-        if (ms.length > 7) {
-            throw { message: "Cannot parse duration value to given precision." };
-        }
-
-        ns = formatNumberWidth(ms.substring(3), 4, true);
-        ms = formatNumberWidth(ms.substring(0, 3), 3, true);
-
-        ms = parseInt10(ms);
-        ns = parseInt10(ns);
-    }
-
-    ms += seconds * 1000 + minutes * 60000 + hours * 3600000 + days * 86400000;
-
-    if (parts[1] === "-") {
-        ms = -ms;
-    }
-
-    var result = { ms: ms, __edmType: "Edm.Time" };
-
-    if (ns) {
-        result.ns = ns;
-    }
-    return result;
-}
-
-/** Parses a timezone description in (+|-)nn:nn format.
- * @param {String} timezone - Timezone offset.
- * @returns {Object} An object with a (d)irection property of 1 for + and -1 for -, offset (h)ours and offset (m)inutes.
- */
-function parseTimezone(timezone) {
-
-    var direction = timezone.substring(0, 1);
-    direction = (direction === "+") ? 1 : -1;
-
-    var offsetHours = parseInt10(timezone.substring(1));
-    var offsetMinutes = parseInt10(timezone.substring(timezone.indexOf(":") + 1));
-    return { d: direction, h: offsetHours, m: offsetMinutes };
-}
-
-/** Prepares a request object so that it can be sent through the network.
-* @param request - Object that represents the request to be sent.
-* @param handler - Handler for data serialization
-* @param context - Context used for preparing the request
-*/
-function prepareRequest(request, handler, context) {
-
-    // Default to GET if no method has been specified.
-    if (!request.method) {
-        request.method = "GET";
-    }
-
-    if (!request.headers) {
-        request.headers = {};
-    } else {
-        normalizeHeaders(request.headers);
-    }
-
-    if (request.headers.Accept === undefined) {
-        request.headers.Accept = handler.accept;
-    }
-
-    if (assigned(request.data) && request.body === undefined) {
-        handler.write(request, context);
-    }
-
-    if (!assigned(request.headers["OData-MaxVersion"])) {
-        request.headers["OData-MaxVersion"] = handler.maxDataServiceVersion || "4.0";
-    }
-
-    if (request.async === undefined) {
-        request.async = true;
-    }
-
-}
-
-/** Traverses a tree of objects invoking callback for every value.
- * @param {Object} item - Object or array to traverse.
- * @param {Function} callback - Callback function with key and value, similar to JSON.parse reviver.
- * @returns {Object} The object with traversed properties.
- Unlike the JSON reviver, this won't delete null members.</remarks>
-*/
-function traverseInternal(item, owner, callback) {
-
-    if (item && typeof item === "object") {
-        for (var name in item) {
-            var value = item[name];
-            var result = traverseInternal(value, name, callback);
-            result = callback(name, result, owner);
-            if (result !== value) {
-                if (value === undefined) {
-                    delete item[name];
-                } else {
-                    item[name] = result;
-                }
-            }
-        }
-    }
-
-    return item;
-}
-
-/** Traverses a tree of objects invoking callback for every value.
- * @param {Object} item - Object or array to traverse.
- * @param {Function} callback - Callback function with key and value, similar to JSON.parse reviver.
- * @returns {Object} The traversed object.
- * Unlike the JSON reviver, this won't delete null members.</remarks>
-*/
-function traverse(item, callback) {
-
-    return callback("", traverseInternal(item, "", callback));
-}
-
-exports.dataItemTypeName = dataItemTypeName;
-exports.EDM_BINARY = EDM_BINARY;
-exports.EDM_BOOLEAN = EDM_BOOLEAN;
-exports.EDM_BYTE = EDM_BYTE;
-exports.EDM_DATETIME = EDM_DATETIME;
-exports.EDM_DATETIMEOFFSET = EDM_DATETIMEOFFSET;
-exports.EDM_DECIMAL = EDM_DECIMAL;
-exports.EDM_DOUBLE = EDM_DOUBLE;
-exports.EDM_GEOGRAPHY = EDM_GEOGRAPHY;
-exports.EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY_POINT;
-exports.EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY_LINESTRING;
-exports.EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY_POLYGON;
-exports.EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY_COLLECTION;
-exports.EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY_MULTIPOLYGON;
-exports.EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY_MULTILINESTRING;
-exports.EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY_MULTIPOINT;
-exports.EDM_GEOMETRY = EDM_GEOMETRY;
-exports.EDM_GEOMETRY_POINT = EDM_GEOMETRY_POINT;
-exports.EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY_LINESTRING;
-exports.EDM_GEOMETRY_POLYGON = EDM_GEOMETRY_POLYGON;
-exports.EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY_COLLECTION;
-exports.EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY_MULTIPOLYGON;
-exports.EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY_MULTILINESTRING;
-exports.EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY_MULTIPOINT;
-exports.EDM_GUID = EDM_GUID;
-exports.EDM_INT16 = EDM_INT16;
-exports.EDM_INT32 = EDM_INT32;
-exports.EDM_INT64 = EDM_INT64;
-exports.EDM_SBYTE = EDM_SBYTE;
-exports.EDM_SINGLE = EDM_SINGLE;
-exports.EDM_STRING = EDM_STRING;
-exports.EDM_TIME = EDM_TIME;
-exports.GEOJSON_POINT = GEOJSON_POINT;
-exports.GEOJSON_LINESTRING = GEOJSON_LINESTRING;
-exports.GEOJSON_POLYGON = GEOJSON_POLYGON;
-exports.GEOJSON_MULTIPOINT = GEOJSON_MULTIPOINT;
-exports.GEOJSON_MULTILINESTRING = GEOJSON_MULTILINESTRING;
-exports.GEOJSON_MULTIPOLYGON = GEOJSON_MULTIPOLYGON;
-exports.GEOJSON_GEOMETRYCOLLECTION = GEOJSON_GEOMETRYCOLLECTION;
-exports.forEachSchema = forEachSchema;
-exports.formatDateTimeOffset = formatDateTimeOffset;
-exports.formatDateTimeOffsetJSON = formatDateTimeOffsetJSON;
-exports.formatDuration = formatDuration;
-exports.formatNumberWidth = formatNumberWidth;
-exports.getCanonicalTimezone = getCanonicalTimezone;
-exports.getCollectionType = getCollectionType;
-exports.invokeRequest = invokeRequest;
-exports.isBatch = isBatch;
-exports.isCollection = isCollection;
-exports.isCollectionType = isCollectionType;
-exports.isComplex = isComplex;
-exports.isDateTimeOffset = isDateTimeOffset;
-exports.isDeferred = isDeferred;
-exports.isEntry = isEntry;
-exports.isFeed = isFeed;
-exports.isGeographyEdmType = isGeographyEdmType;
-exports.isGeometryEdmType = isGeometryEdmType;
-exports.isNamedStream = isNamedStream;
-exports.isPrimitive = isPrimitive;
-exports.isPrimitiveEdmType = isPrimitiveEdmType;
-exports.lookupComplexType = lookupComplexType;
-exports.lookupDefaultEntityContainer = lookupDefaultEntityContainer;
-exports.lookupEntityContainer = lookupEntityContainer;
-exports.lookupEntitySet = lookupEntitySet;
-exports.lookupSingleton = lookupSingleton;
-exports.lookupEntityType = lookupEntityType;
-exports.lookupFunctionImport = lookupFunctionImport;
-exports.lookupNavigationPropertyType = lookupNavigationPropertyType;
-exports.lookupNavigationPropertyEntitySet = lookupNavigationPropertyEntitySet;
-exports.lookupInSchema = lookupInSchema;
-exports.lookupProperty = lookupProperty;
-exports.lookupInMetadata = lookupInMetadata;
-exports.getEntitySetInfo = getEntitySetInfo;
-exports.maxVersion = maxVersion;
-exports.navigationPropertyKind = navigationPropertyKind;
-exports.normalizeHeaders = normalizeHeaders;
-exports.parseBool = parseBool;
-
-
-exports.parseDate = parseDate;
-exports.parseDateTimeOffset = parseDateTimeOffset;
-exports.parseDuration = parseDuration;
-exports.parseTimeOfDay = parseTimeOfDay;
-
-exports.parseInt10 = parseInt10;
-exports.prepareRequest = prepareRequest;
-exports.removeNamespace = removeNamespace;
-exports.traverse = traverse;
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/store.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/store.js b/datajs/src/lib/store.js
deleted file mode 100644
index 5989253..0000000
--- a/datajs/src/lib/store.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- /** @module store */
-
-
-
-
-
-exports.defaultStoreMechanism = "best";
-
-/** Creates a new store object.
- * @param {String} name - Store name.
- * @param {String} [mechanism] - 
- * @returns {Object} Store object.
-*/
-exports.createStore = function (name, mechanism) {
-
-
-    if (!mechanism) {
-        mechanism = exports.defaultStoreMechanism;
-    }
-
-    if (mechanism === "best") {
-        mechanism = (DomStore.isSupported()) ? "dom" : "memory";
-    }
-
-    var factory = mechanisms[mechanism];
-    if (factory) {
-        return factory.create(name);
-    }
-
-    throw { message: "Failed to create store", name: name, mechanism: mechanism };
-};
-
-exports.mechanisms = mechanisms;
-
-
-exports.DomStore       = DomStore       = require('./store/dom.js');
-exports.IndexedDBStore = IndexedDBStore = require('./store/indexeddb.js');
-exports.MemoryStore    = MemoryStore    = require('./store/memory.js');
-
-var mechanisms = {
-    indexeddb: IndexedDBStore,
-    dom: DomStore,
-    memory: MemoryStore
-};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/store/dom.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/store/dom.js b/datajs/src/lib/store/dom.js
deleted file mode 100644
index 740b1ba..0000000
--- a/datajs/src/lib/store/dom.js
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module store/dom */
-
-
-
-var utils = require('./../datajs.js').utils;
-
-// Imports.
-var throwErrorCallback = utils.throwErrorCallback;
-var delay = utils.delay;
-
-var localStorage = null;
-
-/** This method is used to override the Date.toJSON method and is called only by
- * JSON.stringify.  It should never be called directly.
- * @summary Converts a Date object into an object representation friendly to JSON serialization.
- * @returns {Object} Object that represents the Date.
- */
-function domStoreDateToJSON() {
-    var newValue = { v: this.valueOf(), t: "[object Date]" };
-    // Date objects might have extra properties on them so we save them.
-    for (var name in this) {
-        newValue[name] = this[name];
-    }
-    return newValue;
-}
-
-/** This method is used during JSON parsing and invoked only by the reviver function.
- * It should never be called directly.
- * @summary JSON reviver function for converting an object representing a Date in a JSON stream to a Date object
- * @param Object - Object to convert.
- * @returns {Date} Date object.
- */
-function domStoreJSONToDate(_, value) {
-    if (value && value.t === "[object Date]") {
-        var newValue = new Date(value.v);
-        for (var name in value) {
-            if (name !== "t" && name !== "v") {
-                newValue[name] = value[name];
-            }
-        }
-        value = newValue;
-    }
-    return value;
-}
-
-/** Qualifies the key with the name of the store.
- * @param {Object} store - Store object whose name will be used for qualifying the key.
- * @param {String} key - Key string.
- * @returns {String} Fully qualified key string.
- */
-function qualifyDomStoreKey(store, key) {
-    return store.name + "#!#" + key;
-}
-
-/** Gets the key part of a fully qualified key string.
- * @param {Object} store - Store object whose name will be used for qualifying the key.
- * @param {String} key - Fully qualified key string.
- * @returns {String} Key part string
- */
-function unqualifyDomStoreKey(store, key) {
-    return key.replace(store.name + "#!#", "");
-}
-
-/** Constructor for store objects that use DOM storage as the underlying mechanism.
- * @class DomStore
- * @constructor
- * @param {String} name - Store name.
- */
-function DomStore(name) {
-    this.name = name;
-}
-
-/** Creates a store object that uses DOM Storage as its underlying mechanism.
- * @method module:store/dom~DomStore.create
- * @param {String} name - Store name.
- * @returns {Object} Store object.
- */
-DomStore.create = function (name) {
-
-    if (DomStore.isSupported()) {
-        localStorage = localStorage || window.localStorage;
-        return new DomStore(name);
-    }
-
-    throw { message: "Web Storage not supported by the browser" };
-};
-
-/** Checks whether the underlying mechanism for this kind of store objects is supported by the browser.
- * @method DomStore.isSupported
- * @returns {Boolean} - True if the mechanism is supported by the browser; otherwise false.
-*/
-DomStore.isSupported = function () {
-    return !!window.localStorage;
-};
-
-/** Adds a new value identified by a key to the store.
- * @method module:store/dom~DomStore#add
- * @param {String} key - Key string.
- * @param value - Value that is going to be added to the store.
- * @param {Funcktion} success - Callback for a successful add operation.</param>
- * @param {Funcktion} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
- * This method errors out if the store already contains the specified key.
- */
-DomStore.prototype.add = function (key, value, success, error) {
-    error = error || this.defaultError;
-    var store = this;
-    this.contains(key, function (contained) {
-        if (!contained) {
-            store.addOrUpdate(key, value, success, error);
-        } else {
-            delay(error, { message: "key already exists", key: key });
-        }
-    }, error);
-};
-
-/** This method will overwrite the key's current value if it already exists in the store; otherwise it simply adds the new key and value.
- * @summary Adds or updates a value identified by a key to the store.
- * @method module:store/dom~DomStore#addOrUpdate
- * @param {String} key - Key string.
- * @param value - Value that is going to be added or updated to the store.
- * @param {Function} success - Callback for a successful add or update operation.</param>
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
- */
-DomStore.prototype.addOrUpdate = function (key, value, success, error) {
-    error = error || this.defaultError;
-
-    if (key instanceof Array) {
-        error({ message: "Array of keys not supported" });
-    } else {
-        var fullKey = qualifyDomStoreKey(this, key);
-        var oldDateToJSON = Date.prototype.toJSON;
-        try {
-            var storedValue = value;
-            if (storedValue !== undefined) {
-                // Dehydrate using json
-                Date.prototype.toJSON = domStoreDateToJSON;
-                storedValue = window.JSON.stringify(value);
-            }
-            // Save the json string.
-            localStorage.setItem(fullKey, storedValue);
-            delay(success, key, value);
-        }
-        catch (e) {
-            if (e.code === 22 || e.number === 0x8007000E) {
-                delay(error, { name: "QUOTA_EXCEEDED_ERR", error: e });
-            } else {
-                delay(error, e);
-            }
-        }
-        finally {
-            Date.prototype.toJSON = oldDateToJSON;
-        }
-    }
-};
-
-/** In case of an error, this method will not restore any keys that might have been deleted at that point.
- * @summary Removes all the data associated with this store object.
- * @method module:store/dom~DomStore#clear
- * @param {Function} success - Callback for a successful clear operation.</param>
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
- */
-DomStore.prototype.clear = function (success, error) {
-
-    error = error || this.defaultError;
-    try {
-        var i = 0, len = localStorage.length;
-        while (len > 0 && i < len) {
-            var fullKey = localStorage.key(i);
-            var key = unqualifyDomStoreKey(this, fullKey);
-            if (fullKey !== key) {
-                localStorage.removeItem(fullKey);
-                len = localStorage.length;
-            } else {
-                i++;
-            }
-        }
-        delay(success);
-    }
-    catch (e) {
-        delay(error, e);
-    }
-};
-
-/** This function does nothing in DomStore as it does not have a connection model
- * @method module:store/dom~DomStore#close
- */
-DomStore.prototype.close = function () {
-};
-
-/** Checks whether a key exists in the store.
- * @method module:store/dom~DomStore#contains
- * @param {String} key - Key string.
- * @param {Function} success - Callback indicating whether the store contains the key or not.</param>
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-*/
-DomStore.prototype.contains = function (key, success, error) {
-    error = error || this.defaultError;
-    try {
-        var fullKey = qualifyDomStoreKey(this, key);
-        var value = localStorage.getItem(fullKey);
-        delay(success, value !== null);
-    } catch (e) {
-        delay(error, e);
-    }
-};
-
-DomStore.prototype.defaultError = throwErrorCallback;
-
-/** Gets all the keys that exist in the store.
- * @method module:store/dom~DomStore#getAllKeys
- * @param {Function} success - Callback for a successful get operation.</param>
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
- */
-DomStore.prototype.getAllKeys = function (success, error) {
-
-    error = error || this.defaultError;
-
-    var results = [];
-    var i, len;
-
-    try {
-        for (i = 0, len = localStorage.length; i < len; i++) {
-            var fullKey = localStorage.key(i);
-            var key = unqualifyDomStoreKey(this, fullKey);
-            if (fullKey !== key) {
-                results.push(key);
-            }
-        }
-        delay(success, results);
-    }
-    catch (e) {
-        delay(error, e);
-    }
-};
-
-/** Identifies the underlying mechanism used by the store.*/
-DomStore.prototype.mechanism = "dom";
-
-/** Reads the value associated to a key in the store.
- * @method module:store/dom~DomStore#read
- * @param {String} key - Key string.
- * @param {Function} success - Callback for a successful reads operation.
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.
- */
-DomStore.prototype.read = function (key, success, error) {
-
-    error = error || this.defaultError;
-
-    if (key instanceof Array) {
-        error({ message: "Array of keys not supported" });
-    } else {
-        try {
-            var fullKey = qualifyDomStoreKey(this, key);
-            var value = localStorage.getItem(fullKey);
-            if (value !== null && value !== "undefined") {
-                // Hydrate using json
-                value = window.JSON.parse(value, domStoreJSONToDate);
-            }
-            else {
-                value = undefined;
-            }
-            delay(success, key, value);
-        } catch (e) {
-            delay(error, e);
-        }
-    }
-};
-
-/** Removes a key and its value from the store.
- * @method module:store/dom~DomStore#remove
- * @param {String} key - Key string.
- * @param {Funtion} success - Callback for a successful remove operation.</param>
- * @param {Funtion} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
- */
-DomStore.prototype.remove = function (key, success, error) {
-    error = error || this.defaultError;
-
-    if (key instanceof Array) {
-        error({ message: "Batches not supported" });
-    } else {
-        try {
-            var fullKey = qualifyDomStoreKey(this, key);
-            localStorage.removeItem(fullKey);
-            delay(success);
-        } catch (e) {
-            delay(error, e);
-        }
-    }
-};
-
-/** Updates the value associated to a key in the store.
- * @method module:store/dom~DomStore#update
- * @param {String} key - Key string.
- * @param value - New value.
- * @param {Function} success - Callback for a successful update operation.
- * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked
- * This method errors out if the specified key is not found in the store.
- */
-DomStore.prototype.update = function (key, value, success, error) {
-    error = error || this.defaultError;
-    var store = this;
-    this.contains(key, function (contained) {
-        if (contained) {
-            store.addOrUpdate(key, value, success, error);
-        } else {
-            delay(error, { message: "key not found", key: key });
-        }
-    }, error);
-};
-
-module.exports = DomStore;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/store/indexeddb.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/store/indexeddb.js b/datajs/src/lib/store/indexeddb.js
deleted file mode 100644
index 397354a..0000000
--- a/datajs/src/lib/store/indexeddb.js
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module store/indexeddb */
-var utils = require('./../datajs.js').utils;
-
-// Imports.
-var throwErrorCallback = utils.throwErrorCallback;
-var delay = utils.delay;
-
-
-var indexedDB = utils.inBrowser() ? window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB : undefined;
-var IDBKeyRange = utils.inBrowser() ? window.IDBKeyRange || window.webkitIDBKeyRange : undefined;
-var IDBTransaction = utils.inBrowser() ? window.IDBTransaction || window.webkitIDBTransaction || {} : {} ;
-
-var IDBT_READ_ONLY = IDBTransaction.READ_ONLY || "readonly";
-var IDBT_READ_WRITE = IDBTransaction.READ_WRITE || "readwrite";
-
-/** Returns either a specific error handler or the default error handler
- * @param {Function} error - The specific error handler
- * @param {Function} defaultError - The default error handler
- * @returns {Function} The error callback
- */
-function getError(error, defaultError) {
-
-    return function (e) {
-        var errorFunc = error || defaultError;
-        if (!errorFunc) {
-            return;
-        }
-
-        // Old api quota exceeded error support.
-        if (Object.prototype.toString.call(e) === "[object IDBDatabaseException]") {
-            if (e.code === 11 /* IndexedDb disk quota exceeded */) {
-                errorFunc({ name: "QuotaExceededError", error: e });
-                return;
-            }
-            errorFunc(e);
-            return;
-        }
-
-        var errName;
-        try {
-            var errObj = e.target.error || e;
-            errName = errObj.name;
-        } catch (ex) {
-            errName = (e.type === "blocked") ? "IndexedDBBlocked" : "UnknownError";
-        }
-        errorFunc({ name: errName, error: e });
-    };
-}
-
-/** Opens the store object's indexed db database.
- * @param {IndexedDBStore} store - The store object
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-function openStoreDb(store, success, error) {
-
-    var storeName = store.name;
-    var dbName = "_datajs_" + storeName;
-
-    var request = indexedDB.open(dbName);
-    request.onblocked = error;
-    request.onerror = error;
-
-    request.onupgradeneeded = function () {
-        var db = request.result;
-        if (!db.objectStoreNames.contains(storeName)) {
-            db.createObjectStore(storeName);
-        }
-    };
-
-    request.onsuccess = function (event) {
-        var db = request.result;
-        if (!db.objectStoreNames.contains(storeName)) {
-            // Should we use the old style api to define the database schema?
-            if ("setVersion" in db) {
-                var versionRequest = db.setVersion("1.0");
-                versionRequest.onsuccess = function () {
-                    var transaction = versionRequest.transaction;
-                    transaction.oncomplete = function () {
-                        success(db);
-                    };
-                    db.createObjectStore(storeName, null, false);
-                };
-                versionRequest.onerror = error;
-                versionRequest.onblocked = error;
-                return;
-            }
-
-            // The database doesn't have the expected store.
-            // Fabricate an error object for the event for the schema mismatch
-            // and error out.
-            event.target.error = { name: "DBSchemaMismatch" };
-            error(event);
-            return;
-        }
-
-        db.onversionchange = function(event) {
-            event.target.close();
-        };
-        success(db);
-    };
-}
-
-/** Opens a new transaction to the store
- * @param {IndexedDBStore} store - The store object
- * @param {Short} mode - The read/write mode of the transaction (constants from IDBTransaction)
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-function openTransaction(store, mode, success, error) {
-
-    var storeName = store.name;
-    var storeDb = store.db;
-    var errorCallback = getError(error, store.defaultError);
-
-    if (storeDb) {
-        success(storeDb.transaction(storeName, mode));
-        return;
-    }
-
-    openStoreDb(store, function (db) {
-        store.db = db;
-        success(db.transaction(storeName, mode));
-    }, errorCallback);
-}
-
-/** Creates a new IndexedDBStore.
- * @class IndexedDBStore
- * @constructor
- * @param {String} name - The name of the store.
- * @returns {Object} The new IndexedDBStore.
- */
-function IndexedDBStore(name) {
-    this.name = name;
-}
-
-/** Creates a new IndexedDBStore.
- * @method module:store/indexeddb~IndexedDBStore.create
- * @param {String} name - The name of the store.
- * @returns {Object} The new IndexedDBStore.
- */
-IndexedDBStore.create = function (name) {
-    if (IndexedDBStore.isSupported()) {
-        return new IndexedDBStore(name);
-    }
-
-    throw { message: "IndexedDB is not supported on this browser" };
-};
-
-/** Returns whether IndexedDB is supported.
- * @method module:store/indexeddb~IndexedDBStore.isSupported
- * @returns {Boolean} True if IndexedDB is supported, false otherwise.
- */
-IndexedDBStore.isSupported = function () {
-    return !!indexedDB;
-};
-
-/** Adds a key/value pair to the store
- * @method module:store/indexeddb~IndexedDBStore#add
- * @param {String} key - The key
- * @param {Object} value - The value
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
-*/
-IndexedDBStore.prototype.add = function (key, value, success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    var keys = [];
-    var values = [];
-
-    if (key instanceof Array) {
-        keys = key;
-        values = value;
-    } else {
-        keys = [key];
-        values = [value];
-    }
-
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        transaction.onabort = getError(error, defaultError, key, "add");
-        transaction.oncomplete = function () {
-            if (key instanceof Array) {
-                success(keys, values);
-            } else {
-                success(key, value);
-            }
-        };
-
-        for (var i = 0; i < keys.length && i < values.length; i++) {
-            transaction.objectStore(name).add({ v: values[i] }, keys[i]);
-        }
-    }, error);
-};
-
-/** Adds or updates a key/value pair in the store
- * @method module:store/indexeddb~IndexedDBStore#addOrUpdate
- * @param {String} key - The key
- * @param {Object} value - The value
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.addOrUpdate = function (key, value, success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    var keys = [];
-    var values = [];
-
-    if (key instanceof Array) {
-        keys = key;
-        values = value;
-    } else {
-        keys = [key];
-        values = [value];
-    }
-
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        transaction.onabort = getError(error, defaultError);
-        transaction.oncomplete = function () {
-            if (key instanceof Array) {
-                success(keys, values);
-            } else {
-                success(key, value);
-            }
-        };
-
-        for (var i = 0; i < keys.length && i < values.length; i++) {
-            var record = { v: values[i] };
-            transaction.objectStore(name).put(record, keys[i]);
-        }
-    }, error);
-};
-
-/** Clears the store
- * @method module:store/indexeddb~IndexedDBStore#clear
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.clear = function (success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        transaction.onerror = getError(error, defaultError);
-        transaction.oncomplete = function () {
-            success();
-        };
-
-        transaction.objectStore(name).clear();
-    }, error);
-};
-/** Closes the connection to the database
- * @method module:store/indexeddb~IndexedDBStore#close
-*/
-IndexedDBStore.prototype.close = function () {
-    
-    if (this.db) {
-        this.db.close();
-        this.db = null;
-    }
-};
-
-/** Returns whether the store contains a key
- * @method module:store/indexeddb~IndexedDBStore#contains
- * @param {String} key - The key
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.contains = function (key, success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
-        var objectStore = transaction.objectStore(name);
-        var request = objectStore.get(key);
-
-        transaction.oncomplete = function () {
-            success(!!request.result);
-        };
-        transaction.onerror = getError(error, defaultError);
-    }, error);
-};
-
-IndexedDBStore.prototype.defaultError = throwErrorCallback;
-
-/** Gets all the keys from the store
- * @method module:store/indexeddb~IndexedDBStore#getAllKeys
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.getAllKeys = function (success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        var results = [];
-
-        transaction.oncomplete = function () {
-            success(results);
-        };
-
-        var request = transaction.objectStore(name).openCursor();
-
-        request.onerror = getError(error, defaultError);
-        request.onsuccess = function (event) {
-            var cursor = event.target.result;
-            if (cursor) {
-                results.push(cursor.key);
-                // Some tools have issues because continue is a javascript reserved word.
-                cursor["continue"].call(cursor);
-            }
-        };
-    }, error);
-};
-
-/** Identifies the underlying mechanism used by the store.
-*/
-IndexedDBStore.prototype.mechanism = "indexeddb";
-
-/** Reads the value for the specified key
- * @method module:store/indexeddb~IndexedDBStore#read
- * @param {String} key - The key
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- * If the key does not exist, the success handler will be called with value = undefined
- */
-IndexedDBStore.prototype.read = function (key, success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    var keys = (key instanceof Array) ? key : [key];
-
-    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
-        var values = [];
-
-        transaction.onerror = getError(error, defaultError, key, "read");
-        transaction.oncomplete = function () {
-            if (key instanceof Array) {
-                success(keys, values);
-            } else {
-                success(keys[0], values[0]);
-            }
-        };
-
-        for (var i = 0; i < keys.length; i++) {
-            // Some tools have issues because get is a javascript reserved word. 
-            var objectStore = transaction.objectStore(name);
-            var request = objectStore.get.call(objectStore, keys[i]);
-            request.onsuccess = function (event) {
-                var record = event.target.result;
-                values.push(record ? record.v : undefined);
-            };
-        }
-    }, error);
-};
-
-/** Removes the specified key from the store
- * @method module:store/indexeddb~IndexedDBStore#remove
- * @param {String} key - The key
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.remove = function (key, success, error) {
-
-    var name = this.name;
-    var defaultError = this.defaultError;
-    var keys = (key instanceof Array) ? key : [key];
-
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        transaction.onerror = getError(error, defaultError);
-        transaction.oncomplete = function () {
-            success();
-        };
-
-        for (var i = 0; i < keys.length; i++) {
-            // Some tools have issues because continue is a javascript reserved word.
-            var objectStore = transaction.objectStore(name);
-            objectStore["delete"].call(objectStore, keys[i]);
-        }
-    }, error);
-};
-
-/** Updates a key/value pair in the store
- * @method module:store/indexeddb~IndexedDBStore#update
- * @param {String} key - The key
- * @param {Object} value - The value
- * @param {Function} success - The success callback
- * @param {Function} error - The error callback
- */
-IndexedDBStore.prototype.update = function (key, value, success, error) {
-    var name = this.name;
-    var defaultError = this.defaultError;
-    var keys = [];
-    var values = [];
-
-    if (key instanceof Array) {
-        keys = key;
-        values = value;
-    } else {
-        keys = [key];
-        values = [value];
-    }
-
-    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
-        transaction.onabort = getError(error, defaultError);
-        transaction.oncomplete = function () {
-            if (key instanceof Array) {
-                success(keys, values);
-            } else {
-                success(key, value);
-            }
-        };
-
-        for (var i = 0; i < keys.length && i < values.length; i++) {
-            var request = transaction.objectStore(name).openCursor(IDBKeyRange.only(keys[i]));
-            var record = { v: values[i] };
-            request.pair = { key: keys[i], value: record };
-            request.onsuccess = function (event) {
-                var cursor = event.target.result;
-                if (cursor) {
-                    cursor.update(event.target.pair.value);
-                } else {
-                    transaction.abort();
-                }
-            }
-        }
-    }, error);
-};
-
-
-module.exports = IndexedDBStore;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/store/memory.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/store/memory.js b/datajs/src/lib/store/memory.js
deleted file mode 100644
index 7203c46..0000000
--- a/datajs/src/lib/store/memory.js
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module store/memory */
-
-
-var utils = require('./../datajs.js').utils;
-
-// Imports.
-var throwErrorCallback = utils.throwErrorCallback;
-var delay = utils.delay;
-
-/** Constructor for store objects that use a sorted array as the underlying mechanism.
- * @class MemoryStore
- * @constructor
- * @param {String} name - Store name.
- */
-function MemoryStore(name) {
-
-    var holes = [];
-    var items = [];
-    var keys = {};
-
-    this.name = name;
-
-    var getErrorCallback = function (error) {
-        return error || this.defaultError;
-    };
-
-    /** Validates that the specified key is not undefined, not null, and not an array
-     * @param key - Key value.
-     * @param {Function} error - Error callback.
-     * @returns {Boolean} True if the key is valid. False if the key is invalid and the error callback has been queued for execution.
-     */
-    function validateKeyInput(key, error) {
-
-        var messageString;
-
-        if (key instanceof Array) {
-            messageString = "Array of keys not supported";
-        }
-
-        if (key === undefined || key === null) {
-            messageString = "Invalid key";
-        }
-
-        if (messageString) {
-            delay(error, { message: messageString });
-            return false;
-        }
-        return true;
-    }
-
-    /** This method errors out if the store already contains the specified key.
-     * @summery Adds a new value identified by a key to the store.
-     * @method module:store/memory~MemoryStore#add
-     * @param {String} key - Key string.
-     * @param value - Value that is going to be added to the store.
-     * @param {Function} success - Callback for a successful add operation.</param>
-     * @param {Function} error - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-     */
-    this.add = function (key, value, success, error) {
-        error = getErrorCallback(error);
-
-        if (validateKeyInput(key, error)) {
-            if (!keys.hasOwnProperty(key)) {
-                this.addOrUpdate(key, value, success, error);
-            } else {
-                error({ message: "key already exists", key: key });
-            }
-        }
-    };
-
-    /** This method will overwrite the key's current value if it already exists in the store; otherwise it simply adds the new key and value.
-     * @summary Adds or updates a value identified by a key to the store.
-     * @method module:store/memory~MemoryStore#addOrUpdate
-     * @param {String} key - Key string.
-     * @param value - Value that is going to be added or updated to the store.
-     * @param {Function} success - Callback for a successful add or update operation.</param>
-     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-    */
-    this.addOrUpdate = function (key, value, success, error) {
-        
-        error = getErrorCallback(error);
-
-        if (validateKeyInput(key, error)) {
-            var index = keys[key];
-            if (index === undefined) {
-                if (holes.length > 0) {
-                    index = holes.splice(0, 1);
-                } else {
-                    index = items.length;
-                }
-            }
-            items[index] = value;
-            keys[key] = index;
-            delay(success, key, value);
-        }
-    };
-
-    /** Removes all the data associated with this store object.
-     * @method module:store/memory~MemoryStore#clear
-     * @param {Function} success>Callback for a successful clear operation.
-     */
-    this.clear = function (success) {
-        items = [];
-        keys = {};
-        holes = [];
-        delay(success);
-    };
-
-    /** Checks whether a key exists in the store.
-     * @method module:store/memory~MemoryStore#contains
-     * @param {String} key - Key string.
-     * @param {Funktion} success - Callback indicating whether the store contains the key or not.</param>
-     */
-    this.contains = function (key, success) {
-        var contained = keys.hasOwnProperty(key);
-        delay(success, contained);
-    };
-
-    /** Gets all the keys that exist in the store.
-     * @method module:store/memory~MemoryStore#getAllKeys
-     * @param {Function} success - Callback for a successful get operation.</param>
-     */
-    this.getAllKeys = function (success) {
-
-        var results = [];
-        for (var name in keys) {
-            results.push(name);
-        }
-        delay(success, results);
-    };
-
-    /** Reads the value associated to a key in the store.
-     * @method module:store/memory~MemoryStore#read
-     * @param {String} key - Key string.
-     * @param {Function} Function - Callback for a successful reads operation.</param>
-     * @param {Function{}Function - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-     */
-    this.read = function (key, success, error) {
-        error = getErrorCallback(error);
-
-        if (validateKeyInput(key, error)) {
-            var index = keys[key];
-            delay(success, key, items[index]);
-        }
-    };
-
-    /** Removes a key and its value from the store.
-     * @method module:store/memory~MemoryStore#remove
-     * @param {String} key - Key string.
-     * @param {Function} success - Callback for a successful remove operation.</param>
-     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-     */
-    this.remove = function (key, success, error) {
-        error = getErrorCallback(error);
-
-        if (validateKeyInput(key, error)) {
-            var index = keys[key];
-            if (index !== undefined) {
-                if (index === items.length - 1) {
-                    items.pop();
-                } else {
-                    items[index] = undefined;
-                    holes.push(index);
-                }
-                delete keys[key];
-
-                // The last item was removed, no need to keep track of any holes in the array.
-                if (items.length === 0) {
-                    holes = [];
-                }
-            }
-
-            delay(success);
-        }
-    };
-
-    /** Updates the value associated to a key in the store.
-     * @method module:store/memory~MemoryStore#update
-     * @param {String} key - Key string.
-     * @param value - New value.
-     * @param {Function} success - Callback for a successful update operation.</param>
-     * @param {Function} [error] - Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-     * This method errors out if the specified key is not found in the store.
-     */
-    this.update = function (key, value, success, error) {
-        error = getErrorCallback(error);
-        if (validateKeyInput(key, error)) {
-            if (keys.hasOwnProperty(key)) {
-                this.addOrUpdate(key, value, success, error);
-            } else {
-                error({ message: "key not found", key: key });
-            }
-        }
-    };
-}
-
-/** Creates a store object that uses memory storage as its underlying mechanism.
- * @method MemoryStore.create
- * @param {String} name - Store name.
- * @returns {Object} Store object.
- */
-MemoryStore.create = function (name) {
-    return new MemoryStore(name);
-};
-
-/** Checks whether the underlying mechanism for this kind of store objects is supported by the browser.
- * @method MemoryStore.isSupported
- * @returns {Boolean} True if the mechanism is supported by the browser; otherwise false.
- */
-MemoryStore.isSupported = function () {
-    return true;
-};
-
-/** This function does nothing in MemoryStore as it does not have a connection model.
-*/
-MemoryStore.prototype.close = function () {
-};
-
-MemoryStore.prototype.defaultError = throwErrorCallback;
-
-/** Identifies the underlying mechanism used by the store.
-*/
-MemoryStore.prototype.mechanism = "memory";
-
-
-/** MemoryStore (see {@link MemoryStore}) */
-module.exports = MemoryStore;
\ No newline at end of file


[31/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-json-light-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-json-light-tests.js b/datajs/tests/odata-json-light-tests.js
deleted file mode 100644
index fd2c8d4..0000000
--- a/datajs/tests/odata-json-light-tests.js
+++ /dev/null
@@ -1,2492 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-json-light-tests.js
-
-(function (window, undefined) {
-
-    // DATAJS INTERNAL START
-
-    var mockHttpClient;
-
-    module("Unit", {
-        setup: function () {
-            mockHttpClient = window.MockHttpClient.clear();
-        }
-    });
-
-    var getSampleModel = function () {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "NS",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "key": { "propertyRef": [{ "name": "Id"}] },
-                        "property": [
-                                { "name": "Id", "type": "Edm.String" },
-                                { "name": "P1", "type": "Edm.Int32" }
-                         ]
-                    }],
-                    entityContainer: [{
-                        name: "TestContainer",
-                        isDefaultEntityContainer: "true",
-                        entitySet: [{ "name": "EntityTypes", "entityType": "NS.EntityType"}]
-                    }]
-                }]
-            }
-        };
-        return testModel;
-    };
-
-    var getSampleModelWithTwoKeys = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].key = { "propertyRef": [{ "name": "Id" }, { "name": "P1"}] };
-        return testModel;
-    };
-
-    var getSampleModelWithOneConcurrencyProperty = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
-        return testModel;
-    };
-    
-    var getSampleModelWithOneBinaryConcurrencyProperty = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
-        testModel.dataServices.schema[0].entityType[0].property[1].type = "Edm.Binary";
-        return testModel;
-    };
-
-    var getSampleModelWithMultipleConcurrencyProperties = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
-        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
-        return testModel;
-    };
-
-    var getSampleModelWithDateTimeConcurrencyProperties = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.DateTime", concurrencyMode: "Fixed" };
-        return testModel;
-    };
-    
-    var getSampleModelWithDecimalProperty = function () {
-        var testModel = getSampleModel();
-        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.Decimal"};
-        return testModel;
-    };
-
-    var getSampleModelWithNavPropertiesAndInheritedTypes = function () {
-        return {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "maxDataServiceVersion": "4.0",
-                "schema": [
-                    {
-                        "namespace": "ODataDemo",
-                        "entityType": [
-                            {
-                                "name": "Product",
-                                "key": {
-                                    "propertyRef": [
-                                        {
-                                            "name": "ID"
-                                        }
-                                    ]
-                                },
-                                "property": [
-                                    {
-                                        "name": "ID",
-                                        "nullable": "false",
-                                        "type": "Edm.Int32"
-                                    }
-                                ],
-                                "navigationProperty": [
-                                    {
-                                        "name": "Category",
-                                        "toRole": "Category_Products",
-                                        "fromRole": "Product_Category",
-                                        "relationship": "ODataDemo.Product_Category_Category_Products"
-                                    }]
-                            },
-                            {
-                                "name": "FeaturedProduct",
-                                "baseType": "ODataDemo.Product",
-                                "navigationProperty": [
-                                    {
-                                        "name": "Advertisement",
-                                        "toRole": "Advertisement_FeaturedProduct",
-                                        "fromRole": "FeaturedProduct_Advertisement",
-                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
-                                    }
-                                ]
-                            },
-                            {
-                                "name": "Advertisement",
-                                "key": {
-                                    "propertyRef": [
-                                        {
-                                            "name": "ID"
-                                        }
-                                    ]
-                                },
-                                "property": [
-                                    {
-                                        "name": "ID",
-                                        "nullable": "false",
-                                        "type": "Edm.Guid"
-                                    }
-                                ],
-                                "navigationProperty": [
-                                    {
-                                        "name": "FeaturedProduct",
-                                        "toRole": "FeaturedProduct_Advertisement",
-                                        "fromRole": "Advertisement_FeaturedProduct",
-                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
-                                    }
-                                ]
-                            },
-                            {
-                                "name": "Category",
-                                "key": {
-                                    "propertyRef": [
-                                        {
-                                            "name": "ID"
-                                        }
-                                    ]
-                                },
-                                "property": [
-                                    {
-                                        "name": "ID",
-                                        "nullable": "false",
-                                        "type": "Edm.Int32"
-                                    }
-                                ],
-                                "navigationProperty": [
-                                    {
-                                        "name": "Products",
-                                        "toRole": "Product_Category",
-                                        "fromRole": "Category_Products",
-                                        "relationship": "ODataDemo.Product_Category_Category_Products"
-                                    }
-                                ]
-                            }
-                        ],
-                        "association": [
-                            {
-                                "name": "Product_Category_Category_Products",
-                                "end": [
-                                    {
-                                        "type": "ODataDemo.Category",
-                                        "multiplicity": "0..1",
-                                        "role": "Category_Products"
-                                    },
-                                    {
-                                        "type": "ODataDemo.Product",
-                                        "multiplicity": "*",
-                                        "role": "Product_Category"
-                                    }
-                                ]
-                            },
-                            {
-                                "name": "FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
-                                "end": [
-                                    {
-                                        "type": "ODataDemo.Advertisement",
-                                        "multiplicity": "0..1",
-                                        "role": "Advertisement_FeaturedProduct"
-                                    },
-                                    {
-                                        "type": "ODataDemo.FeaturedProduct",
-                                        "multiplicity": "0..1",
-                                        "role": "FeaturedProduct_Advertisement"
-                                    }
-                                ]
-                            }
-                        ],
-                        "entityContainer": [
-                            {
-                                "name": "DemoService",
-                                "isDefaultEntityContainer": "true",
-                                "entitySet": [
-                                    {
-                                        "name": "Products",
-                                        "entityType": "ODataDemo.Product"
-                                    },
-                                    {
-                                        "name": "Advertisements",
-                                        "entityType": "ODataDemo.Advertisement"
-                                    },
-                                    {
-                                        "name": "Categories",
-                                        "entityType": "ODataDemo.Category"
-                                    }
-                                ],
-                                "associationSet": [
-                                    {
-                                        "name": "Products_Advertisement_Advertisements",
-                                        "association": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
-                                        "end": [
-                                            {
-                                                "role": "FeaturedProduct_Advertisement",
-                                                "entitySet": "Products"
-                                            },
-                                            {
-                                                "role": "Advertisement_FeaturedProduct",
-                                                "entitySet": "Advertisements"
-                                            }
-                                        ]
-                                    },
-                                    {
-                                        "name": "Products_Category_Categories",
-                                        "association": "ODataDemo.Product_Category_Category_Products",
-                                        "end": [
-                                            {
-                                                "role": "Product_Category",
-                                                "entitySet": "Products"
-                                            },
-                                            {
-                                                "role": "Category_Products",
-                                                "entitySet": "Categories"
-                                            }
-                                        ]
-                                    }
-                                ]
-                            }
-                        ]
-                    }
-                ]
-            }
-        };
-    };
-
-    var failTest = function (err) {
-        if (err && err.message) {
-            djstest.fail(err.message);
-        } else {
-            djstest.fail("unexpected failure");
-        }
-        djstest.done();
-    };
-
-    var verifySerializedJsonLightData = function (actual, expected, message, requestUri) {
-        mockHttpClient.addRequestVerifier("*", function (request) {
-            djstest.assertAreEqualDeep(JSON.parse(request.body), expected, message);
-            djstest.done();
-        });
-
-        odatajs.oData.request({
-            requestUri: requestUri || "http://someUri",
-            headers: { "Content-Type": "application/json" },
-            method: "PUT",
-            data: actual
-        }, null, failTest, null, mockHttpClient);
-    };
-
-    var verifyReadJsonLightData = function (input, expected, message, model) {
-        var response = { headers: { "Content-Type": "application/json;odata.metadata=full", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
-
-        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-    var verifyReadJsonLightWithMinimalMetadata = function (input, expected, message, model) {
-        var response = { headers: { "Content-Type": "application/json;odata.metadata=minimal", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
-
-        OData.jsonHandler.read(response, { metadata: model });
-        djstest.assertAreEqualDeep(response.data, expected, message);
-    };
-
-
-    djstest.addTest(function jsonLightReadEmptySvcDocTest() {
-        var input = {
-            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
-            "value": []
-        };
-
-        var expected = {
-            workspaces: [
-                {
-                    collections: []
-                }
-            ]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadSvcDocTest() {
-        var input = {
-            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
-            "value": [
-                { "name": "Customers", "url": "Customers" },
-                { "name": "Employees", "url": "http://someUri/ODataService.svc/OData/Employees" }
-            ]
-        };
-
-        var expected = {
-            workspaces: [
-                {
-                    collections: [
-                        {
-                            title: "Customers",
-                            href: "http://someUri/ODataService.svc/OData/Customers"
-                        },
-                        {
-                            title: "Employees",
-                            href: "http://someUri/ODataService.svc/OData/Employees"
-                        }
-                    ]
-                }
-            ]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEntryMetadataUriTest() {
-        var tests = {
-            "Qualified entity set": {
-                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
-                expected: { __metadata: { type: null} }
-            },
-            "Unqualified entity set": {
-                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
-                expected: { __metadata: { type: null} }
-            },
-            "Qualified entity set with type cast": {
-                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/TypeCast/@Element" },
-                expected: { __metadata: { type: "TypeCast"} }
-            },
-
-            "Unqualified entity set with type cast": {
-                input: { "odata.metadata": "http://someUri/$metadata#EntitySet/TypeCast/@Element" },
-                expected: { __metadata: { type: "TypeCast"} }
-            }
-        };
-
-        for (name in tests) {
-            var test = tests[name];
-            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEntryMetadataUriWithMetadataDocumentTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Test.Catalog",
-                    "entityContainer": [{
-                        "name": "TestCatalog",
-                        "isDefaultEntityContainer": "true",
-                        "entitySet": [
-                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
-                    ]
-                    }, {
-                        "name": "GenreCatalog",
-                        "isDefaultEntityContainer": "false",
-                        "entitySet": [
-                           { "name": "Genres", "entityType": "TestCatalog.Model.Genre" }
-                    ]
-                    }]
-                }]
-            }
-        };
-
-        var tests = {
-            "Qualified entity set": {
-                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.GenreCatalog.Genres/@Element" },
-                expected: { __metadata: { type: "TestCatalog.Model.Genre"} }
-            },
-            "Unqualified entity set": {
-                input: { "odata.metadata": "http://someUri/$metadata#Titles/@Element" },
-                expected: { __metadata: { type: "TestCatalog.Model.Title"} }
-            },
-            "Qualified entity set with type cast": {
-                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.Titles/TestCatalog.Model.Songs/@Element" },
-                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
-            },
-            "Unqualified entity set with type cast": {
-                input: { "odata.metadata": "http://someUri/$metadata#Titles/TestCatalog.Model.Songs/@Element" },
-                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
-            },
-            "Unqualified entity set in non default entity container": {
-                input: { "odata.metadata": "http://someUri/$metadata#Generes/@Element" },
-                expected: { __metadata: { type: null} }
-            },
-            "Unqualified entity set in non default entity container with type cast": {
-                input: { "odata.metadata": "http://someUri/$metadata#Generes/TypeCast/@Element" },
-                expected: { __metadata: { type: "TypeCast"} }
-            }
-        };
-
-        for (name in tests) {
-            var test = tests[name];
-            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.", testModel);
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadTypeInPayloadWinsOverModelTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "NS",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "hasStream": "true",
-                        "key": { "propertyRef": [{ "name": "Id"}] },
-                        "property": [
-                                { "name": "Id", "type": "Edm.String" },
-                                { "name": "P1", "type": "Edm.String" },
-                                { "name": "P2", "type": "NS.ComplexType" },
-                                { "name": "P3", "type": "Edm.Int64" }
-                            ]
-                    }],
-                    "complexType": [{
-                        "name": "ComplexType",
-                        "property": [
-                            { "name": "C1", "type": "Edm.String" }
-                        ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
-            P1: "Hello",
-            P2: {
-                "odata.type": "Instance",
-                C1: "World"
-            },
-            "P2@odata.type": "Property",
-            P3: "500",
-            "P3@odata.type": "Property",
-            P4: {
-                "odata.type": "NS.ComplexType",
-                C1: "!!"
-            }
-        };
-
-        var expected = {
-            __metadata: {
-                type: "NS.EntityType",
-                properties: {
-                    P1: { type: "Edm.String" },
-                    P2: {
-                        type: "Instance",
-                        properties: {
-                            C1: { type: null }
-                        }
-                    },
-                    P3: { type: "Property" },
-                    P4: {
-                        type: "NS.ComplexType",
-                        properties: {
-                            C1: { type: "Edm.String" }
-                        }
-                    }
-                }
-            },
-            P1: "Hello",
-            P2: {
-                __metadata: {
-                    type: "Instance"
-                },
-                C1: "World"
-            },
-            P3: "500",
-            P4: {
-                __metadata: {
-                    type: "NS.ComplexType"
-                },
-                C1: "!!"
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadObjectWithCollectionPropertyTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "NS",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "property": [
-                                { "name": "p1", "type": "Collection(Edm.Int32)" }
-                            ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
-            p1: [1, 2, 3],
-            p2: [
-                { c1: 100, c2: 200 },
-                { c1: 400, c2: 500, "odata.type": "NS.OtherType" }
-            ],
-            "p2@odata.type": "Collection(NS.ComplexType)",
-            p3: [5, 6, 7]
-        };
-
-        var expected = {
-            __metadata: {
-                type: "NS.EntityType",
-                properties: {
-                    p1: { type: "Collection(Edm.Int32)" },
-                    p2: {
-                        type: "Collection(NS.ComplexType)",
-                        elements: [
-                            {
-                                type: "NS.ComplexType",
-                                properties: {
-                                    c1: { type: null },
-                                    c2: { type: null }
-                                }
-                            },
-                            {
-                                type: "NS.OtherType",
-                                properties: {
-                                    c1: { type: null },
-                                    c2: { type: null }
-                                }
-                            }
-                        ]
-                    },
-                    p3: { type: null }
-                }
-            },
-            p1: {
-                __metadata: { type: "Collection(Edm.Int32)" },
-                results: [1, 2, 3]
-            },
-            p2: {
-                __metadata: { type: "Collection(NS.ComplexType)" },
-                results: [
-                    {
-                        __metadata: {
-                            type: "NS.ComplexType"
-                        },
-                        c1: 100,
-                        c2: 200
-                    },
-                    {
-                        __metadata: {
-                            type: "NS.OtherType"
-                        },
-                        c1: 400,
-                        c2: 500
-                    }
-                ]
-            },
-            p3: {
-                __metadata: { type: null },
-                results: [5, 6, 7]
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with collection porperties was read properly", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEntryODataAnnotationsTest() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
-            "odata.id": "Customers(1)",
-            "odata.etag": "etag-value",
-            "odata.readLink": "read/Customers(1)",
-            "odata.editLink": "Customers(1)",
-            "odata.mediaReadLink": "Customers(1)/Image",
-            "odata.mediaEditLink": "Customers(1)/$value",
-            "odata.mediaETag": "stream-etag-value",
-            "odata.mediaContentType": "image/jpg"
-        };
-
-        var expected = {
-            __metadata: {
-                id: "Customers(1)",
-                type: "TypeCast",
-                etag: "etag-value",
-                self: "http://someUri/read/Customers(1)",
-                edit: "http://someUri/Customers(1)",
-                uri: "http://someUri/Customers(1)",
-                media_src: "http://someUri/Customers(1)/Image",
-                edit_media: "http://someUri/Customers(1)/$value",
-                media_etag: "stream-etag-value",
-                content_type: "image/jpg"
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light entry OData annotations were read properly");
-        djstest.done();
-    });
-
-
-    djstest.addTest(function jsonLightReadObjectWithComplexPropertyTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Ns",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "property": [
-                                { "name": "p1", "type": "Ns.ComplexType" }
-                         ]
-                    }],
-                    "complexType": [{
-                        "name": "ComplexType",
-                        "property": [
-                            { "name": "c1", "type": "Edm.Int16" },
-                            { "name": "c2", "type": "Edm.Int32" },
-                            { "name": "c3", "type": "Ns.ComplexType" }
-                        ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
-            p1: {
-                c1: 100,
-                c2: 200,
-                c3: {
-                    c1: 300,
-                    c2: 400,
-                    c3: {
-                        c1: 500,
-                        c2: 600,
-                        c3: null
-                    }
-                }
-            },
-            p2: {
-                "odata.type": "Ns.ComplexType2",
-                c4: 800,
-                "c4@odata.type": "Edm.Single",
-                c5: 900,
-                c6: {
-                    c1: 1000,
-                    c2: 2000,
-                    c3: {
-                        c1: 1100,
-                        "c1@odata.type": "Edm.Double",
-                        c2: 1200,
-                        c3: null
-                    }
-                },
-                "c6@odata.type": "Ns.ComplexType"
-            },
-            p3: {},
-            "p3@odata.type": "Ns.ComplexType3"
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Ns.EntityType",
-                properties: {
-                    p1: {
-                        type: "Ns.ComplexType",
-                        properties: {
-                            c1: { type: "Edm.Int16" },
-                            c2: { type: "Edm.Int32" },
-                            c3: {
-                                type: "Ns.ComplexType",
-                                properties: {
-                                    c1: { type: "Edm.Int16" },
-                                    c2: { type: "Edm.Int32" },
-                                    c3: {
-                                        type: "Ns.ComplexType",
-                                        properties: {
-                                            c1: { type: "Edm.Int16" },
-                                            c2: { type: "Edm.Int32" },
-                                            c3: { type: "Ns.ComplexType" }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    p2: {
-                        type: "Ns.ComplexType2",
-                        properties: {
-                            c4: { type: "Edm.Single" },
-                            c5: { type: null },
-                            c6: {
-                                type: "Ns.ComplexType",
-                                properties: {
-                                    c1: { type: "Edm.Int16" },
-                                    c2: { type: "Edm.Int32" },
-                                    c3: {
-                                        type: "Ns.ComplexType",
-                                        properties: {
-                                            c1: { type: "Edm.Double" },
-                                            c2: { type: "Edm.Int32" },
-                                            c3: { type: "Ns.ComplexType" }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    p3: { type: "Ns.ComplexType3" }
-                }
-            },
-            p1: {
-                __metadata: { type: "Ns.ComplexType" },
-                c1: 100,
-                c2: 200,
-                c3: {
-                    __metadata: { type: "Ns.ComplexType" },
-                    c1: 300,
-                    c2: 400,
-                    c3: {
-                        __metadata: { type: "Ns.ComplexType" },
-                        c1: 500,
-                        c2: 600,
-                        c3: null
-                    }
-                }
-            },
-            p2: {
-                __metadata: { type: "Ns.ComplexType2" },
-                c4: 800,
-                c5: 900,
-                c6: {
-                    __metadata: { type: "Ns.ComplexType" },
-                    c1: 1000,
-                    c2: 2000,
-                    c3: {
-                        __metadata: { type: "Ns.ComplexType" },
-                        c1: 1100,
-                        c2: 1200,
-                        c3: null
-                    }
-                }
-            },
-            p3: { __metadata: { type: "Ns.ComplexType3"} }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with complex type properties was read properly", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadObjectWithNamedStreamProperty() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
-            "p1@odata.mediaReadLink": "Customers(1)/namedStream",
-            "p1@odata.mediaEditLink": "Customers(1)/namedStream/$value",
-            "p1@odata.mediaETag": "voice-etag-value",
-            "p1@odata.mediaContentType": "audio/basic"
-        };
-
-        var expected = {
-            __metadata: {
-                type: "TypeCast",
-                properties: {
-                    p1: { type: null }
-                }
-            },
-            p1: {
-                __mediaresource: {
-                    media_src: "http://someUri/Customers(1)/namedStream",
-                    edit_media: "http://someUri/Customers(1)/namedStream/$value",
-                    media_etag: "voice-etag-value",
-                    content_type: "audio/basic"
-                }
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with named stream properties was read properly");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEntryWithDeferredNavigationPropertyTests() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
-            "p1@odata.navigationLinkUrl": "entitySet(1)/deferred",
-            "p1@odata.associationLinkUrl": "entitySet(1)/$links/deferred"
-        };
-
-        var expected = {
-            __metadata: {
-                type: "TypeCast",
-                properties: {
-                    p1: {
-                        type: null,
-                        associationLinkUrl: "http://someUri/entitySet(1)/$links/deferred"
-                    }
-                }
-            },
-            p1: {
-                __deferred: {
-                    uri: "http://someUri/entitySet(1)/deferred"
-                }
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with deferred navigation properties was read properly");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEntryWithInlinedNavigationPropertiesTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Ns",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "navigationProperty": [
-                            { "name": "p1", "relationship": "Ns.Rel1", "toRole": "p1s" },
-                            { "name": "p2", "relationship": "Ns.Rel2", "toRole": "p2s" }
-                        ]
-                    }],
-                    "association": [{
-                        "name": "Rel1",
-                        "end": [
-                            { "type": "Ns.EntityType1", "role": "p1s" },
-                            { "type": "Ns.EntityType", "role": "otherRole" }
-                         ]
-                    },
-                    {
-                        "name": "Rel2",
-                        "end": [
-                            { "type": "Ns.EntityType", "role": "otherRole" },
-                            { "type": "Ns.EntityType2", "role": "p2s" }
-                         ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
-            p1: [
-                { e1: 100, e2: 200 },
-                { e1: 110, e2: 220 }
-            ],
-            "p1@odata.count": 50,
-            "p1@odata.nextLink": "nextToken",
-            p2: {
-                e3: 300
-            },
-            p3: [
-                { e4: 400, e5: 500 },
-                { e4: 440, e5: 550 }
-            ],
-            "p3@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p3",
-            "p3@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p3",
-            p4: {
-                e6: 600
-            },
-            "p4@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p4",
-            "p4@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p4",
-            p5: [
-                {
-                    "odata.id": 12345,
-                    e7: 700,
-                    e8: 800
-                }
-            ],
-            p6: {
-                "odata.id": 78910,
-                e9: 900,
-                "e9@odata.type": "Edm.Int32"
-            }
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Ns.EntityType",
-                properties: {
-                    p1: {
-                        type: "Ns.EntityType1"
-                    },
-                    p2: {
-                        type: "Ns.EntityType2"
-                    },
-                    p3: {
-                        type: null,
-                        navigationLinkUrl: "http://someUri/entitySet(1)/p3",
-                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p3"
-                    },
-                    p4: {
-                        type: null,
-                        navigationLinkUrl: "http://someUri/entitySet(1)/p4",
-                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p4"
-                    },
-                    p5: {
-                        type: null
-                    },
-                    p6: {
-                        type: null
-                    }
-                }
-            },
-            p1: {
-                __count: 50,
-                __next: "http://someUri/nextToken",
-                results: [
-            {
-                __metadata: {
-                    type: "Ns.EntityType1",
-                    properties: {
-                        e1: { type: null },
-                        e2: { type: null }
-                    }
-                },
-                e1: 100,
-                e2: 200
-            },
-            {
-                __metadata: {
-                    type: "Ns.EntityType1",
-                    properties: {
-                        e1: { type: null },
-                        e2: { type: null }
-                    }
-                },
-                e1: 110,
-                e2: 220
-            }
-          ]
-            },
-            p2: {
-                __metadata: {
-                    type: "Ns.EntityType2",
-                    properties: {
-                        e3: { type: null }
-                    }
-                },
-                e3: 300
-            },
-            p3: {
-                results: [
-            {
-                __metadata: {
-                    type: null,
-                    properties: {
-                        e4: { type: null },
-                        e5: { type: null }
-                    }
-                },
-                e4: 400,
-                e5: 500
-            },
-            {
-                __metadata: {
-                    type: null,
-                    properties: {
-                        e4: { type: null },
-                        e5: { type: null }
-                    }
-                },
-                e4: 440,
-                e5: 550
-            }
-            ]
-            },
-            p4: {
-                __metadata: {
-                    type: null,
-                    properties: {
-                        e6: { type: null }
-                    }
-                },
-                e6: 600
-            },
-            p5: {
-                results: [
-                {
-                    __metadata: {
-                        id: 12345,
-                        type: null,
-                        properties: {
-                            e7: { type: null },
-                            e8: { type: null }
-                        }
-                    },
-                    e7: 700,
-                    e8: 800
-                }
-            ]
-            },
-            p6: {
-                __metadata: {
-                    id: 78910,
-                    type: null,
-                    properties: {
-                        e9: { type: "Edm.Int32" }
-                    }
-                },
-                e9: 900
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with inlined navigation properties was read properly", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadStringPropertiesTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Ns",
-                    "entityType": [{
-                        "name": "EntityType",
-                        "property": [
-                                { "name": "p1", "type": "Edm.DateTime" },
-                                { "name": "p2", "type": "Edm.DateTimeOffset" },
-                                { "name": "p3", "type": "Edm.Time" }
-                            ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
-            p1: "2000-01-02T03:04:05",
-            p2: "2000-01-02T03:04:05+01:00",
-            p3: "P0Y0M05DT12H30M5S",
-            p4: "hello world",
-            p5: "2001-01-02T03:04:05",
-            "p5@odata.type": "Edm.DateTime",
-            p6: "2001-01-02T03:04:05+01:00",
-            "p6@odata.type": "Edm.DateTimeOffset",
-            p7: "P0Y0M05DT12H30M10S",
-            "p7@odata.type": "Edm.Time"
-        };
-
-        var p2 = new Date("01/02/2000 02:04:05 GMT");
-        p2.__edmType = "Edm.DateTimeOffset";
-        p2.__offset = "+01:00";
-
-        var p6 = new Date("01/02/2001 02:04:05 GMT");
-        p2.__edmType = "Edm.DateTimeOffset";
-        p2.__offset = "+01:00";
-
-        var expected = {
-            __metadata: {
-                type: "Ns.EntityType",
-                properties: {
-                    p1: { type: "Edm.DateTime" },
-                    p2: { type: "Edm.DateTimeOffset" },
-                    p3: { type: "Edm.Time" },
-                    p4: { type: null },
-                    p5: { type: "Edm.DateTime" },
-                    p6: { type: "Edm.DateTimeOffset" },
-                    p7: { type: "Edm.Time" }
-                }
-            },
-            p1: new Date("01/02/2000 03:04:05 GMT"),
-            p3: { ms: 477005000, __edmType: "Edm.Time" },
-            p2: p2,
-            p4: "hello world",
-            p5: new Date("01/02/2001 03:04:05 GMT"),
-            p6: p6,
-            p7: { ms: 477010000, __edmType: "Edm.Time" }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light object with string properties was read properly", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadRecognizeDateLiteralsTest() {
-        var input = {
-            p1: "2000-01-02T03:04:05",
-            p2: "2000-01-02T03:04:05+01:00"
-        };
-
-        var p2 = new Date("01/02/2000 02:04:05 GMT");
-        p2.__edmType = "Edm.DateTimeOffset";
-        p2.__offset = "+01:00";
-
-        var expected = {
-            __metadata: {
-                properties: {
-                    p1: {
-                        type: null
-                    },
-                    p2: {
-                        type: null
-                    }
-                },
-                type: null
-            },
-            p1: new Date("01/02/2000 03:04:05 GMT"),
-            p2: p2
-        };
-
-        OData.jsonHandler.recognizeDates = true;
-        verifyReadJsonLightData(input, expected, "Json light datetime literals were recognized. ");
-
-        OData.jsonHandler.recognizeDates = false;
-
-        expected.p1 = input.p1;
-        expected.p2 = input.p2;
-
-        verifyReadJsonLightData(input, expected, "Json light datetime literals were ignored");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEmptyFeedTest() {
-        var input = { "odata.metadata": "http://someUri#entitySet/Set", value: [] };
-        var expected = { results: [] };
-
-        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadFeedTest() {
-        var input = {
-            "odata.metadata": "http://someUri#entitySet/Type",
-            value: [
-              { "odata.id": 12345 },
-              { "odata.id": 56789 }
-            ],
-            "odata.count": 50,
-            "odata.nextLink": "skipToken"
-        };
-
-        var expected = {
-            __count: 50,
-            __next: "http://someUri/skipToken",
-            results: [
-                {
-                    __metadata: {
-                        id: 12345,
-                        type: "Type"
-                    }
-                },
-                {
-                    __metadata: {
-                        id: 56789,
-                        type: "Type"
-                    }
-                }
-            ]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadFeedUsingMetadataTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Test.Catalog",
-                    "entityContainer": [{
-                        "name": "TestCatalog",
-                        "isDefaultEntityContainer": "true",
-                        "entitySet": [
-                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
-                        ]
-                    }
-                    ]
-                }
-                ]
-            }
-        };
-
-        var tests = {
-            "Unqualified entity set": {
-                input: { "odata.metadata": "http://someUri#Titles", value: [{}] },
-                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
-            },
-            "Qualified entity set": {
-                input: { "odata.metadata": "http://someUri#Test.Catalog.TestCatalog.Titles", value: [{}] },
-                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
-            },
-            "Type casted entity set": {
-                input: { "odata.metadata": "http://someUri#TestCatalog.Titles/TypeCast", value: [{}] },
-                expected: { results: [{ __metadata: { type: "TypeCast"}}] }
-            }
-        };
-
-        for (var name in tests) {
-            var test = tests[name];
-            verifyReadJsonLightData(test.input, test.expected, name + " - Json light feed was read properly.", testModel);
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadInferFeedAsObjectTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Test.Catalog",
-                    "entityContainer": [{
-                        "name": "TestCatalog",
-                        "isDefaultEntityContainer": "true",
-                        "entitySet": [
-                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
-                        ]
-                    }
-                    ]
-                }
-                ]
-            }
-        };
-
-        var tests = {
-            "Feed as object": {
-                input: { "odata.metadata": "http://someUri#EntitySet", value: [] },
-                expected: {
-                    __metadata: {
-                        type: "EntitySet",
-                        properties: {
-                            value: { type: null }
-                        }
-                    },
-                    value: { __metadata: { type: null }, results: [] }
-                }
-            },
-            "Feed as feed using value": {
-                input: { "odata.metadata": "http://someUri#EntiySet", value: [{ "odata.id": 12345}] },
-                expected: { results: [{ __metadata: { type: null, id: 12345}}] }
-            },
-            "Feed as feed using metadata": {
-                input: { "odata.metadata": "http://someUri#Titles", value: [] },
-                expected: { results: [] }
-            },
-            "Collection of primitive": {
-                input: { "odata.metadata": "http://someUri#Collection(Edm.Int32)", value: [] },
-                expected: { __metadata: { type: "Collection(Edm.Int32)" }, results: [] }
-            },
-            "Collection of complex": {
-                input: { "odata.metadata": "http://someUri#Collection(My.Type)", value: [] },
-                expected: { __metadata: { type: "Collection(My.Type)" }, results: [] }
-            }
-        };
-
-        for (var name in tests) {
-            var test = tests[name];
-            var response = {
-                headers: {
-                    "Content-Type": "application/json;odata.metadata=full",
-                    DataServiceVersion: "4.0"
-                },
-                body: JSON.stringify(test.input)
-            };
-
-            OData.jsonHandler.read(response, { metadata: testModel });
-            djstest.assertAreEqualDeep(response.data, test.expected, name + " - Json light object was read properly ");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadEmptyLinksDocumentTest() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
-            value: []
-        };
-
-        var expected = {
-            results: []
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadLinksDocumentTest() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
-            value: [
-                        { url: "Products(1)" },
-                        { url: "http://someUri/Products(2)" }
-                     ]
-        };
-
-        var expected = {
-            results: [
-                        { uri: "http://someUri/Products(1)" },
-                        { uri: "http://someUri/Products(2)" }
-                    ]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadSingleLinkDocumentTest() {
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp/@Element",
-            url: "Products(1)"
-        };
-
-        var expected = {
-            uri: "http://someUri/Products(1)"
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light single link document was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadTopLevelPrimitiveProperty() {
-        var input = {
-            "odata.metadata": "http://someUri#Edm.GeometryPoint",
-            value: {
-                type: "Point",
-                coordinates: [1.0, 2.0],
-                crs: {
-                    type: name,
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-            }
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Edm.GeometryPoint"
-            },
-            value: {
-                type: "Point",
-                coordinates: [1.0, 2.0],
-                crs: {
-                    type: name,
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light top level primitive property was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadTopLevelComplexTypeTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Ns",
-                    "complexType": [{
-                        "name": "ComplexType",
-                        "property": [
-                            { "name": "value", "type": "Collection(Ns.ComplexType2)" }
-                        ]
-                    }]
-                }]
-            }
-        };
-
-        var input = {
-            "odata.metadata": "http://someUri#Ns.ComplexType",
-            value: [{
-                p1: 100,
-                p2: 200
-            }]
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Ns.ComplexType",
-                properties: {
-                    value: {
-                        type: "Collection(Ns.ComplexType2)",
-                        elements: [
-                            {
-                                type: "Ns.ComplexType2",
-                                properties: {
-                                    p1: { type: null },
-                                    p2: { type: null }
-                                }
-                            }
-                        ]
-                    }
-                }
-            },
-            value: {
-                __metadata: { type: "Collection(Ns.ComplexType2)" },
-                results: [
-                    {
-                        __metadata: { type: "Ns.ComplexType2" },
-                        p1: 100,
-                        p2: 200
-                    }
-                ]
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light top level complex type property was read properly.", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadTopPrimitiveCollectionPropertyTest() {
-        var input = {
-            "odata.metadata": "http://someUri#Collection(Edm.GeometryPoint)",
-            value: [{
-                type: "Point",
-                coordinates: [1.0, 2.0],
-                crs: {
-                    type: "name",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-            }]
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Collection(Edm.GeometryPoint)"
-            },
-            results: [{
-                type: "Point",
-                coordinates: [1.0, 2.0],
-                crs: {
-                    type: "name",
-                    properties: {
-                        name: "EPSG:4326"
-                    }
-                }
-            }]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light top level primitive collection property was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadTopLevelComplexTypeCollectionTest() {
-        var input = {
-            "odata.metadata": "http://someUri#Collection(Ns.ComplexType2)",
-            value: [{
-                p1: 100,
-                p2: 200,
-                "p2@odata.type": "Edm.Int16"
-            }]
-        };
-
-        var expected = {
-            __metadata: {
-                type: "Collection(Ns.ComplexType2)",
-                elements: [
-                    {
-                        type: "Ns.ComplexType2",
-                        properties: {
-                            p1: { type: null },
-                            p2: { type: "Edm.Int16" }
-                        }
-                    }
-                ]
-            },
-            results: [
-                {
-                    __metadata: { type: "Ns.ComplexType2" },
-                    p1: 100,
-                    p2: 200
-                }
-             ]
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light top level complex type collection property was read properly.");
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadFeedAdvertisedActionsTest() {
-
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Ns",
-                    "entityContainer": [{
-                        "name": "EntityContainer",
-                        "isDefaultEntityContainer": "true",
-                        "entitySet": [
-                           { "name": "EntitySet", "entityType": "Ns.EntityType" }
-                        ]
-                    }
-                    ]
-                }
-                ]
-            }
-        };
-
-        input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet",
-            "#action1": {
-                target: "action1/item(0)",
-                title: "Action1"
-            },
-            "#action2": {
-                target: "action2/item(0)",
-                title: "Action2"
-            },
-            value: []
-        };
-
-        expected = {
-            __metadata: {
-                actions: [
-                    {
-                        metadata: "http://someUri/action1",
-                        target: "http://someUri/action1/item(0)",
-                        title: "Action1"
-                    },
-                   {
-                       metadata: "http://someUri/action2",
-                       target: "http://someUri/action2/item(0)",
-                       title: "Action2"
-                   }
-                ]
-            },
-            results: []
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light feed with advertised actions was read properly.", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightReadAdvertisedActionsAndFunctionsTest() {
-        var testModel = {
-            "version": "1.0",
-            "dataServices": {
-                "dataServiceVersion": "4.0",
-                "schema": [{
-                    "namespace": "Test.Catalog",
-                    "entityContainer": [{
-                        "name": "TestCatalog",
-                        "isDefaultEntityContainer": "true",
-                        "functionImport": [
-                            { "name": "function1", "isSideEffecting": "false" },
-                            { "name": "function2", "isSideEffecting": "false" },
-                            { "name": "action1", "isSideEffecting": "true" },
-                            { "name": "action2" }
-                         ]
-                    }, {
-                        "name": "OtherCatalog",
-                        "isDefaultEntityContainer": "false",
-                        "functionImport": [
-                            { "name": "function1", "isSideEffecting": "false" }
-                         ]
-                    }]
-                }]
-            }
-        };
-
-        input = {
-            "odata.metadata": "http://someUri/$metadata#EntitySet/@Element",
-            "#function2": [
-                {
-                    target: "function2/item(0)",
-                    title: "Function2 overload1"
-                },
-                {
-                    target: "function2/item(0)",
-                    title: "Function2 overload2"
-                }
-            ],
-            "#action1": {
-                target: "action1/item(0)",
-                title: "Action1"
-            },
-            "#action2": {
-                target: "action2/item(0)",
-                title: "Action2"
-            },
-            "#function1": {
-                target: "function1/item(0)",
-                title: "Function1"
-            },
-            "#Test.Catalog.OtherCatalog.function1": {
-                target: "Test.Catalog.OtherCatalog.function1/item(0)",
-                title: "Function1 in other catalog"
-            },
-            "#action3": [
-                {
-                    target: "action3/item(0)",
-                    title: "Unkown action overload1"
-                },
-                {
-                    target: "http://otherUri/action3/item(0)",
-                    title: "Unkown action overload2"
-                }
-            ]
-        };
-
-        expected = {
-            __metadata: {
-                type: null,
-                actions: [
-                   {
-                       metadata: "http://someUri/action1",
-                       target: "http://someUri/action1/item(0)",
-                       title: "Action1"
-                   },
-                   {
-                       metadata: "http://someUri/action2",
-                       target: "http://someUri/action2/item(0)",
-                       title: "Action2"
-                   },
-                   {
-                       metadata: "http://someUri/action3",
-                       target: "http://someUri/action3/item(0)",
-                       title: "Unkown action overload1"
-                   },
-                   {
-                       metadata: "http://someUri/action3",
-                       target: "http://otherUri/action3/item(0)",
-                       title: "Unkown action overload2"
-                   }
-                ],
-                functions: [
-                    {
-                        metadata: "http://someUri/function2",
-                        target: "http://someUri/function2/item(0)",
-                        title: "Function2 overload1"
-                    },
-                    {
-                        metadata: "http://someUri/function2",
-                        target: "http://someUri/function2/item(0)",
-                        title: "Function2 overload2"
-                    },
-                    {
-                        metadata: "http://someUri/function1",
-                        target: "http://someUri/function1/item(0)",
-                        title: "Function1"
-                    },
-                    {
-                        metadata: "http://someUri/Test.Catalog.OtherCatalog.function1",
-                        target: "http://someUri/Test.Catalog.OtherCatalog.function1/item(0)",
-                        title: "Function1 in other catalog"
-                    }
-                ]
-            }
-        };
-
-        verifyReadJsonLightData(input, expected, "Json light advertised actions and functions were read properly.", testModel);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryMetadataTest() {
-        var data = {
-            __metadata: {
-                metadata: "http://someUri/$metadata#NS.Container/Set/@Element",
-                id: "http://someUri/Customers(1)",
-                etag: "etag-value",
-                self: "http://someUri/read/Customers(1)",
-                edit: "http://someUri/read/Customers(1)",
-                media_src: "http://someUri/Customers(1)/Image",
-                edit_media: "http://someUri/Customers(1)/$value",
-                media_etag: "stream-etag-value",
-                content_type: "image/jpg"
-            }
-        };
-
-        var expected = {
-            "odata.etag": "etag-value",
-            "odata.mediaReadLink": "http://someUri/Customers(1)/Image",
-            "odata.mediaEditLink": "http://someUri/Customers(1)/$value",
-            "odata.mediaETag": "stream-etag-value",
-            "odata.mediaContentType": "image/jpg"
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry metadata was serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeCustomAnnotationsTest() {
-        var data = {
-            __metadata: {
-                id: "id"
-            },
-            "odata.id": "id",
-            "custom.annotation": "custom annotation value",
-            "p1@ns1.primitive": "primitive",
-            "p1@ns2.complex": { a1: 500 },
-            "p1@ns3.ns4.value": 600,
-            "p2@ns1.primitive": 400,
-            "custom.annotation": "custom annotation value"
-        };
-
-        var expected = {
-            "odata.id": "id",
-            "custom.annotation": "custom annotation value",
-            "p1@ns1.primitive": "primitive",
-            "p1@ns2.complex": { a1: 500 },
-            "p1@ns3.ns4.value": 600,
-            "p2@ns1.primitive": 400
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light custom annotations were serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryCollectionPropertiesTest() {
-        var data = {
-            __metadata: {
-                id: "id",
-                properties: {
-                    primitiveColArray: { type: "Collection(Edm.Int16)" },
-                    primitiveColObject: { type: "Collection(Edm.Int32)" }
-                }
-            },
-            primitiveColArray: [1, 2, 3, 4],
-            primitiveColObject: {
-                results: [5, 6, 7, 8]
-            },
-            complexColArray: [{ p1: 100 }, { p1: 200}],
-            complexColObject: {
-                results: [{ p1: 300 }, { p1: 400}]
-            }
-        };
-
-        var expected = {
-            "primitiveColArray@odata.type": "Collection(Edm.Int16)",
-            primitiveColArray: [1, 2, 3, 4],
-            "primitiveColObject@odata.type": "Collection(Edm.Int32)",
-            primitiveColObject: [5, 6, 7, 8],
-            complexColArray: [{ p1: 100 }, { p1: 200}],
-            complexColObject: [{ p1: 300 }, { p1: 400}]
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry collection properties were serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryDeferredPropertyTest() {
-        var data = {
-            __metadata: {
-                id: "id",
-                properties: {
-                    deferred: {
-                        associationLinkUrl: "http://target/$links"
-                    }
-                }
-            },
-            deferred: {
-                __deferred: { uri: "http://target" }
-            }
-        };
-
-        var expected = {
-            "deferred@odata.navigationLinkUrl": "http://target"
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry deferred property were serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryInlinePropertiesTest() {
-        var data = {
-            __metadata: {
-                id: "id"
-            },
-            inlineEntry: {
-                __metadata: { uri: "", properties: { p1: { type: "Edm.Int64"}} },
-                p1: "300"
-            },
-            inlineBoundEntry: {
-                __metadata: { uri: "http://entries(1)", properties: { p1: { type: "Edm.Int64"}} },
-                p1: "400"
-            },
-            inlineFeedArray: [
-                {
-                    __metadata: { uri: "http://entries(2)" }
-                },
-                {
-                    __metadata: { uri: "", properties: { p1: { type: "Edm.Int32"}} },
-                    p1: "600"
-                },
-                {
-                    __metadata: { uri: "http://entries(3)" }
-                }
-            ],
-            inlineFeedObject: {
-                __count: 50,
-                __next: "next link",
-                results: [
-                    { __metadata: { uri: "" }, p1: "900" }
-                ]
-            },
-            inlineEmptyFeedObject: {
-                results: []
-            }
-        };
-
-        var expected = {
-            inlineEntry: {
-                "p1@odata.type": "Edm.Int64",
-                p1: "300"
-            },
-            "inlineBoundEntry@odata.bind": "http://entries(1)",
-            inlineFeedArray: [{
-                "p1@odata.type": "Edm.Int32",
-                p1: "600"
-            }],
-            "inlineFeedArray@odata.bind": [
-                "http://entries(2)",
-                "http://entries(3)"
-            ],
-            inlineFeedObject: [{
-                p1: "900"
-            }],
-            inlineEmptyFeedObject: []
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry inline properties were serialized properly.");
-
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryComplexPropertyTest() {
-        var data = {
-            __metadata: {
-                id: "id",
-                properties: {
-                    complexAsDeferredOnMetadata: {
-                        type: "complexAsDeferredOnMetadata.type"
-                    },
-                    complexAsCol: {
-                        type: "complexAsCol.type"
-                    }
-                }
-            },
-            complexAsDeferred: {
-                __metadata: {
-                    type: "complexAsDeferred.type"
-                },
-                __deferred: { uri: "http://uri" }
-            },
-            complexAsCol: {
-                results: [1, 2, 3, 4]
-            },
-            complexAsNamedStream: {
-                __metadata: {
-                    type: "complexAsNamedStream"
-                },
-                __mediaresource: {
-                    content_type: "content type",
-                    media_src: "http://source"
-                }
-            },
-            complexAsDeferredOnMetadata: {
-                __deferred: { uri: "http://uri2" }
-            }
-        };
-
-        var expected = {
-            complexAsDeferred: {
-                "odata.type": "complexAsDeferred.type",
-                __deferred: { uri: "http://uri" }
-            },
-            complexAsCol: {
-                "odata.type": "complexAsCol.type",
-                results: [1, 2, 3, 4]
-            },
-            complexAsNamedStream: {
-                "odata.type": "complexAsNamedStream",
-                __mediaresource: {
-                    content_type: "content type",
-                    media_src: "http://source"
-                }
-            },
-            complexAsDeferredOnMetadata: {
-                "odata.type": "complexAsDeferredOnMetadata.type",
-                __deferred: { uri: "http://uri2" }
-            }
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry complex properties were serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeEntryComplexPropertyMetadataTest() {
-        var data = {
-            __metadata: {
-                id: "id",
-                properties: {
-                    complex: {
-                        type: "this should be overriden",
-                        properties: {
-                            nested1: {
-                                type: "types.complex.nested1",
-                                properties: {
-                                    nested2: {
-                                        type: "types.complex.nested1.nested2"
-                                    }
-                                }
-                            },
-                            c1: {
-                                type: "Edm.Int64"
-                            }
-                        }
-                    }
-                }
-            },
-            complex: {
-                __metadata: {
-                    type: "types.complex"
-                },
-                c1: "500",
-                c2: "b",
-                nested1: {
-                    nested2: {
-                    }
-                }
-            }
-        };
-
-        var expected = {
-            complex: {
-                "odata.type": "types.complex",
-                "c1@odata.type": "Edm.Int64",
-                c1: "500",
-                c2: "b",
-                nested1: {
-                    "odata.type": "types.complex.nested1",
-                    nested2: {
-                        "odata.type": "types.complex.nested1.nested2"
-                    }
-                }
-            }
-        };
-
-        verifySerializedJsonLightData(data, expected, " Json light entry complex property was serialized properly.");
-    });
-
-    djstest.addTest(function jsonLightSerializeLinksDocumentTest() {
-        var tests = {
-            "Empty uri string": {
-                i: { uri: "" },
-                e: { url: "" }
-            },
-            "Null uri string": {
-                i: { uri: null },
-                e: { url: null }
-            },
-            "Undefined uri string": {
-                i: { uri: undefined },
-                e: {}
-            },
-            "Uri": {
-                i: { uri: "http://somUri/EntitySet(1)" },
-                e: { url: "http://somUri/EntitySet(1)" }
-            }
-        };
-
-        for (var name in tests) {
-            verifySerializedJsonLightData(tests[name].i, tests[name].e, name + " - Json light links documents whas serialized properly.", "http://someUri/set(3)/$links/navprop");
-        }
-    });
-
-    djstest.addTest(function jsonLightComputeLinksWithSingleKey() {
-        var model = getSampleModel();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "MyId",
-            P1: 42
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes('MyId')",
-                "edit": "http://someUri/EntityTypes('MyId')",
-                "uri": "http://someUri/EntityTypes('MyId')",
-                "self": "http://someUri/EntityTypes('MyId')"
-
-            },
-            "Id": "MyId",
-            "P1": 42
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinksWithMultipleKeys() {
-        var model = getSampleModelWithTwoKeys();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "MyId",
-            P1: 42
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes(Id='MyId',P1=42)",
-                "edit": "http://someUri/EntityTypes(Id='MyId',P1=42)",
-                "uri": "http://someUri/EntityTypes(Id='MyId',P1=42)",
-                "self": "http://someUri/EntityTypes(Id='MyId',P1=42)"
-            },
-            "Id": "MyId",
-            "P1": 42
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinksWithNonComputedEditLink() {
-        var model = getSampleModel();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            "odata.editLink": "EntityTypes('notcomputed')",
-            Id: "MyId",
-            P1: 42
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes('notcomputed')",
-                "edit": "http://someUri/EntityTypes('notcomputed')",
-                "uri": "http://someUri/EntityTypes('notcomputed')",
-                "self": "http://someUri/EntityTypes('notcomputed')"
-            },
-            "Id": "MyId",
-            "P1": 42
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinksWithSingleConcurrencyProperty() {
-        var model = getSampleModelWithOneConcurrencyProperty();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "MyId",
-            P1: 42
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes('MyId')",
-                "edit": "http://someUri/EntityTypes('MyId')",
-                "uri": "http://someUri/EntityTypes('MyId')",
-                "self": "http://someUri/EntityTypes('MyId')",
-                "etag": "W/\"'MyId'\""
-            },
-            "Id": "MyId",
-            "P1": 42
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinksWithSingleBinaryConcurrencyProperty() {
-        var model = getSampleModelWithOneBinaryConcurrencyProperty();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "MyId",
-            P1: "AAAAAAAAB9E="
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Binary"} },
-                "id": "http://someUri/EntityTypes('MyId')",
-                "edit": "http://someUri/EntityTypes('MyId')",
-                "uri": "http://someUri/EntityTypes('MyId')",
-                "self": "http://someUri/EntityTypes('MyId')",
-                "etag": "W/\"X'00000000000007D1'\""
-            },
-            "Id": "MyId",
-            "P1": "AAAAAAAAB9E="
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinkWithMutipleConcurrencyProperty() {
-        var model = getSampleModelWithMultipleConcurrencyProperties();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "MyId",
-            P1: 42
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes('MyId')",
-                "edit": "http://someUri/EntityTypes('MyId')",
-                "uri": "http://someUri/EntityTypes('MyId')",
-                "self": "http://someUri/EntityTypes('MyId')",
-                "etag": "W/\"'MyId',42\""
-            },
-            "Id": "MyId",
-            "P1": 42
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonLightComputeLinkWithNullConcurrencyProperty() {
-        var model = getSampleModelWithMultipleConcurrencyProperties();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "My Id'",
-            P1: null
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
-                "id": "http://someUri/EntityTypes('My%20Id''')",
-                "edit": "http://someUri/EntityTypes('My%20Id''')",
-                "uri": "http://someUri/EntityTypes('My%20Id''')",
-                "self": "http://someUri/EntityTypes('My%20Id''')",
-                "etag": "W/\"'My%20Id''',null\""
-            },
-            "Id": "My Id'",
-            "P1": null
-        };
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-    
-    djstest.addTest(function jsonLightWithDecimalValue() {
-        var model = getSampleModelWithDecimalProperty();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
-            Id: "5",
-            P1: "10.5"
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "NS.EntityType",
-                "properties": {
-                    "Id": {
-                        "type": "Edm.String"
-                    },
-                    "P1": {
-                        "type": "Edm.Decimal"
-                    },
-                },
-                "id": "http:\/\/someUri\/EntityTypes('5')",
-                "uri": "http:\/\/someUri\/EntityTypes('5')",
-                "edit": "http:\/\/someUri\/EntityTypes('5')",
-                "self": "http:\/\/someUri\/EntityTypes('5')"
-            },
-            "Id": "5",
-            "P1": "10.5"
-        };
-
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-    
-    djstest.addTest(function jsonLightNavigationPropertyAndAssociationUriShouldBeComputedTest() {
-        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#Products/@Element",
-            ID: 5,
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "ODataDemo.Product",
-                "properties": {
-                    "ID": {
-                        "type": "Edm.Int32"
-                    },
-                    "Category": {
-                        "type": "ODataDemo.Category",
-                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
-                    }
-                },
-                "id": "http:\/\/someUri\/Products(5)",
-                "uri": "http:\/\/someUri\/Products(5)",
-                "edit": "http:\/\/someUri\/Products(5)",
-                "self": "http:\/\/someUri\/Products(5)"
-            },
-            "ID": 5,
-            "Category": {
-                "__deferred": {
-                    "uri": "http:\/\/someUri\/Products(5)\/Category"
-                }
-            }
-        };
-
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-    
-    djstest.addTest(function jsonLightNullNavigationPropertyShouldNotBeComputedTest() {
-        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#Products/@Element",
-            ID: 5,
-            Category: null
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "ODataDemo.Product",
-                "properties": {
-                    "ID": {
-                        "type": "Edm.Int32"
-                    },
-                    "Category": {
-                        "type": "ODataDemo.Category",
-                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
-                         "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category"
-                    }
-                },
-                "id": "http:\/\/someUri\/Products(5)",
-                "uri": "http:\/\/someUri\/Products(5)",
-                "edit": "http:\/\/someUri\/Products(5)",
-                "self": "http:\/\/someUri\/Products(5)"
-            },
-            "ID": 5,
-            "Category": null
-        };
-
-
-        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
-        djstest.done();
-    });
-    
-    djstest.addTest(function jsonLightUrisShouldBeComputedForExpandedEntities() {
-        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
-        var input = {
-            "odata.metadata": "http://someUri/$metadata#Products/@Element",
-            ID: 5,
-            Category: {
-                ID: 1
-            }            
-        };
-
-        var expected = {
-            "__metadata": {
-                "type": "ODataDemo.Product",
-                "properties": {
-                    "ID": {
-                        "type": "Edm.Int32"
-                    },
-                    "Category": {
-                        "type": "ODataDemo.Category",
-                        "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category",
-                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category"
-                    }
-                },
-                "id": "http:\/\/someUri\/Products(5)",
-                "uri": "http:\/\/someUri\/Products(5)",
-                "edit": "http:\/\/someUri\/Products(5)",
-                "self": "http:\/\/someUri\/Products(5)"
-            },
-            "ID": 5,
-            "Category": {
-                "__metadata": {
-                    "type": "ODataDemo.Category",
-                    "properties": {
-                        "ID": {
-                            "type": "Edm.Int32"
-                        },
-                        "Products": {
-                            "type": "ODataDemo.Product",
-                            "associationLinkUrl": "http:\/\/someUri\/Categories(1)\/$links\/Products"
-                        }
-                    },
-                    "id": "http:\/\/someUri\/Categories(1)",
-                    "uri": "http:\/\/someUri\/Categories(1)",
-                    "edit

<TRUNCATED>

[39/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc b/datajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
deleted file mode 100644
index ac1cfe7..0000000
--- a/datajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
+++ /dev/null
@@ -1,590 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.V4.FoodStoreDataService" %>
-
-namespace DataJS.Tests.V4
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using Microsoft.OData.Service.Providers;
-    using System.Linq;
-    using System.ServiceModel.Web;
-    using System.Web;
-    using System.IO;
-    using Microsoft.Spatial;
-    
-    /// <summary>
-    /// Provides a service similar to FoodStoreDataService, but uses V4 and WCF Data Services 6.0.0-beta1
-    /// features.
-    /// </summary>
-    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class FoodStoreDataService : DataService<FoodContainer>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.UseVerboseErrors = true;
-            // Set Foods page size to 5 for cache testing
-            config.SetEntitySetPageSize("Foods", 5);
-            // Make the Categories set paged to have a paged feed
-            config.SetEntitySetPageSize("Categories", 1);
-        }
-        
-        [WebInvoke]
-        public string ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-            return "Data Reset";
-        }
-
-        [WebGet]
-        public IQueryable<string> FoodsAvailable()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Name);
-        }
-
-        [WebGet]
-        public IQueryable<Package> PackagingTypes()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
-        }
-
-        [WebGet]
-        public string UserNameAndPassword()
-        {
-            var request = WebOperationContext.Current.IncomingRequest;
-            string authorization = request.Headers["Authorization"];
-            if (String.IsNullOrEmpty(authorization))
-            {
-                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
-                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
-            }
-
-            return authorization;
-        }
-    }
-
-    public class FoodContainer : ReflectionDataContext, IUpdatable, IDataServiceStreamProvider2
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Category> Categories
-        {
-            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
-        }
-        
-        public IQueryable<Food> Foods
-        {
-            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            var builder = SpatialImplementation.CurrentImplementation.CreateBuilder();
-            builder.GeometryPipeline.SetCoordinateSystem(CoordinateSystem.DefaultGeography);
-            builder.GeometryPipeline.BeginGeometry(SpatialType.Collection);
-            builder.GeometryPipeline.BeginFigure(new GeometryPosition(5.0, 5.0));
-            builder.GeometryPipeline.EndFigure();
-            builder.GeometryPipeline.EndGeometry();
-            
-            int i = 0;
-            Category[] categories = new Category[]
-            {
-                new Category { CategoryID = i++, Name = "Baking Supplies" },
-                new Category { CategoryID = i++, Name = "Condiments" },
-                new Category { CategoryID = i++, Name = "Empty Category" }
-            };
-            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
-            
-            i = 0;
-            Food[] foods = new Food[]
-            {            
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "flour",
-                    UnitPrice = .19999,
-                    ServingSize = 1,
-                    MeasurementUnit = "Cup",
-                    ProteinGrams = 3,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 20,
-                    CaloriesPerServing = 140,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
-                    ItemGUID = new Guid("27272727272727272727272727272727"),
-                    Weight = 10f,
-                    AvailableUnits = 1,
-                    
-                    Packaging = new Package(){
-                        Type = null, 
-                        Color = String.Empty, 
-                        NumberPerPackage = int.MaxValue, 
-                        RequiresRefridgeration = false, 
-                        PackageDimensions = new Dimensions()
-                        {
-                            Length = Decimal.MaxValue, 
-                            Height = Int16.MaxValue, 
-                            Width = Int64.MaxValue, 
-                            Volume = double.MaxValue,   
-                        },
-                        ShipDate = new DateTime(2000, 12, 29)
-                    },
-                    
-                    CookedSize = new CookedDimensions()
-                    {
-                        Height = 1,
-                        Length = 2,
-                        Width = 3,
-                        Volume = 1 * 2 * 3
-                    },
-                    
-                    Category = categories[0],
-                    
-                    AlternativeNames = new List<string>() {"ground cereal", "ground grain"},
-                    
-                    Providers = new List<Provider> {
-                        new Provider() { 
-                             Name= "Flour Provider", 
-                             Aliases = new List<string>() {"fp1", "flour provider1"},
-                             Details = new ProviderDetails() {
-                                 Telephone= "555-555-555",
-                                 PreferredCode = 1001
-                             }
-                        },
-                        new Provider() { 
-                             Name= "Ground Grains", 
-                             Aliases = new List<string>()
-                        }
-                    },
-                    
-                    SpatialData = (GeometryCollection)builder.ConstructedGeometry 
-                },
-                
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "sugar",
-                    UnitPrice = .2,
-                    ServingSize = 1,
-                    MeasurementUnit = "tsp",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 4,
-                    CaloriesPerServing = 16,
-                    IsAvailable = false,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
-                    Weight = 0.1f,
-                    AvailableUnits = 0,
-
-                    Packaging = new Package(){
-                        Type = " ",
-                        Color = "BLUE",
-                        NumberPerPackage = int.MinValue,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = Decimal.MinValue,
-                            Height = Int16.MinValue,
-                            Width = Int64.MinValue,
-                            Volume = double.MinValue,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = categories[1],
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "1 Chicken Egg",
-                    UnitPrice = 0.55,
-                    MeasurementUnit = null,
-                    ServingSize = 1,
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 1,
-                    CaloriesPerServing = 70,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("00000000000000000000000000000000"),
-                    Weight = 0,
-                    AvailableUnits = -128,
-                    
-                    Packaging = new Package(){
-                        Type = "18     - Carton",
-                        Color = " brown ",
-                        NumberPerPackage = 0,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = null,
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = null,
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "Brown Sugar",
-                    UnitPrice = 1.6,
-                    ServingSize = 1,
-                    MeasurementUnit = "TSP.",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 5, 
-                    CaloriesPerServing = 16,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 4.5f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Cobb Salad",
-                    UnitPrice = 1.99,
-                    ServingSize = -1,
-                    MeasurementUnit = "cups",
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 3, 
-                    CaloriesPerServing = 5,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 5.674f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                    Instructions = "1.) Open 2.) Eat",
-                    NumberOfIngredients = 4,
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Lasagna",
-                    UnitPrice = 0,
-                    ServingSize = 8,
-                    MeasurementUnit = " servings",
-                    ProteinGrams = 100,
-                    FatGrams = 4,
-                    CarbohydrateGrams = 27, 
-                    CaloriesPerServing = 389,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(1904, 2, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 0,
-                    AvailableUnits = 4,
-                    Packaging = new Package(){
-                        Type = "box",
-                        Color = " 1 ",
-                        NumberPerPackage = 1,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = 3,
-                            Height = 1,
-                            Width = 5,
-                            Volume = 1.5,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    Category = categories[0],
-                    Instructions = "Bake in oven",
-                    NumberOfIngredients = 15,
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Chocolate"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Pizza"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Avocados"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Quinoa"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Oatmeal"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Peanut Butter"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Banana"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Yam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Clam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Spam"
-                }
-            };
-            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
-
-            categories[0].Foods.Add(foods[0]);
-            categories[1].Foods.Add(foods[2]);
-            categories[1].Foods.Add(foods[3]);
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-
-        public Stream GetReadStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            return new MemoryStream();
-        }
-
-        public Uri GetReadStreamUri(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            if (streamProperty.Name == "Icon")
-            {
-                return null;
-            }
-            return new Uri(operationContext.AbsoluteServiceUri, streamProperty.Name);
-        }
-
-        public string GetStreamContentType(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            if (streamProperty.Name == "Icon")
-            {
-                return "image/gif";
-            }
-            return "image/png";
-        }
-
-        public string GetStreamETag(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            return "W/\"123456789\"";
-        }
-
-        public Stream GetWriteStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            return new MemoryStream();
-        }
-
-        public void DeleteStream(object entity, DataServiceOperationContext operationContext)
-        {
-            // do nothing.
-        }
-
-        public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public int StreamBufferSize
-        {
-            get { return 1024; }
-        }
-    }
-
-    /// <summary>
-    /// The Category class is a simple class with V1-compatible feed customizations.
-    /// </summary>
-    public class Category
-    {
-        public Category()
-        {
-            this.Foods = new List<Food>();
-        }
-        
-        public int CategoryID { get; set; }
-        public string Name { get; set; }
-        public List<Food> Foods { get; set; }
-    }
-    
-    /// <summary>
-    /// The Food class has a mixture of V1-compatible and incompatible feed
-    /// customizations (thus it's V2), and custom mappings.
-    /// </summary>
-    public class Food
-    {
-        private List<string> alternativeNames = new List<string>();
-        private List<Provider> providers = new List<Provider>();
-        
-        // Primitive types
-        public int FoodID { get; set; }
-        public string Name { get; set; }
-        public double UnitPrice { get; set; }
-        public Decimal ServingSize { get; set; }
-        public string MeasurementUnit { get; set; }
-        public Byte ProteinGrams { get; set; }
-        public Int16 FatGrams { get; set; }
-        public Int32 CarbohydrateGrams { get; set; }
-        public Int64 CaloriesPerServing { get; set; }
-        public Boolean IsAvailable { get; set; }
-        public DateTime ExpirationDate { get; set; }
-        public Guid ItemGUID { get; set; }
-        public Single Weight { get; set; }
-        public sbyte AvailableUnits { get; set; }
-
-        // Complex types
-        public Package Packaging { get; set; }
-        public CookedDimensions CookedSize { get; set; }
-
-        // Navigation properties
-        public Category Category { get; set; }
-
-        // Collection properties
-        public List<string> AlternativeNames
-        {
-            get { return alternativeNames; }
-            set { alternativeNames = value; }
-        }
-
-        public List<Provider> Providers
-        {
-            get { return providers; }
-            set { providers = value; }
-        }
-
-        public GeometryCollection SpatialData
-        {
-            get;
-            set;
-        }
-        
-    }
-
-    public class Provider
-    {
-        public string Name { get; set; }
-        public List<string> Aliases { get; set; }
-        public ProviderDetails Details { get; set; }
-    }
-
-    public class ProviderDetails
-    {
-        public string Telephone { get; set; }
-        public int PreferredCode { get; set; }
-    }
-    
-    public class Package
-    {
-        public string Type { get; set; }
-        public string Color { get; set; }
-        public int NumberPerPackage { get; set; }
-        public Boolean RequiresRefridgeration { get; set; }
-        public DateTime ShipDate { get; set; }
-        public Dimensions PackageDimensions { get; set; }
-    }
-
-    public class Dimensions
-    {
-        public Decimal Length { get; set; }
-        public Int16 Height { get; set; }
-        public Int64 Width { get; set; }
-        public double Volume { get; set; }
-    }
-
-    public class CookedDimensions
-    {
-        public Decimal Length { get; set; }
-        public Int16 Height { get; set; }
-        public Int64 Width { get; set; }
-        public double Volume { get; set; }
-    }
-
-    public class PreparedFood : Food
-    {
-        public string Instructions { get; set; }
-        public float NumberOfIngredients { get; set; }
-    }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/LargeCollectionService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/LargeCollectionService.svc b/datajs/tests-tmp/endpoints/LargeCollectionService.svc
deleted file mode 100644
index bfbd3ef..0000000
--- a/datajs/tests-tmp/endpoints/LargeCollectionService.svc
+++ /dev/null
@@ -1,113 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.LargeCollectionService" %>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Web;
-    using System.Web;
-
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class LargeCollectionService : DataService<LargeCollection>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.UseVerboseErrors = true;
-        }
-
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-    }
-
-    public class LargeCollection : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Customer> Customers
-        {
-            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
-        }
-
-        public IQueryable<Supplier> Suppliers
-        {
-            get { return this.GetResourceSetEntities<Supplier>("Suppliers").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
-            foreach (int i in Enumerable.Range(1, 2 * 1024 * 1024))
-            {
-                customers.Add(new Customer()
-                {
-                    ID = i,
-                    Name = "Customer " + i
-                });
-            }
-
-            IList<Supplier> suppliers = this.GetResourceSetEntities<Supplier>("Suppliers");
-            foreach (int i in Enumerable.Range(1, 5000))
-            {
-                suppliers.Add(new Supplier()
-                {
-                    ID = i,
-                    Name = "Supplier " + i
-                });
-            }
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Customer
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-
-    public class Supplier
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/endpoints/web.config
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/endpoints/web.config b/datajs/tests-tmp/endpoints/web.config
deleted file mode 100644
index 116a567..0000000
--- a/datajs/tests-tmp/endpoints/web.config
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version='1.0'?>
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-<configuration>
-  <system.web>
-    <compilation debug='true'>
-      <assemblies>
-        <add assembly='System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
-        <add assembly='System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
-        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-      </assemblies>
-    </compilation>
-  </system.web>
-  <system.codedom>
-    <compilers>
-      <compiler language='c#;cs;csharp' extension='.cs' type='Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>
-        <providerOption name='CompilerVersion' value='v4.0' />
-      </compiler>
-    </compilers>
-  </system.codedom>
-</configuration>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/odata-json-tests-todo-analyse.js
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/odata-json-tests-todo-analyse.js b/datajs/tests-tmp/odata-json-tests-todo-analyse.js
deleted file mode 100644
index 702e015..0000000
--- a/datajs/tests-tmp/odata-json-tests-todo-analyse.js
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-tests.js
-
-(function (window, undefined) {
-    djstest.addTest(function jsonParserTest() {
-        var tests = [
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: {} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata",
-                    value: [
-                      {
-                          name: "Products",
-                          kind: "EntitySet",
-                          url: "Products"
-                      },
-                      {
-                          name: "ProductDetails",
-                          kind: "EntitySet",
-                          url: "ProductDetails"
-                      }
-                  ]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    value: [
-                      {
-                          name: "Products",
-                          kind: "EntitySet",
-                          url: "http://foo/OData.svc/Products"
-                      },
-                      {
-                          name: "ProductDetails",
-                          kind: "EntitySet",
-                          url: "http://foo/OData.svc/ProductDetails"
-                      }
-                  ]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { "@odata.context": "http://foo/OData.svc/$metadata#Products(0)/Name", value: "Bread"} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
-                    value: [
-                      {
-                          "@odata.type": "#ODataDemo.Product",
-                          "@odata.id": "http://foo/OData.svc/Products(0)",
-                          "@odata.editLink": "Products(0)",
-                          "Categories@odata.navigationLink": "Products(0)/Categories",
-                          "Categories@odata.associationLink": "Products(0)/Categories/$ref",
-                          "Supplier@odata.navigationLink": "Products(0)/Supplier",
-                          "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
-                          "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
-                          "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          "ReleaseDate@odata.type": "#DateTimeOffset",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          "Rating@odata.type": "#Int16",
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                }
-            },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
-                    value: [
-                      {
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                }
-            },
-             { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                 expected: {
-                     value: [
-                      {
-                          ID: 0,
-                          Name: "Bread",
-                          Description: "Whole grain bread",
-                          ReleaseDate: "1992-01-01T00:00:00Z",
-                          DiscontinuedDate: null,
-                          Rating: 4,
-                          Price: 2.5
-                      }]
-                 }
-             },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
-                      "@odata.type": "#ODataDemo.Product",
-                      "@odata.id": "http://foo/OData.svc/Products(0)",
-                      "@odata.editLink": "Products(0)",
-                      "Categories@odata.navigationLink": "Products(0)/Categories",
-                      "Categories@odata.associationLink": "Products(0)/Categories/$ref",
-                      "Supplier@odata.navigationLink": "Products(0)/Supplier",
-                      "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
-                      "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
-                      "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      "ReleaseDate@odata.type": "#DateTimeOffset",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      "Rating@odata.type": "#Int16",
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      ID: 0,
-                      Name: "Bread",
-                      Description: "Whole grain bread",
-                      ReleaseDate: "1992-01-01T00:00:00Z",
-                      DiscontinuedDate: null,
-                      Rating: 4,
-                      Price: 2.5
-                  }
-              },
-              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                  expected: {
-                      "@odata.context": "http://foo/$metadata#Customer(-10)/PrimaryContactInfo/AlternativeNames",
-                      "@odata.type": "#Collection(String)",
-                      value: [
-                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
-                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
-                      "btsnhqrjqryqzgxducl",
-                      "qbtlssjhunufmzdv",
-                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
-                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
-                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
-                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
-                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
-                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
-                     ]
-                  }
-              }
-        ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var data = JSON.stringify(tests[i].expected);
-            var actual = window.odatajs.oData.json.jsonParser(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
-            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected data");
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function jsonSerializerTest() {
-        var tests = [
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: ""} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: []} },
-            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-                expected: {
-                    ID: 0,
-                    Name: "Bread",
-                    Description: "Whole grain bread",
-                    ReleaseDate: "1992-01-01T00:00:00Z",
-                    DiscontinuedDate: null,
-                    Rating: 4,
-                    Price: 2.5
-                }
-            },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   value: [
-                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
-                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
-                      "btsnhqrjqryqzgxducl",
-                      "qbtlssjhunufmzdv",
-                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
-                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
-                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
-                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
-                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
-                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
-                     ]
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   ID: 0,
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                   "@odata.editLink": "Foods(0)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                   ID: 0,
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   value : [{
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   }]
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.editLink": "Foods(0)",
-                   value : [{
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       ComplexInLayerOne:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                           ID: 1,
-                           ComplexInLayerTwo:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                               ID: 2,
-                               ComplexInLayerThreeList: [
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               },
-                               {
-                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                                   "@odata.id": "Foods(4)",
-                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                                   "@odata.editLink": "Foods(0)",
-                                   "@odata.type": "#DataJS.Tests.V4.Food",
-                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                                   ID: 3,
-                                   Name: "BreadInLayer3",
-                                   Description: "Whole grain bread inLayer3",
-                                   ReleaseDate: "1992-01-01T00:00:00Z",
-                                   DiscontinuedDate: null,
-                                   Rating: 7,
-                                   Price: 5.5
-                               }],
-                               Name: "BreadInLayer2",
-                               Description: "Whole grain bread inLayer2",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 6,
-                               Price: 4.5
-                           },
-                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
-                           Description: "Whole grain bread inLayer1",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 5,
-                           Price: 3.5
-                       },
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   }]
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   "@odata.id": "Foods(4)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   ID: 0,
-                   ComplexInLayerOne:
-                   {
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 1,
-                       ComplexInLayerTwo:
-                       {
-                           "@odata.id": "Foods(4)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           ID: 2,
-                           ComplexInLayerThree:
-                           {
-                               "@odata.id": "Foods(4)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               ID: 3,
-                               Name: "BreadInLayer3",
-                               Description: "Whole grain bread inLayer3",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 7,
-                               Price: 5.5
-                           },
-                           Name: "BreadInLayer2",
-                           Description: "Whole grain bread inLayer2",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 6,
-                           Price: 4.5
-                       },
-                       Name: "BreadInLayer1",
-                       Description: "Whole grain bread inLayer1",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 5,
-                       Price: 3.5
-                   },
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               },
-               data: {
-                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                   "@odata.id": "Foods(4)",
-                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                   "@odata.editLink": "Foods(0)",
-                   "@odata.type": "#DataJS.Tests.V4.Food",
-                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                   ID: 0,
-                   ComplexInLayerOne:
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
-                       ID: 1,
-                       ComplexInLayerTwo:
-                       {
-                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                           "@odata.id": "Foods(4)",
-                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                           "@odata.editLink": "Foods(0)",
-                           "@odata.type": "#DataJS.Tests.V4.Food",
-                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
-                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
-                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
-                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
-                           ID: 2,
-                           ComplexInLayerThree:
-                           {
-                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                               "@odata.id": "Foods(4)",
-                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                               "@odata.editLink": "Foods(0)",
-                               "@odata.type": "#DataJS.Tests.V4.Food",
-                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
-                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
-                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
-                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
-                               ID: 3,
-                               Name: "BreadInLayer3",
-                               Description: "Whole grain bread inLayer3",
-                               ReleaseDate: "1992-01-01T00:00:00Z",
-                               DiscontinuedDate: null,
-                               Rating: 7,
-                               Price: 5.5
-                           },
-                           Name: "BreadInLayer2",
-                           Description: "Whole grain bread inLayer2",
-                           ReleaseDate: "1992-01-01T00:00:00Z",
-                           DiscontinuedDate: null,
-                           Rating: 6,
-                           Price: 4.5
-                       },
-                       Name: "BreadInLayer1",
-                       Description: "Whole grain bread inLayer1",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 5,
-                       Price: 3.5
-                   },
-                   Name: "Bread",
-                   Description: "Whole grain bread",
-                   ReleaseDate: "1992-01-01T00:00:00Z",
-                   DiscontinuedDate: null,
-                   Rating: 4,
-                   Price: 2.5
-               }
-           },
-           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
-               expected: {
-                   value: [{
-                       "@odata.id": "Foods(4)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 0,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.id": "Foods(2)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       ID: 1,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1999-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 6,
-                       Price: 3.5
-                   }]
-               },
-               data: {
-                   value: [{
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(4)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(0)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
-                       ID: 0,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1992-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 4,
-                       Price: 2.5
-                   },
-                   {
-                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
-                       "@odata.id": "Foods(2)",
-                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
-                       "@odata.editLink": "Foods(2)",
-                       "@odata.type": "#DataJS.Tests.V4.Food",
-                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink2",
-                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink2",
-                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType2",
-                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag2",
-                       ID: 1,
-                       Name: "Bread",
-                       Description: "Whole grain bread",
-                       ReleaseDate: "1999-01-01T00:00:00Z",
-                       DiscontinuedDate: null,
-                       Rating: 6,
-                       Price: 3.5
-                   }]
-               }
-           }
-          ];
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            var data = tests[i].data ? tests[i].data : tests[i].expected;
-            var actual = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
-            var expected = JSON.stringify(tests[i].expected);
-            djstest.assertAreEqualDeep(actual, expected, "test " + i + "didn't return the expected data");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function normalizeHeadersReadTest() {
-        // Verifies that headers are normalized for reading.
-        // See issue at http://datajs.codeplex.com/workitem/148
-        MockHttpClient.clear();
-
-        MockHttpClient.clear().addResponse("/foo", {
-            statusCode: 200,
-            body: { "@odata.context": "http://foo", value: [] },
-            headers: { "unknown": "u", "Content-Encoding": "compress, gzip", "Content-Length": "8042",
-                "Content-Type": "application/json", "OData-Version": "4.0", "Etag": "Vetag", "Location": "foo", "OData-EntityId": "entityId",
-                "Preference-Applied": "prefered", "Retry-After": "retry"
-            }
-        });
-
-        odatajs.oData.read("/foo", function (data, response) {
-            // djstest.assertAreEqual(data.results.length, 2, "data.results.length has two entries");
-            djstest.assertAreEqual(response.headers.unknown, "u", "u unmodified");
-            djstest.assertAreEqual(response.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
-            djstest.assertAreEqual(response.headers["Content-Length"], "8042", "Content-Length available");
-            djstest.assertAreEqual(response.headers["Content-Type"], "application/json", "Content-Type available");
-            djstest.assertAreEqual(response.headers["ETag"], "Vetag", "Content-Type available");
-            djstest.assertAreEqual(response.headers["Location"], "foo", "Content-Type available");
-            djstest.assertAreEqual(response.headers["OData-EntityId"], "entityId", "OData-EntityId available");
-            djstest.assertAreEqual(response.headers["Preference-Applied"], "prefered", "Preference-Applied available");
-            djstest.assertAreEqual(response.headers["Retry-After"], "retry", "Retry available");
-            djstest.assertAreEqual(response.headers["OData-Version"], "4.0", "OData-Version available");
-            djstest.done();
-        }, undefined, undefined, MockHttpClient);
-    });
-
-    djstest.addTest(function normalizeHeadersWriteTest() {
-
-        // Verifies that headers are normalized for writing.
-        // See issue at http://datajs.codeplex.com/workitem/148
-
-        MockHttpClient.clear().addRequestVerifier("/foo", function (request) {
-            djstest.assertAreEqual(request.headers.Accept, "application/json", "Accept available");
-            djstest.assertAreEqual(request.headers["Content-Type"], "application/json", "json found");
-            djstest.assertAreEqual(request.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
-            djstest.assertAreEqual(request.headers["Content-Length"], "8042", "Content-Length available");
-            djstest.assertAreEqual(request.headers["OData-Version"], "4.0", "OData-Version available");
-            djstest.assertAreEqual(request.headers["Accept-Charset"], "Accept-Charset", "Accept-Charset available");
-            djstest.assertAreEqual(request.headers["If-Match"], "true", "If-Match available");
-            djstest.assertAreEqual(request.headers["If-None-Match"], "false", "If-None-Match available");
-            djstest.assertAreEqual(request.headers["OData-Isolation"], "isolation", "OData-Isolation available");
-            djstest.assertAreEqual(request.headers["OData-MaxVersion"], "4.0", "OData-MaxVersion available");
-            djstest.assertAreEqual(request.headers["Prefer"], "prefer", "prefer available");
-            djstest.done();
-        });
-
-        var request = {
-            method: "POST",
-            requestUri: "/foo",
-            data: { value: 123 },
-            headers: { "Accept": "application/json", "Content-Encoding": "compress, gzip", "Content-Length": "8042", "content-type": "application/json", "OData-Version": "4.0",
-                "accept-charset": "Accept-Charset", "if-match": "true", "if-none-match": "false", "odata-isolation": "isolation",
-                "odata-maxversion": "4.0", "prefer": "prefer"
-            }
-        };
-        odatajs.oData.request(request, function (data) { }, undefined, undefined, MockHttpClient);
-
-    });
-
-
-})(window);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests-tmp/odata-qunit-tests-launcher.htm
----------------------------------------------------------------------
diff --git a/datajs/tests-tmp/odata-qunit-tests-launcher.htm b/datajs/tests-tmp/odata-qunit-tests-launcher.htm
deleted file mode 100644
index 4f8a390..0000000
--- a/datajs/tests-tmp/odata-qunit-tests-launcher.htm
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
-<html>
-  <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="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.5/rx.all.js"></script>
-
-    
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
-
-    <script type="text/javascript" src="./common/logging.js"></script>
-
-    <script type="text/javascript" src="./common/odataCacheVerifier.js"></script>
-    <script type="text/javascript" src="./common/odataVerifyReader.js"></script>
-    
-
-    <script type="text/javascript" src="./common/mockHttpClient.js"></script>
-
-    
-
-    <script type="text/javascript" src="./common/djstest.js"></script>
-    <script type="text/javascript" src="./common/djstest-browser.js"></script>
-
-
-    <script type="text/javascript" src="./bn-odata-json-tests.js"></script>
-    <script type="text/javascript" src="./a-odata-json-tests.js"></script>
-    <script type="text/javascript" src="./b-cache-tests.js"></script>
-  <body>
-    <div id="qunit"></div>
-  </body>
-  
-</html>
\ No newline at end of file


[20/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/cache.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/cache.js b/odatajs/src/lib/cache.js
new file mode 100644
index 0000000..dd872aa
--- /dev/null
+++ b/odatajs/src/lib/cache.js
@@ -0,0 +1,1447 @@
+/*
+ * 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.
+ */
+
+ /** @module cache */
+
+var odatajs = require('./datajs.js');
+var utils = odatajs.utils;
+var deferred = odatajs.deferred;
+var storeReq = odatajs.store;
+var cacheSource = require('./cache/source');
+
+
+var assigned = utils.assigned;
+var delay = utils.delay;
+var extend = utils.extend;
+var djsassert = utils.djsassert;
+var isArray = utils.isArray;
+var normalizeURI = utils.normalizeURI;
+var parseInt10 = utils.parseInt10;
+var undefinedDefault = utils.undefinedDefault;
+
+var createDeferred = deferred.createDeferred;
+var DjsDeferred = deferred.DjsDeferred;
+
+
+var getJsonValueArraryLength = utils.getJsonValueArraryLength;
+var sliceJsonValueArray = utils.sliceJsonValueArray;
+var concatJsonValueArray = utils.concatJsonValueArray;
+
+
+
+/** Appends a page's data to the operation data.
+ * @param {Object} operation - Operation with  (i)ndex, (c)ount and (d)ata.
+ * @param {Object} page - Page with (i)ndex, (c)ount and (d)ata.
+ */
+function appendPage(operation, page) {
+
+    var intersection = intersectRanges(operation, page);
+    var start = 0;
+    var end = 0;
+    if (intersection) {
+        start = intersection.i - page.i;
+        end = start + (operation.c - getJsonValueArraryLength(operation.d));
+    }
+
+    operation.d = concatJsonValueArray(operation.d, sliceJsonValueArray(page.d, start, end));
+}
+
+/** Returns the {(i)ndex, (c)ount} range for the intersection of x and y.
+ * @param {Object} x - Range with (i)ndex and (c)ount members.
+ * @param {Object} y - Range with (i)ndex and (c)ount members.
+ * @returns {Object} The intersection (i)ndex and (c)ount; undefined if there is no intersection.
+ */
+function intersectRanges(x, y) {
+
+    var xLast = x.i + x.c;
+    var yLast = y.i + y.c;
+    var resultIndex = (x.i > y.i) ? x.i : y.i;
+    var resultLast = (xLast < yLast) ? xLast : yLast;
+    var result;
+    if (resultLast >= resultIndex) {
+        result = { i: resultIndex, c: resultLast - resultIndex };
+    }
+
+    return result;
+}
+
+/** Checks whether val is a defined number with value zero or greater.
+ * @param {Number} val - Value to check.
+ * @param {String} name - Parameter name to use in exception.
+ * @throws Throws an exception if the check fails
+ */
+function checkZeroGreater(val, name) {
+
+    if (val === undefined || typeof val !== "number") {
+        throw { message: "'" + name + "' must be a number." };
+    }
+
+    if (isNaN(val) || val < 0 || !isFinite(val)) {
+        throw { message: "'" + name + "' must be greater than or equal to zero." };
+    }
+}
+
+/** Checks whether val is undefined or a number with value greater than zero.
+ * @param {Number} val - Value to check.
+ * @param {String} name - Parameter name to use in exception.
+ * @throws Throws an exception if the check fails
+ */
+function checkUndefinedGreaterThanZero(val, name) {
+
+    if (val !== undefined) {
+        if (typeof val !== "number") {
+            throw { message: "'" + name + "' must be a number." };
+        }
+
+        if (isNaN(val) || val <= 0 || !isFinite(val)) {
+            throw { message: "'" + name + "' must be greater than zero." };
+        }
+    }
+}
+
+/** Checks whether val is undefined or a number
+ * @param {Number} val - Value to check.
+ * @param {String} name - Parameter name to use in exception.
+ * @throws Throws an exception if the check fails
+ */
+function checkUndefinedOrNumber(val, name) {
+    if (val !== undefined && (typeof val !== "number" || isNaN(val) || !isFinite(val))) {
+        throw { message: "'" + name + "' must be a number." };
+    }
+}
+
+/** Performs a linear search on the specified array and removes the first instance of 'item'.
+ * @param {Array} arr - Array to search.
+ * @param {*} item - Item being sought.
+ * @returns {Boolean} true if the item was removed otherwise false
+ */
+function removeFromArray(arr, item) {
+
+    var i, len;
+    for (i = 0, len = arr.length; i < len; i++) {
+        if (arr[i] === item) {
+            arr.splice(i, 1);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/** Estimates the size of an object in bytes.
+ * Object trees are traversed recursively
+ * @param {Object} object - Object to determine the size of.
+ * @returns {Integer} Estimated size of the object in bytes.
+ */
+function estimateSize(object) {
+    var size = 0;
+    var type = typeof object;
+
+    if (type === "object" && object) {
+        for (var name in object) {
+            size += name.length * 2 + estimateSize(object[name]);
+        }
+    } else if (type === "string") {
+        size = object.length * 2;
+    } else {
+        size = 8;
+    }
+    return size;
+}
+
+/** Snaps low and high indices into page sizes and returns a range.
+ * @param {Number} lowIndex - Low index to snap to a lower value.
+ * @param {Number} highIndex - High index to snap to a higher value.
+ * @param {Number} pageSize - Page size to snap to.
+ * @returns {Object} A range with (i)ndex and (c)ount of elements.
+ */
+function snapToPageBoundaries(lowIndex, highIndex, pageSize) {
+    lowIndex = Math.floor(lowIndex / pageSize) * pageSize;
+    highIndex = Math.ceil((highIndex + 1) / pageSize) * pageSize;
+    return { i: lowIndex, c: highIndex - lowIndex };
+}
+
+// The DataCache is implemented using state machines.  The following constants are used to properly
+// identify and label the states that these machines transition to.
+var CACHE_STATE_DESTROY  = "destroy";
+var CACHE_STATE_IDLE     = "idle";
+var CACHE_STATE_INIT     = "init";
+var CACHE_STATE_READ     = "read";
+var CACHE_STATE_PREFETCH = "prefetch";
+var CACHE_STATE_WRITE    = "write";
+
+// DataCacheOperation state machine states.
+// Transitions on operations also depend on the cache current of the cache.
+var OPERATION_STATE_CANCEL = "cancel";
+var OPERATION_STATE_END    = "end";
+var OPERATION_STATE_ERROR  = "error";
+var OPERATION_STATE_START  = "start";
+var OPERATION_STATE_WAIT   = "wait";
+
+// Destroy state machine states
+var DESTROY_STATE_CLEAR = "clear";
+
+// Read / Prefetch state machine states
+var READ_STATE_DONE   = "done";
+var READ_STATE_LOCAL  = "local";
+var READ_STATE_SAVE   = "save";
+var READ_STATE_SOURCE = "source";
+
+/** Creates a new operation object.
+ * @class DataCacheOperation
+ * @param {Function} stateMachine - State machine that describes the specific behavior of the operation.
+ * @param {DjsDeferred} promise - Promise for requested values.
+ * @param {Boolean} isCancelable - Whether this operation can be canceled or not.
+ * @param {Number} index - Index of first item requested.
+ * @param {Number} count - Count of items requested.
+ * @param {Array} data - Array with the items requested by the operation.
+ * @param {Number} pending - Total number of pending prefetch records.
+ * @returns {DataCacheOperation} A new data cache operation instance.
+ */
+function DataCacheOperation(stateMachine, promise, isCancelable, index, count, data, pending) {
+
+    /// <field name="p" type="DjsDeferred">Promise for requested values.</field>
+    /// <field name="i" type="Number">Index of first item requested.</field>
+    /// <field name="c" type="Number">Count of items requested.</field>
+    /// <field name="d" type="Array">Array with the items requested by the operation.</field>
+    /// <field name="s" type="Array">Current state of the operation.</field>
+    /// <field name="canceled" type="Boolean">Whether the operation has been canceled.</field>
+    /// <field name="pending" type="Number">Total number of pending prefetch records.</field>
+    /// <field name="oncomplete" type="Function">Callback executed when the operation reaches the end state.</field>
+
+    var stateData;
+    var cacheState;
+    var that = this;
+
+    that.p = promise;
+    that.i = index;
+    that.c = count;
+    that.d = data;
+    that.s = OPERATION_STATE_START;
+
+    that.canceled = false;
+    that.pending = pending;
+    that.oncomplete = null;
+
+    /** Transitions this operation to the cancel state and sets the canceled flag to true.
+     * The function is a no-op if the operation is non-cancelable.</summary>
+     * @method DataCacheOperation#cancel
+     */
+    that.cancel = function cancel() {
+
+        if (!isCancelable) {
+            return;
+        }
+
+        var state = that.s;
+        if (state !== OPERATION_STATE_ERROR && state !== OPERATION_STATE_END && state !== OPERATION_STATE_CANCEL) {
+            that.canceled = true;
+            transition(OPERATION_STATE_CANCEL, stateData);
+        }
+    };
+
+    /** Transitions this operation to the end state.
+     * @method DataCacheOperation#complete
+     */
+    that.complete = function () {
+
+        djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.complete() - operation is in the end state", that);
+        transition(OPERATION_STATE_END, stateData);
+    };
+
+    /** Transitions this operation to the error state.
+     * @method DataCacheOperation#error
+     */
+    that.error = function (err) {
+        if (!that.canceled) {
+            djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.error() - operation is in the end state", that);
+            djsassert(that.s !== OPERATION_STATE_ERROR, "DataCacheOperation.error() - operation is in the error state", that);
+            transition(OPERATION_STATE_ERROR, err);
+        }
+    };
+
+    /** Executes the operation's current state in the context of a new cache state.
+     * @method DataCacheOperation#run
+     * @param {Object} state - New cache state.
+     */
+    that.run = function (state) {
+
+        cacheState = state;
+        that.transition(that.s, stateData);
+    };
+
+    /** Transitions this operation to the wait state.
+     * @method DataCacheOperation#wait
+     */
+    that.wait = function (data) {
+
+        djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.wait() - operation is in the end state", that);
+        transition(OPERATION_STATE_WAIT, data);
+    };
+
+    /** State machine that describes all operations common behavior.
+     * @method DataCacheOperation#operationStateMachine
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+     * @param {Object} [data] - Additional data passed to the state.
+     */
+    var operationStateMachine = function (opTargetState, cacheState, data) {
+
+        switch (opTargetState) {
+            case OPERATION_STATE_START:
+                // Initial state of the operation. The operation will remain in this state until the cache has been fully initialized.
+                if (cacheState !== CACHE_STATE_INIT) {
+                    stateMachine(that, opTargetState, cacheState, data);
+                }
+                break;
+
+            case OPERATION_STATE_WAIT:
+                // Wait state indicating that the operation is active but waiting for an asynchronous operation to complete.
+                stateMachine(that, opTargetState, cacheState, data);
+                break;
+
+            case OPERATION_STATE_CANCEL:
+                // Cancel state.
+                stateMachine(that, opTargetState, cacheState, data);
+                that.fireCanceled();
+                transition(OPERATION_STATE_END);
+                break;
+
+            case OPERATION_STATE_ERROR:
+                // Error state. Data is expected to be an object detailing the error condition.
+                stateMachine(that, opTargetState, cacheState, data);
+                that.canceled = true;
+                that.fireRejected(data);
+                transition(OPERATION_STATE_END);
+                break;
+
+            case OPERATION_STATE_END:
+                // Final state of the operation.
+                if (that.oncomplete) {
+                    that.oncomplete(that);
+                }
+                if (!that.canceled) {
+                    that.fireResolved();
+                }
+                stateMachine(that, opTargetState, cacheState, data);
+                break;
+
+            default:
+                // Any other state is passed down to the state machine describing the operation's specific behavior.
+                // DATAJS INTERNAL START 
+                if (true) {
+                    // Check that the state machine actually handled the sate.
+                    var handled = stateMachine(that, opTargetState, cacheState, data);
+                    djsassert(handled, "Bad operation state: " + opTargetState + " cacheState: " + cacheState, this);
+                } else {
+                    // DATAJS INTERNAL END 
+                    stateMachine(that, opTargetState, cacheState, data);
+                    // DATAJS INTERNAL START
+                }
+                // DATAJS INTERNAL END
+                break;
+        }
+    };
+
+
+
+    /** Transitions this operation to a new state.
+     * @method DataCacheOperation#transition
+     * @param {Object} state - State to transition the operation to.
+     * @param {Object} [data] - 
+     */
+    var transition = function (state, data) {
+        that.s = state;
+        stateData = data;
+        operationStateMachine(state, cacheState, data);
+    };
+    
+    that.transition = transition;
+    
+    return that;
+}
+
+/** Fires a resolved notification as necessary.
+ * @method DataCacheOperation#fireResolved
+ */
+DataCacheOperation.prototype.fireResolved = function () {
+
+    // Fire the resolve just once.
+    var p = this.p;
+    if (p) {
+        this.p = null;
+        p.resolve(this.d);
+    }
+};
+
+/** Fires a rejected notification as necessary.
+ * @method DataCacheOperation#fireRejected
+ */
+DataCacheOperation.prototype.fireRejected = function (reason) {
+
+    // Fire the rejection just once.
+    var p = this.p;
+    if (p) {
+        this.p = null;
+        p.reject(reason);
+    }
+};
+
+/** Fires a canceled notification as necessary.
+ * @method DataCacheOperation#fireCanceled
+ */
+DataCacheOperation.prototype.fireCanceled = function () {
+
+    this.fireRejected({ canceled: true, message: "Operation canceled" });
+};
+
+
+/** Creates a data cache for a collection that is efficiently loaded on-demand.
+ * @class DataCache
+ * @param options - Options for the data cache, including name, source, pageSize,
+ * prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
+ * @returns {DataCache} A new data cache instance.
+ */
+function DataCache(options) {
+
+    var state = CACHE_STATE_INIT;
+    var stats = { counts: 0, netReads: 0, prefetches: 0, cacheReads: 0 };
+
+    var clearOperations = [];
+    var readOperations = [];
+    var prefetchOperations = [];
+
+    var actualCacheSize = 0;                                             // Actual cache size in bytes.
+    var allDataLocal = false;                                            // Whether all data is local.
+    var cacheSize = undefinedDefault(options.cacheSize, 1048576);        // Requested cache size in bytes, default 1 MB.
+    var collectionCount = 0;                                             // Number of elements in the server collection.
+    var highestSavedPage = 0;                                            // Highest index of all the saved pages.
+    var highestSavedPageSize = 0;                                        // Item count of the saved page with the highest index.
+    var overflowed = cacheSize === 0;                                    // If the cache has overflowed (actualCacheSize > cacheSize or cacheSize == 0);
+    var pageSize = undefinedDefault(options.pageSize, 50);               // Number of elements to store per page.
+    var prefetchSize = undefinedDefault(options.prefetchSize, pageSize); // Number of elements to prefetch from the source when the cache is idling.
+    var version = "1.0";
+    var cacheFailure;
+
+    var pendingOperations = 0;
+
+    var source = options.source;
+    if (typeof source === "string") {
+        // Create a new cache source.
+        source = new cacheSource.ODataCacheSource(options);
+    }
+    source.options = options;
+
+    // Create a cache local store.
+    var store = storeReq.createStore(options.name, options.mechanism);
+
+    var that = this;
+
+    that.onidle = options.idle;
+    that.stats = stats;
+
+    /** Counts the number of items in the collection.
+     * @method DataCache#count
+     * @returns {Object} A promise with the number of items.
+     */
+    that.count = function () {
+
+        if (cacheFailure) {
+            throw cacheFailure;
+        }
+
+        var deferred = createDeferred();
+        var canceled = false;
+
+        if (allDataLocal) {
+            delay(function () {
+                deferred.resolve(collectionCount);
+            });
+
+            return deferred.promise();
+        }
+
+        // TODO: Consider returning the local data count instead once allDataLocal flag is set to true.
+        var request = source.count(function (count) {
+            request = null;
+            stats.counts++;
+            deferred.resolve(count);
+        }, function (err) {
+            request = null;
+            deferred.reject(extend(err, { canceled: canceled }));
+        });
+
+        return extend(deferred.promise(), {
+
+             /** Aborts the count operation (used within promise callback)
+              * @method DataCache#cancelCount
+              */
+            cancel: function () {
+               
+                if (request) {
+                    canceled = true;
+                    request.abort();
+                    request = null;
+                }
+            }
+        });
+    };
+
+    /** Cancels all running operations and clears all local data associated with this cache.
+     * New read requests made while a clear operation is in progress will not be canceled.
+     * Instead they will be queued for execution once the operation is completed.
+     * @method DataCache#clear
+     * @returns {Object} A promise that has no value and can't be canceled.
+     */
+    that.clear = function () {
+
+        if (cacheFailure) {
+            throw cacheFailure;
+        }
+
+        if (clearOperations.length === 0) {
+            var deferred = createDeferred();
+            var op = new DataCacheOperation(destroyStateMachine, deferred, false);
+            queueAndStart(op, clearOperations);
+            return deferred.promise();
+        }
+        return clearOperations[0].p;
+    };
+
+    /** Filters the cache data based a predicate.
+     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
+     * @method DataCache#filterForward
+     * @param {Number} index - The index of the item to start filtering forward from.
+     * @param {Number} count - Maximum number of items to include in the result.
+     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
+     * @returns {DjsDeferred} A promise for an array of results.
+     */
+    that.filterForward = function (index, count, predicate) {
+        return filter(index, count, predicate, false);
+    };
+
+    /** Filters the cache data based a predicate.
+     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
+     * @method DataCache#filterBack
+     * @param {Number} index - The index of the item to start filtering backward from.
+     * @param {Number} count - Maximum number of items to include in the result.
+     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
+     * @returns {DjsDeferred} A promise for an array of results.
+     */
+    that.filterBack = function (index, count, predicate) {
+        return filter(index, count, predicate, true);
+    };
+
+    /** Reads a range of adjacent records.
+     * New read requests made while a clear operation is in progress will not be canceled.
+     * Instead they will be queued for execution once the operation is completed.
+     * @method DataCache#readRange
+     * @param {Number} index - Zero-based index of record range to read.
+     * @param {Number} count - Number of records in the range.
+     * @returns {DjsDeferred} A promise for an array of records; less records may be returned if the
+     * end of the collection is found.
+     */
+    that.readRange = function (index, count) {
+
+        checkZeroGreater(index, "index");
+        checkZeroGreater(count, "count");
+
+        if (cacheFailure) {
+            throw cacheFailure;
+        }
+
+        var deferred = createDeferred();
+
+        // Merging read operations would be a nice optimization here.
+        var op = new DataCacheOperation(readStateMachine, deferred, true, index, count, {}, 0);
+        queueAndStart(op, readOperations);
+
+        return extend(deferred.promise(), {
+            cancel: function () {
+                /** Aborts the readRange operation  (used within promise callback)
+                 * @method DataCache#cancelReadRange
+                 */
+                op.cancel();
+            }
+        });
+    };
+
+    /** Creates an Observable object that enumerates all the cache contents.
+     * @method DataCache#toObservable
+     * @returns A new Observable object that enumerates all the cache contents.
+     */
+    that.ToObservable = that.toObservable = function () {
+        if ( !utils.inBrowser()) {
+            throw { message: "Only in broser supported" };
+        }
+
+        if (!window.Rx || !window.Rx.Observable) {
+            throw { message: "Rx library not available - include rx.js" };
+        }
+
+        if (cacheFailure) {
+            throw cacheFailure;
+        }
+
+        return new window.Rx.Observable(function (obs) {
+            var disposed = false;
+            var index = 0;
+
+            var errorCallback = function (error) {
+                if (!disposed) {
+                    obs.onError(error);
+                }
+            };
+
+            var successCallback = function (data) {
+                if (!disposed) {
+                    var i, len;
+                    for (i = 0, len = data.value.length; i < len; i++) {
+                        // The wrapper automatically checks for Dispose
+                        // on the observer, so we don't need to check it here.
+                        obs.onNext(data.value[i]);
+                    }
+
+                    if (data.value.length < pageSize) {
+                        obs.onCompleted();
+                    } else {
+                        index += pageSize;
+                        that.readRange(index, pageSize).then(successCallback, errorCallback);
+                    }
+                }
+            };
+
+            that.readRange(index, pageSize).then(successCallback, errorCallback);
+
+            return { Dispose: function () { disposed = true; } };
+        });
+    };
+
+    /** Creates a function that handles a callback by setting the cache into failure mode.
+     * @method DataCache~cacheFailureCallback
+     * @param {String} message - Message text.
+     * @returns {Function} Function to use as error callback.
+     * This function will specifically handle problems with critical store resources
+     * during cache initialization.
+     */
+    var cacheFailureCallback = function (message) {
+        
+
+        return function (error) {
+            cacheFailure = { message: message, error: error };
+
+            // Destroy any pending clear or read operations.
+            // At this point there should be no prefetch operations.
+            // Count operations will go through but are benign because they
+            // won't interact with the store.
+            djsassert(prefetchOperations.length === 0, "prefetchOperations.length === 0");
+            var i, len;
+            for (i = 0, len = readOperations.length; i < len; i++) {
+                readOperations[i].fireRejected(cacheFailure);
+            }
+            for (i = 0, len = clearOperations.length; i < len; i++) {
+                clearOperations[i].fireRejected(cacheFailure);
+            }
+
+            // Null out the operation arrays.
+            readOperations = clearOperations = null;
+        };
+    };
+
+    /** Updates the cache's state and signals all pending operations of the change.
+     * @method DataCache~changeState
+     * @param {Object} newState - New cache state.
+     * This method is a no-op if the cache's current state and the new state are the same.</remarks>
+     */
+    var changeState = function (newState) {
+
+        if (newState !== state) {
+            state = newState;
+            var operations = clearOperations.concat(readOperations, prefetchOperations);
+            var i, len;
+            for (i = 0, len = operations.length; i < len; i++) {
+                operations[i].run(state);
+            }
+        }
+    };
+
+    /** Removes all the data stored in the cache.
+     * @method DataCache~clearStore
+     * @returns {DjsDeferred} A promise with no value.
+     */
+    var clearStore = function () {
+        djsassert(state === CACHE_STATE_DESTROY || state === CACHE_STATE_INIT, "DataCache.clearStore() - cache is not on the destroy or initialize state, current sate = " + state);
+
+        var deferred = new DjsDeferred();
+        store.clear(function () {
+
+            // Reset the cache settings.
+            actualCacheSize = 0;
+            allDataLocal = false;
+            collectionCount = 0;
+            highestSavedPage = 0;
+            highestSavedPageSize = 0;
+            overflowed = cacheSize === 0;
+
+            // version is not reset, in case there is other state in eg V1.1 that is still around.
+
+            // Reset the cache stats.
+            stats = { counts: 0, netReads: 0, prefetches: 0, cacheReads: 0 };
+            that.stats = stats;
+
+            store.close();
+            deferred.resolve();
+        }, function (err) {
+            deferred.reject(err);
+        });
+        return deferred;
+    };
+
+    /** Removes an operation from the caches queues and changes the cache state to idle.
+     * @method DataCache~dequeueOperation
+     * @param {DataCacheOperation} operation - Operation to dequeue.
+     * This method is used as a handler for the operation's oncomplete event.</remarks>
+    */
+    var dequeueOperation = function (operation) {
+
+        var removed = removeFromArray(clearOperations, operation);
+        if (!removed) {
+            removed = removeFromArray(readOperations, operation);
+            if (!removed) {
+                removeFromArray(prefetchOperations, operation);
+            }
+        }
+
+        pendingOperations--;
+        changeState(CACHE_STATE_IDLE);
+    };
+
+    /** Requests data from the cache source.
+     * @method DataCache~fetchPage
+     * @param {Number} start - Zero-based index of items to request.
+     * @returns {DjsDeferred} A promise for a page object with (i)ndex, (c)ount, (d)ata.
+     */
+    var fetchPage = function (start) {
+
+        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.fetchPage() - cache is on the destroy state");
+        djsassert(state !== CACHE_STATE_IDLE, "DataCache.fetchPage() - cache is on the idle state");
+
+        var deferred = new DjsDeferred();
+        var canceled = false;
+
+        var request = source.read(start, pageSize, function (data) {
+            var length = getJsonValueArraryLength(data);
+            var page = { i: start, c: length, d: data };
+            deferred.resolve(page);
+        }, function (err) {
+            deferred.reject(err);
+        });
+
+        return extend(deferred, {
+            cancel: function () {
+                if (request) {
+                    request.abort();
+                    canceled = true;
+                    request = null;
+                }
+            }
+        });
+    };
+
+    /** Filters the cache data based a predicate.
+     * @method DataCache~filter
+     * @param {Number} index - The index of the item to start filtering from.
+     * @param {Number} count - Maximum number of items to include in the result.
+     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
+     * @param {Boolean} backwards - True if the filtering should move backward from the specified index, falsey otherwise.
+     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
+     * @returns {DjsDeferred} A promise for an array of results.
+     */
+    var filter = function (index, count, predicate, backwards) {
+
+        index = parseInt10(index);
+        count = parseInt10(count);
+
+        if (isNaN(index)) {
+            throw { message: "'index' must be a valid number.", index: index };
+        }
+        if (isNaN(count)) {
+            throw { message: "'count' must be a valid number.", count: count };
+        }
+
+        if (cacheFailure) {
+            throw cacheFailure;
+        }
+
+        index = Math.max(index, 0);
+
+        var deferred = createDeferred();
+        var returnData = {};
+        returnData.value = [];
+        var canceled = false;
+        var pendingReadRange = null;
+
+        var readMore = function (readIndex, readCount) {
+            if (!canceled) {
+                if (count > 0 && returnData.value.length >= count) {
+                    deferred.resolve(returnData);
+                } else {
+                    pendingReadRange = that.readRange(readIndex, readCount).then(function (data) {
+                        if (data["@odata.context"] && !returnData["@odata.context"]) {
+                            returnData["@odata.context"] = data["@odata.context"];
+                        }
+                        
+                        for (var i = 0, length = data.value.length; i < length && (count < 0 || returnData.value.length < count); i++) {
+                            var dataIndex = backwards ? length - i - 1 : i;
+                            var item = data.value[dataIndex];
+                            if (predicate(item)) {
+                                var element = {
+                                    index: readIndex + dataIndex,
+                                    item: item
+                                };
+
+                                backwards ? returnData.value.unshift(element) : returnData.value.push(element);
+                            }
+                        }
+
+                        // Have we reached the end of the collection?
+                        if ((!backwards && data.value.length < readCount) || (backwards && readIndex <= 0)) {
+                            deferred.resolve(returnData);
+                        } else {
+                            var nextIndex = backwards ? Math.max(readIndex - pageSize, 0) : readIndex + readCount;
+                            readMore(nextIndex, pageSize);
+                        }
+                    }, function (err) {
+                        deferred.reject(err);
+                    });
+                }
+            }
+        };
+
+        // Initially, we read from the given starting index to the next/previous page boundary
+        var initialPage = snapToPageBoundaries(index, index, pageSize);
+        var initialIndex = backwards ? initialPage.i : index;
+        var initialCount = backwards ? index - initialPage.i + 1 : initialPage.i + initialPage.c - index;
+        readMore(initialIndex, initialCount);
+
+        return extend(deferred.promise(), {
+            /** Aborts the filter operation (used within promise callback)
+            * @method DataCache#cancelFilter
+             */
+            cancel: function () {
+
+                if (pendingReadRange) {
+                    pendingReadRange.cancel();
+                }
+                canceled = true;
+            }
+        });
+    };
+
+    /** Fires an onidle event if any functions are assigned.
+     * @method DataCache~fireOnIdle
+    */
+    var fireOnIdle = function () {
+
+        if (that.onidle && pendingOperations === 0) {
+            that.onidle();
+        }
+    };
+
+    /** Creates and starts a new prefetch operation.
+     * @method DataCache~prefetch
+     * @param {Number} start - Zero-based index of the items to prefetch.
+     * This method is a no-op if any of the following conditions is true:
+     *     1.- prefetchSize is 0
+     *     2.- All data has been read and stored locally in the cache.
+     *     3.- There is already an all data prefetch operation queued.
+     *     4.- The cache has run out of available space (overflowed).
+    */
+    var prefetch = function (start) {
+        
+
+        if (allDataLocal || prefetchSize === 0 || overflowed) {
+            return;
+        }
+
+        djsassert(state === CACHE_STATE_READ, "DataCache.prefetch() - cache is not on the read state, current state: " + state);
+
+        if (prefetchOperations.length === 0 || (prefetchOperations[0] && prefetchOperations[0].c !== -1)) {
+            // Merging prefetch operations would be a nice optimization here.
+            var op = new DataCacheOperation(prefetchStateMachine, null, true, start, prefetchSize, null, prefetchSize);
+            queueAndStart(op, prefetchOperations);
+        }
+    };
+
+    /** Queues an operation and runs it.
+     * @param {DataCacheOperation} op - Operation to queue.
+     * @param {Array} queue - Array that will store the operation.
+     */
+    var queueAndStart = function (op, queue) {
+
+        op.oncomplete = dequeueOperation;
+        queue.push(op);
+        pendingOperations++;
+        op.run(state);
+    };
+
+    /** Requests a page from the cache local store.
+     * @method DataCache~readPage    
+     * @param {Number} key - Zero-based index of the reuqested page.
+     * @returns {DjsDeferred} A promise for a found flag and page object with (i)ndex, (c)ount, (d)ata, and (t)icks.
+     */
+    var readPage = function (key) {
+
+        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.readPage() - cache is on the destroy state");
+
+        var canceled = false;
+        var deferred = extend(new DjsDeferred(), {
+            /** Aborts the readPage operation. (used within promise callback)
+             * @method DataCache#cancelReadPage
+             */
+            cancel: function () {
+                canceled = true;
+            }
+        });
+
+        var error = storeFailureCallback(deferred, "Read page from store failure");
+
+        store.contains(key, function (contained) {
+            if (canceled) {
+                return;
+            }
+            if (contained) {
+                store.read(key, function (_, data) {
+                    if (!canceled) {
+                        deferred.resolve(data !== undefined, data);
+                    }
+                }, error);
+                return;
+            }
+            deferred.resolve(false);
+        }, error);
+        return deferred;
+    };
+
+    /** Saves a page to the cache local store.
+     * @method DataCache~savePage    
+     * @param {Number} key - Zero-based index of the requested page.
+     * @param {Object} page - Object with (i)ndex, (c)ount, (d)ata, and (t)icks.
+     * @returns {DjsDeferred} A promise with no value.
+     */
+    var savePage = function (key, page) {
+
+        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.savePage() - cache is on the destroy state");
+        djsassert(state !== CACHE_STATE_IDLE, "DataCache.savePage() - cache is on the idle state");
+
+        var canceled = false;
+
+        var deferred = extend(new DjsDeferred(), {
+            /** Aborts the savePage operation. (used within promise callback)
+             * @method DataCache#cancelReadPage
+             */
+            cancel: function () {
+                canceled = true;
+            }
+        });
+
+        var error = storeFailureCallback(deferred, "Save page to store failure");
+
+        var resolve = function () {
+            deferred.resolve(true);
+        };
+
+        if (page.c > 0) {
+            var pageBytes = estimateSize(page);
+            overflowed = cacheSize >= 0 && cacheSize < actualCacheSize + pageBytes;
+
+            if (!overflowed) {
+                store.addOrUpdate(key, page, function () {
+                    updateSettings(page, pageBytes);
+                    saveSettings(resolve, error);
+                }, error);
+            } else {
+                resolve();
+            }
+        } else {
+            updateSettings(page, 0);
+            saveSettings(resolve, error);
+        }
+        return deferred;
+    };
+
+    /** Saves the cache's current settings to the local store.
+     * @method DataCache~saveSettings    
+     * @param {Function} success - Success callback.
+     * @param {Function} error - Errror callback.
+     */
+    var saveSettings = function (success, error) {
+
+        var settings = {
+            actualCacheSize: actualCacheSize,
+            allDataLocal: allDataLocal,
+            cacheSize: cacheSize,
+            collectionCount: collectionCount,
+            highestSavedPage: highestSavedPage,
+            highestSavedPageSize: highestSavedPageSize,
+            pageSize: pageSize,
+            sourceId: source.identifier,
+            version: version
+        };
+
+        store.addOrUpdate("__settings", settings, success, error);
+    };
+
+    /** Creates a function that handles a store error.
+     * @method DataCache~storeFailureCallback    
+     * @param {DjsDeferred} deferred - Deferred object to resolve.
+     * @param {String} message - Message text.
+     * @returns {Function} Function to use as error callback.
+    
+     * This function will specifically handle problems when interacting with the store.
+     */
+    var storeFailureCallback = function (deferred/*, message*/) {
+        
+
+        return function (/*error*/) {
+            // var console = windo1w.console;
+            // if (console && console.log) {
+            //    console.log(message);
+            //    console.dir(error);
+            // }
+            deferred.resolve(false);
+        };
+    };
+
+    /** Updates the cache's settings based on a page object.
+     * @method DataCache~updateSettings    
+     * @param {Object} page - Object with (i)ndex, (c)ount, (d)ata.
+     * @param {Number} pageBytes - Size of the page in bytes.
+     */
+    var updateSettings = function (page, pageBytes) {
+
+        var pageCount = page.c;
+        var pageIndex = page.i;
+
+        // Detect the collection size.
+        if (pageCount === 0) {
+            if (highestSavedPage === pageIndex - pageSize) {
+                collectionCount = highestSavedPage + highestSavedPageSize;
+            }
+        } else {
+            highestSavedPage = Math.max(highestSavedPage, pageIndex);
+            if (highestSavedPage === pageIndex) {
+                highestSavedPageSize = pageCount;
+            }
+            actualCacheSize += pageBytes;
+            if (pageCount < pageSize && !collectionCount) {
+                collectionCount = pageIndex + pageCount;
+            }
+        }
+
+        // Detect the end of the collection.
+        if (!allDataLocal && collectionCount === highestSavedPage + highestSavedPageSize) {
+            allDataLocal = true;
+        }
+    };
+
+    /** State machine describing the behavior for cancelling a read or prefetch operation.
+     * @method DataCache~cancelStateMachine    
+     * @param {DataCacheOperation} operation - Operation being run.
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+     * @param {Object} [data] - 
+     * This state machine contains behavior common to read and prefetch operations.
+     */
+    var cancelStateMachine = function (operation, opTargetState, cacheState, data) {
+        
+
+        var canceled = operation.canceled && opTargetState !== OPERATION_STATE_END;
+        if (canceled) {
+            if (opTargetState === OPERATION_STATE_CANCEL) {
+                // Cancel state.
+                // Data is expected to be any pending request made to the cache.
+                if (data && data.cancel) {
+                    data.cancel();
+                }
+            }
+        }
+        return canceled;
+    };
+
+    /** State machine describing the behavior of a clear operation.
+     * @method DataCache~destroyStateMachine    
+     * @param {DataCacheOperation} operation - Operation being run.
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+    
+     * Clear operations have the highest priority and can't be interrupted by other operations; however,
+     * they will preempt any other operation currently executing.
+     */
+    var destroyStateMachine = function (operation, opTargetState, cacheState) {
+        
+
+        var transition = operation.transition;
+
+        // Signal the cache that a clear operation is running.
+        if (cacheState !== CACHE_STATE_DESTROY) {
+            changeState(CACHE_STATE_DESTROY);
+            return true;
+        }
+
+        switch (opTargetState) {
+            case OPERATION_STATE_START:
+                // Initial state of the operation.
+                transition(DESTROY_STATE_CLEAR);
+                break;
+
+            case OPERATION_STATE_END:
+                // State that signals the operation is done.
+                fireOnIdle();
+                break;
+
+            case DESTROY_STATE_CLEAR:
+                // State that clears all the local data of the cache.
+                clearStore().then(function () {
+                    // Terminate the operation once the local store has been cleared.
+                    operation.complete();
+                });
+                // Wait until the clear request completes.
+                operation.wait();
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    };
+
+    /** State machine describing the behavior of a prefetch operation.
+     * @method DataCache~prefetchStateMachine    
+     * @param {DataCacheOperation} operation - Operation being run.
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+     * @param {Object} [data] - 
+    
+     *  Prefetch operations have the lowest priority and will be interrupted by operations of
+     *  other kinds. A preempted prefetch operation will resume its execution only when the state
+     *  of the cache returns to idle.
+     * 
+     *  If a clear operation starts executing then all the prefetch operations are canceled,
+     *  even if they haven't started executing yet.
+     */
+    var prefetchStateMachine = function (operation, opTargetState, cacheState, data) {
+        
+
+        // Handle cancelation
+        if (!cancelStateMachine(operation, opTargetState, cacheState, data)) {
+
+            var transition = operation.transition;
+
+            // Handle preemption
+            if (cacheState !== CACHE_STATE_PREFETCH) {
+                if (cacheState === CACHE_STATE_DESTROY) {
+                    if (opTargetState !== OPERATION_STATE_CANCEL) {
+                        operation.cancel();
+                    }
+                } else if (cacheState === CACHE_STATE_IDLE) {
+                    // Signal the cache that a prefetch operation is running.
+                    changeState(CACHE_STATE_PREFETCH);
+                }
+                return true;
+            }
+
+            switch (opTargetState) {
+                case OPERATION_STATE_START:
+                    // Initial state of the operation.
+                    if (prefetchOperations[0] === operation) {
+                        transition(READ_STATE_LOCAL, operation.i);
+                    }
+                    break;
+
+                case READ_STATE_DONE:
+                    // State that determines if the operation can be resolved or has to
+                    // continue processing.
+                    // Data is expected to be the read page.
+                    var pending = operation.pending;
+
+                    if (pending > 0) {
+                        pending -= Math.min(pending, data.c);
+                    }
+
+                    // Are we done, or has all the data been stored?
+                    if (allDataLocal || pending === 0 || data.c < pageSize || overflowed) {
+                        operation.complete();
+                    } else {
+                        // Continue processing the operation.
+                        operation.pending = pending;
+                        transition(READ_STATE_LOCAL, data.i + pageSize);
+                    }
+                    break;
+
+                default:
+                    return readSaveStateMachine(operation, opTargetState, cacheState, data, true);
+            }
+        }
+        return true;
+    };
+
+    /** State machine describing the behavior of a read operation.
+     * @method DataCache~readStateMachine    
+     * @param {DataCacheOperation} operation - Operation being run.
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+     * @param {Object} [data] - 
+    
+     * Read operations have a higher priority than prefetch operations, but lower than
+     * clear operations. They will preempt any prefetch operation currently running
+     * but will be interrupted by a clear operation.
+     *          
+     * If a clear operation starts executing then all the currently running
+     * read operations are canceled. Read operations that haven't started yet will
+     * wait in the start state until the destory operation finishes.
+     */
+    var readStateMachine = function (operation, opTargetState, cacheState, data) {
+        
+
+        // Handle cancelation
+        if (!cancelStateMachine(operation, opTargetState, cacheState, data)) {
+
+            var transition = operation.transition;
+
+            // Handle preemption
+            if (cacheState !== CACHE_STATE_READ && opTargetState !== OPERATION_STATE_START) {
+                if (cacheState === CACHE_STATE_DESTROY) {
+                    if (opTargetState !== OPERATION_STATE_START) {
+                        operation.cancel();
+                    }
+                } else if (cacheState !== CACHE_STATE_WRITE) {
+                    // Signal the cache that a read operation is running.
+                    djsassert(state == CACHE_STATE_IDLE || state === CACHE_STATE_PREFETCH, "DataCache.readStateMachine() - cache is not on the read or idle state.");
+                    changeState(CACHE_STATE_READ);
+                }
+
+                return true;
+            }
+
+            switch (opTargetState) {
+                case OPERATION_STATE_START:
+                    // Initial state of the operation.
+                    // Wait until the cache is idle or prefetching.
+                    if (cacheState === CACHE_STATE_IDLE || cacheState === CACHE_STATE_PREFETCH) {
+                        // Signal the cache that a read operation is running.
+                        changeState(CACHE_STATE_READ);
+                        if (operation.c >= 0) {
+                            // Snap the requested range to a page boundary.
+                            var range = snapToPageBoundaries(operation.i, operation.c, pageSize);
+                            transition(READ_STATE_LOCAL, range.i);
+                        } else {
+                            transition(READ_STATE_DONE, operation);
+                        }
+                    }
+                    break;
+
+                case READ_STATE_DONE:
+                    // State that determines if the operation can be resolved or has to
+                    // continue processing.
+                    // Data is expected to be the read page.
+                    appendPage(operation, data);
+                    var len = getJsonValueArraryLength(operation.d);
+                    // Are we done?
+                    if (operation.c === len || data.c < pageSize) {
+                        // Update the stats, request for a prefetch operation.
+                        stats.cacheReads++;
+                        prefetch(data.i + data.c);
+                        // Terminate the operation.
+                        operation.complete();
+                    } else {
+                        // Continue processing the operation.
+                        transition(READ_STATE_LOCAL, data.i + pageSize);
+                    }
+                    break;
+
+                default:
+                    return readSaveStateMachine(operation, opTargetState, cacheState, data, false);
+            }
+        }
+
+        return true;
+    };
+
+    /** State machine describing the behavior for reading and saving data into the cache.
+     * @method DataCache~readSaveStateMachine    
+     * @param {DataCacheOperation} operation - Operation being run.
+     * @param {Object} opTargetState - Operation state to transition to.
+     * @param {Object} cacheState - Current cache state.
+     * @param {Object} [data] - 
+     * @param {Boolean} isPrefetch - Flag indicating whether a read (false) or prefetch (true) operation is running.
+     * This state machine contains behavior common to read and prefetch operations.
+    */
+    var readSaveStateMachine = function (operation, opTargetState, cacheState, data, isPrefetch) {
+
+        var error = operation.error;
+        var transition = operation.transition;
+        var wait = operation.wait;
+        var request;
+
+        switch (opTargetState) {
+            case OPERATION_STATE_END:
+                // State that signals the operation is done.
+                fireOnIdle();
+                break;
+
+            case READ_STATE_LOCAL:
+                // State that requests for a page from the local store.
+                // Data is expected to be the index of the page to request.
+                request = readPage(data).then(function (found, page) {
+                    // Signal the cache that a read operation is running.
+                    if (!operation.canceled) {
+                        if (found) {
+                            // The page is in the local store, check if the operation can be resolved.
+                            transition(READ_STATE_DONE, page);
+                        } else {
+                            // The page is not in the local store, request it from the source.
+                            transition(READ_STATE_SOURCE, data);
+                        }
+                    }
+                });
+                break;
+
+            case READ_STATE_SOURCE:
+                // State that requests for a page from the cache source.
+                // Data is expected to be the index of the page to request.
+                request = fetchPage(data).then(function (page) {
+                    // Signal the cache that a read operation is running.
+                    if (!operation.canceled) {
+                        // Update the stats and save the page to the local store.
+                        if (isPrefetch) {
+                            stats.prefetches++;
+                        } else {
+                            stats.netReads++;
+                        }
+                        transition(READ_STATE_SAVE, page);
+                    }
+                }, error);
+                break;
+
+            case READ_STATE_SAVE:
+                // State that saves a  page to the local store.
+                // Data is expected to be the page to save.
+                // Write access to the store is exclusive.
+                if (cacheState !== CACHE_STATE_WRITE) {
+                    changeState(CACHE_STATE_WRITE);
+                    request = savePage(data.i, data).then(function (saved) {
+                        if (!operation.canceled) {
+                            if (!saved && isPrefetch) {
+                                operation.pending = 0;
+                            }
+                            // Check if the operation can be resolved.
+                            transition(READ_STATE_DONE, data);
+                        }
+                        changeState(CACHE_STATE_IDLE);
+                    });
+                }
+                break;
+
+            default:
+                // Unknown state that can't be handled by this state machine.
+                return false;
+        }
+
+        if (request) {
+            // The operation might have been canceled between stack frames do to the async calls.
+            if (operation.canceled) {
+                request.cancel();
+            } else if (operation.s === opTargetState) {
+                // Wait for the request to complete.
+                wait(request);
+            }
+        }
+
+        return true;
+    };
+
+    // Initialize the cache.
+    store.read("__settings", function (_, settings) {
+        if (assigned(settings)) {
+            var settingsVersion = settings.version;
+            if (!settingsVersion || settingsVersion.indexOf("1.") !== 0) {
+                cacheFailureCallback("Unsupported cache store version " + settingsVersion)();
+                return;
+            }
+
+            if (pageSize !== settings.pageSize || source.identifier !== settings.sourceId) {
+                // The shape or the source of the data was changed so invalidate the store.
+                clearStore().then(function () {
+                    // Signal the cache is fully initialized.
+                    changeState(CACHE_STATE_IDLE);
+                }, cacheFailureCallback("Unable to clear store during initialization"));
+            } else {
+                // Restore the saved settings.
+                actualCacheSize = settings.actualCacheSize;
+                allDataLocal = settings.allDataLocal;
+                cacheSize = settings.cacheSize;
+                collectionCount = settings.collectionCount;
+                highestSavedPage = settings.highestSavedPage;
+                highestSavedPageSize = settings.highestSavedPageSize;
+                version = settingsVersion;
+
+                // Signal the cache is fully initialized.
+                changeState(CACHE_STATE_IDLE);
+            }
+        } else {
+            // This is a brand new cache.
+            saveSettings(function () {
+                // Signal the cache is fully initialized.
+                changeState(CACHE_STATE_IDLE);
+            }, cacheFailureCallback("Unable to write settings during initialization."));
+        }
+    }, cacheFailureCallback("Unable to read settings from store."));
+
+    return that;
+}
+
+/** Creates a data cache for a collection that is efficiently loaded on-demand.
+ * @param options 
+ * Options for the data cache, including name, source, pageSize, TODO check doku
+ * prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
+ * @returns {DataCache} A new data cache instance.
+ */
+function createDataCache (options) {
+    checkUndefinedGreaterThanZero(options.pageSize, "pageSize");
+    checkUndefinedOrNumber(options.cacheSize, "cacheSize");
+    checkUndefinedOrNumber(options.prefetchSize, "prefetchSize");
+
+    if (!assigned(options.name)) {
+        throw { message: "Undefined or null name", options: options };
+    }
+
+    if (!assigned(options.source)) {
+        throw { message: "Undefined source", options: options };
+    }
+
+    return new DataCache(options);
+}
+
+
+/** estimateSize (see {@link estimateSize}) */
+exports.estimateSize = estimateSize;
+
+/** createDataCache */  
+exports.createDataCache = createDataCache;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/cache/source.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/cache/source.js b/odatajs/src/lib/cache/source.js
new file mode 100644
index 0000000..edc41b2
--- /dev/null
+++ b/odatajs/src/lib/cache/source.js
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+ /** @module cache/source */
+ 
+var utils = require("./../datajs.js").utils;
+var odataRequest = require("./../odata.js");
+
+var parseInt10 = utils.parseInt10;
+var normalizeURICase = utils.normalizeURICase;
+
+
+
+
+/** Appends the specified escaped query option to the specified URI.
+ * @param {String} uri - URI to append option to.
+ * @param {String} queryOption - Escaped query option to append.
+ */
+function appendQueryOption(uri, queryOption) {
+    var separator = (uri.indexOf("?") >= 0) ? "&" : "?";
+    return uri + separator + queryOption;
+}
+
+/** Appends the specified segment to the given URI.
+ * @param {String} uri - URI to append a segment to.
+ * @param {String} segment - Segment to append.
+ * @returns {String} The original URI with a new segment appended.
+ */
+function appendSegment(uri, segment) {
+    var index = uri.indexOf("?");
+    var queryPortion = "";
+    if (index >= 0) {
+        queryPortion = uri.substr(index);
+        uri = uri.substr(0, index);
+    }
+
+    if (uri[uri.length - 1] !== "/") {
+        uri += "/";
+    }
+    return uri + segment + queryPortion;
+}
+
+/** Builds a request object to GET the specified URI.
+ * @param {String} uri - URI for request.
+ * @param {Object} options - Additional options.
+ */
+function buildODataRequest(uri, options) {
+    return {
+        method: "GET",
+        requestUri: uri,
+        user: options.user,
+        password: options.password,
+        enableJsonpCallback: options.enableJsonpCallback,
+        callbackParameterName: options.callbackParameterName,
+        formatQueryString: options.formatQueryString
+    };
+}
+
+/** Finds the index where the value of a query option starts.
+ * @param {String} uri - URI to search in.
+ * @param {String} name - Name to look for.
+ * @returns {Number} The index where the query option starts.
+ */
+function findQueryOptionStart(uri, name) {
+    var result = -1;
+    var queryIndex = uri.indexOf("?");
+    if (queryIndex !== -1) {
+        var start = uri.indexOf("?" + name + "=", queryIndex);
+        if (start === -1) {
+            start = uri.indexOf("&" + name + "=", queryIndex);
+        }
+        if (start !== -1) {
+            result = start + name.length + 2;
+        }
+    }
+    return result;
+}
+
+/** Gets data from an OData service.
+ * @param {String} uri - URI to the OData service.
+ * @param {Object} options - Object with additional well-known request options.
+ * @param {Function} success - Success callback.
+ * @param {Function} error - Error callback.
+ * @returns {Object} Object with an abort method.
+ */
+function queryForData (uri, options, success, error) {
+    var request = queryForDataInternal(uri, options, {}, success, error);
+    return request;
+}
+
+/** Gets data from an OData service taking into consideration server side paging.
+ * @param {String} uri - URI to the OData service.
+ * @param {Object} options - Object with additional well-known request options.
+ * @param {Array} data - Array that stores the data provided by the OData service.
+ * @param {Function} success - Success callback.
+ * @param {Function} error - Error callback.
+ * @returns {Object} Object with an abort method.
+ */
+function queryForDataInternal(uri, options, data, success, error) {
+
+    var request = buildODataRequest(uri, options);
+    var currentRequest = odataRequest.request(request, function (newData) {
+        var nextLink = newData["@odata.nextLink"];
+        if (nextLink) {
+            var index = uri.indexOf(".svc/", 0);
+            if (index != -1) {
+                nextLink = uri.substring(0, index + 5) + nextLink;
+            }
+        }
+
+        if (data.value && newData.value) {
+            data.value = data.value.concat(newData.value);
+        }
+        else {
+            for (var property in newData) {
+                if (property != "@odata.nextLink") {
+                    data[property] = newData[property];
+                }
+            }
+        }
+
+        if (nextLink) {
+            currentRequest = queryForDataInternal(nextLink, options, data, success, error);
+        }
+        else {
+            success(data);
+        }
+    }, error, undefined, options.httpClient, options.metadata);
+
+    return {
+        abort: function () {
+            currentRequest.abort();
+        }
+    };
+}
+
+/** Creates a data cache source object for requesting data from an OData service.
+ * @class ODataCacheSource
+ * @param options - Options for the cache data source.
+ * @returns {ODataCacheSource} A new data cache source instance.
+ */
+function ODataCacheSource (options) {
+    var that = this;
+    var uri = options.source;
+    
+    that.identifier = normalizeURICase(encodeURI(decodeURI(uri)));
+    that.options = options;
+
+    /** Gets the number of items in the collection.
+     * @method ODataCacheSource#count
+     * @param {Function} success - Success callback with the item count.
+     * @param {Function} error - Error callback.
+     * @returns {Object} Request object with an abort method.
+     */
+    that.count = function (success, error) {
+        var options = that.options;
+        return odataRequest.request(
+            buildODataRequest(appendSegment(uri, "$count"), options),
+            function (data) {
+                var count = parseInt10(data.toString());
+                if (isNaN(count)) {
+                    error({ message: "Count is NaN", count: count });
+                } else {
+                    success(count);
+                }
+            }, error, undefined, options.httpClient, options.metadata
+        );
+    };
+    
+    /** Gets a number of consecutive items from the collection.
+     * @method ODataCacheSource#read
+     * @param {Number} index - Zero-based index of the items to retrieve.
+     * @param {Number} count - Number of items to retrieve.
+     * @param {Function} success - Success callback with the requested items.
+     * @param {Function} error - Error callback.
+     * @returns {Object} Request object with an abort method.
+    */
+    that.read = function (index, count, success, error) {
+
+        var queryOptions = "$skip=" + index + "&$top=" + count;
+        return queryForData(appendQueryOption(uri, queryOptions), that.options, success, error);
+    };
+
+    return that;
+}
+
+
+
+/** ODataCacheSource (see {@link ODataCacheSource}) */
+exports.ODataCacheSource = ODataCacheSource;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/datajs.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/datajs.js b/odatajs/src/lib/datajs.js
new file mode 100644
index 0000000..3c1e67a
--- /dev/null
+++ b/odatajs/src/lib/datajs.js
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/** @module datajs */
+
+//expose all external usable functions via self.apiFunc = function
+exports.version = {
+    major: 1,
+    minor: 1,
+    build: 1
+};
+
+exports.deferred = require('./datajs/deferred.js');
+exports.utils = require('./datajs/utils.js');
+exports.xml = require('./datajs/xml.js');
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/datajs/deferred.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/datajs/deferred.js b/odatajs/src/lib/datajs/deferred.js
new file mode 100644
index 0000000..7d5fd68
--- /dev/null
+++ b/odatajs/src/lib/datajs/deferred.js
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+/** @module datajs/deferred */
+
+
+
+/** Creates a new function to forward a call.
+ * @param {Object} thisValue - Value to use as the 'this' object.
+ * @param {String} name - Name of function to forward to.
+ * @param {Object} returnValue - Return value for the forward call (helps keep identity when chaining calls).
+ * @returns {Function} A new function that will forward a call.
+ */
+function forwardCall(thisValue, name, returnValue) {
+    return function () {
+        thisValue[name].apply(thisValue, arguments);
+        return returnValue;
+    };
+}
+
+/** Initializes a new DjsDeferred object.
+ * <ul>
+ * <li> Compability Note A - Ordering of callbacks through chained 'then' invocations <br>
+ *
+ * The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+ * implies that .then() returns a distinct object.
+ *
+ * For compatibility with http://api.jquery.com/category/deferred-object/
+ * we return this same object. This affects ordering, as
+ * the jQuery version will fire callbacks in registration
+ * order regardless of whether they occur on the result
+ * or the original object.
+ * </li>
+ * <li>Compability Note B - Fulfillment value <br>
+ *
+ * The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+ * implies that the result of a success callback is the
+ * fulfillment value of the object and is received by
+ * other success callbacks that are chained.
+ *
+ * For compatibility with http://api.jquery.com/category/deferred-object/
+ * we disregard this value instead.
+ * </li></ul>
+ * @class DjsDeferred 
+ */
+ function DjsDeferred() {
+    this._arguments = undefined;
+    this._done = undefined;
+    this._fail = undefined;
+    this._resolved = false;
+    this._rejected = false;
+}
+
+
+DjsDeferred.prototype = {
+
+    /** Adds success and error callbacks for this deferred object.
+     * See Compatibility Note A.
+     * @method DjsDeferred#then
+     * @param {function} [fulfilledHandler] - Success callback ( may be null)
+     * @param {function} [errorHandler] - Error callback ( may be null)
+     */
+    then: function (fulfilledHandler, errorHandler) {
+
+        if (fulfilledHandler) {
+            if (!this._done) {
+                this._done = [fulfilledHandler];
+            } else {
+                this._done.push(fulfilledHandler);
+            }
+        }
+
+        if (errorHandler) {
+            if (!this._fail) {
+                this._fail = [errorHandler];
+            } else {
+                this._fail.push(errorHandler);
+            }
+        }
+
+        //// See Compatibility Note A in the DjsDeferred constructor.
+        //// if (!this._next) {
+        ////    this._next = createDeferred();
+        //// }
+        //// return this._next.promise();
+
+        if (this._resolved) {
+            this.resolve.apply(this, this._arguments);
+        } else if (this._rejected) {
+            this.reject.apply(this, this._arguments);
+        }
+
+        return this;
+    },
+
+    /** Invokes success callbacks for this deferred object.
+     * All arguments are forwarded to success callbacks.
+     * @method DjsDeferred#resolve
+     */
+    resolve: function (/* args */) {
+        if (this._done) {
+            var i, len;
+            for (i = 0, len = this._done.length; i < len; i++) {
+                //// See Compability Note B - Fulfillment value.
+                //// var nextValue =
+                this._done[i].apply(null, arguments);
+            }
+
+            //// See Compatibility Note A in the DjsDeferred constructor.
+            //// this._next.resolve(nextValue);
+            //// delete this._next;
+
+            this._done = undefined;
+            this._resolved = false;
+            this._arguments = undefined;
+        } else {
+            this._resolved = true;
+            this._arguments = arguments;
+        }
+    },
+
+    /** Invokes error callbacks for this deferred object.
+     * All arguments are forwarded to error callbacks.
+     * @method DjsDeferred#reject
+     */
+    reject: function (/* args */) {
+        
+        if (this._fail) {
+            var i, len;
+            for (i = 0, len = this._fail.length; i < len; i++) {
+                this._fail[i].apply(null, arguments);
+            }
+
+            this._fail = undefined;
+            this._rejected = false;
+            this._arguments = undefined;
+        } else {
+            this._rejected = true;
+            this._arguments = arguments;
+        }
+    },
+
+    /** Returns a version of this object that has only the read-only methods available.
+     * @method DjsDeferred#promise
+     * @returns An object with only the promise object.
+     */
+
+    promise: function () {
+        var result = {};
+        result.then = forwardCall(this, "then", result);
+        return result;
+    }
+};
+
+/** Creates a deferred object.
+ * @returns {DjsDeferred} A new deferred object. If jQuery is installed, then a jQueryDeferred object is returned, which provides a superset of features.
+*/
+function createDeferred() {
+    if (window.jQuery && window.jQuery.Deferred) {
+        return new window.jQuery.Deferred();
+    } else {
+        return new DjsDeferred();
+    }
+};
+
+
+
+
+/** createDeferred (see {@link module:datajs/deferred~createDeferred}) */
+exports.createDeferred = createDeferred;
+
+/** DjsDeferred (see {@link DjsDeferred}) */
+exports.DjsDeferred = DjsDeferred;
\ No newline at end of file


[33/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-batch-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-batch-tests.js b/datajs/tests/odata-batch-tests.js
deleted file mode 100644
index 71a1547..0000000
--- a/datajs/tests/odata-batch-tests.js
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-batch-tests.js
-
-(function (window, undefined) {
-    // DATAJS INTERNAL START
-    var defaultAcceptString = "application/json;q=0.9, */*;q=0.1";
-
-    var testPayload = {
-        CategoryID : 42,
-        Name: "New Category",
-        ID : "odata",
-        version: "4.0"
-    };
-    
-    var jsonPayload = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, testPayload, { "OData-Version": "4.0" });
-
-    djstest.addTest(function writeRequestTest() {
-        var request = {
-            headers: { "Content-Type": "plain/text; charset=utf-8", Accept: "*/*", "OData-Version": "2.0" },
-            requestUri: "http://temp.org",
-            method: "GET",
-            body: "test request"
-        };
-        var expected = "GET http://temp.org HTTP/1.1\r\n" +
-                       "Content-Type: plain/text; charset=utf-8\r\n" +
-                       "Accept: */*\r\n" +
-                       "OData-Version: 2.0\r\n" +
-                       "\r\n" +
-                       "test request";
-
-        var actual = window.odatajs.oData.batch.writeRequest(request);
-        djstest.assertAreEqual(actual, expected, "WriteRequest serializes a request properly");
-        djstest.done();
-    });
-
-    djstest.addTest(function serializeSimpleBatchTest() {
-
-        var request = {
-            requestUri: "http://temp.org",
-            method: "POST",
-            data: { __batchRequests: [
-                { requestUri: "http://feed(1)", headers: {} },
-                { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" }
-            ]
-            }
-        };
-
-        var template = "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "GET http://feed(1) HTTP/1.1\r\n" +
-                       "Accept: " + defaultAcceptString + "\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "GET http://feed(2) HTTP/1.1\r\n" +
-                       "Accept: application/json;odata.metadata=minimal\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       "\r\n--<batchBoundary>--\r\n";
-
-        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
-            var cType = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]);
-            var boundary = cType.properties["boundary"];
-            var expected = template.replace(/<batchBoundary>/g, boundary);
-
-            djstest.assert(boundary, "Request content type has its boundary set");
-            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
-            djstest.done();
-        });
-
-        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-    djstest.addTest(function serializeComplexBatchTest() {
-
-        var request = {
-            requestUri: "http://temp.org",
-            method: "POST",
-            data: { __batchRequests: [
-                { requestUri: "http://feed(1)", headers: {} },
-                { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" },
-                { __changeRequests: [
-                        { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
-                        ]
-                },
-                { requestUri: "http://feed(1)", headers: {} }
-            ]
-            }
-        };
-
-        // 
-        var template = "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "GET http://feed(1) HTTP/1.1\r\n" +
-                       "Accept: " + defaultAcceptString + "\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "GET http://feed(2) HTTP/1.1\r\n" +
-                       "Accept: application/json;odata.metadata=minimal\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
-                       "\r\n--<changesetBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "POST http://feed(1) HTTP/1.1\r\n" +
-                       "Accept: " + defaultAcceptString + "\r\n" +
-                       "OData-Version: 4.0\r\n" +
-                       "Content-Type: application/json\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       jsonPayload +
-                       "\r\n--<changesetBoundary>--\r\n" +
-                       "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "GET http://feed(1) HTTP/1.1\r\n" +
-                       "Accept: " + defaultAcceptString + "\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       "\r\n--<batchBoundary>--\r\n";
-
-        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
-            // Get the boundaries from the request.
-            var start = request.body.indexOf("multipart/mixed");
-            var end = request.body.indexOf("\r\n", start);
-
-            var csetBoundary = window.odatajs.oData.handler.contentType(request.body.substring(start, end)).properties["boundary"];
-            var batchBoundary = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]).properties["boundary"];
-
-            var expected = template.replace(/<batchBoundary>/g, batchBoundary);
-            expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
-
-            djstest.assert(batchBoundary, "Request content type has its boundary set");
-            djstest.assert(csetBoundary, "Changeset content type has its boundary set");
-            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
-            djstest.done();
-        });
-
-        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-    djstest.addTest(function serializeChangeSetTest() {
-        var request = {
-            requestUri: "http://temp.org",
-            method: "POST",
-            data: {
-                __batchRequests: [
-                    { __changeRequests: [
-                        { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
-                        ]
-                    }
-            ]
-            }
-        };
-
-        var template = "\r\n--<batchBoundary>\r\n" +
-                       "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
-                       "\r\n--<changesetBoundary>\r\n" +
-                       "Content-Type: application/http\r\n" +
-                       "Content-Transfer-Encoding: binary\r\n" +
-                       "\r\n" +
-                       "POST http://feed(1) HTTP/1.1\r\n" +
-                       "Accept: " + defaultAcceptString + "\r\n" +
-                       "OData-Version: 4.0\r\n" +
-                       "Content-Type: application/json\r\n" +
-                       "OData-MaxVersion: 4.0\r\n" +
-                       "\r\n" +
-                       jsonPayload +
-                       "\r\n--<changesetBoundary>--\r\n" +
-                       "\r\n--<batchBoundary>--\r\n";
-
-        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
-            // Get the boundaries from the request.
-            var start = request.body.indexOf("multipart/mixed");
-            var end = request.body.indexOf("\r\n", start);
-
-            var csetBoundary = window.odatajs.oData.handler.contentType(request.body.substring(start, end)).properties["boundary"];
-            var batchBoundary = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]).properties["boundary"];
-
-            var expected = template.replace(/<batchBoundary>/g, batchBoundary);
-            expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
-
-            djstest.assert(batchBoundary, "Request content type has its boundary set");
-            djstest.assert(csetBoundary, "Changeset content type has its boundary set");
-            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
-            djstest.done();
-        });
-
-        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-    djstest.addTest(function serializeNestedChangeSetsTest() {
-        var request = {
-            requestUri: "http://temp.org",
-            method: "POST",
-            data: testPayload
-        };
-
-        djstest.expectException(function () {
-            odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler);
-        });
-
-        djstest.done();
-    });
-
-    djstest.addTest(function serializeNonBatchObjectTest() {
-        var request = {
-            requestUri: "http://temp.org",
-            method: "POST",
-            data: {
-                __batchRequests: [
-                    { __changeRequests: [
-                        { __changeRequests: [
-                            { requestUri: "http://feed(2)", headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, method: "PUT", data: testPayload }
-                        ]
-                        }
-                    ]
-                    }
-            ]
-            }
-        };
-
-        djstest.expectException(function () {
-            odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler);
-        });
-
-        djstest.done();
-    });
-
-    djstest.addTest(function readSimpleBatchTest() {
-        var response = {
-            statusCode: 202,
-            statusText: "Accepted",
-            headers: {
-                "Content-Type": "multipart/mixed; boundary=batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9"
-            },
-            body: "--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 201 Created\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
-\r\n\
-{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
---batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 201 Created\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
-\r\n\
-{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
---batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9--\r\n\
-"
-        };
-
-        MockHttpClient.clear().addResponse("http://testuri.org", response);
-        odatajs.oData.read("http://testuri.org", function (data, response) {
-            djstest.assert(data.__batchResponses, "data.__batchResponses is defined");
-            djstest.assertAreEqual(data.__batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the response was read");
-            djstest.assertAreEqual(data.__batchResponses[1].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 2 of the response was read");
-            djstest.assertAreEqual(data.__batchResponses[0].data["CategoryID"], 42, "part 1 data of the response was read");
-            djstest.assertAreEqual(data.__batchResponses[1].data["CategoryID"], 43, "part 2 data of the response was read");
-            djstest.done();
-        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-    djstest.addTest(function readBatchWithChangesetTest() {
-        var response = {
-            statusCode: 202,
-            statusText: "Accepted",
-            headers: {
-                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
-            },
-            body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
-Content-Type: multipart/mixed; boundary=changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
-\r\n\
---changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 201 OK\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
-\r\n\
-{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
---changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 204 No Content\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-OData-Version: 4.0;\r\n\
-\r\n\
-\r\n\
---changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2--\r\n\
---batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 201 Created\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)\r\n\
-\r\n\
-{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":41,\"Name\":\"New Category\"}\r\n\
---batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
-Content-Type: multipart/mixed; boundary=changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
-\r\n\
---changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 201 OK\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
-\r\n\
-{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
---changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 204 No Content\r\n\
-X-Content-Type-Options: nosniff\r\n\
-Cache-Control: no-cache\r\n\
-OData-Version: 4.0;\r\n\
-\r\n\
-\r\n\
---changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07--\r\n\
---batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
-"
-        };
-
-        MockHttpClient.clear().addResponse("http://testuri.org", response);
-        odatajs.oData.read("http://testuri.org", function (data, response) {
-
-            var batchResponses = data.__batchResponses;
-            djstest.assert(batchResponses, "data contains the batch responses");
-
-            var changesetResponses = batchResponses[0].__changeResponses;
-            djstest.assert(changesetResponses, "batch response 1 contains the change set responses");
-            var changesetResponses3 = batchResponses[2].__changeResponses;
-            djstest.assert(changesetResponses3, "batch response 3 contains the change set responses");
-            
-            djstest.assertAreEqual(batchResponses[0].data, undefined, "No data defined for batch response 1");
-            djstest.assertAreEqual(changesetResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the changeset response of the response 1 was read");
-            djstest.assertAreEqual(changesetResponses[0].data["CategoryID"], 42, "part 1 data of the changeset response of the response 1 was read");
-            djstest.assertAreEqual(changesetResponses[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 1");
-            
-            djstest.assertAreEqual(batchResponses[1].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)", "response 2 was read");
-            djstest.assertAreEqual(batchResponses[1].data["CategoryID"], 41, "response 2 data was read");
-            
-            djstest.assertAreEqual(batchResponses[2].data, undefined, "No data defined for");
-            djstest.assertAreEqual(changesetResponses3[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 1 of the changeset response of the response 3 was read");
-            djstest.assertAreEqual(changesetResponses3[0].data["CategoryID"], 43, "part 1 data of the changeset response of the response 3 was read");
-            djstest.assertAreEqual(changesetResponses3[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 3");
-            djstest.done();
-        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-    djstest.addTest(function readBatchWithErrorPartTest() {
-        var response = {
-            statusCode: 202,
-            statusText: "Accepted",
-            headers: {
-                "Content-Type": "multipart/mixed; boundary=batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d"
-            },
-            body: "--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 200 OK\r\n\
-Cache-Control: no-cache\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;charset=utf-8\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
-\r\n\
-{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
---batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 400 Bad Request\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json\r\n\
-{\"error\":{\"code\":\"\",\"message\":\"Error processing request stream.'.\"}}\r\n\
---batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d--\r\n\
-"
-        };
-
-        MockHttpClient.clear().addResponse("http://testuri.org", response);
-        odatajs.oData.read("http://testuri.org", function (data, response) {
-            var batchResponses = data.__batchResponses;
-            djstest.assert(batchResponses, "data.__batchResponses is defined");
-            djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
-            djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
-            djstest.assert(batchResponses[1].response, "part 2 of the response was read");
-            djstest.done();
-        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-    });
-
-
-    djstest.addTest(function readMalformedMultipartResponseThrowsException() {
-        var response = {
-            statusCode: 202,
-            statusText: "Accepted",
-            headers: {
-                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
-            },
-            body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 200 OK\r\n\
-Cache-Control: no-cache\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;charset=utf-8\r\n\
-Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
-\r\n\
-{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
---batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
-Content-Type: multipart/mixed; boundary=changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
-\r\n\
---changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
-Content-Type: application/http\r\n\
-Content-Transfer-Encoding: binary\r\n\
-\r\n\
-HTTP/1.1 404 Not Found\r\n\
-X-Content-Type-Options: nosniff\r\n\
-OData-Version: 4.0;\r\n\
-Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
-\r\n\
-{\"error\":{\"code\":\"\",\"message\":\GET operation cannot be specified in a change set. Only PUT, POST and DELETE operations can be specified in a change set..'.\"}}\r\n\
---changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243--\r\n\
---batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
-"
-        };
-
-        MockHttpClient.clear().addResponse("http://testuri.org", response);
-        odatajs.oData.read("http://testuri.org", function (data, response) {
-            var batchResponses = data.__batchResponses;
-            djstest.assert(batchResponses, "data.__batchResponses is defined");
-            djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
-            djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
-
-            var error = batchResponses[1].__changeResponses[0];
-            djstest.assert(error.response.body.indexOf("GET operation cannot be specified in a change set") > -1, "Response contains expected message");
-            djstest.done();
-        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
-        djstest.done();
-    });
-
-    djstest.addTest(function batchRequestContextIsPushedToThePartsHandlersTest() {
-        var testHandler = {
-            read: function (response, context) {
-                djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
-            },
-            write: function (request, context) {
-                djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
-            }
-        };
-
-        var batch = {
-            headers: {},
-            __batchRequests: [
-                { requestUri: "http://someUri" },
-                { __changeRequests: [
-                     { requestUri: "http://someUri", method: "POST", data: { p1: 500} }
-                  ]
-                }
-            ]
-        };
-
-        var request = { requestUri: "http://someuri", headers: {}, data: batch };
-        var response = {
-            statusCode: 202,
-            statusText: "Accepted",
-            headers: {
-                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
-            },
-            body: '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n' +
-                  'Content-Type: application/http\r\n' +
-                  'Content-Transfer-Encoding: binary\r\n' +
-                  '\r\n' +
-                  'HTTP/1.1 200 OK\r\n' +
-                  'Cache-Control: no-cache\r\n' +
-                  'OData-Version: 1.0;\r\n' +
-                  'Content-Type: application/json\r\n' +
-                  '\r\n' +
-                  '{ "p1": 500 }\r\n' +
-                  '\r\n' +
-                  '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n'
-        };
-
-        var oldPartHandler = window.odatajs.oData.batch.batchHandler.partHandler;
-
-        window.odatajs.oData.batch.batchHandler.partHandler = testHandler;
-
-        window.odatajs.oData.batch.batchHandler.write(request, { recognizeDates: true });
-        window.odatajs.oData.batch.batchHandler.read(response, { recognizeDates: true });
-
-        window.odatajs.oData.batch.batchHandler.partHandler = oldPartHandler;
-
-        djstest.done();
-    });
-
-
-    // DATAJS INTERNAL END
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-filter-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-filter-functional-tests.html b/datajs/tests/odata-cache-filter-functional-tests.html
deleted file mode 100644
index 94cfe2e..0000000
--- a/datajs/tests/odata-cache-filter-functional-tests.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>datajs.cache  filter functional tests</title>
-    <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"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/CacheOracle.js"></script>
-    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
-    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
-    <script type="text/javascript" src="odata-cache-filter-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache filter functional 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/d5ec5557/datajs/tests/odata-cache-filter-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-filter-functional-tests.js b/datajs/tests/odata-cache-filter-functional-tests.js
deleted file mode 100644
index 0fd08f3..0000000
--- a/datajs/tests/odata-cache-filter-functional-tests.js
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var feeds = [
-        { feed: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
-    ];
-
-    var itemsInCollection = 16;
-
-    var pageSize = 3;
-    var readRangeStart = pageSize + 1;
-    var readRangeTake = pageSize;
-
-    // Indices for filterForward after an initial readRange has partially filled the cache
-    var filterForwardAfterReadIndices = [
-        readRangeStart - 1, // before items in the cache
-        readRangeStart, // beginning of items in the cache
-        readRangeStart + readRangeTake, // last item prefetched in the cache
-        readRangeStart + readRangeTake + 1 // past range already in cache
-    ];
-
-    // Indices for filterBack after an initial readRange has partially filled the cache
-    var filterBackAfterReadIndices = [
-        readRangeStart - 1, // before items in the cache
-        readRangeStart, // beginning of items in the cache
-        readRangeStart + readRangeTake, // last item prefetched in the cache
-        readRangeStart + readRangeTake + 1 // past range already in cache
-    ];
-
-    // Counts for filterForward after a readRange has partially filled the cache
-    var filterForwardAfterReadCounts = [
-        -5, // Get all items
-        3, // Subset of all items found in the cache
-        itemsInCollection
-    ];
-
-    // Counts for filterBack after a readRange has partially filled the cache
-    var filterBackAfterReadCounts = [
-        -5, // Get all items
-        3, // Subset of all items found in the cache
-        itemsInCollection
-    ];
-
-    // Indices for single filterForward
-    var singleFilterForwardIndices = [
-        -5,
-        itemsInCollection - 1,
-        itemsInCollection, // beyond the end of the collection
-        itemsInCollection + pageSize // more than one page beyond the collection
-    ];
-
-    // Indices for single filterBack
-    var singleFilterBackIndices = [
-        -1,
-        0,
-        itemsInCollection - 1
-    ];
-
-    // Count for single filterForward
-    var singleFilterForwardCounts = [
-        5,
-        itemsInCollection + 1 // more than number of items in collection
-    ];
-
-    // Count for single filterBack
-    var singleFilterBackCounts = [
-        5,
-        itemsInCollection + 1 // more than number of items in collection
-    ];
-
-    // Index/count variations for multiple filterForwards
-    var multipleFilterForwards = [
-        { index: 0, count: -1 },  // everything
-        {index: 2, count: 5 },   // range in first half
-        {index: 4, count: 7 },   // range in the middle to overlap first and second half
-        {index: 9, count: 4}    // range in second half
-    ];
-
-    // Index/count variations for multiple filterBacks
-    var multipleFilterBacks = [
-        { index: itemsInCollection - 1, count: -1 },  // everything
-        {index: itemsInCollection - 2, count: 5 },   // range in second half
-        {index: itemsInCollection - 4, count: 7 },   // range in the middle to overlap first and second half
-        {index: itemsInCollection - 9, count: 4}    // range in first half
-    ];
-
-
-    var invalidIndices = [NaN, undefined, Infinity, "not a valid value"];
-    var invalidCounts = [NaN, undefined, Infinity, "not a valid value"];
-
-    // Predicate which returns all items in the collection
-    var getAllItemsPredicate = function (item) {
-        return true;
-    };
-
-    // Predicate which returns none of the items in the collection
-    var getNoItemsPredicate = function (item) {
-        return false;
-    };
-
-    var getEveryThirdPredicate = function (item) {
-        return ((item.FoodID % 3) === 0);
-    };
-
-    var filterPredicates = [
-        getAllItemsPredicate,
-        getNoItemsPredicate,
-        getEveryThirdPredicate
-    ];
-
-    var expectException = function (cache) {
-        djstest.assert(false, "We should not get here because the an exception is expected.");
-        djstest.destroyCacheAndDone(cache);
-    };
-
-    var makeUnexpectedErrorHandler = function (cache) {
-        return function (err) {
-            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-            if (cache) {
-                djstest.destroyCacheAndDone(cache);
-            } else {
-                djstest.done();
-            }
-        };
-    };
-
-    var validateFilterResultsAndRequests = function (feed, cache, index, count, predicate, finished, backwards, session, cacheOracle) {
-        /** Runs filter and validates the results and network requests
-         * @param {Object} feed - The feed being read from
-         * @param {Object} cache - The cache to perform the filter on
-         * @param {Integer} index - The index value
-         * @param {Integer} count - The count value
-         * @param {Object} predicate - Filter string to append to the feed to validate the predicate
-         * @param {Function} finished - Callback function called after data is verified
-         * @param {Object} session - Session object to validate the network requests
-         * @param {Object} cacheOracle - cacheOracle object to validate the network requests
-         */
-
-        if (count < 0) {
-            count = itemsInCollection;
-        }
-
-        if (index < 0) {
-            index = 0;
-        }
-
-        window.ODataReadOracle.readJsonAcrossServerPages(feed, function (expectData) {
-            if (backwards) {
-                cache.filterBack(index, count, predicate).then(function (actualResults) {
-                    var expectedResults = CacheOracle.getExpectedFilterResults(expectData, index, count, predicate, backwards);
-                    djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterBack requests");
-
-                    if (session && cacheOracle) {
-                        // If the count is not satisfied in the expected results, read to the beginning of the collection
-                        // otherwise read to the first expected index
-                        var firstIndex = 0; 
-                        if (expectedResults.value.length != 0) {
-                            firstIndex = (expectedResults.value.length < count) ? 0 : expectedResults.value[0].index;
-                        }
-                        // The effective count is the number of items between the first and last index
-                        var expectedCount = index - firstIndex + 1;
-                        cacheOracle.verifyRequests(session.requests, session.responses, firstIndex, expectedCount, "filterBack requests", backwards);
-                    }
-                    finished();
-                });
-            }
-            else {
-                cache.filterForward(index, count, predicate).then(function (actualResults) {
-                    var expectedResults = CacheOracle.getExpectedFilterResults(expectData, index, count, predicate, backwards)
-                    djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterForward requests");
-
-                    if (session && cacheOracle) {
-                        if (expectedResults.value.length > 0) {
-                            // If the count is not satisfied in the expected results, read to the end of the collection
-                            // otherwise read to the last index
-                            var lastIndex = (expectedResults.value.length < count) ? itemsInCollection : expectedResults.value[expectedResults.value.length - 1].index + 1;
-                            // One request is made if the index is outside the range of the collection if the end of the collection has not yet been found
-                            var expectedCount = (index < itemsInCollection) ? (lastIndex - index) : 1;
-                        }
-                        else {
-                            var expectedCount = itemsInCollection;
-                        }
-
-                        cacheOracle.verifyRequests(session.requests, session.responses, index, expectedCount, "filterForward requests", backwards);
-                    }
-                    finished();
-                });
-            }
-        });
-    };
-
-    var createMultipleFilterTestName = function (scenarioName, params) {
-        return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
-            params.firstIndex + ", count " + params.firstCount + "] and [index " + params.secondIndex + ", count " + params.secondCount +
-            "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
-    };
-
-    var createSingleFilterTestName = function (scenarioName, params) {
-        return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
-            params.index + ", count " + params.count + "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
-    };
-
-    var singleFilterTest = function (params) {
-        djstest.assertsExpected(2);
-        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
-
-        var cache = odatajs.cache.createDataCache(options);
-        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
-        var session = this.observableHttpClient.newSession();
-        validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
-    };
-
-    var filterAfterReadRangeTest = function (params) {
-        djstest.assertsExpected(3);
-        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
-
-        var cache = odatajs.cache.createDataCache(options);
-        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
-        var session = this.observableHttpClient.newSession();
-
-        cache.readRange(params.skip, params.take).then(function (data) {
-            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
-            session.clear();
-            validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache); }, params.backwards, session, cacheOracle);
-        });
-    };
-
-    var parallelFilterTest = function (params) {
-        djstest.assertsExpected(2);
-        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
-
-        var cache = odatajs.cache.createDataCache(options);
-
-        var firstfilter = function (finished) {
-            validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate, finished, params.backwards);
-        };
-
-        var secondfilter = function (finished) {
-            validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, finished, params.backwards);
-        };
-
-        djstest.asyncDo([firstfilter, secondfilter], function () {
-            djstest.destroyCacheAndDone(cache);
-        });
-    };
-
-    var serialFilterTest = function (params) {
-        djstest.assertsExpected(4);
-        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
-
-        var cache = odatajs.cache.createDataCache(options);
-        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
-        var session = this.observableHttpClient.newSession();
-
-        var filterMethod = function (index, count, predicate, backwards) {
-            if (backwards) {
-                return cache.filterBack(index, count, predicate);
-            }
-            else {
-                return cache.filterForward(index, count, predicate)
-            }
-        }
-
-        filterMethod(params.firstIndex, params.firstCount, params.predicate, params.backwards).then(
-            function (results) {
-                validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate,
-                function () {
-                    session.clear();
-                    validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
-                }, params.backwards, session, cacheOracle);
-            });
-    };
-
-    module("Functional", {
-        setup: function () {
-            this.observableHttpClient = new ObservableHttpClient();
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
-        },
-
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
-        }
-    });
-
-    $.each(filterPredicates, function (_, filterPredicate) {
-        $.each(feeds, function (_, feedObject) {
-            $.each(filterForwardAfterReadCounts, function (_, filterCount) {
-                $.each(filterForwardAfterReadIndices, function (_, filterIndex) {
-                    var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
-                        skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: false
-                    };
-                    djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("after readRange, ", parameters), parameters);
-                });
-            });
-
-            $.each(filterBackAfterReadCounts, function (_, filterCount) {
-                $.each(filterBackAfterReadIndices, function (_, filterIndex) {
-                    var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
-                        skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: true
-                    };
-                    djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("After readRange, ", parameters), parameters);
-                });
-            });
-        });
-
-        $.each(singleFilterForwardIndices, function (_, filterIndex) {
-            $.each(singleFilterForwardCounts, function (_, filterCount) {
-                var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: false };
-                djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
-            });
-        });
-
-        $.each(singleFilterBackIndices, function (_, filterIndex) {
-            $.each(singleFilterBackCounts, function (_, filterCount) {
-                var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: true };
-                djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
-            });
-        });
-
-        $.each(multipleFilterForwards, function (_, firstFilter) {
-            $.each(multipleFilterForwards, function (_, secondFilter) {
-                var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
-                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: false
-                };
-                djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
-            });
-        });
-
-        $.each(multipleFilterBacks, function (_, firstFilter) {
-            $.each(multipleFilterBacks, function (_, secondFilter) {
-                var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
-                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: true
-                };
-                djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
-            });
-        });
-
-        $.each(multipleFilterForwards, function (_, firstFilter) {
-            $.each(multipleFilterForwards, function (_, secondFilter) {
-                var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
-                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: false
-                };
-                djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
-            });
-        });
-
-        $.each(multipleFilterBacks, function (_, firstFilter) {
-            $.each(multipleFilterBacks, function (_, secondFilter) {
-                var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
-                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: true
-                };
-                djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
-            });
-        });
-
-        $.each([true, false], function (_, isBackwards) {
-            var zeroCountParameters = { index: 0, count: 0, predicate: filterPredicate, feed: feeds[0].feed, take: readRangeTake,
-                skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: isBackwards
-            };
-            djstest.addTest(singleFilterTest, createSingleFilterTestName("Count 0 ", zeroCountParameters), zeroCountParameters);
-        });
-    });
-
-    $.each([true, false], function (_, backwards) {
-        $.each(invalidIndices, function (_, invalidIndex) {
-            var invalidIndexParameters = { index: invalidIndex, count: -1, predicate: filterPredicates[0], feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
-
-            djstest.addTest(
-                function (params) {
-                    djstest.assertsExpected(1);
-                    var options = { name: "cache" + new Date().valueOf(), source: params.feed };
-                    var cache = odatajs.cache.createDataCache(options);
-                    try {
-                        params.backwards ?
-                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
-                                djstest.log(results);
-                            }) :
-                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
-                                djstest.log(results);
-                            });
-                        expectException(cache);
-                    } catch (e) {
-                        djstest.assertAreEqual(e.message, "'index' must be a valid number.", "Error message validation");
-                        djstest.destroyCacheAndDone(cache);
-                    }
-                }, createSingleFilterTestName("invalid index ", invalidIndexParameters), invalidIndexParameters);
-        });
-
-        $.each(invalidCounts, function (_, invalidCount) {
-            var invalidCountParameters = { index: 0, count: invalidCount, predicate: filterPredicates[0], feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
-
-            djstest.addTest(
-                function (params) {
-                    djstest.assertsExpected(1);
-                    var options = { name: "cache" + new Date().valueOf(), source: params.feed };
-                    var cache = odatajs.cache.createDataCache(options);
-                    try {
-                        params.backwards ?
-                            cache.filterBack(params.index, params.count, params.predicate).then(function (results) {
-                                djstest.log(results);
-                            }) :
-                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
-                                djstest.log(results);
-                            });
-                        expectException(cache);
-                    } catch (e) {
-                        djstest.assertAreEqual(e.message, "'count' must be a valid number.", "Error message validation");
-                        djstest.destroyCacheAndDone(cache);
-                    }
-                }, createSingleFilterTestName("invalid count ", invalidCountParameters), invalidCountParameters);
-        });
-    });
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-fperf-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-fperf-tests.html b/datajs/tests/odata-cache-fperf-tests.html
deleted file mode 100644
index c00a814..0000000
--- a/datajs/tests/odata-cache-fperf-tests.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>datajs.cache functional perf tests</title>
-    <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"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>    
-    <script type="text/javascript" src="common/CacheOracle.js"></script>  
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-cache-fperf-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache functional perf 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/d5ec5557/datajs/tests/odata-cache-fperf-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-fperf-tests.js b/datajs/tests/odata-cache-fperf-tests.js
deleted file mode 100644
index cfb698c..0000000
--- a/datajs/tests/odata-cache-fperf-tests.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-
-    var slowHttpClient = {
-        latency: 750,
-        provider: window.odatajs.oData.net.defaultHttpClient,
-        request: function (request, success, error) {
-            setTimeout(function () {
-                slowHttpClient.provider.request(request, success, error);
-            }, slowHttpClient.latency);
-        }
-    };
-
-    var feeds = [
-        { uri: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
-    ];
-
-    module("Functional", {
-        setup: function () {
-            window.odatajs.oData.net.defaultHttpClient = slowHttpClient;
-        },
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = slowHttpClient.provider;
-        }
-    });
-
-    var cacheReadRangeWallClockTest = function (totalReads, interval, mechanism, source, pageSize, prefetchSize, generateRange, threshold) {
-        /** Cache readRange wall-clock test
-         * The average time computed by the wall-clock test does *not* include the initial readRange
-         * @param totalReads - Number of reads to collect data from
-         * @param interval - Interval (milliseconds) between reads
-         * @param mechanism - The cache store mechanism
-         * @param source - The feed source
-         * @param pageSize - The page size
-         * @param prefetchSize - The prefetch size
-         * @param generateRange - The range generator function: given the read index, returns the readRange index and count
-         * @param threshold - The average read time threshold for test to pass; if not specified, defaults to the slowHttpClient latency
-         * @returns The test function
-         */
-        return function () {
-            var cache = odatajs.cache.createDataCache({ name: "cache" + new Date().valueOf(), source: source, pageSize: pageSize, prefetchSize: prefetchSize });
-            var totalTime = 0;
-            var readCount = 0;
-
-            var callReadRange = function () {
-                var range = generateRange(readCount);
-                var startTime = new Date().valueOf();
-                cache.readRange(range.index, range.count).then(function (data) {
-                    var duration = (new Date().valueOf()) - startTime;
-                    djstest.log("readRange " + readCount + " [" + range.index + ", " + range.count + "]: " + duration + "ms");
-
-                    // The first readRange is not counted
-                    totalTime += (readCount > 0) ? duration : 0;
-                    readCount += 1;
-
-                    if (readCount < totalReads) {
-                        setTimeout(callReadRange, interval);
-                    } else {
-                        // The first readRange is not counted
-                        var averageTime = totalTime / (totalReads - 1);
-                        var actualThreshold = threshold === undefined ? slowHttpClient.latency : threshold;
-                        djstest.assert(averageTime < actualThreshold, "Average: " + averageTime + "ms, Threshold: " + actualThreshold + "ms");
-                        djstest.destroyCacheAndDone(cache);
-                    }
-                }, function (err) {
-                    djstest.fail("Unexpected call to error handler with error: " + djstest.toString(err));
-                    djstest.destroyCacheAndDone(cache);
-                });
-            };
-
-            callReadRange();
-        };
-    };
-
-    $.each(CacheOracle.mechanisms, function (_, mechanism) {
-        if (mechanism !== "best" && CacheOracle.isMechanismAvailable(mechanism)) {
-            $.each(feeds, function (_, feed) {
-                djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, feed.uri, 5, 0, function () {
-                    return { index: 0, count: 5 };
-                }), "Cache small single-page wall-clock test with " + mechanism + " on " + feed.uri);
-
-                djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
-                    return { index: readCount * 3, count: 3 };
-                }), "Cache page-by-page wall-clock test with " + mechanism + " on " + feed.uri);
-
-                djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
-                    return { index: readCount, count: 3 };
-                }), "Cache line-by-line wall-clock test with " + mechanism + " on " + feed.uri);
-            });
-
-            var largeFeedUri = "./endpoints/LargeCollectionService.svc/Customers";
-            djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, largeFeedUri, 100, 0, function () {
-                return { index: 0, count: 500 };
-            }), "Cache large single-page wall-clock test with " + mechanism + " on " + largeFeedUri, undefined, 60000);
-        }
-    });
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-cache-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-cache-functional-tests.html b/datajs/tests/odata-cache-functional-tests.html
deleted file mode 100644
index f158030..0000000
--- a/datajs/tests/odata-cache-functional-tests.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData tests against local service</title>
-    <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"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/CacheOracle.js"></script>
-    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
-    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
-    <script type="text/javascript" src="odata-cache-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">datajs.cache tests against local in-memory service</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-</body>
-</html>


[22/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/datajs-1.1.2.min.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/datajs-1.1.2.min.js b/odatajs/demo/scripts/datajs-1.1.2.min.js
new file mode 100644
index 0000000..9b65217
--- /dev/null
+++ b/odatajs/demo/scripts/datajs-1.1.2.min.js
@@ -0,0 +1,13 @@
+// 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.
+(function(n,t){var yt=n.datajs||{},r=n.OData||{},lo,ao,ei,ay,rp;typeof define=="function"&&define.amd?(define("datajs",yt),define("OData",r)):(n.datajs=yt,n.OData=r),yt.version={major:1,minor:1,build:1};var ko=function(t){return n.ActiveXObject?new n.ActiveXObject(t):null},ot=function(n){return n!==null&&n!==t},er=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return!0;return!1},it=function(n,i){return n!==t?n:i},o=function(t){if(arguments.length===1){n.setTimeout(t,0);return}var i=Array.prototype.slice.call(arguments,1);n.setTimeout(function(){t.apply(this,i)},0)},g=function(n,t){for(var i in t)n[i]=t[i];return n},or=function(n,t){if(n)for(var i=0,r=n.length;i<r;i++)if(t(n[i]))return n[i];return null},e=function(n){return Object.prototype.toString.call(n)==="[object Array]"},lf=function(n){return Object.prototype.toString.call(n)==="[object Date]"},af=function(n){return typeof n=="object"},s=function(n){return parseInt(n,10)},ru=function(n,t,i){n.hasOwnProperty(t)&&(n[
 i]=n[t],delete n[t])},uu=function(n){throw n;},go=function(n){return n.trim?n.trim():n.replace(/^\s+|\s+$/g,"")},vf=function(n,i){return n!==t?n:i},up=/^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/,ns=["scheme","authority","path","query","fragment"],yf=function(n){var i={isAbsolute:!1},r,t,u;if(n){if(r=up.exec(n),r)for(t=0,u=ns.length;t<u;t++)r[t+1]&&(i[ns[t]]=r[t+1]);i.scheme&&(i.isAbsolute=!0)}return i},ts=function(n){return"".concat(n.scheme||"",n.authority||"",n.path||"",n.query||"",n.fragment||"")},fp=/^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/,ep=/%[0-9A-F]{2}/ig,op=function(n){var i=yf(n),r=i.scheme,u=i.authority,t;return r&&(i.scheme=r.toLowerCase(),u&&(t=fp.exec(u),t&&(i.authority="//"+(t[1]?t[1]+"@":"")+t[2].toLowerCase()+(t[3]?":"+t[3]:"")))),n=ts(i),n.replace(ep,function(n){return n.toLowerCase()})},c=function(n,t){var i,u,r,f;return t?(i=yf(n),i.isAbsolute)?n:(u=yf(t),r={},i.authority?(r.authority=i.authority,f=i.path,r.query=i.query):(i.path?(f=i.path.charA
 t(0)==="/"?i.path:sp(i.path,u.path),r.query=i.query):(f=u.path,r.query=i.query||u.query),r.authority=u.authority),r.path=hp(f),r.scheme=u.scheme,r.fragment=i.fragment,ts(r)):n},sp=function(n,t){var i="/",r;return t&&(r=t.lastIndexOf("/"),i=t.substring(0,r),i.charAt(i.length-1)!=="/"&&(i=i+"/")),i+n},hp=function(n){for(var t="",r="",i;n;)n.indexOf("..")===0||n.indexOf(".")===0?n=n.replace(/^\.\.?\/?/g,""):n.indexOf("/..")===0?(n=n.replace(/^\/\..\/?/g,"/"),i=t.lastIndexOf("/"),t=i===-1?"":t.substring(0,i)):n.indexOf("/.")===0?n=n.replace(/^\/\.\/?/g,"/"):(r=n,i=n.indexOf("/",1),i!==-1&&(r=n.substring(0,i)),t=t+r,n=n.replace(r,""));return t},cp=function(i){var r=[],o,u,f,s,e,h;if(n.atob===t)r=lp(i);else for(o=n.atob(i),u=0;u<o.length;u++)r.push(o.charCodeAt(u));for(f="",s="0123456789ABCDEF",e=0;e<r.length;e++)h=r[e],f+=s[h>>4],f+=s[h&15];return f},lp=function(n){for(var i="",r,u,f,e,o,t=0;t<n.length;t++)r=ap(n[t]),u="",r!==null&&(u=r.toString(2),i+=vp(u));for(f=[],e=parseInt(i.length/
 8,10),t=0;t<e;t++)o=parseInt(i.substring(t*8,(t+1)*8),2),f.push(o);return f},ap=function(n){var t=n.charCodeAt(0),i=65,r=6;return t>=65&&t<=90?t-i:t>=97&&t<=122?t-i-r:t>=48&&t<=57?t+4:n=="+"?62:n=="/"?63:null},vp=function(n){while(n.length<6)n="0"+n;return n},fu="http://",sr=fu+"www.w3.org/",is=sr+"1999/xhtml",hr=sr+"2000/xmlns/",pi=sr+"XML/1998/namespace",rs=fu+"www.mozilla.org/newlayout/xml/parsererror.xml",yp=function(n){var t=/(^\s)|(\s$)/;return t.test(n)},pp=function(n){var t=/^\s*$/;return n===null||t.test(n)},wp=function(n){while(n!==null&&n.nodeType===1){var t=st(n,"space",pi);if(t==="preserve")return!0;if(t==="default")break;else n=n.parentNode}return!1},bp=function(n){var t=n.nodeName;return t=="xmlns"||t.indexOf("xmlns:")===0},eu=function(n,t,i){try{n.setProperty(t,i)}catch(r){}},kp=function(){var n=ko("Msxml2.DOMDocument.3.0");return n&&(eu(n,"ProhibitDTD",!0),eu(n,"MaxElementDepth",256),eu(n,"AllowDocumentFunction",!1),eu(n,"AllowXsltScript",!1)),n},us=function(){try{v
 ar n=ko("Msxml2.DOMDocument.6.0");return n&&(n.async=!0),n}catch(t){return kp()}},dp=function(n){var t=us(),i;return t?(t.loadXML(n),i=t.parseError,i.errorCode!==0&&cr(i.reason,i.srcText,n),t):null},cr=function(n,t,i){typeof n=="string"&&(n={message:n});throw g(n,{srcText:t||"",errorXmlText:i||""});},ou=function(t){var s=n.DOMParser&&new n.DOMParser,r,e,l;if(!s)return r=dp(t),r||cr("XML DOM parser not supported"),r;try{r=s.parseFromString(t,"text/xml")}catch(v){cr(v,"",t)}var i=r.documentElement,h=i.namespaceURI,c=f(i);if(c==="parsererror"&&h===rs&&(e=b(i,rs,"sourcetext"),l=e?ki(e):"",cr(k(i)||"",l,t)),c==="h3"&&h===is||tw(i,is,"h3")){for(var o="",a=[],u=i.firstChild;u;)u.nodeType===1&&(o+=k(u)||""),a.push(u.nextSibling),u=u.firstChild||a.shift();o+=k(i)||"",cr(o,"",t)}return r},pt=function(n,t){return n?n+":"+t:t},gp=function(n,t){if(yp(t.data)){var i=bi(n,pi,"space");i||(i=si(n.ownerDocument,pi,pt("xml","space")),l(n,i)),i.value="preserve"}return n.appendChild(t),n},wi=function(n,
 t){for(var r=n.attributes,i=0,u=r.length;i<u;i++)t(r.item(i))},st=function(n,t,i){var r=bi(n,t,i);return r?ki(r):null},bi=function(n,t,i){var r=n.attributes;return r.getNamedItemNS?r.getNamedItemNS(i||null,t):r.getQualifiedItem(t,i)||null},rt=function(n,t){var i=bi(n,"base",pi);return(i?c(i.value,t):t)||null},p=function(n,t){pf(n,!1,function(n){return n.nodeType===1&&t(n),!0})},fs=function(n,t,i){for(var u=i.split("/"),r=0,f=u.length;r<f;r++)n=n&&b(n,t,u[r]);return n||null},nw=function(n,t,i){var f=i.lastIndexOf("/"),r=i.substring(f+1),e=i.substring(0,f),u=e?fs(n,t,e):n;return u?r.charAt(0)==="@"?bi(u,r.substring(1),t):b(u,t,r):null},b=function(n,t,i){return es(n,t,i,!1)},tw=function(n,t,i){if(n.getElementsByTagNameNS){var r=n.getElementsByTagNameNS(t,i);return r.length>0?r[0]:null}return es(n,t,i,!0)},es=function(n,t,i,r){var e=null;return pf(n,r,function(n){if(n.nodeType===1){var r=!t||u(n)===t,o=!i||f(n)===i;r&&o&&(e=n)}return e===null}),e},k=function(n){var i=null,r=n.nodeType==
 =9&&n.documentElement?n.documentElement:n,f=r.ownerDocument.preserveWhiteSpace===!1,u;return pf(r,!1,function(n){if(n.nodeType===3||n.nodeType===4){var e=ki(n),o=f||!pp(e);o||(u===t&&(u=wp(r)),o=u),o&&(i?i+=e:i=e)}return!0}),i},f=function(n){return n.localName||n.baseName},u=function(n){return n.namespaceURI||null},ki=function(n){return n.nodeType===1?k(n):n.nodeValue},pf=function(n,t,i){for(var f=[],r=n.firstChild,u=!0;r&&u;)u=i(r),u&&(t&&r.firstChild&&f.push(r.firstChild),r=r.nextSibling||f.shift())},iw=function(n,t,i){for(var r=n.nextSibling,e,o;r;){if(r.nodeType===1&&(e=!t||u(r)===t,o=!i||f(r)===i,e&&o))return r;r=r.nextSibling}return null},os=function(){var t=n.document.implementation;return t&&t.createDocument?t.createDocument(null,null,null):us()},su=function(n,t){if(!e(t))return l(n,t);for(var i=0,r=t.length;i<r;i++)t[i]&&l(n,t[i]);return n},l=function(n,t){if(t){if(typeof t=="string")return gp(n,uw(n.ownerDocument,t));t.nodeType===2?n.setAttributeNodeNS?n.setAttributeNodeNS
 (t):n.setAttributeNode(t):n.appendChild(t)}return n},si=function(n,i,r,u){var f=n.createAttributeNS&&n.createAttributeNS(i,r)||n.createNode(2,r,i||t);return f.value=u||"",f},lr=function(n,i,r,u){var f=n.createElementNS&&n.createElementNS(i,r)||n.createNode(1,r,i||t);return su(f,u||[])},ss=function(n,t,i){return si(n,hr,pt("xmlns",i),t)},rw=function(n,t){for(var f="<c>"+t+"<\/c>",e=ou(f),r=e.documentElement,o=("importNode"in n)?n.importNode(r,!0):r,u=n.createDocumentFragment(),i=o.firstChild;i;)u.appendChild(i),i=i.nextSibling;return u},uw=function(n,t){return n.createTextNode(t)},fw=function(n,t,i,r,u){for(var f="",h=u.split("/"),c=b,a=lr,o=t,e,s=0,v=h.length;s<v;s++)f=h[s],f.charAt(0)==="@"&&(f=f.substring(1),c=bi,a=si),e=c(o,i,f),e||(e=a(n,i,pt(r,f)),l(o,e)),o=e;return o},wf=function(t){var i=n.XMLSerializer,r;if(i)return r=new i,r.serializeToString(t);if(t.xml)return t.xml;throw{message:"XML serialization unsupported"};},ew=function(n){var f=n.childNodes,t,r=f.length,i;if(r===0)r
 eturn"";var e=n.ownerDocument,o=e.createDocumentFragment(),u=e.createElement("c");for(o.appendChild(u),t=0;t<r;t++)u.appendChild(f[t]);for(i=wf(o),i=i.substr(3,i.length-7),t=0;t<r;t++)n.appendChild(u.childNodes[t]);return i},kit=function(i){var r=i.xml,u;if(r!==t)return r;if(n.XMLSerializer)return u=new n.XMLSerializer,u.serializeToString(i);throw{message:"XML serialization unsupported"};},ow=function(n,t,i){return function(){return n[t].apply(n,arguments),i}},di=function(){this._arguments=t,this._done=t,this._fail=t,this._resolved=!1,this._rejected=!1};di.prototype={then:function(n,t){return n&&(this._done?this._done.push(n):this._done=[n]),t&&(this._fail?this._fail.push(t):this._fail=[t]),this._resolved?this.resolve.apply(this,this._arguments):this._rejected&&this.reject.apply(this,this._arguments),this},resolve:function(){if(this._done){for(var n=0,i=this._done.length;n<i;n++)this._done[n].apply(null,arguments);this._done=t,this._resolved=!1,this._arguments=t}else this._resolved=
 !0,this._arguments=arguments},reject:function(){if(this._fail){for(var n=0,i=this._fail.length;n<i;n++)this._fail[n].apply(null,arguments);this._fail=t,this._rejected=!1,this._arguments=t}else this._rejected=!0,this._arguments=arguments},promise:function(){var n={};return n.then=ow(this,"then",n),n}};var hu=function(){return n.jQuery&&n.jQuery.Deferred?new n.jQuery.Deferred:new di},hs=function(n,t){var i=(n&&n.__metadata||{}).type;return i||(t?t.type:null)},v="Edm.",cs=v+"Binary",ls=v+"Boolean",as=v+"Byte",cu=v+"DateTime",lu=v+"DateTimeOffset",vs=v+"Decimal",ys=v+"Double",ps=v+"Guid",ws=v+"Int16",bs=v+"Int32",ks=v+"Int64",ds=v+"SByte",gs=v+"Single",ar=v+"String",au=v+"Time",ht=v+"Geography",nh=ht+"Point",th=ht+"LineString",ih=ht+"Polygon",rh=ht+"Collection",uh=ht+"MultiPolygon",fh=ht+"MultiLineString",eh=ht+"MultiPoint",et=v+"Geometry",oh=et+"Point",sh=et+"LineString",hh=et+"Polygon",ch=et+"Collection",lh=et+"MultiPolygon",ah=et+"MultiLineString",vh=et+"MultiPoint",bf="Point",kf="Li
 neString",df="Polygon",gf="MultiPoint",ne="MultiLineString",te="MultiPolygon",ie="GeometryCollection",sw=[ar,bs,ks,ls,ys,gs,cu,lu,au,vs,ps,as,ws,ds,cs],hw=[et,oh,sh,hh,ch,lh,ah,vh],cw=[ht,nh,th,ih,rh,uh,fh,eh],hi=function(n,t){if(!n)return null;if(e(n)){for(var r,i=0,u=n.length;i<u;i++)if(r=hi(n[i],t),r)return r;return null}return n.dataServices?hi(n.dataServices.schema,t):t(n)},yh=function(n,t){return n=n===0?"":"."+a(n.toString(),3),t>0&&(n===""&&(n=".000"),n+=a(t.toString(),4)),n},ph=function(n){var u,t,e;if(typeof n=="string")return n;if(u=yw(n),t=bh(n.__offset),u&&t!=="Z"){n=new Date(n.valueOf());var i=oc(t),o=n.getUTCHours()+i.d*i.h,s=n.getUTCMinutes()+i.d*i.m;n.setUTCHours(o,s)}else u||(t="");var r=n.getUTCFullYear(),h=n.getUTCMonth()+1,f="";return r<=0&&(r=-(r-1),f="-"),e=yh(n.getUTCMilliseconds(),n.__ns),f+a(r,4)+"-"+a(h,2)+"-"+a(n.getUTCDate(),2)+"T"+a(n.getUTCHours(),2)+":"+a(n.getUTCMinutes(),2)+":"+a(n.getUTCSeconds(),2)+e+t},wh=function(n){var t=n.ms,e="",i,r,u,f;retur
 n t<0&&(e="-",t=-t),i=Math.floor(t/864e5),t-=864e5*i,r=Math.floor(t/36e5),t-=36e5*r,u=Math.floor(t/6e4),t-=6e4*u,f=Math.floor(t/1e3),t-=f*1e3,e+"P"+a(i,2)+"DT"+a(r,2)+"H"+a(u,2)+"M"+a(f,2)+yh(t,n.ns)+"S"},a=function(n,t,i){for(var r=n.toString(10);r.length<t;)i?r+="0":r="0"+r;return r},bh=function(n){return!n||n==="Z"||n==="+00:00"||n==="-00:00"?"Z":n},vu=function(n){if(typeof n=="string"){var t=n.indexOf(")",10);if(n.indexOf("Collection(")===0&&t>0)return n.substring(11,t)}return null},lw=function(n,i,r,u,f,e){return f.request(n,function(f){try{f.headers&&oe(f.headers),f.data===t&&f.statusCode!==204&&u.read(f,e)}catch(o){o.request===t&&(o.request=n),o.response===t&&(o.response=f),r(o);return}i(f.data,f)},r)},aw=function(n){return d(n)&&e(n.__batchRequests)},vw=/Collection\((.*)\)/,kh=function(n,t){var i=n&&n.results||n;return!!i&&yu(t)||!t&&e(i)&&!d(i[0])},yu=function(n){return vw.test(n)},d=function(n){return!!n&&af(n)&&!e(n)&&!lf(n)},yw=function(n){return n.__edmType==="Edm.DateT
 imeOffset"||!n.__edmType&&n.__offset},dh=function(n){if(!n&&!d(n))return!1;var t=n.__metadata||{},i=n.__deferred||{};return!t.type&&!!i.uri},gh=function(n){return d(n)&&n.__metadata&&"uri"in n.__metadata},vr=function(n,t){var i=n&&n.results||n;return e(i)&&!yu(t)&&d(i[0])},re=function(n){return er(cw,n)},ue=function(n){return er(hw,n)},nc=function(n){if(!n&&!d(n))return!1;var i=n.__metadata,t=n.__mediaresource;return!i&&!!t&&!!t.media_src},pu=function(n){return lf(n)||typeof n=="string"||typeof n=="number"||typeof n=="boolean"},fe=function(n){return er(sw,n)},tc=function(n,i){return dh(n)?"deferred":gh(n)?"entry":vr(n)?"feed":i&&i.relationship?n===null||n===t||!vr(n)?"entry":"feed":null},wt=function(n,t){return or(n,function(n){return n.name===t})},ee=function(n,t,i){return n?hi(t,function(t){return gw(n,t,i)}):null},pw=function(n,t){return or(n,function(n){return n.name===t})},gi=function(n,t){return ee(n,t,"complexType")},bt=function(n,t){return ee(n,t,"entityType")},ic=function(n
 ){return hi(n,function(n){return or(n.entityContainer,function(n){return se(n.isDefaultEntityContainer)})})},rc=function(n,t){return ee(n,t,"entityContainer")},ww=function(n,t){return or(n,function(n){return n.name===t})},bw=function(n,t){var u=null,f,i,r;return n&&(f=n.relationship,i=hi(t,function(n){var r=uc(n.namespace,f),i=n.association,t,u;if(r&&i)for(t=0,u=i.length;t<u;t++)if(i[t].name===r)return i[t];return null}),i&&(r=i.end[0],r.role!==n.toRole&&(r=i.end[1]),u=r.type)),u},kw=function(n,t,i){if(n){var u=n.relationship,r=hi(i,function(n){for(var f=n.entityContainer,t,i,r=0;r<f.length;r++)if(t=f[r].associationSet,t)for(i=0;i<t.length;i++)if(t[i].association==u)return t[i];return null});if(r&&r.end[0]&&r.end[1])return r.end[0].entitySet==t?r.end[1].entitySet:r.end[0].entitySet}return null},dw=function(n,t){return hi(t,function(t){for(var f=t.entityContainer,r,u,i=0;i<f.length;i++)if(r=f[i].entitySet,r)for(u=0;u<r.length;u++)if(r[u].name==n)return{entitySet:r[u],containerName:f[
 i].name,functionImport:f[i].functionImport};return null})},uc=function(n,t){return t.indexOf(n)===0&&t.charAt(n.length)==="."?t.substr(n.length+1):null},gw=function(n,t,i){if(n&&t){var r=uc(t.namespace,n);if(r)return or(t[i],function(n){return n.name===r})}return null},ct=function(n,t){var i,f,e;if(n===t)return n;var r=n.split("."),u=t.split("."),o=r.length>=u.length?r.length:u.length;for(i=0;i<o;i++){if(f=r[i]&&s(r[i]),e=u[i]&&s(u[i]),f>e)return n;if(f<e)return t}},nb={accept:"Accept","content-type":"Content-Type",dataserviceversion:"DataServiceVersion",maxdataserviceversion:"MaxDataServiceVersion"},oe=function(n){var t,r,i,u;for(t in n)r=t.toLowerCase(),i=nb[r],i&&t!==i&&(u=n[t],delete n[t],n[i]=u)},se=function(n){return typeof n=="boolean"?n:typeof n=="string"&&n.toLowerCase()==="true"},tb=/^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/,fc=function(n,t,i){var r=tb.exec(n),o=r?bh(r[8]):null,h,u,e,c,l,f;if(!r||!t&&o!=="Z"){if(i)return null;throw{message:
 "Invalid date/time value"};}if(h=s(r[1]),h<=0&&h++,u=r[7],e=0,u){if(u.length>7){if(i)return null;throw{message:"Cannot parse date/time value to given precision."};}e=a(u.substring(3),4,!0),u=a(u.substring(0,3),3,!0),u=s(u),e=s(e)}else u=0;var v=s(r[4]),y=s(r[5]),p=s(r[6])||0;if(o!=="Z"&&(c=oc(o),l=-c.d,v+=c.h*l,y+=c.m*l),f=new Date,f.setUTCFullYear(h,s(r[2])-1,s(r[3])),f.setUTCHours(v,y,p,u),isNaN(f.valueOf())){if(i)return null;throw{message:"Invalid date/time value"};}return t&&(f.__edmType="Edm.DateTimeOffset",f.__offset=o),e&&(f.__ns=e),f},wu=function(n,t){return fc(n,!1,t)},he=function(n,t){return fc(n,!0,t)},ec=/^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/,dit=function(n){ec.test(n)},ce=function(n){var i=ec.exec(n),t,r,u;if(i===null)throw{message:"Invalid duration value."};var f=i[2]||"0",e=i[3]||"0",o=s(i[4]||0),h=s(i[5]||0),c=s(i[6]||0),l=parseFloat(i[7]||0);if(f!=="0"||e!=="0")throw{message:"Unsupported duration value."};if(t
 =i[8],r=0,t){if(t.length>7)throw{message:"Cannot parse duration value to given precision."};r=a(t.substring(3),4,!0),t=a(t.substring(0,3),3,!0),t=s(t),r=s(r)}else t=0;return t+=l*1e3+c*6e4+h*36e5+o*864e5,i[1]==="-"&&(t=-t),u={ms:t,__edmType:"Edm.Time"},r&&(u.ns=r),u},oc=function(n){var t=n.substring(0,1),i,r;return t=t==="+"?1:-1,i=s(n.substring(1)),r=s(n.substring(n.indexOf(":")+1)),{d:t,h:i,m:r}},sc=function(n,i,r){n.method||(n.method="GET"),n.headers?oe(n.headers):n.headers={},n.headers.Accept===t&&(n.headers.Accept=i.accept),ot(n.data)&&n.body===t&&i.write(n,r),ot(n.headers.MaxDataServiceVersion)||(n.headers.MaxDataServiceVersion=i.maxDataServiceVersion||"1.0")},hc=function(n,i,r){var u,e,f;if(n&&typeof n=="object")for(u in n)e=n[u],f=hc(e,u,r),f=r(u,f,i),f!==e&&(e===t?delete n[u]:n[u]=f);return n},ib=function(n,t){return t("",hc(n,"",t))},bu=0,rb=function(n){return n.method&&n.method!=="GET"?!1:!0},ub=function(t){var i=n.document.createElement("IFRAME");i.style.display="none";v
 ar r=t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/\</g,"&lt;"),u='<html><head><script type="text/javascript" src="'+r+'"><\/script><\/head><body><\/body><\/html>',f=n.document.getElementsByTagName("BODY")[0];return f.appendChild(i),cc(i,u),i},fb=function(){if(n.XMLHttpRequest)return new n.XMLHttpRequest;var t;if(n.ActiveXObject)try{return new n.ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(i){try{return new n.ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(r){t=r}}else t={message:"XMLHttpRequest not supported"};throw t;},eb=function(n){return n.indexOf("http://")===0||n.indexOf("https://")===0||n.indexOf("file://")===0},ob=function(t){if(!eb(t))return!0;var i=n.location,r=i.protocol+"//"+i.host+"/";return t.indexOf(r)===0},sb=function(i,r){try{delete n[i]}catch(u){n[i]=t,r===bu-1&&(bu-=1)}},ku=function(n){return n&&(cc(n,""),n.parentNode.removeChild(n)),null},hb=function(n,t){for(var r=n.getAllResponseHeaders().split(/\r?\n/),u,i=0,f=r.length;i<f;i++)r[i]&&(u=r[i].split(": "),t[u[0
 ]]=u[1])},cc=function(n,t){var i=n.contentWindow?n.contentWindow.document:n.contentDocument.document;i.open(),i.write(t),i.close()};r.defaultHttpClient={callbackParameterName:"$callback",formatQueryString:"$format=json",enableJsonpCallback:!1,request:function(i,r,u){var y={},f=null,h=!1,s,a,w,b,k,d,l,v;y.abort=function(){(s=ku(s),h)||(h=!0,f&&(f.abort(),f=null),u({message:"Request aborted"}))};var p=function(){s=ku(s),h||(h=!0,f=null,u({message:"Request timed out"}))},c,e=i.requestUri,g=it(i.enableJsonpCallback,this.enableJsonpCallback),nt=it(i.callbackParameterName,this.callbackParameterName),tt=it(i.formatQueryString,this.formatQueryString);if(!g||ob(e)){if(f=fb(),f.onreadystatechange=function(){var t,n,o,s;h||f===null||f.readyState!==4||(t=f.statusText,n=f.status,n===1223&&(n=204,t="No Content"),o=[],hb(f,o),s={requestUri:e,statusCode:n,statusText:t,headers:o,body:f.responseText},h=!0,f=null,n>=200&&n<=299?r(s):u({message:"HTTP request failed",request:i,response:s}))},f.open(i.me
 thod||"GET",e,!0,i.user,i.password),i.headers)for(c in i.headers)f.setRequestHeader(c,i.headers[c]);i.timeoutMS&&(f.timeout=i.timeoutMS,f.ontimeout=p),f.send(i.body)}else{if(!rb(i))throw{message:"Request is not local and cannot be done through JSONP."};a=bu,bu+=1,w=a.toString(),b=!1,c="handleJSONP_"+w,n[c]=function(i){if(s=ku(s),!h){b=!0,n.clearTimeout(k),sb(c,a),n.ActiveXObject&&(i=n.JSON.parse(n.JSON.stringify(i)));var u;u=i.d===t?{"Content-Type":"application/json;odata=minimalmetadata",dataServiceVersion:"3.0"}:{"Content-Type":"application/json"},o(function(){ku(s),r({body:i,statusCode:200,headers:u})})}},d=i.timeoutMS?i.timeoutMS:12e4,k=n.setTimeout(p,d),l=nt+"=parent."+c,this.formatQueryString&&(l+="&"+tt),v=e.indexOf("?"),e=v===-1?e+"?"+l:v===e.length-1?e+l:e+"&"+l,s=ub(e)}return y}};var ci="3.0",nr=function(n){var t,r,i,f,u;if(!n)return null;for(t=n.split(";"),r={},i=1,f=t.length;i<f;i++)u=t[i].split("="),r[go(u[0])]=u[1];return{mediaType:go(t[0]),properties:r}},cb=function(n
 ){if(!n)return t;var r=n.mediaType,i;for(i in n.properties)r+=";"+i+"="+n.properties[i];return r},lc=function(n,t,i,r){var u={};return g(u,i),g(u,{contentType:n,dataServiceVersion:t,handler:r}),u},ac=function(n,t,i){if(n){var r=n.headers;r[t]||(r[t]=i)}},lb=function(n,t){if(n){var i=n.headers,r=i.DataServiceVersion;i.DataServiceVersion=r?ct(r,t):t}},vc=function(n,i){var r=n.headers;return r&&r[i]||t},yc=function(n){return nr(vc(n,"Content-Type"))},ab=/^\s?(\d+\.\d+);?.*$/,pc=function(n){var i=vc(n,"DataServiceVersion"),t;if(i&&(t=ab.exec(i),t&&t.length))return t[1]},wc=function(n,t){return n.accept.indexOf(t.mediaType)>=0},vb=function(n,i,r,u){var f;if(!r||!r.headers)return!1;var e=yc(r),s=pc(r)||"",o=r.body;return ot(o)?wc(n,e)?(f=lc(e,s,u,n),f.response=r,r.data=i(n,o,f),r.data!==t):!1:!1},yb=function(n,i,r,u){var e,o,f;return!r||!r.headers?!1:(e=yc(r),o=pc(r),(!e||wc(n,e))&&(f=lc(e,o,u,n),f.request=r,r.body=i(n,r.data,f),r.body!==t))?(lb(r,f.dataServiceVersion||"1.0"),ac(r,"Conten
 t-Type",cb(f.contentType)),ac(r,"MaxDataServiceVersion",n.maxDataServiceVersion),!0):!1},li=function(n,t,i,r){return{accept:i,maxDataServiceVersion:r,read:function(t,i){return vb(this,n,t,i)},write:function(n,i){return yb(this,t,n,i)}}},pb=function(n,t){return t},wb=function(n,i){return ot(i)?i.toString():t};r.textHandler=li(pb,wb,"text/plain",ci);var bc=fu+"www.opengis.net",ut=bc+"/gml",kc=bc+"/def/crs/EPSG/0/",dc="gml",yr=function(n,t,i){var r={type:n};return r[t]=i,r},le=function(n){if(e(n)&&n.length>=2){var t=n[0];n[0]=n[1],n[1]=t}return n},ae=function(n,t,i,r,u,f){var e=gc(n,i,r,u,f);return yr(t,"coordinates",e)},gc=function(n,t,i,r,e){var o=[];return p(n,function(n){var s,h,c;if(u(n)===ut){if(s=f(n),s===t){h=b(n,ut),h&&(c=r(h,e),c&&o.push(c));return}s===i&&p(n,function(n){if(u(n)===ut){var t=r(n,e);t&&o.push(t)}})}}),o},bb=function(n,t){var i=gc(n,"geometryMember","geometryMembers",il,t);return yr(ie,"geometries",i)},kb=function(n,t){return yr(kf,"coordinates",ve(n,t))},db=fun
 ction(n,t){return ae(n,ne,"curveMember","curveMembers",ve,t)},gb=function(n,t){return ae(n,gf,"pointMember","pointMembers",ye,t)},nk=function(n,t){return ae(n,te,"surfaceMember","surfaceMembers",nl,t)},tk=function(n,t){return yr(bf,"coordinates",ye(n,t))},ik=function(n,t){return yr(df,"coordinates",nl(n,t))},ve=function(n,t){var i=[];return p(n,function(n){var e=u(n),r;if(e===ut){if(r=f(n),r==="posList"){i=uk(n,t);return}if(r==="pointProperty"){i.push(rk(n,t));return}if(r==="pos"){i.push(pe(n,t));return}}}),i},ye=function(n,t){var i=b(n,ut,"pos");return i?pe(i,t):[]},rk=function(n,t){var i=b(n,ut,"Point");return i?ye(i,t):[]},nl=function(n,t){var i=[],r=!1;return p(n,function(n){if(u(n)===ut){var e=f(n);if(e==="exterior"){r=!0,i.unshift(tl(n,t));return}if(e==="interior"){i.push(tl(n,t));return}}}),!r&&i.length>0&&i.unshift([[]]),i},tl=function(n,t){var i=[];return p(n,function(n){u(n)===ut&&f(n)==="LinearRing"&&(i=ve(n,t))}),i},uk=function(n,t){var f=pe(n,!1),e=f.length,r,i,u;if(e%2
 !=0)throw{message:"GML posList element has an uneven number of numeric values"};for(r=[],i=0;i<e;i+=2)u=f.slice(i,i+2),r.push(t?le(u):u);return r},pe=function(n,t){var u=[],o=" \t\r\n",r=k(n),f;if(r)for(var s=r.length,e=0,i=0;i<=s;)o.indexOf(r.charAt(i))!==-1&&(f=r.substring(e,i),f&&u.push(parseFloat(f)),e=i+1),i++;return t?le(u):u},il=function(n,t){var o=f(n),i,u,r,e;switch(o){case"Point":i=tk;break;case"Polygon":i=ik;break;case"LineString":i=kb;break;case"MultiPoint":i=gb;break;case"MultiCurve":i=db;break;case"MultiSurface":i=nk;break;case"MultiGeometry":i=bb;break;default:throw{message:"Unsupported element: "+o,element:n};}if(u=i(n,t),r=st(n,"srsName",ut)||st(n,"srsName"),r){if(r.indexOf(kc)!==0)throw{message:"Unsupported srs name: "+r,element:n};e=r.substring(kc.length),e&&(u.crs={type:"name",properties:{name:"EPSG:"+e}})}return u},rl=function(n,t,i,r){var u,o,e,s,f,h,c;switch(i){case bf:u=fk;break;case kf:u=ek;break;case df:u=ok;break;case gf:u=sk;break;case ne:u=hk;break;case 
 te:u=ck;break;case ie:u=ak;break;default:return null}return o=u(n,t,r),e=t.crs,e&&e.type==="name"&&(s=e.properties,f=s&&s.name,f&&f.indexOf("ESPG:")===0&&f.length>5&&(h=f.substring(5),c=si(n,null,"srsName",dc+h),l(o,c))),o},kt=function(n,t,i){return lr(n,ut,pt(dc,t),i)},ul=function(n,t,i){var r=e(t)?t:[];return r=i?le(r):r,kt(n,"pos",r.join(" "))},fl=function(n,t,i,r){var f=kt(n,t),u,o;if(e(i)){for(u=0,o=i.length;u<o;u++)l(f,ul(n,i[u],r));o===0&&l(f,kt(n,"posList"))}return f},el=function(n,t,i){return kt(n,"Point",ul(n,t,i))},ol=function(n,t,i){return fl(n,"LineString",t,i)},sl=function(n,t,i,r){var u=kt(n,t),f;return e(i)&&i.length>0&&(f=fl(n,"LinearRing",i,r),l(u,f)),u},hl=function(n,t,i){var f=t&&t.length,u=kt(n,"Polygon"),r;if(e(t)&&f>0)for(l(u,sl(n,"exterior",t[0],i)),r=1;r<f;r++)l(u,sl(n,"interior",t[r],i));return u},fk=function(n,t,i){return el(n,t.coordinates,i)},ek=function(n,t,i){return ol(n,t.coordinates,i)},ok=function(n,t,i){return hl(n,t.coordinates,i)},du=function(n,t
 ,i,r,u,f){var h=r&&r.length,c=kt(n,t),s,o;if(e(r)&&h>0){for(s=kt(n,i),o=0;o<h;o++)l(s,u(n,r[o],f));l(c,s)}return c},sk=function(n,t,i){return du(n,"MultiPoint","pointMembers",t.coordinates,el,i)},hk=function(n,t,i){return du(n,"MultiCurve","curveMembers",t.coordinates,ol,i)},ck=function(n,t,i){return du(n,"MultiSurface","surfaceMembers",t.coordinates,hl,i)},lk=function(n,t,i){return rl(n,t,t.type,i)},ak=function(n,t,i){return du(n,"MultiGeometry","geometryMembers",t.geometries,lk,i)},gu="application/xml",dt=fu+"schemas.microsoft.com/ado/",ai=dt+"2007/08/dataservices",nf=dt+"2007/06/edmx",vk=dt+"2006/04/edm",yk=dt+"2007/05/edm",pk=dt+"2008/01/edm",wk=dt+"2008/09/edm",bk=dt+"2009/08/edm",kk=dt+"2009/11/edm",lt=ai,nt=ai+"/metadata",we=ai+"/related/",cl=ai+"/scheme",ll="d",be="m",gt=function(n,t){var i={name:f(n),value:n.value};return i[t?"namespaceURI":"namespace"]=u(n),i},pr=function(n,t){for(var s=[],h=[],c=n.attributes,e,i,o,r=0,l=c.length;r<l;r++)e=c[r],u(e)!==hr&&s.push(gt(e,t));f
 or(i=n.firstChild;i!=null;)i.nodeType===1&&h.push(pr(i,t)),i=i.nextSibling;return o={name:f(n),value:k(n),attributes:s,children:h},o[t?"namespaceURI":"namespace"]=u(n),o},ke=function(n){return u(n)===lt&&f(n)==="element"},al=function(n,t){return{type:n,extensions:t}},dk=function(n){var t,i;return b(n,ut)?et:(t=b(n,lt),!t)?ar:ke(t)&&(i=iw(t,lt),i&&ke(i))?"Collection()":null},vl=function(n){var t=null,i=!1,r=[];return wi(n,function(n){var e=u(n),o=f(n),s=ki(n);if(e===nt){if(o==="null"){i=s.toLowerCase()==="true";return}if(o==="type"){t=s;return}}if(e!==pi&&e!==hr){r.push(gt(n,!0));return}}),{type:!t&&i?ar:t,isNull:i,extensions:r}},yl=function(n){if(u(n)!==lt)return null;var e=f(n),t=vl(n),o=t.isNull,i=t.type,r=al(i,t.extensions),s=o?null:pl(n,i,r);return{name:e,value:s,metadata:r}},pl=function(n,t,i){t||(t=dk(n),i.type=t);var r=re(t);return r||ue(t)?gk(n,t,r):fe(t)?wl(n,t):yu(t)?td(n,t,i):nd(n,t,i)},gk=function(n,t,i){var u=b(n,ut),r=il(u,i);return r.__metadata={type:t},r},wl=function
 (n,t){var i=ki(n)||"";switch(t){case ls:return se(i);case cs:case vs:case ps:case ks:case ar:return i;case as:case ws:case bs:case ds:return s(i);case ys:case gs:return parseFloat(i);case au:return ce(i);case cu:return wu(i);case lu:return he(i)}return i},nd=function(n,t,i){var r={__metadata:{type:t}};return p(n,function(n){var t=yl(n),u=t.name;i.properties=i.properties||{},i.properties[u]=t.metadata,r[u]=t.value}),r},td=function(n,t,i){var r=[],u=i.elements=[],f=vu(t);return p(n,function(n){if(ke(n)){var t=vl(n),o=t.extensions,i=t.type||f,e=al(i,o),s=pl(n,i,e);r.push(s),u.push(e)}}),{__metadata:{type:t==="Collection()"?null:t},results:r}},id=function(n,i){if(u(n)===lt){i=rt(n,i);var r=f(n);if(r==="links")return rd(n,i);if(r==="uri")return bl(n,i)}return t},rd=function(n,t){var i=[];return p(n,function(n){f(n)==="uri"&&u(n)===lt&&i.push(bl(n,t))}),{results:i}},bl=function(n,t){var i=k(n)||"";return{uri:c(i,t)}},ud=function(n,t){return t===et||t===ht?n&&n.type:t===oh||t===nh?bf:t===s
 h||t===th?kf:t===hh||t===ih?df:t===ch||t===rh?ie:t===lh||t===uh?te:t===ah||t===fh?ne:t===vh||t===eh?gf:null},kl=function(n,t,i){return lr(n,nt,pt(be,t),i)},de=function(n,t,i){return si(n,nt,pt(be,t),i)},dl=function(n,t,i){return lr(n,lt,pt(ll,t),i)},fd=function(n,t){return t===cu||t===lu||lf(n)?ph(n):t===au?wh(n):n.toString()},at=function(n,t){return{element:n,dsv:t}},wr=function(n,t,i,r){var u=i?de(n,"type",i):null,f=dl(n,t,u);return su(f,r)},ed=function(n,t,i,r){var u=fd(i,r),f=wr(n,t,r,u);return at(f,"1.0")},od=function(n,t,i,r){var u=de(n,"null","true"),f=wr(n,t,i,u),e=gi(i,r)?"2.0":"1.0";return at(f,e)},sd=function(n,t,i,r,u,f,o){var c=vu(r),a=e(i)?i:i.results,v=r?{type:c}:{},h,s,y,p,w;for(v.properties=u.properties,h=wr(n,t,c?r:null),s=0,y=a.length;s<y;s++)p=a[s],w=ge(n,"element",p,v,f,o),l(h,w.element);return at(h,"3.0")},hd=function(n,t,i,r,u,f,e){var h=wr(n,t,r),a=u.properties||{},v=gi(r,e)||{},s="1.0",o;for(o in i)if(o!=="__metadata"){var y=i[o],p=wt(v.property,o),w=a[o]||{
 },c=ge(n,o,y,w,p,e);s=ct(s,c.dsv),l(h,c.element)}return at(h,s)},cd=function(n,t,i,r,u){var f=ud(i,r),e=rl(n,i,f,u),o=wr(n,t,r,e);return at(o,"3.0")},ge=function(n,t,i,r,u,f){var e=hs(i,r,u),o,s;return pu(i)?ed(n,t,i,e||ar):(o=re(e),o||ue(e))?cd(n,t,i,e,o):kh(i,e)?sd(n,t,i,e,r,u,f):nc(i)?null:(s=tc(i,u),s!==null)?null:i===null?od(n,t,e):hd(n,t,i,e,r,u,f)},ld=function(n){if(n&&af(n)){var t=os();return l(t,dl(t,"uri",n.uri))}},ad=function(n,t){if(t){var r=ou(t),i=b(r);if(i)return id(i)}},vd=function(n,i,r){var u=r.contentType=r.contentType||nr(gu);return u&&u.mediaType===gu?wf(ld(i)):t};r.xmlHandler=li(ad,vd,gu,ci);var gl="a",ni=sr+"2005/Atom",br=sr+"2007/app",na=ai+"/edit-media/",ta=ai+"/mediaresource/",ia=ai+"/relatedlinks/",ra=["application/atom+xml","application/atomsvc+xml","application/xml"],ua=ra[0],yd=[ni,br,pi,hr],pd={SyndicationAuthorEmail:"author/email",SyndicationAuthorName:"author/name",SyndicationAuthorUri:"author/uri",SyndicationContributorEmail:"contributor/email",Synd
 icationContributorName:"contributor/name",SyndicationContributorUri:"contributor/uri",SyndicationPublished:"published",SyndicationRights:"rights",SyndicationSummary:"summary",SyndicationTitle:"title",SyndicationUpdated:"updated"},wd=function(n){return pd[n]||n},kr=function(n){return!er(yd,n)},fa=function(n,t,i,r,u){var f;if(u=u||"",f=n["FC_TargetPath"+u],!f)return null;var e=n["FC_SourcePath"+u],s=wd(f),o=r?r+(e?"/"+e:""):e,l=o&&tg(i,t,o),h=n["FC_NsUri"+u]||null,c=n["FC_NsPrefix"+u]||null,a=n["FC_KeepInContent"+u]||"";return f!==s&&(h=ni,c=gl),{contentKind:n["FC_ContentKind"+u],keepInContent:a.toLowerCase()==="true",nsPrefix:c,nsURI:h,propertyPath:o,propertyType:l,entryPath:s}},ea=function(n,t,i){for(var c=[],l,r,f,u,e;n;){for(l=n.FC_SourcePath,r=fa(n,n,t),r&&i(r),f=n.property||[],u=0,e=f.length;u<e;u++)for(var o=f[u],s=0,h="";r=fa(o,n,t,o.name,h);)i(r),s++,h="_"+s;n=bt(n.baseType,t)}return c},tf=function(n){var t=[];return wi(n,function(n){var i=u(n);kr(i)&&t.push(gt(n,!0))}),t},oa
 =function(n){return pr(n,!0)},sa=function(n,t,i){var e=u(n),r=f(n);if(e===br&&r==="service")return cg(n,t);if(e===ni){if(r==="feed")return bd(n,t,i);if(r==="entry")return va(n,t,i)}},ha=function(n,t){var r=[],i={extensions:r};return wi(n,function(e){var o=f(e),s=u(e),h=ki(e);if(s===null){if(o==="title"||o==="metadata"){i[o]=h;return}if(o==="target"){i.target=c(h,rt(n,t));return}}kr(s)&&r.push(gt(e,!0))}),i},ca=function(n,t,i){var r=i.actions=i.actions||[];r.push(ha(n,t))},la=function(n,t,i){var r=i.functions=i.functions||[];r.push(ha(n,t))},bd=function(n,t,i){var o=tf(n),r={feed_extensions:o},s=[],e={__metadata:r,results:s};return t=rt(n,t),p(n,function(n){var l=u(n),h=f(n);if(l===nt){if(h==="count"){e.__count=parseInt(k(n),10);return}if(h==="action"){ca(n,t,r);return}if(h==="function"){la(n,t,r);return}}if(kr(l)){o.push(pr(n));return}if(h==="entry"){s.push(va(n,t,i));return}if(h==="link"){kd(n,e,t);return}if(h==="id"){r.uri=c(k(n),t),r.uri_extensions=tf(n);return}if(h==="title"){r.
 title=k(n)||"",r.title_extensions=tf(n);return}}),e},kd=function(n,t,i){var r=aa(n,i),f=r.href,e=r.rel,o=r.extensions,u=t.__metadata;if(e==="next"){t.__next=f,u.next_extensions=o;return}if(e==="self"){u.self=f,u.self_extensions=o;return}},aa=function(n,t){t=rt(n,t);var r=[],i={extensions:r,baseURI:t};if(wi(n,function(n){var s=u(n),e=f(n),o=n.value;if(e==="href"){i.href=c(o,t);return}if(e==="type"||e==="rel"){i[e]=o;return}kr(s)&&r.push(gt(n,!0))}),!i.href)throw{error:"href attribute missing on link element",element:n};return i},dd=function(n,i){if(n.indexOf("/")===-1)return i[n];for(var u=n.split("/"),r=0,f=u.length;r<f;r++){if(i===null)return t;if(i=i[u[r]],i===t)return i}return i},gd=function(n,i,r,u){var o,s,f,h,e;if(n.indexOf("/")===-1)i[n]=r,o=n;else{for(s=n.split("/"),f=0,h=s.length-1;f<h;f++){if(e=i[s[f]],e===t)e={},i[s[f]]=e;else if(e===null)return;i=e}o=s[f],i[o]=r}if(u){var c=i.__metadata=i.__metadata||{},l=c.properties=c.properties||{},a=l[o]=l[o]||{};a.type=u}},ng=functi
 on(n,t,i){var e=n.propertyPath,r,u,f;n.keepInContent||dd(e,i)===null||(r=nw(t,n.nsURI,n.entryPath),r)&&(u=n.propertyType,f=n.contentKind==="xhtml"?ew(r):wl(r,u||"Edm.String"),gd(e,i,f,u))},tg=function(n,t,i){for(var s=i.split("/"),u,h,f,e,o,r;t;){for(f=t,u=0,h=s.length;u<h;u++){if(e=f.property,!e)break;if(o=wt(e,s[u]),!o)break;if(r=o.type,!r||fe(r))return r||null;if(f=gi(r,n),!f)return null}t=bt(t.baseType,n)}return null},va=function(n,t,i){var r={},e={__metadata:r},o=st(n,"etag",nt),s;return o&&(r.etag=o),t=rt(n,t),p(n,function(n){var s=u(n),o=f(n);if(s===ni){if(o==="id"){ig(n,r,t);return}if(o==="category"){rg(n,r);return}if(o==="content"){ug(n,e,r,t);return}if(o==="link"){fg(n,e,r,t,i);return}return}if(s===nt){if(o==="properties"){wa(n,e,r);return}if(o==="action"){ca(n,t,r);return}if(o==="function"){la(n,t,r);return}}}),s=bt(r.type,i),ea(s,i,function(t){ng(t,n,e)}),e},ig=function(n,t,i){t.uri=c(k(n),rt(n,i)),t.uri_extensions=tf(n)},rg=function(n,t){if(st(n,"scheme")===cl){if(t.typ
 e)throw{message:"Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry",element:n};var i=[];wi(n,function(n){var t=u(n),r=f(n);if(!t){r!=="scheme"&&r!=="term"&&i.push(gt(n,!0));return}kr(t)&&i.push(gt(n,!0))}),t.type=st(n,"term"),t.type_extensions=i}},ug=function(n,t,i,r){var e=st(n,"src"),o=st(n,"type");if(e){if(!o)throw{message:"Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",element:n};i.media_src=c(e,rt(n,r)),i.content_type=o}p(n,function(r){if(e)throw{message:"Invalid AtomPub document: content element must not have child elements if the src attribute is specified",element:n};u(r)===nt&&f(r)==="properties"&&wa(r,t,i)})},fg=function(n,t,i,r,u){var f=aa(n,r),e=f.rel,s=f.href,o=f.extensions;if(e==="self"){i.self=s,i.self_link_extensions=o;return}if(e==="edit"){i.edit=s,i.edit_link_extensions=o;return}if(e==="edit-media"){i.edit_media=f.href,i.edit_media_extensio
 ns=o,pa(f,i);return}if(e.indexOf(na)===0){sg(f,t,i);return}if(e.indexOf(ta)===0){hg(f,t,i);return}if(e.indexOf(we)===0){og(n,f,t,i,u);return}if(e.indexOf(ia)===0){eg(f,i);return}},eg=function(n,t){var r=n.rel.substring(ia.length),i;t.properties=t.properties||{},i=t.properties[r]=t.properties[r]||{},i.associationuri=n.href,i.associationuri_extensions=n.extensions},og=function(n,t,i,r,u){var e,o=b(n,nt,"inline"),s,h,f,c;o?(s=b(o),h=rt(o,t.baseURI),e=s?sa(s,h,u):null):e={__deferred:{uri:t.href}},f=t.rel.substring(we.length),i[f]=e,r.properties=r.properties||{},c=r.properties[f]=r.properties[f]||{},c.extensions=t.extensions},sg=function(n,t,i){var o=n.rel.substring(na.length),f=ya(o,t,i),r=f.value,u=f.metadata,e=n.href;r.edit_media=e,r.content_type=n.type,u.edit_media_extensions=n.extensions,r.media_src=r.media_src||e,u.media_src_extensions=u.media_src_extensions||[],pa(n,r)},hg=function(n,t,i){var f=n.rel.substring(ta.length),r=ya(f,t,i),u=r.value,e=r.metadata;u.media_src=n.href,e.medi
 a_src_extensions=n.extensions,u.content_type=n.type},ya=function(n,t,i){i.properties=i.properties||{};var u=i.properties[n],r=t[n]&&t[n].__mediaresource;return r||(r={},t[n]={__mediaresource:r},i.properties[n]=u={}),{value:r,metadata:u}},pa=function(n,t){for(var r=n.extensions,i=0,u=r.length;i<u;i++)if(r[i].namespaceURI===nt&&r[i].name==="etag"){t.media_etag=r[i].value,r.splice(i,1);return}},wa=function(n,t,i){p(n,function(n){var r=yl(n),u,f;r&&(u=r.name,f=i.properties=i.properties||{},f[u]=r.metadata,t[u]=r.value)})},cg=function(n,t){var i=[],r=[];if(t=rt(n,t),p(n,function(n){if(u(n)===br&&f(n)==="workspace"){i.push(lg(n,t));return}r.push(pr(n))}),i.length===0)throw{message:"Invalid AtomPub service document: No workspace element found.",element:n};return{workspaces:i,extensions:r}},lg=function(n,i){var e=[],o=[],r;return i=rt(n,i),p(n,function(n){var s=u(n),h=f(n);if(s===ni&&h==="title"){if(r!==t)throw{message:"Invalid AtomPub service document: workspace has more than one child tit
 le element",element:n};r=k(n);return}if(s===br){h==="collection"&&e.push(ag(n,i));return}o.push(oa(n))}),{title:r||"",collections:e,extensions:o}},ag=function(n,i){var r=st(n,"href"),o,e;if(!r)throw{message:"Invalid AtomPub service document: collection has no href attribute",element:n};if(i=rt(n,i),r=c(r,rt(n,i)),o=[],p(n,function(i){var r=u(i),s=f(i);if(r===ni){if(s==="title"){if(e!==t)throw{message:"Invalid AtomPub service document: collection has more than one child title element",element:i};e=k(i)}return}r!==br&&o.push(oa(n))}),!e)throw{message:"Invalid AtomPub service document: collection has no title element",element:n};return{title:e,href:r,extensions:o}},ti=function(n,t,i){return lr(n,ni,pt(gl,t),i)},tr=function(n,t,i){return si(n,null,t,i)},vg=function(n){var t,e,i,o,r;if(n.childNodes.length>0)return!1;for(t=!0,e=n.attributes,i=0,o=e.length;i<o&&t;i++)r=e[i],t=t&&bp(r)||u(r)==nt&&f(r)==="type";return t},yg=function(n,t,i,r,u){var s=null,e=null,f=null,o="",h;return i!=="defe
 rred"?(s=tr(n,"type","application/atom+xml;type="+i),e=kl(n,"inline"),r&&(o=r.__metadata&&r.__metadata.uri||"",f=ba(n,r,u)||no(n,r,u),l(e,f.element))):o=r.__deferred.uri,h=ti(n,"link",[tr(n,"href",o),tr(n,"rel",c(t,we)),s,e]),at(h,f?f.dsv:"1.0")},pg=function(n,t,i,r,u,f){var e,o;return nc(i)?null:(e=ge(n,t,i,r,u,f),e||(o=tc(i,u),e=yg(n,t,o,i,f)),e)},wg=function(n,t,i,r){var u=fs(i,lt,r.propertyPath),l=u&&bi(u,"null",nt),o,s="1.0",f,e,h,c;if(l&&l.value==="true")return s;if(u&&(o=k(u)||"",!r.keepInContent))for(s="2.0",f=u.parentNode,e=f,f.removeChild(u);e!==i&&vg(e);)f=e.parentNode,f.removeChild(e),e=f;return(h=fw(n,t,r.nsURI,r.nsPrefix,r.entryPath),h.nodeType===2)?(h.value=o,s):(c=r.contentKind,su(h,[c&&si(n,null,"type",c),c==="xhtml"?rw(n,o):o]),s)},no=function(n,t,i){var e=t.__metadata||{},b=e.properties||{},y=e.etag,p=e.uri,s=e.type,o=bt(s,i),h=kl(n,"properties"),c=ti(n,"entry",[ti(n,"author",ti(n,"name")),y&&de(n,"etag",y),p&&ti(n,"id",p),s&&ti(n,"category",[tr(n,"term",s),tr(n,"
 scheme",cl)]),ti(n,"content",[tr(n,"type","application/xml"),h])]),f="1.0",r,v,w;for(r in t)if(r!=="__metadata"){var k=b[r]||{},d=o&&(wt(o.property,r)||wt(o.navigationProperty,r)),a=pg(n,r,t[r],k,d,i);a&&(v=a.element,w=u(v)===ni?c:h,l(w,v),f=ct(f,a.dsv))}return ea(o,i,function(t){var i=wg(n,c,h,t);f=ct(f,i)}),at(c,f)},ba=function(n,t,i){var f=e(t)?t:t.results,r,o,u,h,s;if(!f)return null;for(r="1.0",o=ti(n,"feed"),u=0,h=f.length;u<h;u++)s=no(n,f[u],i),l(o,s.element),r=ct(r,s.dsv);return at(o,r)},bg=function(n,t){var u,i,r,f;return n&&(u=vr(n)&&ba||af(n)&&no,u&&(i=os(),r=u(i,n,t),r))?(f=r.element,su(f,[ss(i,nt,be),ss(i,lt,ll)]),at(l(i,f),r.dsv)):null},kg=function(n,t,i){if(t){var u=ou(t),r=b(u);if(r)return sa(r,null,i.metadata)}},dg=function(n,t,i){var u=i.contentType=i.contentType||nr(ua),r;if(u&&u.mediaType===ua&&(r=bg(t,i.metadata),r))return i.dataServiceVersion=ct(i.dataServiceVersion||"1.0",r.dsv),wf(r.element)};r.atomHandler=li(kg,dg,ra.join(","),ci);var i=function(n,t,i,r){retu
 rn{attributes:n,elements:t,text:i||!1,ns:r}},tt={elements:{Annotations:i(["Target","Qualifier"],["TypeAnnotation*","ValueAnnotation*"]),Association:i(["Name"],["End*","ReferentialConstraint","TypeAnnotation*","ValueAnnotation*"]),AssociationSet:i(["Name","Association"],["End*","TypeAnnotation*","ValueAnnotation*"]),Binary:i(null,null,!0),Bool:i(null,null,!0),Collection:i(null,["String*","Int*","Float*","Decimal*","Bool*","DateTime*","DateTimeOffset*","Guid*","Binary*","Time*","Collection*","Record*"]),CollectionType:i(["ElementType","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"],["CollectionType","ReferenceType","RowType","TypeRef"]),ComplexType:i(["Name","BaseType","Abstract"],["Property*","TypeAnnotation*","ValueAnnotation*"]),DateTime:i(null,null,!0),DateTimeOffset:i(null,null,!0),Decimal:i(null,null,!0),DefiningExpression:i(null,null,!0),Dependent:i(["Role"],["PropertyRef*"]),Documentation:i(null,null,!0),End:i(["Type","Role
 ","Multiplicity","EntitySet"],["OnDelete"]),EntityContainer:i(["Name","Extends"],["EntitySet*","AssociationSet*","FunctionImport*","TypeAnnotation*","ValueAnnotation*"]),EntitySet:i(["Name","EntityType"],["TypeAnnotation*","ValueAnnotation*"]),EntityType:i(["Name","BaseType","Abstract","OpenType"],["Key","Property*","NavigationProperty*","TypeAnnotation*","ValueAnnotation*"]),EnumType:i(["Name","UnderlyingType","IsFlags"],["Member*"]),Float:i(null,null,!0),Function:i(["Name","ReturnType"],["Parameter*","DefiningExpression","ReturnType","TypeAnnotation*","ValueAnnotation*"]),FunctionImport:i(["Name","ReturnType","EntitySet","IsSideEffecting","IsComposable","IsBindable","EntitySetPath"],["Parameter*","ReturnType","TypeAnnotation*","ValueAnnotation*"]),Guid:i(null,null,!0),Int:i(null,null,!0),Key:i(null,["PropertyRef*"]),LabeledElement:i(["Name"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Nu
 ll"]),Member:i(["Name","Value"]),NavigationProperty:i(["Name","Relationship","ToRole","FromRole","ContainsTarget"],["TypeAnnotation*","ValueAnnotation*"]),Null:i(null,null),OnDelete:i(["Action"]),Path:i(null,null,!0),Parameter:i(["Name","Type","Mode","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","SRID"],["CollectionType","ReferenceType","RowType","TypeRef","TypeAnnotation*","ValueAnnotation*"]),Principal:i(["Role"],["PropertyRef*"]),Property:i(["Name","Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","CollectionKind","SRID"],["CollectionType","ReferenceType","RowType","TypeAnnotation*","ValueAnnotation*"]),PropertyRef:i(["Name"]),PropertyValue:i(["Property","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time
 ","Collection","Record","LabeledElement","Null"]),ReferenceType:i(["Type"]),ReferentialConstraint:i(null,["Principal","Dependent"]),ReturnType:i(["ReturnType","Type","EntitySet"],["CollectionType","ReferenceType","RowType"]),RowType:i(["Property*"]),String:i(null,null,!0),Schema:i(["Namespace","Alias"],["Using*","EntityContainer*","EntityType*","Association*","ComplexType*","Function*","ValueTerm*","Annotations*"]),Time:i(null,null,!0),TypeAnnotation:i(["Term","Qualifier"],["PropertyValue*"]),TypeRef:i(["Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"]),Using:i(["Namespace","Alias"]),ValueAnnotation:i(["Term","Qualifier","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ValueTerm:i(["Name","Type"],["TypeAnnotation*","ValueAnnotation
 *"]),Edmx:i(["Version"],["DataServices","Reference*","AnnotationsReference*"],!1,nf),DataServices:i(null,["Schema*"],!1,nf)}},ka=["m:FC_ContentKind","m:FC_KeepInContent","m:FC_NsPrefix","m:FC_NsUri","m:FC_SourcePath","m:FC_TargetPath"];tt.elements.Property.attributes=tt.elements.Property.attributes.concat(ka),tt.elements.EntityType.attributes=tt.elements.EntityType.attributes.concat(ka),tt.elements.Edmx={attributes:["Version"],elements:["DataServices"],ns:nf},tt.elements.DataServices={elements:["Schema*"],ns:nf},tt.elements.EntityContainer.attributes.push("m:IsDefaultEntityContainer"),tt.elements.Property.attributes.push("m:MimeType"),tt.elements.FunctionImport.attributes.push("m:HttpMethod"),tt.elements.FunctionImport.attributes.push("m:IsAlwaysBindable"),tt.elements.EntityType.attributes.push("m:HasStream"),tt.elements.DataServices.attributes=["m:DataServiceVersion","m:MaxDataServiceVersion"];var da=function(n){if(!n)return n;if(n.length>1){var t=n.substr(0,2);return t===t.toUpper
 Case()?n:n.charAt(0).toLowerCase()+n.substr(1)}return n.charAt(0).toLowerCase()},gg=function(n,t){var r,u,e,i,f,o;if(t==="Documentation")return{isArray:!0,propertyName:"documentation"};if(r=n.elements,!r)return null;for(u=0,e=r.length;u<e;u++)if(i=r[u],f=!1,i.charAt(i.length-1)==="*"&&(f=!0,i=i.substr(0,i.length-1)),t===i)return o=da(i),{isArray:f,propertyName:o};return null},nn=/^(m:FC_.*)_[0-9]+$/,ga=function(n){return n===vk||n===yk||n===pk||n===wk||n===bk||n===kk},to=function(n){var o=f(n),e=u(n),i=tt.elements[o];if(!i)return null;if(i.ns){if(e!==i.ns)return null}else if(!ga(e))return null;var t={},r=[],s=i.attributes||[];return wi(n,function(n){var c=f(n),e=u(n),l=n.value,i,o,h;e!==hr&&(i=null,o=!1,ga(e)||e===null?i="":e===nt&&(i="m:"),i!==null&&(i+=c,h=nn.exec(i),h&&(i=h[1]),er(s,i)&&(o=!0,t[da(c)]=l)),o||r.push(gt(n)))}),p(n,function(n){var o=f(n),u=gg(i,o),e;u?u.isArray?(e=t[u.propertyName],e||(e=[],t[u.propertyName]=e),e.push(to(n))):t[u.propertyName]=to(n):r.push(pr(n))}),
 i.text&&(t.text=k(n)),r.length&&(t.extensions=r),t},nv=function(n,i){var r=ou(i),u=b(r);return to(u)||t};r.metadataHandler=li(nv,null,gu,ci);var tv="o",io="f",iv="p",rv="c",uv="s",fv="l",tn="odata",ii=tn+".",rn="@"+ii+"bind",ro=ii+"metadata",ev=ii+"navigationLinkUrl",ir=ii+"type",rf={readLink:"self",editLink:"edit",nextLink:"__next",mediaReadLink:"media_src",mediaEditLink:"edit_media",mediaContentType:"content_type",mediaETag:"media_etag",count:"__count",media_src:"mediaReadLink",edit_media:"mediaEditLink",content_type:"mediaContentType",media_etag:"mediaETag",url:"uri"},h={metadata:"odata.metadata",count:"odata.count",next:"odata.nextLink",id:"odata.id",etag:"odata.etag",read:"odata.readLink",edit:"odata.editLink",mediaRead:"odata.mediaReadLink",mediaEdit:"odata.mediaEditLink",mediaEtag:"odata.mediaETag",mediaContentType:"odata.mediaContentType",actions:"odata.actions",functions:"odata.functions",navigationUrl:"odata.navigationLinkUrl",associationUrl:"odata.associationLinkUrl",type
 :"odata.type"},un=function(n){if(n.indexOf(".")>0){var t=n.indexOf("@"),r=t>-1?n.substring(0,t):null,i=n.substring(t+1);return{target:r,name:i,isOData:i.indexOf(ii)===0}}return null},uo=function(n,t,i,r,u){return d(t)&&t[ir]||i&&i[n+"@"+ir]||r&&r.type||bw(r,u)||null},fo=function(n,t){return t?wt(t.property,n)||wt(t.navigationProperty,n):null},ov=function(n){return d(n)&&ii+"id"in n},fn=function(n,t,i){if(!!t[n+"@"+ev]||i&&i.relationship)return!0;var r=e(t[n])?t[n][0]:t[n];return ov(r)},eo=function(n){return fe(n)||re(n)||ue(n)},ri=function(n,t,i,r,u){var f,e;for(f in n)if(f.indexOf(".")>0&&f.charAt(0)!=="#"&&(e=un(f),e)){var c=e.name,o=e.target,s=null,h=null;o&&(s=fo(o,r),h=uo(o,n[o],n,s,u)),e.isOData?en(c,o,h,n[f],n,t,i):t[f]=n[f]}return t},en=function(n,t,i,r,u,f,e){var o=n.substring(ii.length);switch(o){case"navigationLinkUrl":cn(o,t,i,r,u,f,e);return;case"nextLink":case"count":sn(o,t,r,f,e);return;case"mediaReadLink":case"mediaEditLink":case"mediaContentType":case"mediaETag":hn(
 o,t,i,r,f,e);return;default:on(o,t,r,f,e);return}},on=function(n,t,i,r,u){var f=r.__metadata=r.__metadata||{},e=rf[n]||n,s,o;if(n==="editLink"){f.uri=c(i,u),f[e]=f.uri;return}if((n==="readLink"||n==="associationLinkUrl")&&(i=c(i,u)),t){if(s=f.properties=f.properties||{},o=s[t]=s[t]||{},n==="type"){o[e]=o[e]||i;return}o[e]=i;return}f[e]=i},sn=function(n,t,i,r,u){var f=rf[n],e=t?r[t]:r;e[f]=n==="nextLink"?c(i,u):i},hn=function(n,t,i,r,u,f){var e=u.__metadata=u.__metadata||{},h=rf[n],o,s;if((n==="mediaReadLink"||n==="mediaEditLink")&&(r=c(r,f)),t){o=e.properties=e.properties||{},s=o[t]=o[t]||{},s.type=s.type||i,u.__metadata=e,u[t]=u[t]||{__mediaresource:{}},u[t].__mediaresource[h]=r;return}e[h]=r},cn=function(n,t,i,r,u,f,e){var s=f.__metadata=f.__metadata||{},h=s.properties=s.properties||{},o=h[t]=h[t]||{},l=c(r,e);if(u.hasOwnProperty(t)){o.navigationLinkUrl=l;return}f[t]={__deferred:{uri:l}},o.type=o.type||i},oo=function(n,t,i,r,u,f,o){if(typeof n=="string")return ln(n,t,o);if(!eo(t))
 {if(e(n))return sv(n,t,i,r,f,o);if(d(n))return an(n,t,i,r,f,o)}return n},ln=function(n,t,i){switch(t){case au:return ce(n);case cu:return wu(n,!1);case lu:return he(n,!1)}return i?wu(n,!0)||he(n,!0)||n:n},sv=function(n,t,i,r,u,f){for(var a=vu(t),o=[],h=[],e=0,c=n.length;e<c;e++){var s=uo(null,n[e])||a,l={type:s},v=oo(n[e],s,l,r,null,u,f);eo(s)||pu(n[e])||o.push(l),h.push(v)}return o.length>0&&(i.elements=o),{__metadata:{type:t},results:h}},an=function(n,t,i,r,u,f){var e=uf(n,{type:t},r,u,f),o=e.__metadata,s=o.properties;return s&&(i.properties=s,delete o.properties),e},vn=function(n,t,i,r,u){return e(n)?cv(n,t,i,r,u):d(n)?uf(n,t,i,r,u):null},uf=function(n,i,r,u,f){var d,v,g,o,y,h,c,nt;i=i||{};var l=n[ir]||i.type||null,s=bt(l,u),k=!0;s||(k=!1,s=gi(l,u));var p={type:l},a={__metadata:p},w={},e;if(k&&s&&i.entitySet&&i.contentTypeOdata=="minimalmetadata"){for(d=r.substring(0,r.lastIndexOf("$metadata")),e=null,s.key||(e=s);!!e&&!e.key&&e.baseType;)e=bt(e.baseType,u);(s.key||!!e&&e.key)&&(
 v=s.key?lv(n,s):lv(n,e),v&&(g={key:v,entitySet:i.entitySet,functionImport:i.functionImport,containerName:i.containerName},yn(n,g,l,d,s,e)))}for(o in n)if(o.indexOf("#")===0)hv(o.substring(1),n[o],a,r,u);else if(o.indexOf(".")===-1){for(p.properties||(p.properties=w),y=n[o],h=h=fo(o,s),e=s;!!s&&h===null&&e.baseType;)e=bt(e.baseType,u),h=h=fo(o,e);var tt=fn(o,n,h),b=uo(o,y,n,h,u),it=w[o]=w[o]||{type:b};tt?(c={},i.entitySet!==t&&(nt=kw(h,i.entitySet.name,u),c=dw(nt,u)),c.contentTypeOdata=i.contentTypeOdata,c.kind=i.kind,c.type=b,a[o]=vn(y,c,r,u,f)):a[o]=oo(y,b,it,r,h,u,f)}return ri(n,a,r,s,u)},hv=function(n,t,i,r,u){var f,s,g,nt;if(n&&(e(t)||d(t))){var l=!1,h=n.lastIndexOf("."),a=n.substring(h+1),v=h>-1?n.substring(0,h):"",y=a===n||v.indexOf(".")===-1?ic(u):rc(v,u);y&&(f=ww(y.functionImport,a),f&&!!f.isSideEffecting&&(l=!se(f.isSideEffecting)));for(var p=i.__metadata,w=l?"functions":"actions",tt=c(n,r),b=e(t)?t:[t],o=0,k=b.length;o<k;o++)s=b[o],s&&(g=p[w]=p[w]||[],nt={metadata:tt,title
 :s.title,target:c(s.target,r)},g.push(nt))}},cv=function(n,t,i,r,u){for(var h=e(n)?n:n.value,c=[],l,f,s,o=0,a=h.length;o<a;o++)l=uf(h[o],t,i,r,u),c.push(l);if(f={results:c},d(n)){for(s in n)s.indexOf("#")===0&&(f.__metadata=f.__metadata||{},hv(s.substring(1),n[s],f,i,r));f=ri(n,f,i)}return f},lv=function(n,t){var r,i=t.key.propertyRef,f,e,u;if(r="(",i.length==1)f=wt(t.property,i[0].name).type,r+=so(n[i[0].name],f);else for(e=!0,u=0;u<i.length;u++)e?e=!1:r+=",",f=wt(t.property,i[u].name).type,r+=i[u].name+"="+so(n[i[u].name],f);return r+=")"},yn=function(n,t,i,r,u,f){var o=n[h.id]||n[h.read]||n[h.edit]||t.entitySet.name+t.key,e;n[h.id]=r+o,n[h.edit]||(n[h.edit]=t.entitySet.name+t.key,t.entitySet.entityType!=i&&(n[h.edit]+="/"+i)),n[h.read]=n[h.read]||n[h.edit],n[h.etag]||(e=pn(n,u,f),!e||(n[h.etag]=e)),dn(n,u,f),wn(n,u,f),kn(n,t)},pn=function(n,t,i){for(var u="",f,r=0;t.property&&r<t.property.length;r++)f=t.property[r],u=av(n,u,f);if(i)for(r=0;i.property&&r<i.property.length;r++)f=i.
 property[r],u=av(n,u,f);return u.length>0?u+'"':null},av=function(n,t,i){return i.concurrencyMode=="Fixed"&&(t+=t.length>0?",":'W/"',t+=n[i.name]!==null?so(n[i.name],i.type):"null"),t},wn=function(n,i,r){for(var s="@odata.navigationLinkUrl",c="@odata.associationLinkUrl",u,e,o,f=0;i.navigationProperty&&f<i.navigationProperty.length;f++)u=i.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u));if(r&&r.navigationProperty)for(f=0;f<r.navigationProperty.length;f++)u=r.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u))},so=function(n,t){n=""+bn(n,t),n=encodeURIComponent(n.replace("'","''"));switch(t){case"Edm.Binary":return"X'"+n+"'";case"Edm.DateTime":return"datetime'"+n+"'";case"Edm.DateTimeOffset":return"datetimeoffset'"+n+"'";case"Edm.Decimal":return n+"M";case"Edm.Guid":return"guid'"+n+"'
 ";case"Edm.Int64":return n+"L";case"Edm.Float":return n+"f";case"Edm.Double":return n+"D";case"Edm.Geography":return"geography'"+n+"'";case"Edm.Geometry":return"geometry'"+n+"'";case"Edm.Time":return"time'"+n+"'";case"Edm.String":return"'"+n+"'";default:return n}},bn=function(n,t){switch(t){case"Edm.Binary":return cp(n);default:return n}},kn=function(n,i){for(var u=i.functionImport||[],f,r=0;r<u.length;r++)u[r].isBindable&&u[r].parameter[0]&&u[r].parameter[0].type==i.entitySet.entityType&&(f="#"+i.containerName+"."+u[r].name,n[f]==t&&(n[f]={title:u[r].name,target:n[h.edit]+"/"+u[r].name}))},dn=function(n,t,i){(t.hasStream||i&&i.hasStream)&&(n[h.mediaEdit]=n[h.mediaEdit]||n[h.mediaEdit]+"/$value",n[h.mediaRead]=n[h.mediaRead]||n[h.mediaEdit])},gn=function(n,t,i,r){var u={type:t},f=oo(n.value,t,u,i,null,null,r);return ri(n,{__metadata:u,value:f},i)},ntt=function(n,t,i,r,u){var f={},e=sv(n.value,t,f,i,r,u);return g(e.__metadata,f),ri(n,e,i)},ttt=function(n,t){var r=n.value,u,i,f,o;if(!
 e(r))return vv(n,t);for(u=[],i=0,f=r.length;i<f;i++)u.push(vv(r[i],t));return o={results:u},ri(n,o,t)},vv=function(n,t){var i={uri:c(n.url,t)},u,r;return i=ri(n,i,t),u=i.__metadata||{},r=u.properties||{},ff(r.url),ru(r,"url","uri"),i},ff=function(n){n&&delete n.type},itt=function(n,t){var o=n.value,s=[],h=ri(n,{collections:s},t),e=h.__metadata||{},i=e.properties||{},u,l,f,r;for(ff(i.value),ru(i,"value","collections"),u=0,l=o.length;u<l;u++)f=o[u],r={title:f.name,href:c(f.url,t)},r=ri(f,r,t),e=r.__metadata||{},i=e.properties||{},ff(i.name),ff(i.url),ru(i,"name","title"),ru(i,"url","href"),s.push(r);return{workspaces:[h]}},ui=function(n,t){return{kind:n,type:t||null}},rtt=function(n,t,i){var f=n[ro],s,v,o,y,l,r,p,h,c,w,b,u,k;if(!f||typeof f!="string")return null;if(s=f.lastIndexOf("#"),s===-1)return ui(uv);if(v=f.indexOf("@Element",s),o=v-1,o<0&&(o=f.indexOf("?",s),o===-1&&(o=f.length)),y=f.substring(s+1,o),y.indexOf("/$links/")>0)return ui(fv);if(l=y.split("/"),l.length>=0){if(r=l[0]
 ,p=l[1],eo(r))return ui(iv,r);if(yu(r))return ui(rv,r);if(h=p,!p){var d=r.lastIndexOf("."),g=r.substring(d+1),a=g===r?ic(t):rc(r.substring(0,d),t);a&&(c=pw(a.entitySet,g),w=a.functionImport,b=a.name,h=!c?null:c.entityType)}return v>0?(u=ui(tv,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):h?(u=ui(io,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):e(n.value)&&!gi(r,t)&&(k=n.value[0],!pu(k)&&(ov(k)||!i))?ui(io,null):ui(tv,r)}return null},utt=function(n,t,i,r,u){var e,f,o;if(!d(n))return n;if(u=u||"minimalmetadata",e=n[ro],f=rtt(n,t,r),ot(f)&&(f.contentTypeOdata=u),o=null,f){delete n[ro],o=f.type;switch(f.kind){case io:return cv(n,f,e,t,i);case rv:return ntt(n,o,e,t,i);case iv:return gn(n,o,e,i);case uv:return itt(n,e);case fv:return ttt(n,e)}}return uf(n,f,e,t,i)},yv=["type","etag","media_src","edit_media","content_type","media_etag"],pv=function(n,t){var u=/\/\$links\//,i={},r=n.__metadata,f=t&&u.test(t.request.requestUri);return ho(n,r&&r.properties,i,f),i},ftt=fu
 nction(n,t){var i,u,r,f;if(n)for(i=0,u=yv.length;i<u;i++)r=yv[i],f=ii+(rf[r]||r),dr(f,null,n[r],t)},ho=function(n,t,i,r){var u,f;for(u in n)f=n[u],u==="__metadata"?ftt(f,i):u.indexOf(".")===-1?r&&u==="uri"?ott(f,i):ett(u,f,t,i,r):i[u]=f},ett=function(n,i,r,u){var e=r&&r[n]||{properties:t,type:t},f=hs(i,e);if(pu(i)||!i){dr(ir,n,f,u),u[n]=i;return}if(vr(i,f)||gh(i)){ctt(n,i,u);return}if(!f&&dh(i)){stt(n,i,u);return}if(kh(i,f)){vu(f)&&dr(ir,n,f,u),htt(n,i,u);return}u[n]={},dr(ir,null,f,u[n]),ho(i,e.properties,u[n])},ott=function(n,t){t.url=n},stt=function(n,t,i){dr(ev,n,t.__deferred.uri,i)},htt=function(n,t,i){i[n]=[];var r=e(t)?t:t.results;ho(r,null,i[n])},ctt=function(n,t,i){if(vr(t)){i[n]=[];for(var u=e(t)?t:t.results,r=0,f=u.length;r<f;r++)wv(n,u[r],!0,i);return}wv(n,t,!1,i)},wv=function(n,t,i,r){var f=t.__metadata&&t.__metadata.uri,u;if(f){ltt(n,f,i,r);return}if(u=pv(t),i){r[n].push(u);return}r[n]=u},ltt=function(n,t,i,r){var u=n+rn;if(i){r[u]=r[u]||[],r[u].push(t);return}r[u]=t},
 dr=function(n,i,r,u){r!==t&&(i?u[i+"@"+n]=r:u[n]=r)},bv="application/json",kv=nr(bv),dv=function(n){var r=[],t,i,u;for(t in n)for(i=0,u=n[t].length;i<u;i++)r.push(g({metadata:t},n[t][i]));return r},att=function(n,t,i,r){var c,f,l,u,o,s,v,e,h,a;if(n&&typeof n=="object")if(f=n.__metadata,f&&(f.actions&&(f.actions=dv(f.actions)),f.functions&&(f.functions=dv(f.functions)),c=f&&f.type),l=bt(c,t)||gi(c,t),l){if(o=l.property,o)for(s=0,v=o.length;s<v;s++)if(e=o[s],h=e.name,u=n[h],e.type==="Edm.DateTime"||e.type==="Edm.DateTimeOffset"){if(u){if(u=i(u),!u)throw{message:"Invalid date/time value"};n[h]=u}}else e.type==="Edm.Time"&&(n[h]=ce(u))}else if(r)for(a in n)u=n[a],typeof u=="string"&&(n[a]=i(u)||u);return n},gv=function(n){if(n){var t=n.properties.odata;return t==="nometadata"||t==="minimalmetadata"||t==="fullmetadata"}return!1},vtt=function(n,t){for(var u={collections:[]},r,e,i=0,f=n.EntitySets.length;i<f;i++)r=n.EntitySets[i],e={title:r,href:c(r,t)},u.collections.push(e);return{workspa
 ces:[u]}},ytt=/^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/,ptt=function(n){var t,i;return n<0?(t="-",n=-n):t="+",i=Math.floor(n/60),n=n-60*i,t+a(i,2)+":"+a(n,2)},wtt=function(n){var i=n&&ytt.exec(n),t,r,u;if(i&&(t=new Date(s(i[1])),i[2]&&(r=s(i[3]),i[2]==="-"&&(r=-r),u=t.getUTCMinutes(),t.setUTCMinutes(u-r),t.__edmType="Edm.DateTimeOffset",t.__offset=ptt(r)),!isNaN(t.valueOf())))return t},btt=function(t,i,r){var f=it(r.recognizeDates,t.recognizeDates),h=it(r.inferJsonLightFeedAsObject,t.inferJsonLightFeedAsObject),e=r.metadata,o=r.dataServiceVersion,s=wtt,u=typeof i=="string"?n.JSON.parse(i):i;if(ct("3.0",o)===o){if(gv(r.contentType))return utt(u,e,f,h,r.contentType.properties.odata);s=wu}return u=ib(u.d,function(n,t){return att(t,e,s,f)}),u=nit(u,r.dataServiceVersion),gtt(u,r.response.requestUri)},ny=function(t){var i,r=Date.prototype.toJSON;try{Date.prototype.toJSON=function(){return ph(this)},i=n.JSON.stringify(t,dtt)}finally{Date.prototype.toJSON=r}return i},ktt=function(n,i,r){var e=r.
 dataServiceVersion||"1.0",o=it(r.useJsonLight,n.useJsonLight),u=r.contentType=r.contentType||kv,f;return u&&u.mediaType===kv.mediaType?(f=i,o||gv(u))?(r.dataServiceVersion=ct(e,"3.0"),f=pv(i,r),ny(f)):(ct("3.0",e)===e&&(u.properties.odata="verbose",r.contentType=u),ny(f)):t},dtt=function(n,t){return t&&t.__edmType==="Edm.Time"?wh(t):t},gtt=function(n,t){var i=d(n)&&!n.__metadata&&e(n.EntitySets);return i?vtt(n,t):n},nit=function(n,t){return t&&t.lastIndexOf(";")===t.length-1&&(t=t.substr(0,t.length-1)),t&&t!=="1.0"||e(n)&&(n={results:n}),n},ef=li(btt,ktt,bv,ci);ef.recognizeDates=!1,ef.useJsonLight=!1,ef.inferJsonLightFeedAsObject=!1,r.jsonHandler=ef;var gr="multipart/mixed",tit=/^HTTP\/1\.\d (\d{3}) (.*)$/i,iit=/^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/,co=function(){return Math.floor((1+Math.random())*65536).toString(16).substr(1)},ty=function(n){return n+co()+"-"+co()+"-"+co()},iy=function(n){return n.handler.partHandler},ry=function(n){var t=n.boundaries;return t[t.length-1]},ri
 t=function(n,t,i){var r=i.contentType.properties.boundary;return{__batchResponses:uy(t,{boundaries:[r],handlerContext:i})}},uit=function(n,t,i){var r=i.contentType=i.contentType||nr(gr);if(r.mediaType===gr)return fit(t,i)},uy=function(n,t){var f="--"+ry(t),u,o,s,r,e,i;for(of(n,t,f),rr(n,t),u=[];o!=="--"&&t.position<n.length;){if(s=fy(n,t),r=nr(s["Content-Type"]),r&&r.mediaType===gr){t.boundaries.push(r.properties.boundary);try{e=uy(n,t)}catch(h){h.response=ey(n,t,f),e=[h]}u.push({__changeResponses:e}),t.boundaries.pop(),of(n,t,"--"+ry(t))}else{if(!r||r.mediaType!=="application/http")throw{message:"invalid MIME part type "};rr(n,t),i=ey(n,t,f);try{i.statusCode>=200&&i.statusCode<=299?iy(t.handlerContext).read(i,t.handlerContext):i={message:"HTTP request failed",response:i}}catch(h){i=h}u.push(i)}o=n.substr(t.position,2),rr(n,t)}return u},fy=function(n,t){var r={},i,u,f;do f=t.position,u=rr(n,t),i=iit.exec(u),i!==null?r[i[1]]=i[2]:t.position=f;while(u&&i);return oe(r),r},ey=function(n
 ,t,i){var o=t.position,r=tit.exec(rr(n,t)),u,f,e;return r?(u=r[1],f=r[2],e=fy(n,t),rr(n,t)):t.position=o,{statusCode:u,statusText:f,headers:e,body:of(n,t,"\r\n"+i)}},rr=function(n,t){return of(n,t,"\r\n")},of=function(n,t,i){var u=t.position||0,r=n.length;if(i){if(r=n.indexOf(i,u),r===-1)return null;t.position=r+i.length}else t.position=r;return n.substring(u,r)},fit=function(n,t){var o;if(!aw(n))throw{message:"Data is not a batch object."};for(var r=ty("batch_"),f=n.__batchRequests,u="",i=0,e=f.length;i<e;i++)u+=sf(r,!1)+oy(f[i],t);return u+=sf(r,!0),o=t.contentType.properties,o.boundary=r,u},sf=function(n,t){var i="\r\n--"+n;return t&&(i+="--"),i+"\r\n"},oy=function(n,t,i){var s=n.__changeRequests,r,f,o,h,u;if(e(s)){if(i)throw{message:"Not Supported: change set nested in other change set"};for(f=ty("changeset_"),r="Content-Type: "+gr+"; boundary="+f+"\r\n",o=0,h=s.length;o<h;o++)r+=sf(f,!1)+oy(s[o],t,!0);r+=sf(f,!0)}else r="Content-Type: application/http\r\nContent-Transfer-Encodi
 ng: binary\r\n\r\n",u=g({},t),u.handler=li,u.request=n,u.contentType=null,sc(n,iy(t),u),r+=eit(n);return r},eit=function(n){var t=(n.method?n.method:"GET")+" "+n.requestUri+" HTTP/1.1\r\n",i;for(i in n.headers)n.headers[i]&&(t=t+i+": "+n.headers[i]+"\r\n");return t+="\r\n",n.body&&(t+=n.body),t};r.batchHandler=li(rit,uit,gr,ci),lo=[r.jsonHandler,r.atomHandler,r.xmlHandler,r.textHandler],ao=function(n,t,i){for(var r=0,u=lo.length;r<u&&!lo[r][n](t,i);r++);if(r===u)throw{message:"no handler for data"};},r.defaultSuccess=function(t){n.alert(n.JSON.stringify(t))},r.defaultError=uu,r.defaultHandler={read:function(n,t){n&&ot(n.body)&&n.headers["Content-Type"]&&ao("read",n,t)},write:function(n,t){ao("write",n,t)},maxDataServiceVersion:ci,accept:"application/atomsvc+xml;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1"},r.defaultMetadata=[],r.read=function(n,t,i,u,f,e){var o;return o=n instanceof String||typeof n=="string"?{requestUri:n}:n,r.request(o,t,i,u
 ,f,e)},r.request=function(n,t,i,u,f,e){t=t||r.defaultSuccess,i=i||r.defaultError,u=u||r.defaultHandler,f=f||r.defaultHttpClient,e=e||r.defaultMetadata,n.recognizeDates=it(n.recognizeDates,r.jsonHandler.recognizeDates),n.callbackParameterName=it(n.callbackParameterName,r.defaultHttpClient.callbackParameterName),n.formatQueryString=it(n.formatQueryString,r.defaultHttpClient.formatQueryString),n.enableJsonpCallback=it(n.enableJsonpCallback,r.defaultHttpClient.enableJsonpCallback),n.useJsonLight=it(n.useJsonLight,r.jsonHandler.enableJsonpCallback),n.inferJsonLightFeedAsObject=it(n.inferJsonLightFeedAsObject,r.jsonHandler.inferJsonLightFeedAsObject);var o={metadata:e,recognizeDates:n.recognizeDates,callbackParameterName:n.callbackParameterName,formatQueryString:n.formatQueryString,enableJsonpCallback:n.enableJsonpCallback,useJsonLight:n.useJsonLight,inferJsonLightFeedAsObject:n.inferJsonLightFeedAsObject};try{return sc(n,u,o),lw(n,t,i,u,f,o)}catch(s){i(s)}},r.parseMetadata=function(n){re
 turn nv(null,n)},r.batchHandler.partHandler=r.defaultHandler;var ft=null,oit=function(){var t={v:this.valueOf(),t:"[object Date]"},n;for(n in this)t[n]=this[n];return t},sit=function(n,t){var r,i;if(t&&t.t==="[object Date]"){r=new Date(t.v);for(i in t)i!=="t"&&i!=="v"&&(r[i]=t[i]);t=r}return t},hf=function(n,t){return n.name+"#!#"+t},sy=function(n,t){return t.replace(n.name+"#!#","")},y=function(n){this.name=n};y.create=function(t){if(y.isSupported())return ft=ft||n.localStorage,new y(t);throw{message:"Web Storage not supported by the browser"};},y.isSupported=function(){return!!n.localStorage},y.prototype.add=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?o(r,{message:"key already exists",key:n}):u.addOrUpdate(n,t,i,r)},r)},y.prototype.addOrUpdate=function(i,r,u,f){var s,h,e;if(f=f||this.defaultError,i instanceof Array)f({message:"Array of keys not supported"});else{s=hf(this,i),h=Date.prototype.toJSON;try{e=r,e!==t&&(Date.prototype.toJSON=oit,e=n
 .JSON.stringify(r)),ft.setItem(s,e),o(u,i,r)}catch(c){c.code===22||c.number===2147942414?o(f,{name:"QUOTA_EXCEEDED_ERR",error:c}):o(f,c)}finally{Date.prototype.toJSON=h}}},y.prototype.clear=function(n,t){var i,r,u,f;t=t||this.defaultError;try{for(i=0,r=ft.length;r>0&&i<r;)u=ft.key(i),f=sy(this,u),u!==f?(ft.removeItem(u),r=ft.length):i++;o(n)}catch(e){o(t,e)}},y.prototype.close=function(){},y.prototype.contains=function(n,t,i){i=i||this.defaultError;try{var r=hf(this,n),u=ft.getItem(r);o(t,u!==null)}catch(f){o(i,f)}},y.prototype.defaultError=uu,y.prototype.getAllKeys=function(n,t){var r,i,e,u,f;t=t||this.defaultError,r=[];try{for(i=0,e=ft.length;i<e;i++)u=ft.key(i),f=sy(this,u),u!==f&&r.push(f);o(n,r)}catch(s){o(t,s)}},y.prototype.mechanism="dom",y.prototype.read=function(i,r,u){if(u=u||this.defaultError,i instanceof Array)u({message:"Array of keys not supported"});else try{var e=hf(this,i),f=ft.getItem(e);f=f!==null&&f!=="undefined"?n.JSON.parse(f,sit):t,o(r,i,f)}catch(s){o(u,s)}},y
 .prototype.remove=function(n,t,i){if(i=i||this.defaultError,n instanceof Array)i({message:"Batches not supported"});else try{var r=hf(this,n);ft.removeItem(r),o(t)}catch(u){o(i,u)}},y.prototype.update=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?u.addOrUpdate(n,t,i,r):o(r,{message:"key not found",key:n})},r)};var hy=n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB||n.indexedDB,hit=n.IDBKeyRange||n.webkitIDBKeyRange,cy=n.IDBTransaction||n.webkitIDBTransaction||{},ly=cy.READ_ONLY||"readonly",ur=cy.READ_WRITE||"readwrite",vt=function(n,t){return function(i){var r=n||t,u,f;if(r){if(Object.prototype.toString.call(i)==="[object IDBDatabaseException]"){if(i.code===11){r({name:"QuotaExceededError",error:i});return}r(i);return}try{f=i.target.error||i,u=f.name}catch(e){u=i.type==="blocked"?"IndexedDBBlocked":"UnknownError"}r({name:u,error:i})}}},cit=function(n,t,i){var u=n.name,f="_datajs_"+u,r=hy.open(f);r.onblocked=i,r.onerror=i,r.onupgradeneeded=functio
 n(){var n=r.result;n.objectStoreNames.contains(u)||n.createObjectStore(u)},r.onsuccess=function(n){var f=r.result,e;if(!f.objectStoreNames.contains(u)){if("setVersion"in f){e=f.setVersion("1.0"),e.onsuccess=function(){var n=e.transaction;n.oncomplete=function(){t(f)},f.createObjectStore(u,null,!1)},e.onerror=i,e.onblocked=i;return}n.target.error={name:"DBSchemaMismatch"},i(n);return}f.onversionchange=function(n){n.target.close()},t(f)}},fi=function(n,t,i,r){var u=n.name,f=n.db,e=vt(r,n.defaultError);if(f){i(f.transaction(u,t));return}cit(n,function(r){n.db=r,i(r.transaction(u,t))},e)},w=function(n){this.name=n};w.create=function(n){if(w.isSupported())return new w(n);throw{message:"IndexedDB is not supported on this browser"};},w.isSupported=function(){return!!hy},w.prototype.add=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){s.onabort=vt(r,o,n,"add"),s.oncomplete=function(){n instanceof Array?i(u,f):i
 (n,t)};for(var h=0;h<u.length&&h<f.length;h++)s.objectStore(e).add({v:f[h]},u[h])},r)},w.prototype.addOrUpdate=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){var h,c;for(s.onabort=vt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c={v:f[h]},s.objectStore(e).put(c,u[h])},r)},w.prototype.clear=function(n,t){var i=this.name,r=this.defaultError;fi(this,ur,function(u){u.onerror=vt(t,r),u.oncomplete=function(){n()},u.objectStore(i).clear()},t)},w.prototype.close=function(){this.db&&(this.db.close(),this.db=null)},w.prototype.contains=function(n,t,i){var r=this.name,u=this.defaultError;fi(this,ly,function(f){var e=f.objectStore(r),o=e.get(n);f.oncomplete=function(){t(!!o.result)},f.onerror=vt(i,u)},i)},w.prototype.defaultError=uu,w.prototype.getAllKeys=function(n,t){var i=this.name,r=this.defaultError;fi(this,ur,function(u){var e=[],f;u.oncomplete=function(){n(e
 )},f=u.objectStore(i).openCursor(),f.onerror=vt(t,r),f.onsuccess=function(n){var t=n.target.result;t&&(e.push(t.key),t["continue"].call(t))}},t)},w.prototype.mechanism="indexeddb",w.prototype.read=function(n,i,r){var f=this.name,e=this.defaultError,u=n instanceof Array?n:[n];fi(this,ly,function(o){var h=[],s,c,l;for(o.onerror=vt(r,e,n,"read"),o.oncomplete=function(){n instanceof Array?i(u,h):i(u[0],h[0])},s=0;s<u.length;s++)c=o.objectStore(f),l=c.get.call(c,u[s]),l.onsuccess=function(n){var i=n.target.result;h.push(i?i.v:t)}},r)},w.prototype.remove=function(n,t,i){var u=this.name,f=this.defaultError,r=n instanceof Array?n:[n];fi(this,ur,function(n){var e,o;for(n.onerror=vt(i,f),n.oncomplete=function(){t()},e=0;e<r.length;e++)o=n.objectStore(u),o["delete"].call(o,r[e])},i)},w.prototype.update=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){var h,c,l;for(s.onabort=vt(r,o),s.oncomplete=function(){n instan
 ceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c=s.objectStore(e).openCursor(hit.only(u[h])),l={v:f[h]},c.pair={key:u[h],value:l},c.onsuccess=function(n){var t=n.target.result;t?t.update(n.target.pair.value):s.abort()}},r)},ei=function(n){var e=[],r=[],i={},u,f;this.name=n,u=function(n){return n||this.defaultError},f=function(n,i){var r;return(n instanceof Array&&(r="Array of keys not supported"),(n===t||n===null)&&(r="Invalid key"),r)?(o(i,{message:r}),!1):!0},this.add=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?e({message:"key already exists",key:n}):this.addOrUpdate(n,t,r,e))},this.addOrUpdate=function(n,s,h,c){if(c=u(c),f(n,c)){var l=i[n];l===t&&(l=e.length>0?e.splice(0,1):r.length),r[l]=s,i[n]=l,o(h,n,s)}},this.clear=function(n){r=[],i={},e=[],o(n)},this.contains=function(n,t){var r=i.hasOwnProperty(n);o(t,r)},this.getAllKeys=function(n){var t=[],r;for(r in i)t.push(r);o(n,t)},this.read=function(n,t,e){if(e=u(e),f(n,e)){var s=i[n];o(t,n,r[s])}},this.remove=f
 unction(n,s,h){if(h=u(h),f(n,h)){var c=i[n];c!==t&&(c===r.length-1?r.pop():(r[c]=t,e.push(c)),delete i[n],r.length===0&&(e=[])),o(s)}},this.update=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?this.addOrUpdate(n,t,r,e):e({message:"key not found",key:n}))}},ei.create=function(n){return new ei(n)},ei.isSupported=function(){return!0},ei.prototype.close=function(){},ei.prototype.defaultError=uu,ei.prototype.mechanism="memory",ay={indexeddb:w,dom:y,memory:ei},yt.defaultStoreMechanism="best",yt.createStore=function(n,t){t||(t=yt.defaultStoreMechanism),t==="best"&&(t=y.isSupported()?"dom":"memory");var i=ay[t];if(i)return i.create(n);throw{message:"Failed to create store",name:n,mechanism:t};};var lit=function(n,t){var i=n.indexOf("?")>=0?"&":"?";return n+i+t},ait=function(n,t){var i=n.indexOf("?"),r="";return i>=0&&(r=n.substr(i),n=n.substr(0,i)),n[n.length-1]!=="/"&&(n+="/"),n+t+r},vy=function(n,t){return{method:"GET",requestUri:n,user:t.user,password:t.password,enableJsonpCallba
 ck:t.enableJsonpCallback,callbackParameterName:t.callbackParameterName,formatQueryString:t.formatQueryString}},git=function(n,t){var u=-1,r=n.indexOf("?"),i;return r!==-1&&(i=n.indexOf("?"+t+"=",r),i===-1&&(i=n.indexOf("&"+t+"=",r)),i!==-1&&(u=i+t.length+2)),u},vit=function(n,t,i,r){return yy(n,t,[],i,r)},yy=function(n,i,u,f,e){var s=vy(n,i),o=r.request(s,function(n){var t=n.__next,r=n.results;u=u.concat(r),t?o=yy(t,i,u,f,e):f(u)},e,t,i.httpClient,i.metadata);return{abort:function(){o.abort()}}},yit=function(n){var i=this,u=n.source;return i.identifier=op(encodeURI(decodeURI(u))),i.options=n,i.count=function(n,f){var e=i.options;return r.request(vy(ait(u,"$count"),e),function(t){var i=s(t.toString());isNaN(i)?f({message:"Count is NaN",count:i}):n(i)},f,t,e.httpClient,e.metadata)},i.read=function(n,t,r,f){var e="$skip="+n+"&$top="+t;return vit(lit(u,e),i.options,r,f)},i},pit=function(n,t){var r=wit(n,t),i,u;r&&(i=r.i-t.i,u=i+(n.c-n.d.length),n.d=n.d.concat(t.d.slice(i,u)))},wit=funct
 ion(n,t){var r=n.i+n.c,u=t.i+t.c,i=n.i>t.i?n.i:t.i,f=r<u?r:u,e;return f>=i&&(e={i:i,c:f-i}),e},py=function(n,i){if(n===t||typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<0||!isFinite(n))throw{message:"'"+i+"' must be greater than or equal to zero."};},bit=function(n,i){if(n!==t){if(typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<=0||!isFinite(n))throw{message:"'"+i+"' must be greater than zero."};}},wy=function(n,i){if(n!==t&&(typeof n!="number"||isNaN(n)||!isFinite(n)))throw{message:"'"+i+"' must be a number."};},vo=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return n.splice(i,1),!0;return!1},by=function(n){var t=0,r=typeof n,i;if(r==="object"&&n)for(i in n)t+=i.length*2+by(n[i]);else t=r==="string"?n.length*2:8;return t},ky=function(n,t,i){return n=Math.floor(n/i)*i,t=Math.ceil((t+1)/i)*i,{i:n,c:t-n}},cf="destroy",vi="idle",dy="init",yo="read",po="prefetch",wo="write",nu="cancel",oi="end",bo="error",yi="start",
 gy="wait",np="clear",tu="done",iu="local",tp="save",ip="source",fr=function(n,t,i,r,u,f,e){var h,c,o=this,l,s;return o.p=t,o.i=r,o.c=u,o.d=f,o.s=yi,o.canceled=!1,o.pending=e,o.oncomplete=null,o.cancel=function(){if(i){var n=o.s;n!==bo&&n!==oi&&n!==nu&&(o.canceled=!0,s(nu,h))}},o.complete=function(){s(oi,h)},o.error=function(n){o.canceled||s(bo,n)},o.run=function(n){c=n,o.transition(o.s,h)},o.wait=function(n){s(gy,n)},l=function(t,i,r){switch(t){case yi:i!==dy&&n(o,t,i,r);break;case gy:n(o,t,i,r);break;case nu:n(o,t,i,r),o.fireCanceled(),s(oi);break;case bo:n(o,t,i,r),o.canceled=!0,o.fireRejected(r),s(oi);break;case oi:if(o.oncomplete)o.oncomplete(o);o.canceled||o.fireResolved(),n(o,t,i,r);break;default:n(o,t,i,r)}},s=function(n,t){o.s=n,h=t,l(n,c,t)},o.transition=s,o};fr.prototype.fireResolved=function(){var n=this.p;n&&(this.p=null,n.resolve(this.d))},fr.prototype.fireRejected=function(n){var t=this.p;t&&(this.p=null,t.reject(n))},fr.prototype.fireCanceled=function(){this.fireRejec
 ted({canceled:!0,message:"Operation canceled"})},rp=function(i){var it=dy,y={counts:0,netReads:0,prefetches:0,cacheReads:0},c=[],b=[],p=[],nt=0,l=!1,k=vf(i.cacheSize,1048576),a=0,h=0,d=0,tt=k===0,r=vf(i.pageSize,50),ut=vf(i.prefetchSize,r),ht="1.0",f,ft=0,w=i.source,v,u;typeof w=="string"&&(w=new yit(i)),w.options=i,v=yt.createStore(i.name,i.mechanism),u=this,u.onidle=i.idle,u.stats=y,u.count=function(){var n,i,t;if(f)throw f;return(n=hu(),i=!1,l)?(o(function(){n.resolve(a)}),n.promise()):(t=w.count(function(i){t=null,y.counts++,n.resolve(i)},function(r){t=null,n.reject(g(r,{canceled:i}))}),g(n.promise(),{cancel:function(){t&&(i=!0,t.abort(),t=null)}}))},u.clear=function(){if(f)throw f;if(c.length===0){var n=hu(),t=new fr(ii,n,!1);return et(t,c),n.promise()}return c[0].p},u.filterForward=function(n,t,i){return lt(n,t,i,!1)},u.filterBack=function(n,t,i){return lt(n,t,i,!0)},u.readRange=function(n,t){if(py(n,"index"),py(t,"count"),f)throw f;var i=hu(),r=new fr(ui,i,!0,n,t,[],0);return
  et(r,b),g(i.promise(),{cancel:function(){r.cancel()}})},u.ToObservable=u.toObservable=function(){if(!n.Rx||!n.Rx.Observable)throw{message:"Rx library not available - include rx.js"};if(f)throw f;return n.Rx.Observable.CreateWithDisposable(function(n){var t=!1,i=0,f=function(i){t||n.OnError(i)},e=function(o){if(!t){for(var s=0,h=o.length;s<h;s++)n.OnNext(o[s]);o.length<r?n.OnCompleted():(i+=r,u.readRange(i,r).then(e,f))}};return u.readRange(i,r).then(e,f),{Dispose:function(){t=!0}}})};var rt=function(n){return function(t){f={message:n,error:t};for(var i=0,r=b.length;i<r;i++)b[i].fireRejected(f);for(i=0,r=c.length;i<r;i++)c[i].fireRejected(f);b=c=null}},e=function(n){if(n!==it){it=n;for(var i=c.concat(b,p),t=0,r=i.length;t<r;t++)i[t].run(it)}},ct=function(){var n=new di;return v.clear(function(){nt=0,l=!1,a=0,h=0,d=0,tt=k===0,y={counts:0,netReads:0,prefetches:0,cacheReads:0},u.stats=y,v.close(),n.resolve()},function(t){n.reject(t)}),n},kt=function(n){var t=vo(c,n);t||(t=vo(b,n),t||vo
 (p,n)),ft--,e(vi)},dt=function(n){var t=new di,u=!1,i=w.read(n,r,function(i){var r={i:n,c:i.length,d:i};t.resolve(r)},function(n){t.reject(n)});return g(t,{cancel:function(){i&&(i.abort(),u=!0,i=null)}})},lt=function(n,t,i,e){if(n=s(n),t=s(t),isNaN(n))throw{message:"'index' must be a valid number.",index:n};if(isNaN(t))throw{message:"'count' must be a valid number.",count:t};if(f)throw f;n=Math.max(n,0);var h=hu(),o=[],a=!1,l=null,v=function(n,f){a||(t>=0&&o.length>=t?h.resolve(o):l=u.readRange(n,f).then(function(u){for(var l,a,y,p,s=0,c=u.length;s<c&&(t<0||o.length<t);s++)l=e?c-s-1:s,a=u[l],i(a)&&(y={index:n+l,item:a},e?o.unshift(y):o.push(y));!e&&u.length<f||e&&n<=0?h.resolve(o):(p=e?Math.max(n-r,0):n+f,v(p,r))},function(n){h.reject(n)}))},c=ky(n,n,r),y=e?c.i:n,p=e?n-c.i+1:c.i+c.c-n;return v(y,p),g(h.promise(),{cancel:function(){l&&l.cancel(),a=!0}})},at=function(){u.onidle&&ft===0&&u.onidle()},gt=function(n){if(!l&&ut!==0&&!tt&&(p.length===0||p[0]&&p[0].c!==-1)){var t=new fr(ri,n
 ull,!0,n,ut,null,ut);et(t,p)}},et=function(n,t){n.oncomplete=kt,t.push(n),ft++,n.run(it)},ni=function(n){var r=!1,i=g(new di,{cancel:function(){r=!0}}),u=vt(i,"Read page from store failure");return v.contains(n,function(f){if(!r){if(f){v.read(n,function(n,u){r||i.resolve(u!==t,u)},u);return}i.resolve(!1)}},u),i},ti=function(n,t){var e=!1,i=g(new di,{cancel:function(){e=!0}}),r=vt(i,"Save page to store failure"),u=function(){i.resolve(!0)},f;return t.c>0?(f=by(t),tt=k>=0&&k<nt+f,tt?u():v.addOrUpdate(n,t,function(){pt(t,f),st(u,r)},r)):(pt(t,0),st(u,r)),i},st=function(n,t){var i={actualCacheSize:nt,allDataLocal:l,cacheSize:k,collectionCount:a,highestSavedPage:h,highestSavedPageSize:d,pageSize:r,sourceId:w.identifier,version:ht};v.addOrUpdate("__settings",i,n,t)},vt=function(n){return function(){n.resolve(!1)}},pt=function(n,t){var i=n.c,u=n.i;i===0?h===u-r&&(a=h+d):(h=Math.max(h,u),h===u&&(d=i),nt+=t,i<r&&!a&&(a=u+i)),l||a!==h+d||(l=!0)},wt=function(n,t,i,r){var u=n.canceled&&t!==oi;r
 eturn u&&t===nu&&r&&r.cancel&&r.cancel(),u},ii=function(n,t,i){var r=n.transition;if(i!==cf)return e(cf),!0;switch(t){case yi:r(np);break;case oi:at();break;case np:ct().then(function(){n.complete()}),n.wait();break;default:return!1}return!0},ri=function(n,t,i,u){var o,f;if(!wt(n,t,i,u)){if(o=n.transition,i!==po)return i===cf?t!==nu&&n.cancel():i===vi&&e(po),!0;switch(t){case yi:p[0]===n&&o(iu,n.i);break;case tu:f=n.pending,f>0&&(f-=Math.min(f,u.c)),l||f===0||u.c<r||tt?n.complete():(n.pending=f,o(iu,u.i+r));break;default:return bt(n,t,i,u,!0)}}return!0},ui=function(n,t,i,u){var f,o,s;if(!wt(n,t,i,u)){if(f=n.transition,i!==yo&&t!==yi)return i===cf?t!==yi&&n.cancel():i!==wo&&e(yo),!0;switch(t){case yi:(i===vi||i===po)&&(e(yo),n.c>0?(o=ky(n.i,n.c,r),f(iu,o.i)):f(tu,n));break;case tu:pit(n,u),s=n.d.length,n.c===s||u.c<r?(y.cacheReads++,gt(u.i+u.c),n.complete()):f(iu,u.i+r);break;default:return bt(n,t,i,u,!1)}}return!0},bt=function(n,t,i,r,u){var s=n.error,o=n.transition,h=n.wait,f;switc
 h(t){case oi:at();break;case iu:f=ni(r).then(function(t,i){n.canceled||(t?o(tu,i):o(ip,r))});break;case ip:f=dt(r).then(function(t){n.canceled||(u?y.prefetches++:y.netReads++,o(tp,t))},s);break;case tp:i!==wo&&(e(wo),f=ti(r.i,r).then(function(t){n.canceled||(!t&&u&&(n.pending=0),o(tu,r)),e(vi)}));break;default:return!1}return f&&(n.canceled?f.cancel():n.s===t&&h(f)),!0};return v.read("__settings",function(n,t){if(ot(t)){var i=t.version;if(!i||i.indexOf("1.")!==0){rt("Unsupported cache store version "+i)();return}r!==t.pageSize||w.identifier!==t.sourceId?ct().then(function(){e(vi)},rt("Unable to clear store during initialization")):(nt=t.actualCacheSize,l=t.allDataLocal,k=t.cacheSize,a=t.collectionCount,h=t.highestSavedPage,d=t.highestSavedPageSize,ht=i,e(vi))}else st(function(){e(vi)},rt("Unable to write settings during initialization."))},rt("Unable to read settings from store.")),u},yt.createDataCache=function(n){if(bit(n.pageSize,"pageSize"),wy(n.cacheSize,"cacheSize"),wy(n.prefe
 tchSize,"prefetchSize"),!ot(n.name))throw{message:"Undefined or null name",options:n};if(!ot(n.source))throw{message:"Undefined source",options:n};return new rp(n)}})(this)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/datajs_demo.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/datajs_demo.js b/odatajs/demo/scripts/datajs_demo.js
new file mode 100644
index 0000000..24ac24d
--- /dev/null
+++ b/odatajs/demo/scripts/datajs_demo.js
@@ -0,0 +1,124 @@
+var run = function() {
+    //testJQueryReadMetadata();
+    runSimpleReadRequest();
+    runSimpleReadRequestWithMetadata();
+    //    readWithJsonP();
+    //alert(OData.odataRelatedLinksPrefix);
+    //OData.odataRelatedLinksPrefix = "dasfs";
+    //alert(OData.odataRelatedLinksPrefix);
+    //var time = new Date("1992-08-06T00:00:00+01:00");
+    //var jsonTime = {value : time};
+    //var jsonstring = window.JSON.stringify(jsonTime);
+    //alert(jsonstring);
+
+    //time.offset = 100;
+    //alert(time.offset);
+    //var offsite = time.getTimezoneOffset();
+    //alert(offsite);
+};
+
+var runSimpleReadRequest = function() {
+    var oHeaders = {
+        'Accept': 'application/json',
+        "Odata-Version": "4.0",
+        "OData-MaxVersion": "4.0"
+    };
+
+    var request =
+    {
+        headers: oHeaders,
+        // requestUri: "http://services.odata.org/OData/OData.svc/Categories",
+        requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories",
+        data: null,
+    };
+    var successFunction = function (data) {
+        document.getElementById("simpleRead").innerHTML = JSON.stringify(data, undefined, 2);
+    };
+    var failFunction = function (err) {
+        alert("err");
+        alert(JSON.stringify(err));
+    };
+    odatajs.oData.read(request, successFunction, failFunction);
+};
+
+var runSimpleReadRequestWithMetadata = function () {
+    var oHeaders = {
+        'Accept': 'text/html,application/xhtml+xml,application/xml,application/json;odata.metadata=minimal',
+        "Odata-Version": "4.0",
+        "OData-MaxVersion": "4.0",
+        "Prefer": "odata.allow-entityreferences"
+    };
+    
+    var readMetadataSuccess = function (metadata) {
+        document.getElementById("metadata").innerHTML = JSON.stringify(metadata, undefined, 2);
+        var request =
+        {
+            headers: oHeaders,
+            // requestUri: "http://services.odata.org/OData/OData.svc/Categories",
+            requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Products",
+            data: null,
+        };
+        var successFunction = function(data) {
+            document.getElementById("simpleReadWithMetadata").innerHTML = JSON.stringify(data, undefined, 2);
+        };
+        var failFunction = function(err) {
+            alert("err");
+            alert(JSON.stringify(err));
+        };
+        odatajs.oData.read(request, successFunction, failFunction, null, null, metadata);
+    };
+
+    var readMetadataFail = function (err) {
+        alert("err");
+        alert(JSON.stringify(err));
+    };
+    
+    var metadataRequest =
+    {
+        headers: oHeaders,
+        // requestUri: "http://services.odata.org/OData/OData.svc/$metadata",
+        requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/$metadata", 
+        // "http://localhost:6630/PrimitiveKeys.svc/$metadata",
+        data: null,
+    };
+
+    odatajs.oData.read(metadataRequest, readMetadataSuccess, readMetadataFail, odatajs.V4.oData.metadataHandler);
+};
+
+var readWithJsonP = function() {
+    var sUrl2 = "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc?$expand=Category";
+
+    var oRequest = {
+        requestUri: sUrl2,
+        enableJsonpCallback: true,
+    };
+
+    odatajs.oData.read(oRequest, function (data) {
+        document.getElementById("simpleReadWithJSONP").innerHTML = JSON.stringify(data, undefined, 2);
+    },
+    function (oError) {
+        alert(oError.message);
+    });
+};
+
+var testJQueryReadMetadata = function () {
+    $.ajax({
+        url: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/$metadata",
+        headers: {
+            '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"
+        },
+        type: "GET",
+        converters: { "text xml": OData.metadataParser },
+        dataType: "xml",
+        success: function (xml, textStatus, jqXHR) {
+            var data = OData.metadataParser2(xml) || undefined;
+            document.getElementById("simpleReadWithMetadata").innerHTML = JSON.stringify(data, undefined, 2);
+        },
+        error: function (jqXHR, textStatus, errorThrown) {
+            alert("err");
+        }
+    });
+};


[36/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/TestLogger.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/common/TestLogger.svc b/datajs/tests/common/TestLogger.svc
deleted file mode 100644
index 164d207..0000000
--- a/datajs/tests/common/TestLogger.svc
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="DataJS.Tests.TestSynchronizerFactory" Service="DataJS.Tests.TestSynchronizer" %>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Net;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Channels;
-    using System.ServiceModel.Description;
-    using System.ServiceModel.Dispatcher;
-    using System.ServiceModel.Web;
-    using System.Text;
-    using System.Threading;
-    using System.Xml;
-    
-    /// <summary>
-    /// This factory supports reconfiguring the service to allow incoming messages
-    /// to be larger than the default.
-    /// </summary>
-    public class TestSynchronizerFactory : WebScriptServiceHostFactory
-    {
-        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
-        {
-            var result = base.CreateServiceHost(serviceType, baseAddresses);
-            result.Opening += ServiceHostOpening;
-            return result;
-        }
-
-        private static void UpdateService(ServiceDescription description)
-        {
-            const long LargeMaxReceivedMessageSize = 1024 * 1024 * 16;
-            foreach (var endpoint in description.Endpoints)
-            {
-                var basic = endpoint.Binding as BasicHttpBinding;
-                if (basic != null)
-                {
-                    basic.MaxReceivedMessageSize = LargeMaxReceivedMessageSize;
-                }
-
-                var http = endpoint.Binding as WebHttpBinding;
-                if (http != null)
-                {
-                    http.MaxReceivedMessageSize = LargeMaxReceivedMessageSize;
-                }
-            }
-        }
-
-        private void ServiceHostOpening(object sender, EventArgs e)
-        {
-            UpdateService((sender as ServiceHost).Description);
-        }        
-    }
-
-    /// <summary>Use this class to log test activity.</summary>
-    /// <remarks>
-    /// A test run can be created by invoking CreateTestRun. With a test
-    /// run ID, the following operations can be invoked:
-    ///
-    /// - AddTestPages: adds test pages to be made available to future callers (typically to support tests from different files)
-    /// - SetTestNamePrefix: sets a string that will be prefixed to every test name in logs (typically to include a browser name)
-    /// - MarkInProgress: resets the test run to "in-progress" for another variation (typically to run a different browser)
-    /// - IsTestRunInProgress: checks whether it's still in progress
-    /// - GetTestRunResults: returns the test results in TRX format
-    /// - LogAssert: logs a single assertion in the current test for the run
-    /// - LogTestStart: logs a test that has begun execution
-    /// - LogTestDone: logs a test that has ended execution
-    /// - TestCompleted: logs that a test has completed execution; returns the next page with tests or an empty string
-    /// </remarks>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class TestSynchronizer
-    {
-        private static readonly Dictionary<string, TestRunContext> testRuns = new Dictionary<string, TestRunContext>();
-        private const string Inconclusive = "Inconclusive";
-        private const string InProgress = "InProgress";
-        private const string Failed = "Failed";
-        private const string Passed = "Passed";
-        private const string Completed = "Completed";
-        
-        /// <summary>
-        /// Adds test pages to the specified runs; replaces existing files (helps with reliablity when something
-        /// fails part-way).
-        /// </summary>
-        /// <remarks>This method is typically called by the test harness.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public int AddTestPages(string testRunId, string pages, string filter)
-        {
-            DisableResponseCaching();
-            
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                context.TestPages.Clear();
-                context.TestPages.AddRange(pages.Split(',').Select(page => page + "?testRunId=" + testRunId + (filter == null ? string.Empty : "?filter=" + filter)));
-                return context.TestPages.Count;
-            }
-        }
-
-        /// <remarks>This method is typically called by the test harness.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public string CreateTestRun()
-        {
-            DisableResponseCaching();
-
-            Guid value = Guid.NewGuid();
-            string result = value.ToString();
-            TestRunContext context = CreateTestRunContextWithId(value);
-            
-            lock (testRuns)
-            {
-                testRuns.Add(result, context);
-            }
-
-            return result;
-        }
-
-        /// <summary>Checks whether the test run is in progress.</summary>
-        /// <remarks>This method is typically called by the test harness.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public bool IsTestRunInProgress(string testRunId)
-        {
-            DisableResponseCaching();
-
-            TestRunContext context = GetTestRunContext(testRunId);
-            return context.TestRun.ResultSummary.Outcome == InProgress;
-        }
-        
-        /// <summary>Provides a list of all test runs being tracked.</summary>
-        [OperationContract]
-        [WebGet(ResponseFormat=WebMessageFormat.Json)]
-        public IEnumerable<string> GetActiveTestRuns()
-        {
-            DisableResponseCaching();
-
-            List<string> result;
-            lock (testRuns)
-            {
-                result = new List<string>(testRuns.Keys);
-            }
-            
-            return result;
-        }
-
-        /// <remarks>This method is typically called by the test harness.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Xml)]
-        public Message GetTestRunResults(string testRunId)
-        {
-            DisableResponseCaching();
-
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                TestRun run = context.TestRun;
-                this.CompleteTestRun(run);
-
-                TestRunXmlBodyWriter writer = new TestRunXmlBodyWriter(run);
-                return Message.CreateMessage(
-                    MessageVersion.None,
-                    OperationContext.Current.OutgoingMessageHeaders.Action,
-                    writer);
-            }
-        }
-
-        /// <remarks>This method is typically called by the test case.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public void LogAssert(string testRunId, bool pass, string message, string name, string actual, string expected)
-        {
-            DisableResponseCaching();
-
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                TestRun run = context.TestRun;
-                string prefixedName = context.TestNamePrefix + name;
-                TestResult result = run.TestResults.LastOrDefault(r => r.TestName == prefixedName);
-                if (result == null)
-                {
-                    throw new InvalidOperationException("Unable to find test " + prefixedName + " in run " + testRunId);
-                }
-                
-                result.DebugTrace.AppendLine(message);
-                if (!pass)
-                {
-                    result.ErrorMessages.AppendLine(message);
-                    result.ErrorMessages.AppendLine("Expected: " + expected);
-                    result.ErrorMessages.AppendLine("Actual: " + actual);
-                }
-            }
-        }
-        
-        /// <remarks>This method is typically called by the test case.</remarks>
-        [OperationContract]
-        [WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
-        public void LogBatch(string[] urls)
-        {
-            DisableResponseCaching();
-            
-            foreach (var url in urls)
-            {
-                Uri parsed = new Uri(OperationContext.Current.Channel.LocalAddress.Uri, url);
-                string methodName = parsed.Segments[parsed.Segments.Length - 1];
-                System.Reflection.MethodInfo method = this.GetType().GetMethod(methodName);
-                System.Reflection.ParameterInfo[] parameterInfos = method.GetParameters();
-                object[] parameters = new object[parameterInfos.Length];
-                System.Collections.Specialized.NameValueCollection query = System.Web.HttpUtility.ParseQueryString(parsed.Query);
-                for (int i = 0; i < parameters.Length; i++)
-                {
-                    object value = query[parameterInfos[i].Name];
-                    parameters[i] = Convert.ChangeType(value, parameterInfos[i].ParameterType, System.Globalization.CultureInfo.InvariantCulture);
-                }
-                
-                method.Invoke(this, parameters);
-            }            
-        }
-
-        /// <remarks>This method is typically called by the test case.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public void LogTestStart(string testRunId, string name, DateTime startTime)
-        {
-            DisableResponseCaching();
-            
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                TestRun run = context.TestRun;
-                string prefixedName = context.TestNamePrefix + name;
-                Guid testId = Guid.NewGuid();
-                Guid executionId = Guid.NewGuid();
-                Guid testListId = run.TestLists.Single().Id;
-                run.TestDefinitions.Add(new TestDefinition()
-                {
-                    Id = testId,
-                    Name = prefixedName,
-                    ExecutionId = executionId,
-                });
-                run.TestEntries.Add(new TestEntry()
-                {
-                    TestId = testId,
-                    ExecutionId = executionId,
-                    TestListId = testListId
-                });
-                run.TestResults.Add(new TestResult()
-                {
-                    ExecutionId = executionId,
-                    TestId = testId,
-                    TestListId = testListId,
-                    TestName = prefixedName,
-                    ComputerName = Environment.MachineName,
-                    StartTime = startTime,
-                    EndTime = startTime,
-                    TestType = Guid.Parse("13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"),
-                    Outcome = InProgress,
-                    // RelativeResultsDirectory?
-                });
-            }
-        }
-
-        /// <remarks>This method is typically called by the test case.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public void LogTestDone(string testRunId, string name, int failures, int total, DateTime endTime)
-        {
-            DisableResponseCaching();
-
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                TestRun run = context.TestRun;
-                string prefixedName = context.TestNamePrefix + name;
-                TestResult result = run.TestResults.LastOrDefault(r => r.TestName == prefixedName);
-                if (failures > 0)
-                {
-                    result.Outcome = Failed;
-                }
-                else
-                {
-                    result.Outcome = Passed;
-                }
-
-                result.EndTime = endTime;
-            }
-        }
-
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public void MarkInProgress(string testRunId)
-        {
-            DisableResponseCaching();
-
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                context.TestRun.ResultSummary.Outcome = InProgress;
-            }
-        }
-
-        /// <remarks>This method is typically called by the test harness.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public void SetTestNamePrefix(string testRunId, string prefix)
-        {
-            DisableResponseCaching();
-            
-            TestRunContext context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                context.TestNamePrefix = prefix;
-            }
-        }
-
-        /// <remarks>This method is typically called by the test case.</remarks>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public string TestCompleted(string testRunId, int failures, int total)
-        {
-            DisableResponseCaching();
-            
-            var context = GetTestRunContext(testRunId);
-            lock (context)
-            {
-                string result;
-                if (context.TestPages.Count == 0)
-                {
-                    context.TestRun.ResultSummary.Outcome = Completed;
-                    result = "";
-                }
-                else
-                {
-                    result = context.TestPages[0];
-                    context.TestPages.RemoveAt(0);
-                }
-
-                return result;
-            }
-        }
-
-        private static TestRunContext CreateTestRunContextWithId(Guid value)
-        {
-            TestRun run = new TestRun();
-            run.Id = value;
-            run.Name = "Test run";
-            run.TestTimes.Creation = DateTime.Now;
-            run.TestTimes.Queueing = DateTime.Now;
-            run.TestLists.Add(new TestList()
-            {
-                Name = "All Results",
-                Id = Guid.NewGuid()
-            });
-
-            // For the time being, set up a fake test settings.
-            run.TestSettings.Id = Guid.NewGuid();
-
-            run.ResultSummary.Outcome = InProgress;
-
-            TestRunContext context = new TestRunContext();
-            context.TestRun = run;
-
-            return context;
-        }
-
-        private static void DisableResponseCaching()
-        {
-            WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.CacheControl] = "no-cache";            
-        }
-
-        private static TestRunContext GetTestRunContext(string testRunId)
-        {
-            if (testRunId == null)
-            {
-                throw new ArgumentNullException("testRunId");
-            }
-            
-            lock (testRuns)
-            {
-                // For an 0-filled GUID, allow create-on-demand to simplify ad-hoc testing.
-                // Something like:
-                // http://localhost:8989/tests/odata-qunit-tests.htm?testRunId=00000000-0000-0000-0000-000000000000
-                if (!testRuns.ContainsKey(testRunId))
-                {
-                    Guid value = Guid.Parse(testRunId);
-                    if (value == Guid.Empty)
-                    {
-                        TestRunContext context = CreateTestRunContextWithId(value);
-                        testRuns.Add(testRunId, context);
-                    }
-                }
-                
-                return testRuns[testRunId];
-            }
-        }
-
-        private void CompleteTestRun(TestRun run)
-        {
-            run.TestTimes.Finish = DateTime.Now;
-
-            // Fill counts in result object.
-            var summary = run.ResultSummary;
-            summary.Executed = 0;
-            summary.Error = 0;
-            summary.Failed = 0;
-            summary.Timeout = 0;
-            summary.Aborted = 0;
-            summary.Inconclusive = 0;
-            summary.PassedButRunAborted = 0;
-            summary.NotRunnable = 0;
-            summary.NotExecuted = 0;
-            summary.Disconnected = 0;
-            summary.Warning = 0;
-            summary.Passed = 0;
-            summary.Completed = 0;
-            summary.InProgress = 0;
-            summary.Pending = 0;
-
-            foreach (var testResult in run.TestResults)
-            {
-                string outcome = testResult.Outcome;
-                switch (outcome)
-                {
-                    case InProgress:
-                        summary.Executed++;
-                        summary.InProgress++;
-                        break;
-                    case Failed:
-                        summary.Executed++;
-                        summary.Completed++;
-                        summary.Failed++;
-                        break;
-                    case Passed:
-                        summary.Executed++;
-                        summary.Completed++;
-                        summary.Passed++;
-                        break;
-                    default:
-                        summary.Failed++;
-                        break;
-                }
-            }
-
-            summary.Total = run.TestResults.Count;
-
-            if (summary.Failed != 0)
-            {
-                summary.Outcome = Failed;
-            }
-            else if (summary.Total <= 0 || summary.Passed < summary.Total)
-            {
-                summary.Outcome = Inconclusive;
-            }
-            else
-            {
-                summary.Outcome = Passed;
-            }
-        }
-    }
-
-    public class TestRunContext
-    {
-        public TestRunContext()
-        {
-            this.TestPages = new List<string>();
-        }
-        
-        public TestRun TestRun { get; set; }
-        public string TestNamePrefix { get; set; }
-        public List<string> TestPages { get; set; }
-    }
-
-    public class TestResultWriter
-    {
-        private const string TestNamespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010";
-
-        public static void WriteTestRun(TestRun run, string path)
-        {
-            if (run == null)
-            {
-                throw new ArgumentNullException("run");
-            }
-            if (path == null)
-            {
-                throw new ArgumentNullException("path");
-            }
-
-            using (XmlWriter writer = XmlWriter.Create(path))
-            {
-                WriteTestRun(run, path);
-            }
-        }
-
-        public static void WriteTestRun(TestRun run, XmlWriter writer)
-        {
-            if (run == null)
-            {
-                throw new ArgumentNullException("run");
-            }
-            if (writer == null)
-            {
-                throw new ArgumentNullException("writer");
-            }
-
-            writer.WriteStartElement("TestRun", TestNamespace);
-            writer.WriteGuidIfPresent("id", run.Id);
-            writer.WriteAttributeString("name", run.Name);
-            writer.WriteAttributeString("runUser", run.RunUser);
-
-            WriteTestSettings(run.TestSettings, writer);
-            WriteResultSummary(run.ResultSummary, writer);
-
-            // Write test definitions.
-            writer.WriteStartElement("TestDefinitions", TestNamespace);
-            foreach (var definition in run.TestDefinitions)
-            {
-                WriteTestDefinition(definition, writer);
-            }
-
-            writer.WriteEndElement();
-
-            // Write test lists.
-            writer.WriteStartElement("TestLists", TestNamespace);
-            foreach (var list in run.TestLists)
-            {
-                WriteTestList(list, writer);
-            }
-
-            writer.WriteEndElement();
-
-            // Write test entries.
-            writer.WriteStartElement("TestEntries", TestNamespace);
-            foreach (var entry in run.TestEntries)
-            {
-                WriteTestEntry(entry, writer);
-            }
-
-            writer.WriteEndElement();
-
-            // Write test results.
-            writer.WriteStartElement("Results", TestNamespace);
-            foreach (var result in run.TestResults)
-            {
-                WriteTestResults(result, writer);
-            }
-
-            writer.WriteEndElement();
-
-            // Close the test run element.
-            writer.WriteEndElement();
-        }
-
-        private static void WriteTestResults(TestResult result, XmlWriter writer)
-        {
-            if (result == null)
-            {
-                throw new ArgumentNullException("result");
-            }
-
-            writer.WriteStartElement("UnitTestResult", TestNamespace);
-            writer.WriteGuidIfPresent("testId", result.TestId);
-            writer.WriteGuidIfPresent("testListId", result.TestListId);
-            writer.WriteGuidIfPresent("executionId", result.ExecutionId);
-            writer.WriteGuidIfPresent("RelativeResultsDirectory", result.RelativeResultsDirectory);
-
-            writer.WriteAttributeString("testName", result.TestName);
-            writer.WriteAttributeString("computerName", result.ComputerName);
-            writer.WriteAttributeString("duration", result.Duration.ToString());
-            writer.WriteAttributeString("startTime", XmlConvert.ToString(result.StartTime));
-            writer.WriteAttributeString("endTime", XmlConvert.ToString(result.EndTime));
-            writer.WriteAttributeString("outcome", result.Outcome);
-
-            writer.WriteGuidIfPresent("testType", result.TestType);
-
-            if (result.DebugTrace.Length > 0)
-            {
-                writer.WriteStartElement("Output");
-
-                writer.WriteStartElement("DebugTrace");
-                writer.WriteString(result.DebugTrace.ToString());
-                writer.WriteEndElement();
-
-                writer.WriteStartElement("ErrorInfo");
-                writer.WriteStartElement("Message");
-                writer.WriteString(result.ErrorMessages.ToString());
-                writer.WriteEndElement();
-                writer.WriteEndElement();
-
-                writer.WriteEndElement();
-            }
-            
-            writer.WriteEndElement();
-        }
-
-        private static void WriteTestEntry(TestEntry entry, XmlWriter writer)
-        {
-            if (entry == null)
-            {
-                throw new ArgumentNullException("entry");
-            }
-
-            writer.WriteStartElement("TestEntry", TestNamespace);
-            writer.WriteGuidIfPresent("testId", entry.TestId);
-            writer.WriteGuidIfPresent("testListId", entry.TestListId);
-            writer.WriteGuidIfPresent("executionId", entry.ExecutionId);
-            writer.WriteEndElement();
-        }
-
-        private static void WriteTestList(TestList list, XmlWriter writer)
-        {
-            if (list == null)
-            {
-                throw new ArgumentNullException("list");
-            }
-
-            writer.WriteStartElement("TestList", TestNamespace);
-            writer.WriteAttributeString("name", list.Name);
-            writer.WriteGuidIfPresent("id", list.Id);
-            writer.WriteEndElement();
-        }
-
-        private static void WriteTestDefinition(TestDefinition definition, XmlWriter writer)
-        {
-            if (definition == null)
-            {
-                throw new ArgumentNullException("definition");
-            }
-
-            writer.WriteStartElement("UnitTest", TestNamespace);
-            writer.WriteAttributeString("name", definition.Name);
-            writer.WriteAttributeString("storage", definition.Storage);
-            writer.WriteGuidIfPresent("id", definition.Id);
-            
-            // There are more thing we could write here: DeploymentItems, Execution, TestMethod
-            
-            // This is the minimum needed to load the test in the IDE.
-            writer.WriteStartElement("Execution", TestNamespace);
-            writer.WriteGuidIfPresent("id", definition.ExecutionId);
-            writer.WriteEndElement();
-
-            writer.WriteStartElement("TestMethod", TestNamespace);
-            writer.WriteAttributeString("codeBase", "fake-test-file.js");
-            writer.WriteAttributeString("adapterTypeName", "Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
-            writer.WriteAttributeString("className", "FakeClassName, TestLogging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
-            writer.WriteAttributeString("name", definition.Name);
-            writer.WriteEndElement();
-            
-            writer.WriteEndElement();
-        }
-
-        private static void WriteResultSummary(ResultSummary resultSummary, XmlWriter writer)
-        {
-            if (resultSummary == null)
-            {
-                throw new ArgumentNullException("resultSummary");
-            }
-
-            writer.WriteStartElement("ResultSummary", TestNamespace);
-            writer.WriteAttributeString("outcome", resultSummary.Outcome);
-
-            writer.WriteStartElement("Counters", TestNamespace);
-            
-            foreach (var p in typeof(ResultSummary).GetProperties())
-            {
-                if (p.PropertyType != typeof(int))
-                {
-                    continue;
-                }
-
-                int value = (int)p.GetValue(resultSummary, null);
-                string attributeName = p.Name;
-                attributeName = attributeName.Substring(0, 1).ToLowerInvariant() +  attributeName.Substring(1);
-                writer.WriteAttributeString(attributeName, value.ToString());
-            }
-            
-            writer.WriteEndElement();
-            writer.WriteEndElement();
-        }
-
-        private static void WriteTestSettings(TestSettings testSettings, XmlWriter writer)
-        {
-            if (testSettings == null)
-            {
-                throw new ArgumentNullException("testSettings");
-            }
-            
-            writer.WriteStartElement("TestSettings", TestNamespace);
-            writer.WriteAttributeString("name", testSettings.Name);
-            writer.WriteGuidIfPresent("id", testSettings.Id);
-            // There are more things we could write here.
-            writer.WriteEndElement();
-        }
-    }
-
-    public static class XmlWriterExtensions
-    {
-        public static void WriteGuidIfPresent(this XmlWriter writer, string attributeName, Guid value)
-        {
-            if (value != Guid.Empty)
-            {
-                writer.WriteAttributeString(attributeName, value.ToString());
-            }
-        }
-    }
-
-    public class TestRun
-    {
-        public TestRun()
-        {
-            this.TestDefinitions = new List<TestDefinition>();
-            this.TestLists = new List<TestList>();
-            this.TestEntries = new List<TestEntry>();
-            this.TestResults = new List<TestResult>();
-            this.ResultSummary = new ResultSummary();
-            this.TestTimes = new TestTimes();
-            this.TestSettings = new TestSettings();
-            
-            this.Id = Guid.NewGuid();
-            this.RunUser = Environment.UserDomainName + "\\" + Environment.UserName;
-        }
-
-        public Guid Id { get; set; }
-        public string Name { get; set; }
-        public string RunUser { get; set; }
-        public TestSettings TestSettings { get; set; }
-        public TestTimes TestTimes { get; set; }
-        public ResultSummary ResultSummary { get; set; }
-        public List<TestDefinition> TestDefinitions { get; set; }
-        public List<TestList> TestLists { get; set; }
-        public List<TestEntry> TestEntries { get; set; }
-        public List<TestResult> TestResults { get; set; }
-    }
-
-    public class TestSettings
-    {
-        public Guid Id { get; set; }
-        public string Name { get; set; }
-    }
-
-    public class TestTimes
-    {
-        public DateTime Creation { get; set; }
-        public DateTime Queueing { get; set; }
-        public DateTime Start { get; set; }
-        public DateTime Finish { get; set; }
-    }
-
-    public class ResultSummary
-    {
-        public string Outcome { get; set; }
-        public int Total { get; set; }
-        public int Executed { get; set; }
-        public int Error { get; set; }
-        public int Failed { get; set; }
-        public int Timeout { get; set; }
-        public int Aborted { get; set; }
-        public int Inconclusive { get; set; }
-        public int PassedButRunAborted { get; set; }
-        public int NotRunnable { get; set; }
-        public int NotExecuted { get; set; }
-        public int Disconnected { get; set; }
-        public int Warning { get; set; }
-        public int Passed { get; set; }
-        public int Completed { get; set; }
-        public int InProgress { get; set; }
-        public int Pending { get; set; }
-    }
-
-    public class TestDefinition
-    {
-        public string Name { get; set; }
-        public string Storage { get; set; }
-        public Guid Id { get; set; }
-        public Guid ExecutionId { get; set; }
-    }
-
-    public class TestList
-    {
-        public string Name { get; set; }
-        public Guid Id { get; set; }
-    }
-
-    public class TestEntry
-    {
-        public Guid TestId { get; set; }
-        public Guid ExecutionId { get; set; }
-        public Guid TestListId { get; set; }
-    }
-
-    public class TestResult
-    {
-        public TestResult()
-        {
-            this.DebugTrace = new StringBuilder();
-            this.ErrorMessages = new StringBuilder();
-        }
-        
-        public Guid ExecutionId { get; set; }
-        public Guid TestId { get; set; }
-        public string TestName { get; set; }
-        public string ComputerName { get; set; }
-        public TimeSpan Duration { get { return this.EndTime - this.StartTime; } }
-        public DateTime StartTime { get; set; }
-        public DateTime EndTime { get; set; }
-        public Guid TestType { get; set; }
-        public string Outcome { get; set; }
-        public Guid TestListId { get; set; }
-        public Guid RelativeResultsDirectory { get; set; }
-        public StringBuilder DebugTrace { get; set; }
-        public StringBuilder ErrorMessages { get; set; }
-    }
-
-    class TestRunXmlBodyWriter : BodyWriter
-    {
-        private readonly TestRun run;
-
-        public TestRunXmlBodyWriter(TestRun run)
-            : base(true)
-        {
-            this.run = run;
-        }
-
-        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
-        {
-            TestResultWriter.WriteTestRun(this.run, writer);
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/TestSynchronizerClient.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/TestSynchronizerClient.js b/datajs/tests/common/TestSynchronizerClient.js
deleted file mode 100644
index 157654e..0000000
--- a/datajs/tests/common/TestSynchronizerClient.js
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// TestSynchronizer Client
-// Use to log assert pass/fails and notify mstest a test has completed execution
-
-(function (window, undefined) {
-    var testRunId = "";
-    var serviceRoot = "./common/TestLogger.svc/";
-    var recording = null;
-    var recordingLength = 0;
-    var maxStringLength = 8192;
-    var maxPostLength = 2097152;
-
-    var callTestSynchronizer = function (methodName, parameterUrl) {
-        /** Invokes a function on the test synchronizer.
-         * @param {String} [partialUrl] - 
-         * @returns {String} A response from the server, possibly null.
-        
-         * If the recording variable is assigned, then the call is logged
-         * but nothing is invoked.
-         */
-        
-
-        var partialUrl;
-        if (testRunId) {
-            partialUrl = methodName + "?testRunId=" + testRunId + "&" + parameterUrl;
-        }
-        else {
-            partialUrl = methodName + "?" + parameterUrl;
-        }
-
-        var url = serviceRoot + partialUrl;
-
-        if (recording) {
-            if (url.length > maxStringLength) {
-                url = url.substr(0, maxStringLength);
-            }
-
-            recordingLength += url.length;
-            if (recordingLength > maxPostLength) {
-                submitRecording();
-                recording = [];
-                recordingLength = url.length;
-            }
-
-            recording.push(url);
-            return null;
-        }
-
-        var xhr;
-        if (window.XMLHttpRequest) {
-            xhr = new window.XMLHttpRequest();
-        } else {
-            xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
-        }
-
-        xhr.open("GET", url, false);
-        xhr.send();
-        return xhr.responseText;
-    };
-
-    var getLogPrefix = function (result) {
-        /** Returns the log prefix for a given result
-         * @param {Boolean} result - Whether the result is pass or fail. If null, the log line is assumed to be diagnostic
-         */
-        return "[" + getShortDate() + "] " + (result === true ? "[PASS] " : (result === false ? "[FAIL] " : ""));
-    };
-
-    var getShortDate = function () {
-        /** Returns the current date and time formatted as "yyyy-mm-dd hh:mm:ss.nnn".*/
-        var padToLength = function (number, length) {
-            var result = number + "";
-            var lengthDiff = length - result.length;
-            for (var i = 0; i < lengthDiff; i++) {
-                result = "0" + result;
-            }
-
-            return result;
-        }
-
-        var date = new Date();
-        var day = padToLength(date.getDate(), 2);
-        var month = padToLength(date.getMonth() + 1, 2);
-        var year = date.getFullYear();
-
-        var hours = padToLength(date.getHours(), 2);
-        var minutes = padToLength(date.getMinutes(), 2);
-        var seconds = padToLength(date.getSeconds(), 2);
-        var milliseconds = padToLength(date.getMilliseconds(), 3);
-
-        return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliseconds;
-    };
-
-    var submitRecording = function () {
-        var body = { urls: recording };
-        postToUrl("LogBatch", body);
-    };
-
-    var postToUrl = function (methodName, body) {
-        /** POSTs body to the designated methodName.
-        */
-        var xhr;
-        if (window.XMLHttpRequest) {
-            xhr = new window.XMLHttpRequest();
-        } else {
-            xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
-        }
-
-        var url = serviceRoot + methodName;
-        xhr.open("POST", url, false);
-        xhr.setRequestHeader("Content-Type", "application/json");
-        xhr.send(window.JSON.stringify(body));
-        if (xhr.status < 200 || xhr.status > 299) {
-            throw { message: "Unable to POST to url.\r\n" + xhr.responseText };
-        }
-
-        return xhr.responseText;
-    }
-
-    function LogAssert(result, message, name, expected, actual) {
-        var parameterUrl = "pass=" + result + "&message=" + encodeURIComponent(message) + "&name=" + encodeURIComponent(name);
-
-        if (!result) {
-            parameterUrl += "&actual=" + encodeURIComponent(actual) + "&expected=" + encodeURIComponent(expected);
-        }
-
-        callTestSynchronizer("LogAssert", parameterUrl);
-    }
-
-    function LogTestStart(name) {
-        callTestSynchronizer("LogTestStart", "name=" + encodeURIComponent(name) + "&startTime=" + encodeURIComponent(getShortDate()));
-    }
-
-    function LogTestDone(name, failures, total) {
-        callTestSynchronizer("LogTestDone", "name=" + encodeURIComponent(name) + "&failures=" + failures + "&total=" + total + "&endTime=" + encodeURIComponent(getShortDate()));
-    }
-
-    function TestCompleted(failures, total) {
-        return callTestSynchronizer("TestCompleted", "failures=" + failures + "&total=" + total);
-    }
-
-    var extractTestRunId = function () {
-        /** Extracts the testRunId value from the window query string.
-         * @returns {String} testRunId, possibly empty.
-         */
-        var i, len;
-        var uri = window.location.search;
-        if (uri) {
-            var parameters = uri.split("&");
-            for (i = 0, len = parameters.length; i < len; i++) {
-                var index = parameters[i].indexOf("testRunId=");
-                if (index >= 0) {
-                    return parameters[i].substring(index + "testRunId=".length);
-                }
-            }
-        }
-
-        return "";
-    };
-
-    var init = function (qunit) {
-        /** Initializes the test logger synchronizer.
-        * @param qunit - Unit testing to hook into.
-        * If there is no testRunId present, the QUnit functions are left as they are.</remarks>
-        */
-        var logToConsole = function (context) {
-            if (window.console && window.console.log) {
-                window.console.log(context.result + ' :: ' + context.message);
-            }
-        };
-
-        testRunId = extractTestRunId();
-        if (!testRunId) {
-            qunit.log = logToConsole;
-        } else {
-            recording = [];
-            qunit.log = function (context) {
-                logToConsole(context);
-
-                var name = qunit.config.current.testName;
-                if (!(context.actual && context.expected)) {
-                    context.actual = context.result;
-                    context.expected = true;
-                }
-                LogAssert(context.result, getLogPrefix(context.result) + context.message, name, window.JSON.stringify(context.expected), window.JSON.stringify(context.actual));
-            };
-
-            qunit.testStart = function (context) {
-                LogTestStart(context.name);
-            };
-
-            qunit.testDone = function (context) {
-                LogTestDone(context.name, context.failed, context.total);
-            }
-
-            qunit.done = function (context) {
-                submitRecording();
-                recording = null;
-
-                var nextUrl = TestCompleted(context.failed, context.total);
-                nextUrl = JSON.parse(nextUrl).d;
-                if (nextUrl) {
-                    window.location.href = nextUrl;
-                }
-            }
-        }
-    };
-
-    window.TestSynchronizer = {
-        init: init
-    };
-})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/common.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/common.js b/datajs/tests/common/common.js
deleted file mode 100644
index 8151fc1..0000000
--- a/datajs/tests/common/common.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-(function (window, undefined) {
-        window.temp = window.odatajs;
-        window.temp.store = window.odatajs.store;
-        window.temp.cache = window.odatajs.cache;
-        window.odatajs = window.temp;
-        delete window.temp;
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/djstest-browser.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/djstest-browser.js b/datajs/tests/common/djstest-browser.js
deleted file mode 100644
index 366ca33..0000000
--- a/datajs/tests/common/djstest-browser.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
-// we define the @namespace djstest here instead of the a @module name djstest
-
-/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
- * @namespace djstest
- */
-
-
-var init = function init () {
-
-    var localDjstest = {};
-
-    // Initialize indexedDB if the window object is available
-    localDjstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
-
-    /** Cleans all the test data saved in the IndexedDb database.
-     * @param {Array} storeNames - Array of store objects with a property that is the name of the store
-     * @param {Function} done - Callback function
-     */
-    localDjstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
-        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
-
-        function deleteObjectStores(db) {
-            for ( var i = 0 ; i < db.objectStoreNames.length ; i ++) {
-                db.deleteObjectStore(db.objectStoreNames[i]);
-            }
-        }
-        var job;
-
-        if (localDjstest.indexedDB) {
-            job = new djstest.Job();
-            for ( var i = 0 ; i < storeObjects.length ; i ++) {
-                storeObject = storeObjects[i];
-                job.queue((function (storeObject) {
-                    return function (success, fail) {
-                        var dbname = "_datajs_" + storeObject.name;
-                        var request = localDjstest.indexedDB.open(dbname);
-                        request.onsuccess = function (event) {
-                            var db = request.result;
-
-                            if ("setVersion" in db) {
-                                var versionRequest = db.setVersion("0.1");
-                                versionRequest.onsuccess = function (event) {
-                                    var transaction = versionRequest.transaction;
-                                    transaction.oncomplete = function () {
-                                        db.close();
-                                        success();
-                                    };
-                                    deleteObjectStores(db);
-                                };
-                                versionRequest.onerror = function (e) {
-                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
-                                    fail();
-                                };
-                                return;
-                            }
-
-                            // new api cleanup
-                            db.close();
-                            var deleteRequest = localDjstest.indexedDB.deleteDatabase(dbname);
-                            deleteRequest.onsuccess = function (event) {
-                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
-                                success();
-                            };
-                            deleteRequest.onerror = function (e) {
-                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
-                                fail();
-                            };
-                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
-                        };
-
-                        request.onerror = function (e) {
-                            djstest.fail(e.code + ": " + e.message);
-                        };
-                    };
-                })(storeObject));
-            }
-        }
-
-        if (job) {
-            job.run(function (succeeded) {
-                if (!succeeded) {
-                    djstest.fail("cleanup job failed");
-                }
-                done();
-            });
-        }
-        else {
-            done();
-        }
-    };
-
-
-    // Disable caching to ensure that every test-related AJAX request is actually being sent,
-    // and set up a default error handler
-    if (typeof window !== undefined) {
-        $.ajaxSetup({
-            cache: false,
-            error: function (jqXHR, textStatus, errorThrown) {
-                // Work around bug in IE-Mobile on Windows Phone 7
-                if (jqXHR.status !== 1223) {
-                    var err = {
-                        status: jqXHR.status,
-                        statusText: jqXHR.statusText,
-                        responseText: jqXHR.responseText
-                    };
-                    djstest.fail("AJAX request failed with: " + djstest.toString(err));
-                }
-                djstest.done();
-            }
-        });
-    }
-    return localDjstest;
-};
-
-//export djstest
-
-if (typeof window !== 'undefined') {
-    //expose to browsers window object
-    if ( window.djstest === undefined) {
-        window.djstest = init();
-    } else {
-        var tmp = init();
-        $.extend( window.djstest,tmp);
-    }
-} else {
-    //expose in commonjs style
-    module.exports = init();
-}
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/djstest.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/djstest.js b/datajs/tests/common/djstest.js
deleted file mode 100644
index 5dda9ff..0000000
--- a/datajs/tests/common/djstest.js
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
-// we define the @namespace djstest here instead of the a @module name djstest
-
-/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
- * @namespace djstest
- */
-
-
-var init = function init () {
-    var djstest = {};
-  
-
-    /** Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.
-     * @class Job
-     * @constructor
-     * @returns {Object} Job object
-     */
-    djstest.Job = function () {
-        
-        var currentTask = -1;
-        var tasks = [];
-
-        var failedTasks = 0;
-
-        /** Adds a function to the job queue regardless if the queue is already executing or not.
-         * @method djstest.Job#queue
-         * @param {Function} fn - Function to execute.
-         */
-        this.queue = function (fn) {
-            
-            tasks.push(fn);
-        };
-
-        /** Adds a function to the front of the job queue regardless if the queue is already executing or not.
-         * @method djstest.Job#queueNext
-         * @param {Function} fn - Function to execute.
-         */
-        this.queueNext = function (fn) {
-        
-            if (currentTask < 0) {
-                tasks.unshift(fn);
-            } else {
-                tasks.splice(currentTask + 1, 0, fn);
-            }
-        };
-
-        /** Starts the execution of this job.
-         * @method djstest.Job#run
-         * @param {Function} done - Callback invoked when the job has finished executing all of its enqueued tasks.
-         */
-        this.run = function (done) {
-            /// This method does nothing if called on a unit of work that is already executing.
-            if (currentTask >= 0) {
-                return;
-            }
-
-            if (tasks.length === 0) {
-                done(true);
-                return;
-            }
-
-            /**
-             * @method djstest.Job~makeTaskDoneCallBack
-            */
-            function makeTaskDoneCallBack(failed) {
-                return function () {
-                    // Track the failed task and continue the execution of the job. 
-                    if (failed) {
-                        failedTasks++;
-                    }
-                    currentTask++;
-                    if (currentTask === tasks.length) {
-                        done(failedTasks === 0);
-                    } else {
-                        runNextTask();
-                    }
-                };
-            }
-
-            /** Executes the next function in the queue.
-             * @method djstest.Job~runNextTask
-            */
-            function runNextTask() {
-                defer(function () {
-                    try {
-                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
-                    } catch (e) {
-                        makeTaskDoneCallBack(true)();
-                    }
-                });
-            }
-
-            currentTask = 0;
-            runNextTask();
-        };
-    };
-
-    /** Defers the execution of an arbitrary function that takes no parameters.
-     * @memberof djstest
-     * @inner
-     * @param {Function} fn - Function to schedule for later execution.
-     */
-    function defer(fn) {
-        setTimeout(fn, 0);
-    }
-
-    /** Exposes date values for Date objects to facilitate debugging
-     * @memberof djstest
-     * @inner
-     * @param {Object} data - The object to operate on
-     */
-    function exposeDateValues(data) {
-     
-        if (typeof data === "object") {
-            if (data instanceof Date) {
-                data.__date__ = data.toUTCString();
-            }
-            else {
-                for (var prop in data) {
-                    exposeDateValues(data[prop]);
-                }
-            }
-        }
-
-        return data;
-    }
-
-    /** Determines the name of a function.
-     * @memberof djstest
-     * @inner
-     * @param {String} text - Function text.
-     * @returns {String} The name of the function from text if found; the original text otherwise.
-     */
-    function extractFunctionName(text) {
-
-        var index = text.indexOf("function ");
-        if (index < 0) {
-            return text;
-        }
-
-        var nameStart = index + "function ".length;
-        var parensIndex = text.indexOf("(", nameStart);
-        if (parensIndex < 0) {
-            return text;
-        }
-
-        var result = text.substr(nameStart, parensIndex - nameStart);
-        if (result.indexOf("test") === 0) {
-            result = result.substr("test".length);
-        }
-
-        return result;
-    }
-
-    /** Removes metadata annotations from the specified object.
-     * @memberof djstest
-     * @inner
-     * @param data - Object to remove metadata from; possibly null.
-     */
-    function removeMetadata(data) {
-
-        if (typeof data === "object" && data !== null) {
-            delete data.__metadata;
-            for (var prop in data) {
-                removeMetadata(data[prop]);
-            }
-        }
-    }
-
-    /** Add the unit test cases
-     * @param disable - Indicate whether this test case should be disabled
-    */
-    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
-
-        if (disable !== true) {
-            djstest.addTest(fn, name, arg, timeout);
-        }
-    };
-
-    /** Add the unit test cases
-     * @param disable - Indicate whether this test case should be disabled
-    */
-    djstest.addTest = function (fn, name, arg, timeout) {
-        if (!name) {
-            name = extractFunctionName(fn.toString());
-        }
-
-        test(name, function () {
-            if (!timeout) {
-                timeout = 20000;
-            }
-
-            QUnit.config.testTimeout = timeout;
-            QUnit.stop();
-            fn.call(this, arg);
-        });
-    };
-
-    /** Asserts that a condition is true.
-     * @param {Boolean} test - Condition to test.
-     * @param {String} message - Text message for condition being tested.
-     */
-    djstest.assert = function (test, message) {
-        
-        QUnit.ok(test, message);
-    };
-
-    /** Asserts that the values of the expected and actualobjects are equal.
-     * @memberof djstest
-     * @inner
-     */
-    djstest.assertAreEqual = function (actual, expected, message) {
-        QUnit.equal(actual, expected, message);
-    };
-
-    /** Asserts that the actual and expected objects are the same.
-     */
-    djstest.assertAreEqualDeep = function (actual, expected, message) {
-        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
-    };
-
-    /** Asserts that the actual and expected objects are the same but removes the metadata bevore
-     */
-    djstest.assertWithoutMetadata = function (actual, expected, message) {
-        removeMetadata(actual);
-        removeMetadata(expected);
-        djstest.assertAreEqualDeep(actual, expected, message);
-    };
-
-    /** Calls each async action in asyncActions, passing each action a function which keeps a count and
-     * calls the passed done function when all async actions complete
-     * @param {Array} asyncActions -Array of asynchronous actions to be executed, 
-     * each taking a single parameter - the callback function to call when the action is done.</param>
-     * @param {Function} done - Function to be executed in the last async action to complete.
-     */
-    djstest.asyncDo = function (asyncActions, done) {
-
-        var count = 0;
-        var doneOne = function () {
-            count++;
-            if (count >= asyncActions.length) {
-                done();
-            }
-        };
-
-        if (asyncActions.length > 0) {
-            for ( var i = 0; i < asyncActions.length; i++) {
-                asyncActions[i](doneOne);
-            }
-        } else {
-            done();
-        }
-    };
-
-    /** Makes a deep copy of an object.
-     */
-    djstest.clone = function (object) {
-        if ( object === undefined ) {
-            return undefined;
-        } else if (object === null) {
-            return null;
-        } else if (typeof(object) !== 'object') {
-            return object;
-        } else {
-            var ret = {};
-            for(var key in object) {
-                if(object.hasOwnProperty(key)) {
-                    ret[key] = this.clone(object[key]);
-                }
-            }
-            return ret;
-        }
-        throw("Error cloning an object");
-    };
-
-    /** Destroys the cache and then completes the test
-     * @param cache - The cache to destroy
-     */
-    djstest.destroyCacheAndDone = function (cache) {
-     
-        cache.clear().then(function () {
-            djstest.done();
-        }, function (err) {
-            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
-            djstest.done();
-        });
-    };
-
-    /** Indicates that the currently running test has finished.
-     */
-    djstest.done = function () {
-      
-        QUnit.start();
-    };
-
-    /** Test passes if and only if an exception is thrown.
-     */
-    djstest.expectException = function (testFunction, message) {
-     
-        try {
-            testFunction();
-            djstest.fail("Expected exception but function succeeded: " + " " + message);
-        }
-        catch (e) {
-            // Swallow exception.
-            djstest.pass("Thrown exception expected");
-        }
-    };
-
-    /** Indicates the expected number of asserts, fails test if number is not met.
-     * @param {Number} asserts - Number of asserts expected in test.
-     */
-    djstest.assertsExpected = function (asserts) {
-        
-        expect(asserts);
-    };
-    /** Marks the current test as failed.
-     * @param {String} message - Failure message.
-     */
-    djstest.fail = function (message) {
-
-        QUnit.ok(false, message);
-    };
-
-    /** Returns a function that when invoked will fail this test and be done with it.
-     * @param {String} message - Failure message.
-     * @param {Function} [cleanupCallback] - 
-     * @returns {Function} A new function.
-     */
-    djstest.failAndDoneCallback = function (message, cleanupCallback) {
-
-        return function (err) {
-            message = "" + message + (err) ? JSON.stringify(err) : "";
-            djstest.fail(message);
-            if (cleanupCallback) {
-                try {
-                    cleanupCallback();
-                } catch (e) {
-                    djstest.fail("error during cleanupCallback: " + JSON.stringify(e));
-                }
-            }
-
-            djstest.done();
-        };
-    };
-
-    /** Logs a test message.
-     * @param {String} message - Test message.
-     */
-    djstest.log = function (message) {
-
-        var context = { result: true, actual: true, expected: true, message: message };
-        QUnit.log(context);
-    };
-
-    /** Marks the current test as failed.
-     * @param {String} message - Failure message.
-     */
-    djstest.pass = function (message) {
-        QUnit.ok(true, message);
-    };
-
-    /** Dumps the object as a string
-     * @param {Object} obj - Object to dump
-     */
-    djstest.toString = function (obj) {
-
-        return QUnit.jsDump.parse(obj);
-    };
-
-    /** Executes the function, pausing test execution until the callback is called
-     * @param {Function} fn - Function to execute; takes one parameter which is the callback
-     * This function is typically used in asynchronous setup/teardown methods</remarks>
-     */
-    djstest.wait = function (fn) {
-        QUnit.stop();
-        fn(function () {
-            QUnit.start();
-        });
-    };
-
-    return djstest;
-};
-
-//export djstest
-
-if (typeof window !== 'undefined') {
-    //expose to browsers window object
-    if ( window.djstest === undefined) {
-        window.djstest = init();
-    } else {
-        var tmp = init();
-        $.extend( window.djstest,tmp);
-    }
-} else {
-    //expose in commonjs style
-    module.exports = init();
-}
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/mockHttpClient.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/mockHttpClient.js b/datajs/tests/common/mockHttpClient.js
deleted file mode 100644
index f5b2bd0..0000000
--- a/datajs/tests/common/mockHttpClient.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-//mockHttpClient.js
-//this object allows for associating a uri with a requestVerfier and mock responses that will be sent back to the client of the httpStack.  
-//It can be used to replace OData's httpClient for testing purposes.
-//
-//RequestVerifiers
-//
-//    A request verifier is a function associated to a particular URI that will be executed by the mockHttpClient when it receives a request with the matching URI.
-//    the callback receives as its only parameter the request object passed to the mockHttpClient.
-//
-//    To register a request verifier, simply do 
-//        
-//            MockHttpClient.addRequestVerifier("http://someUri", function(request) {
-//                djstest.assertAreEqual(request.requestUri,"http://someUri");
-//            }
-//
-//Responses
-//    Mock responses can be associated with a particular URI.  When the MockHttpClient receives a request with a URI mapped to a response, then it will, 
-//    depending on the response status code invoke either the success or the error callbacks. 
-//
-//    To register a response,
-//       
-//           MockHttpClient.addResponse("http://someUri", {status: 200, body:"some body"});
-//
-//Exceptions
-//    MockHttpClient will throw an exception if it receives a request to a URI that is not mapped to either a request verifier or a response.
-//
-
-function init(window, undefined) {
-
-    var httpClient = {};
-
-    var responses = {};
-    var requestVerifiers = {};
-
-    httpClient.addRequestVerifier = function (uri, verifier) {
-        requestVerifiers[uri] = verifier;
-        return this;
-    };
-
-    httpClient.addResponse = function (uri, response) {
-        responses[uri] = response;
-        return this;
-    };
-
-    httpClient.async = false;
-
-    httpClient.clear = function () {
-        /** Clears all registered responses and verifiers.
-         * @returns this client
-         */
-        responses = {};
-        requestVerifiers = {};
-        this.async = false;
-        return this;
-    };
-
-    httpClient.request = function (request, success, error) {
-        var uri = request.requestUri;
-        var verifier = requestVerifiers[uri];
-        var response = responses[uri];
-
-        if (verifier === undefined) {
-            verifier = requestVerifiers["*"];
-        }
-
-        if (response === undefined) {
-            response = responses["*"];
-        }
-
-        if (!verifier && !response) {
-            throw { message: "neither verifier or response defined for uri: " + uri };
-        }
-
-        if (verifier) {
-            verifier(request);
-        }
-
-        if (response) {
-            response.requestUri = uri;
-            if (response.statusCode >= 200 && response.statusCode <= 299) {
-                if (this.async) {
-                    setTimeout(function () {
-                        success(response);
-                    });
-                } else {
-                    success(response);
-                }
-            } else {
-                if (this.async) {
-                    setTimeout(function () {
-                        error({ message: "failed test response", request: request, response: response });
-                    });
-                }
-                else {
-                    error({ message: "failed test response", request: request, response: response });
-                }
-            }
-        }
-    };
-
-    httpClient.setAsync = function (value) {
-        this.async = value;
-        return this;
-    };
-
-    return httpClient;
-}
-
-
-
-if (typeof window !== 'undefined') {
-    //in browser call init() directly window as context
-    window.MockHttpClient = init(window);
-} else {
-    //expose function init to be called with a custom context
-    module.exports.init = init;
-}
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/mockXMLHttpRequest.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/mockXMLHttpRequest.js b/datajs/tests/common/mockXMLHttpRequest.js
deleted file mode 100644
index fdd6026..0000000
--- a/datajs/tests/common/mockXMLHttpRequest.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- // mockXMLHttpRequest.js
-//
-// This file provides a window.MockXMLHttpRequest object that can be used
-// to replace or wrap the browser's XMLHttpRequest object for testing.
-//
-// Typically the object is installed, a test run, and then the original
-// object restored. The addResponse and addRequest verifier can be
-// used to set up callbacks; reset is used to clear those values.
-//
-// For a sample demonstrating how to use this functionality, see
-// the httpClientSendRequestTest test in odata-net-tests.js.
-
-(function (window, undefined) {
-
-    if (!window.MockXMLHttpRequest) {
-        window.MockXMLHttpRequest = {};
-    }
-
-    var mockXMLHttpRequest = window.MockXMLHttpRequest;
-
-    var responses = {};
-    var verifiers = {};
-
-    mockXMLHttpRequest.addResponse = function (uri, response) {
-        /** Adds a new response to be returned for the specified uri (* for 'anything').
-         * @param {String} uri - URI to match (* to match anything not otherwise specified).
-         * @param {Object} response - Response object.
-         */
-        responses = responses || {};
-        responses[uri] = response;
-
-        return this;
-    };
-
-    mockXMLHttpRequest.addRequestVerifier = function (uri, verifier) {
-        /** Adds a new request verifier to be invoked for the specified uri (* for 'anything').
-         * @param {String} uri - URI to match (* to match anything not otherwise specified).
-         * @param {Function} response - Verifier callback that takes the request.
-        */
-        verifiers = verifiers || {};
-        verifiers[uri] = verifier;
-
-        return this;
-    };
-
-    mockXMLHttpRequest.reset = function () {
-        /** Resets all configuration from the mock XHR object.
-        */
-
-        responses = {};
-        verifiers = {};
-
-        mockXMLHttpRequest.onCreate = undefined;
-        mockXMLHttpRequest.onAfterSend = undefined;
-
-        return this;
-    };
-
-    var xmlHttpRequest = function () {
-        //properties
-        this.readyState = 0;
-        this.responseXML = undefined;
-
-        //events
-        this.ontimeout = undefined;
-        this.onreadystatechange = undefined;
-
-        if (mockXMLHttpRequest.onCreate) {
-            mockXMLHttpRequest.onCreate(this);
-        }
-    };
-
-    xmlHttpRequest.prototype.open = function (method, url, async, user, password) {
-        if (!method) {
-            throw { method: "method parameter is not defined, empty, or null " };
-        }
-        if (!url) {
-            throw { message: "url parameter is not defined, empty, or null " };
-        }
-
-        this._request = {
-            headers: {},
-            url: url,
-            method: method,
-            async: async,
-            user: user,
-            password: password
-        };
-    };
-
-    xmlHttpRequest.prototype.getAllResponseHeaders = function () {
-        if (!this._response) {
-            throw { message: "_response property is undefined, did you forget to call send() or map the request url to a response?" };
-        }
-
-        var result = "";
-        var header;
-        for (header in this._response.headers) {
-            result = result + header + ": " + this._response.headers[header] + "\n\r";
-        }
-        //remove trailing LFCR
-        return result.substring(0, result.length - 2);
-    };
-
-    xmlHttpRequest.prototype.getResponseHeader = function (header) {
-        if (!this._response) {
-            throw { message: "_response property is undefined, did you forget to call send() or map the request url to a response?" };
-        }
-        return this._response.headers[header];
-    };
-
-    xmlHttpRequest.prototype.abort = function () {
-        //do nothing for now.
-    };
-
-    xmlHttpRequest.prototype.setRequestHeader = function (header, value) {
-        if (!this._request) {
-            throw { message: "_request property is undefined, did you forget to call open() first?" };
-        }
-        this._request.headers[header] = value;
-    };
-
-    xmlHttpRequest.prototype.send = function (data) {
-        if (!this._request) {
-            throw { message: "_request property is undefined, did you forget to call open() first?" };
-        }
-
-        if (this._request.headers["MockNoOp"]) {
-            return;
-        }
-
-        if (this._request.headers["MockTimeOut"]) {
-            if (!this.timeout) {
-                throw { message: "timeout property is not set" };
-            }
-
-            if (this.ontimeout) {
-                (function (xhr) {
-                    setTimeout(function () {
-                        xhr.ontimeout();
-                    }, xhr.timeout);
-                })(this);
-            }
-            return;
-        }
-
-        var url = this._request.url;
-        var verifier = verifiers[url];
-        var response = responses[url];
-
-        if (!verifier) {
-            verifier = verifiers["*"];
-        }
-
-        if (!response) {
-            response = responses["*"];
-        }
-
-        if (!verifier && !response) {
-            throw { message: "neither verifier or response defined for url: " + url };
-        }
-
-        this._request.body = data;
-
-        if (verifier) {
-            verifier(this._request);
-        }
-
-        if (response) {
-            // Execute the respone after a 30ms delay.
-            this._response = response;
-            sendResponseDelay(this, response, 60);
-        }
-    };
-
-    var sendResponseDelay = function (xhr, response, delay) {
-        setTimeout(function () {
-            xhr.status = response.status;
-            xhr.responseText = response.body;
-            xhr.responseBody = response.body;
-
-            xhr.readyState = 4;
-            if (xhr.onreadystatechange) {
-                xhr.onreadystatechange();
-                if (mockXMLHttpRequest.onAfterSend) {
-                    mockXMLHttpRequest.onAfterSend();
-                }
-            }
-        }, delay);
-    };
-
-    mockXMLHttpRequest.XMLHttpRequest = xmlHttpRequest;
-
-})(this);


[05/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-json-parse-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-json-parse-tests.html b/odatajs/tests/odata-json-parse-tests.html
new file mode 100644
index 0000000..57db067
--- /dev/null
+++ b/odatajs/tests/odata-json-parse-tests.html
@@ -0,0 +1,67 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!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/odatajs-4.0.0-beta-01.js"></script>   
+    <script type="text/javascript" src="common/common.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/d5ec5557/odatajs/tests/odata-json-parse-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-json-parse-tests.js b/odatajs/tests/odata-json-parse-tests.js
new file mode 100644
index 0000000..00f0ba2
--- /dev/null
+++ b/odatajs/tests/odata-json-parse-tests.js
@@ -0,0 +1,110 @@
+/*
+ * 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,
+        };
+        odatajs.oData.read(metadataRequest, metaDatasuccess, errorFunc,OData.metadataHandler);
+    }
+
+    djstest.addTest(function test1() {
+        var checkAll = function (metadata, input, expected) {
+            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
+            djstest.assertAreEqual(info,expected, "Test context fragment: "+ input);
+        };
+
+        var checkLastTypeName = function (metadata, input, expectedKind, expectedLastTypeName) {
+            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
+            djstest.assertAreEqual(info.detectedPayloadKind,expectedKind, "Test context fragment: "+ input);
+            djstest.assertAreEqual(info.typeName,expectedLastTypeName, "Test context fragment: "+ input);
+        };
+
+        var checkProjection = function (metadata, input, expectedKind, expectedLastTypeName, projection) {
+            var info = window.odatajs.oData.json.createPayloadInfo({ "@odata.context" : input}, metadata);
+            djstest.assertAreEqual(info.detectedPayloadKind,expectedKind, "Test context fragment: "+ input);
+            djstest.assertAreEqual(info.typeName,expectedLastTypeName, "Test context fragment: "+ input);
+            djstest.assertAreEqual(info.projection,projection, "Test context fragment: "+ input);
+        };
+
+        var checkKind = function (metadata, input, expected) {
+            var info = window.odatajs.oData.json.createPayloadInfo({ "@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
+            checkLastTypeName(metadata, '#Foods', 'f', 'DataJS.Tests.V4.Food');
+            //Chapter 10.3
+            checkLastTypeName(metadata, '#Foods/$entity', 'e', 'DataJS.Tests.V4.Food');
+            //Chapter 10.4
+            //checkKind(metadata, '#Singleton', '');
+            //Chapter 10.5
+            checkLastTypeName(metadata, '#Foods/DataJS.Tests.V4.Food', 'f', 'DataJS.Tests.V4.Food');
+            //Chapter 10.6
+            checkLastTypeName(metadata, '#Foods/DataJS.Tests.V4.Food/$entity', 'e', 'DataJS.Tests.V4.Food');
+            //Chapter 10.7
+            checkProjection(metadata, '#Foods(FoodID,Name)', 'f', 'DataJS.Tests.V4.Food','FoodID,Name');
+            //Chapter 10.8
+            checkProjection(metadata, '#Foods(FoodID,Name)/$entity', 'e', 'DataJS.Tests.V4.Food','FoodID,Name');
+            //Chapter 10.9
+            checkProjection(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))', 'f', 
+                'DataJS.Tests.V4.Food','FoodID,Name,Category,Category+(CategoryID,Name)');
+            //Chapter 10.10
+            checkProjection(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))/$entity', 'e',
+                'DataJS.Tests.V4.Food','FoodID,Name,Category,Category+(CategoryID,Name)');
+            //Chapter 10.11
+            checkKind(metadata, '#Collection($ref)', 'erls');
+            //Chapter 10.12
+            checkKind(metadata, '#$ref', 'erl');
+            //Chapter 10.13
+            checkKind(metadata, '#Foods(0)/Packaging', 'p', 'DataJS.Tests.V4.Package');
+            //Chapter 10.14
+            checkKind(metadata, '#Collection(Edm.String)', 'c',  'Edm.String');
+            //Chapter 10.15
+            checkKind(metadata, '#Edm.String', 'v');
+
+            checkKind(metadata, '#Edm.Null', 'v');
+            //TODO add tests for delta tokens
+            djstest.done();
+        };
+
+        runWithMetadata(success);
+    },'test createPayloadInfo');
+
+
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-json-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-json-tests.js b/odatajs/tests/odata-json-tests.js
new file mode 100644
index 0000000..7d30a7c
--- /dev/null
+++ b/odatajs/tests/odata-json-tests.js
@@ -0,0 +1,986 @@
+/*
+ * 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) {
+   
+    
+    djstest.addTest(function isArrayTest() {
+        console.log("hier-----------------------");
+        djstest.assert(odatajs.utils.isArray([]));
+        djstest.assert(odatajs.utils.isArray([1, 2]));
+        djstest.assert(!odatajs.utils.isArray({}));
+        djstest.assert(!odatajs.utils.isArray("1,2,3,4"));
+        djstest.assert(!odatajs.utils.isArray());
+        djstest.assert(!odatajs.utils.isArray(null));
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonParserTest() {
+        var tests = [
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: {} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata",
+                    value: [
+                      {
+                          name: "Products",
+                          kind: "EntitySet",
+                          url: "Products"
+                      },
+                      {
+                          name: "ProductDetails",
+                          kind: "EntitySet",
+                          url: "ProductDetails"
+                      }
+                  ]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    value: [
+                      {
+                          name: "Products",
+                          kind: "EntitySet",
+                          url: "http://foo/OData.svc/Products"
+                      },
+                      {
+                          name: "ProductDetails",
+                          kind: "EntitySet",
+                          url: "http://foo/OData.svc/ProductDetails"
+                      }
+                  ]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { "@odata.context": "http://foo/OData.svc/$metadata#Products(0)/Name", value: "Bread"} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
+                    value: [
+                      {
+                          "@odata.type": "#ODataDemo.Product",
+                          "@odata.id": "http://foo/OData.svc/Products(0)",
+                          "@odata.editLink": "Products(0)",
+                          "Categories@odata.navigationLink": "Products(0)/Categories",
+                          "Categories@odata.associationLink": "Products(0)/Categories/$ref",
+                          "Supplier@odata.navigationLink": "Products(0)/Supplier",
+                          "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
+                          "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
+                          "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          "ReleaseDate@odata.type": "#DateTimeOffset",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          "Rating@odata.type": "#Int16",
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
+                    value: [
+                      {
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                }
+            },
+             { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                 expected: {
+                     value: [
+                      {
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                 }
+             },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
+                      "@odata.type": "#ODataDemo.Product",
+                      "@odata.id": "http://foo/OData.svc/Products(0)",
+                      "@odata.editLink": "Products(0)",
+                      "Categories@odata.navigationLink": "Products(0)/Categories",
+                      "Categories@odata.associationLink": "Products(0)/Categories/$ref",
+                      "Supplier@odata.navigationLink": "Products(0)/Supplier",
+                      "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
+                      "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
+                      "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      "ReleaseDate@odata.type": "#DateTimeOffset",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      "Rating@odata.type": "#Int16",
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/$metadata#Customer(-10)/PrimaryContactInfo/AlternativeNames",
+                      "@odata.type": "#Collection(String)",
+                      value: [
+                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
+                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
+                      "btsnhqrjqryqzgxducl",
+                      "qbtlssjhunufmzdv",
+                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
+                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
+                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
+                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
+                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
+                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
+                     ]
+                  }
+              }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var data = JSON.stringify(tests[i].expected);
+            var actual = window.odatajs.oData.json.jsonParser(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
+            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected data");
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonSerializerTest() {
+        var tests = [
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: ""} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: []} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    ID: 0,
+                    Name: "Bread",
+                    Description: "Whole grain bread",
+                    ReleaseDate: "1992-01-01T00:00:00Z",
+                    DiscontinuedDate: null,
+                    Rating: 4,
+                    Price: 2.5
+                }
+            },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   value: [
+                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
+                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
+                      "btsnhqrjqryqzgxducl",
+                      "qbtlssjhunufmzdv",
+                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
+                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
+                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
+                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
+                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
+                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
+                     ]
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   ID: 0,
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                   "@odata.editLink": "Foods(0)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                   ID: 0,
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   value : [{
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   }]
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.editLink": "Foods(0)",
+                   value : [{
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   }]
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   ID: 0,
+                   ComplexInLayerOne:
+                   {
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 1,
+                       ComplexInLayerTwo:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 2,
+                           ComplexInLayerThree:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 3,
+                               Name: "BreadInLayer3",
+                               Description: "Whole grain bread inLayer3",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 7,
+                               Price: 5.5
+                           },
+                           Name: "BreadInLayer2",
+                           Description: "Whole grain bread inLayer2",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 6,
+                           Price: 4.5
+                       },
+                       Name: "BreadInLayer1",
+                       Description: "Whole grain bread inLayer1",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 5,
+                       Price: 3.5
+                   },
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                   "@odata.editLink": "Foods(0)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                   ID: 0,
+                   ComplexInLayerOne:
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                       ID: 1,
+                       ComplexInLayerTwo:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                           ID: 2,
+                           ComplexInLayerThree:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                               ID: 3,
+                               Name: "BreadInLayer3",
+                               Description: "Whole grain bread inLayer3",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 7,
+                               Price: 5.5
+                           },
+                           Name: "BreadInLayer2",
+                           Description: "Whole grain bread inLayer2",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 6,
+                           Price: 4.5
+                       },
+                       Name: "BreadInLayer1",
+                       Description: "Whole grain bread inLayer1",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 5,
+                       Price: 3.5
+                   },
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   value: [{
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.id": "Foods(2)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 1,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1999-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 6,
+                       Price: 3.5
+                   }]
+               },
+               data: {
+                   value: [{
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(2)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(2)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink2",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink2",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType2",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag2",
+                       ID: 1,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1999-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 6,
+                       Price: 3.5
+                   }]
+               }
+           }
+          ];
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var data = tests[i].data ? tests[i].data : tests[i].expected;
+            var actual = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
+            var expected = JSON.stringify(tests[i].expected);
+            djstest.assertAreEqualDeep(actual, expected, "test " + i + "didn't return the expected data");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function normalizeHeadersReadTest() {
+        // Verifies that headers are normalized for reading.
+        // See issue at http://datajs.codeplex.com/workitem/148
+        MockHttpClient.clear();
+
+        MockHttpClient.clear().addResponse("/foo", {
+            statusCode: 200,
+            body: { "@odata.context": "http://foo", value: [] },
+            headers: { "unknown": "u", "Content-Encoding": "compress, gzip", "Content-Length": "8042",
+                "Content-Type": "application/json", "OData-Version": "4.0", "Etag": "Vetag", "Location": "foo", "OData-EntityId": "entityId",
+                "Preference-Applied": "prefered", "Retry-After": "retry"
+            }
+        });
+
+        odatajs.oData.read("/foo", function (data, response) {
+            // djstest.assertAreEqual(data.results.length, 2, "data.results.length has two entries");
+            djstest.assertAreEqual(response.headers.unknown, "u", "u unmodified");
+            djstest.assertAreEqual(response.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
+            djstest.assertAreEqual(response.headers["Content-Length"], "8042", "Content-Length available");
+            djstest.assertAreEqual(response.headers["Content-Type"], "application/json", "Content-Type available");
+            djstest.assertAreEqual(response.headers["ETag"], "Vetag", "Content-Type available");
+            djstest.assertAreEqual(response.headers["Location"], "foo", "Content-Type available");
+            djstest.assertAreEqual(response.headers["OData-EntityId"], "entityId", "OData-EntityId available");
+            djstest.assertAreEqual(response.headers["Preference-Applied"], "prefered", "Preference-Applied available");
+            djstest.assertAreEqual(response.headers["Retry-After"], "retry", "Retry available");
+            djstest.assertAreEqual(response.headers["OData-Version"], "4.0", "OData-Version available");
+            djstest.done();
+        }, undefined, undefined, MockHttpClient);
+    });
+
+    djstest.addTest(function normalizeHeadersWriteTest() {
+
+        // Verifies that headers are normalized for writing.
+        // See issue at http://datajs.codeplex.com/workitem/148
+
+        MockHttpClient.clear().addRequestVerifier("/foo", function (request) {
+            djstest.assertAreEqual(request.headers.Accept, "application/json", "Accept available");
+            djstest.assertAreEqual(request.headers["Content-Type"], "application/json", "json found");
+            djstest.assertAreEqual(request.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
+            djstest.assertAreEqual(request.headers["Content-Length"], "8042", "Content-Length available");
+            djstest.assertAreEqual(request.headers["OData-Version"], "4.0", "OData-Version available");
+            djstest.assertAreEqual(request.headers["Accept-Charset"], "Accept-Charset", "Accept-Charset available");
+            djstest.assertAreEqual(request.headers["If-Match"], "true", "If-Match available");
+            djstest.assertAreEqual(request.headers["If-None-Match"], "false", "If-None-Match available");
+            djstest.assertAreEqual(request.headers["OData-Isolation"], "isolation", "OData-Isolation available");
+            djstest.assertAreEqual(request.headers["OData-MaxVersion"], "4.0", "OData-MaxVersion available");
+            djstest.assertAreEqual(request.headers["Prefer"], "prefer", "prefer available");
+            djstest.done();
+        });
+
+        var request = {
+            method: "POST",
+            requestUri: "/foo",
+            data: { value: 123 },
+            headers: { "Accept": "application/json", "Content-Encoding": "compress, gzip", "Content-Length": "8042", "content-type": "application/json", "OData-Version": "4.0",
+                "accept-charset": "Accept-Charset", "if-match": "true", "if-none-match": "false", "odata-isolation": "isolation",
+                "odata-maxversion": "4.0", "prefer": "prefer"
+            }
+        };
+        odatajs.oData.request(request, function (data) { }, undefined, undefined, MockHttpClient);
+
+    });
+
+    var verifyReadJsonLightDataMetadataFull = function (input, expected, message, model) {
+        var response = { 
+          headers: { 
+            "Content-Type": "application/json;odata.metadata=full",
+             DataServiceVersion: "4.0"
+          },
+          body: JSON.stringify(input) 
+        };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+
+    var verifyReadJsonLightDataMetadataMinimal= function (input, expected, message, model) {
+        var response = { 
+          headers: { 
+            "Content-Type": "application/json;odata.metadata=minimal",
+             DataServiceVersion: "4.0"
+          },
+          body: JSON.stringify(input) 
+        };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+    var getPointValue =  { edmType : 'GeographyPoint', value : {
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: "Point",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+
+    var getLineStringValue =  { edmType : 'GeographyLineString', value : {
+                "type": "LineString",
+                "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
+                crs: {
+                    type: "LineString",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+
+    var getPolygonValue =  { edmType : 'GeographyPolygon', value : {
+                "type": "Polygon",
+                "coordinates": [
+                  [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
+                  [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
+                  ],
+                crs: {
+                    type: "Polygon",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+
+    var getMultiPointValue =  { edmType : 'GeographyMultiPoint', value : {
+                "type": "MultiPoint",
+                "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
+                crs: {
+                    type: "MultiPoint",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+
+    var getMultiLineStringValue =  { edmType : 'GeographyMultiLineString', value : {
+                  "type": "MultiLineString",
+                  "coordinates": [
+                      [ [100.0, 0.0], [101.0, 1.0] ],
+                      [ [102.0, 2.0], [103.0, 3.0] ]
+                    ],
+                crs: {
+                    type: "MultiLineString",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+      var getMultiPolygonStringValue =  { edmType : 'GeographyMultiPolygon', value : {
+                  "type": "MultiPolygon",
+                  "coordinates": [
+                    [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
+                    [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
+                     [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
+                    ],
+                crs: {
+                    type: "MultiPolygon",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+              }};
+
+      var getWorkload = [getPointValue, getLineStringValue, getPolygonValue, getMultiPointValue, getMultiLineStringValue, getMultiPolygonStringValue ];
+
+
+      djstest.addTest(function jsonReadGeometryPointFull() {
+
+        for ( var i = 0; i < getWorkload.length; i++) {
+          var item = getWorkload[i]; 
+          var input = {
+            "@odata.context": "http://someUri#Edm."+item.edmType,
+            "value@odata.type" : item.edmType,
+            value: item.value
+          }; 
+
+          var expected = {
+            "@odata.context": "http://someUri#Edm."+item.edmType,
+            "value@odata.type" : item.edmType,
+            value: item.value
+          };
+          verifyReadJsonLightDataMetadataFull(input, expected, "Json light top level primitive property was read properly.");
+        }
+        
+        djstest.done();
+    });
+
+
+    djstest.addTest(function jsonReadGeometryPointMinimal() {
+      for ( var i = 0; i < getWorkload.length; i++) {
+        var item = getWorkload[i]; 
+        var input = {
+            "@odata.context": "http://someUri#Edm."+item.edmType,
+            value: item.value
+        };
+
+        var expected = {
+            "@odata.context": "http://someUri#Edm."+item.edmType,
+            value: item.value,
+            "value@odata.type" : item.edmType,
+        };
+
+        verifyReadJsonLightDataMetadataMinimal(input, expected, "Json light top level primitive property was read properly.", {});
+      }
+      djstest.done();
+    });
+
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-links-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-links-functional-tests.html b/odatajs/tests/odata-links-functional-tests.html
new file mode 100644
index 0000000..21952d8
--- /dev/null
+++ b/odatajs/tests/odata-links-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData tests against local service</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>   
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-links-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">OData.Read tests against local in-memory service</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-links-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-links-functional-tests.js b/odatajs/tests/odata-links-functional-tests.js
new file mode 100644
index 0000000..eb64ec0
--- /dev/null
+++ b/odatajs/tests/odata-links-functional-tests.js
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var uriRegEx = /^([^:/?#]+:)?(\/\/[^/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
+    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
+
+    var getURIInfo = function (uri) {
+        /** Gets information about the components of the specified URI.
+         * @param {String} uri - URI to get information from.
+         * @returns {Object}
+         * An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
+         */
+
+        var result = { isAbsolute: false };
+
+        if (uri) {
+            var matches = uriRegEx.exec(uri);
+            if (matches) {
+                var i, len;
+                for (i = 0, len = uriPartNames.length; i < len; i++) {
+                    if (matches[i + 1]) {
+                        result[uriPartNames[i]] = matches[i + 1];
+                    }
+                }
+            }
+            if (result.scheme) {
+                result.isAbsolute = true;
+            }
+        }
+
+        return result;
+    };
+
+    var normalizeURI = function (uri, base) {
+        /** Normalizes a possibly relative URI with a base URI.
+         * @param {String} uri - URI to normalize, absolute or relative.
+         * @param {String} base - Base URI to compose with (may be null)
+         * @returns {String} The composed URI if relative; the original one if absolute.
+         */
+
+        if (!base) {
+            return uri;
+        }
+
+        var uriInfo = getURIInfo(uri);
+        if (uriInfo.isAbsolute) {
+            return uri;
+        }
+
+        var baseInfo = getURIInfo(base);
+        var normInfo = {};
+
+        if (uriInfo.authority) {
+            normInfo.authority = uriInfo.authority;
+            normInfo.path = uriInfo.path;
+            normInfo.query = uriInfo.query;
+        } else {
+            if (!uriInfo.path) {
+                normInfo.path = baseInfo.path;
+                normInfo.query = uriInfo.query || baseInfo.query;
+            } else {
+                if (uriInfo.path.charAt(0) === '/') {
+                    normInfo.path = uriInfo.path;
+                } else {
+                    normInfo.path = mergeUriPathWithBase(uriInfo, baseInfo);
+                }
+
+                normInfo.query = uriInfo.query;
+            }
+
+            normInfo.authority = baseInfo.authority;
+        }
+
+        normInfo.scheme = baseInfo.scheme;
+        normInfo.fragment = uriInfo.fragment;
+
+        return "".concat(
+            normInfo.scheme || "",
+            normInfo.authority || "",
+            normInfo.path || "",
+            normInfo.query || "",
+            normInfo.fragment || "");
+    };
+
+    var mergeUriPathWithBase = function (uriInfo, baseInfo) {
+        /** Merges the path of a relative URI and a base URI.
+         * @param uriInfo - URI component information for the relative URI.
+         * @param baseInfo - URI component information for the base URI.
+         * @returns {String} A string with the merged path.
+         */
+
+        var basePath = "/";
+        if (baseInfo.path) {
+            var end = baseInfo.path.lastIndexOf("/");
+            basePath = baseInfo.path.substring(0, end);
+
+            if (basePath.charAt(basePath.length - 1) !== "/") {
+                basePath = basePath + "/";
+            }
+        }
+
+        return basePath + uriInfo.path;
+    };
+
+    var services = [
+        "./endpoints/FoodStoreDataServiceV4.svc"
+    ];
+
+    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
+
+    var httpStatusCode = {
+        created: 201,
+        noContent: 204,
+        notFound: 404
+    };
+
+    $.each(services, function (_, service) {
+
+        var foodsFeed = service + "/Foods";
+        var categoriesFeed = service + "/Categories";
+
+        var baseLinkUri = normalizeURI(service.substr(2), window.location.href);
+
+        var newFoodLinks = {
+            "@odata.id": baseLinkUri + "/Foods" + "(1)"
+        };
+
+        var newCategoryLinks = {
+            "@odata.id": baseLinkUri + "/Categories" + "(2)"
+        };
+
+
+        module("Functional", {
+            setup: function () {
+                djstest.wait(function (done) {
+                    $.post(service + "/ResetData", done);
+                });
+            }
+        });
+
+        var readLinksFeed = categoriesFeed + "(1)/Foods/$ref";
+        var readLinksEntry = foodsFeed + "(0)/Category/$ref";
+
+        $.each(mimeTypes, function (_, mimeType) {
+
+            var headers = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
+
+            djstest.addTest(function readValidLinksFeedTests(params) {
+                djstest.assertsExpected(1);
+                odatajs.oData.read({ requestUri: params.linksFeed, headers: headers },
+                    function (data, response) {
+                        window.ODataReadOracle.readLinksFeed(params.linksFeed,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, params.mimeType
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+            }, "Testing valid read of " + readLinksFeed + " with " + mimeType, { linksFeed: readLinksFeed, mimeType: mimeType });
+
+            djstest.addTest(function readValidLinksEntryTest(params) {
+                djstest.assertsExpected(1);
+                odatajs.oData.read({ requestUri: params.linksEntry, headers: headers },
+                    function (data, response) {
+                        window.ODataReadOracle.readLinksEntry(params.linksEntry,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, params.mimeType
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+            }, "Testing valid read of " + readLinksEntry + " with " + mimeType, { linksEntry: readLinksEntry, mimeType: mimeType });
+
+            djstest.addTest(function updateLinksEntityTest(mimeType) {
+
+                var request = {
+                    requestUri: foodsFeed + "(1)/Category/$ref",
+                    method: "PUT",
+                    headers: djstest.clone(headers),
+                    data: newCategoryLinks
+                };
+
+
+                odatajs.oData.request(request, function (data, response) {
+                    var httpOperation = request.method + " " + request.requestUri;
+                    djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+                    ODataReadOracle.readLinksEntry(request.requestUri, function (actualData) {
+                        if (actualData && actualData["@odata.context"]) {
+                            delete actualData["@odata.context"];
+                        }
+                        
+                        djstest.assertAreEqualDeep(actualData, request.data, "Verify new links entry against the request: " + httpOperation);
+                        djstest.done();
+                    });
+                }, unexpectedErrorHandler);
+
+            }, "Update links entity (mimeType = " + mimeType + " service = " + service + ")", mimeType);
+
+            djstest.addTest(function addDeleteLinksFeedTest(mimeType) {
+
+                var request = {
+                    requestUri: categoriesFeed + "(2)/Foods/$ref",
+                    method: "POST",
+                    headers: djstest.clone(headers),
+                    data: newFoodLinks
+                };
+
+                var deleteAndVerify = function (){
+                
+                    // delete by id
+                    var deletionRequest = {
+                        requestUri: categoriesFeed + "(2)/Foods/$ref?$id=" + newFoodLinks["@odata.id"],
+                        method: "DELETE",
+                        headers: djstest.clone(headers),
+                        data: null
+                    };
+
+                    odatajs.oData.request(deletionRequest, function (data, response) {
+                        var httpOperation = deletionRequest.method + " " + deletionRequest.requestUri;
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+
+                        odatajs.oData.read(request.requestUri, function (data, response) {
+                           var httpOperation = "Read " + request.requestUri;
+                           djstest.assertAreEqual(0, response.data.value.length, "Verify links against the request: " + httpOperation);
+                           djstest.done();
+                        },unexpectedErrorHandler);
+                    }, unexpectedErrorHandler);
+                };
+
+                // add
+                odatajs.oData.request(request, function (data, response) {
+
+                    var httpOperation = request.method + " " + request.requestUri;
+                    djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+
+                    odatajs.oData.read(request.requestUri, function (data, response) {
+                        ODataReadOracle.readLinksFeed(request.requestUri, function (actualData) {
+                            djstest.assertAreEqualDeep(actualData, response.data, "Verify updated links entry against the request: " + httpOperation);
+                            deleteAndVerify();
+                        });
+                    });
+                }, unexpectedErrorHandler);
+                
+            }, "Add & Delete entity (mimeType = " + mimeType + " service = " + service + ")", mimeType);
+            
+        });
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-metadata-awareness-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-metadata-awareness-functional-tests.html b/odatajs/tests/odata-metadata-awareness-functional-tests.html
new file mode 100644
index 0000000..fc5bb0b
--- /dev/null
+++ b/odatajs/tests/odata-metadata-awareness-functional-tests.html
@@ -0,0 +1,48 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>metadata awareness tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>   
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-metadata-awareness-functional-tests.js"></script>
+</head>
+<body>
+    <h1 id="qunit-header">metadata awareness 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


[08/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-batch-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-batch-tests.js b/odatajs/tests/odata-batch-tests.js
new file mode 100644
index 0000000..71a1547
--- /dev/null
+++ b/odatajs/tests/odata-batch-tests.js
@@ -0,0 +1,559 @@
+/*
+ * 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-batch-tests.js
+
+(function (window, undefined) {
+    // DATAJS INTERNAL START
+    var defaultAcceptString = "application/json;q=0.9, */*;q=0.1";
+
+    var testPayload = {
+        CategoryID : 42,
+        Name: "New Category",
+        ID : "odata",
+        version: "4.0"
+    };
+    
+    var jsonPayload = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, testPayload, { "OData-Version": "4.0" });
+
+    djstest.addTest(function writeRequestTest() {
+        var request = {
+            headers: { "Content-Type": "plain/text; charset=utf-8", Accept: "*/*", "OData-Version": "2.0" },
+            requestUri: "http://temp.org",
+            method: "GET",
+            body: "test request"
+        };
+        var expected = "GET http://temp.org HTTP/1.1\r\n" +
+                       "Content-Type: plain/text; charset=utf-8\r\n" +
+                       "Accept: */*\r\n" +
+                       "OData-Version: 2.0\r\n" +
+                       "\r\n" +
+                       "test request";
+
+        var actual = window.odatajs.oData.batch.writeRequest(request);
+        djstest.assertAreEqual(actual, expected, "WriteRequest serializes a request properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function serializeSimpleBatchTest() {
+
+        var request = {
+            requestUri: "http://temp.org",
+            method: "POST",
+            data: { __batchRequests: [
+                { requestUri: "http://feed(1)", headers: {} },
+                { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" }
+            ]
+            }
+        };
+
+        var template = "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "GET http://feed(1) HTTP/1.1\r\n" +
+                       "Accept: " + defaultAcceptString + "\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "GET http://feed(2) HTTP/1.1\r\n" +
+                       "Accept: application/json;odata.metadata=minimal\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       "\r\n--<batchBoundary>--\r\n";
+
+        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+            var cType = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]);
+            var boundary = cType.properties["boundary"];
+            var expected = template.replace(/<batchBoundary>/g, boundary);
+
+            djstest.assert(boundary, "Request content type has its boundary set");
+            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+            djstest.done();
+        });
+
+        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+    djstest.addTest(function serializeComplexBatchTest() {
+
+        var request = {
+            requestUri: "http://temp.org",
+            method: "POST",
+            data: { __batchRequests: [
+                { requestUri: "http://feed(1)", headers: {} },
+                { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" },
+                { __changeRequests: [
+                        { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
+                        ]
+                },
+                { requestUri: "http://feed(1)", headers: {} }
+            ]
+            }
+        };
+
+        // 
+        var template = "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "GET http://feed(1) HTTP/1.1\r\n" +
+                       "Accept: " + defaultAcceptString + "\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "GET http://feed(2) HTTP/1.1\r\n" +
+                       "Accept: application/json;odata.metadata=minimal\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
+                       "\r\n--<changesetBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "POST http://feed(1) HTTP/1.1\r\n" +
+                       "Accept: " + defaultAcceptString + "\r\n" +
+                       "OData-Version: 4.0\r\n" +
+                       "Content-Type: application/json\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       jsonPayload +
+                       "\r\n--<changesetBoundary>--\r\n" +
+                       "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "GET http://feed(1) HTTP/1.1\r\n" +
+                       "Accept: " + defaultAcceptString + "\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       "\r\n--<batchBoundary>--\r\n";
+
+        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+            // Get the boundaries from the request.
+            var start = request.body.indexOf("multipart/mixed");
+            var end = request.body.indexOf("\r\n", start);
+
+            var csetBoundary = window.odatajs.oData.handler.contentType(request.body.substring(start, end)).properties["boundary"];
+            var batchBoundary = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]).properties["boundary"];
+
+            var expected = template.replace(/<batchBoundary>/g, batchBoundary);
+            expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
+
+            djstest.assert(batchBoundary, "Request content type has its boundary set");
+            djstest.assert(csetBoundary, "Changeset content type has its boundary set");
+            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+            djstest.done();
+        });
+
+        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+    djstest.addTest(function serializeChangeSetTest() {
+        var request = {
+            requestUri: "http://temp.org",
+            method: "POST",
+            data: {
+                __batchRequests: [
+                    { __changeRequests: [
+                        { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
+                        ]
+                    }
+            ]
+            }
+        };
+
+        var template = "\r\n--<batchBoundary>\r\n" +
+                       "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
+                       "\r\n--<changesetBoundary>\r\n" +
+                       "Content-Type: application/http\r\n" +
+                       "Content-Transfer-Encoding: binary\r\n" +
+                       "\r\n" +
+                       "POST http://feed(1) HTTP/1.1\r\n" +
+                       "Accept: " + defaultAcceptString + "\r\n" +
+                       "OData-Version: 4.0\r\n" +
+                       "Content-Type: application/json\r\n" +
+                       "OData-MaxVersion: 4.0\r\n" +
+                       "\r\n" +
+                       jsonPayload +
+                       "\r\n--<changesetBoundary>--\r\n" +
+                       "\r\n--<batchBoundary>--\r\n";
+
+        MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+            // Get the boundaries from the request.
+            var start = request.body.indexOf("multipart/mixed");
+            var end = request.body.indexOf("\r\n", start);
+
+            var csetBoundary = window.odatajs.oData.handler.contentType(request.body.substring(start, end)).properties["boundary"];
+            var batchBoundary = window.odatajs.oData.handler.contentType(request.headers["Content-Type"]).properties["boundary"];
+
+            var expected = template.replace(/<batchBoundary>/g, batchBoundary);
+            expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
+
+            djstest.assert(batchBoundary, "Request content type has its boundary set");
+            djstest.assert(csetBoundary, "Changeset content type has its boundary set");
+            djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+            djstest.done();
+        });
+
+        odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+    djstest.addTest(function serializeNestedChangeSetsTest() {
+        var request = {
+            requestUri: "http://temp.org",
+            method: "POST",
+            data: testPayload
+        };
+
+        djstest.expectException(function () {
+            odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler);
+        });
+
+        djstest.done();
+    });
+
+    djstest.addTest(function serializeNonBatchObjectTest() {
+        var request = {
+            requestUri: "http://temp.org",
+            method: "POST",
+            data: {
+                __batchRequests: [
+                    { __changeRequests: [
+                        { __changeRequests: [
+                            { requestUri: "http://feed(2)", headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, method: "PUT", data: testPayload }
+                        ]
+                        }
+                    ]
+                    }
+            ]
+            }
+        };
+
+        djstest.expectException(function () {
+            odatajs.oData.request(request, null, null, window.odatajs.oData.batch.batchHandler);
+        });
+
+        djstest.done();
+    });
+
+    djstest.addTest(function readSimpleBatchTest() {
+        var response = {
+            statusCode: 202,
+            statusText: "Accepted",
+            headers: {
+                "Content-Type": "multipart/mixed; boundary=batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9"
+            },
+            body: "--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
+--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
+--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9--\r\n\
+"
+        };
+
+        MockHttpClient.clear().addResponse("http://testuri.org", response);
+        odatajs.oData.read("http://testuri.org", function (data, response) {
+            djstest.assert(data.__batchResponses, "data.__batchResponses is defined");
+            djstest.assertAreEqual(data.__batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the response was read");
+            djstest.assertAreEqual(data.__batchResponses[1].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 2 of the response was read");
+            djstest.assertAreEqual(data.__batchResponses[0].data["CategoryID"], 42, "part 1 data of the response was read");
+            djstest.assertAreEqual(data.__batchResponses[1].data["CategoryID"], 43, "part 2 data of the response was read");
+            djstest.done();
+        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+    djstest.addTest(function readBatchWithChangesetTest() {
+        var response = {
+            statusCode: 202,
+            statusText: "Accepted",
+            headers: {
+                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+            },
+            body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 OK\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 204 No Content\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+\r\n\
+\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":41,\"Name\":\"New Category\"}\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 OK\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 204 No Content\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+\r\n\
+\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
+"
+        };
+
+        MockHttpClient.clear().addResponse("http://testuri.org", response);
+        odatajs.oData.read("http://testuri.org", function (data, response) {
+
+            var batchResponses = data.__batchResponses;
+            djstest.assert(batchResponses, "data contains the batch responses");
+
+            var changesetResponses = batchResponses[0].__changeResponses;
+            djstest.assert(changesetResponses, "batch response 1 contains the change set responses");
+            var changesetResponses3 = batchResponses[2].__changeResponses;
+            djstest.assert(changesetResponses3, "batch response 3 contains the change set responses");
+            
+            djstest.assertAreEqual(batchResponses[0].data, undefined, "No data defined for batch response 1");
+            djstest.assertAreEqual(changesetResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the changeset response of the response 1 was read");
+            djstest.assertAreEqual(changesetResponses[0].data["CategoryID"], 42, "part 1 data of the changeset response of the response 1 was read");
+            djstest.assertAreEqual(changesetResponses[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 1");
+            
+            djstest.assertAreEqual(batchResponses[1].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)", "response 2 was read");
+            djstest.assertAreEqual(batchResponses[1].data["CategoryID"], 41, "response 2 data was read");
+            
+            djstest.assertAreEqual(batchResponses[2].data, undefined, "No data defined for");
+            djstest.assertAreEqual(changesetResponses3[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 1 of the changeset response of the response 3 was read");
+            djstest.assertAreEqual(changesetResponses3[0].data["CategoryID"], 43, "part 1 data of the changeset response of the response 3 was read");
+            djstest.assertAreEqual(changesetResponses3[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 3");
+            djstest.done();
+        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+    djstest.addTest(function readBatchWithErrorPartTest() {
+        var response = {
+            statusCode: 202,
+            statusText: "Accepted",
+            headers: {
+                "Content-Type": "multipart/mixed; boundary=batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d"
+            },
+            body: "--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 200 OK\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;charset=utf-8\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
+--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 400 Bad Request\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Error processing request stream.'.\"}}\r\n\
+--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d--\r\n\
+"
+        };
+
+        MockHttpClient.clear().addResponse("http://testuri.org", response);
+        odatajs.oData.read("http://testuri.org", function (data, response) {
+            var batchResponses = data.__batchResponses;
+            djstest.assert(batchResponses, "data.__batchResponses is defined");
+            djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
+            djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
+            djstest.assert(batchResponses[1].response, "part 2 of the response was read");
+            djstest.done();
+        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+    });
+
+
+    djstest.addTest(function readMalformedMultipartResponseThrowsException() {
+        var response = {
+            statusCode: 202,
+            statusText: "Accepted",
+            headers: {
+                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+            },
+            body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 200 OK\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;charset=utf-8\r\n\
+Location: http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
+\r\n\
+--changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 404 Not Found\r\n\
+X-Content-Type-Options: nosniff\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\GET operation cannot be specified in a change set. Only PUT, POST and DELETE operations can be specified in a change set..'.\"}}\r\n\
+--changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
+"
+        };
+
+        MockHttpClient.clear().addResponse("http://testuri.org", response);
+        odatajs.oData.read("http://testuri.org", function (data, response) {
+            var batchResponses = data.__batchResponses;
+            djstest.assert(batchResponses, "data.__batchResponses is defined");
+            djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
+            djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
+
+            var error = batchResponses[1].__changeResponses[0];
+            djstest.assert(error.response.body.indexOf("GET operation cannot be specified in a change set") > -1, "Response contains expected message");
+            djstest.done();
+        }, null, window.odatajs.oData.batch.batchHandler, MockHttpClient);
+        djstest.done();
+    });
+
+    djstest.addTest(function batchRequestContextIsPushedToThePartsHandlersTest() {
+        var testHandler = {
+            read: function (response, context) {
+                djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
+            },
+            write: function (request, context) {
+                djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
+            }
+        };
+
+        var batch = {
+            headers: {},
+            __batchRequests: [
+                { requestUri: "http://someUri" },
+                { __changeRequests: [
+                     { requestUri: "http://someUri", method: "POST", data: { p1: 500} }
+                  ]
+                }
+            ]
+        };
+
+        var request = { requestUri: "http://someuri", headers: {}, data: batch };
+        var response = {
+            statusCode: 202,
+            statusText: "Accepted",
+            headers: {
+                "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+            },
+            body: '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n' +
+                  'Content-Type: application/http\r\n' +
+                  'Content-Transfer-Encoding: binary\r\n' +
+                  '\r\n' +
+                  'HTTP/1.1 200 OK\r\n' +
+                  'Cache-Control: no-cache\r\n' +
+                  'OData-Version: 1.0;\r\n' +
+                  'Content-Type: application/json\r\n' +
+                  '\r\n' +
+                  '{ "p1": 500 }\r\n' +
+                  '\r\n' +
+                  '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n'
+        };
+
+        var oldPartHandler = window.odatajs.oData.batch.batchHandler.partHandler;
+
+        window.odatajs.oData.batch.batchHandler.partHandler = testHandler;
+
+        window.odatajs.oData.batch.batchHandler.write(request, { recognizeDates: true });
+        window.odatajs.oData.batch.batchHandler.read(response, { recognizeDates: true });
+
+        window.odatajs.oData.batch.batchHandler.partHandler = oldPartHandler;
+
+        djstest.done();
+    });
+
+
+    // DATAJS INTERNAL END
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-filter-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-filter-functional-tests.html b/odatajs/tests/odata-cache-filter-functional-tests.html
new file mode 100644
index 0000000..94cfe2e
--- /dev/null
+++ b/odatajs/tests/odata-cache-filter-functional-tests.html
@@ -0,0 +1,52 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>datajs.cache  filter functional tests</title>
+    <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"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/CacheOracle.js"></script>
+    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="odata-cache-filter-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache filter functional 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/d5ec5557/odatajs/tests/odata-cache-filter-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-filter-functional-tests.js b/odatajs/tests/odata-cache-filter-functional-tests.js
new file mode 100644
index 0000000..0fd08f3
--- /dev/null
+++ b/odatajs/tests/odata-cache-filter-functional-tests.js
@@ -0,0 +1,431 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var feeds = [
+        { feed: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
+    ];
+
+    var itemsInCollection = 16;
+
+    var pageSize = 3;
+    var readRangeStart = pageSize + 1;
+    var readRangeTake = pageSize;
+
+    // Indices for filterForward after an initial readRange has partially filled the cache
+    var filterForwardAfterReadIndices = [
+        readRangeStart - 1, // before items in the cache
+        readRangeStart, // beginning of items in the cache
+        readRangeStart + readRangeTake, // last item prefetched in the cache
+        readRangeStart + readRangeTake + 1 // past range already in cache
+    ];
+
+    // Indices for filterBack after an initial readRange has partially filled the cache
+    var filterBackAfterReadIndices = [
+        readRangeStart - 1, // before items in the cache
+        readRangeStart, // beginning of items in the cache
+        readRangeStart + readRangeTake, // last item prefetched in the cache
+        readRangeStart + readRangeTake + 1 // past range already in cache
+    ];
+
+    // Counts for filterForward after a readRange has partially filled the cache
+    var filterForwardAfterReadCounts = [
+        -5, // Get all items
+        3, // Subset of all items found in the cache
+        itemsInCollection
+    ];
+
+    // Counts for filterBack after a readRange has partially filled the cache
+    var filterBackAfterReadCounts = [
+        -5, // Get all items
+        3, // Subset of all items found in the cache
+        itemsInCollection
+    ];
+
+    // Indices for single filterForward
+    var singleFilterForwardIndices = [
+        -5,
+        itemsInCollection - 1,
+        itemsInCollection, // beyond the end of the collection
+        itemsInCollection + pageSize // more than one page beyond the collection
+    ];
+
+    // Indices for single filterBack
+    var singleFilterBackIndices = [
+        -1,
+        0,
+        itemsInCollection - 1
+    ];
+
+    // Count for single filterForward
+    var singleFilterForwardCounts = [
+        5,
+        itemsInCollection + 1 // more than number of items in collection
+    ];
+
+    // Count for single filterBack
+    var singleFilterBackCounts = [
+        5,
+        itemsInCollection + 1 // more than number of items in collection
+    ];
+
+    // Index/count variations for multiple filterForwards
+    var multipleFilterForwards = [
+        { index: 0, count: -1 },  // everything
+        {index: 2, count: 5 },   // range in first half
+        {index: 4, count: 7 },   // range in the middle to overlap first and second half
+        {index: 9, count: 4}    // range in second half
+    ];
+
+    // Index/count variations for multiple filterBacks
+    var multipleFilterBacks = [
+        { index: itemsInCollection - 1, count: -1 },  // everything
+        {index: itemsInCollection - 2, count: 5 },   // range in second half
+        {index: itemsInCollection - 4, count: 7 },   // range in the middle to overlap first and second half
+        {index: itemsInCollection - 9, count: 4}    // range in first half
+    ];
+
+
+    var invalidIndices = [NaN, undefined, Infinity, "not a valid value"];
+    var invalidCounts = [NaN, undefined, Infinity, "not a valid value"];
+
+    // Predicate which returns all items in the collection
+    var getAllItemsPredicate = function (item) {
+        return true;
+    };
+
+    // Predicate which returns none of the items in the collection
+    var getNoItemsPredicate = function (item) {
+        return false;
+    };
+
+    var getEveryThirdPredicate = function (item) {
+        return ((item.FoodID % 3) === 0);
+    };
+
+    var filterPredicates = [
+        getAllItemsPredicate,
+        getNoItemsPredicate,
+        getEveryThirdPredicate
+    ];
+
+    var expectException = function (cache) {
+        djstest.assert(false, "We should not get here because the an exception is expected.");
+        djstest.destroyCacheAndDone(cache);
+    };
+
+    var makeUnexpectedErrorHandler = function (cache) {
+        return function (err) {
+            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+            if (cache) {
+                djstest.destroyCacheAndDone(cache);
+            } else {
+                djstest.done();
+            }
+        };
+    };
+
+    var validateFilterResultsAndRequests = function (feed, cache, index, count, predicate, finished, backwards, session, cacheOracle) {
+        /** Runs filter and validates the results and network requests
+         * @param {Object} feed - The feed being read from
+         * @param {Object} cache - The cache to perform the filter on
+         * @param {Integer} index - The index value
+         * @param {Integer} count - The count value
+         * @param {Object} predicate - Filter string to append to the feed to validate the predicate
+         * @param {Function} finished - Callback function called after data is verified
+         * @param {Object} session - Session object to validate the network requests
+         * @param {Object} cacheOracle - cacheOracle object to validate the network requests
+         */
+
+        if (count < 0) {
+            count = itemsInCollection;
+        }
+
+        if (index < 0) {
+            index = 0;
+        }
+
+        window.ODataReadOracle.readJsonAcrossServerPages(feed, function (expectData) {
+            if (backwards) {
+                cache.filterBack(index, count, predicate).then(function (actualResults) {
+                    var expectedResults = CacheOracle.getExpectedFilterResults(expectData, index, count, predicate, backwards);
+                    djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterBack requests");
+
+                    if (session && cacheOracle) {
+                        // If the count is not satisfied in the expected results, read to the beginning of the collection
+                        // otherwise read to the first expected index
+                        var firstIndex = 0; 
+                        if (expectedResults.value.length != 0) {
+                            firstIndex = (expectedResults.value.length < count) ? 0 : expectedResults.value[0].index;
+                        }
+                        // The effective count is the number of items between the first and last index
+                        var expectedCount = index - firstIndex + 1;
+                        cacheOracle.verifyRequests(session.requests, session.responses, firstIndex, expectedCount, "filterBack requests", backwards);
+                    }
+                    finished();
+                });
+            }
+            else {
+                cache.filterForward(index, count, predicate).then(function (actualResults) {
+                    var expectedResults = CacheOracle.getExpectedFilterResults(expectData, index, count, predicate, backwards)
+                    djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterForward requests");
+
+                    if (session && cacheOracle) {
+                        if (expectedResults.value.length > 0) {
+                            // If the count is not satisfied in the expected results, read to the end of the collection
+                            // otherwise read to the last index
+                            var lastIndex = (expectedResults.value.length < count) ? itemsInCollection : expectedResults.value[expectedResults.value.length - 1].index + 1;
+                            // One request is made if the index is outside the range of the collection if the end of the collection has not yet been found
+                            var expectedCount = (index < itemsInCollection) ? (lastIndex - index) : 1;
+                        }
+                        else {
+                            var expectedCount = itemsInCollection;
+                        }
+
+                        cacheOracle.verifyRequests(session.requests, session.responses, index, expectedCount, "filterForward requests", backwards);
+                    }
+                    finished();
+                });
+            }
+        });
+    };
+
+    var createMultipleFilterTestName = function (scenarioName, params) {
+        return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
+            params.firstIndex + ", count " + params.firstCount + "] and [index " + params.secondIndex + ", count " + params.secondCount +
+            "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
+    };
+
+    var createSingleFilterTestName = function (scenarioName, params) {
+        return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
+            params.index + ", count " + params.count + "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
+    };
+
+    var singleFilterTest = function (params) {
+        djstest.assertsExpected(2);
+        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+        var cache = odatajs.cache.createDataCache(options);
+        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+        var session = this.observableHttpClient.newSession();
+        validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
+    };
+
+    var filterAfterReadRangeTest = function (params) {
+        djstest.assertsExpected(3);
+        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+        var cache = odatajs.cache.createDataCache(options);
+        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+        var session = this.observableHttpClient.newSession();
+
+        cache.readRange(params.skip, params.take).then(function (data) {
+            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+            session.clear();
+            validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache); }, params.backwards, session, cacheOracle);
+        });
+    };
+
+    var parallelFilterTest = function (params) {
+        djstest.assertsExpected(2);
+        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+        var cache = odatajs.cache.createDataCache(options);
+
+        var firstfilter = function (finished) {
+            validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate, finished, params.backwards);
+        };
+
+        var secondfilter = function (finished) {
+            validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, finished, params.backwards);
+        };
+
+        djstest.asyncDo([firstfilter, secondfilter], function () {
+            djstest.destroyCacheAndDone(cache);
+        });
+    };
+
+    var serialFilterTest = function (params) {
+        djstest.assertsExpected(4);
+        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+        var cache = odatajs.cache.createDataCache(options);
+        var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+        var session = this.observableHttpClient.newSession();
+
+        var filterMethod = function (index, count, predicate, backwards) {
+            if (backwards) {
+                return cache.filterBack(index, count, predicate);
+            }
+            else {
+                return cache.filterForward(index, count, predicate)
+            }
+        }
+
+        filterMethod(params.firstIndex, params.firstCount, params.predicate, params.backwards).then(
+            function (results) {
+                validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate,
+                function () {
+                    session.clear();
+                    validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
+                }, params.backwards, session, cacheOracle);
+            });
+    };
+
+    module("Functional", {
+        setup: function () {
+            this.observableHttpClient = new ObservableHttpClient();
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
+        },
+
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
+        }
+    });
+
+    $.each(filterPredicates, function (_, filterPredicate) {
+        $.each(feeds, function (_, feedObject) {
+            $.each(filterForwardAfterReadCounts, function (_, filterCount) {
+                $.each(filterForwardAfterReadIndices, function (_, filterIndex) {
+                    var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
+                        skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: false
+                    };
+                    djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("after readRange, ", parameters), parameters);
+                });
+            });
+
+            $.each(filterBackAfterReadCounts, function (_, filterCount) {
+                $.each(filterBackAfterReadIndices, function (_, filterIndex) {
+                    var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
+                        skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: true
+                    };
+                    djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("After readRange, ", parameters), parameters);
+                });
+            });
+        });
+
+        $.each(singleFilterForwardIndices, function (_, filterIndex) {
+            $.each(singleFilterForwardCounts, function (_, filterCount) {
+                var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: false };
+                djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
+            });
+        });
+
+        $.each(singleFilterBackIndices, function (_, filterIndex) {
+            $.each(singleFilterBackCounts, function (_, filterCount) {
+                var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: true };
+                djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
+            });
+        });
+
+        $.each(multipleFilterForwards, function (_, firstFilter) {
+            $.each(multipleFilterForwards, function (_, secondFilter) {
+                var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: false
+                };
+                djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
+            });
+        });
+
+        $.each(multipleFilterBacks, function (_, firstFilter) {
+            $.each(multipleFilterBacks, function (_, secondFilter) {
+                var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: true
+                };
+                djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
+            });
+        });
+
+        $.each(multipleFilterForwards, function (_, firstFilter) {
+            $.each(multipleFilterForwards, function (_, secondFilter) {
+                var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: false
+                };
+                djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
+            });
+        });
+
+        $.each(multipleFilterBacks, function (_, firstFilter) {
+            $.each(multipleFilterBacks, function (_, secondFilter) {
+                var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+                    predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: true
+                };
+                djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
+            });
+        });
+
+        $.each([true, false], function (_, isBackwards) {
+            var zeroCountParameters = { index: 0, count: 0, predicate: filterPredicate, feed: feeds[0].feed, take: readRangeTake,
+                skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: isBackwards
+            };
+            djstest.addTest(singleFilterTest, createSingleFilterTestName("Count 0 ", zeroCountParameters), zeroCountParameters);
+        });
+    });
+
+    $.each([true, false], function (_, backwards) {
+        $.each(invalidIndices, function (_, invalidIndex) {
+            var invalidIndexParameters = { index: invalidIndex, count: -1, predicate: filterPredicates[0], feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
+
+            djstest.addTest(
+                function (params) {
+                    djstest.assertsExpected(1);
+                    var options = { name: "cache" + new Date().valueOf(), source: params.feed };
+                    var cache = odatajs.cache.createDataCache(options);
+                    try {
+                        params.backwards ?
+                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+                                djstest.log(results);
+                            }) :
+                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+                                djstest.log(results);
+                            });
+                        expectException(cache);
+                    } catch (e) {
+                        djstest.assertAreEqual(e.message, "'index' must be a valid number.", "Error message validation");
+                        djstest.destroyCacheAndDone(cache);
+                    }
+                }, createSingleFilterTestName("invalid index ", invalidIndexParameters), invalidIndexParameters);
+        });
+
+        $.each(invalidCounts, function (_, invalidCount) {
+            var invalidCountParameters = { index: 0, count: invalidCount, predicate: filterPredicates[0], feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
+
+            djstest.addTest(
+                function (params) {
+                    djstest.assertsExpected(1);
+                    var options = { name: "cache" + new Date().valueOf(), source: params.feed };
+                    var cache = odatajs.cache.createDataCache(options);
+                    try {
+                        params.backwards ?
+                            cache.filterBack(params.index, params.count, params.predicate).then(function (results) {
+                                djstest.log(results);
+                            }) :
+                            cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+                                djstest.log(results);
+                            });
+                        expectException(cache);
+                    } catch (e) {
+                        djstest.assertAreEqual(e.message, "'count' must be a valid number.", "Error message validation");
+                        djstest.destroyCacheAndDone(cache);
+                    }
+                }, createSingleFilterTestName("invalid count ", invalidCountParameters), invalidCountParameters);
+        });
+    });
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-fperf-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-fperf-tests.html b/odatajs/tests/odata-cache-fperf-tests.html
new file mode 100644
index 0000000..c00a814
--- /dev/null
+++ b/odatajs/tests/odata-cache-fperf-tests.html
@@ -0,0 +1,50 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>datajs.cache functional perf tests</title>
+    <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"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>    
+    <script type="text/javascript" src="common/CacheOracle.js"></script>  
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-cache-fperf-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache functional perf 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/d5ec5557/odatajs/tests/odata-cache-fperf-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-fperf-tests.js b/odatajs/tests/odata-cache-fperf-tests.js
new file mode 100644
index 0000000..cfb698c
--- /dev/null
+++ b/odatajs/tests/odata-cache-fperf-tests.js
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+
+    var slowHttpClient = {
+        latency: 750,
+        provider: window.odatajs.oData.net.defaultHttpClient,
+        request: function (request, success, error) {
+            setTimeout(function () {
+                slowHttpClient.provider.request(request, success, error);
+            }, slowHttpClient.latency);
+        }
+    };
+
+    var feeds = [
+        { uri: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
+    ];
+
+    module("Functional", {
+        setup: function () {
+            window.odatajs.oData.net.defaultHttpClient = slowHttpClient;
+        },
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = slowHttpClient.provider;
+        }
+    });
+
+    var cacheReadRangeWallClockTest = function (totalReads, interval, mechanism, source, pageSize, prefetchSize, generateRange, threshold) {
+        /** Cache readRange wall-clock test
+         * The average time computed by the wall-clock test does *not* include the initial readRange
+         * @param totalReads - Number of reads to collect data from
+         * @param interval - Interval (milliseconds) between reads
+         * @param mechanism - The cache store mechanism
+         * @param source - The feed source
+         * @param pageSize - The page size
+         * @param prefetchSize - The prefetch size
+         * @param generateRange - The range generator function: given the read index, returns the readRange index and count
+         * @param threshold - The average read time threshold for test to pass; if not specified, defaults to the slowHttpClient latency
+         * @returns The test function
+         */
+        return function () {
+            var cache = odatajs.cache.createDataCache({ name: "cache" + new Date().valueOf(), source: source, pageSize: pageSize, prefetchSize: prefetchSize });
+            var totalTime = 0;
+            var readCount = 0;
+
+            var callReadRange = function () {
+                var range = generateRange(readCount);
+                var startTime = new Date().valueOf();
+                cache.readRange(range.index, range.count).then(function (data) {
+                    var duration = (new Date().valueOf()) - startTime;
+                    djstest.log("readRange " + readCount + " [" + range.index + ", " + range.count + "]: " + duration + "ms");
+
+                    // The first readRange is not counted
+                    totalTime += (readCount > 0) ? duration : 0;
+                    readCount += 1;
+
+                    if (readCount < totalReads) {
+                        setTimeout(callReadRange, interval);
+                    } else {
+                        // The first readRange is not counted
+                        var averageTime = totalTime / (totalReads - 1);
+                        var actualThreshold = threshold === undefined ? slowHttpClient.latency : threshold;
+                        djstest.assert(averageTime < actualThreshold, "Average: " + averageTime + "ms, Threshold: " + actualThreshold + "ms");
+                        djstest.destroyCacheAndDone(cache);
+                    }
+                }, function (err) {
+                    djstest.fail("Unexpected call to error handler with error: " + djstest.toString(err));
+                    djstest.destroyCacheAndDone(cache);
+                });
+            };
+
+            callReadRange();
+        };
+    };
+
+    $.each(CacheOracle.mechanisms, function (_, mechanism) {
+        if (mechanism !== "best" && CacheOracle.isMechanismAvailable(mechanism)) {
+            $.each(feeds, function (_, feed) {
+                djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, feed.uri, 5, 0, function () {
+                    return { index: 0, count: 5 };
+                }), "Cache small single-page wall-clock test with " + mechanism + " on " + feed.uri);
+
+                djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
+                    return { index: readCount * 3, count: 3 };
+                }), "Cache page-by-page wall-clock test with " + mechanism + " on " + feed.uri);
+
+                djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
+                    return { index: readCount, count: 3 };
+                }), "Cache line-by-line wall-clock test with " + mechanism + " on " + feed.uri);
+            });
+
+            var largeFeedUri = "./endpoints/LargeCollectionService.svc/Customers";
+            djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, largeFeedUri, 100, 0, function () {
+                return { index: 0, count: 500 };
+            }), "Cache large single-page wall-clock test with " + mechanism + " on " + largeFeedUri, undefined, 60000);
+        }
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-functional-tests.html b/odatajs/tests/odata-cache-functional-tests.html
new file mode 100644
index 0000000..f158030
--- /dev/null
+++ b/odatajs/tests/odata-cache-functional-tests.html
@@ -0,0 +1,52 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData tests against local service</title>
+    <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"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/CacheOracle.js"></script>
+    <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="odata-cache-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache tests against local in-memory service</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>


[28/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-read-crossdomain-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-read-crossdomain-functional-tests.js b/datajs/tests/odata-read-crossdomain-functional-tests.js
deleted file mode 100644
index 9e8aca9..0000000
--- a/datajs/tests/odata-read-crossdomain-functional-tests.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var fixConstructors = function (obj) {
-        /** Fix the constructors of the supplied object graph.
-        */
-        
-        /// When using IE9 or a non-IE browser, the JSONP support in the library creates objects in a separate IFRAME,
-        /// causing the constructor property to be different to that of objects created by the oracle. This function
-        /// stringifies and then re-parses the object, which fixes the constructors.
-        
-        if (!window.ActiveXObject || window.DOMParser) {
-            return window.JSON.parse(window.JSON.stringify(obj));
-        } else {
-            return obj;
-        }
-    };
-
-    var handlerAcceptStrings = [
-        "*/*",
-        "application/json",
-        undefined
-    ];
-
-    var formatJsonStrings = [
-        "application/json",
-        "application/json;odata.metadata=none",
-        "application/json;odata.metadata=minimal",
-        "application/json;odata.metadata=full", // to do: all the full metadata scenarios fail currently, need to fix.
-        undefined
-    ];
-    var azureOdataService = "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/";
-    var azureOdataFeed = azureOdataService + "Categories";
-    var crossDomainTimeout = 45000;
-
-    module("CrossDomain", {
-        setup: function () {
-            this.oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
-        },
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = this.oldEnableJsonpCallback;
-        }
-    });
-
-    for (var i = 0; i < handlerAcceptStrings.length; i++) {
-        for (var j = 0; j < formatJsonStrings.length; j++) {
-            djstest.addTest(function readCrossDomainFullFeedTest(params) {
-                djstest.assertsExpected(1);
-                var request = { requestUri: azureOdataFeed, headers: { Accept: params.handlerAccept}, enableJsonpCallback: true };
-                if (params.formatJsonString != undefined) {
-                    request.formatQueryString = "$format=" + params.formatJsonString;
-                }
-
-                djstest.log("Reading data over the wire.");
-                odatajs.oData.read(request, function (data, response) {
-                    djstest.log("Verifying data over the wire from Oracle.");
-                    window.ODataReadOracle.readFeed(azureOdataFeed, function (expectedData) {
-                        data = fixConstructors(data);
-                        djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
-                        djstest.done();
-                    }, params.formatJsonString);
-                }, unexpectedErrorHandler);
-            }, "Testing valid read of cross domain feed collection with " + handlerAcceptStrings[i] + "," + formatJsonStrings[j], { handlerAccept: handlerAcceptStrings[i], formatJsonString: formatJsonStrings[j] }, crossDomainTimeout);
-        }
-
-        djstest.addTest(function readCrossDomainEntryTest(handlerAccept) {
-            var endPoint = azureOdataFeed + "(1)";
-            djstest.assertsExpected(1);
-            djstest.log("Reading data over the wire.");
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
-                djstest.log("Verifying data over the wire from Oracle.");
-                window.ODataReadOracle.readEntry(endPoint, function (expectedData) {
-                    data = fixConstructors(data);
-                    djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
-                    djstest.done();
-                }, "application/json");
-            }, unexpectedErrorHandler);
-        }, "Testing valid read of cross domain entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i], crossDomainTimeout);
-    }
-
-    var prefetchSizes = [-1, 0, 15];
-    var cacheSizes = [-1, 0, 15];
-    var skipValues = [
-        0,
-        14, // < pageSize
-        15, // = pageSize
-        16 // > pageSize but < pageSize + prefetchSize
-    ];
-
-    var createTestName = function (params) {
-        return "Testing ReadRange of " + params.feed + " skip " + params.skip + " take " + params.take + " with pageSize " +
-            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
-    };
-
-    var dataCacheReadRangeSingleTest = function (params) {
-        var options = { name: "cache", source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
-        window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
-        var cache = odatajs.cache.createDataCache(options);
-        cache.readRange(params.skip, params.take).then(function (data) {
-            validateExpectedRange(cache, data, params.feed, params.skip, params.take);
-        }, unexpectedErrorHandler);
-    };
-
-    var validateExpectedRange = function (cache, data, feed, skipValue, takeValue) {
-        var expectedRangeUrl = feed + "?$skip=" + skipValue + "&$top=" + takeValue;
-        window.ODataReadOracle.readFeed(expectedRangeUrl, function (expectedData) {
-            if (expectedData.results) {
-                expectedData = expectedData.results;
-            }
-            data = fixConstructors(data);
-            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-            djstest.destroyCacheAndDone(cache);
-        });
-    };
-
-    $.each(prefetchSizes, function (_, prefetchSizeValue) {
-        $.each(cacheSizes, function (_, cacheSizeValue) {
-            var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: 0, take: 5, pageSize: 15, prefetchSize: prefetchSizeValue, cacheSize: cacheSizeValue };
-            djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters);
-        });
-    });
-
-    $.each(skipValues, function (_, skipValue) {
-        var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: skipValue, take: 14, pageSize: 5, prefetchSize: 5, cacheSize: 5 };
-        djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters, crossDomainTimeout);
-    });
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-read-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-read-functional-tests.html b/datajs/tests/odata-read-functional-tests.html
deleted file mode 100644
index 11d930d..0000000
--- a/datajs/tests/odata-read-functional-tests.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData tests against local service</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>   
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-read-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">OData.Read tests against local in-memory service</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-read-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-read-functional-tests.js b/datajs/tests/odata-read-functional-tests.js
deleted file mode 100644
index 6253856..0000000
--- a/datajs/tests/odata-read-functional-tests.js
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var validServiceDocumentAcceptHeaders = [
-            "*/*",
-            "application/json",
-            undefined
-          ];
-
-    var validMetadataAcceptHeaders = [
-            "*/*",
-            "application/xml",
-            undefined
-          ];
-
-    var invalidServiceDocumentAcceptHeaders = [
-        "application/atom+xml"
-    ];
-
-    var invalidMetadataAcceptHeaders = [
-            "application/json"
-        ];
-
-    var handlerAcceptStrings = [
-        "*/*",
-        "application/json",
-         undefined
-      ];
-
-    var httpStatusCode = {
-        notFound: 404,
-        badRequest: 400,
-        unsupportedMediaType: 415
-    };
-
-    var service = "./endpoints/FoodStoreDataServiceV4.svc/";
-    var epmService = "./endpoints/EpmDataService.svc/";
-    var feed = service + "Foods";
-    var categoriesFeed = service + "Categories";
-
-    var expectedErrorMessage = "HTTP request failed";
-
-    module("Functional", {
-        setup: function () {
-            djstest.wait(function (done) {
-                $.post(service + "ResetData", done);
-            });
-            window.odatajs.oData.json.jsonHandler.recognizeDates = false;
-        }
-    });
-
-    for (var i = 0; i < handlerAcceptStrings.length; i++) {
-
-        djstest.addTest(function readFullFeedTest(handlerAccept) {
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: feed, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(feed,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-        }, "Testing valid read of full feed collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readMaxAndNullValueEntryTest(handlerAccept) {
-            var endPoint = feed + "(0)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endPoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-        }, "Testing valid read of entry with max numbers, complex types, and null and empty strings " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readMinAndZeroValueEntryTest(handlerAccept) {
-            var endPoint = feed + "(1)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: "./endpoints/FoodStoreDataServiceV4.svc/Foods(1)", headers: { Accept: handlerAccept} },
-                function (data, response) {
-                    window.ODataReadOracle.readEntry(endPoint,
-                        function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                            djstest.done();
-                        }, handlerAccept
-                    );
-                },
-                unexpectedErrorHandler);
-        }, "Testing valid read of minimum and zero values " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readNullNestedComplexTypeEntryTest(handlerAccept) {
-            var endPoint = feed + "(2)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endPoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                 );
-        }, "Testing valid read of null nested complex type and navigation property " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readNullComplexTypeEntryTest(handlerAccept) {
-            var endPoint = feed + "(3)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endPoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                 );
-        }, "Testing valid read of null top level complex type" + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readNullPropertiesDerivedEntryTest(handlerAccept) {
-            djstest.assertsExpected(1);
-            var endPoint = feed + "(4)";
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endPoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-        }, "Testing valid read of derived type null properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readNextComplexTypeDerivedEntryTest(handlerAccept) {
-
-            djstest.assertsExpected(1);
-            var endPoint = feed + "(5)";
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endPoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                 );
-        }, "Testing valid read of derived type with full nested complex type properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readEntryWithInlineFeedTest(handlerAccept) {
-            var endpoint = categoriesFeed + "(0)?$expand=Foods";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-        }, "Testing read of entry with inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readFeedWithEmptyInlineFeedTest(handlerAccept) {
-            var endpoint = categoriesFeed + "?$filter=Name eq 'Empty Category'&$expand=Foods";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-               );
-        }, "Testing read of entry with empty inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readEntryWithInlineEntryTest(handlerAccept) {
-            var endpoint = feed + "(0)?$expand=Category";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data.Category, expectedData.Category, "Verify inline entry");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-               );
-        }, "Testing read of entry with inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readFeedWithNullInlineEntryTest(handlerAccept) {
-            var endpoint = feed + "?$expand=Category&$filter=Category eq null";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline data");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
-                                djstest.done();
-                            }, handlerAccept);
-                    },
-                    unexpectedErrorHandler
-               );
-        }, "Testing read of feed with null inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readFeedWithInlineCountTest(handlerAccept) {
-            var endpoint = feed + "?$count=true";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqual(data["@odata.count"], expectedData["@odata.count"], "Verify count in response data");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    },
-                    unexpectedErrorHandler
-                );
-        }, "Testing read of collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function selectSinglePropertyOnEntryTest(handlerAccept) {
-            var endpoint = feed + "(0)?$select=Name";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                function (data, response) {
-                    window.ODataReadOracle.readEntry(endpoint,
-                        function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
-                            djstest.done();
-                        }, handlerAccept
-                    );
-                },
-                unexpectedErrorHandler);
-        }, "Select single property of entry " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function selectComplexTypeOnFeedTest(handlerAccept) {
-            var endpoint = feed + "?$select=Packaging";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                function (data, response) {
-                    window.ODataReadOracle.readFeed(endpoint,
-                        function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
-                            djstest.done();
-                        }, handlerAccept
-                    );
-                },
-                unexpectedErrorHandler);
-        }, "Select single complex type property of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function selectMultiplePropertiesOnEntryTest(handlerAccept) {
-            var endpoint = feed + "(3)?$select=Packaging,ExpirationDate,IsAvailable";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                function (data, response) {
-                    window.ODataReadOracle.readEntry(endpoint,
-                        function (expectedData) {
-                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
-                            djstest.done();
-                        }, handlerAccept
-                    );
-                },
-                unexpectedErrorHandler);
-        }, "Select multiple primitive properties of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readPagedCategoriesCollectionTest(handlerAccept) {
-            var endpoint = categoriesFeed;
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    }, unexpectedErrorHandler);
-        }, "Testing read of paged collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readPagedCollectionWithInlineCountTest(handlerAccept) {
-            var endpoint = categoriesFeed + "?$count=true";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readFeed(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqual(data["@odata.context"], expectedData["@odata.context"], "Verify count in response data");
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    }, unexpectedErrorHandler);
-        }, "Testing read of paged collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readEntryWithNamedStreams(handlerAccept) {
-            var endpoint = feed + "(1)?$expand=Category";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    }, unexpectedErrorHandler);
-        }, "Testing read of entry with named streams " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readEntryWithCollectionProperties(handlerAccept) {
-            var endpoint = feed + "(0)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        window.ODataReadOracle.readEntry(endpoint,
-                            function (expectedData) {
-                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
-                                djstest.done();
-                            }, handlerAccept
-                        );
-                    }, unexpectedErrorHandler);
-        }, "Testing read of entry with collection properties " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function invalidEntryReadTest(handlerAccept) {
-            var endPoint = feed + "(16)";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        djstest.assert(false, "We should not get here because data is not valid.");
-                        djstest.done()
-                    },
-                    function (err) {
-                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
-                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
-                        djstest.done();
-                    });
-        }, "Testing invalid entry read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function invalidFeedReadTest(handlerAccept) {
-            var endPoint = feed + "Invalid";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                    function (data, response) {
-                        djstest.assert(false, "We should not get here because data is not valid.");
-                        djstest.done();
-                    },
-                    function (err) {
-                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
-                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
-                        djstest.done();
-                    });
-        }, "Testing invalid feed read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function standardErrorReadTest(handlerAccept) {
-            var endPoint = feed + "?$foo=bar";
-            djstest.assertsExpected(2);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
-                                    function (data, response) {
-                                        djstest.assert(false, "We should not get here because data is not valid.");
-                                        djstest.done()
-                                    },
-                                    function (err) {
-                                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
-                                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.badRequest, "Response status code");
-                                        djstest.done();
-                                    });
-        }, "Testing standard error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function inStreamErrorReadTest(handlerAccept) {
-            var endPoint = "./endpoints/ErrorDataService.svc/Entities";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
-                djstest.assert(false, "Unexpected call to success handler with response: " + djstest.toString(response));
-                djstest.done()
-            }, function (err) {
-                djstest.assert(err.response.body.indexOf("An error occurred while processing this request") > -1, "Error handler was called with the correct response body");
-                djstest.done();
-            });
-        }, "Testing in-stream error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        var user = "djsUser";
-        var password = "djsPassword";
-
-        djstest.addTest(function readFullFeedBasicAuthTest(handlerAccept) {
-            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
-                window.ODataReadOracle.readFeed({ url: endpoint, user: user, password: password }, function (expectedData) {
-                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                    djstest.done();
-                }, handlerAccept);
-            }, unexpectedErrorHandler);
-        }, "Testing valid read of full feed collection on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-
-        djstest.addTest(function readEntryBasicAuthTest(handlerAccept) {
-            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers(1)";
-            djstest.assertsExpected(1);
-            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
-                window.ODataReadOracle.readEntry({ url: endpoint, user: user, password: password }, function (expectedData) {
-                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                    djstest.done();
-                }, handlerAccept);
-            }, unexpectedErrorHandler);
-        }, "Testing valid read of entry on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
-    }
-
-    var services = [
-            service,
-            epmService
-        ];
-
-    $.each(services, function (_, serviceName) {
-        $.each(validServiceDocumentAcceptHeaders, function (_, validServiceDocumentAcceptHeader) {
-            var parameters = { handlerAccept: validServiceDocumentAcceptHeader, serviceName: serviceName };
-
-            djstest.addTest(function validReadServiceDocumentTest(params) {
-                djstest.assertsExpected(1);
-                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
-                        function (data, response) {
-                            window.ODataReadOracle.readServiceDocument(serviceName,
-                                function (expectedData) {
-                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                    djstest.done();
-                                }, params.handlerAccept
-                            );
-                        },
-                        unexpectedErrorHandler
-                    );
-            }, "Testing valid read of service document " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
-        });
-
-        $.each(invalidServiceDocumentAcceptHeaders, function (_, invalidServiceDocumentAcceptHeader) {
-            var parameters = { handlerAccept: invalidServiceDocumentAcceptHeader, serviceName: serviceName };
-
-            djstest.addTest(function invalidReadServiceDocumentTest(params) {
-                djstest.assertsExpected(2);
-                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
-                        function success(data, response) {
-                            djstest.fail("Reading service document should produce error with " + params.handlerAccept);
-                            djstest.done();
-                        },
-                        function (err) {
-                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
-                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
-                            djstest.done();
-                        }
-                    );
-            }, "Testing read of service document with invalid MIME type " + parameters.invalidServiceDocumentAcceptHeader + " on service " + serviceName, parameters);
-        });
-
-        //to do:
-        $.each(validMetadataAcceptHeaders, function (_, validMetadataAcceptHeader) {
-            var parameters = { handlerAccept: validMetadataAcceptHeader, serviceName: serviceName };
-
-            djstest.addTest(function validReadMetadataTest(params) {
-                djstest.assertsExpected(1);
-                var endPoint = params.serviceName + "$metadata";
-                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
-                        function (data, response) {
-                            window.ODataReadOracle.readMetadata(endPoint,
-                                function (expectedData) {
-                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                    djstest.done();
-                                }
-                            );
-                        },
-                        unexpectedErrorHandler,
-                        OData.metadataHandler
-                    );
-            }, "Testing valid read metadata " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
-        });
-
-        $.each(invalidMetadataAcceptHeaders, function (_, invalidMetadataAcceptHeader) {
-            var parameters = { handlerAccept: invalidMetadataAcceptHeader, serviceName: serviceName };
-            djstest.addTest(function invlaidReadMetadataTest(params) {
-                djstest.assertsExpected(2);
-                var endPoint = params.serviceName + "$metadata";
-                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
-                        function success(data, response) {
-                            djstest.fail("Reading metadata should produce error with " + params.handlerAccept);
-                            djstest.done();
-                        },
-                        function (err) {
-                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
-                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
-                            djstest.done();
-                        },
-                        OData.metadataHandler
-                    );
-            }, "Testing read metadata with invalid MIME type " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
-        });
-    });
-
-    // To do: update the test data for enabling the annotation test
-    djstest.addFullTest(true, function metadataElementExtensionsTest() {
-        var csdlFile = "./endpoints/CustomAnnotations.xml";
-        var modifyTypeHttpClient = {};
-        var originalHttpClient = window.odatajs.oData.net.defaultHttpClient;
-
-        // Modify the content-type of the response so that it is accepted by the metadataHandler.
-        // By default, the content-type of CustomAnnotations.xml comes back as text/xml
-        modifyTypeHttpClient.request = function (request, success, error) {
-            return originalHttpClient.request(request, function (response) {
-                response.headers["Content-Type"] = "application/xml";
-                success(response);
-            }, error);
-        }
-
-        window.odatajs.oData.net.defaultHttpClient = modifyTypeHttpClient;
-
-        odatajs.oData.read({ requestUri: csdlFile, headers: { Accept: "text/xml"} },
-            function (data) {
-                window.ODataReadOracle.readMetadata(csdlFile,
-                    function (expectedData) {
-                        djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                        djstest.done();
-                    }
-                )
-            },
-            unexpectedErrorHandler, OData.metadataHandler
-         );
-    });
-
-    djstest.addTest(function verifyNonDefaultReadMethodCalled() {
-        var endPoint = feed + "(0)";
-        djstest.assertsExpected(2);
-        odatajs.oData.read(
-                { requestUri: endPoint },
-                function success(data, response) {
-                    djstest.assert(true, "Test executed");
-                    djstest.done();
-                },
-                null,
-                {
-                    read: function (response) {
-                        djstest.assert(true, "Non-default read reached");
-                        djstest.done();
-                    },
-                    accept: "*/*"
-                }
-            );
-    }, "Testing nondefault read is called.");
-
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-request-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-request-functional-tests.html b/datajs/tests/odata-request-functional-tests.html
deleted file mode 100644
index 4148634..0000000
--- a/datajs/tests/odata-request-functional-tests.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>odata.request tests</title>
-    <meta http-equiv="cache-control" content="no-cache" />
-    <meta http-equiv="pragma" content="no-cache" />
-    <meta http-equiv="expires" content="-1" />
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-request-functional-tests.js"></script>
-</head>
-<body>
-    <h1 id="qunit-header">odata.request 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/d5ec5557/datajs/tests/odata-request-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-request-functional-tests.js b/datajs/tests/odata-request-functional-tests.js
deleted file mode 100644
index 82e4258..0000000
--- a/datajs/tests/odata-request-functional-tests.js
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var verifyRequest = function (request, done) {
-        if (request.method == "POST") {
-            verifyPost(request, done);
-        }
-        else if (request.method == "PUT") {
-            verifyPut(request, done);
-        }
-        else if (request.method == "PATCH") {
-            verifyPatch(request, done);
-        }
-    };
-
-    var tryRemoveOdataType = function (data) {
-        if (data && data["@odata.type"]) {
-            delete data["@odata.type"];
-        }
-
-        return data;
-    };
-
-    var verifyPost = function (request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        djstest.log(httpOperation);
-        odatajs.oData.request(request, function (data, response) {
-            djstest.log("Status code:" + response.statusCode);
-            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
-            djstest.log("Uri:" + request.requestUri);
-            ODataReadOracle.readEntry(response.headers["Location"], function (expectedData) {
-                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
-                done();
-            }, request.headers.Accept);
-        }, unexpectedErrorHandler);
-    };
-
-    var verifyPut = function(request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        djstest.log(httpOperation);
-        odatajs.oData.request(request, function(data, response) {
-            djstest.log("Status code:" + response.statusCode);
-            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
-            djstest.log("Uri:" + request.requestUri);
-            ODataReadOracle.readEntry(request.requestUri, function(actualData) {
-                var requestData = tryRemoveOdataType(request.data);
-                djstest.assertAreEqualDeep(subset(actualData, requestData), requestData, "Verify updated entry: " + httpOperation);
-                done();
-            }, request.headers.Accept);
-        }, unexpectedErrorHandler);
-    };
-
-    var verifyPatch = function (request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        djstest.log(httpOperation);
-        ODataReadOracle.readEntry(request.requestUri, function (originalData) {
-            odatajs.oData.request(request, function (data, response) {
-                djstest.log("Status code:" + response.statusCode);
-                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
-                djstest.log("Uri:" + request.requestUri);
-                ODataReadOracle.readEntry(request.requestUri, function (actualData) {
-
-                    // Merge the original data with the updated data to get the expected data
-                    var expectedData = $.extend(true, {}, originalData, request.data);
-                    djstest.assertAreEqualDeep(actualData, tryRemoveOdataType(expectedData), "Verify merged data");
-                    done();
-                }, request.headers["Content-Type"]);
-            }, unexpectedErrorHandler);
-        }, request.headers["Content-Type"]);
-    };
-
-    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
-    var subset = function (object, subsetObject) {
-        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
-            var result = {};
-            for (subsetProp in subsetObject) {
-                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
-            }
-            return result;
-        }
-        else {
-            return object;
-        }
-    };
-
-    var foodData = {
-        "@odata.type": "#DataJS.Tests.V4.Food",
-        FoodID: 42,
-        Name: "olive oil",
-        UnitPrice: 3.14,
-        ServingSize: 1,
-        MeasurementUnit: "",
-        ProteinGrams: 5,
-        FatGrams: 9,
-        CarbohydrateGrams: 2,
-        CaloriesPerServing: 6,
-        IsAvailable: true,
-        ExpirationDate: "2010-12-25T12:00:00Z",
-        ItemGUID: "27272727-2727-2727-2727-272727272727",
-        Weight: 10,
-        AvailableUnits: 1,
-        Packaging: {
-            Type: "Can",
-            Color: null,
-            NumberPerPackage: 1,
-            RequiresRefridgeration: false,
-            PackageDimensions: {
-                Length: 4,
-                Height: 3,
-                Width: 2,
-                Volume: 1
-            },
-            ShipDate: "2010-12-25T12:00:00Z"
-        }
-    };
-
-    var testServices = {
-        V4: "./endpoints/FoodStoreDataServiceV4.svc"
-    };
-
-    var testData = {
-        V4: $.extend(true, {}, foodData, {
-            AlternativeNames: ["name1", "name2"],
-            Providers:
-                    [{
-                        Name: "Provider",
-                        Aliases: ["alias1"],
-                        Details: {
-                            Telephone: "555-555-555",
-                            PreferredCode: 999
-                        }
-                    },
-                    {
-                        Name: "Provider2",
-                        Aliases: [],
-                        Details: null
-                    }
-                ]
-        })
-    };
-
-    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
-
-    var httpStatusCode = {
-        created: 201,
-        noContent: 204,
-        notFound: 404
-    };
-
-    $.each(testServices, function (serviceName, service) {
-        var newFood = testData[serviceName];
-
-        var foodsFeed = service + "/Foods";
-        var categoriesFeed = service + "/Categories";
-
-        module("Functional", {
-            setup: function () {
-                djstest.log("Resetting data");
-                djstest.wait(function (done) {
-                    $.post(service + "/ResetData", done);
-                });
-            }
-        });
-
-        $.each(mimeTypes, function (_, mimeType) {
-            // Provide coverage for both undefined and specific DSVs
-            // For all other cases DSV = undefined is a valid scenario
-            var dataServiceVersions = ["4.0"];
-
-            $.each(dataServiceVersions, function (_, dataServiceVersion) {
-                var headers;
-                if (mimeType || dataServiceVersion) {
-                    headers = {
-                        "Content-Type": mimeType,
-                        Accept: mimeType,
-                        "OData-Version": dataServiceVersion
-                    };
-                }
-
-                djstest.addTest(function addEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: {
-                            CategoryID: 42,
-                            Name: "New Category"
-                        }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Add new entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function addEntityWithUTF16CharTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: {
-                            CategoryID: 42,
-                            Name: "\u00f6 New Category \u00f1"
-                        }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Add new entity with UTF-16 character to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function addLinkedEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)/Foods",
-                        method: "POST",
-                        headers: headers,
-                        data: newFood
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Add new linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function addEntityWithInlineFeedTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: {
-                            CategoryID: 42,
-                            Name: "Olive Products",
-                            Foods: [newFood]
-                        }
-                    };
-
-                    djstest.assertsExpected(3);
-                    verifyRequest(request, function () {
-                        ODataReadOracle.readEntry(foodsFeed + "(" + newFood.FoodID + ")", function (actualData) {
-                            djstest.assertAreEqual(actualData.Name, newFood.Name, "Verify inline entities were added");
-                            djstest.done();
-                        }, headers ? headers.Accept : undefined);
-                    });
-                }, "Add new entity with inline feed to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function addEntityWithInlineEntryTest(headers) {
-                    var request = {
-                        requestUri: foodsFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: $.extend({}, newFood, {
-                            Category: {
-                                CategoryID: 42,
-                                Name: "Olive Products"
-                            }
-                        })
-                    };
-
-                    djstest.assertsExpected(3);
-                    verifyRequest(request, function () {
-                        ODataReadOracle.readEntry(categoriesFeed + "(" + request.data.Category.CategoryID + ")", function (actualData) {
-                            djstest.assertAreEqual(actualData.Name, request.data.Category.Name, "Verify inline entities were added");
-                            djstest.done();
-                        }, headers ? headers.Accept : undefined);
-                    });
-                }, "Add new entity with inline entry to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function updateEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)",
-                        method: "PUT",
-                        headers: headers,
-                        data: {
-                            CategoryID: 0,
-                            Name: "Updated Category"
-                        }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Update entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                if (serviceName === "V4") {
-                    djstest.addTest(function updateEntityTest(headers) {
-                        var request = {
-                            requestUri: foodsFeed + "(0)",
-                            method: "PATCH",
-                            headers: headers,
-                            data: {
-                                "@odata.type": "#DataJS.Tests.V4.Food",
-                                AlternativeNames: ["one", "two"]
-                            }
-                        };
-
-                        djstest.assertsExpected(2);
-                        verifyRequest(request, djstest.done);
-                    }, "Update collection property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-                }
-
-                djstest.addTest(function updatePrimitivePropertyTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)/Name",
-                        method: "PUT",
-                        headers: headers,
-                        data: { value: "Updated Category" }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Update primitive property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function updateLinkedEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)/Foods(0)",
-                        method: "PUT",
-                        headers: headers,
-                        data: {
-                            "@odata.type": "#DataJS.Tests.V4.Food",
-                            Name: "Updated Food"
-                        }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Update linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function mergeEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)",
-                        method: "PATCH",
-                        headers: headers,
-                        data: { Name: "Merged Category" }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Merge entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function mergeLinkedEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed + "(0)/Foods(0)",
-                        method: "PATCH",
-                        headers: headers,
-                        data: {
-                            "@odata.type": "#DataJS.Tests.V4.Food",
-                            Name: "Merged Food"
-                        }
-                    };
-
-                    djstest.assertsExpected(2);
-                    verifyRequest(request, djstest.done);
-                }, "Merge linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-
-                djstest.addTest(function deleteEntityTest(headers) {
-                    var endpoint = categoriesFeed + "(0)";
-                    djstest.assertsExpected(2);
-                    odatajs.oData.request({
-                        requestUri: endpoint,
-                        method: "DELETE",
-                        headers: headers
-                    }, function (data, response) {
-                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
-                        $.ajax({
-                            url: endpoint,
-                            error: function (xhr) {
-                                djstest.assertAreEqual(xhr.status, httpStatusCode.notFound, "Verify response code of attempted retrieval after delete");
-                                djstest.done();
-                            },
-                            success: function () {
-                                djstest.fail("Delete failed: querying the endpoint did not return expected response code");
-                                djstest.done();
-                            }
-                        });
-                    }, unexpectedErrorHandler);
-                }, "Delete entity from " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
-            });
-        });
-    });
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-roundtrip-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-roundtrip-functional-tests.js b/datajs/tests/odata-roundtrip-functional-tests.js
deleted file mode 100644
index 6e3c356..0000000
--- a/datajs/tests/odata-roundtrip-functional-tests.js
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var verifyRequest = function (request, done) {
-        if (request.method == "POST") {
-            if (request.headers && request.headers["X-HTTP-Method"] == "MERGE") {
-                verifyMerge(request, done);
-            }
-            else {
-                verifyPost(request, done);
-            }
-        }
-        else if (request.method == "PUT") {
-            verifyPut(request, done);
-        }
-    };
-
-    var verifyPost = function (request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        odatajs.oData.request(request, function (data, response) {
-            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
-            ODataReadOracle.readJson(data.__metadata.uri, function (expectedData) {
-                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
-                done();
-            }, request.headers.Accept);
-        }, unexpectedErrorHandler);
-    };
-
-    var verifyPut = function (request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        odatajs.oData.request(request, function (data, response) {
-            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
-            ODataReadOracle.readJson(request.requestUri, function (actualData) {
-                djstest.assertAreEqualDeep(actualData, request.data, "Verify updated entry: " + httpOperation);
-                done();
-            }, request.headers.Accept);
-        }, unexpectedErrorHandler);
-    }
-
-    var verifyMerge = function (request, done) {
-        var httpOperation = request.method + " " + request.requestUri;
-        ODataReadOracle.readJson(request.requestUri, function (originalData) {
-            odatajs.oData.request(request, function (data, response) {
-                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
-                ODataReadOracle.readJson(request.requestUri, function (actualData) {
-                    // Merge the original data with the updated data to get the expected data
-                    var expectedData = $.extend(true, {}, originalData, request.data);
-                    djstest.assertAreEqualDeep(actualData, expectedData, "Verify merged data");
-                    done();
-                }, request.headers["Content-Type"]);
-            }, unexpectedErrorHandler);
-        }, request.headers["Content-Type"]);
-    }
-
-    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
-    var subset = function (object, subsetObject) {
-        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
-            var result = {};
-            for (subsetProp in subsetObject) {
-                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
-            }
-            return result;
-        }
-        else {
-            return object;
-        }
-    };
-
-    var service = "./endpoints/FoodStoreDataService.svc";
-    var foodsFeed = service + "/Foods";
-    var categoriesFeed = service + "/Categories";
-    //var mimeTypes = [undefined, "application/json", "application/atom+xml"];
-    var mimeTypes = ["application/json", "application/atom+xml"];
-
-    var httpStatusCode = {
-        created: 201,
-        noContent: 204,
-        notFound: 404
-    };
-
-    var newFood = {
-        "__metadata": {
-            type: "DataJS.Tests.Food"
-        },
-        FoodID: 42,
-        Name: "olive oil",
-        UnitPrice: 3.14,
-        ServingSize: "1",
-        MeasurementUnit: "Cup",
-        ProteinGrams: 5,
-        FatGrams: 9,
-        CarbohydrateGrams: 2,
-        CaloriesPerServing: "6",
-        IsAvailable: true,
-        ExpirationDate: new Date("2011/05/03 12:00:00 PM"),
-        ItemGUID: "27272727-2727-2727-2727-272727272727",
-        Weight: 10,
-        AvailableUnits: 1,
-        Packaging: {
-            Type: "Can",
-            Color: "White",
-            NumberPerPackage: 1,
-            RequiresRefridgeration: false,
-            PackageDimensions: {
-                Length: "4",
-                Height: 3,
-                Width: "2",
-                Volume: 1
-            },
-            ShipDate: new Date("2011/01/01 12:00:00 PM")
-        }
-    };
-
-    var newFoodLinks = {
-        uri: foodsFeed + "(1)"
-    }
-
-    module("Functional", {
-        setup: function () {
-            $.ajax({ async: false, type: "POST", url: service + "/ResetData" });
-        }
-    });
-
-    $.each(mimeTypes, function (_, mimeType) {
-        var headers = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
-
-                djstest.addTest(function addEntityTest(headers) {
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: {
-                            CategoryID: 42,
-                            Name: "New Category"
-                        }
-                    };
-
-                    verifyRequest(request, function () {
-                        odatajs.oData.read({ requestUri: categoriesFeed + "(42)", headers: { Accept: mimeType} }, function (actualData, response) {
-                            actualData.CategoryID = 27;
-                            var newRequest = {
-                                requestUri: categoriesFeed,
-                                method: "POST",
-                                headers: headers,
-                                data: actualData
-                            };
-                            verifyRequest(newRequest, function () { djstest.done(); });
-                        }, request.headers["Content-Type"]);
-                    });
-
-                }, "Post, read posted data, post read data (mimeType = " + mimeType + ")", headers);
-
-        djstest.addTest(function addLinkedEntityTest(headers) {
-            var request = {
-                requestUri: categoriesFeed + "(0)/Foods",
-                method: "POST",
-                headers: headers,
-                data: newFood
-            };
-
-            verifyRequest(request, function () {
-                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(42)", headers: { Accept: mimeType} }, function (actualData, response) {
-                    actualData.FoodID = 94;
-                    var newRequest = {
-                        requestUri: categoriesFeed + "(0)/Foods",
-                        method: "POST",
-                        headers: headers,
-                        data: actualData
-                    };
-                    verifyRequest(newRequest, function () { djstest.done(); });
-                }, request.headers["Content-Type"]);
-            });
-        }, "POST, read, POST an entry " + mimeType + ")", headers);
-
-
-        djstest.addTest(function addLinkedEntityTest(headers) {
-            var request = {
-                requestUri: categoriesFeed + "(0)/Foods(0)",
-                method: "PUT",
-                headers: headers,
-                data: newFood
-            };
-
-            verifyRequest(request, function () {
-                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(0)", headers: { Accept: mimeType} }, function (actualData, response) {
-                    var newRequest = {
-                        requestUri: categoriesFeed + "(0)/Foods(0)",
-                        method: "PUT",
-                        headers: headers,
-                        data: {
-                            "__metadata": { type: "DataJS.Tests.Food" },
-                            Name: "New Food" 
-                        }
-                    };
-                    verifyRequest(newRequest, function () { djstest.done(); });
-                });
-            });
-        }, "PUT, read, PUT a new linked entry " + mimeType + ")", headers);
-
-        djstest.addTest(function addEntityWithInlineFeedTest(headers) {
-            var request = {
-                requestUri: categoriesFeed,
-                method: "POST",
-                headers: headers,
-                data: {
-                    CategoryID: 42,
-                    Name: "Olive Products",
-                    Foods: [newFood]
-                }
-            };
-
-            verifyRequest(request, function () {
-                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
-                    var newRequest = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: {
-                            CategoryID: 27,
-                            Name: "Olive Products",
-                            Foods: [actualData]
-                        }
-                    };
-                    verifyRequest(newRequest, function () { djstest.done(); });
-                });
-            });
-
-        }, "POST, read, POST an entity with inline feed " + mimeType + ")", headers);
-
-        djstest.addTest(function addEntityWithInlineEntryTest(headers) {
-            var request = {
-                requestUri: foodsFeed,
-                method: "POST",
-                headers: headers,
-                data: $.extend({}, newFood, {
-                    Category: {
-                        "__metadata": { uri: "" },
-                        CategoryID: 42,
-                        Name: "Olive Products"
-                    }
-                })
-            };
-
-            verifyRequest(request, function () {
-                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
-                    actualData.FoodID = 76;
-                    var newRequest = {
-                        requestUri: foodsFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: $.extend({}, actualData, {
-                            Category: {
-                                "__metadata": { uri: "" },
-                                CategoryID: 27,
-                                Name: "Olive Products"
-                            }
-                        })
-                    };
-                    verifyRequest(newRequest, function () { djstest.done(); });
-                });
-            });
-        }, "Add new entity with inline entry (mimeType = " + mimeType + ")", headers);
-
-        djstest.addTest(function addEntityTest(headers) {
-            var request = {
-                requestUri: categoriesFeed + "(1)",
-                method: "PUT",
-                headers: headers,
-                data: {
-                    CategoryID: 1,
-                    Name: "New Category"
-                }
-            };
-
-            verifyRequest(request, function () {
-                odatajs.oData.read({ requestUri: categoriesFeed + "(1)", headers: { Accept: mimeType} }, function (actualData, response) {
-                    actualData.CategoryID = 2;
-                    var newRequest = {
-                        requestUri: categoriesFeed + "(2)",
-                        method: "PUT",
-                        headers: headers,
-                        data: actualData
-                    };
-                    verifyRequest(newRequest, function () { djstest.done(); });
-                }, request.headers["Content-Type"]);
-            });
-
-        }, "Put, read put data, put read data (mimeType = " + mimeType + ")", headers);
-
-        djstest.addTest(function addEntityTest(headers) {
-            odatajs.oData.read({ requestUri: foodsFeed + "(0)", headers: { Accept: mimeType} },
-                function (actualData, response) {
-                    actualData.CategoryID = 216;
-                    var request = {
-                        requestUri: foodsFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: actualData
-                    };
-                    verifyRequest(request,
-                        function () {
-                            odatajs.oData.read({ requestUri: foodsFeed + "(216)", headers: { Accept: mimeType} },
-                                function (data, response) {
-                                    ODataReadOracle.readJson(foodsFeed + "(216)",
-                                        function (expectedData) {
-                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                            djstest.done();
-                                        });
-                                });
-                        });
-                });
-        }, "Read data with dates, post read data with dates to new ID, read new ID data with dates" + mimeType + ")", headers);
-
-        djstest.addTest(function addEntityTest(headers) {
-            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} }, 
-                function (actualData, response) {
-                    actualData.CategoryID = 81;
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: actualData
-                    };
-                    verifyRequest(request, 
-                        function () { 
-                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} }, 
-                                function (data, response) {
-                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
-                                        function (expectedData) {
-                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                            djstest.done();
-                                        }
-                                    );
-                                }
-                            );
-                        }
-                    );
-                }
-            );
-        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
-
-
-        djstest.addTest(function addEntityTest(headers) {
-            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} },
-                function (actualData, response) {
-                    actualData.CategoryID = 81;
-                    var request = {
-                        requestUri: categoriesFeed,
-                        method: "POST",
-                        headers: headers,
-                        data: actualData
-                    };
-                    verifyRequest(request,
-                        function () {
-                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} },
-                                function (data, response) {
-                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
-                                        function (expectedData) {
-                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
-                                            djstest.done();
-                                        });
-                                });
-                        });
-                });
-        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
-    });
-})(this);
\ No newline at end of file


[37/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/code/ReflectionDataContext.cs
----------------------------------------------------------------------
diff --git a/datajs/tests/code/ReflectionDataContext.cs b/datajs/tests/code/ReflectionDataContext.cs
deleted file mode 100644
index 1635d54..0000000
--- a/datajs/tests/code/ReflectionDataContext.cs
+++ /dev/null
@@ -1,743 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections;
-    using System.Collections.Generic;
-    using System.Collections.ObjectModel;
-    using Microsoft.OData.Service;
-    using System.Globalization;
-    using System.Linq;
-    using System.Reflection;
-
-    /// <summary>
-    /// Provides a reflection-based, updatable data context.
-    /// </summary>
-    public abstract class ReflectionDataContext
-    {
-        // Fields
-        private List<object> deletedObjects = new List<object>();
-        private List<Action> pendingChanges;
-        private static Dictionary<Type, Dictionary<string, IList>> resourceSetsByContextTypeStorage = new Dictionary<Type, Dictionary<string, IList>>();
-
-        // Methods
-        protected ReflectionDataContext()
-        {
-            this.MetadataHelper = new ReflectionMetadataHelper(this);
-            this.pendingChanges = new List<Action>();
-            if (!resourceSetsByContextTypeStorage.ContainsKey(base.GetType()))
-            {
-                resourceSetsByContextTypeStorage.Add(base.GetType(), new Dictionary<string, IList>());
-                foreach (string resourceSetName in this.MetadataHelper.GetResourceSetNames())
-                {
-                    Type resourceType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
-                    IList listOfTInstance = Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { resourceType })) as IList;
-                    this.ResourceSetsStorage.Add(resourceSetName, listOfTInstance);
-                }
-            }
-            this.EnsureDataIsInitialized();
-        }
-
-        public virtual void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
-            ExceptionUtilities.CheckArgumentNotNull(resourceToBeAdded, "resourceToBeAdded");
-            UpdatableToken targetToken = UpdatableToken.AssertIsToken(targetResource, "targetResource");
-            targetResource = targetToken.Resource;
-            resourceToBeAdded = UpdatableToken.AssertIsTokenAndResolve(resourceToBeAdded, "resourceToBeAdded");
-            IList list = this.GetValue(targetToken, propertyName) as IList;
-            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
-            this.pendingChanges.Add(delegate {
-                list.Add(resourceToBeAdded);
-            });
-        }
-
-        public virtual void ClearChanges()
-        {
-            this.pendingChanges.Clear();
-        }
-
-        public void ClearData()
-        {
-            this.ResourceSetsStorage.Clear();
-        }
-
-        private static bool CompareETagValues(Dictionary<string, object> resourceCookieValues, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
-        {
-            if (concurrencyValues.Count<KeyValuePair<string, object>>() != resourceCookieValues.Count)
-            {
-                return false;
-            }
-            foreach (KeyValuePair<string, object> keyValuePair in concurrencyValues)
-            {
-                if (!resourceCookieValues.ContainsKey(keyValuePair.Key))
-                {
-                    return false;
-                }
-                if (keyValuePair.Value == null)
-                {
-                    return (resourceCookieValues[keyValuePair.Key] == null);
-                }
-                if (!keyValuePair.Value.Equals(resourceCookieValues[keyValuePair.Key]))
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public virtual object CreateResource(string containerName, string fullTypeName)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(fullTypeName, "fullTypeName");
-            UpdatableToken token = this.InstantiateResourceType(fullTypeName);
-            if (containerName != null)
-            {
-                this.pendingChanges.Add(delegate {
-                    this.GetResourceSetEntities(containerName).Add(token.Resource);
-                });
-            }
-            return token;
-        }
-
-        private void DeleteAllReferences(object targetResource)
-        {
-            foreach (string currentSetName in this.MetadataHelper.GetResourceSetNames())
-            {
-                Type currentEntityType = this.MetadataHelper.GetResourceTypeOfSet(currentSetName);
-                IList entitySetList = this.GetResourceSetEntities(currentSetName);
-                foreach (NavigationPropertyInfo navigationProperty in this.MetadataHelper.GetNavigationProperties(GetResourceTypeFullName(currentEntityType)))
-                {
-                    if (navigationProperty.CollectionElementType != null)
-                    {
-                        foreach (object currentEntityInstance in entitySetList)
-                        {
-                            this.RemoveResourceFromCollectionOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
-                        }
-                    }
-                    else
-                    {
-                        ExceptionUtilities.CheckObjectNotNull(navigationProperty.PropertyInfo, "Invalid navigation property info", new object[0]);
-                        foreach (object currentEntityInstance in entitySetList)
-                        {
-                            this.SetEntityReferenceToNullOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
-                        }
-                    }
-                }
-            }
-        }
-
-        public virtual void DeleteResource(object targetResource)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            targetResource = UpdatableToken.AssertIsTokenAndResolve(targetResource, "targetResource");
-            string resourceSetName = this.GetResourceSetOfTargetResource(targetResource);
-            ExceptionUtilities.CheckObjectNotNull(resourceSetName, "Unable to find set of the resource to delete", new object[0]);
-            this.deletedObjects.Add(targetResource);
-            IList resourceSetList = this.GetResourceSetEntities(resourceSetName);
-            this.DeleteAllReferences(targetResource);
-            this.pendingChanges.Add(delegate {
-                resourceSetList.Remove(targetResource);
-            });
-        }
-
-        protected abstract void EnsureDataIsInitialized();
-
-        protected virtual Type GetCollectionPropertyType(string fullTypeName, string propertyName)
-        {
-            Type type = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
-            Type collectionType = null;
-            if (type != null)
-            {
-                PropertyInfo property = type.GetProperty(propertyName);
-                if (property != null)
-                {
-                    collectionType = property.PropertyType;
-                }
-            }
-            return collectionType;
-        }
-
-        private Dictionary<string, object> GetConcurrencyValues(object targetResource)
-        {
-            Dictionary<string, object> etagValues = new Dictionary<string, object>();
-            foreach (string etagProperty in this.MetadataHelper.GetETagPropertiesOfType(GetResourceTypeFullName(targetResource.GetType())))
-            {
-                etagValues.Add(etagProperty, targetResource.GetType().GetProperty(etagProperty).GetValue(targetResource, null));
-            }
-            return etagValues;
-        }
-
-        public virtual object GetResource(IQueryable query, string fullTypeName)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(query, "query");
-            object resource = null;
-            foreach (object r in query)
-            {
-                ExceptionUtilities.Assert(resource == null, "Invalid Uri specified. The query '{0}' must refer to a single resource", new object[] { query.ToString() });
-                resource = r;
-            }
-            if (resource == null)
-            {
-                return null;
-            }
-            if (fullTypeName != null)
-            {
-                this.ValidateResourceType(resource, fullTypeName);
-            }
-            return new UpdatableToken(resource);
-        }
-
-        public IList<T> GetResourceSetEntities<T>(string resourceSetName)
-        {
-            return (IList<T>) this.GetResourceSetEntities(resourceSetName);
-        }
-
-        internal IList GetResourceSetEntities(string resourceSetName)
-        {
-            IList entities;
-            if (!this.ResourceSetsStorage.TryGetValue(resourceSetName, out entities))
-            {
-                Type elementType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
-                entities = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { elementType }));
-                this.ResourceSetsStorage[resourceSetName] = entities;
-            }
-            return entities;
-        }
-
-        private string GetResourceSetOfTargetResource(object targetResource)
-        {
-            foreach (string currentResourceSetName in this.MetadataHelper.GetResourceSetNames())
-            {
-                if (this.GetResourceSetEntities(currentResourceSetName).Contains(targetResource))
-                {
-                    return currentResourceSetName;
-                }
-            }
-            return null;
-        }
-
-        public static string GetResourceTypeFullName(Type type)
-        {
-            return type.FullName.Replace('+', '_');
-        }
-
-        public virtual object GetValue(object targetResource, string propertyName)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
-            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
-            if (token.PendingPropertyUpdates.ContainsKey(propertyName))
-            {
-                return token.PendingPropertyUpdates[propertyName];
-            }
-            targetResource = token.Resource;
-            PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
-            ExceptionUtilities.CheckObjectNotNull(pi, "Cannot find the property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
-            object value = pi.GetValue(targetResource, null);
-            if ((value != null) && (pi.PropertyType.Assembly == base.GetType().Assembly))
-            {
-                ExceptionUtilities.Assert(!this.MetadataHelper.IsTypeAnEntityType(pi.PropertyType), "GetValue should never be called for reference properties. Type was '{0}', property was '{1}'", new object[] { pi.PropertyType.FullName, propertyName });
-                value = new UpdatableToken(value);
-            }
-            return value;
-        }
-
-        private UpdatableToken InstantiateResourceType(string fullTypeName)
-        {
-            Type t = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
-            object instance = Activator.CreateInstance(t);
-            UpdatableToken token = new UpdatableToken(instance);
-            foreach (PropertyInfo p in t.GetProperties())
-            {
-                object generatedValue;
-                PropertyInfo property = p;
-                if (this.IsCollectionProperty(property))
-                {
-                    Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(t), property.Name);
-                    if (collectionType != null)
-                    {
-                        object newCollection = Activator.CreateInstance(collectionType);
-                        token.PendingPropertyUpdates[property.Name] = newCollection;
-                        this.pendingChanges.Add(delegate {
-                            property.SetValue(instance, newCollection, null);
-                        });
-                    }
-                }
-                if (this.TryGetStoreGeneratedValue(fullTypeName, property.Name, out generatedValue))
-                {
-                    token.PendingPropertyUpdates[property.Name] = generatedValue;
-                    this.pendingChanges.Add(delegate {
-                        property.SetValue(instance, generatedValue, null);
-                    });
-                }
-            }
-            return token;
-        }
-
-        protected virtual bool IsCollectionProperty(PropertyInfo propertyInfo)
-        {
-            return ((typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType) && (propertyInfo.PropertyType != typeof(string))) && (propertyInfo.PropertyType != typeof(byte[])));
-        }
-
-        public virtual void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
-            ExceptionUtilities.CheckArgumentNotNull(resourceToBeRemoved, "resourceToBeRemoved");
-            UpdatableToken.AssertIsToken(targetResource, "targetResource");
-            resourceToBeRemoved = UpdatableToken.AssertIsTokenAndResolve(resourceToBeRemoved, "resourceToBeRemoved");
-            IList list = this.GetValue(targetResource, propertyName) as IList;
-            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
-            this.pendingChanges.Add(delegate {
-                list.Remove(resourceToBeRemoved);
-            });
-        }
-
-        private void RemoveResourceFromCollectionOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
-        {
-            IEnumerable childCollectionObject = navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) as IEnumerable;
-            if (childCollectionObject.Cast<object>().Any<object>(delegate (object o) {
-                return o == targetResource;
-            }))
-            {
-                MethodInfo removeMethod = navigationPropertyInfo.PropertyInfo.PropertyType.GetMethod("Remove");
-                this.pendingChanges.Add(delegate {
-                    removeMethod.Invoke(childCollectionObject, new object[] { targetResource });
-                });
-            }
-        }
-
-        public virtual object ResetResource(object resource)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
-            UpdatableToken token = UpdatableToken.AssertIsToken(resource, "resource");
-            resource = token.Resource;
-            token = new UpdatableToken(resource);
-            object newInstance = Activator.CreateInstance(resource.GetType());
-            ExceptionUtilities.CheckObjectNotNull(newInstance, "Cannot reset resource because unable to creating new instance of type '{0}' returns null", new object[] { resource.GetType().Name });
-            foreach (string propertyToReset in this.MetadataHelper.GetPropertiesToReset(GetResourceTypeFullName(resource.GetType())))
-            {
-                PropertyInfo pi = newInstance.GetType().GetProperty(propertyToReset);
-                ExceptionUtilities.CheckObjectNotNull(pi, "Cannot reset resource because unable to find property '{0}'", new object[] { propertyToReset });
-                object newValue = pi.GetValue(newInstance, null);
-                this.pendingChanges.Add(delegate {
-                    pi.SetValue(resource, newValue, null);
-                });
-                token.PendingPropertyUpdates[propertyToReset] = newValue;
-            }
-            return token;
-        }
-
-        public virtual object ResolveResource(object resource)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
-            return UpdatableToken.AssertIsTokenAndResolve(resource, "resource");
-        }
-
-        public virtual void SaveChanges()
-        {
-            foreach (Action pendingChange in this.pendingChanges)
-            {
-                pendingChange();
-            }
-            this.pendingChanges.Clear();
-            foreach (object deleted in this.deletedObjects)
-            {
-                foreach (object entity in this.ResourceSetsStorage.SelectMany<KeyValuePair<string, IList>, object>(delegate (KeyValuePair<string, IList> p) {
-                    return p.Value.Cast<object>();
-                }))
-                {
-                    ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, entity), "Found deleted entity!", new object[0]);
-                    foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties())
-                    {
-                        object value = propertyInfo.GetValue(entity, null);
-                        ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, value), "Found deleted entity!", new object[0]);
-                        IEnumerable enumerable = value as IEnumerable;
-                        if (enumerable != null)
-                        {
-                            foreach (object valueElement in enumerable.Cast<object>())
-                            {
-                                ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, valueElement), "Found deleted entity!", new object[0]);
-                            }
-                        }
-                    }
-                }
-            }
-            this.deletedObjects.Clear();
-        }
-
-        protected virtual void SetCollectionPropertyValue(object targetResource, PropertyInfo propertyInfo, IEnumerable propertyValue)
-        {
-            object collection;
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyInfo, "propertyInfo");
-            ExceptionUtilities.CheckArgumentNotNull(propertyValue, "propertyValue");
-            Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(propertyInfo.ReflectedType), propertyInfo.Name);
-            ExceptionUtilities.CheckObjectNotNull(collectionType, "Could not infer collection type for property", new object[0]);
-            propertyValue = propertyValue.Cast<object>().Select<object, object>(delegate (object o) {
-                return UpdatableToken.ResolveIfToken(o);
-            });
-            ConstructorInfo enumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable) });
-            if (enumerableConstructor != null)
-            {
-                collection = enumerableConstructor.Invoke(new object[] { propertyValue });
-            }
-            else if (collectionType.IsGenericType && (collectionType.GetGenericArguments().Count<Type>() == 1))
-            {
-                Type typeArgument = collectionType.GetGenericArguments().Single<Type>();
-                ConstructorInfo typedEnumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable<>).MakeGenericType(new Type[] { typeArgument }) });
-                if (typedEnumerableConstructor != null)
-                {
-                    object typedEnumerable = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new Type[] { typeArgument }).Invoke(null, new object[] { propertyValue });
-                    collection = typedEnumerableConstructor.Invoke(new object[] { typedEnumerable });
-                }
-                else
-                {
-                    MethodInfo typedAddMethod = collectionType.GetMethod("Add", new Type[] { typeArgument });
-                    ExceptionUtilities.CheckObjectNotNull(typedAddMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
-                    collection = Activator.CreateInstance(collectionType);
-                    foreach (object element in propertyValue)
-                    {
-                        typedAddMethod.Invoke(collection, new object[] { element });
-                    }
-                }
-            }
-            else
-            {
-                MethodInfo addMethod = collectionType.GetMethod("Add");
-                ExceptionUtilities.CheckObjectNotNull(addMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
-                collection = Activator.CreateInstance(collectionType);
-                foreach (object element in propertyValue)
-                {
-                    addMethod.Invoke(collection, new object[] { element });
-                }
-            }
-            propertyInfo.SetValue(targetResource, collection, null);
-        }
-
-        public virtual void SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(resourceCookie, "resourceCookie");
-            ExceptionUtilities.ThrowDataServiceExceptionIfFalse(checkForEquality.HasValue, 0x1a1, "Missing concurrency token for update operation", new object[0]);
-            ExceptionUtilities.Assert(checkForEquality.Value, "Should not be called with check for equality parameter equal to false", new object[0]);
-            ExceptionUtilities.CheckArgumentNotNull(concurrencyValues, "concurrencyValues");
-            if (concurrencyValues.Any<KeyValuePair<string, object>>())
-            {
-                resourceCookie = UpdatableToken.AssertIsTokenAndResolve(resourceCookie, "resourceCookie");
-                ExceptionUtilities.ThrowDataServiceExceptionIfFalse(CompareETagValues(this.GetConcurrencyValues(resourceCookie), concurrencyValues), 0x19c, "Concurrency tokens do not match", new object[0]);
-            }
-        }
-
-        private void SetEntityReferenceToNullOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
-        {
-            if (navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) == targetResource)
-            {
-                this.pendingChanges.Add(delegate {
-                    navigationPropertyInfo.PropertyInfo.SetValue(currentEntityInstance, null, null);
-                });
-            }
-        }
-
-        public virtual void SetReference(object targetResource, string propertyName, object propertyValue)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
-            if (propertyValue != null)
-            {
-                UpdatableToken.AssertIsToken(propertyValue, "propertyValue");
-            }
-            this.SetValue(targetResource, propertyName, propertyValue);
-        }
-
-        public virtual void SetValue(object targetResource, string propertyName, object propertyValue)
-        {
-            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
-            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
-            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
-            targetResource = token.Resource;
-            token.PendingPropertyUpdates[propertyName] = propertyValue;
-            this.pendingChanges.Add(delegate {
-                object generatedValue;
-                Type t = targetResource.GetType();
-                PropertyInfo pi = t.GetProperty(propertyName);
-                ExceptionUtilities.CheckObjectNotNull(pi, "Unable to find property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
-                if (this.TryGetStoreGeneratedValue(GetResourceTypeFullName(t), propertyName, out generatedValue))
-                {
-                    propertyValue = generatedValue;
-                }
-                if (this.IsCollectionProperty(pi))
-                {
-                    ExceptionUtilities.CheckObjectNotNull(propertyValue, "Collection property value was null", new object[0]);
-                    IEnumerable enumerable = propertyValue as IEnumerable;
-                    ExceptionUtilities.CheckObjectNotNull(enumerable, "Collection property value was not an enumerable", new object[0]);
-                    this.SetCollectionPropertyValue(targetResource, pi, enumerable);
-                }
-                else
-                {
-                    propertyValue = UpdatableToken.ResolveIfToken(propertyValue);
-                    pi.SetValue(targetResource, propertyValue, null);
-                }
-            });
-        }
-
-        protected virtual bool TryGetStoreGeneratedValue(string fullTypeName, string propertyName, out object propertyValue)
-        {
-            propertyValue = null;
-            return false;
-        }
-
-        private void ValidateResourceType(object targetResource, string fullTypeName)
-        {
-            ExceptionUtilities.Assert(this.MetadataHelper.FindClrTypeByFullName(fullTypeName).IsAssignableFrom(targetResource.GetType()), "Invalid uri specified. expected type: '{0}', actual type: '{1}'", new object[] { fullTypeName, targetResource.GetType().FullName });
-        }
-
-        // Properties
-        internal ReflectionMetadataHelper MetadataHelper { get; set; }
-
-        internal Dictionary<string, IList> ResourceSetsStorage
-        {
-            get
-            {
-                Dictionary<string, IList> resourceSetsLookup = null;
-                Type currentContextType = base.GetType();
-                ExceptionUtilities.Assert(resourceSetsByContextTypeStorage.TryGetValue(currentContextType, out resourceSetsLookup), "Cannot find resource sets by the context type '{0}'", new object[] { currentContextType });
-                return resourceSetsLookup;
-            }
-        }
-
-        #region Inner types.
-    
-        internal class ReflectionMetadataHelper
-        {
-            // Fields
-            private ReflectionDataContext reflectionDataContext;
-
-            // Methods
-            public ReflectionMetadataHelper(ReflectionDataContext reflectionDataContext)
-            {
-                this.reflectionDataContext = reflectionDataContext;
-            }
-
-            public Type FindClrTypeByFullName(string resourceTypeFullName)
-            {
-                Type type = this.reflectionDataContext.GetType().Assembly.GetTypes().Where<Type>(delegate (Type t) {
-                    return (ReflectionDataContext.GetResourceTypeFullName(t) == resourceTypeFullName);
-                }).FirstOrDefault<Type>();
-                ExceptionUtilities.CheckObjectNotNull(type, "Unable to find type '{0}'", new object[] { resourceTypeFullName });
-                return type;
-            }
-
-            public string[] GetETagPropertiesOfType(string fullTypeName)
-            {
-                Type type = this.FindClrTypeByFullName(fullTypeName);
-                List<string> etags = new List<string>();
-                foreach (ETagAttribute customAttribute in type.GetCustomAttributes(typeof(ETagAttribute), true))
-                {
-                    etags.AddRange(customAttribute.PropertyNames);
-                }
-                
-                return etags.ToArray();
-            }
-
-            public string[] GetKeyProperties(string fullTypeName)
-            {
-                Type type = this.FindClrTypeByFullName(fullTypeName);
-                List<string> keyPropertyList = new List<string>();
-                foreach (PropertyInfo keyProperty in type.GetProperties().Where(pi => pi.Name.Contains("ID")))
-                {
-                    keyPropertyList.Add(keyProperty.Name);
-                }
-                
-                return keyPropertyList.ToArray();
-            }
-
-            public NavigationPropertyInfo[] GetNavigationProperties(string fullTypeName)
-            {
-                Type type = this.FindClrTypeByFullName(fullTypeName);
-                var navigationProperties = new List<NavigationPropertyInfo>();
-                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
-                foreach (PropertyInfo pi in type.GetProperties())
-                {
-                    if (!keyProperties.Contains(pi.Name))
-                    {
-                        if (this.IsTypeAnEntityType(pi.PropertyType))
-                        {
-                            navigationProperties.Add(new NavigationPropertyInfo(pi, null));
-                        }
-
-                        if (pi.PropertyType.IsGenericType && ((pi.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) || (pi.PropertyType.GetGenericTypeDefinition() == typeof(Collection<>))))
-                        {
-                            Type elementType = pi.PropertyType.GetGenericArguments()[0];
-                            if (this.IsTypeAnEntityType(elementType))
-                            {
-                                navigationProperties.Add(new NavigationPropertyInfo(pi, elementType));
-                            }
-                        }
-                    }
-                }
-
-                return navigationProperties.ToArray();
-            }
-
-            public string[] GetPropertiesToReset(string fullTypeName)
-            {
-                Type type = this.FindClrTypeByFullName(fullTypeName);
-                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
-                var navigationProperties = new List<string>(this.GetNavigationProperties(fullTypeName).Select(ni =>ni.PropertyInfo.Name));
-                return type.GetProperties().Where(
-                    pi => !keyProperties.Contains(pi.Name) && !navigationProperties.Contains(pi.Name)
-                ).Select(pi => pi.Name).ToArray();
-            }
-
-            public string[] GetResourceSetNames()
-            {
-                return this.reflectionDataContext.GetType().GetProperties().Where(
-                    pi => pi.PropertyType.IsGenericType && (pi.PropertyType.GetGenericTypeDefinition() == typeof(IQueryable<>))
-                ).Select(pi => pi.Name).ToArray();
-            }
-
-            public Type GetResourceTypeOfSet(string resourceSetName)
-            {
-                PropertyInfo resourceSetPropertyInfo = this.reflectionDataContext.GetType().GetProperties().Where(pi => pi.Name == resourceSetName).FirstOrDefault();
-                ExceptionUtilities.CheckObjectNotNull(resourceSetPropertyInfo, "Error finding type of set '{0}'", new object[] { resourceSetName });
-                return resourceSetPropertyInfo.PropertyType.GetGenericArguments()[0];
-            }
-
-            public bool IsTypeAnEntityType(Type t)
-            {
-                foreach (string setName in this.GetResourceSetNames())
-                {
-                    if (this.GetResourceTypeOfSet(setName).IsAssignableFrom(t))
-                    {
-                        return true;
-                    }
-                }
-
-                return false;
-            }
-        }
-
-        internal static class ExceptionUtilities
-        {
-            // Methods
-            public static void Assert(bool condition, string errorMessage, params object[] messageArguments)
-            {
-                if (!condition)
-                {
-                    throw new InvalidOperationException("Assertion failed: " + string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
-                }
-            }
-
-            public static void CheckArgumentNotNull(object argument, string argumentName)
-            {
-                if (argument == null)
-                {
-                    throw new ArgumentNullException(argumentName);
-                }
-            }
-
-            public static void CheckCollectionNotEmpty<TElement>(IEnumerable<TElement> argument, string argumentName)
-            {
-                CheckArgumentNotNull(argument, argumentName);
-                if (!argument.Any<TElement>())
-                {
-                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Collection argument '{0}' must have at least one element.", new object[] { argumentName }));
-                }
-            }
-
-            public static void CheckObjectNotNull(object value, string exceptionMessageFormatText, params object[] messageArguments)
-            {
-                Assert(exceptionMessageFormatText != null, "message cannnot be null", new object[0]);
-                Assert(messageArguments != null, "messageArguments cannnot be null", new object[0]);
-                if (value == null)
-                {
-                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, exceptionMessageFormatText, messageArguments));
-                }
-            }
-
-            public static void ThrowDataServiceExceptionIfFalse(bool condition, int statusCode, string errorMessage, params object[] messageArguments)
-            {
-                if (!condition)
-                {
-                    throw new DataServiceException(statusCode, string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
-                }
-            }
-        }
-
-        public class UpdatableToken
-        {
-            // Methods
-            public UpdatableToken(object resource)
-            {
-                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
-                this.Resource = resource;
-                this.PendingPropertyUpdates = new Dictionary<string, object>();
-            }
-
-            public static UpdatableToken AssertIsToken(object resource, string name)
-            {
-                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
-                UpdatableToken token = resource as UpdatableToken;
-                ExceptionUtilities.CheckObjectNotNull(token, "{0} was not a token. Type was: '{1}'", new object[] { name, resource.GetType() });
-                return token;
-            }
-
-            public static object AssertIsTokenAndResolve(object resource, string name)
-            {
-                return AssertIsToken(resource, name).Resource;
-            }
-
-            public static object ResolveIfToken(object resource)
-            {
-                UpdatableToken token = resource as UpdatableToken;
-                if (token != null)
-                {
-                    resource = token.Resource;
-                }
-                return resource;
-            }
-
-            // Properties
-            public IDictionary<string, object> PendingPropertyUpdates { get; set; }
-
-            public object Resource { get; set; }
-        }
-
-        internal class NavigationPropertyInfo
-        {
-            // Methods
-            internal NavigationPropertyInfo(PropertyInfo pi, Type collectionElementType)
-            {
-                this.PropertyInfo = pi;
-                this.CollectionElementType = collectionElementType;
-            }
-
-            // Properties
-            public Type CollectionElementType { get; set; }
-
-            public PropertyInfo PropertyInfo { get; set; }
-        }
-
-        #endregion Inner types.
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/code/csdlreader.cs
----------------------------------------------------------------------
diff --git a/datajs/tests/code/csdlreader.cs b/datajs/tests/code/csdlreader.cs
deleted file mode 100644
index c88333e..0000000
--- a/datajs/tests/code/csdlreader.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/// <summary>
-/// Class used to parse csdl to create the metatdata object
-/// </summary>
-/// 
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.IO;
-    using System.Linq;
-    using System.Xml.Linq;
-
-
-    public static class CsdlReader
-    {
-        static readonly string knownNamespace = "http://docs.oasis-open.org";
-        static readonly string[] repeatingElements = 
-            {
-                "Action",
-                "ActionImport",
-                "Annotation",
-                "Annotations",
-                "Apply",
-                "Binary",
-                "Bool",
-                "Cast",
-                "Collection",
-                "ComplexType",
-                "Date",
-                "DateTimeOffset",
-                "Decimal",
-                "Duration",
-                "EntitySet",
-                "EntityType",
-                "EnumMember",
-                "EnumType",
-                "Float",
-                "Function",
-                "FunctionImport",
-                "Guid",
-                "If",
-                "Int",
-                "IsOf",
-                "Key",
-                "LabeledElement",
-                "LabeledElementReference",
-                "Member",
-                "NavigationProperty",
-                "NavigationPropertyBinding",
-                "NavigationPropertyPath",
-                "Null",
-                "OnDelete",
-                "Path",
-                "Parameter",
-                "Property",
-                "PropertyPath",
-                "PropertyRef",
-                "PropertyValue",
-                "Record",
-                "ReferentialConstraint",
-                "String",
-                "Schema",
-                "Singleton",
-                "Term",
-                "TimeOfDay",
-                "TypeDefinition",
-                "UrlRef",
-                "Reference",
-                "Include",
-                "IncludeAnnotations"
-            };
-
-        public static Dictionary<string, object> ReadCsdl(TextReader payload)
-        {
-            return BuildElementJsonObject(XElement.Load(payload));
-        }
-
-        /// <summary>
-        /// Build the attribute object 
-        /// </summary>
-        /// <param name="xmlAttributes">IEnumberable of XAttributes to build the attribute object</param>
-        /// <returns>The JsonObject containing the name-value pairs for an element's attributes</returns>
-        static Dictionary<string, object> BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes)
-        {
-            Dictionary<string, object> jsonObject = new Dictionary<string, object>();
-
-            foreach (XAttribute attribute in xmlAttributes)
-            {
-                if (!attribute.IsNamespaceDeclaration)
-                {
-                    string attributeNamespace = attribute.Name.Namespace.ToString();
-                    if (string.IsNullOrEmpty(attributeNamespace) ||
-                        attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
-                    {
-                        jsonObject[MakeFirstLetterLowercase(attribute.Name.LocalName)] = attribute.Value;
-                    }
-                }
-            }
-
-            return jsonObject;
-        }
-
-        /// <summary>
-        /// Creates a JsonObject from an XML container element with each attribute or subelement as a property
-        /// </summary>
-        /// <param name="container">The XML container</param>
-        /// <param name="buildValue">Function that builds a value from a property element</param>
-        /// <returns>The JsonObject containing the name-value pairs</returns>
-        public static Dictionary<string, object> BuildElementJsonObject(XElement container)
-        {
-            if (container == null)
-            {
-                return null;
-            }
-
-            Dictionary<string, object> jsonObject = new Dictionary<string, object>();
-            string keyName = MakeFirstLetterLowercase(container.Name.LocalName);
-
-            if (container.HasAttributes || container.HasElements)
-            {
-                Dictionary<string, List<Dictionary<string, object>>> repeatingObjectArrays = new Dictionary<string, List<Dictionary<string, object>>>();
-
-                jsonObject = BuildAttributeJsonObject(container.Attributes());
-
-                foreach (XElement propertyElement in container.Elements())
-                {
-                    string propertyName = MakeFirstLetterLowercase(propertyElement.Name.LocalName);
-                    string properyNamespace = propertyElement.Name.Namespace.ToString();
-
-                    if (string.IsNullOrEmpty(properyNamespace) || properyNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
-                    {
-                        // Check to see if the element is repeating and needs to be an array
-                        if (repeatingElements.Contains(propertyElement.Name.LocalName))
-                        {
-                            // See if property was already created as an array, if not then create it
-                            if (!repeatingObjectArrays.ContainsKey(propertyName))
-                            {
-                                repeatingObjectArrays.Add(propertyName, new List<Dictionary<string, object>>());
-                            }
-
-                            repeatingObjectArrays[propertyName].Add(BuildElementJsonObject(propertyElement));
-                        }
-                        else
-                        {
-                            jsonObject[propertyName] = BuildElementJsonObject(propertyElement);
-                        }
-                    }
-                }
-
-                foreach (string key in repeatingObjectArrays.Keys)
-                {
-                    jsonObject[key] = repeatingObjectArrays[key].ToArray();
-                }
-            }
-            else
-            {
-                jsonObject[MakeFirstLetterLowercase(container.Name.LocalName)] = container.Value;
-            }
-
-            return jsonObject;
-        }
-
-        /// <summary>
-        /// Makes the first letter of a string lowercase
-        /// </summary>
-        /// <param name="name">The string to be modified</param>
-        /// <returns>Modified string</returns>
-        private static string MakeFirstLetterLowercase(string str)
-        {
-            if (!string.IsNullOrWhiteSpace(str))
-            {
-                if (str.Length > 1 && !(str[1].ToString() == str[1].ToString().ToUpper()))
-                {
-                    return str[0].ToString().ToLower() + str.Substring(1);
-                }
-                else
-                {
-                    return str;
-                }
-            }
-
-            return str;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/code/jsdate.cs
----------------------------------------------------------------------
diff --git a/datajs/tests/code/jsdate.cs b/datajs/tests/code/jsdate.cs
deleted file mode 100644
index 06f995d..0000000
--- a/datajs/tests/code/jsdate.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/// <summary>
-/// The oracle's representation of a Javascript date object as deserialized by the library
-/// </summary>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.IO;
-    using System.Linq;
-    using System.Net;
-    using System.Runtime.Serialization;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Syndication;
-    using System.ServiceModel.Web;
-    using System.Xml;
-    using System.Xml.Linq;
-    using Microsoft.Spatial;
-    using Microsoft.OData.Core;
-
-    [Serializable]
-    public class JsDate : JsonObject
-    {
-        private static readonly DateTime JsEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-
-        public JsDate(DateTime dateTime)
-            : base()
-        {
-            this["milliseconds"] = dateTime.Subtract(JsEpoch).TotalMilliseconds;
-        }
-
-        public JsDate(DateTimeOffset dateTimeOffset)
-            : this(dateTimeOffset.UtcDateTime)
-        {
-            this["__edmType"] = "Edm.DateTimeOffset";
-            this["__offset"] = (dateTimeOffset.Offset < TimeSpan.Zero ? "-" : "+") + dateTimeOffset.Offset.ToString("hh':'mm");
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/code/jsonobject.cs
----------------------------------------------------------------------
diff --git a/datajs/tests/code/jsonobject.cs b/datajs/tests/code/jsonobject.cs
deleted file mode 100644
index 27f4b9b..0000000
--- a/datajs/tests/code/jsonobject.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/// <summary>
-/// A weakly typed representation of a JSON object using a dictionary implementation
-/// </summary>
-/// <typeparam name="T">The CLR type of the values of the properties</typeparam>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Runtime.Serialization;
-
-    [Serializable]
-    [KnownType(typeof(JsonObject))]
-    [KnownType(typeof(JsonObject[]))]
-    [KnownType(typeof(JsDate))]
-    [KnownType(typeof(List<object>))]
-    public class JsonObject : ISerializable, IEnumerable<KeyValuePair<string, object>>
-    {
-        Dictionary<string, object> dictionary = new Dictionary<string, object>();
-
-        public void Remove(string key)
-        {
-            dictionary.Remove(key);
-        }
-
-        public object this[string key]
-        {
-            get
-            {
-                return this.dictionary[key];
-            }
-            set
-            {
-                this.dictionary[key] = value;
-            }
-        }
-
-        public bool ContainsKey(string key)
-        {
-            return this.dictionary.ContainsKey(key);
-        }
-
-        public static JsonObject Merge(JsonObject first, JsonObject second)
-        {
-            if (first == null)
-            {
-                return second;
-            }
-
-            if (second != null)
-            {
-                JsonObject merged = new JsonObject();
-                merged.dictionary = new Dictionary<string, object>(first.dictionary);
-                foreach (var pair in second.dictionary)
-                {
-                    merged.dictionary[pair.Key] = pair.Value;
-                }
-                return merged;
-            }
-            return first;
-        }
-
-        public void GetObjectData(SerializationInfo info, StreamingContext context)
-        {
-            this.dictionary.ToList().ForEach(pair => info.AddValue(pair.Key, pair.Value));
-        }
-
-        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
-        {
-            return this.dictionary.GetEnumerator();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return this.dictionary.GetEnumerator();
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/code/readerutils.cs
----------------------------------------------------------------------
diff --git a/datajs/tests/code/readerutils.cs b/datajs/tests/code/readerutils.cs
deleted file mode 100644
index 094a70c..0000000
--- a/datajs/tests/code/readerutils.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Web.Script.Serialization;
-
-namespace DataJS.Tests
-{
-    public static class ReaderUtils
-    {
-        public static JsonObject CreateEntryPropertyMetadata(string type)
-        {
-            return CreateEntryPropertyMetadata(type, true);
-        }
-
-        public static JsonObject CreateEntryPropertyMetadata(string type, bool withExtensions)
-        {
-            JsonObject json = new JsonObject();
-            json["type"] = type;
-
-
-            // TODO: add proper support for property extensions
-            if (withExtensions)
-            {
-                json["extensions"] = new JsonObject[] { };
-            }
-
-            return json;
-        }
-
-        public static JsonObject CreateExtension(string name, string nameSpace, string value)
-        {
-            JsonObject json = new JsonObject();
-            json["name"] = name;
-            json["namespaceURI"] = nameSpace;
-            json["value"] = value;
-            return json;
-        }
-
-        public static WebRequest CreateRequest(string url, string user = null, string password = null)
-        {
-            WebRequest request = WebRequest.Create(url);
-            if (user != null || password != null)
-            {
-                request.Credentials = new NetworkCredential(user, password);
-                request.PreAuthenticate = true;
-            }
-
-            return request;
-        }
-
-        public static Stream ConvertDictionarytoJsonlightStream(Dictionary<string, object> dict)
-        {
-            MemoryStream stream = new MemoryStream();
-            if (dict == null)
-            {
-                return stream;
-            }
-
-            string jsonString = new JavaScriptSerializer().Serialize(dict);
-            StreamWriter writer = new StreamWriter(stream);
-            writer.Write(jsonString);
-            writer.Flush();
-            stream.Position = 0;
-            return stream;
-        }
-
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/CacheOracle.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/CacheOracle.js b/datajs/tests/common/CacheOracle.js
deleted file mode 100644
index d34d79f..0000000
--- a/datajs/tests/common/CacheOracle.js
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// CacheOracle.js
-// This object verifies the operation of the cache.
-// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
-
-(function (window, undefined) {
-
-    var CacheOracle = function (baseUri, pageSize, total, cacheSize) {
-        /** Creates a new CacheOracle
-         * @param {String} baseUri - The base URI of the collection
-         * @param {Integer} pageSize - The page size used in the cache
-         * @param {Integer} total - The total number of items in the collection
-         * @param {Integer} cacheSize - Cache size in bytes
-         */
-        this.baseUri = baseUri;
-        this.pageSize = pageSize;
-        this.total = total;
-        this.cacheSize = (cacheSize !== undefined) ? cacheSize : 1024 * 1024;
-        this.actualSize = 0;
-        this.actualCount = 0;
-        this.cachedPages = [];
-        this.exactPageCount = (total % pageSize === 0);
-        this.maxPage = Math.floor(total / pageSize);
-        this.overflowed = this.cacheSize === 0;
-    };
-
-    CacheOracle.mechanisms = {
-        memory: "memory",
-        indexeddb: "indexeddb",
-        dom: "dom",
-        best: "best"
-    };
-
-    CacheOracle.isMechanismAvailable = function (mechanism) {
-        /** Determines if the specified local storage mechanism is available
-         * @param mechanism - The name of the mechanism
-         * @returns Whether the mechanism is available
-         */
-        switch (mechanism) {
-            case CacheOracle.mechanisms.indexeddb:
-                if (window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.indexedDB) {
-                    return true;
-                }
-                else {
-                    return false;
-                }
-                break;
-            case CacheOracle.mechanisms.dom:
-                if (window.localStorage) {
-                    return true;
-                }
-                else {
-                    return false;
-                }
-                break;
-            case CacheOracle.mechanisms.memory:
-            case CacheOracle.mechanisms.best:
-            case undefined:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    CacheOracle.prototype.clear = function () {
-        /** Clears the cache in the oracle
-        */
-        this.cachedPages = [];
-        this.actualSize = 0;
-        this.actualCount = 0;
-        this.overflowed = this.cacheSize === 0;
-    }
-
-    CacheOracle.prototype.verifyRequests = function (requests, responses, index, count, description, backwards, isPrefetch) {
-        /** Verifies the HTTP requests for a single data request, and updates the oracle with cached pages
-         * @param {Array} requests - The sequence of request objects (from OData.defaultHttpClient)
-         * @param {Array} responses - The sequence of response objects (from OData.defaultHttpClient)
-         * @param {Integer} index - The starting index of the read
-         * @param {Integer} count - The count of items in the read
-         * @param {String} description - The description of the requests being verified
-         * @param {Boolean} backwards - Whether or not filterBack is being verified
-         * @param {Boolean} isPrefetch - Whether the requests being verified come from the prefetcher
-         */
-        var that = this;
-
-        index = (index < 0 ? 0 : index);
-        var pageIndex = function (index) {
-            /** Returns the page index that the given item index belongs to
-             * @param {Integer} index - The item index
-             * @returns The page index
-             */
-            return Math.floor(index / that.pageSize);
-        };
-
-        var estimateSize = function (obj) {
-            /** Estimates the size of an object in bytes.
-             * @param {Object} obj - Object to determine the size of.
-             * @returns {Number} Estimated size of the object in bytes.
-             */
-
-            var size = 0;
-            var type = typeof obj;
-
-            if (type === "object" && obj) {
-                for (var name in obj) {
-                    size += name.length * 2 + estimateSize(obj[name]);
-                }
-            } else if (type === "string") {
-                size = obj.length * 2;
-            } else {
-                size = 8;
-            }
-            return size;
-        };
-
-        var expectedUris = [];
-        var responseIndex = 0;
-        if (count >= 0) {
-            var minPage = pageIndex(index);
-            var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(this.total));
-
-            // In the case that the index is outside the range of the collection the minPage will be greater than the maxPage  
-            maxPage = Math.max(minPage, maxPage);
-
-            if (!(isPrefetch && !this.exactPageCount && minPage > this.maxPage)) {
-                for (var page = minPage; page <= maxPage && this.actualCount <= this.total && !(isPrefetch && this.overflowed); page++) {
-                    if (!this.cachedPages[page]) {
-
-                        expectedUris.push(that.baseUri + "?$skip=" + page * this.pageSize + "&$top=" + (this.pageSize));
-
-                        var actualPageSize = 0;
-                        var actualPageCount = 0;
-                        if (responses[responseIndex] && responses[responseIndex].data) {
-                            actualPageSize += estimateSize(responses[responseIndex].data);
-                            actualPageCount += responses[responseIndex].data.value.length;
-                            // Handle server paging skipToken requests
-                            while (responses[responseIndex].data["@odata.nextLink"]) {
-                                var nextLink = responses[responseIndex].data["@odata.nextLink"];
-                                if (nextLink) {
-                                    var index = that.baseUri.indexOf(".svc/", 0);
-                                    if (index != -1) {
-                                        nextLink = that.baseUri.substring(0, index + 5) + nextLink;
-                                    }
-                                }
-
-                                expectedUris.push(nextLink);
-                                responseIndex++;
-                                actualPageSize += estimateSize(responses[responseIndex].data);
-                                actualPageCount += responses[responseIndex].data.value.length;
-                            }
-
-                            actualPageSize += 24; // 24 byte overhead for the pages (i)ndex, and (c)ount fields
-                        }
-
-                        responseIndex++;
-
-                        this.overflowed = this.cacheSize >= 0 && this.actualSize + actualPageSize > this.cacheSize;
-                        if (!this.overflowed) {
-                            this.cachedPages[page] = true;
-                            this.actualSize += actualPageSize;
-                            this.actualCount += actualPageCount;
-                        }
-                    }
-                }
-            }
-        }
-
-        if (backwards) {
-            expectedUris.reverse();
-        }
-
-        var actualUris = $.map(requests, function (r) { return r.requestUri; });
-        djstest.assertAreEqualDeep(actualUris, expectedUris, description);
-    };
-
-    CacheOracle.getExpectedFilterResults = function (data, filterIndex, filterCount, predicate, backwards) {
-        /** Verifies the cache filter returns the correct data
-         * @param {Array} collection - Array of items in the collection
-         * @param {Integer} filterIndex - The index value
-         * @param {Integer} filterCount - The count value
-         * @param {Function} predicate - Predicate to be applied in filter, takes an item
-         * @param {Boolean} backwards - Whether or not filterBackwards is being verified
-         */
-        if (!data || !data.value) {
-            return data;
-        }
-
-        var value = [];
-        if (filterCount !== 0) {
-            // Convert [item0, item1, ...] into [{ index: 0, item: item0 }, { index: 1, item: item1 }, ...]
-            var indexedCollection = $.map(data.value, function (item, index) {
-                return { index: index, item: item };
-            });
-
-            var grepPredicate = function (element, index) {
-                return predicate(element.item);
-            };
-
-            var index = filterIndex < 0 ? 0 : filterIndex;
-            var count = filterCount < 0 ? indexedCollection.length : filterCount;
-
-            value = backwards ?
-            // Slice up to 'index', filter, then slice 'count' number of items from the end
-                $.grep(indexedCollection.slice(0, index + 1), grepPredicate).slice(-count) :
-            // Slice from 'index' to the end, filter, then slice 'count' number of items from the beginning
-                $.grep(indexedCollection.slice(index), grepPredicate).slice(0, count);
-        }
-
-        var expectedResults = {};
-        for (var property in data) {
-            if (property == "value") {
-                expectedResults[property] = value;
-            } else {
-                expectedResults[property] = data[property];
-            }
-        }
-
-        return expectedResults;
-    };
-
-    window.CacheOracle = CacheOracle;
-
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/Instrument.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/Instrument.js b/datajs/tests/common/Instrument.js
deleted file mode 100644
index fab583a..0000000
--- a/datajs/tests/common/Instrument.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Instrument.js
-// Instrumentation utilities
-
-(function (window, undefined) {
-
-    var warmedUp = false;
-    var getBrowserMemorySize = function (success) {
-        /** Gets the memory size (in bytes) of the browser process
-         * @param {Function} success - The success callback
-         */
-        var makeRequest = function (success) {
-            $.get("./common/Instrument.svc/GetBrowserMemorySize", function (data) {
-                success(parseInt(data));
-            }, "text");
-        };
-
-        if (window.CollectGarbage) {
-            window.CollectGarbage();
-        }
-
-        if (!warmedUp) {
-            // Make a dummy request to warm it up
-            makeRequest(function () {
-                warmedUp = true;
-                makeRequest(success);
-            });
-        } else {
-            makeRequest(success);
-        }
-    }
-
-    window.Instrument = {
-        getBrowserMemorySize: getBrowserMemorySize
-    };
-
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/Instrument.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/common/Instrument.svc b/datajs/tests/common/Instrument.svc
deleted file mode 100644
index 111020f..0000000
--- a/datajs/tests/common/Instrument.svc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
-    Service="DataJS.Tests.Instrument" %>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Diagnostics;
-    using System.IO;
-    using System.Linq;
-    using System.Runtime.Serialization;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Syndication;
-    using System.ServiceModel.Web;
-    using System.Text;
-
-    /// <summary>
-    /// Instrumentation utilities
-    /// </summary>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class Instrument
-    {
-        static readonly Dictionary<string, string> userAgents = new Dictionary<string,string>
-        {
-            { "MSIE", "iexplore" },
-            { "Firefox", "firefox" },
-            { "Chrome", "chrome" },
-            { "Safari", "safari" }
-        };
-        
-        /// <summary>
-        /// Gets the memory size used by the browser
-        /// </summary>
-        /// <returns>The memory size used by the browser (in bytes), or zero if browser is not supported</returns>
-        [OperationContract]
-        [WebGet]
-        public Stream GetBrowserMemorySize()
-        {
-            string userAgentString = WebOperationContext.Current.IncomingRequest.UserAgent;
-            string userAgentKey = Instrument.userAgents.Keys.FirstOrDefault(ua => userAgentString.Contains(ua));
-
-            if (userAgentKey != null)
-            {
-                string processName = userAgents[userAgentKey];
-                long totalMemory = Process.GetProcessesByName(processName).Select(p => p.WorkingSet64).Sum();
-                
-                return new MemoryStream(Encoding.UTF8.GetBytes(totalMemory.ToString()));
-            }
-            else
-            {
-                return new MemoryStream(Encoding.UTF8.GetBytes("0"));
-            }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/ODataReadOracle.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/ODataReadOracle.js b/datajs/tests/common/ODataReadOracle.js
deleted file mode 100644
index 83967ce..0000000
--- a/datajs/tests/common/ODataReadOracle.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-
-// Client for the odata.read oracle service
-
-(function (window, undefined) {
-    var jsonMime = "application/json";
-    var universalMime = "*/*";
-
-    var readFeed = function (url, success, mimeType, recognizeDates) {
-        /** Calls the ReadFeed endpoint with the specified URL
-         * @param {String} url - The URL to read the feed from
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME media type in the Accept header
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) {
-            success(data);
-        });
-    };
-
-    var readEntry = function (url, success, mimeType, recognizeDates) {
-        /** Calls the ReadEntry endpoint with the specified URL
-         * @param {String} url - The URL to read the entry from
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME media type in the Accept header
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, success);
-    };
-
-    var readLinksEntry = function (url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        readJson(
-            url,
-            success
-        );
-    };
-
-    var readLinksFeed = function (url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        readJson(
-            url,
-            function (data) {
-                success(data);
-            }
-        );
-    };
-
-    var readMetadata = function (url, success) {
-        /** Calls the ReadMetadata endpoint with the specified URL
-         * @param {String} url - The URL to read the metadata from
-         * @param {Function} success - The success callback function
-         */
-        oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success);
-    };
-
-    var readServiceDocument = function (url, success, mimeType) {
-        /** Calls the ReadServiceDocument endpoint with the specified URL
-         * @param {String} url - The URL to the service
-         * @param {Function} success - The success callback function
-         * @param {String} mimeType - The MIME type being tested
-         */
-        var readMethod = getReadMethod(mimeType);
-        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success);
-    };
-
-    var readJson = function (url, success) {
-        $.ajax({
-            url: url,
-            accepts: null,
-            dataType: "json",
-            beforeSend: function (xhr) {
-                xhr.setRequestHeader("Accept", jsonMime);
-                xhr.setRequestHeader("OData-MaxVersion", "4.0");
-            },
-            success: function (data) {
-                success(data);
-            }
-        });
-    };
-
-    var readJsonAcrossServerPages = function (url, success) {
-        var data = {};
-        var readPage = function (url) {
-            readJson(url, function (feedData) {
-                var nextLink = feedData["@odata.nextLink"];
-                if (nextLink) {
-                    var index = url.indexOf(".svc/", 0);
-                    if (index != -1) {
-                        nextLink = url.substring(0, index + 5) + nextLink;
-                    }
-                }
-
-                if (data.value && feedData.value) {
-                    data.value = data.value.concat(feedData.value);
-                }
-                else {
-                    for (var property in feedData) {
-                        if (property != "@odata.nextLink") {
-                            data[property] = feedData[property];
-                        }
-                    }
-                }
-
-                if (nextLink) {
-                    readPage(nextLink);
-                }
-                else {
-                    success(data);
-                }
-            });
-        };
-
-        readPage(url);
-    };
-
-    var getReadMethod = function (mimeType) {
-        switch (mimeType) {
-            case jsonMime:
-            case universalMime:
-            default:
-                return "ReadJson";
-        }
-    };
-
-    var oracleRequest = function (method, endpoint, data, mimeType, recognizeDates, success) {
-        /** Requests a JSON object from the oracle service, removing WCF-specific artifacts
-         * @param {String} method - The HTTP method (GET or POST)
-         * @param {String} endpoint - The oracle endpoint
-         * @param {Object} data - The data to send with the request
-         * @param {Function} reviver - The reviver function to run on each deserialized object
-         * @param {Function} success - Success callback
-         */
-        var url = "./common/ODataReadOracle.svc/" + endpoint;
-        if (mimeType) {
-            data.mimeType = mimeType;
-        }
-
-        $.ajax({
-            type: method,
-            url: url,
-            data: data,
-            dataType: "text",
-            success: function (data) {
-                var json = JSON.parse(data);
-                success(json);
-            }
-        });
-    };
-
-    var removeProperty = function (data, property) {
-        /** Removes the specified property recursively from the given object
-         * @param {Object} data - The object to operate on
-         * @param {String} property - The name of the property to remove
-         */
-        if (typeof data === "object" && data !== null) {
-            if (data[property]) {
-                delete data[property];
-            }
-
-            for (prop in data) {
-                removeProperty(data[prop], property);
-            }
-        }
-    };
-
-    window.ODataReadOracle = {
-        readFeed: readFeed,
-        readEntry: readEntry,
-        readLinksEntry: readLinksEntry,
-        readLinksFeed: readLinksFeed,
-        readJson: readJson,
-        readJsonAcrossServerPages: readJsonAcrossServerPages,
-        readMetadata: readMetadata,
-        readServiceDocument: readServiceDocument
-    };
-})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/ODataReadOracle.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/common/ODataReadOracle.svc b/datajs/tests/common/ODataReadOracle.svc
deleted file mode 100644
index 339666c..0000000
--- a/datajs/tests/common/ODataReadOracle.svc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
-    Service="DataJS.Tests.ODataReadOracle" %>
-
-//uncomment this line to debug JSON serialization.
-//#define DEBUG_SERIALIZATION
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using System.IO;
-    using System.Linq;
-    using System.Net;
-    using System.Runtime.Serialization;
-    using System.ServiceModel;
-    using System.ServiceModel.Activation;
-    using System.ServiceModel.Syndication;
-    using System.ServiceModel.Web;
-    using System.Xml;
-    using System.Xml.Linq;
-    using Microsoft.Spatial;
-    using Microsoft.OData.Core;
-    using System.Web.Script.Serialization;
-
-    /// <summary>
-    /// Oracle for the OData.read library function
-    /// </summary>
-    [ServiceContract]
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
-    public class ODataReadOracle
-    {
-        const string jsonlightMediaType = "application/json";
-
-        /// <summary>
-        /// Reads a URI that will return a metadata object
-        /// </summary>
-        /// <param name="url">The URL to send the request to</param>
-        /// <returns>Stream of metadata in json light format</returns>
-        [OperationContract]
-        [WebGet]
-        public Stream ReadMetadata(string url)
-        {
-            WebResponse response = WebRequest.Create(ResolveUri(url, UriKind.Absolute)).GetResponse();
-            Dictionary<string, object> jsonObject = CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream()));
-            return ReaderUtils.ConvertDictionarytoJsonlightStream(jsonObject);
-        }
-        
-        /// <summary>
-        /// Reads a URI that will get the Json response and return the stream
-        /// </summary>
-        /// <param name="url">URL of the entry</param>
-        /// <param name="user">The username for basic authentication</param>
-        /// <param name="password">The password for basic authentication</param>
-        /// <returns>Stream of the Json response expected to be returned by OData.read</returns>
-        [OperationContract]
-        [WebGet(ResponseFormat = WebMessageFormat.Json)]
-        public Stream ReadJson(string url, string mimeType, string user, string password)
-        {
-            if (mimeType == null)
-            {
-                mimeType = jsonlightMediaType + ";odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8";
-            }
-            
-            HttpWebRequest request = (HttpWebRequest)ReaderUtils.CreateRequest(ResolveUri(url, UriKind.Absolute), user, password);
-            request.Accept = mimeType;
-            WebResponse response = request.GetResponse();
-
-            return response.GetResponseStream();
-        }
-
-        /// <summary>
-        /// Resolves the given url string to a URI
-        /// </summary>
-        /// <param name="url">The given URL string</param>
-        /// <param name="urlKind">URI kind to resolve to</param>
-        /// <returns>The resolved URI</returns>
-        private static string ResolveUri(string url, UriKind uriKind)
-        {
-            Uri resolvedUri = new Uri(url, UriKind.RelativeOrAbsolute);
-            if (!resolvedUri.IsAbsoluteUri)
-            {
-                // If the given URI is relative, then base it on the Referer URI
-                Uri baseUri = new Uri(WebOperationContext.Current.IncomingRequest.Headers["Referer"]);
-                resolvedUri = new Uri(baseUri, resolvedUri);
-                if (uriKind == UriKind.Relative)
-                {
-                    resolvedUri = baseUri.MakeRelativeUri(resolvedUri);
-                }
-            }
-
-            return resolvedUri.ToString();
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/common/ObservableHttpClient.js
----------------------------------------------------------------------
diff --git a/datajs/tests/common/ObservableHttpClient.js b/datajs/tests/common/ObservableHttpClient.js
deleted file mode 100644
index 9be75f8..0000000
--- a/datajs/tests/common/ObservableHttpClient.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// ObservableHttpClient.js
-// This object extends OData's default httpClient by supporting request and response recording sessions, and firing a custom
-// JQuery event for each request/response.
-//
-// The events fired by this object are:
-//      request: Before a request is made
-//      success: Before the primary success handler is called
-//
-// To bind to an event, JQuery event attachers can be used on the object, e.g.
-//      $(observableHttpClient).bind("request", function (request) { ... });
-//
-// To begin a new recording session, use:
-//      var session = observableHttpClient.newSession();
-//
-// Requests and responses are then recorded in session.requests and session.responses. Session can be ended by session.end().
-// Multiple simultaneous sessions are supported.
-
-(function (window, undefined) {
-
-    var ObservableHttpClient = function (provider) {
-        this.provider = provider ? provider : window.odatajs.oData.net.defaultHttpClient;
-    };
-
-    ObservableHttpClient.prototype.newSession = function () {
-        return new Session(this);
-    };
-
-    ObservableHttpClient.prototype.request = function (request, success, error) {
-        var that = this;
-
-        $(this).triggerHandler("request", request);
-        return this.provider.request(request, function (response) {
-            $(that).triggerHandler("success", response);
-            success(response);
-        }, error);
-    };
-
-
-    var Session = function (client) {
-        var that = this;
-
-        this.client = client;
-        this.clear();
-
-        this.requestHandler = function (event, request) { that.requests.push(request); };
-        $(client).bind("request", this.requestHandler);
-
-        this.successHandler = function (event, response) { that.responses.push(response); };
-        $(client).bind("success", this.successHandler);
-    };
-
-    Session.prototype.clear = function () {
-        this.requests = [];
-        this.responses = [];
-    }
-
-    Session.prototype.end = function () {
-        $(this.client).unbind("request", this.requestHandler);
-        $(this.client).unbind("success", this.successHandler);
-    };
-
-    window.ObservableHttpClient = ObservableHttpClient;
-    window.Session = Session;
-
-})(this);
\ No newline at end of file


[15/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/djstest.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/djstest.js b/odatajs/tests-tmp/common/djstest.js
new file mode 100644
index 0000000..104c4cf
--- /dev/null
+++ b/odatajs/tests-tmp/common/djstest.js
@@ -0,0 +1,412 @@
+/*
+ * 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.
+ */
+
+
+// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
+// we define the @namespace djstest here instead of the a @module name djstest
+
+/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
+ * @namespace djstest
+ */
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    window.djstest = window.djstest || {};
+    init(window.djstest);
+} else {
+    //expose in commonjs style
+    module.exports = init();
+}
+
+
+function init (parent) {
+    djstest = parent || {};
+
+    /** Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.
+     * @class Job
+     * @constructor
+     * @returns {Object} Job object
+     */
+    djstest.Job = function () {
+        
+        var currentTask = -1;
+        var tasks = [];
+
+        var failedTasks = 0;
+
+        /** Adds a function to the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queue
+         * @param {Function} fn - Function to execute.
+         */
+        this.queue = function (fn) {
+            
+            tasks.push(fn);
+        };
+
+        /** Adds a function to the front of the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queueNext
+         * @param {Function} fn - Function to execute.
+         */
+        this.queueNext = function (fn) {
+        
+            if (currentTask < 0) {
+                tasks.unshift(fn);
+            } else {
+                tasks.splice(currentTask + 1, 0, fn);
+            }
+        };
+
+        /** Starts the execution of this job.
+         * @method djstest.Job#run
+         * @param {Function} done - Callback invoked when the job has finished executing all of its enqueued tasks.
+         */
+        this.run = function (done) {
+            /// This method does nothing if called on a unit of work that is already executing.
+            if (currentTask >= 0) {
+                return;
+            }
+
+            if (tasks.length === 0) {
+                done(true);
+                return;
+            }
+
+            /**
+             * @method djstest.Job~makeTaskDoneCallBack
+            */
+            function makeTaskDoneCallBack(failed) {
+                return function () {
+                    // Track the failed task and continue the execution of the job. 
+                    if (failed) {
+                        failedTasks++;
+                    }
+                    currentTask++;
+                    if (currentTask === tasks.length) {
+                        done(failedTasks === 0);
+                    } else {
+                        runNextTask();
+                    }
+                };
+            }
+
+            /** Executes the next function in the queue.
+             * @method djstest.Job~runNextTask
+            */
+            function runNextTask() {
+                defer(function () {
+                    try {
+                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
+                    } catch (e) {
+                        makeTaskDoneCallBack(true)();
+                    }
+                });
+            }
+
+            currentTask = 0;
+            runNextTask();
+        };
+    };
+
+    /** Defers the execution of an arbitrary function that takes no parameters.
+     * @memberof djstest
+     * @inner
+     * @param {Function} fn - Function to schedule for later execution.
+     */
+    function defer(fn) {
+        setTimeout(fn, 0);
+    }
+
+    /** Exposes date values for Date objects to facilitate debugging
+     * @memberof djstest
+     * @inner
+     * @param {Object} data - The object to operate on
+     */
+    function exposeDateValues(data) {
+     
+        if (typeof data === "object") {
+            if (data instanceof Date) {
+                data.__date__ = data.toUTCString();
+            }
+            else {
+                for (var prop in data) {
+                    exposeDateValues(data[prop]);
+                }
+            }
+        }
+
+        return data;
+    }
+
+    /** Determines the name of a function.
+     * @memberof djstest
+     * @inner
+     * @param {String} text - Function text.
+     * @returns {String} The name of the function from text if found; the original text otherwise.
+     */
+    function extractFunctionName(text) {
+
+        var index = text.indexOf("function ");
+        if (index < 0) {
+            return text;
+        }
+
+        var nameStart = index + "function ".length;
+        var parensIndex = text.indexOf("(", nameStart);
+        if (parensIndex < 0) {
+            return text;
+        }
+
+        var result = text.substr(nameStart, parensIndex - nameStart);
+        if (result.indexOf("test") === 0) {
+            result = result.substr("test".length);
+        }
+
+        return result;
+    }
+
+    /** Removes metadata annotations from the specified object.
+     * @memberof djstest
+     * @inner
+     * @param data - Object to remove metadata from; possibly null.
+     */
+    function removeMetadata(data) {
+
+        if (typeof data === "object" && data !== null) {
+            delete data.__metadata;
+            for (var prop in data) {
+                removeMetadata(data[prop]);
+            }
+        }
+    }
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
+
+        if (disable !== true) {
+            djstest.addTest(fn, name, arg, timeout);
+        }
+    };
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addTest = function (fn, name, arg, timeout) {
+        if (!name) {
+            name = extractFunctionName(fn.toString());
+        }
+
+        test(name, function () {
+            if (!timeout) {
+                timeout = 20000;
+            }
+
+            QUnit.config.testTimeout = timeout;
+            QUnit.stop();
+            fn.call(this, arg);
+        });
+    };
+
+    /** Asserts that a condition is true.
+     * @param {Boolean} test - Condition to test.
+     * @param {String} message - Text message for condition being tested.
+     */
+    djstest.assert = function (test, message) {
+        
+        QUnit.ok(test, message);
+    };
+
+    /** Asserts that the values of the expected and actualobjects are equal.
+     * @memberof djstest
+     * @inner
+     */
+    djstest.assertAreEqual = function (actual, expected, message) {
+        QUnit.equal(actual, expected, message);
+    };
+
+    /** Asserts that the actual and expected objects are the same.
+     */
+    djstest.assertAreEqualDeep = function (actual, expected, message) {
+        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
+    };
+
+    /** Asserts that the actual and expected objects are the same but removes the metadata bevore
+     */
+    djstest.assertWithoutMetadata = function (actual, expected, message) {
+        removeMetadata(actual);
+        removeMetadata(expected);
+        djstest.assertAreEqualDeep(actual, expected, message);
+    };
+
+    /** Calls each async action in asyncActions, passing each action a function which keeps a count and
+     * calls the passed done function when all async actions complete
+     * @param {Array} asyncActions -Array of asynchronous actions to be executed, 
+     * each taking a single parameter - the callback function to call when the action is done.</param>
+     * @param {Function} done - Function to be executed in the last async action to complete.
+     */
+    djstest.asyncDo = function (asyncActions, done) {
+
+        var count = 0;
+        var doneOne = function () {
+            count++;
+            if (count >= asyncActions.length) {
+                done();
+            }
+        };
+
+        if (asyncActions.length > 0) {
+            for ( var i = 0; i < asyncActions.length; i++) {
+                asyncActions[i](doneOne);
+            }
+        } else {
+            done();
+        }
+    };
+
+    /** Makes a deep copy of an object.
+     */
+    djstest.clone = function (object) {
+        if ( object === undefined ) {
+            return undefined;
+        } else if (object === null) {
+            return null;
+        } else if (typeof(object) !== 'object') {
+            return object;
+        } else {
+            var ret = {};
+            for(var key in object) {
+                if(object.hasOwnProperty(key)) {
+                    ret[key] = this.clone(object[key]);
+                }
+            }
+            return ret;
+        }
+        throw("Error cloning an object");
+    };
+
+    /** Destroys the cache and then completes the test
+     * @param cache - The cache to destroy
+     */
+    djstest.destroyCacheAndDone = function (cache) {
+     
+        cache.clear().then(function () {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
+            djstest.done();
+        });
+    };
+
+    /** Indicates that the currently running test has finished.
+     */
+    djstest.done = function () {
+      
+        QUnit.start();
+    };
+
+    /** Test passes if and only if an exception is thrown.
+     */
+    djstest.expectException = function (testFunction, message) {
+     
+        try {
+            testFunction();
+            djstest.fail("Expected exception but function succeeded: " + " " + message);
+        }
+        catch (e) {
+            // Swallow exception.
+            djstest.pass("Thrown exception expected");
+        }
+    };
+
+    /** Indicates the expected number of asserts, fails test if number is not met.
+     * @param {Number} asserts - Number of asserts expected in test.
+     */
+    djstest.assertsExpected = function (asserts) {
+        
+        expect(asserts);
+    };
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.fail = function (message) {
+
+        QUnit.ok(false, message);
+    };
+
+    /** Returns a function that when invoked will fail this test and be done with it.
+     * @param {String} message - Failure message.
+     * @param {Function} [cleanupCallback] - 
+     * @returns {Function} A new function.
+     */
+    djstest.failAndDoneCallback = function (message, cleanupCallback) {
+
+        return function (err) {
+            message = "" + message + (err) ? JSON.stringify(err) : "";
+            djstest.fail(message);
+            if (cleanupCallback) {
+                try {
+                    cleanupCallback();
+                } catch (e) {
+                    djstest.fail("error during cleanupCallback: " + JSON.stringify(e));
+                }
+            }
+
+            djstest.done();
+        };
+    };
+
+    /** Logs a test message.
+     * @param {String} message - Test message.
+     */
+    djstest.log = function (message) {
+
+        var context = { result: true, actual: true, expected: true, message: message };
+        QUnit.ok(true, message);
+        
+    };
+
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.pass = function (message) {
+        QUnit.ok(true, message);
+    };
+
+    /** Dumps the object as a string
+     * @param {Object} obj - Object to dump
+     */
+    djstest.toString = function (obj) {
+        return QUnit.jsDump.parse(obj);
+    };
+
+    /** Executes the function, pausing test execution until the callback is called
+     * @param {Function} fn - Function to execute; takes one parameter which is the callback
+     * This function is typically used in asynchronous setup/teardown methods</remarks>
+     */
+    djstest.wait = function (fn) {
+        QUnit.stop();
+        fn(function () {
+            QUnit.start();
+        });
+    };
+
+    return djstest;
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/logging.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/logging.js b/odatajs/tests-tmp/common/logging.js
new file mode 100644
index 0000000..9297527
--- /dev/null
+++ b/odatajs/tests-tmp/common/logging.js
@@ -0,0 +1,5 @@
+QUnit.log( function (context) {
+    if (window.console && window.console.log && context.message) {
+        window.console.log(context.result + ' :: ' + context.message  );
+    }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/mockHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/mockHttpClient.js b/odatajs/tests-tmp/common/mockHttpClient.js
new file mode 100644
index 0000000..2ec97e7
--- /dev/null
+++ b/odatajs/tests-tmp/common/mockHttpClient.js
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+ 
+//mockHttpClient.js
+//this object allows for associating a uri with a requestVerfier and mock responses that will be sent back to the client of the httpStack.  
+//It can be used to replace OData's httpClient for testing purposes.
+//
+//RequestVerifiers
+//
+//    A request verifier is a function associated to a particular URI that will be executed by the mockHttpClient when it receives a request with the matching URI.
+//    the callback receives as its only parameter the request object passed to the mockHttpClient.
+//
+//    To register a request verifier, simply do 
+//        
+//            MockHttpClient.addRequestVerifier("http://someUri", function(request) {
+//                djstest.assertAreEqual(request.requestUri,"http://someUri");
+//            }
+//
+//Responses
+//    Mock responses can be associated with a particular URI.  When the MockHttpClient receives a request with a URI mapped to a response, then it will, 
+//    depending on the response status code invoke either the success or the error callbacks. 
+//
+//    To register a response,
+//       
+//           MockHttpClient.addResponse("http://someUri", {status: 200, body:"some body"});
+//
+//Exceptions
+//    MockHttpClient will throw an exception if it receives a request to a URI that is not mapped to either a request verifier or a response.
+//
+
+
+if (typeof window !== 'undefined') {
+    //in browser call init() directly window as context
+    window.MockHttpClient = window.MockHttpClient || {};
+    init(window.MockHttpClient);
+} else {
+    //expose function init to be called with a custom context
+    module.exports = init();
+}
+
+
+function init(parent, undefined) {
+    httpClient = parent || {};
+
+    var responses = {};
+    var requestVerifiers = {};
+
+    httpClient.addRequestVerifier = function (uri, verifier) {
+        requestVerifiers[uri] = verifier;
+        return this;
+    };
+
+    httpClient.addResponse = function (uri, response) {
+        responses[uri] = response;
+        return this;
+    };
+
+    httpClient.async = false;
+
+    httpClient.clear = function () {
+        /** Clears all registered responses and verifiers.
+         * @returns this client
+         */
+        responses = {};
+        requestVerifiers = {};
+        this.async = false;
+        return this;
+    };
+
+    httpClient.request = function (request, success, error) {
+        var uri = request.requestUri;
+        var verifier = requestVerifiers[uri];
+        var response = responses[uri];
+
+        if (verifier === undefined) {
+            verifier = requestVerifiers["*"];
+        }
+
+        if (response === undefined) {
+            response = responses["*"];
+        }
+
+        if (!verifier && !response) {
+            throw { message: "neither verifier or response defined for uri: " + uri };
+        }
+
+        if (verifier) {
+            verifier(request);
+        }
+
+        if (response) {
+            response.requestUri = uri;
+            if (response.statusCode >= 200 && response.statusCode <= 299) {
+                if (this.async) {
+                    setTimeout(function () {
+                        success(response);
+                    });
+                } else {
+                    success(response);
+                }
+            } else {
+                if (this.async) {
+                    setTimeout(function () {
+                        error({ message: "failed test response", request: request, response: response });
+                    });
+                }
+                else {
+                    error({ message: "failed test response", request: request, response: response });
+                }
+            }
+        }
+    };
+
+    httpClient.setAsync = function (value) {
+        this.async = value;
+        return this;
+    };
+
+    return httpClient;
+}
+
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/node-test-setup.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/node-test-setup.js b/odatajs/tests-tmp/common/node-test-setup.js
new file mode 100644
index 0000000..c08c439
--- /dev/null
+++ b/odatajs/tests-tmp/common/node-test-setup.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+*/
+//Creates the global objects
+
+//tools
+
+var window = {};
+window.djstest = require("./djstest.js");
+window.mockHttpClient = require("./mockHttpClient.js");
+window.odatajs  = require('./../../src/index.js');
+
+global.window = window;
+console.log(global.window.odatajs.node+'asdfasdfasdfasdf');
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/observableHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/observableHttpClient.js b/odatajs/tests-tmp/common/observableHttpClient.js
new file mode 100644
index 0000000..9be75f8
--- /dev/null
+++ b/odatajs/tests-tmp/common/observableHttpClient.js
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+// ObservableHttpClient.js
+// This object extends OData's default httpClient by supporting request and response recording sessions, and firing a custom
+// JQuery event for each request/response.
+//
+// The events fired by this object are:
+//      request: Before a request is made
+//      success: Before the primary success handler is called
+//
+// To bind to an event, JQuery event attachers can be used on the object, e.g.
+//      $(observableHttpClient).bind("request", function (request) { ... });
+//
+// To begin a new recording session, use:
+//      var session = observableHttpClient.newSession();
+//
+// Requests and responses are then recorded in session.requests and session.responses. Session can be ended by session.end().
+// Multiple simultaneous sessions are supported.
+
+(function (window, undefined) {
+
+    var ObservableHttpClient = function (provider) {
+        this.provider = provider ? provider : window.odatajs.oData.net.defaultHttpClient;
+    };
+
+    ObservableHttpClient.prototype.newSession = function () {
+        return new Session(this);
+    };
+
+    ObservableHttpClient.prototype.request = function (request, success, error) {
+        var that = this;
+
+        $(this).triggerHandler("request", request);
+        return this.provider.request(request, function (response) {
+            $(that).triggerHandler("success", response);
+            success(response);
+        }, error);
+    };
+
+
+    var Session = function (client) {
+        var that = this;
+
+        this.client = client;
+        this.clear();
+
+        this.requestHandler = function (event, request) { that.requests.push(request); };
+        $(client).bind("request", this.requestHandler);
+
+        this.successHandler = function (event, response) { that.responses.push(response); };
+        $(client).bind("success", this.successHandler);
+    };
+
+    Session.prototype.clear = function () {
+        this.requests = [];
+        this.responses = [];
+    }
+
+    Session.prototype.end = function () {
+        $(this.client).unbind("request", this.requestHandler);
+        $(this.client).unbind("success", this.successHandler);
+    };
+
+    window.ObservableHttpClient = ObservableHttpClient;
+    window.Session = Session;
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/odataCacheVerifier.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/odataCacheVerifier.js b/odatajs/tests-tmp/common/odataCacheVerifier.js
new file mode 100644
index 0000000..54e4659
--- /dev/null
+++ b/odatajs/tests-tmp/common/odataCacheVerifier.js
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+// CacheVerifier.js
+// This object verifies the operation of the cache.
+// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
+
+(function (window, undefined) {
+
+    var CacheVerifier = function (baseUri, pageSize, total, cacheSize) {
+        /** Creates a new CacheVerifier
+         * @param {String} baseUri - The base URI of the collection
+         * @param {Integer} pageSize - The page size used in the cache
+         * @param {Integer} total - The total number of items in the collection
+         * @param {Integer} cacheSize - Cache size in bytes
+         */
+        this.baseUri = baseUri;
+        this.pageSize = pageSize;
+        this.total = total;
+        this.cacheSize = (cacheSize !== undefined) ? cacheSize : 1024 * 1024;
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.cachedPages = [];
+        this.exactPageCount = (total % pageSize === 0);
+        this.maxPage = Math.floor(total / pageSize);
+        this.overflowed = this.cacheSize === 0;
+    };
+
+    CacheVerifier.mechanisms = {
+        memory: "memory",
+        indexeddb: "indexeddb",
+        dom: "dom",
+        best: "best"
+    };
+
+    CacheVerifier.isMechanismAvailable = function (mechanism) {
+        /** Determines if the specified local storage mechanism is available
+         * @param mechanism - The name of the mechanism
+         * @returns Whether the mechanism is available
+         */
+        switch (mechanism) {
+            case CacheVerifier.mechanisms.indexeddb:
+                if (window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.indexedDB) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheVerifier.mechanisms.dom:
+                if (window.localStorage) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheVerifier.mechanisms.memory:
+            case CacheVerifier.mechanisms.best:
+            case undefined:
+                return true;
+            default:
+                return false;
+        }
+    };
+
+    CacheVerifier.prototype.clear = function () {
+        /** Clears the cache in the oracle
+        */
+        this.cachedPages = [];
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.overflowed = this.cacheSize === 0;
+    };
+
+    CacheVerifier.prototype.verifyRequests = function (requests, responses, index, count, description, backwards, isPrefetch) {
+        /** Verifies the HTTP requests for a single data request, and updates the oracle with cached pages
+         * @param {Array} requests - The sequence of request objects (from OData.defaultHttpClient)
+         * @param {Array} responses - The sequence of response objects (from OData.defaultHttpClient)
+         * @param {Integer} index - The starting index of the read
+         * @param {Integer} count - The count of items in the read
+         * @param {String} description - The description of the requests being verified
+         * @param {Boolean} backwards - Whether or not filterBack is being verified
+         * @param {Boolean} isPrefetch - Whether the requests being verified come from the prefetcher
+         */
+        var that = this;
+
+        index = (index < 0 ? 0 : index);
+        var pageIndex = function (index) {
+            /** Returns the page index that the given item index belongs to
+             * @param {Integer} index - The item index
+             * @returns The page index
+             */
+            return Math.floor(index / that.pageSize);
+        };
+
+        var estimateSize = function (obj) {
+            /** Estimates the size of an object in bytes.
+             * @param {Object} obj - Object to determine the size of.
+             * @returns {Number} Estimated size of the object in bytes.
+             */
+
+            var size = 0;
+            var type = typeof obj;
+
+            if (type === "object" && obj) {
+                for (var name in obj) {
+                    size += name.length * 2 + estimateSize(obj[name]);
+                }
+            } else if (type === "string") {
+                size = obj.length * 2;
+            } else {
+                size = 8;
+            }
+            return size;
+        };
+
+        var expectedUris = [];
+        var responseIndex = 0;
+        if (count >= 0) {
+            var minPage = pageIndex(index);
+            var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(this.total));
+
+            // In the case that the index is outside the range of the collection the minPage will be greater than the maxPage  
+            maxPage = Math.max(minPage, maxPage);
+
+            if (!(isPrefetch && !this.exactPageCount && minPage > this.maxPage)) {
+                for (var page = minPage; page <= maxPage && this.actualCount <= this.total && !(isPrefetch && this.overflowed); page++) {
+                    if (!this.cachedPages[page]) {
+
+                        expectedUris.push(that.baseUri + "?$skip=" + page * this.pageSize + "&$top=" + (this.pageSize));
+
+                        var actualPageSize = 0;
+                        var actualPageCount = 0;
+                        if (responses[responseIndex] && responses[responseIndex].data) {
+                            actualPageSize += estimateSize(responses[responseIndex].data);
+                            actualPageCount += responses[responseIndex].data.value.length;
+                            // Handle server paging skipToken requests
+                            while (responses[responseIndex].data["@odata.nextLink"]) {
+                                var nextLink = responses[responseIndex].data["@odata.nextLink"];
+                                if (nextLink) {
+                                    var index = that.baseUri.indexOf(".svc/", 0);
+                                    if (index != -1) {
+                                        nextLink = that.baseUri.substring(0, index + 5) + nextLink;
+                                    }
+                                }
+
+                                expectedUris.push(nextLink);
+                                responseIndex++;
+                                actualPageSize += estimateSize(responses[responseIndex].data);
+                                actualPageCount += responses[responseIndex].data.value.length;
+                            }
+
+                            actualPageSize += 24; // 24 byte overhead for the pages (i)ndex, and (c)ount fields
+                        }
+
+                        responseIndex++;
+
+                        this.overflowed = this.cacheSize >= 0 && this.actualSize + actualPageSize > this.cacheSize;
+                        if (!this.overflowed) {
+                            this.cachedPages[page] = true;
+                            this.actualSize += actualPageSize;
+                            this.actualCount += actualPageCount;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (backwards) {
+            expectedUris.reverse();
+        }
+
+        var actualUris = $.map(requests, function (r) { return r.requestUri; });
+        djstest.assertAreEqualDeep(actualUris, expectedUris, description);
+    };
+
+    CacheVerifier.getExpectedFilterResults = function (data, filterIndex, filterCount, predicate, backwards) {
+        /** Verifies the cache filter returns the correct data
+         * @param {Array} collection - Array of items in the collection
+         * @param {Integer} filterIndex - The index value
+         * @param {Integer} filterCount - The count value
+         * @param {Function} predicate - Predicate to be applied in filter, takes an item
+         * @param {Boolean} backwards - Whether or not filterBackwards is being verified
+         */
+        if (!data || !data.value) {
+            return data;
+        }
+
+        var value = [];
+        if (filterCount !== 0) {
+            // Convert [item0, item1, ...] into [{ index: 0, item: item0 }, { index: 1, item: item1 }, ...]
+            var indexedCollection = $.map(data.value, function (item, index) {
+                return { index: index, item: item };
+            });
+
+            var grepPredicate = function (element, index) {
+                return predicate(element.item);
+            };
+
+            var index = filterIndex < 0 ? 0 : filterIndex;
+            var count = filterCount < 0 ? indexedCollection.length : filterCount;
+
+            value = backwards ?
+            // Slice up to 'index', filter, then slice 'count' number of items from the end
+                $.grep(indexedCollection.slice(0, index + 1), grepPredicate).slice(-count) :
+            // Slice from 'index' to the end, filter, then slice 'count' number of items from the beginning
+                $.grep(indexedCollection.slice(index), grepPredicate).slice(0, count);
+        }
+
+        var expectedResults = {};
+        for (var property in data) {
+            if (property == "value") {
+                expectedResults[property] = value;
+            } else {
+                expectedResults[property] = data[property];
+            }
+        }
+
+        return expectedResults;
+    };
+
+    window.CacheVerifier = CacheVerifier;
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/odataVerifyReader.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/odataVerifyReader.js b/odatajs/tests-tmp/common/odataVerifyReader.js
new file mode 100644
index 0000000..14bf54e
--- /dev/null
+++ b/odatajs/tests-tmp/common/odataVerifyReader.js
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+ 
+
+// Client for the odata.read oracle service
+
+(function (window, undefined) {
+    var jsonMime = "application/json";
+    var universalMime = "*/*";
+
+    function readFeed(url, success, mimeType, recognizeDates) {
+        /** Calls the ReadFeed endpoint with the specified URL
+         * @param {String} url - The URL to read the feed from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) {
+            success(data);
+        });
+    }
+
+    function readEntry(url, success, mimeType, recognizeDates) {
+        /** Calls the ReadEntry endpoint with the specified URL
+         * @param {String} url - The URL to read the entry from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, success);
+    }
+
+    function readLinksEntry(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            success
+        );
+    }
+
+    function readLinksFeed(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            function (data) {
+                success(data);
+            }
+        );
+    }
+
+    function readMetadata(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success);
+    }
+
+    function readServiceDocument (url, success, mimeType) {
+        /** Calls the ReadServiceDocument endpoint with the specified URL
+         * @param {String} url - The URL to the service
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME type being tested
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success);
+    }
+
+    function readJson(url, success) {
+        $.ajax({
+            url: url,
+            accepts: null,
+            dataType: "json",
+            beforeSend: function (xhr) {
+                xhr.setRequestHeader("Accept", jsonMime);
+                xhr.setRequestHeader("OData-MaxVersion", "4.0");
+            },
+            success: function (data) {
+                success(data);
+            }
+        });
+    }
+
+    function readJsonAcrossServerPages(url, success) {
+        var data = {};
+        var readPage = function (url) {
+            readJson(url, function (feedData) {
+                var nextLink = feedData["@odata.nextLink"];
+                if (nextLink) {
+                    var index = url.indexOf(".svc/", 0);
+                    if (index != -1) {
+                        nextLink = url.substring(0, index + 5) + nextLink;
+                    }
+                }
+
+                if (data.value && feedData.value) {
+                    data.value = data.value.concat(feedData.value);
+                }
+                else {
+                    for (var property in feedData) {
+                        if (property != "@odata.nextLink") {
+                            data[property] = feedData[property];
+                        }
+                    }
+                }
+
+                if (nextLink) {
+                    readPage(nextLink);
+                }
+                else {
+                    success(data);
+                }
+            });
+        };
+
+        readPage(url);
+    }
+
+    function getReadMethod(mimeType) {
+        switch (mimeType) {
+            case jsonMime:
+            case universalMime:
+                /* falls through */
+            default:
+                return "ReadJson";
+        }
+        return undefined;
+    }
+
+    function oracleRequest(method, endpoint, data, mimeType, recognizeDates, success) {
+        /** Requests a JSON object from the oracle service, removing WCF-specific artifacts
+         * @param {String} method - The HTTP method (GET or POST)
+         * @param {String} endpoint - The oracle endpoint
+         * @param {Object} data - The data to send with the request
+         * @param {Function} reviver - The reviver function to run on each deserialized object
+         * @param {Function} success - Success callback
+         */
+        var url = "./common/ODataVerifiyReader.svc/" + endpoint;
+        if (mimeType) {
+            data.mimeType = mimeType;
+        }
+
+        $.ajax({
+            type: method,
+            url: url,
+            data: data,
+            dataType: "text",
+            success: function (data) {
+                var json = JSON.parse(data);
+                success(json);
+            }
+        });
+    }
+
+    function removeProperty(data, property) {
+        /** Removes the specified property recursively from the given object
+         * @param {Object} data - The object to operate on
+         * @param {String} property - The name of the property to remove
+         */
+        if (typeof data === "object" && data !== null) {
+            if (data[property]) {
+                delete data[property];
+            }
+
+            for (var prop in data) {
+                removeProperty(data[prop], property);
+            }
+        }
+    }
+
+    window.ODataVerifyReader = {
+        readFeed: readFeed,
+        readEntry: readEntry,
+        readLinksEntry: readLinksEntry,
+        readLinksFeed: readLinksFeed,
+        readJson: readJson,
+        readJsonAcrossServerPages: readJsonAcrossServerPages,
+        readMetadata: readMetadata,
+        readServiceDocument: readServiceDocument
+    };
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/done.txt
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/done.txt b/odatajs/tests-tmp/done.txt
new file mode 100644
index 0000000..85ca39b
--- /dev/null
+++ b/odatajs/tests-tmp/done.txt
@@ -0,0 +1,29 @@
+This tests-tmp folder will repleace the tests folder.
+The plan is to 
+- select test case per testcase,
+- verify it, and 
+- copy it to the tmp-tests
+- once each tests is checkt and copied the folder tests will be deleted and replaced by tmp-tests
+
+DONE
+
+TestSynchronizerClient.js 
+  -> removed
+  -> Moved from custom c# logging service to jenkins
+
+ODataReadOracle.js 
+  -> removed
+  -> TODO check dependencies
+
+rx.js 
+  -> removed
+  -> TODO check dependencies
+
+odata-json-test.js 
+  -> copied and splittet 
+
+  
+ODataReadOracle.js -> odataVerifyReader.js
+ODataReadOracle.svc -> odataVerifyReader.svc
+
+ODataReadOracle -> odataVerifyReader

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc b/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
new file mode 100644
index 0000000..e059314
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
@@ -0,0 +1,124 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.BasicAuthDataService" %>
+/*
+ * 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.
+ */
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Web;
+    using System.Text;
+    using System.Web;
+
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class BasicAuthDataService : DataService<BasicAuthDataSource>
+    {
+        const string Username = "djsUser";
+        const string Password = "djsPassword";
+        
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+        }
+
+        public BasicAuthDataService()
+            : base()
+        {
+            this.ProcessingPipeline.ProcessingRequest += OnRequest;
+        }
+
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+
+        private static void UnauthorizedRequest(DataServiceOperationContext context)
+        {
+            context.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"DataJS.Tests\"";
+            throw new DataServiceException(401, "401 Unauthorized");
+        }
+
+        private void OnRequest(object sender, DataServiceProcessingPipelineEventArgs e)
+        {
+            string authHeader = e.OperationContext.RequestHeaders["Authorization"];
+            
+            // Validate the Authorization header
+            if (authHeader == null || !authHeader.StartsWith("Basic"))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+
+            // Decode the username and password from the header
+            string base64Credentials = authHeader.Substring(6);
+            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(':');
+            if (credentials.Length != 2 || !(credentials[0].Equals(Username) && credentials[1].Equals(Password)))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+        }
+    }
+
+    public class BasicAuthDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Customer> Customers
+        {
+            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+            foreach (int i in Enumerable.Range(1, 16))
+            {
+                customers.Add(new Customer()
+                {
+                    ID = i,
+                    Name = "Customer " + i
+                });
+            }
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Customer
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/CustomAnnotations.xml b/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
new file mode 100644
index 0000000..ebf4e26
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
@@ -0,0 +1,121 @@
+<!--/*
+ * 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.
+*/
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
+  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
+    <Schema xmlns="http://schemas.microsoft.com/ado/2007/05/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:mcns="http://MyCustomNamespace.com"
+             Namespace="DataJS.Tests">
+      <EntityType Name="MappedEntry" mcns:MyCustomAnnotation="My custom attribute.">
+        <Key mcns:MyCustomAnnotation="//">
+          <PropertyRef Name="ID" mcns:MyCustomAnnotation="  "/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author" m:FC_KeepInContent_5="false" m:FC_SourcePath_5="Contributor/Name" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorName" m:FC_KeepInContent_4="false" m:FC_SourcePath_4="Contributor/Email" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorEmail" m:FC_KeepInContent_3="false" m:FC_SourcePath_3="Uri" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationAuthorUri" m:FC_KeepInContent_2="false" m:FC_SourcePath_2="Name" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorName" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Email" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorEmail" m:FC_KeepInContent="false" m:FC_SourcePath="Contributor/Uri" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationContributorUri"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished"/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="false" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author" mcns:MyCustomAnnotation="">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=""/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor"/>
+      </ComplexType>
+      <ComplexType Name="Contributor">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=" "/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="true"/>
+      </ComplexType>
+      <ComplexType Name="Location">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single" mcns:MyCustomAnnotation="27"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="ReplicatedEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author2" m:FC_KeepInContent_5="true" m:FC_SourcePath_5="Contributor/Uri" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorUri" m:FC_KeepInContent_4="true" m:FC_SourcePath_4="Contributor/Name" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorName" m:FC_KeepInContent_3="true" m:FC_SourcePath_3="Contributor/Email" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationContributorEmail" m:FC_KeepInContent_2="true" m:FC_SourcePath_2="Uri" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorUri" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Name" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorName" m:FC_KeepInContent="true" m:FC_SourcePath="Email" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationAuthorEmail" mcns:MyCustomAnnotation="b>100/b>"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished" mcns:MyCustomAnnotation=" . "/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary" mcns:MyCustomAnnotation="/Property"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location2" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="true" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor2"/>
+      </ComplexType>
+      <ComplexType Name="Contributor2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+      </ComplexType>
+      <ComplexType Name="Location2">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="DerivedEntry" m:FC_KeepInContent="false" m:FC_SourcePath="MappedInDerivedField" m:FC_TargetPath="mappedField/@mappedInDerived" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy" BaseType="DataJS.Tests.BaseEntry">
+        <Property Name="UnmappedConcreteField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedConcreteField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField/@mappedConcrete" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityType Name="BaseEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedInDerivedField" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="false"/>
+        <Property Name="MappedField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityContainer Name="EpmDataSource" m:IsDefaultEntityContainer="true" mcns:MyCustomAnnotation="0">
+        <EntitySet Name="MappedEntries" EntityType="DataJS.Tests.MappedEntry"/>
+        <EntitySet Name="ReplicatedEntries" EntityType="DataJS.Tests.ReplicatedEntry"/>
+        <EntitySet Name="HierarchicalEntries" EntityType="DataJS.Tests.BaseEntry"/>
+        <FunctionImport Name="ResetData" m:HttpMethod="POST" mcns:MyCustomAnnotation="null"/>
+      </EntityContainer>
+      <mcns:EmptyElement></mcns:EmptyElement>
+      <mcns:ParentCustomElement mcns:MyCustomAnnotation="annotation" mcns:MySecondCustomAnnotation="annotation 2">
+        <mcns:CustomChildElement1>Custom metadata 1.</mcns:CustomChildElement1>
+        <mcns:CustomChildElement2>Custom metadata 2.</mcns:CustomChildElement2>
+      </mcns:ParentCustomElement>
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/CustomDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/CustomDataService.svc b/odatajs/tests-tmp/endpoints/CustomDataService.svc
new file mode 100644
index 0000000..67fcfd0
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/CustomDataService.svc
@@ -0,0 +1,85 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory"
+    Service="DataJS.Tests.CustomDataService" %>
+
+
+using System.Collections;
+using System.IO;
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// Custom data service that does not use OData
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class CustomDataService
+    {
+        static readonly Item[] data = Enumerable.Range(0, 16).Select(i => new Item
+        {
+            ID = i,
+            Name = "Item " + i
+        }).ToArray();
+
+        // This uses the same URI template as OData so that the CacheOracle can be reused
+        [OperationContract]
+        [WebGet(UriTemplate = "ReadRange?$skip={skip}&$top={top}")]
+        public Stream ReadRange(int skip, int top)
+        {
+            IEnumerable selectData = data.Skip(skip).Take(top);
+            Dictionary<string, object> result = new Dictionary<string, object>();
+            List<Dictionary<string, string>> value = new List<Dictionary<string, string>>(); 
+            foreach (Item d in selectData)
+            {
+                Dictionary<string, string> item = new Dictionary<string, string>();
+                item.Add("ID", d.ID.ToString());
+                item.Add("Name", d.Name);
+                value.Add(item);
+            }
+            
+            result.Add("value", value);
+            return ReaderUtils.ConvertDictionarytoJsonlightStream(result);
+        }
+
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public int Count()
+        {
+            return data.Count();
+        }
+    }
+
+    public class Item
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/EpmDataService.svc b/odatajs/tests-tmp/endpoints/EpmDataService.svc
new file mode 100644
index 0000000..316c9ae
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/EpmDataService.svc
@@ -0,0 +1,336 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.EpmDataService" %>
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// A data service that uses EPM
+    /// </summary>
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class EpmDataService : DataService<EpmDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+
+        }
+        
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+    }
+
+    public class EpmDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<MappedEntry> MappedEntries
+        {
+            get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<ReplicatedEntry> ReplicatedEntries
+        {
+            get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<BaseEntry> HierarchicalEntries
+        {
+            get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            MappedEntry[] mappedEntries = new MappedEntry[]
+            {
+                new MappedEntry
+                {
+                    ID = 0,
+                    UnmappedField = "Unmapped0",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail0",
+                        Name = "AuthorName0",
+                        Uri = "http://www.example.com/AuthorUri",
+                        Contributor = new Contributor
+                        {
+                            Email = "ContributorEmail0",
+                            Name = "ContributorName0",
+                            Uri = "http://www.example.com/ContributorUri",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights0",
+                    Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
+                    Title = "Title<b>0</b>",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement0",
+                    CustomAttribute = "CustomAttribute0",
+                    NestedElement1 = "NestedElement1_0",
+                    NestedElement2 = "NestedElement2_0",
+                    CommonAttribute1 = "CommonAttribute1_0",
+                    CommonAttribute2 = "CommonAttribute2_0",
+                    Location = new Location
+                    {
+                        Lat = 3.14f,
+                        Long = 2.72f
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 1,
+                    UnmappedField = null,
+                    Author = new Author
+                    {
+                        Email = null,
+                        Name = string.Empty,
+                        Uri = "http://www.example.com/AuthorUri1",
+                        Contributor = new Contributor
+                        {
+                            Email = null,
+                            Name = string.Empty,
+                            Uri = "http://www.example.com/ContributorUri1",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = null,
+                    Summary = "",
+                    Title = "Title<i>1</i>",
+                    Updated = "2111-01-01T00:00:00-08:00",
+                    CustomElement = null,
+                    NestedElement1 = string.Empty,
+                    NestedElement2 = "NestedElement2_1",
+                    CustomAttribute = null,
+                    CommonAttribute1 = string.Empty,
+                    CommonAttribute2 = "CommonAttribute2_1",
+                    Location = new Location
+                    {
+                        Lat = float.MaxValue,
+                        Long = float.MinValue
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 2,
+                    UnmappedField = "Unmapped2",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail2",
+                        Name = "AuthorName2",
+                        Uri = "http://www.example.com/AuthorUri2",
+                        Contributor = null
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights2",
+                    Summary = "Summary2",
+                    Title = "Title2",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement2",
+                    CustomAttribute = "CustomAttribute2",
+                    NestedElement1 = "NestedElement1_2",
+                    NestedElement2 = "NestedElement2_2",
+                    CommonAttribute1 = "CommonAttribute1_2",
+                    CommonAttribute2 = "CommonAttribute2_2",
+                    Location = null
+                },
+            };
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
+
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
+            {
+                ID = item.ID,
+                UnmappedField = item.UnmappedField,
+                Author = item.Author == null ? null : new Author2
+                {
+                    Email = item.Author.Email,
+                    Name = item.Author.Name,
+                    Uri = item.Author.Uri,
+                    Contributor = item.Author.Contributor == null ? null : new Contributor2
+                    {
+                        Name = item.Author.Contributor.Name,
+                        Email = item.Author.Contributor.Email,
+                        Uri = item.Author.Contributor.Uri
+                    },
+                },
+                Published = item.Published,
+                Rights = item.Rights,
+                Summary = item.Summary,
+                Title = item.Title,
+                Updated = item.Updated,
+                CustomElement = item.CustomElement,
+                CustomAttribute = item.CustomAttribute,
+                NestedElement1 = item.NestedElement1,
+                NestedElement2 = item.NestedElement2,
+                CommonAttribute1 = item.CommonAttribute1,
+                CommonAttribute2 = item.CommonAttribute2,
+                Location = item.Location == null ? null : new Location2
+                {
+                    Lat = item.Location.Lat,
+                    Long = item.Location.Long
+                }
+            }));
+
+            BaseEntry[] hierarchicalEntries = new BaseEntry[]
+            {
+                new BaseEntry
+                {
+                    ID = 0,
+                    MappedField = "MappedField0",
+                    MappedInDerivedField = "MappedInDerivedField0",
+                    UnmappedField = "UnmappedField0"
+                },
+                new DerivedEntry
+                {
+                    ID = 1,
+                    MappedField = "MappedField1",
+                    MappedInDerivedField = "MappedInDerivedField1",
+                    UnmappedField = "UnmappedField1",
+                    MappedConcreteField = "MappedConcreteField1",
+                    UnmappedConcreteField = "UnmappedConcreteField1"
+                },
+            };
+            Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Author
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor Contributor { get; set; }
+    }
+
+    public class Contributor
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+    
+    public class Location
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+
+    public class Author2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor2 Contributor { get; set; }
+    }
+
+    public class Contributor2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+
+    public class Location2
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+    
+    public class MappedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location Location { get; set; }
+    }
+
+    public class ReplicatedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author2 Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location2 Location { get; set; }
+    }
+    
+    public class BaseEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public string MappedInDerivedField { get; set; }
+        public string MappedField { get; set; }
+    }
+    
+    public class DerivedEntry : BaseEntry
+    {
+        public string UnmappedConcreteField { get; set; }
+        public string MappedConcreteField { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/ErrorDataService.svc b/odatajs/tests-tmp/endpoints/ErrorDataService.svc
new file mode 100644
index 0000000..052a2df
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/ErrorDataService.svc
@@ -0,0 +1,78 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.ErrorDataService" %>
+
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+
+    /// <summary>
+    /// A data service that contains in-stream errors
+    /// </summary>
+    public class ErrorDataService : DataService<ErrorDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+        }
+    }
+
+    public class ErrorDataSource
+    {
+        public IQueryable<ErrorType> Entities
+        {
+            get
+            {
+                ErrorType[] entities = new ErrorType[]
+                {
+                    new ErrorType(() => 0),
+                    new ErrorType(() => { throw new ApplicationException(); })
+                };
+
+                return entities.AsQueryable();
+            }
+        }
+    }
+    
+    public class ErrorType
+    {
+        Func<int> generateID;
+        
+        public ErrorType(Func<int> generateID)
+        {
+            this.generateID = generateID;
+        }
+        
+        public int ID
+        {
+            get { return this.generateID(); }
+        }
+    }
+}
\ No newline at end of file


[29/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-metadata-awareness-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-metadata-awareness-functional-tests.js b/datajs/tests/odata-metadata-awareness-functional-tests.js
deleted file mode 100644
index a5d2887..0000000
--- a/datajs/tests/odata-metadata-awareness-functional-tests.js
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var service = "./endpoints/EpmDataService.svc";
-    var metadataUri = service + "/$metadata";
-
-    var httpStatusCode = {
-        ok: 200,
-        created: 201,
-        noContent: 204
-    };
-
-    var acceptHeaders = { Accept: "application/json" };
-    var mimeHeaders = { "Content-Type": "application/json", Accept: "application/json" };
-    var keepInContentVariations = [true, false];
-    var feedUris = { "true": service + "/ReplicatedEntries", "false": service + "/MappedEntries" };
-    var typeNames = { "true": "DataJS.Tests.ReplicatedEntry", "false": "DataJS.Tests.MappedEntry" };
-    var selectProperties = ["Published", "Author", "CustomElement", "NestedElement1", "Published,Author,CustomElement,NestedElement1"];
-
-    var newEntry = {
-        UnmappedField: "Unmapped100",
-        Author: {
-            Email: "AuthorEmail100",
-            Name: "AuthorName100",
-            Uri: "http://www.example.com/AuthorUri100",
-            Contributor: {
-                Email: "ContributorEmail100",
-                Name: "ContributorName100",
-                Uri: "http://www.example.com/ContributorUri1000"
-            }
-        },
-        Published: "2100-01-01T00:00:00-08:00",
-        Rights: "Rights100",
-        Summary: "<xmlElement xmlns=\"http://www.example.com/dummy\" attr=\"value100\">Summary100</xmlElement>",
-        Title: "Title<b>100</b>",
-        Updated: "2100-01-01T00:00:00-08:00",
-        CustomElement: "CustomElement100",
-        CustomAttribute: "CustomAttribute100",
-        NestedElement1: "NestedElement1_100",
-        NestedElement2: "NestedElement2_100",
-        CommonAttribute1: "CommonAttribute1_100",
-        CommonAttribute2: "CommonAttribute2_100",
-        Location: {
-            Lat: 1.23,
-            Long: 4.56
-        }
-    };
-
-    var newSpecialValuesEntry = $.extend(true, {}, newEntry, {
-        Author: {
-            Email: null,
-            Name: "",
-            Uri: " ",
-            Contributor: {
-                Email: null,
-                Name: "",
-                Uri: " "
-            }
-        },
-        Rights: null,
-        Summary: "",
-        Title: " ",
-        CustomElement: null,
-        NestedElement1: "",
-        NestedElement2: " ",
-        CustomAttribute: null,
-        CommonAttribute1: "",
-        CommonAttribute2: " "
-    });
-
-    var nullComplexTypeEntry = $.extend(true, {}, newEntry, {
-        Author: { Contributor: null },
-        Location: null
-    });
-
-    var testEntries = [
-        { data: newEntry, description: "entry" },
-        { data: newSpecialValuesEntry, description: "entry containing null and empty string" },
-        { data: nullComplexTypeEntry, description: "entry containing null complex type value" }
-    ];
-
-    var serviceMetadata;
-    var getMetadata = function (callback) {
-        /** Common function for tests to get and cache metadata, to reduce network calls made by tests
-        */
-        if (!serviceMetadata) {
-            odatajs.oData.read(metadataUri, function (metadata) {
-                serviceMetadata = metadata;
-                callback(metadata);
-            }, unexpectedErrorHandler, OData.metadataHandler);
-        }
-        else {
-            callback(serviceMetadata);
-        }
-    }
-
-    module("Functional", {
-        setup: function () {
-            djstest.wait(function (done) {
-                $.post(service + "/ResetData", done);
-            });
-            OData.defaultMetadata = [];
-            OData.jsonHandler.recognizeDates = false;
-        }
-    });
-
-    $.each(selectProperties, function (_, selectProperty) {
-        djstest.addTest(function getSelectPropertiesOnEntry(propertyToSelect) {
-            var entryUri = feedUris["true"] + "(0)?$select=" + propertyToSelect;
-            djstest.assertsExpected(2);
-            getMetadata(function (metadata) {
-                OData.defaultMetadata.push(metadata);
-                odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
-                    djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
-                    ODataReadOracle.readJson(entryUri, function (expectedData) {
-                        djstest.assertWithoutMetadata(data, expectedData, "Verify data");
-                        djstest.done();
-                    })
-                }, unexpectedErrorHandler);
-            }, unexpectedErrorHandler, OData.metadataHandler);
-        }, "GET with mapped properties selecting " + selectProperty + " with keepInContent = true", selectProperty);
-    });
-
-    $.each(keepInContentVariations, function (_, keepInContent) {
-        var feedUri = feedUris[keepInContent];
-
-        $.each(testEntries, function (entryIndex, testEntry) {
-            params = {
-                feedUri: feedUri,
-                testEntry: $.extend(true, {}, testEntry, {
-                    data: {
-                        "__metadata": { type: typeNames[keepInContent] }
-                    }
-                })
-            };
-
-            djstest.addTest(function getMappedEntry(params) {
-                var entryUri = params.feedUri + "(" + entryIndex + ")";
-                djstest.assertsExpected(2);
-                getMetadata(function (metadata) {
-                    OData.defaultMetadata.push(metadata);
-                    odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
-                        djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
-                        ODataReadOracle.readJson(entryUri, function (expectedData) {
-                            djstest.assertWithoutMetadata(data, expectedData, "Verify data");
-                            djstest.done();
-                        })
-                    }, unexpectedErrorHandler);
-                }, unexpectedErrorHandler, OData.metadataHandler);
-            }, "GET " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
-
-            djstest.addTest(function postMappedEntry(params) {
-                var postEntry = $.extend(true, {}, params.testEntry.data, { ID: 100 });
-                djstest.assertsExpected(2);
-                getMetadata(function (metadata) {
-                    odatajs.oData.request({ requestUri: params.feedUri, method: "POST", headers: djstest.clone(mimeHeaders), data: postEntry }, function (data, response) {
-                        djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code");
-                        ODataReadOracle.readJson(feedUri + "(" + postEntry.ID + ")", function (actualData) {
-                            djstest.assertWithoutMetadata(actualData, postEntry, "Verify new entry data against server");
-                            djstest.done();
-                        })
-                    }, unexpectedErrorHandler, undefined, undefined, metadata);
-                }, unexpectedErrorHandler, OData.metadataHandler);
-            }, "POST " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
-
-            djstest.addTest(function putMappedEntry(params) {
-                var entryUri = params.feedUri + "(0)";
-                djstest.assertsExpected(2);
-                getMetadata(function (metadata) {
-                    OData.defaultMetadata.push(metadata);
-                    odatajs.oData.request({ requestUri: entryUri, method: "PUT", headers: djstest.clone(mimeHeaders), data: params.testEntry.data }, function (data, response) {
-                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
-                        ODataReadOracle.readJson(entryUri, function (actualData) {
-                            djstest.assertWithoutMetadata(actualData, $.extend({ ID: 0 }, params.testEntry.data), "Verify updated entry data against server");
-                            djstest.done();
-                        })
-                    }, unexpectedErrorHandler);
-                }, unexpectedErrorHandler, OData.metadataHandler);
-            }, "PUT " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
-        });
-    });
-
-    var descriptions = ["base type", "derived type"];
-    $.each(descriptions, function (index, _) {
-        djstest.addTest(function getHierarchicalEntry(index) {
-            var entryUri = service + "/HierarchicalEntries(" + index + ")";
-            djstest.assertsExpected(2);
-            getMetadata(function (metadata) {
-                odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
-                    djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
-                    ODataReadOracle.readJson(entryUri, function (expectedData) {
-                        djstest.assertWithoutMetadata(data, expectedData, "Verify data");
-                        djstest.done();
-                    })
-                }, unexpectedErrorHandler, undefined, undefined, metadata);
-            }, unexpectedErrorHandler, OData.metadataHandler);
-        }, "GET " + descriptions[index] + " with mapped properties: keepInContent = false", index);
-    });
-
-    $.each([false, true], function (_, recognizeDates) {
-        djstest.addTest(function readDateTimeWithMetadataTest(params) {
-            var foodStoreDataService = "./endpoints/FoodStoreDataServiceV4.svc";
-            var specialDaysEndpoint = foodStoreDataService + "/SpecialDays";
-
-            djstest.assertsExpected(1);
-            OData.jsonHandler.recognizeDates = params.recognizeDates;
-            odatajs.oData.read(foodStoreDataService + "/$metadata", function (metadata) {
-                odatajs.oData.read({ requestUri: specialDaysEndpoint, headers: { Accept: params.accept} }, function (data, response) {
-                    // Because our oracle isn't metadata aware, it is not 100% correct, so we will pass in recognizeDates = true
-                    // in all cases and manually fix up the property that was incorrectly converted
-                    window.ODataReadOracle.readFeed(specialDaysEndpoint, function (expectedData) {
-                        // Fix up the string property that has a "date-like" string deliberately injected
-                        expectedData.results[2].Name = "/Date(" + expectedData.results[2].Name.valueOf() + ")/";
-                        djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
-                        djstest.done();
-                    }, params.accept, true);
-                }, unexpectedErrorHandler, undefined, undefined, metadata);
-            }, unexpectedErrorHandler, OData.metadataHandler);
-        }, "GET metadata-aware JSON dates with recognizeDates=" + recognizeDates, { recognizeDates: recognizeDates, accept: "application/json;odata.metadata=minimal" });
-    });
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-metadata-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-metadata-tests.js b/datajs/tests/odata-metadata-tests.js
deleted file mode 100644
index 525dd62..0000000
--- a/datajs/tests/odata-metadata-tests.js
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-metadata-tests.js
-
-(function (window, undefined) {
-    djstest.addTest(function testMetadataHandler() {
-        // Test cases as result / model tuples.
-        var cases = [
-            { i: {}, e: undefined },
-            { i: { headers: { "Content-Type": "application/xml" }, body: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" />' },
-                e: { version: "4.0" }
-            }
-        ];
-
-        var i, len;
-        for (i = 0, len = cases.length; i < len; i++) {
-            var response = cases[i].i;
-            var testClient = { request: function (r, success, error) { success(response); } };
-            window.odatajs.oData.read("foo", function (data) {
-                djstest.assertAreEqualDeep(data, cases[i].e, "handler result matches target");
-            }, function (err) {
-                djstest.fail(err.message);
-            }, window.odatajs.oData.metadataHandler, testClient);
-        }
-
-        djstest.done();
-    });
-
-    // DATAJS INTERNAL START
-    djstest.addTest(function testScriptCase() {
-        // Test cases as input/result pairs.
-        var cases = [
-            { i: null, e: null },
-            { i: "", e: "" },
-            { i: "a", e: "a" },
-            { i: "A", e: "a" },
-            { i: "TestCase", e: "testCase" },
-            { i: "123abc", e: "123abc" },
-            { i: "ITEM", e: "ITEM" }
-        ];
-
-        var i, len;
-        for (i = 0, len = cases.length; i < len; i++) {
-            djstest.assertAreEqual(window.odatajs.oData.metadata.scriptCase(cases[i].i), cases[i].e, "processed input matches expected value");
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function testGetChildSchema() {
-        // Test cases as input parent / input element / result tuples.
-        var schema = window.odatajs.oData.metadata.schema;
-        var cases = [
-            { ip: schema.elements.EntityType, ie: "Property", e: { isArray: true, propertyName: "property"} },
-            { ip: schema.elements.EntityType, ie: "Key", e: { isArray: true, propertyName: "key"} },
-            { ip: schema.elements.EntitySet, ie: "SomethingElse", e: null },
-            { ip: schema.elements.Property, ie: "Name", e: null} // this is an attribute, not an element, thus it's no found
-        ];
-
-        var i, len;
-        for (i = 0, len = cases.length; i < len; i++) {
-            var result = window.odatajs.oData.metadata.getChildSchema(cases[i].ip, cases[i].ie);
-            djstest.assertAreEqualDeep(result, cases[i].e, "getChildSchema matches target");
-        }
-
-        djstest.done();
-    });
-
-    var testFullCsdl = '' +
-        '<?xml version="1.0" encoding="utf-8"?>\r\n' +
-        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">\r\n' +
-        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
-        '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="TestCatalog.Model">\r\n' +
-        '      <EntityType Name="Genre">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
-        '        <NavigationProperty Name="Titles" Type="Collection(TestCatalog.Model.Title)" Partner="Series" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Language">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" />\r\n' +
-        '        <NavigationProperty Name="Titles" Type="Collection(TestCatalog.Model.Title)" Partner="Languages" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Person">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.Int32" Nullable="false" />\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="true" />\r\n' +
-        '        <NavigationProperty Name="Awards" Type="Collection(TestCatalog.Model.TitleAward)" Partner="Person"/>\r\n' +
-        '        <NavigationProperty Name="TitlesActedIn" Type="Collection(TestCatalog.Model.Title)" Partner="Cast"/>\r\n' +
-        '        <NavigationProperty Name="TitlesDirected" Type="Collection(TestCatalog.Model.Title)" Partner="Directors"/>\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="TitleAudioFormat">\r\n' +
-        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Language" /><PropertyRef Name="Format" /></Key>\r\n' +
-        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
-        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" />\r\n' +
-        '        <Property Name="Language" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="AudioFormats" >\r\n' +
-        '            <ReferentialConstraint Property="TitleId" ReferencedProperty="Id" />' +
-        '        </NavigationProperty>' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="TitleAward">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.Guid" Nullable="false" />\r\n' +
-        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" />\r\n' +
-        '        <Property Name="Category" Type="Edm.String" Nullable="false" MaxLength="60" Unicode="false" />\r\n' +
-        '        <Property Name="Year" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Won" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="Awards"/>\r\n' +
-        '        <NavigationProperty Name="Person" Type="TestCatalog.Model.Person" Partner="Awards"/>\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Title" HasStream="true">\r\n' +
-        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
-        '        <Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
-        '        <Property Name="Synopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" />\r\n' +
-        '        <Property Name="ShortSynopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" />\r\n' +
-        '        <Property Name="AverageRating" Type="Edm.Double" Nullable="true" />\r\n' +
-        '        <Property Name="ReleaseYear" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Url" Type="Edm.String" Nullable="true" MaxLength="200" Unicode="false" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
-        '        <Property Name="DateModified" Type="Edm.DateTime" Nullable="false" />\r\n' +
-        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="8" Unicode="false" />\r\n' +
-        '        <Property Name="BoxArt" Type="TestCatalog.Model.BoxArt" Nullable="false" />\r\n' +
-        '        <Property Name="ShortName" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" />\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" />\r\n' +
-        '        <Property Name="Instant" Type="TestCatalog.Model.InstantAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="Dvd" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="BluRay" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
-        '        <Property Name="TinyUrl" Type="Edm.String" Nullable="false" />\r\n' +
-        '        <Property Name="WebsiteUrl" Type="Edm.String" Nullable="true" />\r\n' +
-        '        <Property Name="TestApiId" Type="Edm.String" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="AudioFormats" Type="Collection(TestCatalog.Model.TitleAudioFormat)" Partner="Title" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Awards" Type="Collection(TestCatalog.Model.TitleAward)" Partner="Title" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Disc" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
-        '        <NavigationProperty Name="Movie" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
-        '        <NavigationProperty Name="Season" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
-        '        <NavigationProperty Name="Series" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
-        '        <NavigationProperty Name="ScreenFormats" Type="Collection(TestCatalog.Model.TitleScreenFormat)" Partner="Title" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Cast" Type="Collection(TestCatalog.Model.Person)" Partner="TitlesActedIn" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Languages" Type="Collection(TestCatalog.Model.Language)" Partner="Titles" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Directors" Type="Collection(TestCatalog.Model.Person)" Partner="TitlesDirected" Nullable="false" />\r\n' +
-        '        <NavigationProperty Name="Genres" Type="Collection(TestCatalog.Model.Genre)" Partner="Titles" Nullable="false" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <ComplexType Name="BoxArt">\r\n' +
-        '        <Property Name="SmallUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
-        '        <Property Name="MediumUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
-        '        <Property Name="LargeUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
-        '        <Property Name="HighDefinitionUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <ComplexType Name="InstantAvailability">\r\n' +
-        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="HighDefinitionAvailable" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <ComplexType Name="DeliveryFormatAvailability">\r\n' +
-        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
-        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
-        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
-        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
-        '      </ComplexType>\r\n' +
-        '      <EntityType Name="TitleScreenFormat">\r\n' +
-        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Format" /></Key>\r\n' +
-        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
-        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" />\r\n' +
-        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" />\r\n' +
-        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="ScreenFormats" >\r\n' +
-        '            <ReferentialConstraint Property="TitleId" ReferencedProperty="Id" />' +
-        '        </NavigationProperty>' +
-        '      </EntityType>\r\n' +
-        '      <Function Name="ProductsByRating">' +
-        '        <ReturnType Type="Collection(TestCatalog.Model.Title)" />\r\n' +
-        '      </Function>\r\n' +
-        '    </Schema>\r\n' +
-        '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Test.Catalog">\r\n' +
-        '      <EntityContainer Name="TestCatalog" >\r\n' +
-        '        <FunctionImport Name="Movies" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
-        '        <FunctionImport Name="Series" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
-        '        <FunctionImport Name="Seasons" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
-        '        <FunctionImport Name="Discs" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
-        '        <FunctionImport Name="Episodes" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
-        '        <EntitySet Name="Genres" EntityType="TestCatalog.Model.Genre" >\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Titles" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '        <EntitySet Name="Languages" EntityType="TestCatalog.Model.Language" >\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Languages" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '        <EntitySet Name="People" EntityType="TestCatalog.Model.Person" >\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Cast" />\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Directors" />\r\n' +
-        '        </EntitySet>' +
-        '        <EntitySet Name="TitleAudioFormats" EntityType="TestCatalog.Model.TitleAudioFormat" >\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="AudioFormats" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '        <EntitySet Name="TitleAwards" EntityType="TestCatalog.Model.TitleAward" >\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Awards" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '        <EntitySet Name="Titles" EntityType="TestCatalog.Model.Title" >\r\n' +
-        '            <NavigationPropertyBinding Target="TitleAudioFormats" Path="Title" />\r\n' +
-        '            <NavigationPropertyBinding Target="TitleAwards" Path="Title" />\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Disc" />\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Movie" />\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Season" />\r\n' +
-        '            <NavigationPropertyBinding Target="Titles" Path="Series" />\r\n' +
-        '            <NavigationPropertyBinding Target="TitleScreenFormats" Path="ScreenFormats" />\r\n' +
-        '            <NavigationPropertyBinding Target="People" Path="TitlesActedIn" />\r\n' +
-        '            <NavigationPropertyBinding Target="Languages" Path="Titles" />\r\n' +
-        '            <NavigationPropertyBinding Target="People" Path="TitlesDirected" />\r\n' +
-        '            <NavigationPropertyBinding Target="Genres" Path="Genres" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '        <EntitySet Name="TitleScreenFormats" EntityType="TestCatalog.Model.TitleScreenFormat" >\r\n' +
-        '            <NavigationPropertyBinding Target="TitleScreenFormats" Path="Title" />\r\n' +
-        '        </EntitySet>\r\n' +
-        '      </EntityContainer>\r\n' +
-        '    </Schema>\r\n' +
-        '  </edmx:DataServices>\r\n' +
-        '</edmx:Edmx>\r\n' +
-        '';
-
-    var testFullMetadataResult = {
-        "version": "4.0",
-        "dataServices": {
-            "dataServiceVersion": "4.0",
-            "maxDataServiceVersion": "4.0",
-            "schema": [{
-                "namespace": "TestCatalog.Model",
-                "entityType": [{
-                    "name": "Genre",
-                    "key": [{ "propertyRef": [{ "name": "Name"}] }],
-                    "property": [{ "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "50", "unicode": "false"}],
-                    "navigationProperty": [{ "name": "Titles", "partner": "Series", "type": "Collection(TestCatalog.Model.Title)"}]
-                }, {
-                    "name": "Language",
-                    "key": [{ "propertyRef": [{ "name": "Name"}] }],
-                    "property": [{ "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "80", "unicode": "false"}],
-                    "navigationProperty": [{ "name": "Titles", "partner": "Languages", "type": "Collection(TestCatalog.Model.Title)"}]
-                }, {
-                    "name": "Person",
-                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
-                    "property": [
-                        { "name": "Id", "type": "Edm.Int32", "nullable": "false" },
-                        { "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "80", "unicode": "true" }
-                    ],
-                    "navigationProperty": [
-                        { "name": "Awards", "partner": "Person", "type": "Collection(TestCatalog.Model.TitleAward)" },
-                        { "name": "TitlesActedIn", "partner": "Cast", "type": "Collection(TestCatalog.Model.Title)" },
-                        { "name": "TitlesDirected", "partner": "Directors", "type": "Collection(TestCatalog.Model.Title)" }
-                    ]
-                }, {
-                    "name": "TitleAudioFormat",
-                    "key": [{ "propertyRef": [{ "name": "TitleId" }, { "name": "DeliveryFormat" }, { "name": "Language" }, { "name": "Format"}] }],
-                    "property": [
-                        { "name": "TitleId", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
-                        { "name": "DeliveryFormat", "type": "Edm.String", "nullable": "false", "maxLength": "10", "unicode": "false" },
-                        { "name": "Language", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" },
-                        { "name": "Format", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" }
-                    ],
-                    "navigationProperty": [{ "name": "Title", "partner": "AudioFormats", "referentialConstraint": [{"property": "TitleId", "referencedProperty": "Id"}], "type": "TestCatalog.Model.Title" }]
-                }, {
-                    "name": "TitleAward",
-                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
-                    "property": [
-                        { "name": "Id", "type": "Edm.Guid", "nullable": "false" },
-                        { "name": "Type", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" },
-                        { "name": "Category", "type": "Edm.String", "nullable": "false", "maxLength": "60", "unicode": "false" },
-                        { "name": "Year", "type": "Edm.Int32", "nullable": "true" }, { "name": "Won", "type": "Edm.Boolean", "nullable": "false" }
-                    ],
-                    "navigationProperty": [
-                        { "name": "Title", "partner": "Awards", "type": "TestCatalog.Model.Title" },
-                        { "name": "Person", "partner": "Awards", "type": "TestCatalog.Model.Person" }
-                    ]
-                }, {
-                    "name": "Title",
-                    "hasStream": "true",
-                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
-                    "property": [
-                        { "name": "Id", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
-                        { "name": "Synopsis", "type": "Edm.String", "nullable": "true", "maxLength": "Max", "unicode": "false" },
-                        { "name": "ShortSynopsis", "type": "Edm.String", "nullable": "true", "maxLength": "Max", "unicode": "false" },
-                        { "name": "AverageRating", "type": "Edm.Double", "nullable": "true" }, { "name": "ReleaseYear", "type": "Edm.Int32", "nullable": "true" },
-                        { "name": "Url", "type": "Edm.String", "nullable": "true", "maxLength": "200", "unicode": "false" },
-                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
-                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" },
-                        { "name": "DateModified", "type": "Edm.DateTime", "nullable": "false"},
-                        { "name": "Type", "type": "Edm.String", "nullable": "false", "maxLength": "8", "unicode": "false" },
-                        { "name": "BoxArt", "type": "TestCatalog.Model.BoxArt", "nullable": "false" },
-                        { "name": "ShortName", "type": "Edm.String", "nullable": "false", "maxLength": "200", "unicode": "false" },
-                        { "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "200", "unicode": "false" },
-                        { "name": "Instant", "type": "TestCatalog.Model.InstantAvailability", "nullable": "false" },
-                        { "name": "Dvd", "type": "TestCatalog.Model.DeliveryFormatAvailability", "nullable": "false" },
-                        { "name": "BluRay", "type": "TestCatalog.Model.DeliveryFormatAvailability", "nullable": "false" },
-                        { "name": "TinyUrl", "type": "Edm.String", "nullable": "false" },
-                        { "name": "WebsiteUrl", "type": "Edm.String", "nullable": "true" },
-                        { "name": "TestApiId", "type": "Edm.String", "nullable": "false" }
-                    ],
-                    "navigationProperty": [
-                        { "name": "AudioFormats", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleAudioFormat)" },
-                        { "name": "Awards", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleAward)" },
-                        { "name": "Disc", "type": "Collection(TestCatalog.Model.Title)" },
-                        { "name": "Movie", "type": "Collection(TestCatalog.Model.Title)" },
-                        { "name": "Season", "type": "Collection(TestCatalog.Model.Title)" },
-                        { "name": "Series", "type": "Collection(TestCatalog.Model.Title)" },
-                        { "name": "ScreenFormats", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleScreenFormat)" },
-                        { "name": "Cast", "nullable": "false", "partner": "TitlesActedIn", "type": "Collection(TestCatalog.Model.Person)" },
-                        { "name": "Languages", "nullable": "false", "partner": "Titles", "type": "Collection(TestCatalog.Model.Language)" },
-                        { "name": "Directors", "nullable": "false", "partner": "TitlesDirected", "type": "Collection(TestCatalog.Model.Person)" },
-                        { "name": "Genres", "nullable": "false", "partner": "Titles", "type": "Collection(TestCatalog.Model.Genre)" }
-                    ]
-                }, {
-                    "name": "TitleScreenFormat",
-                    "key": [{ "propertyRef": [{ "name": "TitleId" }, { "name": "DeliveryFormat" }, { "name": "Format"}]}],
-                    "property": [
-                        { "name": "TitleId", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
-                        { "name": "DeliveryFormat", "type": "Edm.String", "nullable": "false", "maxLength": "10", "unicode": "false" },
-                        { "name": "Format", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" }
-                    ],
-                    "navigationProperty": [{ "name": "Title", "partner": "ScreenFormats", "referentialConstraint": [{"property": "TitleId", "referencedProperty": "Id"}], "type": "TestCatalog.Model.Title" }]
-                }],
-                "complexType": [{
-                    "name": "BoxArt",
-                    "property": [
-                        { "name": "SmallUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
-                        { "name": "MediumUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
-                        { "name": "LargeUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
-                        { "name": "HighDefinitionUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" }
-                    ]
-                }, {
-                    "name": "InstantAvailability",
-                    "property": [
-                        { "name": "Available", "type": "Edm.Boolean", "nullable": "false" },
-                        { "name": "AvailableFrom", "type": "Edm.DateTime", "nullable": "true" },
-                        { "name": "AvailableTo", "type": "Edm.DateTime", "nullable": "true" },
-                        { "name": "HighDefinitionAvailable", "type": "Edm.Boolean", "nullable": "false" },
-                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
-                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" }
-                    ]
-                }, {
-                    "name": "DeliveryFormatAvailability",
-                    "property": [
-                        { "name": "Available", "type": "Edm.Boolean", "nullable": "false" },
-                        { "name": "AvailableFrom", "type": "Edm.DateTime", "nullable": "true" },
-                        { "name": "AvailableTo", "type": "Edm.DateTime", "nullable": "true" },
-                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
-                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" }
-                    ]
-                }],
-                "function": [
-                {
-                   "name": "ProductsByRating",
-                   "returnType": {"type": "Collection(TestCatalog.Model.Title)" }
-                }]
-            }, {
-                "namespace": "Test.Catalog",
-                "entityContainer": {
-                    "name": "TestCatalog",
-                    "functionImport": [
-                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Movies"},
-                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Series"},
-                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Seasons" },
-                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Discs" },
-                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Episodes" }
-                    ], "entitySet": [
-                        { "name": "Genres", "entityType": "TestCatalog.Model.Genre", "navigationPropertyBinding": [{"path": "Titles", "target": "Titles"}] },
-                        { "name": "Languages", "entityType": "TestCatalog.Model.Language", "navigationPropertyBinding": [{ "path": "Languages", "target": "Titles"}] },
-                        { "name": "People", "entityType": "TestCatalog.Model.Person", "navigationPropertyBinding": [{ "path": "Cast", "target": "Titles" }, { "path": "Directors", "target": "Titles"}] },
-                        { "name": "TitleAudioFormats", "entityType": "TestCatalog.Model.TitleAudioFormat", "navigationPropertyBinding": [{ "path": "AudioFormats", "target": "Titles"}] },
-                        { "name": "TitleAwards", "entityType": "TestCatalog.Model.TitleAward", "navigationPropertyBinding": [{ "path": "Awards", "target": "Titles"}] },
-                        { "name": "Titles", "entityType": "TestCatalog.Model.Title", "navigationPropertyBinding": [{ "path": "Title", "target": "TitleAudioFormats" }, { "path": "Title", "target": "TitleAwards" }, { "path": "Disc", "target": "Titles" }, { "path": "Movie", "target": "Titles" }, { "path": "Season", "target": "Titles" }, { "path": "Series", "target": "Titles" }, { "path": "ScreenFormats", "target": "TitleScreenFormats" }, { "path": "TitlesActedIn", "target": "People" }, { "path": "Titles", "target": "Languages" }, { "path": "TitlesDirected", "target": "People" }, { "path": "Genres", "target": "Genres"}] },
-                        { "name": "TitleScreenFormats", "entityType": "TestCatalog.Model.TitleScreenFormat", "navigationPropertyBinding": [{ "path": "Title", "target": "TitleScreenFormats"}] }
-                    ]
-                }
-            }]
-        }
-    };
-
-    var testCsdlV4 = '' +
-    '<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">\r\n' +
-    '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
-    '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="TestCatalog.Model"/>\r\n' +
-    '  </edmx:DataServices>\r\n' +
-    '</edmx:Edmx>';
-
-    var testMetadataV4 = {
-        "version": "4.0",
-        "dataServices": {
-            "maxDataServiceVersion": "4.0",
-            "dataServiceVersion": "4.0",
-            "schema": [{
-                "namespace": "TestCatalog.Model"
-            }]
-        }
-    };
-
-    djstest.addTest(function testParseConceptualModelElement() {
-        // Test cases as input XML text / result tuples.
-        var cases = [
-            { i: "<foo />", e: null },
-            { i: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" />', e: { version: "4.0"} },
-            { i: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx-invalid" />', e: null },
-            { i: testCsdlV4, e: testMetadataV4 },
-            { i: testFullCsdl, e: testFullMetadataResult }
-        ];
-
-        var i, len;
-        for (i = 0, len = cases.length; i < len; i++) {
-            var doc = window.odatajs.xml.xmlParse(cases[i].i);
-            var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
-            djstest.assertAreEqualDeep(schema, cases[i].e, "parseConceptualModelElement result matches target");
-        }
-
-        djstest.done();
-    });
-
-    djstest.addTest(function metadataVocabularyTest() {
-        var testCsdl = '' +
-        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
-        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" >\r\n' +
-        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
-        '    <Schema Namespace="TestCatalog.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">\r\n' +
-        '          <Term Name="Rating" Type="Edm.Int32" />\r\n' +
-        '          <Term Name="CanEdit" Type="Edm.String" />\r\n' +
-        '      <EntityType Name="Genre">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
-        '      </EntityType></Schema></edmx:DataServices></edmx:Edmx>';
-
-
-        var doc = window.odatajs.xml.xmlParse(testCsdl);
-        var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
-
-        djstest.assertAreEqual(schema.dataServices.schema[0].term.length, 2, "schema.DataServices.Schema.Term.length === 2");
-        djstest.assertAreEqual(schema.dataServices.schema[0].term[0].name, "Rating", "schema.DataServices.Schema.Term[0].name === 'Rating'");
-        djstest.assertAreEqual(schema.dataServices.schema[0].term[1].name, "CanEdit", "schema.DataServices.Schema.Term[1].name === 'CanEdit'");
-        djstest.done();
-    });
-
-    djstest.addTest(function metadataAnnotationTest() {
-        var testCsdl = '' +
-        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
-        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" >\r\n' +
-        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
-        '    <Schema Namespace="TestCatalog.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">\r\n' +
-        '      <EntityType Name="Genre">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <EntityType Name="Language">\r\n' +
-        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
-        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" />\r\n' +
-        '        <Property Name="Id" Type="Edm.Int32" />\r\n' +
-        '      </EntityType>\r\n' +
-        '      <Annotations Target="TestCatalog.Model.Genre/Name">\r\n' +
-        '        <Annotation String="Genre Name" Term="Org.OData.Display.V1.DisplayName"/>\r\n' +
-        '      </Annotations>\r\n' +
-        '      <Annotations Target="TestCatalog.Model.Language/Name">\r\n' +
-        '        <Annotation String="Language Name" Term="Org.OData.Display.V1.DisplayName"/>\r\n' +
-        '        <Annotation String="Language Name 2" Term="Org.OData.Display.V1.DisplayName 2"/>\r\n' +
-        '      </Annotations>\r\n' +
-        '    </Schema></edmx:DataServices></edmx:Edmx>';
-
-
-        var doc = window.odatajs.xml.xmlParse(testCsdl);
-        var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
-
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations.length, 2, "Annotations number");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation.length, 1, "Annotation number");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation[0].string, "Genre Name", "Annotation name");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation[0].term, "Org.OData.Display.V1.DisplayName", "Annotation term");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation.length, 2, "Annotation number");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[0].string, "Language Name", "Annotation name");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[0].term, "Org.OData.Display.V1.DisplayName", "Annotation term");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[1].string, "Language Name 2", "Annotation name");
-        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[1].term, "Org.OData.Display.V1.DisplayName 2", "Annotation term");
-        djstest.done();
-    });
-
-    // DATAJS INTERNAL END
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-net-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-net-tests.js b/datajs/tests/odata-net-tests.js
deleted file mode 100644
index 351b197..0000000
--- a/datajs/tests/odata-net-tests.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-net-tests.js
-(function (window, undefined) {
-    module("Unit");
-    djstest.addTest(function httpClientSendRequestTest() {
-        var tests = [
-            { url: "http://localhost/test1", response: { headers: {}, status: 200, body: "test"} },
-            { url: "http://localhost/test2", response: { headers: {}, status: 204, body: "test"} },
-            { url: "http://localhost/test3", response: { headers: {}, status: 299, body: "test"} },
-            { url: "http://localhost/test4", response: { headers: {}, status: 500, body: "error"} }
-        ];
-
-        djstest.assertsExpected(12);
-
-        var sentCount = 0;
-        MockXMLHttpRequest.onAfterSend = function () {
-            sentCount++;
-        };
-
-        var oldXmlHttpRequest = window.XMLHttpRequest;
-        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-        try {
-            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
-            var i, len;
-            for (i = 0, len = tests.length; i < len; i++) {
-                MockXMLHttpRequest.addResponse(tests[i].url, tests[i].response);
-
-                window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
-                //Need a closure to capture the current test being executed. 
-                (function (test) {
-                    window.odatajs.oData.net.defaultHttpClient.request(
-                    { requestUri: test.url, headers: {} },
-                    function (response) {
-                        djstest.assert(response.statusCode >= 200 & response.statusCode <= 299, "response status is in the success range");
-                        djstest.assertAreEqual(response.body, test.response.body, "response body is the expected one");
-                        djstest.assertAreEqualDeep(response.headers, [], "response headers are the expected ones");
-                    },
-                    function (error) {
-                        djstest.assert(error.response.statusCode > 299, "response status is in the error range");
-                        djstest.assertAreEqual(error.response.body, test.response.body, "response body is the expected one");
-                        djstest.assertAreEqualDeep(error.response.headers, [], "response headers are the expected ones");
-                    });
-                })(tests[i]);
-            }
-        }
-        finally {
-            //Cleanup and finish the test after all requests have been sent and processed. Poll every 50 ms
-            var timer = setInterval(function () {
-                if (sentCount === tests.length) {
-                    clearInterval(timer)
-                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-                    window.XMLHttpRequest = oldXmlHttpRequest;
-                    MockXMLHttpRequest.reset();
-                    djstest.done();
-                }
-            }, 50);
-        }
-    });
-
-    djstest.addTest(function httpClientRequestTimeoutTest() {
-        var oldXmlHttpRequest = window.XMLHttpRequest;
-        var testDone = false;
-
-        djstest.assertsExpected(1);
-
-        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-        try {
-            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
-
-            window.odatajs.oData.net.defaultHttpClient.request(
-               { requestUri: "http://test1", timeoutMS: 10, headers: { MockTimeOut: true} },
-               function (response) {
-                   djstest.fail("success method was hit when not expected");
-                   testDone = true;
-               },
-               function (error) {
-                   djstest.assertAreEqual(error.message, "Request timed out", "error method executes and error is the expected one");
-                   testDone = true;
-               });
-        }
-        finally {
-            //Cleanup and finish the test after all requests have been sent and processed. Poll every 50 ms
-            var timer = setInterval(function () {
-                if (testDone) {
-                    clearInterval(timer);
-                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-                    window.XMLHttpRequest = oldXmlHttpRequest;
-                    MockXMLHttpRequest.reset();
-                    djstest.done();
-                }
-            }, 50);
-        }
-    });
-
-    djstest.addTest(function httpClientRequestAbortTest() {
-
-        var oldXmlHttpRequest = window.XMLHttpRequest;
-
-        djstest.assertsExpected(1);
-
-        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-        try {
-            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
-
-            var result = window.odatajs.oData.net.defaultHttpClient.request(
-               { requestUri: "http://test1", headers: { MockNoOp: true} },
-               function (response) {
-                   djstest.fail("success method was hit when not expected");
-               },
-               function (error) {
-                   djstest.assertAreEqual(error.message, "Request aborted", "error method executes and error is the expected one");
-               });
-
-            result.abort();
-        }
-        finally {
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-            window.XMLHttpRequest = oldXmlHttpRequest;
-            MockXMLHttpRequest.reset();
-            djstest.done();
-        }
-    });
-
-    djstest.addTest(function httpClientRequestAbortOnCompletedRequestTest() {
-
-        var oldXmlHttpRequest = window.XMLHttpRequest;
-        var testDone = false;
-
-        djstest.assertsExpected(1);
-
-        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-        try {
-            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
-
-            MockXMLHttpRequest.addResponse("http://test1", { headers: {}, status: 200, body: "test body" });
-
-            MockXMLHttpRequest.onAfterSend = function () {
-                result.abort();
-                testDone = true;
-            };
-
-            result = window.odatajs.oData.net.defaultHttpClient.request(
-               { requestUri: "http://test1", headers: {} },
-               function (response) {
-                   djstest.pass("success method was hit");
-               },
-               function (error) {
-                   djstest.fail("success method was hit when not expected - [" + error.message + "]");
-               });
-        }
-        finally {
-            // Cleanup after test is done, poll eavery 50ms
-            var timer = setInterval(function () {
-                if (testDone) {
-                    clearInterval(timer);
-                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-                    window.XMLHttpRequest = oldXmlHttpRequest;
-                    MockXMLHttpRequest.reset();
-                    djstest.done();
-                }
-            }, 50);
-        }
-    });
-
-    djstest.addTest(function httpClientRequestSendsRequestCorrectlyTest() {
-        var tests = [
-            {
-                request: { requestUri: "http://test1", headers: {}, body: "test" },
-                expected: { headers: {}, url: "http://test1", method: "GET", body: "test", async: true, user: undefined, password: undefined }
-            },
-            {
-                request: { requestUri: "http://test2", headers: {}, method: "POST", body: "test" },
-                expected: { headers: {}, url: "http://test2", method: "POST", body: "test", async: true, user: undefined, password: undefined }
-            },
-            {
-                request: { requestUri: "http://test3", headers: { header1: "value1", header2: "value2" }, body: "test" },
-                expected: { headers: { header1: "value1", header2: "value2" }, url: "http://test3", method: "GET", body: "test", async: true, user: undefined, password: undefined }
-            }
-        ];
-
-        var oldXmlHttpRequest = window.XMLHttpRequest;
-        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
-        try {
-            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
-            var i, len;
-
-            for (i = 0, len = tests.length; i < len; i++) {
-
-                MockXMLHttpRequest.addRequestVerifier(tests[i].request.requestUri, function (request) {
-                    djstest.assertAreEqualDeep(request, tests[i].expected, "request matches target");
-                });
-
-                window.odatajs.oData.net.defaultHttpClient.request(
-                    tests[i].request,
-                    function (response) { });
-            }
-        }
-        finally {
-            // Restore original values.
-            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
-            window.XMLHttpRequest = oldXmlHttpRequest;
-        }
-        djstest.done();
-    });
-
-    // DATAJS INTERNAL START
-    djstest.addTest(function canUseJSONPTest() {
-        var tests = [
-            { pass: true, input: {} },
-            { pass: true, input: { method: "GET"} },
-            { pass: false, input: { method: "PUT"} },
-            { pass: false, input: { method: "get"} },
-            { pass: true, input: { accept: "*/*"} },
-            { pass: true, input: { accept: "application/json"} },
-            { pass: true, input: { accept: "text/javascript"} },
-            { pass: true, input: { accept: "application/javascript"} },
-            { pass: true, input: { accept: "application/xml"} },
-            { pass: true, input: { headers: { Accept: "application/xml"}} }
-        ];
-        for (var i = 0; i < tests.length; i++) {
-            var actual = window.odatajs.oData.net.canUseJSONP(tests[i].input);
-            djstest.assert(actual === tests[i].pass, "test " + i + " didn't actually match pass (" + tests[i].pass + ")");
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function isAbsoluteUrlTest() {
-        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("http://something/"));
-        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("http://malformed url/"));
-        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("https://localhost/"));
-        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("file://another-protocol/"));
-        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("/path"));
-        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("?query-string"));
-        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl(""));
-        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("mailto:someone"));
-        djstest.done();
-    });
-
-    djstest.addTest(function isLocalUrlTest() {
-        var thisUrl = window.location.href;
-        var localUrls = [
-            "", ".", "/howdy.htm", "  ", "?queryparam",
-            thisUrl, thisUrl + "/foo", thisUrl + "?something-else"
-        ];
-        var remoteUrls = [
-            "http://www.microsoft.com/",
-            "https://www.microsoft.com/",
-            "https://" + window.location.host,
-            "https://" + window.location.hostname,
-        // 21 is FTP, so the test shouldn't collide
-            "http://" + window.location.hostname + ":21"
-        ];
-        var i, len;
-        for (i = 0, len = localUrls.length; i < len; i++) {
-            djstest.assert(window.odatajs.oData.net.isLocalUrl(localUrls[i]), "is local: [" + localUrls[i] + "]");
-        }
-        for (i = 0, len = remoteUrls.length; i < len; i++) {
-            djstest.assert(!window.odatajs.oData.net.isLocalUrl(remoteUrls[i]), "is not local: [" + remoteUrls[i] + "]");
-        }
-        djstest.done();
-    });
-
-    // DATAJS INTERNAL END
-
-    djstest.addTest(function userPasswordTest() {
-        odatajs.oData.request({
-            requestUri: "./endpoints/FoodStoreDataServiceV4.svc/UserNameAndPassword",
-            user: "the-user",
-            password: "the-password"
-        }, function (data) {
-            djstest.assertAreEqualDeep(data.value, "Basic dGhlLXVzZXI6dGhlLXBhc3N3b3Jk", "response matches");
-            djstest.done();
-        }, function (err) {
-            djstest.fail("error: " + err.message);
-            djstest.done();
-        });
-    });
-
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-perf-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-perf-tests.html b/datajs/tests/odata-perf-tests.html
deleted file mode 100644
index 238246f..0000000
--- a/datajs/tests/odata-perf-tests.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData perf tests</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/TestSynchronizerClient.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script> 
-    <script type="text/javascript" src="common/common.js"></script> 
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="common/Instrument.js"></script>
-
-    <script type="text/javascript" src="odata-perf-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">OData perf 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/d5ec5557/datajs/tests/odata-perf-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-perf-tests.js b/datajs/tests/odata-perf-tests.js
deleted file mode 100644
index cd465fe..0000000
--- a/datajs/tests/odata-perf-tests.js
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var timedHttpClient = {
-        duration: 0,
-        provider: window.odatajs.oData.net.defaultHttpClient,
-        request: function (request, success, error) {
-            var startTime = new Date();
-            return timedHttpClient.provider.request(request, function () {
-                timedHttpClient.duration = new Date() - startTime;
-                success.apply(this, arguments);
-            }, error);
-        }
-    };
-
-    var largeCollectionService = "./endpoints/LargeCollectionService.svc/";
-
-    // null "service" indicates the feed is read-only
-    var feeds = [
-        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=minimal" },
-        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=full" },
-        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=none" },
-        { service: largeCollectionService, uri: largeCollectionService + "Suppliers", mimeType: "application/json" },
-        { service: null, uri: "http://odata.netflix.com/Catalog/Titles", mimeType: "application/json" }
-    ];
-
-    module("Performance", {
-        setup: function () {
-            djstest.wait(function (done) {
-                $.post(largeCollectionService + "ResetData", done);
-            });
-        },
-        teardown: function () {
-            window.odatajs.oData.net.defaultHttpClient = timedHttpClient.provider;
-        }
-    });
-
-    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
-    $.each(feeds, function (_, feed) {
-        $.each([5, 500], function (_, items) {
-            var params = $.extend({}, feed, { items: items, readUri: feed.uri + "?$top=" + items });
-            djstest.addTest(function readPerfTest(params) {
-                var measureRead = function (metadata) {
-                    var startTime = new Date();
-                    odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function () {
-                        var duration = new Date() - startTime - timedHttpClient.duration;
-                        djstest.pass("Duration: " + duration + " ms (Network: " + timedHttpClient.duration + " ms)");
-                        djstest.done();
-                    }, unexpectedErrorHandler, undefined, undefined, metadata);
-                };
-
-                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
-                djstest.assertsExpected(1);
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measureRead();
-                }
-            }, "Time to read (once) " + params.readUri + " with " + params.mimeType, params);
-
-            djstest.addTest(function readParallelMemoryTest(params) {
-                var total = 10;
-                var count = 0;
-                var measureRead = function (metadata) {
-                    Instrument.getBrowserMemorySize(function (memoryBefore) {
-                        for (var i = 0; i < total; i++) {
-                            odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function (_, response) {
-                                count++;
-                                if (count >= total) {
-                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
-                                        var memory = memoryAfter - memoryBefore;
-                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
-                                        djstest.done();
-                                    });
-                                }
-                            }, unexpectedErrorHandler, undefined, undefined, metadata);
-                        }
-                    });
-                };
-
-                djstest.assertsExpected(1);
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measureRead();
-                }
-            }, "Memory to read (x10 parallel) " + params.readUri + " with " + params.mimeType, params, 300000);
-
-            djstest.addTest(function readSerialMemoryTest(params) {
-                var total = 10;
-                var count = 0;
-                var measureRead = function (metadata) {
-                    Instrument.getBrowserMemorySize(function (memoryBefore) {
-                        var makeRequest = function () {
-                            odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function (_, response) {
-                                count++;
-                                if (count < total) {
-                                    setTimeout(makeRequest, 0);
-                                } else {
-                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
-                                        var memory = memoryAfter - memoryBefore;
-                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
-                                        djstest.done();
-                                    });
-                                }
-                            }, unexpectedErrorHandler, undefined, undefined, metadata);
-                        };
-
-                        makeRequest();
-                    });
-                };
-
-                djstest.assertsExpected(1);
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measureRead();
-                }
-            }, "Memory to read (x10 serial) " + params.readUri + " with " + params.mimeType, params, 300000);
-        });
-
-        if (feed.service) {
-            var params = $.extend({}, feed, {
-                request: {
-                    requestUri: feed.uri,
-                    method: "POST",
-                    headers: { "Content-Type": feed.mimeType, Accept: feed.mimeType },
-                    data: {
-                        ID: -1,
-                        Name: "New Entity"
-                    }
-                }
-            });
-
-            djstest.addTest(function postPerfTest(params) {
-                var measurePost = function (metadata) {
-                    var startTime = new Date();
-                    odatajs.oData.request(params.request, function () {
-                        var duration = new Date() - startTime - timedHttpClient.duration;
-                        djstest.pass("Duration: " + duration + " ms (Network: " + timedHttpClient.duration + " ms)");
-                        djstest.done();
-                    }, unexpectedErrorHandler, undefined, undefined, metadata);
-                };
-
-                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
-                djstest.assertsExpected(1);
-
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measurePost();
-                }
-            }, "Time to POST " + params.uri + " with " + params.mimeType, params);
-
-            djstest.addTest(function postParallelMemoryTest(params) {
-                var total = 10;
-                var count = 0;
-                var measurePost = function (metadata) {
-                    Instrument.getBrowserMemorySize(function (memoryBefore) {
-                        for (var i = 0; i < total; i++) {
-                            odatajs.oData.request(params.request, function (_, response) {
-                                count++;
-                                if (count >= total) {
-                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
-                                        var memory = memoryAfter - memoryBefore;
-                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
-                                        djstest.done();
-                                    });
-                                }
-                            }, unexpectedErrorHandler, undefined, undefined, metadata);
-                        }
-                    });
-                };
-
-                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
-                djstest.assertsExpected(1);
-
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measurePost();
-                }
-            }, "Memory to POST (x10 parallel) " + params.uri + " with " + params.mimeType, params);
-
-            djstest.addTest(function postSerialMemoryTest(params) {
-                var total = 10;
-                var count = 0;
-                var measurePost = function (metadata) {
-                    Instrument.getBrowserMemorySize(function (memoryBefore) {
-                        var makeRequest = function () {
-                            odatajs.oData.request(params.request, function (_, response) {
-                                count++;
-                                if (count < total) {
-                                    setTimeout(makeRequest, 0);
-                                } else {
-                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
-                                        var memory = memoryAfter - memoryBefore;
-                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
-                                        djstest.done();
-                                    });
-                                }
-                            }, unexpectedErrorHandler, undefined, undefined, metadata);
-                        };
-
-                        makeRequest();
-                    });
-                };
-
-                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
-                djstest.assertsExpected(1);
-
-                if (params.metadata) {
-                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
-                } else {
-                    measurePost();
-                }
-            }, "Memory to POST (x10 serial) " + params.uri + " with " + params.mimeType, params);
-        }
-    });
-})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-qunit-tests.htm
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-qunit-tests.htm b/datajs/tests/odata-qunit-tests.htm
deleted file mode 100644
index 3054691..0000000
--- a/datajs/tests/odata-qunit-tests.htm
+++ /dev/null
@@ -1,76 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
-<html>
-  <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/ODataReadOracle.js"></script>
-    <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
-
-    <!--<script type="text/javascript" src="common/rx.js"></script>-->
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.5/rx.all.js"></script>
-    <script type="text/javascript">
-        window.TestSynchronizer.init(QUnit);
-    </script>
-    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script>
-
-    <script type="text/javascript" src="./common/mockHttpClient.js"></script>
-    <script type="text/javascript" src="./common/mockXMLHttpRequest.js"></script>
-
-    <script type="text/javascript" src="./common/djstest.js"></script>
-    <script type="text/javascript" src="./common/djstest-browser.js"></script>
-    <script type="text/javascript" src="./common/CacheOracle.js"></script>
-
-<!--bingl: disable the failure test case. Will fix them in the next change set-->
-<!--    <script type="text/javascript" src="odata-tests.js"></script>-->
-    <script type="text/javascript" src="odata-json-tests.js"></script>
-<!--    <script type="text/javascript" src="odata-json-light-tests.js"></script>-->
-    <script type="text/javascript" src="odata-links-functional-tests.js"></script>
-    <script type="text/javascript" src="odata-metadata-tests.js"></script>
-    <script type="text/javascript" src="odata-xml-tests.js"></script>
-    <script type="text/javascript" src="odata-handler-tests.js"></script>
-    <script type="text/javascript" src="odata-net-tests.js"></script>
-    <script type="text/javascript" src="odata-batch-tests.js"></script>
-    <script type="text/javascript" src="cache-tests.js"></script>
-    <script type="text/javascript" src="store-tests.js"></script>
-    <script type="text/javascript" src="store-indexeddb-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/d5ec5557/datajs/tests/odata-read-crossdomain-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-read-crossdomain-functional-tests.html b/datajs/tests/odata-read-crossdomain-functional-tests.html
deleted file mode 100644
index 86ce093..0000000
--- a/datajs/tests/odata-read-crossdomain-functional-tests.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>OData tests against local service</title>
-    <meta http-equiv="cache-control" content="no-cache"/> 
-    <meta http-equiv="pragma" content="no-cache"/> 
-    <meta http-equiv="expires" content="-1"/> 
-
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
-    <script type="text/javascript" src="common/common.js"></script> 
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-read-crossdomain-functional-tests.js"></script>  
-</head>
-<body>
- <h1 id="qunit-header">OData.Read tests against cross domain endpoints</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-</body>
-</html>
\ No newline at end of file


[46/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/tools.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/tools.js b/datajs/demo/scripts/tools.js
deleted file mode 100644
index d13dd7d..0000000
--- a/datajs/demo/scripts/tools.js
+++ /dev/null
@@ -1,146 +0,0 @@
-(function($) {
-  $.fn.prettify = function(options) {
-    return this.each(function() {
-      try {
-        var $code = $(document.createElement('div')).addClass('code');
-        $(this).before($code).remove();
-        var content = $(this).text();
-        var match = /(xml|json)/.exec($(this).attr('data-type'));
-        var format = (match) ? match[1] : null;
-        var html = null;
-        if (format == 'xml') {
-          var xmlDoc = $.parseXML(content);
-          html = (xmlDoc) ? formatXML(xmlDoc) : null;
-        } else if (format == 'json') {
-          var jsonObj = $.parseJSON(content);
-          html = (jsonObj) ? formatJSON(jsonObj) : null;
-        }
-        if (html) {
-          $code.addClass(format).html(html).find('.list').each(function() {
-            if (this.parentNode.nodeName == 'LI') {
-              $(document.createElement('div')).addClass("toggle").text("-").click(function() {
-                var target = $(this).siblings('.list:first');
-                if (target.size() != 1)
-                  return;
-                if (target.is(':hidden')) {
-                  target.show().siblings('.deffered').remove();
-                } else {
-                  target.hide().before($(document.createElement('span')).attr("class", "deffered").html("..."));
-                }
-                $(this).text($(this).text() == '-' ? '+' : '-');
-              }).insertBefore($(this.parentNode).children(':first'));
-            }
-          });
-        }
-      } catch (e) {
-        console.log(e);
-      }
-      /* encode html */
-      function encodeHtml(html) {
-        return (html != null) ? html.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
-      }
-      /* convert json to html */
-      function formatJSON(value) {
-        var typeofValue = typeof value;
-        if (value == null) {
-          return '<span class="null">null</span>';
-        } else if (typeofValue == 'number') {
-          return '<span class="numeric">' + encodeHtml(value) + '</span>';
-        } else if (typeofValue == 'string') {
-          if (/^(http|https):\/\/[^\s]+$/.test(value)) {
-            var fragment = '';
-            var fragmentIndex = value.indexOf('#');
-            if (fragmentIndex != -1) {
-              fragment = value.substr(fragmentIndex);
-              value = value.substr(0, fragmentIndex);
-            }
-            var format = (value.length > 7) ? (value.substr(value.length - 7, 7) == '/$value' ? '' : '&$format=json' ) : '';
-            format = (value.length > 10) ? (value.substr(value.length - 10, 10) == '/$metadata' ? '' : '&$format=json' ) : '';
-            var separator = (value.indexOf('?') == -1) ? '?' : '&';
-            return '<span class="string">"<a href="' + value + separator + 'sap-ds-debug=true' + format + fragment + '">' + encodeHtml(value) + encodeHtml(fragment) + '</a>"</span>';
-          } else {
-            return '<span class="string">"' + encodeHtml(value) + '"</span>'
-          }
-        } else if (typeofValue == 'boolean') {
-          return '<span class="boolean">' + encodeHtml(value) + '</span>'
-        } else if (value && value.constructor == Array) {
-          return formatArray(value);
-        } else if (typeofValue == 'object') {
-          return formatObject(value);
-        } else {
-          return '';
-        }
-        function formatArray(json) {
-          var html = '';
-          for ( var prop in json)
-            html += '<li>' + formatJSON(json[prop]) + '</li>';
-          return (html) ? '<span class="array">[</span><ul class="array list">' + html + '</ul><span class="array">]</span>' : '<span class="array">[]</span>'
-        }
-        function formatObject(json) {
-          var html = '';
-          for ( var prop in json)
-            html += '<li><span class="property">' + encodeHtml(prop) + '</span>: ' + formatJSON(json[prop]) + '</li>';
-          return (html) ? '<span class="obj">{</span><ul class="obj list">' + html + '</ul><span class="obj">}</span>' : '<span class="obj">{}</span>';
-        }
-      }
-      /* convert xml to html */
-      function formatXML(document) {
-        return formatElement(document.documentElement);
-        function formatElement(element) {
-          var html = '<span>&lt;</span><span class="tag">' + encodeHtml(element.nodeName) + '</span>';
-          if (element.attributes && element.attributes.length > 0) {
-           html += formatAttributes(element);
-          }
-          if (element.childNodes && element.childNodes.length > 0) {
-            html += '<span>&gt;</span>';
-            if (element.childNodes.length == 1 && element.childNodes[0].nodeType == 3) {
-              html += '<span class="text">' + encodeHtml(element.childNodes[0].nodeValue) + '</span>';
-            } else {
-              html += formatChildNodes(element.childNodes);                    
-            } 
-            html += '<span>&lt;/</span><span class="tag">' + encodeHtml(element.nodeName) + '</span><span>&gt;</span>';
-          } else {
-            html += '<span>/&gt;</span>';
-          } 
-          return html;                
-        }
-        function formatChildNodes(childNodes) {
-          html = '<ul class="list">';
-          for ( var i = 0; i < childNodes.length; i++) {
-            var node = childNodes[i];
-            if (node.nodeType == 1) {
-              html += '<li>' + formatElement(node) + '</li>';
-            } else if (node.nodeType == 3 && !/^\s+$/.test(node.nodeValue)) {
-              html += '<li><span class="text">' + encodeHtml(node.nodeValue) + '</span></li>';
-            } else if (node.nodeType == 4) {
-              html += '<li><span class="cdata">&lt;![CDATA[' + encodeHtml(node.nodeValue) + ']]&gt;</span></li>';
-            } else if (node.nodeType == 8) {
-              html += '<li><span class="comment">&lt;!--' + encodeHtml(node.nodeValue) + '--&gt;</span></li>';
-            }
-          }
-          html += '</ul>';
-          return html;
-        }
-        function formatAttributes(element) {
-          var html = '';
-          for (var i = 0; i < element.attributes.length; i++) {
-            var attribute = element.attributes[i];
-            if (/^xmlns:[^\s]+$/.test(attribute.nodeName)) {
-              html += ' <span class="ns">' + encodeHtml(attribute.nodeName) + '="' + encodeHtml(attribute.nodeValue) + '"</span>';
-            } else {
-              html += ' <span class="atn">' + encodeHtml(attribute.nodeName) + '</span>=';
-              if (attribute.nodeName == 'href' || attribute.nodeName == 'src') {
-                var separator = (attribute.nodeValue.indexOf('?') == -1) ? '?' : '&';
-                var href = (element.baseURI && attribute.nodeValue[0] != '/') ? element.baseURI + attribute.nodeValue : attribute.nodeValue;
-                html += '"<a class="link" href="' + href + separator + 'sap-ds-debug=true">' + encodeHtml(attribute.nodeValue) + '</a>"';                    
-              } else {
-                html += '"<span class="atv">' + encodeHtml(attribute.nodeValue) + '</span>"';
-              }                
-            }   
-          }
-          return html;
-        }
-      }
-    });
-  };
-})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/tester.html
----------------------------------------------------------------------
diff --git a/datajs/demo/tester.html b/datajs/demo/tester.html
deleted file mode 100644
index 512b9e1..0000000
--- a/datajs/demo/tester.html
+++ /dev/null
@@ -1,217 +0,0 @@
-<html>
-    <head>
-        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
-        <title>datajs startup perf test</title>
-        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
-        <script type="text/javascript" src="./scripts/odatajs-4.0.0-beta-01.js"></script>
-        <script type="text/javascript" src="./scripts/tools.js" ></script>
-        <style type="text/css">
-            .code{font-family:"Courier New",monospace;font-size:13px;line-height:18px;}
-            .code ul{list-style:none;margin:0 0 0 1.5em;padding:0;}
-            .code li{position:relative;}
-            .code.json li:after{content:',';}
-            .code.json li:last-child:after{content:'';}
-            .code span{white-space:nowrap;padding:2px 1px;}
-            .code .property{font-weight:bold;color:#000000;}
-            .code .null{color:#9d261d;}
-            .code .boolean{color:#760a85;}
-            .code .numeric{color:#0076cb;}
-            .code .string{color:#247230;}
-            .code .deffered{color:#666666;font-size:0.9em;}
-            .code .toggle{position:absolute;left:-1em;cursor:pointer;}
-            .code .tag{color:#003283;}
-            .code .atn{color:#760a85;}
-            .code .atv{color:#247230;}
-            .code .text{color:#000000;}
-            .code .cdata{color:#008080;}
-            .code .comment,.code .ns{color:#666666;}
-
-            .left {
-                margin-left : 20px;
-                position:relative;
-            }
-
-        </style>
-    </head>   
-    <body>
-        <table><tr><td valign="top" width="150px">
-            Metadata<br>
-            <input type="radio" id="inMetadata1" name="inMetadata" value="none"/>                       
-            <label for="inMetadata1">none</label><br>
-
-            <input type="radio" id="inMetadata2" name="inMetadata" value="minimal" checked="checked"/>  
-            <label for="inMetadata2">minimal<br>
-            <div class="left">                                   
-                <input type="checkbox" id="inMinimalToFull">                                   
-                <label for="inMinimalToFull" id="lblInMinimalToFull">minimal to full</label><br>
-            </div>
-
-            <input type="radio" id="inMetadata3" name="inMetadata" value="full"><label for="inMetadata3">full</label>
-            <br>
-            Recognize Dates<br>
-            <input type="checkbox" id="inRecognizeDates"><label for="check1">yes/no</label><br>
-
-        </td><td>
-            <div id="buttons"></div>
-        </td><td>
-            <button id="btnMetaData">MetaData</button><br/>
-            <button id="btnPOST_entry_food">POST food entry</button><br/>
-            <button id="btnPOST_entry_categorie">POST categorie entry</button><br/>
-        </td></tr></table>
-        <div id='resultsArea' data-type="json">
-        </div>
-        <script>
-            // Config
-            var config = [
-                { name: 'Feed', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods'},
-                { name: 'Entry', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)'},
-                { name: 'Collection of Complex', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Providers'},
-                { name: 'Collection of Simple', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/AlternativeNames'},
-                { name: 'Complex property', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Packaging'},
-                { name: 'Simple property', url: 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods(0)/Name'},
-            ];
-
-            // UI Stuff
-            var createButtonClickHandler = function(nr) {
-                return function() { buttonClick(nr);};
-            };
-
-            var buttonRoot = $('#buttons');
-            $("input[name*='inMetadata'").click( function() {
-                var metadata = $("input[name*='inMetadata']:checked").val();
-                if (metadata === "minimal") {
-                    $("#lblInMinimalToFull").css('color', '#000000');
-                    $("#inMinimalToFull").removeAttr('disabled');
-                } else {
-                    $("#lblInMinimalToFull").css('color', '#999999');
-                    $("#inMinimalToFull").attr('disabled','disabled');
-                }
-            });
-
-            for (var i = 0; i < config.length; i++) {
-                var button = $('<button id="btnArray">'+config[i].name+'</button><br/>"');
-                button.click( createButtonClickHandler(i));
-                buttonRoot.append(button);
-            }
-
-            // Testing 
-            function buttonClick(configNr) {
-                var metadata = $("input[name*='inMetadata']:checked").val();
-                var recognizeDates  = ($("#inRecognizeDates").val() ==='on') ? true : false;
-                var inMinimalToFull = ($("#inMinimalToFull").val() ==='on') ? true : false;
-
-                var requestUri = {
-                    requestUri : config[configNr].url
-                };
-
-                requestUri.recognizeDates = recognizeDates;
-
-                var metaDatasuccess = function(metadata){
-                    odatajs.oData.read(requestUri, success, errorFunc, null, null, metadata);
-                };
-
-                if ( metadata === 'full') {
-                    requestUri.headers =  { Accept : 'application/json;odata.metadata=full' };
-                    odatajs.oData.read(requestUri, success, errorFunc);
-                } else if ( metadata === 'minimal') {
-                    requestUri.headers =  { Accept : 'application/json;odata.metadata=minimal' };
-                    if (inMinimalToFull) {
-                        getMetaData(metaDatasuccess);
-                    } else {
-                        odatajs.oData.read(requestUri, success, errorFunc);   
-                    }
-                } else {
-                    requestUri.headers =  { Accept : 'application/json;odata.metadata=none' };
-                    odatajs.oData.read(requestUri, success, errorFunc);
-                }
-            }
-
-            function show(data) {
-                $('#resultsArea').empty();
-                var code = $('<code data-type="json"></code>').text(JSON.stringify(data));
-                $('#resultsArea').append(code);
-                $('code[data-type]').prettify();
-            }
-            function success(data) {
-                show(data);
-            }
-
-            function errorFunc(err) {
-                $('#resultsArea').empty();
-                $("#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,
-                };
-                odatajs.oData.read(metadataRequest, metaDatasuccess, errorFunc,odatajs.oData.metadataHandler);
-            }
-
-            /*******Special buttons***********/           
-
-            $('#btnMetaData').on("click", function(){
-                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,
-                };
-
-                odatajs.oData.read(metadataRequest, success, errorFunc,odatajs.oData.metadataHandler);
-            });
-
-            $('#btnPOST_entry_food').on("click", function(){
-                var requestUri = {
-                    requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
-                    method: 'POST',
-                    headers : { Accept : 'application/json' },
-                    recognizeDates : true,
-                    data : {
-                        "@odata.type": "#DataJS.Tests.V4.Food",
-                        "@odata.context": "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Foods/$entity",
-                        FoodID: 111,
-                        Name: "flour1"
-                    }
-                };
-                odatajs.oData.read(requestUri, success, errorFunc);
-            });
-            $('#btnPOST_entry_categorie').on("click", function(){
-
-                var requestUri = {
-                    requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Categories',
-                    method: 'POST',
-                    headers : { Accept : 'application/json' },
-                    recognizeDates : true,
-                    data : {
-                        "@odata.type": "#DataJS.Tests.V4.Category",
-                        "@odata.context": "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity",
-                        CategoryID: 111,
-                        Name: "cat111"
-                    }
-                };
-                odatajs.oData.read(requestUri, success, errorFunc);
-            });
-
-
-
-        </script>
-    </body>
-</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/testerV2.html
----------------------------------------------------------------------
diff --git a/datajs/demo/testerV2.html b/datajs/demo/testerV2.html
deleted file mode 100644
index b9bf1c8..0000000
--- a/datajs/demo/testerV2.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<html>
-    <head>
-        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
-        <title>datajs startup perf test</title>
-        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
-        <script type="text/javascript" src="./scripts/datajs-1.1.2.js"></script>
-        <script type="text/javascript" src="./scripts/tools.js" ></script>
-        <style type="text/css">
-            .code{font-family:"Courier New",monospace;font-size:13px;line-height:18px;}
-            .code ul{list-style:none;margin:0 0 0 1.5em;padding:0;}
-            .code li{position:relative;}
-            .code.json li:after{content:',';}
-            .code.json li:last-child:after{content:'';}
-            .code span{white-space:nowrap;padding:2px 1px;}
-            .code .property{font-weight:bold;color:#000000;}
-            .code .null{color:#9d261d;}
-            .code .boolean{color:#760a85;}
-            .code .numeric{color:#0076cb;}
-            .code .string{color:#247230;}
-            .code .deffered{color:#666666;font-size:0.9em;}
-            .code .toggle{position:absolute;left:-1em;cursor:pointer;}
-            .code .tag{color:#003283;}
-            .code .atn{color:#760a85;}
-            .code .atv{color:#247230;}
-            .code .text{color:#000000;}
-            .code .cdata{color:#008080;}
-            .code .comment,.code .ns{color:#666666;}
-        </style>
-    </head>   
-    <body>
-        <button id="btnMetaData">MetaData</button><br/>
-        <button id="btnJSON_minimal">pure JSON</button><br/>
-
-        <div id='resultsArea'>
-
-        </div>
-        <script>
-            function show(data) {
-                $('#resultsArea').empty();
-                var code = $('<code data-type="json"></code>').text(JSON.stringify(data))
-                $('#resultsArea').append(code);
-                $('code[data-type]').prettify();
-            }
-            function success(data) {
-                show(data);
-            }
-
-            function errorFunc(err) {
-                $('#resultsArea').empty();
-                $("#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);
-            });
-            
-            $('#btnJSON_minimal').on("click", function(){
-                var requestUri ='http://localhost:4003/sap/bc/odata/Employees?$format=json';
-                OData.read(requestUri, success, errorFunc);
-            });
-
-        </script>
-    </body>
-</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/browserify_transforms/stripheader/package.json
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/browserify_transforms/stripheader/package.json b/datajs/grunt-config/browserify_transforms/stripheader/package.json
deleted file mode 100644
index b8837af..0000000
--- a/datajs/grunt-config/browserify_transforms/stripheader/package.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "name": "grunt-rat",
-  "version": "0.0.1",
-  "description": "Transform vor removing license headers",
-  "license": "Apache",
-  "author": {
-    "name": "Sven Kobler-Morris",
-    "email": "koblers@apache.org"
-  },
-  "files": [
-    "tasks"
-  ],
-  "dependencies": {
-    "through": "^2.3.4"
-  },
-  "devDependencies": {
-  },
-  "peerDependencies": {
-    "grunt": "~0.4.0"
-  },
-  "engines": {
-    "node": ">=0.8.0"
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/browserify_transforms/stripheader/stripheader.js
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/browserify_transforms/stripheader/stripheader.js b/datajs/grunt-config/browserify_transforms/stripheader/stripheader.js
deleted file mode 100644
index 7df58cb..0000000
--- a/datajs/grunt-config/browserify_transforms/stripheader/stripheader.js
+++ /dev/null
@@ -1,21 +0,0 @@
-var through = require('through');
-
-module.exports = function (file) {
-  //if (/\.json$/.test(file)) return through();
-
-  var data = "";
-
-  return through(
-    function (buf) { data += buf;    },
-    function () {
-      try {
-        var out = data.replace(/^(\/\*(.|\n|\r)*?\*\/)/gi,"");
-        this.queue(out);
-      } catch (er) {
-        this.emit("error", new Error(er.toString().replace("Error: ", "") + " (" + file + ")"));
-      }
-      this.queue(null);
-    }
-  );
-};
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/custom-tasks/rat/package.json
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/custom-tasks/rat/package.json b/datajs/grunt-config/custom-tasks/rat/package.json
deleted file mode 100644
index 6753173..0000000
--- a/datajs/grunt-config/custom-tasks/rat/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "name": "grunt-rat",
-  "version": "0.0.1",
-  "description": "Run Apache Rat(release audit tool)",
-  "license": "Apache",
-  "author": {
-    "name": "Sven Kobler-Morris",
-    "email": "koblers@apache.org"
-  },
-  "files": [
-    "tasks"
-  ],
-  "dependencies": {
-    "chalk": "~0.4.0"
-  },
-  "devDependencies": {
-    "grunt": "~0.4.0",
-    "xml2js": "^0.4.4"
-  },
-  "peerDependencies": {
-    "grunt": "~0.4.0"
-  },
-  "engines": {
-    "node": ">=0.8.0"
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/custom-tasks/rat/readme.md
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/custom-tasks/rat/readme.md b/datajs/grunt-config/custom-tasks/rat/readme.md
deleted file mode 100644
index 2921499..0000000
--- a/datajs/grunt-config/custom-tasks/rat/readme.md
+++ /dev/null
@@ -1,2 +0,0 @@
-require http://creadur.apache.org/rat/download_rat.cgi --> apache-rat-0.10-bin.zip
-to be upacked to /tools/apache-rat-0.10-bin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/custom-tasks/rat/tasks/rat.js
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/custom-tasks/rat/tasks/rat.js b/datajs/grunt-config/custom-tasks/rat/tasks/rat.js
deleted file mode 100644
index 8c6e8b0..0000000
--- a/datajs/grunt-config/custom-tasks/rat/tasks/rat.js
+++ /dev/null
@@ -1,93 +0,0 @@
-'use strict';
-
-module.exports = function (grunt) {
-  grunt.registerMultiTask('rat', 'Run Apache Rat', function () {
-    var path = require('path');
-    var chalk = require('chalk');
-    var childProcess = require('child_process');
-    var xml2js = require('xml2js');
-    var fs = require('fs');
-
-    var cb = this.async();
-
-    var options = this.options({ xml : true, tmpDir : './build/tmp'});
-    var dir = this.data.dir;
-    var out = options.tmpDir + '/' + (options.xml ? 'rat.xml' : 'rat.txt');
-
-    var pathToRat =  path.resolve(__dirname,'./../tools/apache-rat-0.10/apache-rat-0.10.jar');
-    
-    //sample command java -jar apache-rat-0.10.jar -x -d ./src > ./build/tmp/rat.txt
-    var cmd = 'java -jar ' + pathToRat+ ' ';
-    cmd += options.xml ? ' -x' : '';
-    cmd += ' --force -d ' + dir + ' > ' + out;
-
-    grunt.verbose.writeln('Directory: '+dir);
-
-    var cp = childProcess.exec(cmd, options.execOptions, function (err, stdout, stderr) {
-      if (err) {
-        grunt.fail.warn('rat --> ' + err, 1); //exit grunt with error code 1
-      }
-      
-      
-      
-      if (!options.xml) {
-        grunt.fail.warn('rat --> ' + 'No XML output: checkRatLogFile skipped!', 1); 
-      }
-
-      var xml = grunt.file.read(out);
-      var parser = new xml2js.Parser();
-
-      parser.parseString(xml, function (err, result) {
-
-          if (err) {
-            grunt.fail.warn('rat --> ' + err, 1); 
-          }
-          
-          if (checkRatLogFile(result)) {
-            grunt.fail.warn('rat --> ' + 'Missing or Invalied license header detected ( see "'+out+'")', 1);
-          }
-
-          
-      });
-      cb(); 
-      
-    }.bind(this));
-
-    var checkRatLogFile = function(result) {
-
-      var list = result['rat-report']['resource'];
-      for (var i = 0; i < list.length; i++ ){
-        var item = list[i];
-
-        var headerType = list[i]['header-type'];
-        var attr = headerType[0]['$'];
-        if (attr.name.trim() !== 'AL') {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    var captureOutput = function (child, output) {
-      if (grunt.option('color') === false) {
-        child.on('data', function (data) {
-          output.write(chalk.stripColor(data));
-        });
-      } else {
-        child.pipe(output);
-      }
-    };
-
-    grunt.verbose.writeln('Command:', chalk.yellow(cmd));
-
-    captureOutput(cp.stdout, process.stdout);
-      captureOutput(cp.stderr, process.stderr);
-
-    if (options.stdin) {
-      process.stdin.resume();
-      process.stdin.setEncoding('utf8');
-      process.stdin.pipe(cp.stdin);
-    }
-  });
-};
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/grunt-config/rat-config.js
----------------------------------------------------------------------
diff --git a/datajs/grunt-config/rat-config.js b/datajs/grunt-config/rat-config.js
deleted file mode 100644
index 06f5b7d..0000000
--- a/datajs/grunt-config/rat-config.js
+++ /dev/null
@@ -1,15 +0,0 @@
-module.exports = function(grunt) {
-  grunt.config('rat', {
-    options: { xml : true, tmpDir : './build/tmp' },
-    src: {                      
-      dir: './src',
-    },
-    test: {                      
-      dir: './tests'
-    },
-  });
-
- 
-  grunt.loadTasks('grunt-config/custom-tasks/rat/tasks');
-  grunt.registerTask('custom-license-check',['rat:src','rat:test']);
-};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/package.json
----------------------------------------------------------------------
diff --git a/datajs/package.json b/datajs/package.json
deleted file mode 100644
index 18eee26..0000000
--- a/datajs/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "name": "odatajs",
-  "postfix" : "beta-01",
-  "title": "Olingo OData Client for Java Script",
-  "version": "4.0.0",
-  "description": "odatajs is a new cross-browser JavaScript library that enables data-centric web applications by leveraging modern protocols such as JSON and OData and HTML5-enabled browser features. It's designed to be small, fast and easy to use.",
-  "homepage": "http://olingo.apache.org",
-  "main": "index.js",
-  "repository": {
-    "type": "git",
-    "url": "http://git-wip-us.apache.org/repos/asf/olingo-odata4-js.git"
-  },
-  "engines": {
-    "node": ">= 0.10.0"
-  },
-  "contributors": [
-    {
-      "name": "Bing Li",
-      "email": "bingl@apache.org"
-    },
-    {
-      "name": "Sven Kobler-Morris",
-      "email": "koblers@apache.org"
-    }
-  ],
-  "scripts": {},
-  "devDependencies": {
-    "browserify": "^4.1.5",
-    "grunt": "^0.4.5",
-    "grunt-browserify": "^2.1.0",
-    "grunt-connect-proxy": "^0.1.10",
-    "grunt-contrib-clean": "^0.6.0",
-    "grunt-contrib-compress": "^0.10.0",
-    "grunt-contrib-concat": "^0.5.0",
-    "grunt-contrib-connect": "^0.7.1",
-    "grunt-contrib-copy": "^0.5.0",
-    "grunt-contrib-uglify": "^0.4.0",
-    "grunt-jsdoc": "^0.5.6",
-    "grunt-node-qunit": "^2.0.2",
-    "through": "^2.3.4"
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/packages.config
----------------------------------------------------------------------
diff --git a/datajs/packages.config b/datajs/packages.config
deleted file mode 100644
index 9e7480b..0000000
--- a/datajs/packages.config
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="Microsoft.OData.Client" version="6.5.0" targetFramework="net40" />
-  <package id="Microsoft.OData.Core" version="6.5.0" targetFramework="net40" />
-  <package id="Microsoft.OData.Edm" version="6.5.0" targetFramework="net40" />
-  <package id="Microsoft.Spatial" version="6.5.0" targetFramework="net40" />
-</packages>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/readme.md
----------------------------------------------------------------------
diff --git a/datajs/readme.md b/datajs/readme.md
deleted file mode 100644
index bcd2560..0000000
--- a/datajs/readme.md
+++ /dev/null
@@ -1,20 +0,0 @@
-Development
-===========
-
-Preparation 
-1.  npm install -g grunt-cli
-
-Installation
-1.  git clone https://git-wip-us.apache.org/repos/asf/olingo-odata4-js
-1.  cd datajs
-1.  npm install
-
-Build datajs-x.x.x.js
-1.  grunt build
-*   Output is copied into the directory ...
-
-Run demo
-1.  grunt run
-
-Run tests
-1.  grunt test

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/banner.txt
----------------------------------------------------------------------
diff --git a/datajs/src/banner.txt b/datajs/src/banner.txt
deleted file mode 100644
index edbaff2..0000000
--- a/datajs/src/banner.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/index.js
----------------------------------------------------------------------
diff --git a/datajs/src/index.js b/datajs/src/index.js
deleted file mode 100644
index fa4203d..0000000
--- a/datajs/src/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-var odatajs = require('./lib/datajs.js');
-
-odatajs.oData = require('./lib/odata.js');
-odatajs.store = require('./lib/store.js');
-odatajs.cache = require('./lib/cache.js');
-
-if (typeof window !== 'undefined') {
-    //expose to browsers window object
-    window.odatajs = odatajs;
-} else {
-    //expose in commonjs style
-    odatajs.node = "node";
-    module.exports = odatajs;
-}


[49/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/datajs-1.1.1.min.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/datajs-1.1.1.min.js b/datajs/demo/scripts/datajs-1.1.1.min.js
deleted file mode 100644
index 0d862a1..0000000
--- a/datajs/demo/scripts/datajs-1.1.1.min.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) Microsoft.  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.
-
-(function(n,t){var pt=n.datajs||{},r=n.OData||{},co,lo,ei,ly,ip;typeof define=="function"&&define.amd?(define("datajs",pt),define("OData",r)):(n.datajs=pt,n.OData=r),pt.version={major:1,minor:1,build:1};var bo=function(t){return n.ActiveXObject?new n.ActiveXObject(t):null},ot=function(n){return n!==null&&n!==t},fr=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return!0;return!1},it=function(n,i){return n!==t?n:i},o=function(t){if(arguments.length===1){n.setTimeout(t,0);return}var i=Array.prototype.slice.call(arguments,1);n.setTimeout(function(){t.apply(this,i)},0)},g=function(n,t){for(var i in t)n[i]=t[i];return n},er=function(n,t){if(n)for(var i=0,r=n.length;i<r;i++)if(t(n[i]))return n[i];return null},e=function(n){return Object.prototype.toString.call(n)==="[object Array]"},cf=function(n){return Object.prototype.toString.call(n)==="[object Date]"},lf=function(n){return typeof n=="object"},s=function(n){return parseInt(n,10)},iu=function(n,t,i){n.hasOwnProperty(t)&&(n[
 i]=n[t],delete n[t])},ru=function(n){throw n;},ko=function(n){return n.trim?n.trim():n.replace(/^\s+|\s+$/g,"")},af=function(n,i){return n!==t?n:i},rp=/^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/,go=["scheme","authority","path","query","fragment"],vf=function(n){var i={isAbsolute:!1},r,t,u;if(n){if(r=rp.exec(n),r)for(t=0,u=go.length;t<u;t++)r[t+1]&&(i[go[t]]=r[t+1]);i.scheme&&(i.isAbsolute=!0)}return i},ns=function(n){return"".concat(n.scheme||"",n.authority||"",n.path||"",n.query||"",n.fragment||"")},up=/^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/,fp=/%[0-9A-F]{2}/ig,ep=function(n){var i=vf(n),r=i.scheme,u=i.authority,t;return r&&(i.scheme=r.toLowerCase(),u&&(t=up.exec(u),t&&(i.authority="//"+(t[1]?t[1]+"@":"")+t[2].toLowerCase()+(t[3]?":"+t[3]:"")))),n=ns(i),n.replace(fp,function(n){return n.toLowerCase()})},c=function(n,t){var i,u,r,f;return t?(i=vf(n),i.isAbsolute)?n:(u=vf(t),r={},i.authority?(r.authority=i.authority,f=i.path,r.query=i.query):(i.path?(f=i.path.charA
 t(0)==="/"?i.path:op(i.path,u.path),r.query=i.query):(f=u.path,r.query=i.query||u.query),r.authority=u.authority),r.path=sp(f),r.scheme=u.scheme,r.fragment=i.fragment,ns(r)):n},op=function(n,t){var i="/",r;return t&&(r=t.lastIndexOf("/"),i=t.substring(0,r),i.charAt(i.length-1)!=="/"&&(i=i+"/")),i+n},sp=function(n){for(var t="",r="",i;n;)n.indexOf("..")===0||n.indexOf(".")===0?n=n.replace(/^\.\.?\/?/g,""):n.indexOf("/..")===0?(n=n.replace(/^\/\..\/?/g,"/"),i=t.lastIndexOf("/"),t=i===-1?"":t.substring(0,i)):n.indexOf("/.")===0?n=n.replace(/^\/\.\/?/g,"/"):(r=n,i=n.indexOf("/",1),i!==-1&&(r=n.substring(0,i)),t=t+r,n=n.replace(r,""));return t},hp=function(i){var r=[],o,u,f,s,e,h;if(n.atob===t)r=cp(i);else for(o=n.atob(i),u=0;u<o.length;u++)r.push(o.charCodeAt(u));for(f="",s="0123456789ABCDEF",e=0;e<r.length;e++)h=r[e],f+=s[h>>4],f+=s[h&15];return f},cp=function(n){for(var i="",r,u,f,e,o,t=0;t<n.length;t++)r=lp(n[t]),u="",r!==null&&(u=r.toString(2),i+=ap(u));for(f=[],e=parseInt(i.length/
 8,10),t=0;t<e;t++)o=parseInt(i.substring(t*8,(t+1)*8),2),f.push(o);return f},lp=function(n){var t=n.charCodeAt(0),i=65,r=6;return t>=65&&t<=90?t-i:t>=97&&t<=122?t-i-r:t>=48&&t<=57?t+4:n=="+"?62:n=="/"?63:null},ap=function(n){while(n.length<6)n="0"+n;return n},uu="http://",or=uu+"www.w3.org/",ts=or+"1999/xhtml",sr=or+"2000/xmlns/",yi=or+"XML/1998/namespace",is=uu+"www.mozilla.org/newlayout/xml/parsererror.xml",vp=function(n){var t=/(^\s)|(\s$)/;return t.test(n)},yp=function(n){var t=/^\s*$/;return n===null||t.test(n)},pp=function(n){while(n!==null&&n.nodeType===1){var t=st(n,"space",yi);if(t==="preserve")return!0;if(t==="default")break;else n=n.parentNode}return!1},wp=function(n){var t=n.nodeName;return t=="xmlns"||t.indexOf("xmlns:")===0},fu=function(n,t,i){try{n.setProperty(t,i)}catch(r){}},bp=function(){var n=bo("Msxml2.DOMDocument.3.0");return n&&(fu(n,"ProhibitDTD",!0),fu(n,"MaxElementDepth",256),fu(n,"AllowDocumentFunction",!1),fu(n,"AllowXsltScript",!1)),n},rs=function(){try{v
 ar n=bo("Msxml2.DOMDocument.6.0");return n&&(n.async=!0),n}catch(t){return bp()}},kp=function(n){var t=rs(),i;return t?(t.loadXML(n),i=t.parseError,i.errorCode!==0&&hr(i.reason,i.srcText,n),t):null},hr=function(n,t,i){typeof n=="string"&&(n={message:n});throw g(n,{srcText:t||"",errorXmlText:i||""});},eu=function(t){var s=n.DOMParser&&new n.DOMParser,r,e,l;if(!s)return r=kp(t),r||hr("XML DOM parser not supported"),r;try{r=s.parseFromString(t,"text/xml")}catch(v){hr(v,"",t)}var i=r.documentElement,h=i.namespaceURI,c=f(i);if(c==="parsererror"&&h===is&&(e=b(i,is,"sourcetext"),l=e?bi(e):"",hr(k(i)||"",l,t)),c==="h3"&&h===ts||nw(i,ts,"h3")){for(var o="",a=[],u=i.firstChild;u;)u.nodeType===1&&(o+=k(u)||""),a.push(u.nextSibling),u=u.firstChild||a.shift();o+=k(i)||"",hr(o,"",t)}return r},wt=function(n,t){return n?n+":"+t:t},dp=function(n,t){if(vp(t.data)){var i=wi(n,yi,"space");i||(i=si(n.ownerDocument,yi,wt("xml","space")),l(n,i)),i.value="preserve"}return n.appendChild(t),n},pi=function(n,
 t){for(var r=n.attributes,i=0,u=r.length;i<u;i++)t(r.item(i))},st=function(n,t,i){var r=wi(n,t,i);return r?bi(r):null},wi=function(n,t,i){var r=n.attributes;return r.getNamedItemNS?r.getNamedItemNS(i||null,t):r.getQualifiedItem(t,i)||null},rt=function(n,t){var i=wi(n,"base",yi);return(i?c(i.value,t):t)||null},p=function(n,t){yf(n,!1,function(n){return n.nodeType===1&&t(n),!0})},us=function(n,t,i){for(var u=i.split("/"),r=0,f=u.length;r<f;r++)n=n&&b(n,t,u[r]);return n||null},gp=function(n,t,i){var f=i.lastIndexOf("/"),r=i.substring(f+1),e=i.substring(0,f),u=e?us(n,t,e):n;return u?r.charAt(0)==="@"?wi(u,r.substring(1),t):b(u,t,r):null},b=function(n,t,i){return fs(n,t,i,!1)},nw=function(n,t,i){if(n.getElementsByTagNameNS){var r=n.getElementsByTagNameNS(t,i);return r.length>0?r[0]:null}return fs(n,t,i,!0)},fs=function(n,t,i,r){var e=null;return yf(n,r,function(n){if(n.nodeType===1){var r=!t||u(n)===t,o=!i||f(n)===i;r&&o&&(e=n)}return e===null}),e},k=function(n){var i=null,r=n.nodeType==
 =9&&n.documentElement?n.documentElement:n,f=r.ownerDocument.preserveWhiteSpace===!1,u;return yf(r,!1,function(n){if(n.nodeType===3||n.nodeType===4){var e=bi(n),o=f||!yp(e);o||(u===t&&(u=pp(r)),o=u),o&&(i?i+=e:i=e)}return!0}),i},f=function(n){return n.localName||n.baseName},u=function(n){return n.namespaceURI||null},bi=function(n){return n.nodeType===1?k(n):n.nodeValue},yf=function(n,t,i){for(var f=[],r=n.firstChild,u=!0;r&&u;)u=i(r),u&&(t&&r.firstChild&&f.push(r.firstChild),r=r.nextSibling||f.shift())},tw=function(n,t,i){for(var r=n.nextSibling,e,o;r;){if(r.nodeType===1&&(e=!t||u(r)===t,o=!i||f(r)===i,e&&o))return r;r=r.nextSibling}return null},es=function(){var t=n.document.implementation;return t&&t.createDocument?t.createDocument(null,null,null):rs()},ou=function(n,t){if(!e(t))return l(n,t);for(var i=0,r=t.length;i<r;i++)t[i]&&l(n,t[i]);return n},l=function(n,t){if(t){if(typeof t=="string")return dp(n,rw(n.ownerDocument,t));t.nodeType===2?n.setAttributeNodeNS?n.setAttributeNodeNS
 (t):n.setAttributeNode(t):n.appendChild(t)}return n},si=function(n,i,r,u){var f=n.createAttributeNS&&n.createAttributeNS(i,r)||n.createNode(2,r,i||t);return f.value=u||"",f},cr=function(n,i,r,u){var f=n.createElementNS&&n.createElementNS(i,r)||n.createNode(1,r,i||t);return ou(f,u||[])},os=function(n,t,i){return si(n,sr,wt("xmlns",i),t)},iw=function(n,t){for(var f="<c>"+t+"<\/c>",e=eu(f),r=e.documentElement,o=("importNode"in n)?n.importNode(r,!0):r,u=n.createDocumentFragment(),i=o.firstChild;i;)u.appendChild(i),i=i.nextSibling;return u},rw=function(n,t){return n.createTextNode(t)},uw=function(n,t,i,r,u){for(var f="",h=u.split("/"),c=b,a=cr,o=t,e,s=0,v=h.length;s<v;s++)f=h[s],f.charAt(0)==="@"&&(f=f.substring(1),c=wi,a=si),e=c(o,i,f),e||(e=a(n,i,wt(r,f)),l(o,e)),o=e;return o},pf=function(t){var i=n.XMLSerializer,r;if(i)return r=new i,r.serializeToString(t);if(t.xml)return t.xml;throw{message:"XML serialization unsupported"};},fw=function(n){var f=n.childNodes,t,r=f.length,i;if(r===0)r
 eturn"";var e=n.ownerDocument,o=e.createDocumentFragment(),u=e.createElement("c");for(o.appendChild(u),t=0;t<r;t++)u.appendChild(f[t]);for(i=pf(o),i=i.substr(3,i.length-7),t=0;t<r;t++)n.appendChild(u.childNodes[t]);return i},vit=function(i){var r=i.xml,u;if(r!==t)return r;if(n.XMLSerializer)return u=new n.XMLSerializer,u.serializeToString(i);throw{message:"XML serialization unsupported"};},ew=function(n,t,i){return function(){return n[t].apply(n,arguments),i}},ki=function(){this._arguments=t,this._done=t,this._fail=t,this._resolved=!1,this._rejected=!1};ki.prototype={then:function(n,t){return n&&(this._done?this._done.push(n):this._done=[n]),t&&(this._fail?this._fail.push(t):this._fail=[t]),this._resolved?this.resolve.apply(this,this._arguments):this._rejected&&this.reject.apply(this,this._arguments),this},resolve:function(){if(this._done){for(var n=0,i=this._done.length;n<i;n++)this._done[n].apply(null,arguments);this._done=t,this._resolved=!1,this._arguments=t}else this._resolved=
 !0,this._arguments=arguments},reject:function(){if(this._fail){for(var n=0,i=this._fail.length;n<i;n++)this._fail[n].apply(null,arguments);this._fail=t,this._rejected=!1,this._arguments=t}else this._rejected=!0,this._arguments=arguments},promise:function(){var n={};return n.then=ew(this,"then",n),n}};var su=function(){return n.jQuery&&n.jQuery.Deferred?new n.jQuery.Deferred:new ki},ss=function(n,t){var i=(n&&n.__metadata||{}).type;return i||(t?t.type:null)},v="Edm.",hs=v+"Binary",cs=v+"Boolean",ls=v+"Byte",hu=v+"DateTime",cu=v+"DateTimeOffset",as=v+"Decimal",vs=v+"Double",ys=v+"Guid",ps=v+"Int16",ws=v+"Int32",bs=v+"Int64",ks=v+"SByte",ds=v+"Single",lr=v+"String",lu=v+"Time",ht=v+"Geography",gs=ht+"Point",nh=ht+"LineString",th=ht+"Polygon",ih=ht+"Collection",rh=ht+"MultiPolygon",uh=ht+"MultiLineString",fh=ht+"MultiPoint",et=v+"Geometry",eh=et+"Point",oh=et+"LineString",sh=et+"Polygon",hh=et+"Collection",ch=et+"MultiPolygon",lh=et+"MultiLineString",ah=et+"MultiPoint",wf="Point",bf="Li
 neString",kf="Polygon",df="MultiPoint",gf="MultiLineString",ne="MultiPolygon",te="GeometryCollection",ow=[lr,ws,bs,cs,vs,ds,hu,cu,lu,as,ys,ls,ps,ks,hs],sw=[et,eh,oh,sh,hh,ch,lh,ah],hw=[ht,gs,nh,th,ih,rh,uh,fh],hi=function(n,t){if(!n)return null;if(e(n)){for(var r,i=0,u=n.length;i<u;i++)if(r=hi(n[i],t),r)return r;return null}return n.dataServices?hi(n.dataServices.schema,t):t(n)},vh=function(n,t){return n=n===0?"":"."+a(n.toString(),3),t>0&&(n===""&&(n=".000"),n+=a(t.toString(),4)),n},yh=function(n){var u,t,e;if(typeof n=="string")return n;if(u=vw(n),t=wh(n.__offset),u&&t!=="Z"){n=new Date(n.valueOf());var i=ec(t),o=n.getUTCHours()+i.d*i.h,s=n.getUTCMinutes()+i.d*i.m;n.setUTCHours(o,s)}else u||(t="");var r=n.getUTCFullYear(),h=n.getUTCMonth()+1,f="";return r<=0&&(r=-(r-1),f="-"),e=vh(n.getUTCMilliseconds(),n.__ns),f+a(r,4)+"-"+a(h,2)+"-"+a(n.getUTCDate(),2)+"T"+a(n.getUTCHours(),2)+":"+a(n.getUTCMinutes(),2)+":"+a(n.getUTCSeconds(),2)+e+t},ph=function(n){var t=n.ms,e="",i,r,u,f;retur
 n t<0&&(e="-",t=-t),i=Math.floor(t/864e5),t-=864e5*i,r=Math.floor(t/36e5),t-=36e5*r,u=Math.floor(t/6e4),t-=6e4*u,f=Math.floor(t/1e3),t-=f*1e3,e+"P"+a(i,2)+"DT"+a(r,2)+"H"+a(u,2)+"M"+a(f,2)+vh(t,n.ns)+"S"},a=function(n,t,i){for(var r=n.toString(10);r.length<t;)i?r+="0":r="0"+r;return r},wh=function(n){return!n||n==="Z"||n==="+00:00"||n==="-00:00"?"Z":n},au=function(n){if(typeof n=="string"){var t=n.indexOf(")",10);if(n.indexOf("Collection(")===0&&t>0)return n.substring(11,t)}return null},cw=function(n,i,r,u,f,e){return f.request(n,function(f){try{f.headers&&ee(f.headers),f.data===t&&f.statusCode!==204&&u.read(f,e)}catch(o){o.request===t&&(o.request=n),o.response===t&&(o.response=f),r(o);return}i(f.data,f)},r)},lw=function(n){return d(n)&&e(n.__batchRequests)},aw=/Collection\((.*)\)/,bh=function(n,t){var i=n&&n.results||n;return!!i&&vu(t)||!t&&e(i)&&!d(i[0])},vu=function(n){return aw.test(n)},d=function(n){return!!n&&lf(n)&&!e(n)&&!cf(n)},vw=function(n){return n.__edmType==="Edm.DateT
 imeOffset"||!n.__edmType&&n.__offset},kh=function(n){if(!n&&!d(n))return!1;var t=n.__metadata||{},i=n.__deferred||{};return!t.type&&!!i.uri},dh=function(n){return d(n)&&n.__metadata&&"uri"in n.__metadata},ar=function(n,t){var i=n&&n.results||n;return e(i)&&!vu(t)&&d(i[0])},ie=function(n){return fr(hw,n)},re=function(n){return fr(sw,n)},gh=function(n){if(!n&&!d(n))return!1;var i=n.__metadata,t=n.__mediaresource;return!i&&!!t&&!!t.media_src},yu=function(n){return cf(n)||typeof n=="string"||typeof n=="number"||typeof n=="boolean"},ue=function(n){return fr(ow,n)},nc=function(n,i){return kh(n)?"deferred":dh(n)?"entry":ar(n)?"feed":i&&i.relationship?n===null||n===t||!ar(n)?"entry":"feed":null},bt=function(n,t){return er(n,function(n){return n.name===t})},fe=function(n,t,i){return n?hi(t,function(t){return dw(n,t,i)}):null},yw=function(n,t){return er(n,function(n){return n.name===t})},di=function(n,t){return fe(n,t,"complexType")},kt=function(n,t){return fe(n,t,"entityType")},tc=function(n
 ){return hi(n,function(n){return er(n.entityContainer,function(n){return oe(n.isDefaultEntityContainer)})})},ic=function(n,t){return fe(n,t,"entityContainer")},pw=function(n,t){return er(n,function(n){return n.name===t})},ww=function(n,t){var u=null,f,i,r;return n&&(f=n.relationship,i=hi(t,function(n){var r=rc(n.namespace,f),i=n.association,t,u;if(r&&i)for(t=0,u=i.length;t<u;t++)if(i[t].name===r)return i[t];return null}),i&&(r=i.end[0],r.role!==n.toRole&&(r=i.end[1]),u=r.type)),u},bw=function(n,t,i){if(n){var u=n.relationship,r=hi(i,function(n){for(var f=n.entityContainer,t,i,r=0;r<f.length;r++)if(t=f[r].associationSet,t)for(i=0;i<t.length;i++)if(t[i].association==u)return t[i];return null});if(r&&r.end[0]&&r.end[1])return r.end[0].entitySet==t?r.end[1].entitySet:r.end[0].entitySet}return null},kw=function(n,t){return hi(t,function(t){for(var f=t.entityContainer,r,u,i=0;i<f.length;i++)if(r=f[i].entitySet,r)for(u=0;u<r.length;u++)if(r[u].name==n)return{entitySet:r[u],containerName:f[
 i].name,functionImport:f[i].functionImport};return null})},rc=function(n,t){return t.indexOf(n)===0&&t.charAt(n.length)==="."?t.substr(n.length+1):null},dw=function(n,t,i){if(n&&t){var r=rc(t.namespace,n);if(r)return er(t[i],function(n){return n.name===r})}return null},ct=function(n,t){var i,f,e;if(n===t)return n;var r=n.split("."),u=t.split("."),o=r.length>=u.length?r.length:u.length;for(i=0;i<o;i++){if(f=r[i]&&s(r[i]),e=u[i]&&s(u[i]),f>e)return n;if(f<e)return t}},gw={accept:"Accept","content-type":"Content-Type",dataserviceversion:"DataServiceVersion",maxdataserviceversion:"MaxDataServiceVersion"},ee=function(n){var t,r,i,u;for(t in n)r=t.toLowerCase(),i=gw[r],i&&t!==i&&(u=n[t],delete n[t],n[i]=u)},oe=function(n){return typeof n=="boolean"?n:typeof n=="string"&&n.toLowerCase()==="true"},nb=/^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/,uc=function(n,t,i){var r=nb.exec(n),o=r?wh(r[8]):null,h,u,e,c,l,f;if(!r||!t&&o!=="Z"){if(i)return null;throw{message:
 "Invalid date/time value"};}if(h=s(r[1]),h<=0&&h++,u=r[7],e=0,u){if(u.length>7){if(i)return null;throw{message:"Cannot parse date/time value to given precision."};}e=a(u.substring(3),4,!0),u=a(u.substring(0,3),3,!0),u=s(u),e=s(e)}else u=0;var v=s(r[4]),y=s(r[5]),p=s(r[6])||0;if(o!=="Z"&&(c=ec(o),l=-c.d,v+=c.h*l,y+=c.m*l),f=new Date,f.setUTCFullYear(h,s(r[2])-1,s(r[3])),f.setUTCHours(v,y,p,u),isNaN(f.valueOf())){if(i)return null;throw{message:"Invalid date/time value"};}return t&&(f.__edmType="Edm.DateTimeOffset",f.__offset=o),e&&(f.__ns=e),f},pu=function(n,t){return uc(n,!1,t)},se=function(n,t){return uc(n,!0,t)},fc=/^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/,yit=function(n){fc.test(n)},he=function(n){var i=fc.exec(n),t,r,u;if(i===null)throw{message:"Invalid duration value."};var f=i[2]||"0",e=i[3]||"0",o=s(i[4]||0),h=s(i[5]||0),c=s(i[6]||0),l=parseFloat(i[7]||0);if(f!=="0"||e!=="0")throw{message:"Unsupported duration value."};if(t
 =i[8],r=0,t){if(t.length>7)throw{message:"Cannot parse duration value to given precision."};r=a(t.substring(3),4,!0),t=a(t.substring(0,3),3,!0),t=s(t),r=s(r)}else t=0;return t+=l*1e3+c*6e4+h*36e5+o*864e5,i[1]==="-"&&(t=-t),u={ms:t,__edmType:"Edm.Time"},r&&(u.ns=r),u},ec=function(n){var t=n.substring(0,1),i,r;return t=t==="+"?1:-1,i=s(n.substring(1)),r=s(n.substring(n.indexOf(":")+1)),{d:t,h:i,m:r}},oc=function(n,i,r){n.method||(n.method="GET"),n.headers?ee(n.headers):n.headers={},n.headers.Accept===t&&(n.headers.Accept=i.accept),ot(n.data)&&n.body===t&&i.write(n,r),ot(n.headers.MaxDataServiceVersion)||(n.headers.MaxDataServiceVersion=i.maxDataServiceVersion||"1.0")},sc=function(n,i,r){var u,e,f;if(n&&typeof n=="object")for(u in n)e=n[u],f=sc(e,u,r),f=r(u,f,i),f!==e&&(e===t?delete n[u]:n[u]=f);return n},tb=function(n,t){return t("",sc(n,"",t))},wu=0,ib=function(n){return n.method&&n.method!=="GET"?!1:!0},rb=function(t){var i=n.document.createElement("IFRAME");i.style.display="none";v
 ar r=t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/\</g,"&lt;"),u='<html><head><script type="text/javascript" src="'+r+'"><\/script><\/head><body><\/body><\/html>',f=n.document.getElementsByTagName("BODY")[0];return f.appendChild(i),hc(i,u),i},ub=function(){if(n.XMLHttpRequest)return new n.XMLHttpRequest;var t;if(n.ActiveXObject)try{return new n.ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(i){try{return new n.ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(r){t=r}}else t={message:"XMLHttpRequest not supported"};throw t;},fb=function(n){return n.indexOf("http://")===0||n.indexOf("https://")===0||n.indexOf("file://")===0},eb=function(t){if(!fb(t))return!0;var i=n.location,r=i.protocol+"//"+i.host+"/";return t.indexOf(r)===0},ob=function(i,r){try{delete n[i]}catch(u){n[i]=t,r===wu-1&&(wu-=1)}},bu=function(n){return n&&(hc(n,""),n.parentNode.removeChild(n)),null},sb=function(n,t){for(var r=n.getAllResponseHeaders().split(/\r?\n/),u,i=0,f=r.length;i<f;i++)r[i]&&(u=r[i].split(": "),t[u[0
 ]]=u[1])},hc=function(n,t){var i=n.contentWindow?n.contentWindow.document:n.contentDocument.document;i.open(),i.write(t),i.close()};r.defaultHttpClient={callbackParameterName:"$callback",formatQueryString:"$format=json",enableJsonpCallback:!1,request:function(i,r,u){var y={},f=null,h=!1,s,a,w,b,k,d,l,v;y.abort=function(){(s=bu(s),h)||(h=!0,f&&(f.abort(),f=null),u({message:"Request aborted"}))};var p=function(){s=bu(s),h||(h=!0,f=null,u({message:"Request timed out"}))},c,e=i.requestUri,g=it(i.enableJsonpCallback,this.enableJsonpCallback),nt=it(i.callbackParameterName,this.callbackParameterName),tt=it(i.formatQueryString,this.formatQueryString);if(!g||eb(e)){if(f=ub(),f.onreadystatechange=function(){var t,n,o,s;h||f===null||f.readyState!==4||(t=f.statusText,n=f.status,n===1223&&(n=204,t="No Content"),o=[],sb(f,o),s={requestUri:e,statusCode:n,statusText:t,headers:o,body:f.responseText},h=!0,f=null,n>=200&&n<=299?r(s):u({message:"HTTP request failed",request:i,response:s}))},f.open(i.me
 thod||"GET",e,!0,i.user,i.password),i.headers)for(c in i.headers)f.setRequestHeader(c,i.headers[c]);i.timeoutMS&&(f.timeout=i.timeoutMS,f.ontimeout=p),f.send(i.body)}else{if(!ib(i))throw{message:"Request is not local and cannot be done through JSONP."};a=wu,wu+=1,w=a.toString(),b=!1,c="handleJSONP_"+w,n[c]=function(i){if(s=bu(s),!h){b=!0,n.clearTimeout(k),ob(c,a),n.ActiveXObject&&(i=n.JSON.parse(n.JSON.stringify(i)));var u;u=i.d===t?{"Content-Type":"application/json;odata.metadata=minimal",dataServiceVersion:"4.0"}:{"Content-Type":"application/json"},o(function(){bu(s),r({body:i,statusCode:200,headers:u})})}},d=i.timeoutMS?i.timeoutMS:12e4,k=n.setTimeout(p,d),l=nt+"=parent."+c,this.formatQueryString&&(l+="&"+tt),v=e.indexOf("?"),e=v===-1?e+"?"+l:v===e.length-1?e+l:e+"&"+l,s=rb(e)}return y}};var ci="4.0",gi=function(n){var t,r,i,f,u;if(!n)return null;for(t=n.split(";"),r={},i=1,f=t.length;i<f;i++)u=t[i].split("="),r[ko(u[0])]=u[1];return{mediaType:ko(t[0]),properties:r}},hb=function(
 n){if(!n)return t;var r=n.mediaType,i;for(i in n.properties)r+=";"+i+"="+n.properties[i];return r},cc=function(n,t,i,r){var u={};return g(u,i),g(u,{contentType:n,dataServiceVersion:t,handler:r}),u},lc=function(n,t,i){if(n){var r=n.headers;r[t]||(r[t]=i)}},cb=function(n,t){if(n){var i=n.headers,r=i.DataServiceVersion;i.DataServiceVersion=r?ct(r,t):t}},ac=function(n,i){var r=n.headers;return r&&r[i]||t},vc=function(n){return gi(ac(n,"Content-Type"))},lb=/^\s?(\d+\.\d+);?.*$/,yc=function(n){var i=ac(n,"DataServiceVersion"),t;if(i&&(t=lb.exec(i),t&&t.length))return t[1]},pc=function(n,t){return n.accept.indexOf(t.mediaType)>=0},ab=function(n,i,r,u){var f;if(!r||!r.headers)return!1;var e=vc(r),s=yc(r)||"",o=r.body;return ot(o)?pc(n,e)?(f=cc(e,s,u,n),f.response=r,r.data=i(n,o,f),r.data!==t):!1:!1},vb=function(n,i,r,u){var e,o,f;return!r||!r.headers?!1:(e=vc(r),o=yc(r),(!e||pc(n,e))&&(f=cc(e,o,u,n),f.request=r,r.body=i(n,r.data,f),r.body!==t))?(cb(r,f.dataServiceVersion||"1.0"),lc(r,"Conte
 nt-Type",hb(f.contentType)),lc(r,"MaxDataServiceVersion",n.maxDataServiceVersion),!0):!1},li=function(n,t,i,r){return{accept:i,maxDataServiceVersion:r,read:function(t,i){return ab(this,n,t,i)},write:function(n,i){return vb(this,t,n,i)}}},yb=function(n,t){return t},pb=function(n,i){return ot(i)?i.toString():t};r.textHandler=li(yb,pb,"text/plain",ci);var wc=uu+"www.opengis.net",ut=wc+"/gml",bc=wc+"/def/crs/EPSG/0/",kc="gml",vr=function(n,t,i){var r={type:n};return r[t]=i,r},ce=function(n){if(e(n)&&n.length>=2){var t=n[0];n[0]=n[1],n[1]=t}return n},le=function(n,t,i,r,u,f){var e=dc(n,i,r,u,f);return vr(t,"coordinates",e)},dc=function(n,t,i,r,e){var o=[];return p(n,function(n){var s,h,c;if(u(n)===ut){if(s=f(n),s===t){h=b(n,ut),h&&(c=r(h,e),c&&o.push(c));return}s===i&&p(n,function(n){if(u(n)===ut){var t=r(n,e);t&&o.push(t)}})}}),o},wb=function(n,t){var i=dc(n,"geometryMember","geometryMembers",tl,t);return vr(te,"geometries",i)},bb=function(n,t){return vr(bf,"coordinates",ae(n,t))},kb=fu
 nction(n,t){return le(n,gf,"curveMember","curveMembers",ae,t)},db=function(n,t){return le(n,df,"pointMember","pointMembers",ve,t)},gb=function(n,t){return le(n,ne,"surfaceMember","surfaceMembers",gc,t)},nk=function(n,t){return vr(wf,"coordinates",ve(n,t))},tk=function(n,t){return vr(kf,"coordinates",gc(n,t))},ae=function(n,t){var i=[];return p(n,function(n){var e=u(n),r;if(e===ut){if(r=f(n),r==="posList"){i=rk(n,t);return}if(r==="pointProperty"){i.push(ik(n,t));return}if(r==="pos"){i.push(ye(n,t));return}}}),i},ve=function(n,t){var i=b(n,ut,"pos");return i?ye(i,t):[]},ik=function(n,t){var i=b(n,ut,"Point");return i?ve(i,t):[]},gc=function(n,t){var i=[],r=!1;return p(n,function(n){if(u(n)===ut){var e=f(n);if(e==="exterior"){r=!0,i.unshift(nl(n,t));return}if(e==="interior"){i.push(nl(n,t));return}}}),!r&&i.length>0&&i.unshift([[]]),i},nl=function(n,t){var i=[];return p(n,function(n){u(n)===ut&&f(n)==="LinearRing"&&(i=ae(n,t))}),i},rk=function(n,t){var f=ye(n,!1),e=f.length,r,i,u;if(e%
 2!=0)throw{message:"GML posList element has an uneven number of numeric values"};for(r=[],i=0;i<e;i+=2)u=f.slice(i,i+2),r.push(t?ce(u):u);return r},ye=function(n,t){var u=[],o=" \t\r\n",r=k(n),f;if(r)for(var s=r.length,e=0,i=0;i<=s;)o.indexOf(r.charAt(i))!==-1&&(f=r.substring(e,i),f&&u.push(parseFloat(f)),e=i+1),i++;return t?ce(u):u},tl=function(n,t){var o=f(n),i,u,r,e;switch(o){case"Point":i=nk;break;case"Polygon":i=tk;break;case"LineString":i=bb;break;case"MultiPoint":i=db;break;case"MultiCurve":i=kb;break;case"MultiSurface":i=gb;break;case"MultiGeometry":i=wb;break;default:throw{message:"Unsupported element: "+o,element:n};}if(u=i(n,t),r=st(n,"srsName",ut)||st(n,"srsName"),r){if(r.indexOf(bc)!==0)throw{message:"Unsupported srs name: "+r,element:n};e=r.substring(bc.length),e&&(u.crs={type:"name",properties:{name:"EPSG:"+e}})}return u},il=function(n,t,i,r){var u,o,e,s,f,h,c;switch(i){case wf:u=uk;break;case bf:u=fk;break;case kf:u=ek;break;case df:u=ok;break;case gf:u=sk;break;case
  ne:u=hk;break;case te:u=lk;break;default:return null}return o=u(n,t,r),e=t.crs,e&&e.type==="name"&&(s=e.properties,f=s&&s.name,f&&f.indexOf("ESPG:")===0&&f.length>5&&(h=f.substring(5),c=si(n,null,"srsName",kc+h),l(o,c))),o},dt=function(n,t,i){return cr(n,ut,wt(kc,t),i)},rl=function(n,t,i){var r=e(t)?t:[];return r=i?ce(r):r,dt(n,"pos",r.join(" "))},ul=function(n,t,i,r){var f=dt(n,t),u,o;if(e(i)){for(u=0,o=i.length;u<o;u++)l(f,rl(n,i[u],r));o===0&&l(f,dt(n,"posList"))}return f},fl=function(n,t,i){return dt(n,"Point",rl(n,t,i))},el=function(n,t,i){return ul(n,"LineString",t,i)},ol=function(n,t,i,r){var u=dt(n,t),f;return e(i)&&i.length>0&&(f=ul(n,"LinearRing",i,r),l(u,f)),u},sl=function(n,t,i){var f=t&&t.length,u=dt(n,"Polygon"),r;if(e(t)&&f>0)for(l(u,ol(n,"exterior",t[0],i)),r=1;r<f;r++)l(u,ol(n,"interior",t[r],i));return u},uk=function(n,t,i){return fl(n,t.coordinates,i)},fk=function(n,t,i){return el(n,t.coordinates,i)},ek=function(n,t,i){return sl(n,t.coordinates,i)},ku=function(n,
 t,i,r,u,f){var h=r&&r.length,c=dt(n,t),s,o;if(e(r)&&h>0){for(s=dt(n,i),o=0;o<h;o++)l(s,u(n,r[o],f));l(c,s)}return c},ok=function(n,t,i){return ku(n,"MultiPoint","pointMembers",t.coordinates,fl,i)},sk=function(n,t,i){return ku(n,"MultiCurve","curveMembers",t.coordinates,el,i)},hk=function(n,t,i){return ku(n,"MultiSurface","surfaceMembers",t.coordinates,sl,i)},ck=function(n,t,i){return il(n,t,t.type,i)},lk=function(n,t,i){return ku(n,"MultiGeometry","geometryMembers",t.geometries,ck,i)},du="application/xml",ak=uu+"docs.oasis-open.org/odata/",lt=ak+"ns",gu=lt+"/edmx",vk=lt+"/edm",at=lt,nt=lt+"/metadata",pe=lt+"/related/",hl=lt+"/scheme",cl="d",we="m",gt=function(n,t){var i={name:f(n),value:n.value};return i[t?"namespaceURI":"namespace"]=u(n),i},yr=function(n,t){for(var s=[],h=[],c=n.attributes,e,i,o,r=0,l=c.length;r<l;r++)e=c[r],u(e)!==sr&&s.push(gt(e,t));for(i=n.firstChild;i!=null;)i.nodeType===1&&h.push(yr(i,t)),i=i.nextSibling;return o={name:f(n),value:k(n),attributes:s,children:h},
 o[t?"namespaceURI":"namespace"]=u(n),o},be=function(n){return u(n)===at&&f(n)==="element"},ll=function(n,t){return{type:n,extensions:t}},yk=function(n){var t,i;return b(n,ut)?et:(t=b(n,at),!t)?lr:be(t)&&(i=tw(t,at),i&&be(i))?"Collection()":null},al=function(n){var t=null,i=!1,r=[];return pi(n,function(n){var e=u(n),o=f(n),s=bi(n);if(e===nt){if(o==="null"){i=s.toLowerCase()==="true";return}if(o==="type"){t=s;return}}if(e!==yi&&e!==sr){r.push(gt(n,!0));return}}),{type:!t&&i?lr:t,isNull:i,extensions:r}},vl=function(n){if(u(n)!==at)return null;var e=f(n),t=al(n),o=t.isNull,i=t.type,r=ll(i,t.extensions),s=o?null:yl(n,i,r);return{name:e,value:s,metadata:r}},yl=function(n,t,i){t||(t=yk(n),i.type=t);var r=ie(t);return r||re(t)?pk(n,t,r):ue(t)?pl(n,t):vu(t)?bk(n,t,i):wk(n,t,i)},pk=function(n,t,i){var u=b(n,ut),r=tl(u,i);return r.__metadata={type:t},r},pl=function(n,t){var i=bi(n)||"";switch(t){case cs:return oe(i);case hs:case as:case ys:case bs:case lr:return i;case ls:case ps:case ws:case 
 ks:return s(i);case vs:case ds:return parseFloat(i);case lu:return he(i);case hu:return pu(i);case cu:return se(i)}return i},wk=function(n,t,i){var r={__metadata:{type:t}};return p(n,function(n){var t=vl(n),u=t.name;i.properties=i.properties||{},i.properties[u]=t.metadata,r[u]=t.value}),r},bk=function(n,t,i){var r=[],u=i.elements=[],f=au(t);return p(n,function(n){if(be(n)){var t=al(n),o=t.extensions,i=t.type||f,e=ll(i,o),s=yl(n,i,e);r.push(s),u.push(e)}}),{__metadata:{type:t==="Collection()"?null:t},results:r}},kk=function(n,i){if(u(n)===at){i=rt(n,i);var r=f(n);if(r==="links")return dk(n,i);if(r==="uri")return wl(n,i)}return t},dk=function(n,t){var i=[];return p(n,function(n){f(n)==="uri"&&u(n)===at&&i.push(wl(n,t))}),{results:i}},wl=function(n,t){var i=k(n)||"";return{uri:c(i,t)}},gk=function(n,t){return t===et||t===ht?n&&n.type:t===eh||t===gs?wf:t===oh||t===nh?bf:t===sh||t===th?kf:t===hh||t===ih?te:t===ch||t===rh?ne:t===lh||t===uh?gf:t===ah||t===fh?df:null},bl=function(n,t,i){ret
 urn cr(n,nt,wt(we,t),i)},ke=function(n,t,i){return si(n,nt,wt(we,t),i)},kl=function(n,t,i){return cr(n,at,wt(cl,t),i)},nd=function(n,t){return t===hu||t===cu||cf(n)?yh(n):t===lu?ph(n):n.toString()},vt=function(n,t){return{element:n,dsv:t}},pr=function(n,t,i,r){var u=i?ke(n,"type",i):null,f=kl(n,t,u);return ou(f,r)},td=function(n,t,i,r){var u=nd(i,r),f=pr(n,t,r,u);return vt(f,"1.0")},id=function(n,t,i,r){var u=ke(n,"null","true"),f=pr(n,t,i,u),e=di(i,r)?"2.0":"1.0";return vt(f,e)},rd=function(n,t,i,r,u,f,o){var c=au(r),a=e(i)?i:i.results,v=r?{type:c}:{},h,s,y,p,w;for(v.properties=u.properties,h=pr(n,t,c?r:null),s=0,y=a.length;s<y;s++)p=a[s],w=de(n,"element",p,v,f,o),l(h,w.element);return vt(h,"4.0")},ud=function(n,t,i,r,u,f,e){var h=pr(n,t,r),a=u.properties||{},v=di(r,e)||{},s="1.0",o;for(o in i)if(o!=="__metadata"){var y=i[o],p=bt(v.property,o),w=a[o]||{},c=de(n,o,y,w,p,e);s=ct(s,c.dsv),l(h,c.element)}return vt(h,s)},fd=function(n,t,i,r,u){var f=gk(i,r),e=il(n,i,f,u),o=pr(n,t,r,e);r
 eturn vt(o,".0")},de=function(n,t,i,r,u,f){var e=ss(i,r,u),o,s;return yu(i)?td(n,t,i,e||lr):(o=ie(e),o||re(e))?fd(n,t,i,e,o):bh(i,e)?rd(n,t,i,e,r,u,f):gh(i)?null:(s=nc(i,u),s!==null)?null:i===null?id(n,t,e):ud(n,t,i,e,r,u,f)},ed=function(n){if(n&&lf(n)){var t=es();return l(t,kl(t,"uri",n.uri))}},od=function(n,t){if(t){var r=eu(t),i=b(r);if(i)return kk(i)}},sd=function(n,i,r){var u=r.contentType=r.contentType||gi(du);return u&&u.mediaType===du?pf(ed(i)):t};r.xmlHandler=li(od,sd,du,ci);var dl="a",ni=or+"2005/Atom",wr=or+"2007/app",gl=lt+"/edit-media/",na=lt+"/mediaresource/",ta=lt+"/relatedlinks/",ia=["application/atom+xml","application/atomsvc+xml","application/xml"],ra=ia[0],hd=[ni,wr,yi,sr],cd={SyndicationAuthorEmail:"author/email",SyndicationAuthorName:"author/name",SyndicationAuthorUri:"author/uri",SyndicationContributorEmail:"contributor/email",SyndicationContributorName:"contributor/name",SyndicationContributorUri:"contributor/uri",SyndicationPublished:"published",SyndicationRi
 ghts:"rights",SyndicationSummary:"summary",SyndicationTitle:"title",SyndicationUpdated:"updated"},ld=function(n){return cd[n]||n},br=function(n){return!fr(hd,n)},ua=function(n,t,i,r,u){var f;if(u=u||"",f=n["FC_TargetPath"+u],!f)return null;var e=n["FC_SourcePath"+u],s=ld(f),o=r?r+(e?"/"+e:""):e,l=o&&bd(i,t,o),h=n["FC_NsUri"+u]||null,c=n["FC_NsPrefix"+u]||null,a=n["FC_KeepInContent"+u]||"";return f!==s&&(h=ni,c=dl),{contentKind:n["FC_ContentKind"+u],keepInContent:a.toLowerCase()==="true",nsPrefix:c,nsURI:h,propertyPath:o,propertyType:l,entryPath:s}},fa=function(n,t,i){for(var c=[],l,r,f,u,e;n;){for(l=n.FC_SourcePath,r=ua(n,n,t),r&&i(r),f=n.property||[],u=0,e=f.length;u<e;u++)for(var o=f[u],s=0,h="";r=ua(o,n,t,o.name,h);)i(r),s++,h="_"+s;n=kt(n.baseType,t)}return c},nf=function(n){var t=[];return pi(n,function(n){var i=u(n);br(i)&&t.push(gt(n,!0))}),t},ea=function(n){return yr(n,!0)},oa=function(n,t,i){var e=u(n),r=f(n);if(e===wr&&r==="service")return fg(n,t);if(e===ni){if(r==="feed")
 return ad(n,t,i);if(r==="entry")return aa(n,t,i)}},sa=function(n,t){var r=[],i={extensions:r};return pi(n,function(e){var o=f(e),s=u(e),h=bi(e);if(s===null){if(o==="title"||o==="metadata"){i[o]=h;return}if(o==="target"){i.target=c(h,rt(n,t));return}}br(s)&&r.push(gt(e,!0))}),i},ha=function(n,t,i){var r=i.actions=i.actions||[];r.push(sa(n,t))},ca=function(n,t,i){var r=i.functions=i.functions||[];r.push(sa(n,t))},ad=function(n,t,i){var o=nf(n),r={feed_extensions:o},s=[],e={__metadata:r,results:s};return t=rt(n,t),p(n,function(n){var l=u(n),h=f(n);if(l===nt){if(h==="count"){e.__count=parseInt(k(n),10);return}if(h==="action"){ha(n,t,r);return}if(h==="function"){ca(n,t,r);return}}if(br(l)){o.push(yr(n));return}if(h==="entry"){s.push(aa(n,t,i));return}if(h==="link"){vd(n,e,t);return}if(h==="id"){r.uri=c(k(n),t),r.uri_extensions=nf(n);return}if(h==="title"){r.title=k(n)||"",r.title_extensions=nf(n);return}}),e},vd=function(n,t,i){var r=la(n,i),f=r.href,e=r.rel,o=r.extensions,u=t.__metadata
 ;if(e==="next"){t.__next=f,u.next_extensions=o;return}if(e==="self"){u.self=f,u.self_extensions=o;return}},la=function(n,t){t=rt(n,t);var r=[],i={extensions:r,baseURI:t};if(pi(n,function(n){var s=u(n),e=f(n),o=n.value;if(e==="href"){i.href=c(o,t);return}if(e==="type"||e==="rel"){i[e]=o;return}br(s)&&r.push(gt(n,!0))}),!i.href)throw{error:"href attribute missing on link element",element:n};return i},yd=function(n,i){if(n.indexOf("/")===-1)return i[n];for(var u=n.split("/"),r=0,f=u.length;r<f;r++){if(i===null)return t;if(i=i[u[r]],i===t)return i}return i},pd=function(n,i,r,u){var o,s,f,h,e;if(n.indexOf("/")===-1)i[n]=r,o=n;else{for(s=n.split("/"),f=0,h=s.length-1;f<h;f++){if(e=i[s[f]],e===t)e={},i[s[f]]=e;else if(e===null)return;i=e}o=s[f],i[o]=r}if(u){var c=i.__metadata=i.__metadata||{},l=c.properties=c.properties||{},a=l[o]=l[o]||{};a.type=u}},wd=function(n,t,i){var e=n.propertyPath,r,u,f;n.keepInContent||yd(e,i)===null||(r=gp(t,n.nsURI,n.entryPath),r)&&(u=n.propertyType,f=n.content
 Kind==="xhtml"?fw(r):pl(r,u||"Edm.String"),pd(e,i,f,u))},bd=function(n,t,i){for(var s=i.split("/"),u,h,f,e,o,r;t;){for(f=t,u=0,h=s.length;u<h;u++){if(e=f.property,!e)break;if(o=bt(e,s[u]),!o)break;if(r=o.type,!r||ue(r))return r||null;if(f=di(r,n),!f)return null}t=kt(t.baseType,n)}return null},aa=function(n,t,i){var r={},e={__metadata:r},o=st(n,"etag",nt),s;return o&&(r.etag=o),t=rt(n,t),p(n,function(n){var s=u(n),o=f(n);if(s===ni){if(o==="id"){kd(n,r,t);return}if(o==="category"){dd(n,r);return}if(o==="content"){gd(n,e,r,t);return}if(o==="link"){ng(n,e,r,t,i);return}return}if(s===nt){if(o==="properties"){pa(n,e,r);return}if(o==="action"){ha(n,t,r);return}if(o==="function"){ca(n,t,r);return}}}),s=kt(r.type,i),fa(s,i,function(t){wd(t,n,e)}),e},kd=function(n,t,i){t.uri=c(k(n),rt(n,i)),t.uri_extensions=nf(n)},dd=function(n,t){if(st(n,"scheme")===hl){if(t.type)throw{message:"Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry",elem
 ent:n};var i=[];pi(n,function(n){var t=u(n),r=f(n);if(!t){r!=="scheme"&&r!=="term"&&i.push(gt(n,!0));return}br(t)&&i.push(gt(n,!0))}),t.type=st(n,"term"),t.type_extensions=i}},gd=function(n,t,i,r){var e=st(n,"src"),o=st(n,"type");if(e){if(!o)throw{message:"Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",element:n};i.media_src=c(e,rt(n,r)),i.content_type=o}p(n,function(r){if(e)throw{message:"Invalid AtomPub document: content element must not have child elements if the src attribute is specified",element:n};u(r)===nt&&f(r)==="properties"&&pa(r,t,i)})},ng=function(n,t,i,r,u){var f=la(n,r),e=f.rel,s=f.href,o=f.extensions;if(e==="self"){i.self=s,i.self_link_extensions=o;return}if(e==="edit"){i.edit=s,i.edit_link_extensions=o;return}if(e==="edit-media"){i.edit_media=f.href,i.edit_media_extensions=o,ya(f,i);return}if(e.indexOf(gl)===0){rg(f,t,i);return}if(e.indexOf(na)===0){ug(f,t,i);return}if(e.indexOf(pe)===0){ig(n,f,t,i,u
 );return}if(e.indexOf(ta)===0){tg(f,i);return}},tg=function(n,t){var r=n.rel.substring(ta.length),i;t.properties=t.properties||{},i=t.properties[r]=t.properties[r]||{},i.associationuri=n.href,i.associationuri_extensions=n.extensions},ig=function(n,t,i,r,u){var e,o=b(n,nt,"inline"),s,h,f,c;o?(s=b(o),h=rt(o,t.baseURI),e=s?oa(s,h,u):null):e={__deferred:{uri:t.href}},f=t.rel.substring(pe.length),i[f]=e,r.properties=r.properties||{},c=r.properties[f]=r.properties[f]||{},c.extensions=t.extensions},rg=function(n,t,i){var o=n.rel.substring(gl.length),f=va(o,t,i),r=f.value,u=f.metadata,e=n.href;r.edit_media=e,r.content_type=n.type,u.edit_media_extensions=n.extensions,r.media_src=r.media_src||e,u.media_src_extensions=u.media_src_extensions||[],ya(n,r)},ug=function(n,t,i){var f=n.rel.substring(na.length),r=va(f,t,i),u=r.value,e=r.metadata;u.media_src=n.href,e.media_src_extensions=n.extensions,u.content_type=n.type},va=function(n,t,i){i.properties=i.properties||{};var u=i.properties[n],r=t[n]&&
 t[n].__mediaresource;return r||(r={},t[n]={__mediaresource:r},i.properties[n]=u={}),{value:r,metadata:u}},ya=function(n,t){for(var r=n.extensions,i=0,u=r.length;i<u;i++)if(r[i].namespaceURI===nt&&r[i].name==="etag"){t.media_etag=r[i].value,r.splice(i,1);return}},pa=function(n,t,i){p(n,function(n){var r=vl(n),u,f;r&&(u=r.name,f=i.properties=i.properties||{},f[u]=r.metadata,t[u]=r.value)})},fg=function(n,t){var i=[],r=[];if(t=rt(n,t),p(n,function(n){if(u(n)===wr&&f(n)==="workspace"){i.push(eg(n,t));return}r.push(yr(n))}),i.length===0)throw{message:"Invalid AtomPub service document: No workspace element found.",element:n};return{workspaces:i,extensions:r}},eg=function(n,i){var e=[],o=[],r;return i=rt(n,i),p(n,function(n){var s=u(n),h=f(n);if(s===ni&&h==="title"){if(r!==t)throw{message:"Invalid AtomPub service document: workspace has more than one child title element",element:n};r=k(n);return}if(s===wr){h==="collection"&&e.push(og(n,i));return}o.push(ea(n))}),{title:r||"",collections:e,
 extensions:o}},og=function(n,i){var r=st(n,"href"),o,e;if(!r)throw{message:"Invalid AtomPub service document: collection has no href attribute",element:n};if(i=rt(n,i),r=c(r,rt(n,i)),o=[],p(n,function(i){var r=u(i),s=f(i);if(r===ni){if(s==="title"){if(e!==t)throw{message:"Invalid AtomPub service document: collection has more than one child title element",element:i};e=k(i)}return}r!==wr&&o.push(ea(n))}),!e)throw{message:"Invalid AtomPub service document: collection has no title element",element:n};return{title:e,href:r,extensions:o}},ti=function(n,t,i){return cr(n,ni,wt(dl,t),i)},nr=function(n,t,i){return si(n,null,t,i)},sg=function(n){var t,e,i,o,r;if(n.childNodes.length>0)return!1;for(t=!0,e=n.attributes,i=0,o=e.length;i<o&&t;i++)r=e[i],t=t&&wp(r)||u(r)==nt&&f(r)==="type";return t},hg=function(n,t,i,r,u){var s=null,e=null,f=null,o="",h;return i!=="deferred"?(s=nr(n,"type","application/atom+xml;type="+i),e=bl(n,"inline"),r&&(o=r.__metadata&&r.__metadata.uri||"",f=wa(n,r,u)||ge(n,r,u
 ),l(e,f.element))):o=r.__deferred.uri,h=ti(n,"link",[nr(n,"href",o),nr(n,"rel",c(t,pe)),s,e]),vt(h,f?f.dsv:"1.0")},cg=function(n,t,i,r,u,f){var e,o;return gh(i)?null:(e=de(n,t,i,r,u,f),e||(o=nc(i,u),e=hg(n,t,o,i,f)),e)},lg=function(n,t,i,r){var u=us(i,at,r.propertyPath),l=u&&wi(u,"null",nt),o,s="1.0",f,e,h,c;if(l&&l.value==="true")return s;if(u&&(o=k(u)||"",!r.keepInContent))for(s="2.0",f=u.parentNode,e=f,f.removeChild(u);e!==i&&sg(e);)f=e.parentNode,f.removeChild(e),e=f;return(h=uw(n,t,r.nsURI,r.nsPrefix,r.entryPath),h.nodeType===2)?(h.value=o,s):(c=r.contentKind,ou(h,[c&&si(n,null,"type",c),c==="xhtml"?iw(n,o):o]),s)},ge=function(n,t,i){var e=t.__metadata||{},b=e.properties||{},y=e.etag,p=e.uri,s=e.type,o=kt(s,i),h=bl(n,"properties"),c=ti(n,"entry",[ti(n,"author",ti(n,"name")),y&&ke(n,"etag",y),p&&ti(n,"id",p),s&&ti(n,"category",[nr(n,"term",s),nr(n,"scheme",hl)]),ti(n,"content",[nr(n,"type","application/xml"),h])]),f="1.0",r,v,w;for(r in t)if(r!=="__metadata"){var k=b[r]||{},d=o&
 &(bt(o.property,r)||bt(o.navigationProperty,r)),a=cg(n,r,t[r],k,d,i);a&&(v=a.element,w=u(v)===ni?c:h,l(w,v),f=ct(f,a.dsv))}return fa(o,i,function(t){var i=lg(n,c,h,t);f=ct(f,i)}),vt(c,f)},wa=function(n,t,i){var f=e(t)?t:t.results,r,o,u,h,s;if(!f)return null;for(r="1.0",o=ti(n,"feed"),u=0,h=f.length;u<h;u++)s=ge(n,f[u],i),l(o,s.element),r=ct(r,s.dsv);return vt(o,r)},ag=function(n,t){var u,i,r,f;return n&&(u=ar(n)&&wa||lf(n)&&ge,u&&(i=es(),r=u(i,n,t),r))?(f=r.element,ou(f,[os(i,nt,we),os(i,at,cl)]),vt(l(i,f),r.dsv)):null},vg=function(n,t,i){if(t){var u=eu(t),r=b(u);if(r)return oa(r,null,i.metadata)}},yg=function(n,t,i){var u=i.contentType=i.contentType||gi(ra),r;if(u&&u.mediaType===ra&&(r=ag(t,i.metadata),r))return i.dataServiceVersion=ct(i.dataServiceVersion||"1.0",r.dsv),pf(r.element)};r.atomHandler=li(vg,yg,ia.join(","),ci);var i=function(n,t,i,r){return{attributes:n,elements:t,text:i||!1,ns:r}},tt={elements:{Annotations:i(["Target","Qualifier"],["TypeAnnotation*","ValueAnnotation*
 "]),Association:i(["Name"],["End*","ReferentialConstraint","TypeAnnotation*","ValueAnnotation*"]),AssociationSet:i(["Name","Association"],["End*","TypeAnnotation*","ValueAnnotation*"]),Binary:i(null,null,!0),Bool:i(null,null,!0),Collection:i(null,["String*","Int*","Float*","Decimal*","Bool*","DateTime*","DateTimeOffset*","Guid*","Binary*","Time*","Collection*","Record*"]),CollectionType:i(["ElementType","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"],["CollectionType","ReferenceType","RowType","TypeRef"]),ComplexType:i(["Name","BaseType","Abstract"],["Property*","TypeAnnotation*","ValueAnnotation*"]),DateTime:i(null,null,!0),DateTimeOffset:i(null,null,!0),Decimal:i(null,null,!0),DefiningExpression:i(null,null,!0),Dependent:i(["Role"],["PropertyRef*"]),Documentation:i(null,null,!0),End:i(["Type","Role","Multiplicity","EntitySet"],["OnDelete"]),EntityContainer:i(["Name","Extends"],["EntitySet*","AssociationSet*","FunctionImport*","
 TypeAnnotation*","ValueAnnotation*"]),EntitySet:i(["Name","EntityType"],["TypeAnnotation*","ValueAnnotation*"]),EntityType:i(["Name","BaseType","Abstract","OpenType"],["Key","Property*","NavigationProperty*","TypeAnnotation*","ValueAnnotation*"]),EnumType:i(["Name","UnderlyingType","IsFlags"],["Member*"]),Float:i(null,null,!0),Function:i(["Name","ReturnType"],["Parameter*","DefiningExpression","ReturnType","TypeAnnotation*","ValueAnnotation*"]),FunctionImport:i(["Name","ReturnType","EntitySet","IsSideEffecting","IsComposable","IsBindable","EntitySetPath"],["Parameter*","ReturnType","TypeAnnotation*","ValueAnnotation*"]),Guid:i(null,null,!0),Int:i(null,null,!0),Key:i(null,["PropertyRef*"]),LabeledElement:i(["Name"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),Member:i(["Name","Value"]),NavigationProperty:i(["Name","Relationship","ToRole","FromRole","ContainsTarget"],["TypeAnnotation*
 ","ValueAnnotation*"]),Null:i(null,null),OnDelete:i(["Action"]),Path:i(null,null,!0),Parameter:i(["Name","Type","Mode","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","SRID"],["CollectionType","ReferenceType","RowType","TypeRef","TypeAnnotation*","ValueAnnotation*"]),Principal:i(["Role"],["PropertyRef*"]),Property:i(["Name","Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","CollectionKind","SRID"],["CollectionType","ReferenceType","RowType","TypeAnnotation*","ValueAnnotation*"]),PropertyRef:i(["Name"]),PropertyValue:i(["Property","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ReferenceType:i(["Type"]),ReferentialConstraint:i(null,["Principal","Dependent"]),
 ReturnType:i(["ReturnType","Type","EntitySet"],["CollectionType","ReferenceType","RowType"]),RowType:i(["Property*"]),String:i(null,null,!0),Schema:i(["Namespace","Alias"],["Using*","EntityContainer*","EntityType*","Association*","ComplexType*","Function*","ValueTerm*","Annotations*"]),Time:i(null,null,!0),TypeAnnotation:i(["Term","Qualifier"],["PropertyValue*"]),TypeRef:i(["Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"]),Using:i(["Namespace","Alias"]),ValueAnnotation:i(["Term","Qualifier","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ValueTerm:i(["Name","Type"],["TypeAnnotation*","ValueAnnotation*"]),Edmx:i(["Version"],["DataServices","Reference*","AnnotationsReference*"],!1,gu),DataServices:i(null,["Schema*"],!1,gu)}},ba=["m
 :FC_ContentKind","m:FC_KeepInContent","m:FC_NsPrefix","m:FC_NsUri","m:FC_SourcePath","m:FC_TargetPath"];tt.elements.Property.attributes=tt.elements.Property.attributes.concat(ba),tt.elements.EntityType.attributes=tt.elements.EntityType.attributes.concat(ba),tt.elements.Edmx={attributes:["Version"],elements:["DataServices"],ns:gu},tt.elements.DataServices={elements:["Schema*"],ns:gu},tt.elements.EntityContainer.attributes.push("m:IsDefaultEntityContainer"),tt.elements.Property.attributes.push("m:MimeType"),tt.elements.FunctionImport.attributes.push("m:HttpMethod"),tt.elements.FunctionImport.attributes.push("m:IsAlwaysBindable"),tt.elements.EntityType.attributes.push("m:HasStream"),tt.elements.DataServices.attributes=["m:DataServiceVersion","m:MaxDataServiceVersion"];var ka=function(n){if(!n)return n;if(n.length>1){var t=n.substr(0,2);return t===t.toUpperCase()?n:n.charAt(0).toLowerCase()+n.substr(1)}return n.charAt(0).toLowerCase()},pg=function(n,t){var r,u,e,i,f,o;if(t==="Documentat
 ion")return{isArray:!0,propertyName:"documentation"};if(r=n.elements,!r)return null;for(u=0,e=r.length;u<e;u++)if(i=r[u],f=!1,i.charAt(i.length-1)==="*"&&(f=!0,i=i.substr(0,i.length-1)),t===i)return o=ka(i),{isArray:f,propertyName:o};return null},wg=/^(m:FC_.*)_[0-9]+$/,da=function(n){return n===vk},no=function(n){var o=f(n),e=u(n),i=tt.elements[o];if(!i)return null;if(i.ns){if(e!==i.ns)return null}else if(!da(e))return null;var t={},r=[],s=i.attributes||[];return pi(n,function(n){var c=f(n),e=u(n),l=n.value,i,o,h;e!==sr&&(i=null,o=!1,da(e)||e===null?i="":e===nt&&(i="m:"),i!==null&&(i+=c,h=wg.exec(i),h&&(i=h[1]),fr(s,i)&&(o=!0,t[ka(c)]=l)),o||r.push(gt(n)))}),p(n,function(n){var o=f(n),u=pg(i,o),e;u?u.isArray?(e=t[u.propertyName],e||(e=[],t[u.propertyName]=e),e.push(no(n))):t[u.propertyName]=no(n):r.push(yr(n))}),i.text&&(t.text=k(n)),r.length&&(t.extensions=r),t},ga=function(n,i){var r=eu(i),u=b(r);return no(u)||t};r.metadataHandler=li(ga,null,du,ci);var nv="o",to="f",tv="p",iv="c"
 ,rv="s",uv="l",bg="odata",ii=bg+".",kg="@"+ii+"bind",io=ii+"metadata",fv=ii+"navigationLinkUrl",tr=ii+"type",tf={readLink:"self",editLink:"edit",nextLink:"__next",mediaReadLink:"media_src",mediaEditLink:"edit_media",mediaContentType:"content_type",mediaETag:"media_etag",count:"__count",media_src:"mediaReadLink",edit_media:"mediaEditLink",content_type:"mediaContentType",media_etag:"mediaETag",url:"uri"},h={metadata:"odata.metadata",count:"odata.count",next:"odata.nextLink",id:"odata.id",etag:"odata.etag",read:"odata.readLink",edit:"odata.editLink",mediaRead:"odata.mediaReadLink",mediaEdit:"odata.mediaEditLink",mediaEtag:"odata.mediaETag",mediaContentType:"odata.mediaContentType",actions:"odata.actions",functions:"odata.functions",navigationUrl:"odata.navigationLinkUrl",associationUrl:"odata.associationLinkUrl",type:"odata.type"},dg=function(n){if(n.indexOf(".")>0){var t=n.indexOf("@"),r=t>-1?n.substring(0,t):null,i=n.substring(t+1);return{target:r,name:i,isOData:i.indexOf(ii)===0}}re
 turn null},ro=function(n,t,i,r,u){return d(t)&&t[tr]||i&&i[n+"@"+tr]||r&&r.type||ww(r,u)||null},uo=function(n,t){return t?bt(t.property,n)||bt(t.navigationProperty,n):null},ev=function(n){return d(n)&&ii+"id"in n},gg=function(n,t,i){if(!!t[n+"@"+fv]||i&&i.relationship)return!0;var r=e(t[n])?t[n][0]:t[n];return ev(r)},fo=function(n){return ue(n)||ie(n)||re(n)},ri=function(n,t,i,r,u){var f,e;for(f in n)if(f.indexOf(".")>0&&f.charAt(0)!=="#"&&(e=dg(f),e)){var c=e.name,o=e.target,s=null,h=null;o&&(s=uo(o,r),h=ro(o,n[o],n,s,u)),e.isOData?nn(c,o,h,n[f],n,t,i):t[f]=n[f]}return t},nn=function(n,t,i,r,u,f,e){var o=n.substring(ii.length);switch(o){case"navigationLinkUrl":fn(o,t,i,r,u,f,e);return;case"nextLink":case"count":rn(o,t,r,f,e);return;case"mediaReadLink":case"mediaEditLink":case"mediaContentType":case"mediaETag":un(o,t,i,r,f,e);return;default:tn(o,t,r,f,e);return}},tn=function(n,t,i,r,u){var f=r.__metadata=r.__metadata||{},e=tf[n]||n,s,o;if(n==="editLink"){f.uri=c(i,u),f[e]=f.uri;retu
 rn}if((n==="readLink"||n==="associationLinkUrl")&&(i=c(i,u)),t){if(s=f.properties=f.properties||{},o=s[t]=s[t]||{},n==="type"){o[e]=o[e]||i;return}o[e]=i;return}f[e]=i},rn=function(n,t,i,r,u){var f=tf[n],e=t?r[t]:r;e[f]=n==="nextLink"?c(i,u):i},un=function(n,t,i,r,u,f){var e=u.__metadata=u.__metadata||{},h=tf[n],o,s;if((n==="mediaReadLink"||n==="mediaEditLink")&&(r=c(r,f)),t){o=e.properties=e.properties||{},s=o[t]=o[t]||{},s.type=s.type||i,u.__metadata=e,u[t]=u[t]||{__mediaresource:{}},u[t].__mediaresource[h]=r;return}e[h]=r},fn=function(n,t,i,r,u,f,e){var s=f.__metadata=f.__metadata||{},h=s.properties=s.properties||{},o=h[t]=h[t]||{},l=c(r,e);if(u.hasOwnProperty(t)){o.navigationLinkUrl=l;return}f[t]={__deferred:{uri:l}},o.type=o.type||i},eo=function(n,t,i,r,u,f,o){if(typeof n=="string")return en(n,t,o);if(!fo(t)){if(e(n))return ov(n,t,i,r,f,o);if(d(n))return on(n,t,i,r,f,o)}return n},en=function(n,t,i){switch(t){case lu:return he(n);case hu:return pu(n,!1);case cu:return se(n,!1)}r
 eturn i?pu(n,!0)||se(n,!0)||n:n},ov=function(n,t,i,r,u,f){for(var a=au(t),o=[],h=[],e=0,c=n.length;e<c;e++){var s=ro(null,n[e])||a,l={type:s},v=eo(n[e],s,l,r,null,u,f);fo(s)||yu(n[e])||o.push(l),h.push(v)}return o.length>0&&(i.elements=o),{__metadata:{type:t},results:h}},on=function(n,t,i,r,u,f){var e=rf(n,{type:t},r,u,f),o=e.__metadata,s=o.properties;return s&&(i.properties=s,delete o.properties),e},sn=function(n,t,i,r,u){return e(n)?hv(n,t,i,r,u):d(n)?rf(n,t,i,r,u):null},rf=function(n,i,r,u,f){var d,v,g,o,y,h,c,nt;i=i||{};var l=n[tr]||i.type||null,s=kt(l,u),k=!0;s||(k=!1,s=di(l,u));var p={type:l},a={__metadata:p},w={},e;if(k&&s&&i.entitySet&&i.contentTypeOdata=="minimalmetadata"){for(d=r.substring(0,r.lastIndexOf("$metadata")),e=null,s.key||(e=s);!!e&&!e.key&&e.baseType;)e=kt(e.baseType,u);(s.key||!!e&&e.key)&&(v=s.key?cv(n,s):cv(n,e),v&&(g={key:v,entitySet:i.entitySet,functionImport:i.functionImport,containerName:i.containerName},hn(n,g,l,d,s,e)))}for(o in n)if(o.indexOf("#")===0
 )sv(o.substring(1),n[o],a,r,u);else if(o.indexOf(".")===-1){for(p.properties||(p.properties=w),y=n[o],h=h=uo(o,s),e=s;!!s&&h===null&&e.baseType;)e=kt(e.baseType,u),h=h=uo(o,e);var tt=gg(o,n,h),b=ro(o,y,n,h,u),it=w[o]=w[o]||{type:b};tt?(c={},i.entitySet!==t&&(nt=bw(h,i.entitySet.name,u),c=kw(nt,u)),c.contentTypeOdata=i.contentTypeOdata,c.kind=i.kind,c.type=b,a[o]=sn(y,c,r,u,f)):a[o]=eo(y,b,it,r,h,u,f)}return ri(n,a,r,s,u)},sv=function(n,t,i,r,u){var f,s,g,nt;if(n&&(e(t)||d(t))){var l=!1,h=n.lastIndexOf("."),a=n.substring(h+1),v=h>-1?n.substring(0,h):"",y=a===n||v.indexOf(".")===-1?tc(u):ic(v,u);y&&(f=pw(y.functionImport,a),f&&!!f.isSideEffecting&&(l=!oe(f.isSideEffecting)));for(var p=i.__metadata,w=l?"functions":"actions",tt=c(n,r),b=e(t)?t:[t],o=0,k=b.length;o<k;o++)s=b[o],s&&(g=p[w]=p[w]||[],nt={metadata:tt,title:s.title,target:c(s.target,r)},g.push(nt))}},hv=function(n,t,i,r,u){for(var h=e(n)?n:n.value,c=[],l,f,s,o=0,a=h.length;o<a;o++)l=rf(h[o],t,i,r,u),c.push(l);if(f={results:c}
 ,d(n)){for(s in n)s.indexOf("#")===0&&(f.__metadata=f.__metadata||{},sv(s.substring(1),n[s],f,i,r));f=ri(n,f,i)}return f},cv=function(n,t){var r,i=t.key.propertyRef,f,e,u;if(r="(",i.length==1)f=bt(t.property,i[0].name).type,r+=oo(n[i[0].name],f);else for(e=!0,u=0;u<i.length;u++)e?e=!1:r+=",",f=bt(t.property,i[u].name).type,r+=i[u].name+"="+oo(n[i[u].name],f);return r+=")"},hn=function(n,t,i,r,u,f){var o=n[h.id]||n[h.read]||n[h.edit]||t.entitySet.name+t.key,e;n[h.id]=r+o,n[h.edit]||(n[h.edit]=t.entitySet.name+t.key,t.entitySet.entityType!=i&&(n[h.edit]+="/"+i)),n[h.read]=n[h.read]||n[h.edit],n[h.etag]||(e=cn(n,u,f),!e||(n[h.etag]=e)),yn(n,u,f),ln(n,u,f),vn(n,t)},cn=function(n,t,i){for(var u="",f,r=0;t.property&&r<t.property.length;r++)f=t.property[r],u=lv(n,u,f);if(i)for(r=0;i.property&&r<i.property.length;r++)f=i.property[r],u=lv(n,u,f);return u.length>0?u+'"':null},lv=function(n,t,i){return i.concurrencyMode=="Fixed"&&(t+=t.length>0?",":'W/"',t+=n[i.name]!==null?oo(n[i.name],i.type
 ):"null"),t},ln=function(n,i,r){for(var s="@odata.navigationLinkUrl",c="@odata.associationLinkUrl",u,e,o,f=0;i.navigationProperty&&f<i.navigationProperty.length;f++)u=i.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u));if(r&&r.navigationProperty)for(f=0;f<r.navigationProperty.length;f++)u=r.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u))},oo=function(n,t){n=""+an(n,t),n=encodeURIComponent(n.replace("'","''"));switch(t){case"Edm.Binary":return"X'"+n+"'";case"Edm.DateTime":return"datetime'"+n+"'";case"Edm.DateTimeOffset":return"datetimeoffset'"+n+"'";case"Edm.Decimal":return n+"M";case"Edm.Guid":return"guid'"+n+"'";case"Edm.Int64":return n+"L";case"Edm.Float":return n+"f";case"Edm.Double":return n+"D";case"Edm.Geography":return"geography'"+n+"'";case"Edm.Geometry":return"geometry'"+
 n+"'";case"Edm.Time":return"time'"+n+"'";case"Edm.String":return"'"+n+"'";default:return n}},an=function(n,t){switch(t){case"Edm.Binary":return hp(n);default:return n}},vn=function(n,i){for(var u=i.functionImport||[],f,r=0;r<u.length;r++)u[r].isBindable&&u[r].parameter[0]&&u[r].parameter[0].type==i.entitySet.entityType&&(f="#"+i.containerName+"."+u[r].name,n[f]==t&&(n[f]={title:u[r].name,target:n[h.edit]+"/"+u[r].name}))},yn=function(n,t,i){(t.hasStream||i&&i.hasStream)&&(n[h.mediaEdit]=n[h.mediaEdit]||n[h.mediaEdit]+"/$value",n[h.mediaRead]=n[h.mediaRead]||n[h.mediaEdit])},pn=function(n,t,i,r){var u={type:t},f=eo(n.value,t,u,i,null,null,r);return ri(n,{__metadata:u,value:f},i)},wn=function(n,t,i,r,u){var f={},e=ov(n.value,t,f,i,r,u);return g(e.__metadata,f),ri(n,e,i)},bn=function(n,t){var r=n.value,u,i,f,o;if(!e(r))return av(n,t);for(u=[],i=0,f=r.length;i<f;i++)u.push(av(r[i],t));return o={results:u},ri(n,o,t)},av=function(n,t){var i={uri:c(n.url,t)},u,r;return i=ri(n,i,t),u=i.__me
 tadata||{},r=u.properties||{},uf(r.url),iu(r,"url","uri"),i},uf=function(n){n&&delete n.type},kn=function(n,t){var o=n.value,s=[],h=ri(n,{collections:s},t),e=h.__metadata||{},i=e.properties||{},u,l,f,r;for(uf(i.value),iu(i,"value","collections"),u=0,l=o.length;u<l;u++)f=o[u],r={title:f.name,href:c(f.url,t)},r=ri(f,r,t),e=r.__metadata||{},i=e.properties||{},uf(i.name),uf(i.url),iu(i,"name","title"),iu(i,"url","href"),s.push(r);return{workspaces:[h]}},ui=function(n,t){return{kind:n,type:t||null}},dn=function(n,t,i){var f=n[io],s,v,o,y,l,r,p,h,c,w,b,u,k;if(!f||typeof f!="string")return null;if(s=f.lastIndexOf("#"),s===-1)return ui(rv);if(v=f.indexOf("@Element",s),o=v-1,o<0&&(o=f.indexOf("?",s),o===-1&&(o=f.length)),y=f.substring(s+1,o),y.indexOf("/$links/")>0)return ui(uv);if(l=y.split("/"),l.length>=0){if(r=l[0],p=l[1],fo(r))return ui(tv,r);if(vu(r))return ui(iv,r);if(h=p,!p){var d=r.lastIndexOf("."),g=r.substring(d+1),a=g===r?tc(t):ic(r.substring(0,d),t);a&&(c=yw(a.entitySet,g),w=a.f
 unctionImport,b=a.name,h=!c?null:c.entityType)}return v>0?(u=ui(nv,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):h?(u=ui(to,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):e(n.value)&&!di(r,t)&&(k=n.value[0],!yu(k)&&(ev(k)||!i))?ui(to,null):ui(nv,r)}return null},gn=function(n,t,i,r,u){var e,f,o;if(!d(n))return n;if(u=u||"minimalmetadata",e=n[io],f=dn(n,t,r),ot(f)&&(f.contentTypeOdata=u),o=null,f){delete n[io],o=f.type;switch(f.kind){case to:return hv(n,f,e,t,i);case iv:return wn(n,o,e,t,i);case tv:return pn(n,o,e,i);case rv:return kn(n,e);case uv:return bn(n,e)}}return rf(n,f,e,t,i)},vv=["type","etag","media_src","edit_media","content_type","media_etag"],yv=function(n,t){var u=/\/\$links\//,i={},r=n.__metadata,f=t&&u.test(t.request.requestUri);return so(n,r&&r.properties,i,f),i},ntt=function(n,t){var i,u,r,f;if(n)for(i=0,u=vv.length;i<u;i++)r=vv[i],f=ii+(tf[r]||r),kr(f,null,n[r],t)},so=function(n,t,i,r){var u,f;for(u in n)f=n[u],u==="__metadata"?ntt(f,i):u.indexO
 f(".")===-1?r&&u==="uri"?itt(f,i):ttt(u,f,t,i,r):i[u]=f},ttt=function(n,i,r,u){var e=r&&r[n]||{properties:t,type:t},f=ss(i,e);if(yu(i)||!i){kr(tr,n,f,u),u[n]=i;return}if(ar(i,f)||dh(i)){ftt(n,i,u);return}if(!f&&kh(i)){rtt(n,i,u);return}if(bh(i,f)){au(f)&&kr(tr,n,f,u),utt(n,i,u);return}u[n]={},kr(tr,null,f,u[n]),so(i,e.properties,u[n])},itt=function(n,t){t.url=n},rtt=function(n,t,i){kr(fv,n,t.__deferred.uri,i)},utt=function(n,t,i){i[n]=[];var r=e(t)?t:t.results;so(r,null,i[n])},ftt=function(n,t,i){if(ar(t)){i[n]=[];for(var u=e(t)?t:t.results,r=0,f=u.length;r<f;r++)pv(n,u[r],!0,i);return}pv(n,t,!1,i)},pv=function(n,t,i,r){var f=t.__metadata&&t.__metadata.uri,u;if(f){ett(n,f,i,r);return}if(u=yv(t),i){r[n].push(u);return}r[n]=u},ett=function(n,t,i,r){var u=n+kg;if(i){r[u]=r[u]||[],r[u].push(t);return}r[u]=t},kr=function(n,i,r,u){r!==t&&(i?u[i+"@"+n]=r:u[n]=r)},wv="application/json",bv=gi(wv),kv=function(n){var r=[],t,i,u;for(t in n)for(i=0,u=n[t].length;i<u;i++)r.push(g({metadata:t},n[t
 ][i]));return r},ott=function(n,t,i,r){var c,f,l,u,o,s,v,e,h,a;if(n&&typeof n=="object")if(f=n.__metadata,f&&(f.actions&&(f.actions=kv(f.actions)),f.functions&&(f.functions=kv(f.functions)),c=f&&f.type),l=kt(c,t)||di(c,t),l){if(o=l.property,o)for(s=0,v=o.length;s<v;s++)if(e=o[s],h=e.name,u=n[h],e.type==="Edm.DateTime"||e.type==="Edm.DateTimeOffset"){if(u){if(u=i(u),!u)throw{message:"Invalid date/time value"};n[h]=u}}else e.type==="Edm.Time"&&(n[h]=he(u))}else if(r)for(a in n)u=n[a],typeof u=="string"&&(n[a]=i(u)||u);return n},dv=function(n){if(n){var t=n.properties.odata;return t==="nometadata"||t==="minimalmetadata"||t==="fullmetadata"}return!1},stt=function(n,t){for(var u={collections:[]},r,e,i=0,f=n.EntitySets.length;i<f;i++)r=n.EntitySets[i],e={title:r,href:c(r,t)},u.collections.push(e);return{workspaces:[u]}},htt=/^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/,ctt=function(n){var t,i;return n<0?(t="-",n=-n):t="+",i=Math.floor(n/60),n=n-60*i,t+a(i,2)+":"+a(n,2)},ltt=function(n){var i=n&&ht
 t.exec(n),t,r,u;if(i&&(t=new Date(s(i[1])),i[2]&&(r=s(i[3]),i[2]==="-"&&(r=-r),u=t.getUTCMinutes(),t.setUTCMinutes(u-r),t.__edmType="Edm.DateTimeOffset",t.__offset=ctt(r)),!isNaN(t.valueOf())))return t},att=function(t,i,r){var f=it(r.recognizeDates,t.recognizeDates),h=it(r.inferJsonLightFeedAsObject,t.inferJsonLightFeedAsObject),e=r.metadata,o=r.dataServiceVersion,s=ltt,u=typeof i=="string"?n.JSON.parse(i):i;if(ct("4.0",o)===o){if(dv(r.contentType))return gn(u,e,f,h,r.contentType.properties.odata);s=pu}return u=tb(u.d,function(n,t){return ott(t,e,s,f)}),u=wtt(u,r.dataServiceVersion),ptt(u,r.response.requestUri)},gv=function(t){var i,r=Date.prototype.toJSON;try{Date.prototype.toJSON=function(){return yh(this)},i=n.JSON.stringify(t,ytt)}finally{Date.prototype.toJSON=r}return i},vtt=function(n,i,r){var e=r.dataServiceVersion||"1.0",o=it(r.useJsonLight,n.useJsonLight),u=r.contentType=r.contentType||bv,f;return u&&u.mediaType===bv.mediaType?(f=i,o||dv(u))?(r.dataServiceVersion=ct(e,"4.0"
 ),f=yv(i,r),gv(f)):(ct("4.0",e)===e&&(u.properties.odata="verbose",r.contentType=u),gv(f)):t},ytt=function(n,t){return t&&t.__edmType==="Edm.Time"?ph(t):t},ptt=function(n,t){var i=d(n)&&!n.__metadata&&e(n.EntitySets);return i?stt(n,t):n},wtt=function(n,t){return t&&t.lastIndexOf(";")===t.length-1&&(t=t.substr(0,t.length-1)),t&&t!=="1.0"||e(n)&&(n={results:n}),n},ff=li(att,vtt,wv,ci);ff.recognizeDates=!1,ff.useJsonLight=!1,ff.inferJsonLightFeedAsObject=!1,r.jsonHandler=ff;var dr="multipart/mixed",btt=/^HTTP\/1\.\d (\d{3}) (.*)$/i,ktt=/^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/,ho=function(){return Math.floor((1+Math.random())*65536).toString(16).substr(1)},ny=function(n){return n+ho()+"-"+ho()+"-"+ho()},ty=function(n){return n.handler.partHandler},iy=function(n){var t=n.boundaries;return t[t.length-1]},dtt=function(n,t,i){var r=i.contentType.properties.boundary;return{__batchResponses:ry(t,{boundaries:[r],handlerContext:i})}},gtt=function(n,t,i){var r=i.contentType=i.contentType||gi(
 dr);if(r.mediaType===dr)return nit(t,i)},ry=function(n,t){var f="--"+iy(t),u,o,s,r,e,i;for(ef(n,t,f),ir(n,t),u=[];o!=="--"&&t.position<n.length;){if(s=uy(n,t),r=gi(s["Content-Type"]),r&&r.mediaType===dr){t.boundaries.push(r.properties.boundary);try{e=ry(n,t)}catch(h){h.response=fy(n,t,f),e=[h]}u.push({__changeResponses:e}),t.boundaries.pop(),ef(n,t,"--"+iy(t))}else{if(!r||r.mediaType!=="application/http")throw{message:"invalid MIME part type "};ir(n,t),i=fy(n,t,f);try{i.statusCode>=200&&i.statusCode<=299?ty(t.handlerContext).read(i,t.handlerContext):i={message:"HTTP request failed",response:i}}catch(h){i=h}u.push(i)}o=n.substr(t.position,2),ir(n,t)}return u},uy=function(n,t){var r={},i,u,f;do f=t.position,u=ir(n,t),i=ktt.exec(u),i!==null?r[i[1]]=i[2]:t.position=f;while(u&&i);return ee(r),r},fy=function(n,t,i){var o=t.position,r=btt.exec(ir(n,t)),u,f,e;return r?(u=r[1],f=r[2],e=uy(n,t),ir(n,t)):t.position=o,{statusCode:u,statusText:f,headers:e,body:ef(n,t,"\r\n"+i)}},ir=function(n,t)
 {return ef(n,t,"\r\n")},ef=function(n,t,i){var u=t.position||0,r=n.length;if(i){if(r=n.indexOf(i,u),r===-1)return null;t.position=r+i.length}else t.position=r;return n.substring(u,r)},nit=function(n,t){var o;if(!lw(n))throw{message:"Data is not a batch object."};for(var r=ny("batch_"),f=n.__batchRequests,u="",i=0,e=f.length;i<e;i++)u+=of(r,!1)+ey(f[i],t);return u+=of(r,!0),o=t.contentType.properties,o.boundary=r,u},of=function(n,t){var i="\r\n--"+n;return t&&(i+="--"),i+"\r\n"},ey=function(n,t,i){var s=n.__changeRequests,r,f,o,h,u;if(e(s)){if(i)throw{message:"Not Supported: change set nested in other change set"};for(f=ny("changeset_"),r="Content-Type: "+dr+"; boundary="+f+"\r\n",o=0,h=s.length;o<h;o++)r+=of(f,!1)+ey(s[o],t,!0);r+=of(f,!0)}else r="Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\n",u=g({},t),u.handler=li,u.request=n,u.contentType=null,oc(n,ty(t),u),r+=tit(n);return r},tit=function(n){var t=(n.method?n.method:"GET")+" "+n.requestUri+" HTTP/1.
 1\r\n",i;for(i in n.headers)n.headers[i]&&(t=t+i+": "+n.headers[i]+"\r\n");return t+="\r\n",n.body&&(t+=n.body),t};r.batchHandler=li(dtt,gtt,dr,ci),co=[r.jsonHandler,r.atomHandler,r.xmlHandler,r.textHandler],lo=function(n,t,i){for(var r=0,u=co.length;r<u&&!co[r][n](t,i);r++);if(r===u)throw{message:"no handler for data"};},r.defaultSuccess=function(t){n.alert(n.JSON.stringify(t))},r.defaultError=ru,r.defaultHandler={read:function(n,t){n&&ot(n.body)&&n.headers["Content-Type"]&&lo("read",n,t)},write:function(n,t){lo("write",n,t)},maxDataServiceVersion:ci,accept:"application/atomsvc+xml;q=0.8, application/json;odata.metadata=full;q=0.7, application/json;q=0.5, */*;q=0.1"},r.defaultMetadata=[],r.read=function(n,t,i,u,f,e){var o;return o=n instanceof String||typeof n=="string"?{requestUri:n}:n,r.request(o,t,i,u,f,e)},r.request=function(n,t,i,u,f,e){t=t||r.defaultSuccess,i=i||r.defaultError,u=u||r.defaultHandler,f=f||r.defaultHttpClient,e=e||r.defaultMetadata,n.recognizeDates=it(n.recogniz
 eDates,r.jsonHandler.recognizeDates),n.callbackParameterName=it(n.callbackParameterName,r.defaultHttpClient.callbackParameterName),n.formatQueryString=it(n.formatQueryString,r.defaultHttpClient.formatQueryString),n.enableJsonpCallback=it(n.enableJsonpCallback,r.defaultHttpClient.enableJsonpCallback),n.useJsonLight=it(n.useJsonLight,r.jsonHandler.enableJsonpCallback),n.inferJsonLightFeedAsObject=it(n.inferJsonLightFeedAsObject,r.jsonHandler.inferJsonLightFeedAsObject);var o={metadata:e,recognizeDates:n.recognizeDates,callbackParameterName:n.callbackParameterName,formatQueryString:n.formatQueryString,enableJsonpCallback:n.enableJsonpCallback,useJsonLight:n.useJsonLight,inferJsonLightFeedAsObject:n.inferJsonLightFeedAsObject};try{return oc(n,u,o),cw(n,t,i,u,f,o)}catch(s){i(s)}},r.parseMetadata=function(n){return ga(null,n)},r.batchHandler.partHandler=r.defaultHandler;var ft=null,iit=function(){var t={v:this.valueOf(),t:"[object Date]"},n;for(n in this)t[n]=this[n];return t},rit=functio
 n(n,t){var r,i;if(t&&t.t==="[object Date]"){r=new Date(t.v);for(i in t)i!=="t"&&i!=="v"&&(r[i]=t[i]);t=r}return t},sf=function(n,t){return n.name+"#!#"+t},oy=function(n,t){return t.replace(n.name+"#!#","")},y=function(n){this.name=n};y.create=function(t){if(y.isSupported())return ft=ft||n.localStorage,new y(t);throw{message:"Web Storage not supported by the browser"};},y.isSupported=function(){return!!n.localStorage},y.prototype.add=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?o(r,{message:"key already exists",key:n}):u.addOrUpdate(n,t,i,r)},r)},y.prototype.addOrUpdate=function(i,r,u,f){var s,h,e;if(f=f||this.defaultError,i instanceof Array)f({message:"Array of keys not supported"});else{s=sf(this,i),h=Date.prototype.toJSON;try{e=r,e!==t&&(Date.prototype.toJSON=iit,e=n.JSON.stringify(r)),ft.setItem(s,e),o(u,i,r)}catch(c){c.code===22||c.number===2147942414?o(f,{name:"QUOTA_EXCEEDED_ERR",error:c}):o(f,c)}finally{Date.prototype.toJSON=h}}},y.prototy
 pe.clear=function(n,t){var i,r,u,f;t=t||this.defaultError;try{for(i=0,r=ft.length;r>0&&i<r;)u=ft.key(i),f=oy(this,u),u!==f?(ft.removeItem(u),r=ft.length):i++;o(n)}catch(e){o(t,e)}},y.prototype.close=function(){},y.prototype.contains=function(n,t,i){i=i||this.defaultError;try{var r=sf(this,n),u=ft.getItem(r);o(t,u!==null)}catch(f){o(i,f)}},y.prototype.defaultError=ru,y.prototype.getAllKeys=function(n,t){var r,i,e,u,f;t=t||this.defaultError,r=[];try{for(i=0,e=ft.length;i<e;i++)u=ft.key(i),f=oy(this,u),u!==f&&r.push(f);o(n,r)}catch(s){o(t,s)}},y.prototype.mechanism="dom",y.prototype.read=function(i,r,u){if(u=u||this.defaultError,i instanceof Array)u({message:"Array of keys not supported"});else try{var e=sf(this,i),f=ft.getItem(e);f=f!==null&&f!=="undefined"?n.JSON.parse(f,rit):t,o(r,i,f)}catch(s){o(u,s)}},y.prototype.remove=function(n,t,i){if(i=i||this.defaultError,n instanceof Array)i({message:"Batches not supported"});else try{var r=sf(this,n);ft.removeItem(r),o(t)}catch(u){o(i,u)}}
 ,y.prototype.update=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?u.addOrUpdate(n,t,i,r):o(r,{message:"key not found",key:n})},r)};var sy=n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB||n.indexedDB,uit=n.IDBKeyRange||n.webkitIDBKeyRange,hy=n.IDBTransaction||n.webkitIDBTransaction||{},cy=hy.READ_ONLY||"readonly",rr=hy.READ_WRITE||"readwrite",yt=function(n,t){return function(i){var r=n||t,u,f;if(r){if(Object.prototype.toString.call(i)==="[object IDBDatabaseException]"){if(i.code===11){r({name:"QuotaExceededError",error:i});return}r(i);return}try{f=i.target.error||i,u=f.name}catch(e){u=i.type==="blocked"?"IndexedDBBlocked":"UnknownError"}r({name:u,error:i})}}},fit=function(n,t,i){var u=n.name,f="_datajs_"+u,r=sy.open(f);r.onblocked=i,r.onerror=i,r.onupgradeneeded=function(){var n=r.result;n.objectStoreNames.contains(u)||n.createObjectStore(u)},r.onsuccess=function(n){var f=r.result,e;if(!f.objectStoreNames.contains(u)){if("setVersion"in f){e=f.setV
 ersion("1.0"),e.onsuccess=function(){var n=e.transaction;n.oncomplete=function(){t(f)},f.createObjectStore(u,null,!1)},e.onerror=i,e.onblocked=i;return}n.target.error={name:"DBSchemaMismatch"},i(n);return}f.onversionchange=function(n){n.target.close()},t(f)}},fi=function(n,t,i,r){var u=n.name,f=n.db,e=yt(r,n.defaultError);if(f){i(f.transaction(u,t));return}fit(n,function(r){n.db=r,i(r.transaction(u,t))},e)},w=function(n){this.name=n};w.create=function(n){if(w.isSupported())return new w(n);throw{message:"IndexedDB is not supported on this browser"};},w.isSupported=function(){return!!sy},w.prototype.add=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){s.onabort=yt(r,o,n,"add"),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)};for(var h=0;h<u.length&&h<f.length;h++)s.objectStore(e).add({v:f[h]},u[h])},r)},w.prototype.addOrUpdate=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n inst
 anceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){var h,c;for(s.onabort=yt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c={v:f[h]},s.objectStore(e).put(c,u[h])},r)},w.prototype.clear=function(n,t){var i=this.name,r=this.defaultError;fi(this,rr,function(u){u.onerror=yt(t,r),u.oncomplete=function(){n()},u.objectStore(i).clear()},t)},w.prototype.close=function(){this.db&&(this.db.close(),this.db=null)},w.prototype.contains=function(n,t,i){var r=this.name,u=this.defaultError;fi(this,cy,function(f){var e=f.objectStore(r),o=e.get(n);f.oncomplete=function(){t(!!o.result)},f.onerror=yt(i,u)},i)},w.prototype.defaultError=ru,w.prototype.getAllKeys=function(n,t){var i=this.name,r=this.defaultError;fi(this,rr,function(u){var e=[],f;u.oncomplete=function(){n(e)},f=u.objectStore(i).openCursor(),f.onerror=yt(t,r),f.onsuccess=function(n){var t=n.target.result;t&&(e.push(t.key),t["continue"].call(t))}},t)},w.prototype.mechanism="indexeddb",w
 .prototype.read=function(n,i,r){var f=this.name,e=this.defaultError,u=n instanceof Array?n:[n];fi(this,cy,function(o){var h=[],s,c,l;for(o.onerror=yt(r,e,n,"read"),o.oncomplete=function(){n instanceof Array?i(u,h):i(u[0],h[0])},s=0;s<u.length;s++)c=o.objectStore(f),l=c.get.call(c,u[s]),l.onsuccess=function(n){var i=n.target.result;h.push(i?i.v:t)}},r)},w.prototype.remove=function(n,t,i){var u=this.name,f=this.defaultError,r=n instanceof Array?n:[n];fi(this,rr,function(n){var e,o;for(n.onerror=yt(i,f),n.oncomplete=function(){t()},e=0;e<r.length;e++)o=n.objectStore(u),o["delete"].call(o,r[e])},i)},w.prototype.update=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){var h,c,l;for(s.onabort=yt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c=s.objectStore(e).openCursor(uit.only(u[h])),l={v:f[h]},c.pair={key:u[h],value:l},c.onsuccess=function(n){var t=n.target.re
 sult;t?t.update(n.target.pair.value):s.abort()}},r)},ei=function(n){var e=[],r=[],i={},u,f;this.name=n,u=function(n){return n||this.defaultError},f=function(n,i){var r;return(n instanceof Array&&(r="Array of keys not supported"),(n===t||n===null)&&(r="Invalid key"),r)?(o(i,{message:r}),!1):!0},this.add=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?e({message:"key already exists",key:n}):this.addOrUpdate(n,t,r,e))},this.addOrUpdate=function(n,s,h,c){if(c=u(c),f(n,c)){var l=i[n];l===t&&(l=e.length>0?e.splice(0,1):r.length),r[l]=s,i[n]=l,o(h,n,s)}},this.clear=function(n){r=[],i={},e=[],o(n)},this.contains=function(n,t){var r=i.hasOwnProperty(n);o(t,r)},this.getAllKeys=function(n){var t=[],r;for(r in i)t.push(r);o(n,t)},this.read=function(n,t,e){if(e=u(e),f(n,e)){var s=i[n];o(t,n,r[s])}},this.remove=function(n,s,h){if(h=u(h),f(n,h)){var c=i[n];c!==t&&(c===r.length-1?r.pop():(r[c]=t,e.push(c)),delete i[n],r.length===0&&(e=[])),o(s)}},this.update=function(n,t,r,e){e=u(e),f(n,e)&&(
 i.hasOwnProperty(n)?this.addOrUpdate(n,t,r,e):e({message:"key not found",key:n}))}},ei.create=function(n){return new ei(n)},ei.isSupported=function(){return!0},ei.prototype.close=function(){},ei.prototype.defaultError=ru,ei.prototype.mechanism="memory",ly={indexeddb:w,dom:y,memory:ei},pt.defaultStoreMechanism="best",pt.createStore=function(n,t){t||(t=pt.defaultStoreMechanism),t==="best"&&(t=y.isSupported()?"dom":"memory");var i=ly[t];if(i)return i.create(n);throw{message:"Failed to create store",name:n,mechanism:t};};var eit=function(n,t){var i=n.indexOf("?")>=0?"&":"?";return n+i+t},oit=function(n,t){var i=n.indexOf("?"),r="";return i>=0&&(r=n.substr(i),n=n.substr(0,i)),n[n.length-1]!=="/"&&(n+="/"),n+t+r},ay=function(n,t){return{method:"GET",requestUri:n,user:t.user,password:t.password,enableJsonpCallback:t.enableJsonpCallback,callbackParameterName:t.callbackParameterName,formatQueryString:t.formatQueryString}},pit=function(n,t){var u=-1,r=n.indexOf("?"),i;return r!==-1&&(i=n.inde
 xOf("?"+t+"=",r),i===-1&&(i=n.indexOf("&"+t+"=",r)),i!==-1&&(u=i+t.length+2)),u},sit=function(n,t,i,r){return vy(n,t,[],i,r)},vy=function(n,i,u,f,e){var s=ay(n,i),o=r.request(s,function(n){var t=n.__next,r=n.results;u=u.concat(r),t?o=vy(t,i,u,f,e):f(u)},e,t,i.httpClient,i.metadata);return{abort:function(){o.abort()}}},hit=function(n){var i=this,u=n.source;return i.identifier=ep(encodeURI(decodeURI(u))),i.options=n,i.count=function(n,f){var e=i.options;return r.request(ay(oit(u,"$count"),e),function(t){var i=s(t.toString());isNaN(i)?f({message:"Count is NaN",count:i}):n(i)},f,t,e.httpClient,e.metadata)},i.read=function(n,t,r,f){var e="$skip="+n+"&$top="+t;return sit(eit(u,e),i.options,r,f)},i},cit=function(n,t){var r=lit(n,t),i,u;r&&(i=r.i-t.i,u=i+(n.c-n.d.length),n.d=n.d.concat(t.d.slice(i,u)))},lit=function(n,t){var r=n.i+n.c,u=t.i+t.c,i=n.i>t.i?n.i:t.i,f=r<u?r:u,e;return f>=i&&(e={i:i,c:f-i}),e},yy=function(n,i){if(n===t||typeof n!="number")throw{message:"'"+i+"' must be a number.
 "};if(isNaN(n)||n<0||!isFinite(n))throw{message:"'"+i+"' must be greater than or equal to zero."};},ait=function(n,i){if(n!==t){if(typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<=0||!isFinite(n))throw{message:"'"+i+"' must be greater than zero."};}},py=function(n,i){if(n!==t&&(typeof n!="number"||isNaN(n)||!isFinite(n)))throw{message:"'"+i+"' must be a number."};},ao=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return n.splice(i,1),!0;return!1},wy=function(n){var t=0,r=typeof n,i;if(r==="object"&&n)for(i in n)t+=i.length*2+wy(n[i]);else t=r==="string"?n.length*2:8;return t},by=function(n,t,i){return n=Math.floor(n/i)*i,t=Math.ceil((t+1)/i)*i,{i:n,c:t-n}},hf="destroy",ai="idle",ky="init",vo="read",yo="prefetch",po="write",gr="cancel",oi="end",wo="error",vi="start",dy="wait",gy="clear",nu="done",tu="local",np="save",tp="source",ur=function(n,t,i,r,u,f,e){var h,c,o=this,l,s;return o.p=t,o.i=r,o.c=u,o.d=f,o.s=vi,o.canceled=!1,o.pending=e,o.oncom
 plete=null,o.cancel=function(){if(i){var n=o.s;n!==wo&&n!==oi&&n!==gr&&(o.canceled=!0,s(gr,h))}},o.complete=function(){s(oi,h)},o.error=function(n){o.canceled||s(wo,n)},o.run=function(n){c=n,o.transition(o.s,h)},o.wait=function(n){s(dy,n)},l=function(t,i,r){switch(t){case vi:i!==ky&&n(o,t,i,r);break;case dy:n(o,t,i,r);break;case gr:n(o,t,i,r),o.fireCanceled(),s(oi);break;case wo:n(o,t,i,r),o.canceled=!0,o.fireRejected(r),s(oi);break;case oi:if(o.oncomplete)o.oncomplete(o);o.canceled||o.fireResolved(),n(o,t,i,r);break;default:n(o,t,i,r)}},s=function(n,t){o.s=n,h=t,l(n,c,t)},o.transition=s,o};ur.prototype.fireResolved=function(){var n=this.p;n&&(this.p=null,n.resolve(this.d))},ur.prototype.fireRejected=function(n){var t=this.p;t&&(this.p=null,t.reject(n))},ur.prototype.fireCanceled=function(){this.fireRejected({canceled:!0,message:"Operation canceled"})},ip=function(i){var it=ky,y={counts:0,netReads:0,prefetches:0,cacheReads:0},c=[],b=[],p=[],nt=0,l=!1,k=af(i.cacheSize,1048576),a=0,h=
 0,d=0,tt=k===0,r=af(i.pageSize,50),ut=af(i.prefetchSize,r),ht="1.0",f,ft=0,w=i.source,v,u;typeof w=="string"&&(w=new hit(i)),w.options=i,v=pt.createStore(i.name,i.mechanism),u=this,u.onidle=i.idle,u.stats=y,u.count=function(){var n,i,t;if(f)throw f;return(n=su(),i=!1,l)?(o(function(){n.resolve(a)}),n.promise()):(t=w.count(function(i){t=null,y.counts++,n.resolve(i)},function(r){t=null,n.reject(g(r,{canceled:i}))}),g(n.promise(),{cancel:function(){t&&(i=!0,t.abort(),t=null)}}))},u.clear=function(){if(f)throw f;if(c.length===0){var n=su(),t=new ur(ii,n,!1);return et(t,c),n.promise()}return c[0].p},u.filterForward=function(n,t,i){return lt(n,t,i,!1)},u.filterBack=function(n,t,i){return lt(n,t,i,!0)},u.readRange=function(n,t){if(yy(n,"index"),yy(t,"count"),f)throw f;var i=su(),r=new ur(ui,i,!0,n,t,[],0);return et(r,b),g(i.promise(),{cancel:function(){r.cancel()}})},u.ToObservable=u.toObservable=function(){if(!n.Rx||!n.Rx.Observable)throw{message:"Rx library not available - include rx.js"
 };if(f)throw f;return n.Rx.Observable.CreateWithDisposable(function(n){var t=!1,i=0,f=function(i){t||n.OnError(i)},e=function(o){if(!t){for(var s=0,h=o.length;s<h;s++)n.OnNext(o[s]);o.length<r?n.OnCompleted():(i+=r,u.readRange(i,r).then(e,f))}};return u.readRange(i,r).then(e,f),{Dispose:function(){t=!0}}})};var rt=function(n){return function(t){f={message:n,error:t};for(var i=0,r=b.length;i<r;i++)b[i].fireRejected(f);for(i=0,r=c.length;i<r;i++)c[i].fireRejected(f);b=c=null}},e=function(n){if(n!==it){it=n;for(var i=c.concat(b,p),t=0,r=i.length;t<r;t++)i[t].run(it)}},ct=function(){var n=new ki;return v.clear(function(){nt=0,l=!1,a=0,h=0,d=0,tt=k===0,y={counts:0,netReads:0,prefetches:0,cacheReads:0},u.stats=y,v.close(),n.resolve()},function(t){n.reject(t)}),n},kt=function(n){var t=ao(c,n);t||(t=ao(b,n),t||ao(p,n)),ft--,e(ai)},dt=function(n){var t=new ki,u=!1,i=w.read(n,r,function(i){var r={i:n,c:i.length,d:i};t.resolve(r)},function(n){t.reject(n)});return g(t,{cancel:function(){i&&(i.a
 bort(),u=!0,i=null)}})},lt=function(n,t,i,e){if(n=s(n),t=s(t),isNaN(n))throw{message:"'index' must be a valid number.",index:n};if(isNaN(t))throw{message:"'count' must be a valid number.",count:t};if(f)throw f;n=Math.max(n,0);var h=su(),o=[],a=!1,l=null,v=function(n,f){a||(t>=0&&o.length>=t?h.resolve(o):l=u.readRange(n,f).then(function(u){for(var l,a,y,p,s=0,c=u.length;s<c&&(t<0||o.length<t);s++)l=e?c-s-1:s,a=u[l],i(a)&&(y={index:n+l,item:a},e?o.unshift(y):o.push(y));!e&&u.length<f||e&&n<=0?h.resolve(o):(p=e?Math.max(n-r,0):n+f,v(p,r))},function(n){h.reject(n)}))},c=by(n,n,r),y=e?c.i:n,p=e?n-c.i+1:c.i+c.c-n;return v(y,p),g(h.promise(),{cancel:function(){l&&l.cancel(),a=!0}})},at=function(){u.onidle&&ft===0&&u.onidle()},gt=function(n){if(!l&&ut!==0&&!tt&&(p.length===0||p[0]&&p[0].c!==-1)){var t=new ur(ri,null,!0,n,ut,null,ut);et(t,p)}},et=function(n,t){n.oncomplete=kt,t.push(n),ft++,n.run(it)},ni=function(n){var r=!1,i=g(new ki,{cancel:function(){r=!0}}),u=vt(i,"Read page from store 
 failure");return v.contains(n,function(f){if(!r){if(f){v.read(n,function(n,u){r||i.resolve(u!==t,u)},u);return}i.resolve(!1)}},u),i},ti=function(n,t){var e=!1,i=g(new ki,{cancel:function(){e=!0}}),r=vt(i,"Save page to store failure"),u=function(){i.resolve(!0)},f;return t.c>0?(f=wy(t),tt=k>=0&&k<nt+f,tt?u():v.addOrUpdate(n,t,function(){yt(t,f),st(u,r)},r)):(yt(t,0),st(u,r)),i},st=function(n,t){var i={actualCacheSize:nt,allDataLocal:l,cacheSize:k,collectionCount:a,highestSavedPage:h,highestSavedPageSize:d,pageSize:r,sourceId:w.identifier,version:ht};v.addOrUpdate("__settings",i,n,t)},vt=function(n){return function(){n.resolve(!1)}},yt=function(n,t){var i=n.c,u=n.i;i===0?h===u-r&&(a=h+d):(h=Math.max(h,u),h===u&&(d=i),nt+=t,i<r&&!a&&(a=u+i)),l||a!==h+d||(l=!0)},wt=function(n,t,i,r){var u=n.canceled&&t!==oi;return u&&t===gr&&r&&r.cancel&&r.cancel(),u},ii=function(n,t,i){var r=n.transition;if(i!==hf)return e(hf),!0;switch(t){case vi:r(gy);break;case oi:at();break;case gy:ct().then(functi
 on(){n.complete()}),n.wait();break;default:return!1}return!0},ri=function(n,t,i,u){var o,f;if(!wt(n,t,i,u)){if(o=n.transition,i!==yo)return i===hf?t!==gr&&n.cancel():i===ai&&e(yo),!0;switch(t){case vi:p[0]===n&&o(tu,n.i);break;case nu:f=n.pending,f>0&&(f-=Math.min(f,u.c)),l||f===0||u.c<r||tt?n.complete():(n.pending=f,o(tu,u.i+r));break;default:return bt(n,t,i,u,!0)}}return!0},ui=function(n,t,i,u){var f,o,s;if(!wt(n,t,i,u)){if(f=n.transition,i!==vo&&t!==vi)return i===hf?t!==vi&&n.cancel():i!==po&&e(vo),!0;switch(t){case vi:(i===ai||i===yo)&&(e(vo),n.c>0?(o=by(n.i,n.c,r),f(tu,o.i)):f(nu,n));break;case nu:cit(n,u),s=n.d.length,n.c===s||u.c<r?(y.cacheReads++,gt(u.i+u.c),n.complete()):f(tu,u.i+r);break;default:return bt(n,t,i,u,!1)}}return!0},bt=function(n,t,i,r,u){var s=n.error,o=n.transition,h=n.wait,f;switch(t){case oi:at();break;case tu:f=ni(r).then(function(t,i){n.canceled||(t?o(nu,i):o(tp,r))});break;case tp:f=dt(r).then(function(t){n.canceled||(u?y.prefetches++:y.netReads++,o(np,t
 ))},s);break;case np:i!==po&&(e(po),f=ti(r.i,r).then(function(t){n.canceled||(!t&&u&&(n.pending=0),o(nu,r)),e(ai)}));break;default:return!1}return f&&(n.canceled?f.cancel():n.s===t&&h(f)),!0};return v.read("__settings",function(n,t){if(ot(t)){var i=t.version;if(!i||i.indexOf("1.")!==0){rt("Unsupported cache store version "+i)();return}r!==t.pageSize||w.identifier!==t.sourceId?ct().then(function(){e(ai)},rt("Unable to clear store during initialization")):(nt=t.actualCacheSize,l=t.allDataLocal,k=t.cacheSize,a=t.collectionCount,h=t.highestSavedPage,d=t.highestSavedPageSize,ht=i,e(ai))}else st(function(){e(ai)},rt("Unable to write settings during initialization."))},rt("Unable to read settings from store.")),u},pt.createDataCache=function(n){if(ait(n.pageSize,"pageSize"),py(n.cacheSize,"cacheSize"),py(n.prefetchSize,"prefetchSize"),!ot(n.name))throw{message:"Undefined or null name",options:n};if(!ot(n.source))throw{message:"Undefined source",options:n};return new ip(n)}})(this)
\ No newline at end of file


[06/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-json-light-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-json-light-tests.js b/odatajs/tests/odata-json-light-tests.js
new file mode 100644
index 0000000..fd2c8d4
--- /dev/null
+++ b/odatajs/tests/odata-json-light-tests.js
@@ -0,0 +1,2492 @@
+/*
+ * 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-json-light-tests.js
+
+(function (window, undefined) {
+
+    // DATAJS INTERNAL START
+
+    var mockHttpClient;
+
+    module("Unit", {
+        setup: function () {
+            mockHttpClient = window.MockHttpClient.clear();
+        }
+    });
+
+    var getSampleModel = function () {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "key": { "propertyRef": [{ "name": "Id"}] },
+                        "property": [
+                                { "name": "Id", "type": "Edm.String" },
+                                { "name": "P1", "type": "Edm.Int32" }
+                         ]
+                    }],
+                    entityContainer: [{
+                        name: "TestContainer",
+                        isDefaultEntityContainer: "true",
+                        entitySet: [{ "name": "EntityTypes", "entityType": "NS.EntityType"}]
+                    }]
+                }]
+            }
+        };
+        return testModel;
+    };
+
+    var getSampleModelWithTwoKeys = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].key = { "propertyRef": [{ "name": "Id" }, { "name": "P1"}] };
+        return testModel;
+    };
+
+    var getSampleModelWithOneConcurrencyProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
+        return testModel;
+    };
+    
+    var getSampleModelWithOneBinaryConcurrencyProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
+        testModel.dataServices.schema[0].entityType[0].property[1].type = "Edm.Binary";
+        return testModel;
+    };
+
+    var getSampleModelWithMultipleConcurrencyProperties = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[0].concurrencyMode = "Fixed";
+        testModel.dataServices.schema[0].entityType[0].property[1].concurrencyMode = "Fixed";
+        return testModel;
+    };
+
+    var getSampleModelWithDateTimeConcurrencyProperties = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.DateTime", concurrencyMode: "Fixed" };
+        return testModel;
+    };
+    
+    var getSampleModelWithDecimalProperty = function () {
+        var testModel = getSampleModel();
+        testModel.dataServices.schema[0].entityType[0].property[1] = { "name": "P1", "type": "Edm.Decimal"};
+        return testModel;
+    };
+
+    var getSampleModelWithNavPropertiesAndInheritedTypes = function () {
+        return {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "maxDataServiceVersion": "4.0",
+                "schema": [
+                    {
+                        "namespace": "ODataDemo",
+                        "entityType": [
+                            {
+                                "name": "Product",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Int32"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "Category",
+                                        "toRole": "Category_Products",
+                                        "fromRole": "Product_Category",
+                                        "relationship": "ODataDemo.Product_Category_Category_Products"
+                                    }]
+                            },
+                            {
+                                "name": "FeaturedProduct",
+                                "baseType": "ODataDemo.Product",
+                                "navigationProperty": [
+                                    {
+                                        "name": "Advertisement",
+                                        "toRole": "Advertisement_FeaturedProduct",
+                                        "fromRole": "FeaturedProduct_Advertisement",
+                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "Advertisement",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Guid"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "FeaturedProduct",
+                                        "toRole": "FeaturedProduct_Advertisement",
+                                        "fromRole": "Advertisement_FeaturedProduct",
+                                        "relationship": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "Category",
+                                "key": {
+                                    "propertyRef": [
+                                        {
+                                            "name": "ID"
+                                        }
+                                    ]
+                                },
+                                "property": [
+                                    {
+                                        "name": "ID",
+                                        "nullable": "false",
+                                        "type": "Edm.Int32"
+                                    }
+                                ],
+                                "navigationProperty": [
+                                    {
+                                        "name": "Products",
+                                        "toRole": "Product_Category",
+                                        "fromRole": "Category_Products",
+                                        "relationship": "ODataDemo.Product_Category_Category_Products"
+                                    }
+                                ]
+                            }
+                        ],
+                        "association": [
+                            {
+                                "name": "Product_Category_Category_Products",
+                                "end": [
+                                    {
+                                        "type": "ODataDemo.Category",
+                                        "multiplicity": "0..1",
+                                        "role": "Category_Products"
+                                    },
+                                    {
+                                        "type": "ODataDemo.Product",
+                                        "multiplicity": "*",
+                                        "role": "Product_Category"
+                                    }
+                                ]
+                            },
+                            {
+                                "name": "FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
+                                "end": [
+                                    {
+                                        "type": "ODataDemo.Advertisement",
+                                        "multiplicity": "0..1",
+                                        "role": "Advertisement_FeaturedProduct"
+                                    },
+                                    {
+                                        "type": "ODataDemo.FeaturedProduct",
+                                        "multiplicity": "0..1",
+                                        "role": "FeaturedProduct_Advertisement"
+                                    }
+                                ]
+                            }
+                        ],
+                        "entityContainer": [
+                            {
+                                "name": "DemoService",
+                                "isDefaultEntityContainer": "true",
+                                "entitySet": [
+                                    {
+                                        "name": "Products",
+                                        "entityType": "ODataDemo.Product"
+                                    },
+                                    {
+                                        "name": "Advertisements",
+                                        "entityType": "ODataDemo.Advertisement"
+                                    },
+                                    {
+                                        "name": "Categories",
+                                        "entityType": "ODataDemo.Category"
+                                    }
+                                ],
+                                "associationSet": [
+                                    {
+                                        "name": "Products_Advertisement_Advertisements",
+                                        "association": "ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct",
+                                        "end": [
+                                            {
+                                                "role": "FeaturedProduct_Advertisement",
+                                                "entitySet": "Products"
+                                            },
+                                            {
+                                                "role": "Advertisement_FeaturedProduct",
+                                                "entitySet": "Advertisements"
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "name": "Products_Category_Categories",
+                                        "association": "ODataDemo.Product_Category_Category_Products",
+                                        "end": [
+                                            {
+                                                "role": "Product_Category",
+                                                "entitySet": "Products"
+                                            },
+                                            {
+                                                "role": "Category_Products",
+                                                "entitySet": "Categories"
+                                            }
+                                        ]
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                ]
+            }
+        };
+    };
+
+    var failTest = function (err) {
+        if (err && err.message) {
+            djstest.fail(err.message);
+        } else {
+            djstest.fail("unexpected failure");
+        }
+        djstest.done();
+    };
+
+    var verifySerializedJsonLightData = function (actual, expected, message, requestUri) {
+        mockHttpClient.addRequestVerifier("*", function (request) {
+            djstest.assertAreEqualDeep(JSON.parse(request.body), expected, message);
+            djstest.done();
+        });
+
+        odatajs.oData.request({
+            requestUri: requestUri || "http://someUri",
+            headers: { "Content-Type": "application/json" },
+            method: "PUT",
+            data: actual
+        }, null, failTest, null, mockHttpClient);
+    };
+
+    var verifyReadJsonLightData = function (input, expected, message, model) {
+        var response = { headers: { "Content-Type": "application/json;odata.metadata=full", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+    var verifyReadJsonLightWithMinimalMetadata = function (input, expected, message, model) {
+        var response = { headers: { "Content-Type": "application/json;odata.metadata=minimal", DataServiceVersion: "4.0" }, body: JSON.stringify(input) };
+
+        OData.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+
+    djstest.addTest(function jsonLightReadEmptySvcDocTest() {
+        var input = {
+            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
+            "value": []
+        };
+
+        var expected = {
+            workspaces: [
+                {
+                    collections: []
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadSvcDocTest() {
+        var input = {
+            "odata.metadata": "http://someUri/ODataService.svc/OData/$metadata",
+            "value": [
+                { "name": "Customers", "url": "Customers" },
+                { "name": "Employees", "url": "http://someUri/ODataService.svc/OData/Employees" }
+            ]
+        };
+
+        var expected = {
+            workspaces: [
+                {
+                    collections: [
+                        {
+                            title: "Customers",
+                            href: "http://someUri/ODataService.svc/OData/Customers"
+                        },
+                        {
+                            title: "Employees",
+                            href: "http://someUri/ODataService.svc/OData/Employees"
+                        }
+                    ]
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryMetadataUriTest() {
+        var tests = {
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Qualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Ns.Container.EntitySet/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            },
+
+            "Unqualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#EntitySet/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            }
+        };
+
+        for (name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryMetadataUriWithMetadataDocumentTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                    ]
+                    }, {
+                        "name": "GenreCatalog",
+                        "isDefaultEntityContainer": "false",
+                        "entitySet": [
+                           { "name": "Genres", "entityType": "TestCatalog.Model.Genre" }
+                    ]
+                    }]
+                }]
+            }
+        };
+
+        var tests = {
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.GenreCatalog.Genres/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Genre"} }
+            },
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri/$metadata#Titles/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Title"} }
+            },
+            "Qualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Test.Catalog.Titles/TestCatalog.Model.Songs/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
+            },
+            "Unqualified entity set with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Titles/TestCatalog.Model.Songs/@Element" },
+                expected: { __metadata: { type: "TestCatalog.Model.Songs"} }
+            },
+            "Unqualified entity set in non default entity container": {
+                input: { "odata.metadata": "http://someUri/$metadata#Generes/@Element" },
+                expected: { __metadata: { type: null} }
+            },
+            "Unqualified entity set in non default entity container with type cast": {
+                input: { "odata.metadata": "http://someUri/$metadata#Generes/TypeCast/@Element" },
+                expected: { __metadata: { type: "TypeCast"} }
+            }
+        };
+
+        for (name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light entry metadata uri was read properly.", testModel);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTypeInPayloadWinsOverModelTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "hasStream": "true",
+                        "key": { "propertyRef": [{ "name": "Id"}] },
+                        "property": [
+                                { "name": "Id", "type": "Edm.String" },
+                                { "name": "P1", "type": "Edm.String" },
+                                { "name": "P2", "type": "NS.ComplexType" },
+                                { "name": "P3", "type": "Edm.Int64" }
+                            ]
+                    }],
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "C1", "type": "Edm.String" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
+            P1: "Hello",
+            P2: {
+                "odata.type": "Instance",
+                C1: "World"
+            },
+            "P2@odata.type": "Property",
+            P3: "500",
+            "P3@odata.type": "Property",
+            P4: {
+                "odata.type": "NS.ComplexType",
+                C1: "!!"
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "NS.EntityType",
+                properties: {
+                    P1: { type: "Edm.String" },
+                    P2: {
+                        type: "Instance",
+                        properties: {
+                            C1: { type: null }
+                        }
+                    },
+                    P3: { type: "Property" },
+                    P4: {
+                        type: "NS.ComplexType",
+                        properties: {
+                            C1: { type: "Edm.String" }
+                        }
+                    }
+                }
+            },
+            P1: "Hello",
+            P2: {
+                __metadata: {
+                    type: "Instance"
+                },
+                C1: "World"
+            },
+            P3: "500",
+            P4: {
+                __metadata: {
+                    type: "NS.ComplexType"
+                },
+                C1: "!!"
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadObjectWithCollectionPropertyTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "NS",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Collection(Edm.Int32)" }
+                            ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/NS.EntityType/@Element",
+            p1: [1, 2, 3],
+            p2: [
+                { c1: 100, c2: 200 },
+                { c1: 400, c2: 500, "odata.type": "NS.OtherType" }
+            ],
+            "p2@odata.type": "Collection(NS.ComplexType)",
+            p3: [5, 6, 7]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "NS.EntityType",
+                properties: {
+                    p1: { type: "Collection(Edm.Int32)" },
+                    p2: {
+                        type: "Collection(NS.ComplexType)",
+                        elements: [
+                            {
+                                type: "NS.ComplexType",
+                                properties: {
+                                    c1: { type: null },
+                                    c2: { type: null }
+                                }
+                            },
+                            {
+                                type: "NS.OtherType",
+                                properties: {
+                                    c1: { type: null },
+                                    c2: { type: null }
+                                }
+                            }
+                        ]
+                    },
+                    p3: { type: null }
+                }
+            },
+            p1: {
+                __metadata: { type: "Collection(Edm.Int32)" },
+                results: [1, 2, 3]
+            },
+            p2: {
+                __metadata: { type: "Collection(NS.ComplexType)" },
+                results: [
+                    {
+                        __metadata: {
+                            type: "NS.ComplexType"
+                        },
+                        c1: 100,
+                        c2: 200
+                    },
+                    {
+                        __metadata: {
+                            type: "NS.OtherType"
+                        },
+                        c1: 400,
+                        c2: 500
+                    }
+                ]
+            },
+            p3: {
+                __metadata: { type: null },
+                results: [5, 6, 7]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with collection porperties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryODataAnnotationsTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "odata.id": "Customers(1)",
+            "odata.etag": "etag-value",
+            "odata.readLink": "read/Customers(1)",
+            "odata.editLink": "Customers(1)",
+            "odata.mediaReadLink": "Customers(1)/Image",
+            "odata.mediaEditLink": "Customers(1)/$value",
+            "odata.mediaETag": "stream-etag-value",
+            "odata.mediaContentType": "image/jpg"
+        };
+
+        var expected = {
+            __metadata: {
+                id: "Customers(1)",
+                type: "TypeCast",
+                etag: "etag-value",
+                self: "http://someUri/read/Customers(1)",
+                edit: "http://someUri/Customers(1)",
+                uri: "http://someUri/Customers(1)",
+                media_src: "http://someUri/Customers(1)/Image",
+                edit_media: "http://someUri/Customers(1)/$value",
+                media_etag: "stream-etag-value",
+                content_type: "image/jpg"
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light entry OData annotations were read properly");
+        djstest.done();
+    });
+
+
+    djstest.addTest(function jsonLightReadObjectWithComplexPropertyTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Ns.ComplexType" }
+                         ]
+                    }],
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "c1", "type": "Edm.Int16" },
+                            { "name": "c2", "type": "Edm.Int32" },
+                            { "name": "c3", "type": "Ns.ComplexType" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: {
+                c1: 100,
+                c2: 200,
+                c3: {
+                    c1: 300,
+                    c2: 400,
+                    c3: {
+                        c1: 500,
+                        c2: 600,
+                        c3: null
+                    }
+                }
+            },
+            p2: {
+                "odata.type": "Ns.ComplexType2",
+                c4: 800,
+                "c4@odata.type": "Edm.Single",
+                c5: 900,
+                c6: {
+                    c1: 1000,
+                    c2: 2000,
+                    c3: {
+                        c1: 1100,
+                        "c1@odata.type": "Edm.Double",
+                        c2: 1200,
+                        c3: null
+                    }
+                },
+                "c6@odata.type": "Ns.ComplexType"
+            },
+            p3: {},
+            "p3@odata.type": "Ns.ComplexType3"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: {
+                        type: "Ns.ComplexType",
+                        properties: {
+                            c1: { type: "Edm.Int16" },
+                            c2: { type: "Edm.Int32" },
+                            c3: {
+                                type: "Ns.ComplexType",
+                                properties: {
+                                    c1: { type: "Edm.Int16" },
+                                    c2: { type: "Edm.Int32" },
+                                    c3: {
+                                        type: "Ns.ComplexType",
+                                        properties: {
+                                            c1: { type: "Edm.Int16" },
+                                            c2: { type: "Edm.Int32" },
+                                            c3: { type: "Ns.ComplexType" }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    p2: {
+                        type: "Ns.ComplexType2",
+                        properties: {
+                            c4: { type: "Edm.Single" },
+                            c5: { type: null },
+                            c6: {
+                                type: "Ns.ComplexType",
+                                properties: {
+                                    c1: { type: "Edm.Int16" },
+                                    c2: { type: "Edm.Int32" },
+                                    c3: {
+                                        type: "Ns.ComplexType",
+                                        properties: {
+                                            c1: { type: "Edm.Double" },
+                                            c2: { type: "Edm.Int32" },
+                                            c3: { type: "Ns.ComplexType" }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    p3: { type: "Ns.ComplexType3" }
+                }
+            },
+            p1: {
+                __metadata: { type: "Ns.ComplexType" },
+                c1: 100,
+                c2: 200,
+                c3: {
+                    __metadata: { type: "Ns.ComplexType" },
+                    c1: 300,
+                    c2: 400,
+                    c3: {
+                        __metadata: { type: "Ns.ComplexType" },
+                        c1: 500,
+                        c2: 600,
+                        c3: null
+                    }
+                }
+            },
+            p2: {
+                __metadata: { type: "Ns.ComplexType2" },
+                c4: 800,
+                c5: 900,
+                c6: {
+                    __metadata: { type: "Ns.ComplexType" },
+                    c1: 1000,
+                    c2: 2000,
+                    c3: {
+                        __metadata: { type: "Ns.ComplexType" },
+                        c1: 1100,
+                        c2: 1200,
+                        c3: null
+                    }
+                }
+            },
+            p3: { __metadata: { type: "Ns.ComplexType3"} }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with complex type properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadObjectWithNamedStreamProperty() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "p1@odata.mediaReadLink": "Customers(1)/namedStream",
+            "p1@odata.mediaEditLink": "Customers(1)/namedStream/$value",
+            "p1@odata.mediaETag": "voice-etag-value",
+            "p1@odata.mediaContentType": "audio/basic"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "TypeCast",
+                properties: {
+                    p1: { type: null }
+                }
+            },
+            p1: {
+                __mediaresource: {
+                    media_src: "http://someUri/Customers(1)/namedStream",
+                    edit_media: "http://someUri/Customers(1)/namedStream/$value",
+                    media_etag: "voice-etag-value",
+                    content_type: "audio/basic"
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with named stream properties was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryWithDeferredNavigationPropertyTests() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#NS.Container.Set/TypeCast/@Element",
+            "p1@odata.navigationLinkUrl": "entitySet(1)/deferred",
+            "p1@odata.associationLinkUrl": "entitySet(1)/$links/deferred"
+        };
+
+        var expected = {
+            __metadata: {
+                type: "TypeCast",
+                properties: {
+                    p1: {
+                        type: null,
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/deferred"
+                    }
+                }
+            },
+            p1: {
+                __deferred: {
+                    uri: "http://someUri/entitySet(1)/deferred"
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with deferred navigation properties was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEntryWithInlinedNavigationPropertiesTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "navigationProperty": [
+                            { "name": "p1", "relationship": "Ns.Rel1", "toRole": "p1s" },
+                            { "name": "p2", "relationship": "Ns.Rel2", "toRole": "p2s" }
+                        ]
+                    }],
+                    "association": [{
+                        "name": "Rel1",
+                        "end": [
+                            { "type": "Ns.EntityType1", "role": "p1s" },
+                            { "type": "Ns.EntityType", "role": "otherRole" }
+                         ]
+                    },
+                    {
+                        "name": "Rel2",
+                        "end": [
+                            { "type": "Ns.EntityType", "role": "otherRole" },
+                            { "type": "Ns.EntityType2", "role": "p2s" }
+                         ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: [
+                { e1: 100, e2: 200 },
+                { e1: 110, e2: 220 }
+            ],
+            "p1@odata.count": 50,
+            "p1@odata.nextLink": "nextToken",
+            p2: {
+                e3: 300
+            },
+            p3: [
+                { e4: 400, e5: 500 },
+                { e4: 440, e5: 550 }
+            ],
+            "p3@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p3",
+            "p3@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p3",
+            p4: {
+                e6: 600
+            },
+            "p4@odata.navigationLinkUrl": "http://someUri/entitySet(1)/p4",
+            "p4@odata.associationLinkUrl": "http://someUri/entitySet(1)/$links/p4",
+            p5: [
+                {
+                    "odata.id": 12345,
+                    e7: 700,
+                    e8: 800
+                }
+            ],
+            p6: {
+                "odata.id": 78910,
+                e9: 900,
+                "e9@odata.type": "Edm.Int32"
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: {
+                        type: "Ns.EntityType1"
+                    },
+                    p2: {
+                        type: "Ns.EntityType2"
+                    },
+                    p3: {
+                        type: null,
+                        navigationLinkUrl: "http://someUri/entitySet(1)/p3",
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p3"
+                    },
+                    p4: {
+                        type: null,
+                        navigationLinkUrl: "http://someUri/entitySet(1)/p4",
+                        associationLinkUrl: "http://someUri/entitySet(1)/$links/p4"
+                    },
+                    p5: {
+                        type: null
+                    },
+                    p6: {
+                        type: null
+                    }
+                }
+            },
+            p1: {
+                __count: 50,
+                __next: "http://someUri/nextToken",
+                results: [
+            {
+                __metadata: {
+                    type: "Ns.EntityType1",
+                    properties: {
+                        e1: { type: null },
+                        e2: { type: null }
+                    }
+                },
+                e1: 100,
+                e2: 200
+            },
+            {
+                __metadata: {
+                    type: "Ns.EntityType1",
+                    properties: {
+                        e1: { type: null },
+                        e2: { type: null }
+                    }
+                },
+                e1: 110,
+                e2: 220
+            }
+          ]
+            },
+            p2: {
+                __metadata: {
+                    type: "Ns.EntityType2",
+                    properties: {
+                        e3: { type: null }
+                    }
+                },
+                e3: 300
+            },
+            p3: {
+                results: [
+            {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e4: { type: null },
+                        e5: { type: null }
+                    }
+                },
+                e4: 400,
+                e5: 500
+            },
+            {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e4: { type: null },
+                        e5: { type: null }
+                    }
+                },
+                e4: 440,
+                e5: 550
+            }
+            ]
+            },
+            p4: {
+                __metadata: {
+                    type: null,
+                    properties: {
+                        e6: { type: null }
+                    }
+                },
+                e6: 600
+            },
+            p5: {
+                results: [
+                {
+                    __metadata: {
+                        id: 12345,
+                        type: null,
+                        properties: {
+                            e7: { type: null },
+                            e8: { type: null }
+                        }
+                    },
+                    e7: 700,
+                    e8: 800
+                }
+            ]
+            },
+            p6: {
+                __metadata: {
+                    id: 78910,
+                    type: null,
+                    properties: {
+                        e9: { type: "Edm.Int32" }
+                    }
+                },
+                e9: 900
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with inlined navigation properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadStringPropertiesTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityType": [{
+                        "name": "EntityType",
+                        "property": [
+                                { "name": "p1", "type": "Edm.DateTime" },
+                                { "name": "p2", "type": "Edm.DateTimeOffset" },
+                                { "name": "p3", "type": "Edm.Time" }
+                            ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/Ns.EntityType/@Element",
+            p1: "2000-01-02T03:04:05",
+            p2: "2000-01-02T03:04:05+01:00",
+            p3: "P0Y0M05DT12H30M5S",
+            p4: "hello world",
+            p5: "2001-01-02T03:04:05",
+            "p5@odata.type": "Edm.DateTime",
+            p6: "2001-01-02T03:04:05+01:00",
+            "p6@odata.type": "Edm.DateTimeOffset",
+            p7: "P0Y0M05DT12H30M10S",
+            "p7@odata.type": "Edm.Time"
+        };
+
+        var p2 = new Date("01/02/2000 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var p6 = new Date("01/02/2001 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var expected = {
+            __metadata: {
+                type: "Ns.EntityType",
+                properties: {
+                    p1: { type: "Edm.DateTime" },
+                    p2: { type: "Edm.DateTimeOffset" },
+                    p3: { type: "Edm.Time" },
+                    p4: { type: null },
+                    p5: { type: "Edm.DateTime" },
+                    p6: { type: "Edm.DateTimeOffset" },
+                    p7: { type: "Edm.Time" }
+                }
+            },
+            p1: new Date("01/02/2000 03:04:05 GMT"),
+            p3: { ms: 477005000, __edmType: "Edm.Time" },
+            p2: p2,
+            p4: "hello world",
+            p5: new Date("01/02/2001 03:04:05 GMT"),
+            p6: p6,
+            p7: { ms: 477010000, __edmType: "Edm.Time" }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light object with string properties was read properly", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadRecognizeDateLiteralsTest() {
+        var input = {
+            p1: "2000-01-02T03:04:05",
+            p2: "2000-01-02T03:04:05+01:00"
+        };
+
+        var p2 = new Date("01/02/2000 02:04:05 GMT");
+        p2.__edmType = "Edm.DateTimeOffset";
+        p2.__offset = "+01:00";
+
+        var expected = {
+            __metadata: {
+                properties: {
+                    p1: {
+                        type: null
+                    },
+                    p2: {
+                        type: null
+                    }
+                },
+                type: null
+            },
+            p1: new Date("01/02/2000 03:04:05 GMT"),
+            p2: p2
+        };
+
+        OData.jsonHandler.recognizeDates = true;
+        verifyReadJsonLightData(input, expected, "Json light datetime literals were recognized. ");
+
+        OData.jsonHandler.recognizeDates = false;
+
+        expected.p1 = input.p1;
+        expected.p2 = input.p2;
+
+        verifyReadJsonLightData(input, expected, "Json light datetime literals were ignored");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEmptyFeedTest() {
+        var input = { "odata.metadata": "http://someUri#entitySet/Set", value: [] };
+        var expected = { results: [] };
+
+        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedTest() {
+        var input = {
+            "odata.metadata": "http://someUri#entitySet/Type",
+            value: [
+              { "odata.id": 12345 },
+              { "odata.id": 56789 }
+            ],
+            "odata.count": 50,
+            "odata.nextLink": "skipToken"
+        };
+
+        var expected = {
+            __count: 50,
+            __next: "http://someUri/skipToken",
+            results: [
+                {
+                    __metadata: {
+                        id: 12345,
+                        type: "Type"
+                    }
+                },
+                {
+                    __metadata: {
+                        id: 56789,
+                        type: "Type"
+                    }
+                }
+            ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light feed object was read properly");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedUsingMetadataTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        var tests = {
+            "Unqualified entity set": {
+                input: { "odata.metadata": "http://someUri#Titles", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
+            },
+            "Qualified entity set": {
+                input: { "odata.metadata": "http://someUri#Test.Catalog.TestCatalog.Titles", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TestCatalog.Model.Title"}}] }
+            },
+            "Type casted entity set": {
+                input: { "odata.metadata": "http://someUri#TestCatalog.Titles/TypeCast", value: [{}] },
+                expected: { results: [{ __metadata: { type: "TypeCast"}}] }
+            }
+        };
+
+        for (var name in tests) {
+            var test = tests[name];
+            verifyReadJsonLightData(test.input, test.expected, name + " - Json light feed was read properly.", testModel);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadInferFeedAsObjectTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "Titles", "entityType": "TestCatalog.Model.Title" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        var tests = {
+            "Feed as object": {
+                input: { "odata.metadata": "http://someUri#EntitySet", value: [] },
+                expected: {
+                    __metadata: {
+                        type: "EntitySet",
+                        properties: {
+                            value: { type: null }
+                        }
+                    },
+                    value: { __metadata: { type: null }, results: [] }
+                }
+            },
+            "Feed as feed using value": {
+                input: { "odata.metadata": "http://someUri#EntiySet", value: [{ "odata.id": 12345}] },
+                expected: { results: [{ __metadata: { type: null, id: 12345}}] }
+            },
+            "Feed as feed using metadata": {
+                input: { "odata.metadata": "http://someUri#Titles", value: [] },
+                expected: { results: [] }
+            },
+            "Collection of primitive": {
+                input: { "odata.metadata": "http://someUri#Collection(Edm.Int32)", value: [] },
+                expected: { __metadata: { type: "Collection(Edm.Int32)" }, results: [] }
+            },
+            "Collection of complex": {
+                input: { "odata.metadata": "http://someUri#Collection(My.Type)", value: [] },
+                expected: { __metadata: { type: "Collection(My.Type)" }, results: [] }
+            }
+        };
+
+        for (var name in tests) {
+            var test = tests[name];
+            var response = {
+                headers: {
+                    "Content-Type": "application/json;odata.metadata=full",
+                    DataServiceVersion: "4.0"
+                },
+                body: JSON.stringify(test.input)
+            };
+
+            OData.jsonHandler.read(response, { metadata: testModel });
+            djstest.assertAreEqualDeep(response.data, test.expected, name + " - Json light object was read properly ");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadEmptyLinksDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
+            value: []
+        };
+
+        var expected = {
+            results: []
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadLinksDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp",
+            value: [
+                        { url: "Products(1)" },
+                        { url: "http://someUri/Products(2)" }
+                     ]
+        };
+
+        var expected = {
+            results: [
+                        { uri: "http://someUri/Products(1)" },
+                        { uri: "http://someUri/Products(2)" }
+                    ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light links document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadSingleLinkDocumentTest() {
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/$links/NavProp/@Element",
+            url: "Products(1)"
+        };
+
+        var expected = {
+            uri: "http://someUri/Products(1)"
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light single link document was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelPrimitiveProperty() {
+        var input = {
+            "odata.metadata": "http://someUri#Edm.GeometryPoint",
+            value: {
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: name,
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Edm.GeometryPoint"
+            },
+            value: {
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: name,
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level primitive property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelComplexTypeTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "complexType": [{
+                        "name": "ComplexType",
+                        "property": [
+                            { "name": "value", "type": "Collection(Ns.ComplexType2)" }
+                        ]
+                    }]
+                }]
+            }
+        };
+
+        var input = {
+            "odata.metadata": "http://someUri#Ns.ComplexType",
+            value: [{
+                p1: 100,
+                p2: 200
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Ns.ComplexType",
+                properties: {
+                    value: {
+                        type: "Collection(Ns.ComplexType2)",
+                        elements: [
+                            {
+                                type: "Ns.ComplexType2",
+                                properties: {
+                                    p1: { type: null },
+                                    p2: { type: null }
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            value: {
+                __metadata: { type: "Collection(Ns.ComplexType2)" },
+                results: [
+                    {
+                        __metadata: { type: "Ns.ComplexType2" },
+                        p1: 100,
+                        p2: 200
+                    }
+                ]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level complex type property was read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopPrimitiveCollectionPropertyTest() {
+        var input = {
+            "odata.metadata": "http://someUri#Collection(Edm.GeometryPoint)",
+            value: [{
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: "name",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Collection(Edm.GeometryPoint)"
+            },
+            results: [{
+                type: "Point",
+                coordinates: [1.0, 2.0],
+                crs: {
+                    type: "name",
+                    properties: {
+                        name: "EPSG:4326"
+                    }
+                }
+            }]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level primitive collection property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadTopLevelComplexTypeCollectionTest() {
+        var input = {
+            "odata.metadata": "http://someUri#Collection(Ns.ComplexType2)",
+            value: [{
+                p1: 100,
+                p2: 200,
+                "p2@odata.type": "Edm.Int16"
+            }]
+        };
+
+        var expected = {
+            __metadata: {
+                type: "Collection(Ns.ComplexType2)",
+                elements: [
+                    {
+                        type: "Ns.ComplexType2",
+                        properties: {
+                            p1: { type: null },
+                            p2: { type: "Edm.Int16" }
+                        }
+                    }
+                ]
+            },
+            results: [
+                {
+                    __metadata: { type: "Ns.ComplexType2" },
+                    p1: 100,
+                    p2: 200
+                }
+             ]
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light top level complex type collection property was read properly.");
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadFeedAdvertisedActionsTest() {
+
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Ns",
+                    "entityContainer": [{
+                        "name": "EntityContainer",
+                        "isDefaultEntityContainer": "true",
+                        "entitySet": [
+                           { "name": "EntitySet", "entityType": "Ns.EntityType" }
+                        ]
+                    }
+                    ]
+                }
+                ]
+            }
+        };
+
+        input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet",
+            "#action1": {
+                target: "action1/item(0)",
+                title: "Action1"
+            },
+            "#action2": {
+                target: "action2/item(0)",
+                title: "Action2"
+            },
+            value: []
+        };
+
+        expected = {
+            __metadata: {
+                actions: [
+                    {
+                        metadata: "http://someUri/action1",
+                        target: "http://someUri/action1/item(0)",
+                        title: "Action1"
+                    },
+                   {
+                       metadata: "http://someUri/action2",
+                       target: "http://someUri/action2/item(0)",
+                       title: "Action2"
+                   }
+                ]
+            },
+            results: []
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light feed with advertised actions was read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightReadAdvertisedActionsAndFunctionsTest() {
+        var testModel = {
+            "version": "1.0",
+            "dataServices": {
+                "dataServiceVersion": "4.0",
+                "schema": [{
+                    "namespace": "Test.Catalog",
+                    "entityContainer": [{
+                        "name": "TestCatalog",
+                        "isDefaultEntityContainer": "true",
+                        "functionImport": [
+                            { "name": "function1", "isSideEffecting": "false" },
+                            { "name": "function2", "isSideEffecting": "false" },
+                            { "name": "action1", "isSideEffecting": "true" },
+                            { "name": "action2" }
+                         ]
+                    }, {
+                        "name": "OtherCatalog",
+                        "isDefaultEntityContainer": "false",
+                        "functionImport": [
+                            { "name": "function1", "isSideEffecting": "false" }
+                         ]
+                    }]
+                }]
+            }
+        };
+
+        input = {
+            "odata.metadata": "http://someUri/$metadata#EntitySet/@Element",
+            "#function2": [
+                {
+                    target: "function2/item(0)",
+                    title: "Function2 overload1"
+                },
+                {
+                    target: "function2/item(0)",
+                    title: "Function2 overload2"
+                }
+            ],
+            "#action1": {
+                target: "action1/item(0)",
+                title: "Action1"
+            },
+            "#action2": {
+                target: "action2/item(0)",
+                title: "Action2"
+            },
+            "#function1": {
+                target: "function1/item(0)",
+                title: "Function1"
+            },
+            "#Test.Catalog.OtherCatalog.function1": {
+                target: "Test.Catalog.OtherCatalog.function1/item(0)",
+                title: "Function1 in other catalog"
+            },
+            "#action3": [
+                {
+                    target: "action3/item(0)",
+                    title: "Unkown action overload1"
+                },
+                {
+                    target: "http://otherUri/action3/item(0)",
+                    title: "Unkown action overload2"
+                }
+            ]
+        };
+
+        expected = {
+            __metadata: {
+                type: null,
+                actions: [
+                   {
+                       metadata: "http://someUri/action1",
+                       target: "http://someUri/action1/item(0)",
+                       title: "Action1"
+                   },
+                   {
+                       metadata: "http://someUri/action2",
+                       target: "http://someUri/action2/item(0)",
+                       title: "Action2"
+                   },
+                   {
+                       metadata: "http://someUri/action3",
+                       target: "http://someUri/action3/item(0)",
+                       title: "Unkown action overload1"
+                   },
+                   {
+                       metadata: "http://someUri/action3",
+                       target: "http://otherUri/action3/item(0)",
+                       title: "Unkown action overload2"
+                   }
+                ],
+                functions: [
+                    {
+                        metadata: "http://someUri/function2",
+                        target: "http://someUri/function2/item(0)",
+                        title: "Function2 overload1"
+                    },
+                    {
+                        metadata: "http://someUri/function2",
+                        target: "http://someUri/function2/item(0)",
+                        title: "Function2 overload2"
+                    },
+                    {
+                        metadata: "http://someUri/function1",
+                        target: "http://someUri/function1/item(0)",
+                        title: "Function1"
+                    },
+                    {
+                        metadata: "http://someUri/Test.Catalog.OtherCatalog.function1",
+                        target: "http://someUri/Test.Catalog.OtherCatalog.function1/item(0)",
+                        title: "Function1 in other catalog"
+                    }
+                ]
+            }
+        };
+
+        verifyReadJsonLightData(input, expected, "Json light advertised actions and functions were read properly.", testModel);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryMetadataTest() {
+        var data = {
+            __metadata: {
+                metadata: "http://someUri/$metadata#NS.Container/Set/@Element",
+                id: "http://someUri/Customers(1)",
+                etag: "etag-value",
+                self: "http://someUri/read/Customers(1)",
+                edit: "http://someUri/read/Customers(1)",
+                media_src: "http://someUri/Customers(1)/Image",
+                edit_media: "http://someUri/Customers(1)/$value",
+                media_etag: "stream-etag-value",
+                content_type: "image/jpg"
+            }
+        };
+
+        var expected = {
+            "odata.etag": "etag-value",
+            "odata.mediaReadLink": "http://someUri/Customers(1)/Image",
+            "odata.mediaEditLink": "http://someUri/Customers(1)/$value",
+            "odata.mediaETag": "stream-etag-value",
+            "odata.mediaContentType": "image/jpg"
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry metadata was serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeCustomAnnotationsTest() {
+        var data = {
+            __metadata: {
+                id: "id"
+            },
+            "odata.id": "id",
+            "custom.annotation": "custom annotation value",
+            "p1@ns1.primitive": "primitive",
+            "p1@ns2.complex": { a1: 500 },
+            "p1@ns3.ns4.value": 600,
+            "p2@ns1.primitive": 400,
+            "custom.annotation": "custom annotation value"
+        };
+
+        var expected = {
+            "odata.id": "id",
+            "custom.annotation": "custom annotation value",
+            "p1@ns1.primitive": "primitive",
+            "p1@ns2.complex": { a1: 500 },
+            "p1@ns3.ns4.value": 600,
+            "p2@ns1.primitive": 400
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light custom annotations were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryCollectionPropertiesTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    primitiveColArray: { type: "Collection(Edm.Int16)" },
+                    primitiveColObject: { type: "Collection(Edm.Int32)" }
+                }
+            },
+            primitiveColArray: [1, 2, 3, 4],
+            primitiveColObject: {
+                results: [5, 6, 7, 8]
+            },
+            complexColArray: [{ p1: 100 }, { p1: 200}],
+            complexColObject: {
+                results: [{ p1: 300 }, { p1: 400}]
+            }
+        };
+
+        var expected = {
+            "primitiveColArray@odata.type": "Collection(Edm.Int16)",
+            primitiveColArray: [1, 2, 3, 4],
+            "primitiveColObject@odata.type": "Collection(Edm.Int32)",
+            primitiveColObject: [5, 6, 7, 8],
+            complexColArray: [{ p1: 100 }, { p1: 200}],
+            complexColObject: [{ p1: 300 }, { p1: 400}]
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry collection properties were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryDeferredPropertyTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    deferred: {
+                        associationLinkUrl: "http://target/$links"
+                    }
+                }
+            },
+            deferred: {
+                __deferred: { uri: "http://target" }
+            }
+        };
+
+        var expected = {
+            "deferred@odata.navigationLinkUrl": "http://target"
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry deferred property were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryInlinePropertiesTest() {
+        var data = {
+            __metadata: {
+                id: "id"
+            },
+            inlineEntry: {
+                __metadata: { uri: "", properties: { p1: { type: "Edm.Int64"}} },
+                p1: "300"
+            },
+            inlineBoundEntry: {
+                __metadata: { uri: "http://entries(1)", properties: { p1: { type: "Edm.Int64"}} },
+                p1: "400"
+            },
+            inlineFeedArray: [
+                {
+                    __metadata: { uri: "http://entries(2)" }
+                },
+                {
+                    __metadata: { uri: "", properties: { p1: { type: "Edm.Int32"}} },
+                    p1: "600"
+                },
+                {
+                    __metadata: { uri: "http://entries(3)" }
+                }
+            ],
+            inlineFeedObject: {
+                __count: 50,
+                __next: "next link",
+                results: [
+                    { __metadata: { uri: "" }, p1: "900" }
+                ]
+            },
+            inlineEmptyFeedObject: {
+                results: []
+            }
+        };
+
+        var expected = {
+            inlineEntry: {
+                "p1@odata.type": "Edm.Int64",
+                p1: "300"
+            },
+            "inlineBoundEntry@odata.bind": "http://entries(1)",
+            inlineFeedArray: [{
+                "p1@odata.type": "Edm.Int32",
+                p1: "600"
+            }],
+            "inlineFeedArray@odata.bind": [
+                "http://entries(2)",
+                "http://entries(3)"
+            ],
+            inlineFeedObject: [{
+                p1: "900"
+            }],
+            inlineEmptyFeedObject: []
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry inline properties were serialized properly.");
+
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryComplexPropertyTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    complexAsDeferredOnMetadata: {
+                        type: "complexAsDeferredOnMetadata.type"
+                    },
+                    complexAsCol: {
+                        type: "complexAsCol.type"
+                    }
+                }
+            },
+            complexAsDeferred: {
+                __metadata: {
+                    type: "complexAsDeferred.type"
+                },
+                __deferred: { uri: "http://uri" }
+            },
+            complexAsCol: {
+                results: [1, 2, 3, 4]
+            },
+            complexAsNamedStream: {
+                __metadata: {
+                    type: "complexAsNamedStream"
+                },
+                __mediaresource: {
+                    content_type: "content type",
+                    media_src: "http://source"
+                }
+            },
+            complexAsDeferredOnMetadata: {
+                __deferred: { uri: "http://uri2" }
+            }
+        };
+
+        var expected = {
+            complexAsDeferred: {
+                "odata.type": "complexAsDeferred.type",
+                __deferred: { uri: "http://uri" }
+            },
+            complexAsCol: {
+                "odata.type": "complexAsCol.type",
+                results: [1, 2, 3, 4]
+            },
+            complexAsNamedStream: {
+                "odata.type": "complexAsNamedStream",
+                __mediaresource: {
+                    content_type: "content type",
+                    media_src: "http://source"
+                }
+            },
+            complexAsDeferredOnMetadata: {
+                "odata.type": "complexAsDeferredOnMetadata.type",
+                __deferred: { uri: "http://uri2" }
+            }
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry complex properties were serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeEntryComplexPropertyMetadataTest() {
+        var data = {
+            __metadata: {
+                id: "id",
+                properties: {
+                    complex: {
+                        type: "this should be overriden",
+                        properties: {
+                            nested1: {
+                                type: "types.complex.nested1",
+                                properties: {
+                                    nested2: {
+                                        type: "types.complex.nested1.nested2"
+                                    }
+                                }
+                            },
+                            c1: {
+                                type: "Edm.Int64"
+                            }
+                        }
+                    }
+                }
+            },
+            complex: {
+                __metadata: {
+                    type: "types.complex"
+                },
+                c1: "500",
+                c2: "b",
+                nested1: {
+                    nested2: {
+                    }
+                }
+            }
+        };
+
+        var expected = {
+            complex: {
+                "odata.type": "types.complex",
+                "c1@odata.type": "Edm.Int64",
+                c1: "500",
+                c2: "b",
+                nested1: {
+                    "odata.type": "types.complex.nested1",
+                    nested2: {
+                        "odata.type": "types.complex.nested1.nested2"
+                    }
+                }
+            }
+        };
+
+        verifySerializedJsonLightData(data, expected, " Json light entry complex property was serialized properly.");
+    });
+
+    djstest.addTest(function jsonLightSerializeLinksDocumentTest() {
+        var tests = {
+            "Empty uri string": {
+                i: { uri: "" },
+                e: { url: "" }
+            },
+            "Null uri string": {
+                i: { uri: null },
+                e: { url: null }
+            },
+            "Undefined uri string": {
+                i: { uri: undefined },
+                e: {}
+            },
+            "Uri": {
+                i: { uri: "http://somUri/EntitySet(1)" },
+                e: { url: "http://somUri/EntitySet(1)" }
+            }
+        };
+
+        for (var name in tests) {
+            verifySerializedJsonLightData(tests[name].i, tests[name].e, name + " - Json light links documents whas serialized properly.", "http://someUri/set(3)/$links/navprop");
+        }
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleKey() {
+        var model = getSampleModel();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')"
+
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithMultipleKeys() {
+        var model = getSampleModelWithTwoKeys();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "edit": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "uri": "http://someUri/EntityTypes(Id='MyId',P1=42)",
+                "self": "http://someUri/EntityTypes(Id='MyId',P1=42)"
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithNonComputedEditLink() {
+        var model = getSampleModel();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            "odata.editLink": "EntityTypes('notcomputed')",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('notcomputed')",
+                "edit": "http://someUri/EntityTypes('notcomputed')",
+                "uri": "http://someUri/EntityTypes('notcomputed')",
+                "self": "http://someUri/EntityTypes('notcomputed')"
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleConcurrencyProperty() {
+        var model = getSampleModelWithOneConcurrencyProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"'MyId'\""
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinksWithSingleBinaryConcurrencyProperty() {
+        var model = getSampleModelWithOneBinaryConcurrencyProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: "AAAAAAAAB9E="
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Binary"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"X'00000000000007D1'\""
+            },
+            "Id": "MyId",
+            "P1": "AAAAAAAAB9E="
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinkWithMutipleConcurrencyProperty() {
+        var model = getSampleModelWithMultipleConcurrencyProperties();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "MyId",
+            P1: 42
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('MyId')",
+                "edit": "http://someUri/EntityTypes('MyId')",
+                "uri": "http://someUri/EntityTypes('MyId')",
+                "self": "http://someUri/EntityTypes('MyId')",
+                "etag": "W/\"'MyId',42\""
+            },
+            "Id": "MyId",
+            "P1": 42
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonLightComputeLinkWithNullConcurrencyProperty() {
+        var model = getSampleModelWithMultipleConcurrencyProperties();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "My Id'",
+            P1: null
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": { "Id": { "type": "Edm.String" }, "P1": { "type": "Edm.Int32"} },
+                "id": "http://someUri/EntityTypes('My%20Id''')",
+                "edit": "http://someUri/EntityTypes('My%20Id''')",
+                "uri": "http://someUri/EntityTypes('My%20Id''')",
+                "self": "http://someUri/EntityTypes('My%20Id''')",
+                "etag": "W/\"'My%20Id''',null\""
+            },
+            "Id": "My Id'",
+            "P1": null
+        };
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightWithDecimalValue() {
+        var model = getSampleModelWithDecimalProperty();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#EntityTypes/@Element",
+            Id: "5",
+            P1: "10.5"
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "NS.EntityType",
+                "properties": {
+                    "Id": {
+                        "type": "Edm.String"
+                    },
+                    "P1": {
+                        "type": "Edm.Decimal"
+                    },
+                },
+                "id": "http:\/\/someUri\/EntityTypes('5')",
+                "uri": "http:\/\/someUri\/EntityTypes('5')",
+                "edit": "http:\/\/someUri\/EntityTypes('5')",
+                "self": "http:\/\/someUri\/EntityTypes('5')"
+            },
+            "Id": "5",
+            "P1": "10.5"
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightNavigationPropertyAndAssociationUriShouldBeComputedTest() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": {
+                "__deferred": {
+                    "uri": "http:\/\/someUri\/Products(5)\/Category"
+                }
+            }
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightNullNavigationPropertyShouldNotBeComputedTest() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+            Category: null
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category",
+                         "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category"
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": null
+        };
+
+
+        verifyReadJsonLightWithMinimalMetadata(input, expected, "Json light type annotations in payload are preferred over type information in the metadata document", model);
+        djstest.done();
+    });
+    
+    djstest.addTest(function jsonLightUrisShouldBeComputedForExpandedEntities() {
+        var model = getSampleModelWithNavPropertiesAndInheritedTypes();
+        var input = {
+            "odata.metadata": "http://someUri/$metadata#Products/@Element",
+            ID: 5,
+            Category: {
+                ID: 1
+            }            
+        };
+
+        var expected = {
+            "__metadata": {
+                "type": "ODataDemo.Product",
+                "properties": {
+                    "ID": {
+                        "type": "Edm.Int32"
+                    },
+                    "Category": {
+                        "type": "ODataDemo.Category",
+                        "navigationLinkUrl": "http:\/\/someUri\/Products(5)\/Category",
+                        "associationLinkUrl": "http:\/\/someUri\/Products(5)\/$links\/Category"
+                    }
+                },
+                "id": "http:\/\/someUri\/Products(5)",
+                "uri": "http:\/\/someUri\/Products(5)",
+                "edit": "http:\/\/someUri\/Products(5)",
+                "self": "http:\/\/someUri\/Products(5)"
+            },
+            "ID": 5,
+            "Category": {
+                "__metadata": {
+                    "type": "ODataDemo.Category",
+                    "properties": {
+                        "ID": {
+                            "type": "Edm.Int32"
+                        },
+                        "Products": {
+                            "type": "ODataDemo.Product",
+                            "associationLinkUrl": "http:\/\/someUri\/Categories(1)\/$links\/Products"
+                        }
+                    },
+                    "id": "http:\/\/someUri\/Categories(1)",
+                    "uri": "http:\/\/someUri\/Categories(1)",
+                    "edit

<TRUNCATED>

[16/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/b-cache-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/b-cache-tests.js b/odatajs/tests-tmp/b-cache-tests.js
new file mode 100644
index 0000000..5b41123
--- /dev/null
+++ b/odatajs/tests-tmp/b-cache-tests.js
@@ -0,0 +1,1191 @@
+/*
+ * 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.
+*/
+
+(function (window, undefined) {
+
+    module("cache-tests.js");
+    var foodsFeed = "./endpoints/FoodStoreDataServiceV4.svc/Foods";
+    var collectionSize = 16;
+
+    var thenFailTest = function (err) {
+        if (err && err.message) {
+            djstest.fail(err.message);
+        } else {
+            djstest.fail("unexepected promise failure");
+        }
+
+        djstest.done();
+    };
+
+    djstest.addTest(function dataCacheCountTest() {
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
+        cache.count().then(function (count) {
+            djstest.assertAreEqual(count, collectionSize, "expected count for Foods");
+            djstest.destroyCacheAndDone(cache);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheCountOnLocalTest() {
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed, pageSize: collectionSize + 10, mechanism: "memory" });
+        cache.readRange(0, collectionSize + 10).then(function (data) {
+            var expectedCount = data.value ? data.value.length : 0;
+            cache.count().then(function (count) {
+                djstest.assertAreEqual(count, expectedCount, "expected count for expectedCount");
+                djstest.destroyCacheAndDone(cache);
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheCountAbortTest() {
+        // Abort before completion.
+        var cache = odatajs.cache.createDataCache({ name: "cache", source: foodsFeed });
+        var item = cache.count().then(thenFailTest, function (err) {
+            djstest.assertAreEqual(true, err.canceled, "err.aborted is true");
+            djstest.destroyCacheAndDone(cache);
+        }).cancel();
+    });
+
+    var createNewCache = function (options) {
+
+        var thenSuccess = null;
+
+        var resolved = false;
+        var rejected = false;
+
+        var args = null;
+
+        this.then = function (success) {
+            if (resolved) {
+                success.apply(null, args);
+            } else if (!rejected) {
+                thenSuccess = success;
+            }
+        };
+
+        var resolve = function (/*args*/) {
+            resolved = true;
+            args = arguments;
+            if (thenSuccess) {
+                thenSuccess.apply(null, arguments);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache(options);
+        cache.clear().then(function () {
+            var newCache = odatajs.cache.createDataCache(options);
+            resolve(newCache);
+        }, function (err) {
+            rejected = true;
+            thenFailTest(err);
+        });
+
+        return this;
+    };
+
+    djstest.addTest(function dataCacheReadRangeSingleTest() {
+        // Read a new range.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 1, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "food id is 0.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeExactPageTest() {
+        // Read exactly one page.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 2).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 2, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeMultiplePageTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 3).
+                    then(function (data) {
+                        djstest.assertAreEqual(data.value.length, 3, "single item was read.");
+                        djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                        djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                        djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
+                        djstest.done();
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeSyncDelaysTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).
+                    then(function (data) {
+                        djstest.assertAreEqual(counter, 0, "counter is zero for first set of results");
+                        djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
+                        counter++;
+                        cache.readRange(0, 1).
+                            then(function (data) {
+                                djstest.assertAreEqual(counter, 2, "counter is two because even sync results are delayed)");
+                                djstest.assertAreEqual(cache.stats.netReads, 1, "no additional requests since requested data is in cache");
+                                djstest.done();
+                            }, thenFailTest);
+                        djstest.assertAreEqual(counter, 1, "counter is one because readRange hasn't run (even if results are cached)");
+                        counter++;
+                    }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangesWithDestroyTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
+        var counter = 0;
+        createNewCache(options).then(function (cache) {
+            cache.readRange(0, 1).then(function (data) {
+                djstest.assertAreEqual(cache.stats.netReads, 1, "one request made to fulfill the readRange");
+                cache.clear().then(function () {
+                    djstest.assertAreEqual(cache.stats.netReads, 0, "stats cleared in destroy");
+                    cache.readRange(0, 1).then(function (data) {
+                        djstest.assertAreEqual(cache.stats.netReads, 1, "request made after destroy to fulfill the readRange");
+                        djstest.done();
+                    }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadSimultaneousTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        var theCache;
+        var checkDataAndCount = function (data) {
+            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
+            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
+            djstest.assertAreEqual(theCache.stats.netReads, 1, "single theCache.stats.netReads");
+            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
+            counter++;
+            if (counter === 3) {
+                djstest.done();
+            }
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheMultipleClearTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        var counter = 0;
+        var checkCount = function (data) {
+            djstest.assert(true, "clear then was called");
+            counter++;
+            if (counter === 3) {
+                djstest.done();
+            }
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 1).then(function () {
+                    cache.clear().then(checkCount, thenFailTest);
+                    cache.clear().then(checkCount, thenFailTest);
+                    cache.clear().then(checkCount, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheOnIdleIsFired() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0 };
+
+        createNewCache(options).
+            then(function (cache) {
+                var counter = 0;
+                var clearSucceeded = false;
+
+                var thenFailThisTest = function (err) {
+                    if (err && err.message) {
+                        djstest.fail(err.message);
+                    } else {
+                        djstest.fail("unexepected promise failure");
+                    }
+                };
+
+                cache.onidle = function () {
+                    counter++;
+                    djstest.assertAreEqual(counter, 1, "onidle was called 1 times");
+                    djstest.assert(clearSucceeded, "onidle was called after destroy");
+                    djstest.done();
+                };
+
+                cache.readRange(0, 1).then(null, thenFailThisTest);
+                cache.readRange(0, 1).then(null, thenFailThisTest);
+                cache.readRange(3, 4).then(function () {
+                    cache.readRange(5, 6).then(function () {
+                        cache.clear().then(function () {
+                            clearSucceeded = true;
+                        }, thenFailThisTest);
+                    }, thenFailThisTest);
+                }, thenFailThisTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheOnIdleFiresOnErrorTest() {
+
+        var errorResponse = false;
+        var httpClient = {
+            request: function (request, success, error) {
+                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ d: [1, 2] }) };
+                if (!errorResponse) {
+                    errorResponse = true;
+                    setTimeout(function () {
+                        success(response);
+                    }, 0);
+                } else {
+                    response.statusCode = 500;
+                    response.body = "bad response";
+                    setTimeout(function () {
+                        error({ message: "HTTP request failed", request: request, response: response });
+                    }, 0);
+                }
+            }
+        };
+
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 0, httpClient: httpClient };
+
+        createNewCache(options).
+            then(function (cache) {
+                var counter = 0;
+                var errorHandlerCalled = false;
+
+                var thenFailThisTest = function (err) {
+                    if (err && err.message) {
+                        if (errorResponse) {
+                            djstest.assertAreEqual(err.message, "HTTP request failed", "Error is the expected one");
+                            errorHandlerCalled = true;
+                        } else {
+                            djstest.fail(err.message);
+                        }
+                    } else {
+                        djstest.fail("unexepected promise failure");
+                    }
+                };
+
+                cache.onidle = function () {
+                    counter++;
+                    djstest.assertAreEqual(counter, 1, "onidle was called");
+                    djstest.assert(errorHandlerCalled, "error handler was called before onidle");
+                    cache.onidle = null;
+                    cache.clear().then(function () {
+                        djstest.done();
+                    }, thenFailTest);
+                };
+                cache.readRange(0, 2).then(function () {
+                    cache.readRange(2, 4).then(function () {
+                        djstest.fail("unexpected readRange success");
+                    }, thenFailThisTest);
+                }, thenFailThisTest);
+            }, thenFailTest);
+    });
+
+
+    djstest.addTest(function dataCacheOdataSourceNormalizedURITest() {
+        var requestsMade = 0;
+        var httpClient = {
+            request: function (request, success, error) {
+                var response = { statusCode: 200, headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: JSON.stringify({ value: [1, 2] }) };
+                if (requestsMade === 0) {
+                    djstest.pass("Cache made first request for data from the source");
+                    requestsMade++;
+                } else {
+                    // In memory storage will make a second request from the new cache since two caches with the same name will coexist
+                    if (window.mozIndexedDB || window.localStorage || requestsMade > 1) {
+                        djstest.fail("Unexpected request to the source");
+                    } else {
+                        djstest.pass("In memory cache requested the data from the source");
+                    }
+                }
+                setTimeout(function () {
+                    success(response);
+                }, 0);
+            }
+        };
+
+        var options = { name: "cache", source: "http://exampleuri.com/my service.svc", pageSize: 2, prefetchSize: 0, httpClient: httpClient };
+
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 2).then(function () {
+                    options.source = "HtTp://ExampleURI.cOm/my%20service.svc";
+                    var newCache = odatajs.cache.createDataCache(options);
+                    newCache.readRange(0, 2).then(function (data) {
+                        djstest.assertAreEqualDeep(data.value, [1, 2], "Got the expected data from the new cache instance");
+                        newCache.clear().then(function () {
+                            djstest.done();
+                        }, thenFailTest);
+                    }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+
+    djstest.addTest(function dataCachePrefetchAllTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: -1 };
+        var counter = 0;
+        var theCache;
+
+        var callback = function () {
+            counter++;
+            if (counter === 2) {
+                djstest.assertAreEqual(1, theCache.stats.netReads, "single page to satisfy read (" + theCache.stats.netReads + ")");
+                djstest.assert(theCache.stats.prefetches > 1, "theCache.stats.prefetches(" + theCache.stats.prefetches + ") > 1 - multiple prefetches");
+                djstest.done();
+            }
+        };
+
+        var checkDataAndCount = function (data) {
+            djstest.assertAreEqual(data.value.length, 1, "Single item returned");
+            djstest.assertAreEqual(data.value[0].FoodID, 0, "FoodId is set to zero for first item");
+            djstest.assertAreEqual(1, theCache.stats.netReads, "single theCache.stats.netReads");
+            djstest.assert(theCache.stats.prefetches <= 1, "theCache.stats.prefetches <= 1 - no repetitions");
+            callback();
+        };
+
+        createNewCache(options).
+            then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 1).then(checkDataAndCount, thenFailTest);
+                cache.onidle = function () {
+                    djstest.log("onidle fired");
+                    callback();
+                };
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeTakeMoreThanCollectionCountTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.count().then(function (count) {
+                    cache.readRange(0, count + 1).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, count, "all items in the collection were read.");
+                            cache.readRange(2, count + 1).
+                                then(function (data) {
+                                    djstest.assertAreEqual(data.value.length, count - 2, "all requested in the collection were read.");
+                                    djstest.assertAreEqual(data.value[0].FoodID, 2, "first read food id is 2.");
+                                    djstest.done();
+                                }, thenFailTest);
+                        }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeSkipMoreThanCollectionCountTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.count().then(function (count) {
+                    cache.readRange(count + 1, 5).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, 0, "no items were read.");
+                            djstest.done();
+                        }, thenFailTest);
+                }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheReadRangeTakeMoreThanPrefetchSizeTest() {
+        // Read multiple pages.
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
+        createNewCache(options).
+            then(function (cache) {
+                cache.readRange(0, 4).
+                        then(function (data) {
+                            djstest.assertAreEqual(data.value.length, 4, "all requested in the collection were read.");
+                            djstest.assertAreEqual(data.value[0].FoodID, 0, "first food id is 0.");
+                            djstest.assertAreEqual(data.value[1].FoodID, 1, "second food id is 1.");
+                            djstest.assertAreEqual(data.value[2].FoodID, 2, "third food id is 2.");
+                            djstest.assertAreEqual(data.value[3].FoodID, 3, "third food id is 3.");
+                            djstest.done();
+                        }, thenFailTest);
+            }, thenFailTest);
+    });
+
+    djstest.addTest(function dataCacheRangeInvalidIndexAndCount() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 2, prefetchSize: 1 };
+        var counter = 0;
+
+        var thenFailSuccess = function () {
+            djstest.fail("Call to success was unexpected");
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var thenFailError = function () {
+            djstest.fail("Call to error was unexpected");
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var invalidValues = [-5, -1, null, undefined, NaN, Infinity, "5", "this is not a number"];
+        var tests = [];
+        $.each(invalidValues, function (_, value) {
+            tests.push({ i: value, c: 0 });
+            tests.push({ i: 0, c: value });
+            tests.push({ i: value, c: value });
+        });
+
+        createNewCache(options).
+            then(function (cache) {
+                var i, len;
+                for (i = 0, len = tests.length; i < len; i++) {
+                    var test = tests[i];
+                    try {
+                        cache.readRange(test.i, test.c).then(thenFailSuccess, thenFailTest);
+                    } catch (err) {
+                        djstest.pass("Expected exception was thrown: " + err.message);
+                        counter++;
+                    }
+                }
+                if (counter === tests.length) {
+                    djstest.done();
+                }
+            });
+    });
+
+
+    djstest.addTest(function cacheOptionsForCountTest() {
+        var httpClient = {
+            request: function (r, success, error) {
+                window.setTimeout(function () {
+                    success({ data: "10" });
+                }, 1);
+                return null;
+            }
+        };
+        var cache = odatajs.cache.createDataCache({
+            name: "mem", mechanism: "memory", source: "http://www.example.org/service/",
+            httpClient: httpClient
+        });
+        cache.count().then(function (count) {
+            djstest.assertAreEqual(count, 10, "count value");
+            djstest.done();
+        }, djstest.failAndDoneCallback("failed to get count"));
+    });
+
+    djstest.addTest(function dataCacheDestoryStopsThePrefetcherTest() {
+        var oldHttpClientRequest = window.odatajs.oData.net.defaultHttpClient.request;
+        var prefetchCount = 0;
+        var theCache;
+
+        window.odatajs.oData.net.defaultHttpClient.request = function (request, success, error) {
+            prefetchCount++;
+            djstest.assert(prefetchCount <= 3, "Expected prefetch request");
+            if (prefetchCount === 3) {
+                theCache.clear().then(function () {
+                    djstest.assertAreEqual(prefetchCount, 3, "cache.clear() stopped the prefetcher");
+                    djstest.done();
+                    window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
+                }, thenFailTest);
+                return {
+                    abort: function () { }
+                };
+            }
+            return oldHttpClientRequest(request, success, error);
+        };
+
+        try {
+            var options = { name: "cache", source: foodsFeed, pageSize: 1, prefetchSize: -1 };
+            createNewCache(options).then(function (cache) {
+                theCache = cache;
+                cache.readRange(0, 0).then(null, thenFailTest);
+            });
+        } catch (e) {
+            window.odatajs.oData.net.defaultHttpClient.request = oldHttpClientRequest;
+            djstest.fail("Exception thrown,  prefetchSize: " + tests[count] + " error:  " + e.message);
+            djstest.done();
+        }
+    });
+
+    djstest.addTest(function dataCacheFilterTest() {
+        var options = { name: "cache", source: foodsFeed, pageSize: 3, prefetchSize: -1 };
+        var counter = 0;
+
+        var singleItemPredicate = function (data) {
+            return data.FoodID === 2;
+        };
+
+        var multipleItemPredicate = function (data) {
+            return data.FoodID % 2 === 1;
+        };
+
+        var noItemPredicate = function (data) {
+            return data.Name === "something i would never eat";
+        };
+
+        var allItemPredicate = function (data) {
+            return data.FoodID >= 0;
+        };
+
+        var doneAfterAllTests = function () {
+            counter++;
+            if (counter === tests.length) {
+                djstest.done();
+            }
+        };
+
+        var last = collectionSize - 1;
+        var tests = [
+            { index: 0, count: -5, predicate: singleItemPredicate },    // Single match in entire collection
+            {index: 2, count: 1, predicate: singleItemPredicate },     // Single match, single count
+            {index: 3, count: 1, predicate: singleItemPredicate },     // Single match skipped, i.e. no matches
+            {index: 0, count: -1, predicate: multipleItemPredicate },  // Multiple matches in entire collection
+            {index: 0, count: 5, predicate: multipleItemPredicate },   // Multiple matches, take partial
+            {index: 3, count: 5, predicate: multipleItemPredicate },   // Multiple matches, skip/take partial
+            {index: 7, count: 10, predicate: multipleItemPredicate },  // Multiple matches, skip partial, take past end of collection
+            {index: 13, count: 4, predicate: allItemPredicate },       // All items match, skip/take partial
+            {index: 0, count: 20, predicate: noItemPredicate },        // No matches
+            {index: 0, count: 0, predicate: allItemPredicate },        // Zero count
+            {index: -5, count: 1, predicate: allItemPredicate },       // Negative index
+            {index: last + 1, count: 1, predicate: allItemPredicate }, // Index past end of collection
+
+            {index: last, count: -5, predicate: singleItemPredicate, backwards: true },        // Single match in entire collection
+            {index: 2, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match, single count
+            {index: 1, count: 1, predicate: singleItemPredicate, backwards: true },            // Single match skipped, i.e. no matches
+            {index: last, count: -1, predicate: multipleItemPredicate, backwards: true },      // Multiple matches in entire collection
+            {index: last, count: 6, predicate: multipleItemPredicate, backwards: true },       // Multiple matches, take partial
+            {index: last - 3, count: 5, predicate: multipleItemPredicate, backwards: true },   // Multiple matches, skip/take partial
+            {index: 13, count: 10, predicate: multipleItemPredicate, backwards: true },        // Multiple matches, skip partial, take past end of collection
+            {index: 4, count: 13, predicate: allItemPredicate, backwards: true },              // All items match, skip/take partial
+            {index: last, count: 20, predicate: noItemPredicate, backwards: true },            // No matches
+            {index: 0, count: 0, predicate: allItemPredicate, backwards: true },               // Zero count
+            {index: -5, count: 1, predicate: allItemPredicate, backwards: true },              // Negative index
+            {index: last + 1, count: 1, predicate: allItemPredicate, backwards: true },        // Index past end of collection
+
+            {index: "foo", count: 1, predicate: singleItemPredicate, exception: { message: "'index' must be a valid number.", index: NaN} },
+            { index: 0, count: "foo", predicate: multipleItemPredicate, exception: { message: "'count' must be a valid number.", count: NaN} }
+        ];
+
+        var testDescription = function(test) {
+            return "filter [" + test.index + ", " + test.count + " " + (test.backwards ? "back" : "forward") + "] for predicate " + test.predicate;
+        };
+
+        var filterErrorCallback = function (err) {
+            if (err && err.message) {
+                djstest.fail(err.message);
+            } else {
+                djstest.fail("unexpected promise failure");
+            }
+            doneAfterAllTests();
+        };
+
+        var removeSafariExceptionProperties = function (err) {
+            /** Removes Safari-specific properties from an exception object
+             * @param {Exception} err -The exception object to operate on
+             * @returns {Exception} The original exception object with the Safari-specific properties removed
+             */
+            var safariProperties = ["line", "expressionBeginOffset", "expressionEndOffset", "sourceId", "sourceURL"];
+
+            var result = {};
+            $.each(err, function (property, value) {
+                if ($.inArray(property, safariProperties) === -1) {
+                    result[property] = value;
+                }
+            });
+
+            return result;
+        };
+
+        ODataVerifyReader.readJsonAcrossServerPages(foodsFeed, function (expectData) {
+            $.each(tests, function (_, test) {
+                createNewCache(options).then(function (cache) {
+                    try {
+                        var expectedResults = {};
+                        if (test.backwards) {
+                            cache.filterBack(test.index, test.count, test.predicate).then(function (results) {
+                                expectedResults = CacheVerifier.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
+                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
+                                doneAfterAllTests();
+                            }, filterErrorCallback);
+                        } else {
+                            cache.filterForward(test.index, test.count, test.predicate).then(function (results) {
+                                expectedResults = CacheVerifier.getExpectedFilterResults(expectData, test.index, test.count, test.predicate, test.backwards);
+                                djstest.assertAreEqualDeep(results, expectedResults, "results for " + testDescription(test));
+                                doneAfterAllTests();
+                            }, filterErrorCallback);
+                        }
+
+                        if (test.exception) {
+                            djstest.fail("expected exception for " + testDescription(test));
+                            doneAfterAllTests();
+                        }
+                    } catch (err) {
+                        if (test.exception) {
+                            djstest.assertAreEqualDeep(removeSafariExceptionProperties(err), test.exception, "exception for " + testDescription(test));
+                        } else {
+                            djstest.fail("unexpected exception for " + testDescription(test) + ": " + djstest.toString(err));
+                        }
+                        doneAfterAllTests();
+                    }
+                }, thenFailTest);
+            });
+        });
+    });
+
+    djstest.addTest(function createDataCacheTest() {
+        var cache;
+
+        // Verify the defaults.
+        cache = odatajs.cache.createDataCache({ name: "name", source: "src" });
+
+        djstest.assertAreEqual(cache.onidle, undefined, "onidle is undefined");
+
+        // Verify specific values.
+        cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: 3, idle: 123 });
+
+        djstest.assertAreEqual(cache.onidle, 123, "onidle is as specified");
+
+        // Verify 0 pageSize 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 0, prefetchSize: 3, idle: 123 });
+        }, "zero pageSize");
+
+        // Verify negative pageSize
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: -2, prefetchSize: 3, idle: 123 });
+        }, "negative pageSize");
+
+        // Verify NaN pageSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: "2", prefetchSize: 3, idle: 123 });
+        }, "NaN pageSize");
+
+        // Verify NaN cacheSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: "1", pageSize: 2, prefetchSize: 3, idle: 123 });
+        }, "NaN cacheSize");
+
+        // Verify NaN prefetchSize
+        djstest.expectException(function () {
+            cache = odatajs.cache.createDataCache({ name: "name", source: "src", cacheSize: 1, pageSize: 2, prefetchSize: "3", idle: 123 });
+        }, "NaN prefetchSize");
+
+        // Verify undefined name 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "undefined name");
+
+        // Verify null name 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: null, source: "src", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "null name");
+
+        // Verify undefined source 
+        djstest.expectException(function () {
+            odatajs.cache.createDataCache({ name: "name", cacheSize: 1, pageSize: 1, prefetchSize: 3, idle: 123 });
+        }, "undefined source");
+
+        djstest.done();
+    });
+
+    djstest.addTest(function createDataCacheWithSourceTest() {
+        var cacheSource = {
+            count: function (success) {
+                djstest.pass("cacheSource.count was called");
+                success(0);
+            },
+
+            read: function (index, count, success, error) {
+                djstest.assertAreEqual(index, 0, "index is the expected one");
+                djstest.assertAreEqual(count, 10, "test is the expected one");
+                djstest.assert(success, "success is defined");
+                djstest.assert(error, "error is defined");
+                djstest.pass("cacheSource.read was called");
+
+                setTimeout(function () {
+                    success([]);
+                }, 0);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
+        cache.count().then(function () {
+            cache.readRange(0, 5).then(function () {
+                djstest.done();
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    djstest.addTest(function cacheInitializationFailTest() {
+        // Tests various failure modes for cache initialization.
+        var failures = ["read-settings", "write-settings", "v2"];
+        var failureIndex = 0;
+
+        var originalStore = odatajs.store.createStore;
+        var restoreStore = function () {
+            odatajs.store.createStore = originalStore;
+        };
+
+        var storeError = { message: "cacheInitializationFailTest error" };
+        odatajs.store.createStore = function (name, mechanism) {
+            return {
+                addOrUpdate: function (key, value, successCallback, errorCallback) {
+                    if (failures[failureIndex] === "write-settings") {
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    } else {
+                        djstest.fail("Error unaccounted for in addOrUpdate for " + failures[failureIndex]);
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    }
+                },
+                read: function (key, successCallback, errorCallback) {
+                    if (failures[failureIndex] === "read-settings") {
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    } else if (failures[failureIndex] === "v2") {
+                        window.setTimeout(function () {
+                            successCallback("K", { version: "2.0" });
+                        }, 2);
+                    } else if (failures[failureIndex] === "write-settings") {
+                        window.setTimeout(function () { successCallback(null, null); }, 2);
+                    } else {
+                        djstest.fail("Error unaccounted for read in " + failures[failureIndex]);
+                        window.setTimeout(function () { errorCallback(storeError); }, 2);
+                    }
+                }
+            };
+        };
+
+        var nextFailure = function () {
+            djstest.log("Failure mode: " + failures[failureIndex]);
+            var cache = odatajs.cache.createDataCache({ name: "name", source: "foo", mechanism: "memory", pageSize: 10 });
+            try {
+                // The first readRange should succeed, because the data cache isn't really initialized at this time.
+                cache.readRange(1, 2).then(djstest.failAndDoneCallback("No function should succeed"), function (err) {
+                    djstest.expectException(function () {
+                        cache.readRange(1, 2);
+                    }, "readRange after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.count();
+                    }, "count after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.clear();
+                    }, "clear after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.filterForward(1, 2);
+                    }, "filterForward after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.filterBack(1, 2);
+                    }, "filterBack after store is invalidated");
+
+                    djstest.expectException(function () {
+                        cache.toObservable();
+                    }, "toObservable after store is invalidated");
+
+                    failureIndex++;
+                    if (failureIndex === failures.length) {
+                        restoreStore();
+                        djstest.done();
+                    } else {
+                        nextFailure();
+                    }
+                });
+            } catch (outerError) {
+                djstest.fail("Unexpected failure for first .readRange: " + window.JSON.stringify(outerError));
+                restoreStore();
+                djstest.done();
+            }
+        };
+
+        nextFailure();
+    });
+
+    djstest.addTest(function createDataCacheWithSourceCallsErrorTest() {
+        var cacheSource = {
+            count: function () {
+                djstest.fail("cacheSource.count was called");
+            },
+
+            read: function (index, count, success, error) {
+                setTimeout(function () {
+                    error({ message: "source error" });
+                }, 0);
+            }
+        };
+
+        var cache = odatajs.cache.createDataCache({ name: "name", source: cacheSource, mechanism: "memory", pageSize: 10 });
+        cache.readRange(0, 5).then(function () {
+            djstest.fail("unexpected call to then success");
+            djstest.done();
+        }, function (err) {
+            djstest.assertAreEqual(err.message, "source error", "got the expected error");
+            djstest.done();
+        });
+    });
+
+    djstest.addTest(function toObservableMissingTest() {
+        createNewCache({ name: "cache", source: "http://temp.org" }).then(function (cache) {
+            var hiddenRx = window.Rx;
+            try {
+                window.Rx = null;
+                var error = null;
+                try {
+                    cache.toObservable();
+                } catch (err) {
+                    error = err;
+                }
+
+                djstest.assert(error !== null, "error !== null");
+            } finally {
+                window.Rx = hiddenRx;
+            }
+
+            djstest.assert(error !== null, "error !== null");
+            djstest.destroyCacheAndDone(cache);
+        });
+    });
+
+    djstest.addTest(function toObservableSinglePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
+            var lastId = -1;
+            cache.toObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableCaseSinglePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed }).then(function (cache) {
+            var lastId = -1;
+            cache.toObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableMultiplePageTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var callCount = 0;
+            cache.toObservable().subscribe(function (item) {
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+                callCount += 1;
+            }, thenFailTest, function () {
+                djstest.assert(lastId !== -1, "lastId !== -1");
+                djstest.assert(callCount > 1, "callCount > 1");
+                djstest.done();
+            });
+        });
+    });
+
+    djstest.addTest(function toObservableEarlyDisposeTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var callCount = 0;
+            var complete = false;
+            var observer = cache.toObservable().subscribe(function (item) {
+                djstest.assert(complete === false, "complete === false");
+                djstest.assert(lastId < item.FoodID, "lastId < item.FoodID");
+                lastId = item.FoodID;
+                callCount += 1;
+                complete = true;
+                observer.Dispose();
+                djstest.done();
+            }, thenFailTest);
+        });
+    });
+
+    djstest.addTest(function toObservableFailureTest() {
+        createNewCache({ name: "cache", source: foodsFeed, pageSize: 2 }).then(function (cache) {
+            var lastId = -1;
+            var complete = false;
+            window.MockHttpClient.clear().addResponse("*", { statusCode: 500, body: "server error" });
+            window.MockHttpClient.async = true;
+            var savedClient = window.odatajs.oData.net.defaultHttpClient;
+            window.odatajs.oData.net.defaultHttpClient = window.MockHttpClient;
+            cache.toObservable().subscribe(function (item) {
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                djstest.fail("Unexpected call to OnNext");
+            }, function (err) {
+                djstest.assert(complete === false, "complete === false");
+                djstest.assert(err, "err defined");
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                complete = true;
+                djstest.done();
+            }, function (complete) {
+                djstest.fail("Unexpected call to complete. Error handler should be called.");
+                window.odatajs.oData.net.defaultHttpClient = savedClient;
+                complete = true;
+                djstest.done();
+            });
+        });
+    });
+
+    // DATAJS INTERNAL START
+
+    djstest.addTest(function createDeferredTest() {
+        // Verify basic use of deferred object.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (val1, val2) {
+            djstest.assertAreEqual(val1, 1, "val1 is as specified");
+            djstest.assertAreEqual(val2, 2, "val2 is as specified");
+            djstest.done();
+        });
+        deferred.resolve(1, 2);
+    });
+
+    djstest.addTest(function deferredThenTest() {
+        // Verify then registration and chaining.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (val1, val2) {
+            djstest.assertAreEqual(val1, 1, "val1 is as specified");
+            djstest.assertAreEqual(val2, 2, "val2 is as specified");
+            return "foo";
+        }).then(function (foo) {
+            // See Compatibility Note B in DjsDeferred remarks.
+            djstest.assert(foo !== "foo", "argument for chained 'then' is *not* result of previous call");
+            djstest.assert(foo === 1, "argument for chained 'then' is same as for previous call");
+
+            var other = odatajs.deferred.createDeferred();
+            other.then(null, function (err, msg) {
+                djstest.assertAreEqual("error", err, "err is as specified");
+                djstest.assertAreEqual("message", msg, "msg is as specified");
+
+            }).then(null, function (err, msg) {
+                djstest.log("chained errors are called");
+
+                djstest.assertAreEqual("error", err, "err is as specified");
+                djstest.assertAreEqual("message", msg, "msg is as specified");
+
+                var multiple = odatajs.deferred.createDeferred();
+                var count = 0;
+
+                // See Compatibility Note A in DjsDeferred remarks.
+                multiple.then(function () {
+                    djstest.assertAreEqual(count, 0, "first base registration fires as #0");
+                    count++;
+                }).then(function () {
+                    djstest.assertAreEqual(count, 1, "first chained registration fires as #1");
+                    count++;
+                });
+
+                multiple.then(function () {
+                    djstest.assertAreEqual(count, 2, "second base registration fires as #2");
+                    count++;
+                }).then(function () {
+                    djstest.assertAreEqual(count, 3, "second chained registration fires as #3");
+                    djstest.done();
+                });
+
+                multiple.resolve();
+            });
+            other.reject("error", "message");
+        });
+
+        deferred.resolve(1, 2);
+    });
+
+    djstest.addTest(function deferredResolveTest() {
+        // Resolve with no arguments.
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(function (arg) {
+            djstest.assertAreEqual(arg, undefined, "resolve with no args shows up as undefined");
+
+            // Resolve with no callbacks.
+            var other = odatajs.deferred.createDeferred();
+            other.resolve();
+            djstest.done();
+        });
+
+        deferred.resolve();
+    });
+
+    djstest.addTest(function deferredRejectTest() {
+        // Resolve with no arguments.   
+        var deferred = odatajs.deferred.createDeferred();
+        deferred.then(null, function (arg) {
+            djstest.assertAreEqual(arg, undefined, "reject with no args shows up as undefined");
+
+            // Resolve with no callbacks.
+            var other = odatajs.deferred.createDeferred();
+            other.reject();
+            djstest.done();
+        });
+
+        deferred.reject();
+    });
+
+    djstest.addTest(function estimateSizeTest() {
+        var tests = [
+            { i: null, e: 8 },
+            { i: undefined, e: 8 },
+            { i: 0, e: 8 },
+            { i: "abc", e: 6 },
+            { i: [1, 2, 3], e: 30 },
+            { i: { a1: null, a2: undefined, a3: 5, a4: "ab", a5: { b1: 5, b2: 6} }, e: 72 },
+            { i: {}, e: 0 }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var test = tests[i];
+            djstest.assertAreEqual(odatajs.cache.estimateSize(test.i), test.e);
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function cacheOptionsTunnelTest() {
+        var mockClient = window.MockHttpClient;
+        var doneCalled = false;
+
+        mockClient.clear().setAsync(true).addRequestVerifier("*", function (theRequest) {
+            if (!doneCalled) {
+                doneCalled = true;
+                djstest.assertAreEqual(theRequest.user, "the-user", "theRequest.user");
+                djstest.assertAreEqual(theRequest.password, "the-password", "theRequest.password");
+                djstest.assertAreEqual(theRequest.enableJsonpCallback, false, "theRequest.enableJsonpCallback");
+                djstest.assertAreEqual(theRequest.callbackParameterName, "p", "callbackParameterName");
+                djstest.done();
+            }
+        });
+
+        var cache = odatajs.cache.createDataCache({
+            name: "cacheOptionsTunnel",
+            source: "http://foo-bar/",
+            user: "the-user",
+            password: "the-password",
+            enableJsonpCallback: false,
+            callbackParameterName: "p",
+            httpClient: mockClient
+        });
+
+        cache.readRange(0, 10).then(function (arr) {
+            djstest.fail("unexpected callback into readRange in test cacheOptionsTunnelTest");
+            if (!doneCalled) {
+                doneCalled = true;
+                djstest.done();
+            }
+        });
+    });
+
+    djstest.addTest(function dataCacheHandlesFullStoreTest() {
+
+        var TestStore = function (name) {
+            var that = new window.odatajs.store.MemoryStore(name);
+            that.addOrUpdate = function (key, value, success, error) {
+                if (key === "__settings") {
+                    window.setTimeout(function () {
+                        success(key, value);
+                    }, 0);
+                } else {
+                    window.setTimeout(function () {
+                        error({ name: "QUOTA_EXCEEDED_ERR" });
+                    }, 0);
+                }
+            };
+            return that;
+        };
+
+        TestStore.create = function (name) {
+            return new TestStore(name);
+        };
+
+        TestStore.isSupported = function () {
+            return true;
+        };
+
+        var cacheSource = {
+            identifier: "testSource",
+            count: function (success) {
+                djstest.fail("cacheSource.count was called");
+                success(5);
+            },
+            read: function (index, count, success, error) {
+                djstest.assertAreEqual(index, 0, "index is the expected one");
+                djstest.assertAreEqual(count, 5, "test is the expected one");
+
+                setTimeout(function () {
+                    success({ value: [1, 2, 3, 4, 5] });
+                }, 0);
+            }
+        };
+
+        var originalCreateStore = window.odatajs.store.createStore;
+
+        window.odatajs.store.createStore = function (name, mechanism) {
+            return TestStore(name);
+        };
+
+        try {
+            var cache = odatajs.cache.createDataCache({
+                name: "cache",
+                pageSize: 5,
+                prefetchSize: 0,
+                source: cacheSource,
+                mechanism: "teststore"
+            });
+        } finally {
+            window.odatajs.store.createStore = originalCreateStore;
+        }
+
+        cache.readRange(0, 5).then(function (data) {
+            djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
+            cache.readRange(0, 5).then(function (data) {
+                djstest.assertAreEqual(data.value.length, 5, "5 items were read.");
+                djstest.done();
+            }, thenFailTest);
+        }, thenFailTest);
+    });
+
+    // DATAJS INTERNAL END
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html b/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
new file mode 100644
index 0000000..a3820cb
--- /dev/null
+++ b/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.html
@@ -0,0 +1,53 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<html>
+<head>
+    <title>datajs.cache and datajs.store full local store tests</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>-->
+    <!--<script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>-->
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
+    <!--<script type="text/javascript" src="common/common.js"></script>-->
+
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/djstest-browser.js"></script>
+    <script type="text/javascript" src="common/cacheVerifier.js"></script>
+    <script type="text/javascript" src="common/observableHttpClient.js"></script>
+    <!--<script type="text/javascript" src="common/ODataReadOracle.js"></script>-->
+    
+    <script type="text/javascript" src="b-datajs-cache-large-collection-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache and datajs.store full local store 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/d5ec5557/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js b/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
new file mode 100644
index 0000000..d09ae51
--- /dev/null
+++ b/odatajs/tests-tmp/b-datajs-cache-large-collection-functional-tests.js
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    window.odatajs.oData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var largeCollectionFeed = "./endpoints/LargeCollectionService.svc/Customers";
+    var itemsInCollection = 2 * 1024 * 1024;
+
+    var cleanDomStorage = function (done) {
+        /* Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
+         *  setup and teardown methods to be consistent with indexedDb's cleanup method.
+         * @param {Function} done - Function to be called after DOM storage is cleared.
+         */
+        if (window.localStorage) {
+            window.localStorage.clear();
+        }
+        done();
+    };
+
+    var cleanIndexedDb = function (done) {
+        /** Cleans all the data saved in the browser's IndexedDb Storage.
+         * @param {Function} done - Function to be called after DOM storage is cleared.
+         */
+        var caches = this.caches;
+
+        djstest.cleanStoreOnIndexedDb(caches, done);
+    };
+
+    var makeUnexpectedErrorHandler = function () {
+        return function (err) {
+            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        };
+    };
+
+    var storageMechanisms = {
+        indexeddb: { cleanup: cleanIndexedDb },
+        dom: { cleanup: cleanDomStorage }
+    };
+
+    var cleanupAllStorage = function(done) {
+        /** Cleans up all available storage mechanisms in the browser.
+         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
+         */
+        var that = this;
+        var storeCleanup = [];
+
+        $.each(CacheVerifier.mechanisms, function(_, mechanism) {
+            if (CacheVerifier.isMechanismAvailable(mechanism)) {
+                storeCleanup.push(function(done) {
+                    if (storageMechanisms[mechanism]) {
+                        storageMechanisms[mechanism].cleanup.call(that, done);
+                    } else {
+                        done();
+                    }
+                });
+            }
+        });
+
+        djstest.asyncDo(storeCleanup, done);
+    };
+
+
+    module("Functional", {
+        setup: function () {
+            this.observableHttpClient = new ObservableHttpClient();
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
+            this.caches = [];
+            var that = this;
+
+            djstest.wait(function (done) {
+                cleanupAllStorage.call(that, done);
+            });
+        },
+
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
+            var clearActions = [];
+            var that = this;
+
+            $.each(this.caches, function (_, cacheObject) {
+                cacheObject.cache.onidle = undefined;
+
+                clearActions.push(function (done) {
+                    cacheObject.cache.clear().then(function () {
+                        done();
+                    },
+                        function (err) {
+                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
+                        });
+                });
+            });
+
+            djstest.wait(function (done) {
+                djstest.asyncDo(clearActions, function () {
+                    cleanupAllStorage.call(that, function () {
+                        that.caches = [];
+                        done();
+                    });
+                });
+            });
+        }
+    });
+
+    $.each(["dom", "indexeddb"], function (_, mechanism) {
+        if (CacheVerifier.isMechanismAvailable(mechanism)) {
+            $.each([-1, 10 * 1024 * 1024, 1024 * 10248], function (_, cacheSize) {
+                var prefetchParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 5, pageSize: 1024, prefetchSize: -1, cacheSize: cacheSize };
+                djstest.addTest(function (params) {
+
+                    djstest.assertsExpected(3);
+                    var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+                        mechanism: params.mechanism, cacheSize: params.cacheSize
+                    };
+
+                    var cache = odatajs.cache.createDataCache(options);
+                    this.caches.push({ name: options.name,
+                        cache: cache
+                    });
+
+                    cache.onidle = function () {
+                        djstest.assert(true, "onidle Called");
+                        djstest.done();
+                    };
+
+                    var cacheOracle = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
+                    var session = this.observableHttpClient.newSession();
+
+                    cache.readRange(params.skip, params.take).then(function (data) {
+                        var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+                        cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests with prefetch", false, true);
+                        window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                        });
+                    }, function (err) {
+                        makeUnexpectedErrorHandler(err)();
+                    });
+                }, "readRange and prefetch all to fill store on " + prefetchParameters.mechanism + " with cacheSize=" + prefetchParameters.cacheSize, prefetchParameters, 600000);
+
+                $.each([500, 1024 * 10 /*Test reduced from 100 to 10 to work around slow running script error in IE8 and Safari (bug 2200)*/], function (_, pageSize) {
+                    var largeReadParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 1024, pageSize: pageSize, prefetchSize: 0, cacheSize: cacheSize };
+                    djstest.addTest(function (params) {
+
+                        djstest.assertsExpected(2);
+                        var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+                            mechanism: params.mechanism, cacheSize: params.cacheSize
+                        };
+
+                        var cache = odatajs.cache.createDataCache(options);
+                        this.caches.push({ name: options.name, cache: cache });
+
+                        var cacheOracle = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
+                        var session = this.observableHttpClient.newSession();
+
+                        cache.readRange(params.skip, params.take).then(function (data) {
+                            var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+                            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests without prefetch", false, false);
+                            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                                djstest.done();
+                            });
+                        }, function (err) {
+                            makeUnexpectedErrorHandler(err)();
+                            djstest.done();
+                        });
+                    }, "readRange of skip=" + largeReadParameters.skip + " take=" + largeReadParameters.take + " cacheSize=" + largeReadParameters.cacheSize + " and pageSize=" + largeReadParameters.pageSize +
+                        " to fill store on " + largeReadParameters.mechanism, largeReadParameters, 600000);
+                });
+            });
+        }
+    });
+})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/bn-odata-json-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/bn-odata-json-tests.js b/odatajs/tests-tmp/bn-odata-json-tests.js
new file mode 100644
index 0000000..3e306a5
--- /dev/null
+++ b/odatajs/tests-tmp/bn-odata-json-tests.js
@@ -0,0 +1,211 @@
+/*
+ * 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) {
+    QUnit.module("odata-json-tests.js");
+
+    djstest.addTest(function isArrayTest() {
+        djstest.assert(window.odatajs.utils.isArray([]));
+        djstest.assert(window.odatajs.utils.isArray([1, 2]));
+        djstest.assert(!window.odatajs.utils.isArray({}));
+        djstest.assert(!window.odatajs.utils.isArray("1,2,3,4"));
+        djstest.assert(!window.odatajs.utils.isArray());
+        djstest.assert(!window.odatajs.utils.isArray(null));
+        djstest.done();
+    });
+
+    var verifyReadJsonLightDataMetadataFull = function (input, expected, message, model) {
+        var response = { 
+          headers: { 
+            "Content-Type": "application/json;odata.metadata=full",
+             DataServiceVersion: "4.0"
+          },
+          body: JSON.stringify(input) 
+        };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+
+    var verifyReadJsonLightDataMetadataMinimal= function (input, expected, message, model) {
+        var response = { 
+          headers: { 
+            "Content-Type": "application/json;odata.metadata=minimal",
+             DataServiceVersion: "4.0"
+          },
+          body: JSON.stringify(input) 
+        };
+
+        window.odatajs.oData.json.jsonHandler.read(response, { metadata: model });
+        djstest.assertAreEqualDeep(response.data, expected, message);
+    };
+
+
+    function createPointValue(geoKind) { 
+      return { 
+        edmType : geoKind+'Point', value : {
+          type: "Point",
+          coordinates: [1.0, 2.0],
+          crs: {
+              type: "Point",
+              properties: {
+                  name: "EPSG:4326"
+              }
+          }
+        }
+      };
+    }
+
+    function createLineStringValue(geoKind) { 
+      return  { 
+        edmType : geoKind+'LineString', value : {
+          "type": "LineString",
+          "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
+          crs: {
+              type: "LineString",
+              properties: {
+                  name: "EPSG:4326"
+              }
+          }
+        }
+      };
+    }
+
+    function createPolygonValue(geoKind) { 
+      return  {
+        edmType : geoKind+'Polygon', value : {
+          "type": "Polygon",
+          "coordinates": [
+            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
+            [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
+            ],
+          crs: {
+              type: "Polygon",
+              properties: {
+                  name: "EPSG:4326"
+              }
+          }
+        }
+      };
+    }
+
+    function createMultiPointValue(geoKind) { 
+      return  { 
+        edmType : geoKind+'MultiPoint', value : {
+          "type": "MultiPoint",
+          "coordinates": [ [100.0, 0.0], [101.0, 1.0] ],
+          crs: {
+              type: "MultiPoint",
+              properties: {
+                  name: "EPSG:4326"
+              }
+          }
+        }
+      };
+    }
+
+    function createMultiLineStringValue(geoKind) { 
+      return  { 
+        edmType : geoKind+'MultiLineString', value : {
+          "type": "MultiLineString",
+          "coordinates": [
+              [ [100.0, 0.0], [101.0, 1.0] ],
+              [ [102.0, 2.0], [103.0, 3.0] ]
+            ],
+          crs: {
+              type: "MultiLineString",
+              properties: {
+                  name: "EPSG:4326"
+              }
+          }
+        }
+      };
+    }
+    function createMultiPolygonStringValue(geoKind) { 
+      return  { 
+        edmType : geoKind+'MultiPolygon', value : {
+                "type": "MultiPolygon",
+                "coordinates": [
+                  [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
+                  [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
+                   [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
+                  ],
+              crs: {
+                  type: "MultiPolygon",
+                  properties: {
+                      name: "EPSG:4326"
+                  }
+              }
+            }
+          };
+        }
+
+    function createWorkload(geoKind) { 
+      return [
+        createPointValue(geoKind),
+        createLineStringValue(geoKind), 
+        createPolygonValue(geoKind),
+        createMultiPointValue(geoKind),
+        createMultiLineStringValue(geoKind),
+        createMultiPolygonStringValue(geoKind) 
+      ];
+    }
+
+    function checkGeoKind(geoKind, full) {
+      var workload = createWorkload(geoKind);
+      for ( var i = 0; i < workload.length; i++) {
+        var item = workload[i]; 
+        var input = {
+          "@odata.context": "http://someUri#Edm."+item.edmType,
+          "value@odata.type" : item.edmType,
+          value: item.value
+        }; 
+
+        var expected = {
+          "@odata.context": "http://someUri#Edm."+item.edmType,
+          "value@odata.type" : item.edmType,
+          value: item.value
+        };
+        if (full) {
+          verifyReadJsonLightDataMetadataFull(input, expected, item.edmType + " was read properly.", {});
+        } else {
+          verifyReadJsonLightDataMetadataMinimal(input, expected, item.edmType + " was read properly.", {});
+        }
+      }
+      
+      djstest.done();
+    }
+
+    djstest.addTest(function jsonReadGeometryFull() {
+      checkGeoKind('Geometry',true);
+    });
+    djstest.addTest(function jsonReadGeometryMinimal() {
+      checkGeoKind('Geometry',false);
+    });
+    djstest.addTest(function jsonReadGeographyFull() {
+      checkGeoKind('Geography',true);
+    });
+    djstest.addTest(function jsonReadGeographyMinimal() {
+      checkGeoKind('Geography',false);
+    });
+
+})(window);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/ODataVerifiyReader.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/ODataVerifiyReader.svc b/odatajs/tests-tmp/common/ODataVerifiyReader.svc
new file mode 100644
index 0000000..101cf36
--- /dev/null
+++ b/odatajs/tests-tmp/common/ODataVerifiyReader.svc
@@ -0,0 +1,114 @@
+/*
+ * 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.
+*/
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
+    Service="DataJS.Tests.ODataVerifyReader" %>
+
+//uncomment this line to debug JSON serialization.
+//#define DEBUG_SERIALIZATION
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using System.Net;
+    using System.Runtime.Serialization;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Syndication;
+    using System.ServiceModel.Web;
+    using System.Xml;
+    using System.Xml.Linq;
+    using Microsoft.Spatial;
+    using Microsoft.OData.Core;
+    using System.Web.Script.Serialization;
+
+    /// <summary>
+    /// Oracle for the OData.read library function
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class ODataVerifyReader
+    {
+        const string jsonlightMediaType = "application/json";
+
+        /// <summary>
+        /// Reads a URI that will return a metadata object
+        /// </summary>
+        /// <param name="url">The URL to send the request to</param>
+        /// <returns>Stream of metadata in json light format</returns>
+        [OperationContract]
+        [WebGet]
+        public Stream ReadMetadata(string url)
+        {
+            WebResponse response = WebRequest.Create(ResolveUri(url, UriKind.Absolute)).GetResponse();
+            Dictionary<string, object> jsonObject = CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream()));
+            return ReaderUtils.ConvertDictionarytoJsonlightStream(jsonObject);
+        }
+        
+        /// <summary>
+        /// Reads a URI that will get the Json response and return the stream
+        /// </summary>
+        /// <param name="url">URL of the entry</param>
+        /// <param name="user">The username for basic authentication</param>
+        /// <param name="password">The password for basic authentication</param>
+        /// <returns>Stream of the Json response expected to be returned by OData.read</returns>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public Stream ReadJson(string url, string mimeType, string user, string password)
+        {
+            if (mimeType == null)
+            {
+                mimeType = jsonlightMediaType + ";odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8";
+            }
+            
+            HttpWebRequest request = (HttpWebRequest)ReaderUtils.CreateRequest(ResolveUri(url, UriKind.Absolute), user, password);
+            request.Accept = mimeType;
+            WebResponse response = request.GetResponse();
+
+            return response.GetResponseStream();
+        }
+
+        /// <summary>
+        /// Resolves the given url string to a URI
+        /// </summary>
+        /// <param name="url">The given URL string</param>
+        /// <param name="urlKind">URI kind to resolve to</param>
+        /// <returns>The resolved URI</returns>
+        private static string ResolveUri(string url, UriKind uriKind)
+        {
+            Uri resolvedUri = new Uri(url, UriKind.RelativeOrAbsolute);
+            if (!resolvedUri.IsAbsoluteUri)
+            {
+                // If the given URI is relative, then base it on the Referer URI
+                Uri baseUri = new Uri(WebOperationContext.Current.IncomingRequest.Headers["Referer"]);
+                resolvedUri = new Uri(baseUri, resolvedUri);
+                if (uriKind == UriKind.Relative)
+                {
+                    resolvedUri = baseUri.MakeRelativeUri(resolvedUri);
+                }
+            }
+
+            return resolvedUri.ToString();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/djstest-browser.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/djstest-browser.js b/odatajs/tests-tmp/common/djstest-browser.js
new file mode 100644
index 0000000..14e5401
--- /dev/null
+++ b/odatajs/tests-tmp/common/djstest-browser.js
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+
+// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
+// we define the @namespace djstest here instead of the a @module name djstest
+
+/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
+ * @namespace djstest
+ */
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    window.djstest = window.djstest || {};
+    init(window.djstest);
+} else {
+    //expose in commonjs style
+    module.exports = init();
+}
+
+
+function init (parent) {
+    djstest = parent || {};
+
+    // Initialize indexedDB if the window object is available
+    djstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
+
+    /** Cleans all the test data saved in the IndexedDb database.
+     * @param {Array} storeNames - Array of store objects with a property that is the name of the store
+     * @param {Function} done - Callback function
+     */
+    djstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
+        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
+
+        function deleteObjectStores(db) {
+            for ( var i = 0 ; i < db.objectStoreNames.length ; i ++) {
+                db.deleteObjectStore(db.objectStoreNames[i]);
+            }
+        }
+        var job;
+
+        if (djstest.indexedDB) {
+            job = new djstest.Job();
+            for ( var i = 0 ; i < storeObjects.length ; i ++) {
+                storeObject = storeObjects[i];
+                job.queue((function (storeObject) {
+                    return function (success, fail) {
+                        var dbname = "_datajs_" + storeObject.name;
+                        var request = djstest.indexedDB.open(dbname);
+                        request.onsuccess = function (event) {
+                            var db = request.result;
+
+                            if ("setVersion" in db) {
+                                var versionRequest = db.setVersion("0.1");
+                                versionRequest.onsuccess = function (event) {
+                                    var transaction = versionRequest.transaction;
+                                    transaction.oncomplete = function () {
+                                        db.close();
+                                        success();
+                                    };
+                                    deleteObjectStores(db);
+                                };
+                                versionRequest.onerror = function (e) {
+                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
+                                    fail();
+                                };
+                                return;
+                            }
+
+                            // new api cleanup
+                            db.close();
+                            var deleteRequest = djstest.indexedDB.deleteDatabase(dbname);
+                            deleteRequest.onsuccess = function (event) {
+                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
+                                success();
+                            };
+                            deleteRequest.onerror = function (e) {
+                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
+                                fail();
+                            };
+                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
+                        };
+
+                        request.onerror = function (e) {
+                            djstest.fail(e.code + ": " + e.message);
+                        };
+                    };
+                })(storeObject));
+            }
+        }
+
+        if (job) {
+            job.run(function (succeeded) {
+                if (!succeeded) {
+                    djstest.fail("cleanup job failed");
+                }
+                done();
+            });
+        }
+        else {
+            done();
+        }
+    };
+
+
+    // Disable caching to ensure that every test-related AJAX request is actually being sent,
+    // and set up a default error handler
+    if (typeof window !== undefined) {
+        $.ajaxSetup({
+            cache: false,
+            error: function (jqXHR, textStatus, errorThrown) {
+                // Work around bug in IE-Mobile on Windows Phone 7
+                if (jqXHR.status !== 1223) {
+                    var err = {
+                        status: jqXHR.status,
+                        statusText: jqXHR.statusText,
+                        responseText: jqXHR.responseText
+                    };
+                    djstest.fail("AJAX request failed with: " + djstest.toString(err));
+                }
+                djstest.done();
+            }
+        });
+    }
+    return djstest;
+}


[26/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/store-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/store-tests.js b/datajs/tests/store-tests.js
deleted file mode 100644
index 48169c3..0000000
--- a/datajs/tests/store-tests.js
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// odata-tests.js
-(function (window, undefined) {
-
-    var cleanDomStorage = function () {
-        /** Cleans all the data saved in the browser's DOM Storage.
-        */
-        if (window.localStorage) {
-            window.localStorage.clear();
-        }
-    };
-
-    var cleanMemoryStorage = function () {
-        /** Clean memory storage is a no op.
-        */
-    };
-
-    var cleanIndexedDbStorage = function () {
-        var stores = this.stores;
-        $.each(stores, function (_, store) {
-            store.close();
-        });
-
-        djstest.wait(function (done) {
-            djstest.cleanStoreOnIndexedDb(stores, done);
-        });
-    };
-
-    var canCreateMemoryStore = function () {
-        /** Checks whether memory storage is supported by the browser.
-         * @returns {boolean} True
-         */
-        return true;
-    };
-
-    var canCreateDomStore = function () {
-        /** Checks whether Web Storage (DOM Storage) is supported by the browser.
-         * @returns {boolean} True if DOM Storage is supported by the browser; false otherwise.
-         */
-        return !!window.localStorage;
-    };
-
-    var canCreateIndexedDb = function () {
-        /** Checks whether Web Storage (DOM Storage) is supported by the browser.
-         * @returns {Boolean} True if IndexedDB is supported by the browser, false otherwise.
-         */
-        return !!djstest.indexedDB;
-    };
-
-    var canCreateStore = function (mechanism) {
-        /** Determines whether a particular mechanism is supported by the browser.
-         * @param {String} mechanism - Mechanism name.
-         * @returns {Boolean} True if the mechanism is supported by the browser; otherwise false.
-         */
-        var implementation = mechanismImplementations[mechanism];
-        return implementation && implementation.canCreate();
-    }
-    var makeUnexpectedErrorHandler = function (fail) {
-        return function (err) {
-            djstest.fail("error: " + err.name + " -- message: " + err.message);
-            fail();
-        };
-    };
-
-    var testJobDone = function (succeeded) {
-        if (!succeeded) {
-            djstest.fail("Job completed but some of the functions it called failed");
-        }
-        djstest.done();
-    };
-
-    var mechanismImplementations = {
-        indexeddb: { factory: odatajs.IndexedDBStore, canCreate: canCreateIndexedDb, cleanup: cleanIndexedDbStorage },
-        dom: { factory: odatajs.DomStore, canCreate: canCreateDomStore, cleanup: cleanDomStorage },
-        memory: { factory: odatajs.MemoryStore, canCreate: canCreateMemoryStore, cleanup: cleanMemoryStorage }
-    };
-
-    var oldWindowOnError;
-
-    for (var mechanism in mechanismImplementations) {
-        module("Unit", {
-            mechanism: mechanism,
-            createStore: function (name) {
-                var store = odatajs.store.createStore(name + "_" + this.mechanism, this.mechanism);
-                this.stores.push(store);
-                return store;
-            },
-            setup: function () {
-                this.stores = [];
-                mechanismImplementations[this.mechanism].cleanup.call(this);
-
-                // FireFox 7.0.1 bubbles an error event when there is an IndexedDB error, even when the error has been handled graciously.
-                // This is a work around to keep QUnit from reporting false failures in IndexedDB negative tests.
-                if (this.mechanism === "indexeddb") {
-                    oldWindowOnError = window.onerror;
-                    window.onerror = null;
-                }
-            },
-            teardown: function () {
-                mechanismImplementations[this.mechanism].cleanup.call(this);
-                this.stores = [];
-
-                // Restore QUnit's onerror handler.
-                if (this.mechanism === "indexeddb") {
-                    window.onerror = oldWindowOnError;
-                }
-            }
-        });
-
-        if (!canCreateStore(mechanism)) {
-            djstest.addTest(function (mechanism) {
-                djstest.expectException(function () {
-                    mechanismImplemenatations[mechanism].factory.create("my horrible not working store");
-                });
-                djstest.done();
-            }, "Local storage mechanism " + mechanism + " not supported by this browser", mechanism);
-        } else {
-
-            djstest.addTest(function storeAddTest(mechanism) {
-                var tuples = [
-                    { key: "null", value: null },
-                    { key: "undefined", value: undefined },
-                    { key: "number", value: 12345.678 },
-                    { key: "string", value: "String value" },
-                    { key: "date", value: new Date() },
-                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b"}} },
-                    { key: "array", value: [1, 2, 3, 4, 5] },
-                    { key: "key1", value: "some value" },
-                    { key: "key1", value: "this should fail", error: true },
-                    { key: ["key", "key2"], value: ["value", "value2"], error: mechanism !== "indexeddb" },
-                    { key: ["key6", "key7", "key6"], value: ["value", "value2", "value3"], error: true }
-                ];
-
-                var store = this.createStore("store1");
-                var job = new djstest.Job();
-
-                $.each(tuples, function (_, tuple) {
-                    job.queue(function task(success, fail) {
-
-                        var unexpectedError = makeUnexpectedErrorHandler(fail);
-                        djstest.log("running task");
-
-                        store.add(tuple.key, tuple.value,
-                            function (key, value) {
-                                djstest.assertAreEqual(key, tuple.key, "Keys match for " + mechanism + " - key = " + key.toString());
-                                djstest.assertAreEqualDeep(value, tuple.value, "Values match for " + mechanism + " - key = " + key.toString());
-
-                                job.queueNext(function (success, fail) {
-                                    store.read(tuple.key, function (key, value) {
-                                        djstest.assertAreEqualDeep(value, tuple.value, "Key: " + key + " is present in the store");
-                                        success();
-                                    }, makeUnexpectedErrorHandler(fail));
-                                });
-                                success();
-                            },
-                            function (err) {
-                                if (!tuple.error) {
-                                    unexpectedError(err);
-                                } else {
-                                    djstest.pass("error handler was called as expected");
-                                    success();
-                                }
-                            });
-                    });
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-
-            }, "Store Add Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeAddOrUpdateTest(mechanism) {
-                var tuples = [
-                    { key: "null", value: null },
-                    { key: "undefined", value: undefined },
-                    { key: "number", value: 12345.678 },
-                    { key: "string", value: "String value" },
-                    { key: "date", value: new Date() },
-                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b"}} },
-                    { key: "array", value: [1, 2, 3, 4, 5] },
-                    { key: "key1", value: "some value" },
-                    { key: "key1", value: "this should not fail" },
-                    { key: ["key", "key2", "key3"], value: ["value", "value2", "value3"], error: mechanism !== "indexeddb" },
-                    { key: ["key", "key2", "key3"], value: ["value4", "value5", "value6"], error: mechanism !== "indexeddb" },
-                    { key: "key1", value: 456 }
-                ];
-
-                var store = this.createStore("store2");
-                var job = new djstest.Job();
-
-                $.each(tuples, function (_, tuple) {
-                    job.queue(function (success, fail) {
-
-                        var unexpectedError = makeUnexpectedErrorHandler(fail);
-
-                        store.addOrUpdate(tuple.key, tuple.value,
-                            function (key, value) {
-                                djstest.assert(!tuple.error, "success should be called");
-                                djstest.assertAreEqual(key, tuple.key, "Keys match");
-                                djstest.assertAreEqualDeep(value, tuple.value, "Values match");
-
-                                store.read(tuple.key, function (key, value) {
-                                    djstest.assertAreEqual(key, tuple.key, "Keys match");
-                                    djstest.assertAreEqualDeep(value, tuple.value, "Values match");
-                                    success();
-                                }, unexpectedError);
-                            },
-                            function (err) {
-                                if (!tuple.error) {
-                                    unexpectedError(err);
-                                } else {
-                                    djstest.pass("error handler was called as expected");
-                                    success();
-                                }
-                            });
-                    });
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Add or Update Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeContainsTest(mechanism) {
-                var store = this.createStore("store3");
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add("Key1", "Some value", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.contains("Key1", function (contained) {
-                        djstest.assert(contained, "Key is present in the store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.contains("Key2", function (contained) {
-                        djstest.assert(!contained, "Key is not present in the store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-
-            }, "Store Contains Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeGetAllKeysTest(mechanism) {
-                var store = this.createStore("store4");
-                var store2 = this.createStore("store4_1");
-
-                var expectedKeys = [];
-                var job = new djstest.Job();
-
-                var i;
-                for (i = 1; i <= 20; i++) {
-                    (function (i) {
-                        job.queue(function (success, fail) {
-                            store.add(i.toString(), "value" + i, success, makeUnexpectedErrorHandler(fail));
-                        });
-
-                        job.queue(function (success, fail) {
-                            store2.add((i + 20).toString(), "value" + (i + 20), success, makeUnexpectedErrorHandler(fail));
-                        });
-                    })(i);
-
-                    expectedKeys.push(i.toString());
-                }
-
-                job.queue(function (success, fail) {
-                    store.getAllKeys(function (keys) {
-                        expectedKeys.sort();
-                        keys.sort();
-                        djstest.assertAreEqualDeep(keys, expectedKeys, "All expected keys where returned");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    store2.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Get All Keys Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeReadTest(mechanism) {
-                var tuples = [
-                    { key: "null", value: null },
-                    { key: "undefined", value: undefined },
-                    { key: "number", value: 12345.678 },
-                    { key: "string", value: "String value" },
-                    { key: "date", value: new Date() },
-                    { key: "dateOffset", value: (function () {
-                        var d = new Date();
-                        d.__type = "Edm.DateTimeOffset";
-                        d.__offset = "+03:30";
-                        return d;
-                    })()
-                    },
-                    { key: "complexDate", value: (function () {
-                        var d = new Date();
-                        d.nestedDate = new Date();
-                        d.nestedDate.__type = "Edm.DateTimeOffset";
-                        d.nestedDate.__offset = "+03:30";
-                        return d;
-                    })()
-                    },
-                    { key: "object", value: { p1: 1234, nested: { p1: "a", p2: "b", p3: new Date()}} },
-                    { key: "array", value: [1, 2, 3, 4, 5] }
-                ];
-
-                var store = this.createStore("store5");
-                var job = new djstest.Job();
-
-                $.each(tuples, function (_, tuple) {
-                    job.queue(function (success, fail) {
-                        store.add(tuple.key, tuple.value,
-                            function () {
-                                job.queue(function (success, fail) {
-                                    store.read(tuple.key, function (key, value) {
-                                        djstest.assertAreEqual(key, tuple.key, "Keys match");
-                                        djstest.assertAreEqualDeep(value, tuple.value, "Values match");
-                                        success();
-                                    }, makeUnexpectedErrorHandler(fail));
-                                });
-                                success();
-                            },
-                           function (err) {
-                               if (!tuple.error) {
-                                   djstest.fail(err.message);
-                                   fail();
-                               } else {
-                                   djstest.pass("error handler was called as expected");
-                                   success();
-                               }
-                           });
-                    });
-                });
-
-                job.queue(function (success, fail) {
-                    store.read("Unknown key", function (key, value) {
-                        djstest.assertAreEqual(value, undefined, "Store get returns undefined for keys that do not exist in the store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-
-            }, "Store Read Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeReadArrayTest(mechanism) {
-                var makeError = function (success, fail) {
-                    return function (err) {
-                        if (mechanism !== "indexeddb") {
-                            djstest.pass("Error callback called as expected");
-                            success();
-                        } else {
-                            djstest.fail(err.message);
-                            fail();
-                        }
-                    };
-                };
-
-                var store = this.createStore("store6");
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add(["key", "key2", "key3"], ["value", "value2", "value3"], success, makeError(success, fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.read(["key", "key2", "key3"], function (keys, values) {
-                        djstest.assertAreEqualDeep(keys, ["key", "key2", "key3"]);
-                        djstest.assertAreEqualDeep(values, ["value", "value2", "value3"]);
-                        success();
-                    }, makeError(success, fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.read(["key", "badkey"], function (keys, values) {
-                        djstest.assertAreEqualDeep(keys, ["key", "badkey"]);
-                        djstest.assertAreEqualDeep(values, ["value", undefined]);
-                        success();
-                    }, makeError(success, fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Read Array Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeRemoveTest(mechanism) {
-                var store = this.createStore("store7");
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add("Key1", "Some value", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.add("Key2", "Some value", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.remove("Key1", function () {
-                        djstest.pass("Key1 was removed from the store")
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.contains("Key1", function (contained) {
-                        djstest.assert(!contained, "Key1 is not present in the store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.remove("Key that has never been added", function () {
-                        djstest.pass('"Key that has never been added" was removed from the store');
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.contains("Key2", function (contained) {
-                        djstest.assert(contained, "Key2 is present in the store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Remove Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeUpdateTest(mechanism) {
-                var store = this.createStore("store8");
-
-                var startKey = "Key1";
-                var startValue = "start value";
-                var updateKey = "Key2";
-                var updatedValue = "updated value";
-
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add(startKey, startValue, success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.add(updateKey, startValue, success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.update(updateKey, updatedValue, function (key, value) {
-                        djstest.assertAreEqual(key, updateKey, "Updated keys match");
-                        djstest.assertAreEqualDeep(value, updatedValue, "Updated values match");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.read(updateKey, function (key, value) {
-                        djstest.assertAreEqual(key, updateKey, "Updated keys match after get");
-                        djstest.assertAreEqualDeep(value, updatedValue, "Updated values match after get");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.read(startKey, function (key, value) {
-                        djstest.assertAreEqual(key, startKey, "Non updated keys match after get");
-                        djstest.assertAreEqualDeep(value, startValue, "Non updated values match after get");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Update Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeClearTest(mechanism) {
-                var store = this.createStore("store9");
-                var store2 = this.createStore("store9_1");
-
-                var job = new djstest.Job();
-                job.queue(function (success, fail) {
-                    store.add("Key1", "value in store", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.add("Key2", "value in store", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.add("Key3", "value in store", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store2.add("Key1", "value in store2", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.clear(function () {
-                        djstest.pass("Store was cleared");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.contains("Key1", function (contained) {
-                        djstest.assert(!contained, "Key1 was removed from store");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store2.contains("Key1", function (contained) {
-                        djstest.assert(contained, "Key1 still exists in store 2");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    store2.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Clear Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeUpdateNonExistentTest(mechanism) {
-                var store = this.createStore("store10");
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add("key", "value", success, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.update("badKey", "new value",
-                        function () {
-                            djstest.fail("Sucess handler called when not expected");
-                            fail();
-                        },
-                        function (err) {
-                            djstest.pass("Error callback called as expexted");
-                            success();
-                        });
-                });
-
-                job.queue(function (success, fail) {
-                    store.update(["key", "badkey"], ["value", "badvalue"],
-                        function () {
-                            djstest.fail("Sucess handler called when not expected");
-                            fail();
-                        },
-                        function (err) {
-                            djstest.pass("Error callback called as expected");
-                            success();
-                        });
-                });
-
-                job.queue(function (success, fail) {
-                    store.read("key", function (key, value) {
-                        djstest.assertAreEqual(value, "value", "value was not changed");
-                        success();
-                    }, makeUnexpectedErrorHandler(fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Update Non-Existent Test with mechanism " + mechanism, mechanism);
-
-            djstest.addTest(function storeUpdateArrayTest(mechanism) {
-                var makeError = function (success, fail) {
-                    return function (err) {
-                        if (mechanism !== "indexeddb") {
-                            djstest.pass("Error callback called as expected");
-                            success();
-                        } else {
-                            djstest.fail(err.message);
-                            fail();
-                        }
-                    };
-                };
-
-                var store = this.createStore("store11");
-                var job = new djstest.Job();
-
-                job.queue(function (success, fail) {
-                    store.add(["key", "key2"], ["value1", "value2"], success, makeError(success, fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.update(["key", "key2"], ["value1", "value4"], success, makeError(success, fail));
-                });
-
-                job.queue(function (success, fail) {
-                    store.read(["key", "key2"], function (key, value) {
-                        djstest.assertAreEqualDeep(value, ["value1", "value4"], "value was not changed");
-                        success();
-                    }, makeError(success, fail));
-                });
-
-                job.run(function (succeeded) {
-                    store.close();
-                    testJobDone(succeeded);
-                });
-            }, "Store Update Array Test with mechanism " + mechanism, mechanism);
-        }
-    }
-
-    module("Unit");
-
-    djstest.addTest(function CreateStoreTest() {
-        var defaultExpected = canCreateDomStore() ? "dom" : "memory";
-        var tests = [
-            { mechanism: "dom", exception: !canCreateDomStore(), expected: "dom" },
-            { mechanism: "memory", exception: false, expected: "memory" },
-            { mechanism: "", exception: false, expected: defaultExpected },
-            { mechanism: null, exception: false, expected: defaultExpected },
-            { mechanism: "unknown", exception: true }
-       ];
-
-        var i, len;
-        for (i = 0, len = tests.length; i < len; i++) {
-            try {
-                var test = tests[i];
-                var store = odatajs.store.createStore("testStore" + i, tests[i].mechanism);
-
-                if (!test.exception) {
-                    djstest.assertAreEqual(store.mechanism, test.expected, "Created store of the expected mechanism");
-                } else {
-                    djstest.fail("Didn't get the expected exception");
-                }
-            }
-            catch (e) {
-                djstest.assert(test.exception, "Expected exception");
-            }
-        }
-        djstest.done();
-    });
-
-    djstest.addTest(function CreateBestStoreTest() {
-        var bestMechanism;
-
-        for (var name in mechanismImplementations) {
-            if (!bestMechanism && canCreateStore(name) && name !== "indexeddb") {
-                bestMechanism = name;
-            }
-        }
-
-        if (bestMechanism) {
-            var tests = [
-                "best",
-                undefined
-            ];
-
-            for (var i in tests) {
-                var store = odatajs.store.createStore("best store ever " + i, tests[i]);
-                djstest.assertAreEqual(store.mechanism, bestMechanism, "Mechanisms match");
-            }
-        } else {
-            djstest.pass("This browser doesn't support any of the implemented local storage mechanisms");
-        }
-        djstest.done();
-    });
-
-})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/test-list.js
----------------------------------------------------------------------
diff --git a/datajs/tests/test-list.js b/datajs/tests/test-list.js
deleted file mode 100644
index 3a69064..0000000
--- a/datajs/tests/test-list.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Test list for datajs tests
-
-function getAllTestFiles() {
-    return [
-        "odata-qunit-tests.htm"
-    ];
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/test-manager.html
----------------------------------------------------------------------
diff --git a/datajs/tests/test-manager.html b/datajs/tests/test-manager.html
deleted file mode 100644
index 290f161..0000000
--- a/datajs/tests/test-manager.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
--->
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>datajs test manager</title>
-    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js"></script>
-    <script type="text/javascript" src="test-list.js"></script>
-    <script type="text/javascript">
-        var serviceRoot = "./common/TestLogger.svc/";
-        $(function () {
-            $(getAllTestFiles()).each(function () {
-                $("#pages").append("<input type='checkbox' name='page' value='" + this + "' checked />" + this + "<br />");
-            });
-            refreshActiveRuns();
-        });
-
-        var createTestRun = function (form) {
-            $.getJSON(serviceRoot + "CreateTestRun", function (data) {
-                var testRunId = data.d;
-
-                // Build pages list
-                var pages = [];
-                $(form).find("input[name='page']:checked").each(function () {
-                    pages.push(this.value);
-                });
-
-                var firstPage = pages[0];
-                pages.shift();
-
-                $.get(serviceRoot + "MarkInProgress?testRunId=" + testRunId, function () {
-                    $.get(serviceRoot + "SetTestNamePrefix?testRunId=" + testRunId + "&prefix=" + $("#browser").val() + "-", function () {
-                        var renderLinks = function () {
-                            $("#runLink").attr("href", firstPage + "?testRunId=" + testRunId);
-                            $("#runLink").text(testRunId);
-                            $("#resultsLink").attr("href", serviceRoot + "GetTestRunResults?testRunId=" + testRunId);
-                            $("#resultsLink").text(testRunId);
-                            refreshActiveRuns();
-                        };
-
-                        if (pages.length > 0) {
-                            $.get(serviceRoot + "AddTestPages?testRunId=" + testRunId + "&pages=" + pages.join(","), renderLinks);
-                        }
-                        else {
-                            renderLinks();
-                        }
-                    });
-                });
-            });
-        };
-
-        var refreshActiveRuns = function () {
-            $("#activeRuns").empty();
-            $.getJSON(serviceRoot + "GetActiveTestRuns", function (data) {
-                if (data.d.length === 0) {
-                    $("#activeRuns").text("There are no active runs");
-                } else {
-                    $.each(data.d, function (_, id) {
-                        $("#activeRuns").append("<a href='" + serviceRoot + "GetTestRunResults?testRunId=" + id + "'>" + id + "</a><br />");
-                    })
-                };
-            });
-        };
-    </script>
-</head>
-<body>
-    <h1>datajs test manager</h1>
-    <table style="width:100%"><tr><td style="vertical-align:top">
-        <h4>1. Create Test Run</h4>
-        <form onsubmit="createTestRun(this); return false;">
-            <div>Pages</div>
-            <div id="pages"></div>
-            <br />
-            <div>Browser: <input type="text" id="browser" /></div>
-            <br />
-            <input type="submit" value="Create Test Run" />
-        </form>
-
-        <h4>2. Run Tests</h4>
-        Test Run ID: <a id="runLink"></a>
-
-        <h4>3. View Results</h4>
-        Test Run ID: <a id="resultsLink"></a>
-
-    </td><td style="vertical-align:top">
-        <h4>Active Runs <input type="button" value="Refresh" onclick="refreshActiveRuns()" /></h4>
-        <div id="activeRuns"></div>
-    </td></tr></table>
-</body>
-</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/.gitignore
----------------------------------------------------------------------
diff --git a/odatajs/.gitignore b/odatajs/.gitignore
new file mode 100644
index 0000000..d7c3df6
--- /dev/null
+++ b/odatajs/.gitignore
@@ -0,0 +1,9 @@
+node_modules/
+build
+dist
+localgrunt.config
+bin/
+obj/
+packages/
+JSLib.suo
+JSLib.csproj.user

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/Gruntfile.js
----------------------------------------------------------------------
diff --git a/odatajs/Gruntfile.js b/odatajs/Gruntfile.js
new file mode 100644
index 0000000..bc300e5
--- /dev/null
+++ b/odatajs/Gruntfile.js
@@ -0,0 +1,227 @@
+module.exports = function(grunt) {
+  'use strict';
+  var init = {
+    pkg: grunt.file.readJSON('package.json'),
+    banner: grunt.file.read('src/banner.txt'),
+    filename : '<%= pkg.name %>-<%= pkg.version %>-<%= pkg.postfix %>',
+
+    browserify: {
+      // start with index.js and follow all required source in order pack them together 
+      datajs: {
+        files: {
+          'build/<%= filename %>.js': ['src/index.js'],
+        },
+        options: {
+          transform: ['./grunt-config/browserify_transforms/stripheader/stripheader.js'],
+          browserifyOptions: {
+          } ,
+          bundleOptions: {
+          },
+        }
+      }
+    },
+    uglify: {
+      options: {
+        sourceMap : true,
+        sourceMapName :  'build/<%= filename %>.map',
+        sourceMapIncludeSources :true,
+      },
+      // uglify and compress the packed sources
+      build: {
+        src: 'build/<%= filename %>.js',
+        dest: 'build/<%= filename %>.min.js'
+      }
+    },
+    concat : {
+      options : {
+        banner : '<%= banner %>'
+      },
+      licence_min: {
+        src: 'build/<%= filename %>.min.js',
+        dest: 'build/<%= filename %>.min.js',
+      },
+      licence: {
+        src: 'build/<%= filename %>.js',
+        dest: 'build/<%= filename %>.js',
+      }
+    },
+    copy: {
+      forDemo: {
+        files: [
+          // includes files within path
+          {expand: true, cwd: 'build/', src: ['**'], dest: 'demo/scripts/', filter: 'isFile'},
+        ]
+      }
+    },
+    connect: {
+      demo: {
+        options: {
+          port: 4001 ,
+          hostname: "localhost",
+          base: "demo",
+          keepalive : true,
+          middleware: function (connect, options) {
+            return [
+              require("grunt-connect-proxy/lib/utils").proxyRequest ,
+              connect.static(options.base),   // static content
+              connect.directory(options.base) // browse directories
+            ];
+          },
+        },
+      },
+      // start a node webserver with proxy to host the qunit-test html files
+      'test-browser': {             
+        options: {
+          port: 4003 ,
+          hostname: "localhost",
+          base: "",
+          keepalive : true,
+          //changeOrigin: true,
+          middleware: function (connect, options) {
+            return [
+              require("grunt-connect-proxy/lib/utils").proxyRequest ,
+              connect.static(options.base),   // static content
+              connect.directory(options.base) // browse directories
+            ];
+          },
+        },
+        // proxy all request going to /tests/endpoints/ to the .net data services
+        proxies: [{
+          context: "/tests/endpoints/",  // When the url contains this...
+          host: "localhost",
+          changeOrigin: true,
+          https: false,
+          port: 46541,
+          rejectUnauthorized: false, 
+        }],
+      },
+    },
+    'node-qunit': {   
+      //used to run some background qunit test on node         
+      'default-tests': {
+        setup: {
+          log: {
+            summary: true,
+            assertions: true,
+            errors: true,
+            globalSummary: true,
+            coverage: false,
+            globalCoverage: false,
+            testing: true
+          },
+          coverage: false,
+          deps: null,
+          namespace: null
+        },
+        deps: '',
+        code: './tests-tmp/common/node-test-setup.js',
+        tests: ['./tests-tmp/odata-json-tests.js'],
+        done: function(err, res){
+            !err && publishResults("node", res, this.async());
+        }
+      },
+    },
+    jsdoc : {
+        src : {
+            src: ['src/**/*.js'], 
+            options: {
+                destination: 'build/doc',
+                verbose : false 
+            }
+        },
+        test : {
+            src: ['tests/**/*.js'], 
+            options: {
+                destination: 'build/doc-test',
+                verbose : false 
+            }
+        }
+    },
+    "npm-clean": {
+      tmp: {
+        src: [ "build/tmp"]
+      },
+      doc: {
+        src: ["build/doc"],
+          options: {
+                force: true
+            }
+      },
+      "doc-test": {
+        src: ["build/doc-test"],
+          options: {
+                force: true
+            }
+      },
+    },
+    compress: {
+      build: {
+        options: {archive: 'dist/<%= filename %>-lib.zip'},
+        files: [{expand: true, cwd: 'build/', src: ['*'], filter: 'isFile', dest: '<%= filename %>-lib/'}]
+      },
+      doc: {
+        options: {archive: 'dist/<%= filename %>-doc.zip'},
+        files: [{expand: true, cwd: 'build/doc/', src: ['**'], dest: '<%= filename %>-doc/'}]
+      },
+      src: {
+        options: {archive: 'dist/<%= filename %>-source.zip'},
+        files: [{expand: true, cwd: 'src/', src: ['**'], dest: '<%= filename %>-src/'}]
+      }
+    }
+  };
+  
+  /*** Join local configuration for proxies and local test servers ***/
+  if (grunt.file.exists('localgrunt.config')) {
+    console.log("merge localgrunt.config");
+    var localGrundConfig = grunt.file.read('localgrunt.config');
+    init.connect['test-browser'].proxies = init.connect['test-browser'].proxies.concat(JSON.parse(localGrundConfig).proxies);
+  }
+
+  /*** Init ***/
+  grunt.initConfig(init);
+
+  /*** Load tasks from npm modules ***/
+  grunt.loadNpmTasks('grunt-browserify');
+  grunt.loadNpmTasks('grunt-contrib-uglify');
+  grunt.loadNpmTasks("grunt-connect-proxy");
+  grunt.loadNpmTasks("grunt-contrib-connect");
+  grunt.loadNpmTasks("grunt-contrib-copy");
+  grunt.loadNpmTasks("grunt-contrib-concat");
+  grunt.loadNpmTasks('grunt-contrib-compress');
+  grunt.loadNpmTasks("grunt-jsdoc");
+
+
+  //    Start Qunit tests direcly in node js, internally qunit (npm qunit) 
+  //    is used, no phantomjs instance required
+  grunt.loadNpmTasks('grunt-node-qunit'); 
+  grunt.loadNpmTasks('grunt-contrib-clean');
+
+  //    Load the custom-* tasks from the grunt-config directory
+  grunt.loadTasks('grunt-config');
+
+  //    rename some tasks to avoid name clashes with the user tasks
+  grunt.renameTask('clean','npm-clean');
+  
+
+  /*** E N D U S E R   T A S K S ***/
+
+  grunt.registerTask('clean', ['npm-clean:doc','npm-clean:tmp']);
+
+  //    Runs the license header check to verify the any source file contains a license header
+  grunt.registerTask('license-check', ['custom-license-check']);
+
+  //    Create documentation in /build/doc
+  grunt.registerTask('doc', [/*'npm-clean:doc',*/'jsdoc:src']);
+  grunt.registerTask('doc-test', [/*'npm-clean:doc-test',*/'jsdoc:test']);
+
+  //    Build the odatajs library
+  grunt.registerTask('build', ['browserify:datajs', 'uglify:build', 'concat','copy:forDemo']);
+
+
+  grunt.registerTask('test-browser', ['configureProxies:test-browser', 'connect:test-browser']);
+  grunt.registerTask('test-node', ['node-qunit:default-tests']);
+  grunt.registerTask('release', ['build','doc','compress']);
+
+  
+};
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/JSLib.csproj
----------------------------------------------------------------------
diff --git a/odatajs/JSLib.csproj b/odatajs/JSLib.csproj
new file mode 100644
index 0000000..c2c3906
--- /dev/null
+++ b/odatajs/JSLib.csproj
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>
+    </ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}</ProjectGuid>
+    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>JSLib</RootNamespace>
+    <AssemblyName>JSLib</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    <UseIISExpress>false</UseIISExpress>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Content Include="src\index.js" />
+    <Content Include="src\banner.txt" />
+    <Content Include="src\lib\cache.js" />
+    <Content Include="src\lib\datajs.js" />
+    <Content Include="src\lib\odata.js" />
+    <Content Include="src\lib\store.js" />
+    <Content Include="src\lib\cache\source.js" />
+    <Content Include="src\lib\datajs\deferred.js" />
+    <Content Include="src\lib\datajs\utils.js" />
+    <Content Include="src\lib\datajs\xml.js" />
+    <Content Include="src\lib\odata\batch.js" />
+    <Content Include="src\lib\odata\handler.js" />
+    <Content Include="src\lib\odata\json.js" />
+    <Content Include="src\lib\odata\metadata.js" />
+    <Content Include="src\lib\odata\net.js" />
+    <Content Include="src\lib\odata\utils.js" />
+    <Content Include="src\lib\store\dom.js" />
+    <Content Include="src\lib\store\indexeddb.js" />
+    <Content Include="src\lib\store\memory.js" />
+    <Content Include="tests\cache-tests.js" />
+    <Content Include="tests\common\CacheOracle.js" />
+    <Content Include="tests\common\common.js" />
+    <Content Include="tests\common\Instrument.svc" />
+    <Content Include="tests\common\Instrument.js" />
+    <Content Include="tests\common\mockXMLHttpRequest.js" />
+    <Content Include="tests\common\mockHttpClient.js" />
+    <Content Include="tests\common\djstest.js" />
+    <Content Include="tests\common\gpo-ie8-tour-disable.reg" />
+    <Content Include="tests\common\ObservableHttpClient.js" />
+    <Content Include="tests\common\ODataReadOracle.js" />
+    <Content Include="tests\common\ODataReadOracle.svc" />
+    <Content Include="tests\common\rx.js" />
+    <Content Include="tests\common\TestLogger.svc" />
+    <Content Include="tests\common\TestSynchronizerClient.js" />
+    <Content Include="tests\e2etest\Test.html" />
+    <Content Include="tests\odata-json-light-tests.js" />
+    <Content Include="tests\datajs-startup-perf-test.html" />
+    <Content Include="tests\endpoints\BasicAuthDataService.svc" />
+    <Content Include="tests\endpoints\FoodStoreDataServiceV4.svc" />
+    <Content Include="tests\endpoints\CustomAnnotations.xml" />
+    <Content Include="tests\endpoints\CustomDataService.svc" />
+    <Content Include="tests\endpoints\EpmDataService.svc" />
+    <Content Include="tests\endpoints\ErrorDataService.svc" />
+    <Content Include="tests\endpoints\LargeCollectionService.svc" />
+    <Content Include="tests\endpoints\web.config" />
+    <Content Include="tests\datajs-cache-large-collection-functional-tests.html" />
+    <Content Include="tests\datajs-cache-large-collection-functional-tests.js" />
+    <Content Include="tests\datajs-cache-long-haul-tests.html" />
+    <Content Include="tests\odata-batch-functional-tests.html" />
+    <Content Include="tests\odata-batch-functional-tests.js" />
+    <Content Include="tests\odata-batch-tests.js" />
+    <Content Include="tests\odata-cache-filter-functional-tests.html" />
+    <Content Include="tests\odata-cache-filter-functional-tests.js" />
+    <Content Include="tests\odata-cache-fperf-tests.html" />
+    <Content Include="tests\odata-cache-fperf-tests.js" />
+    <Content Include="tests\odata-cache-functional-tests.html" />
+    <Content Include="tests\odata-cache-functional-tests.js" />
+    <Content Include="tests\odata-cache-rx-functional-tests.html" />
+    <Content Include="tests\odata-cache-rx-functional-tests.js" />
+    <Content Include="tests\odata-fuzz.html" />
+    <Content Include="tests\odata-metadata-tests.js" />
+    <Content Include="tests\odata-handler-tests.js" />
+    <Content Include="tests\odata-json-tests.js" />
+    <Content Include="tests\odata-links-functional-tests.html" />
+    <Content Include="tests\odata-links-functional-tests.js" />
+    <Content Include="tests\odata-metadata-awareness-functional-tests.html" />
+    <Content Include="tests\odata-metadata-awareness-functional-tests.js" />
+    <Content Include="tests\odata-net-tests.js" />
+    <Content Include="tests\odata-perf-tests.html" />
+    <Content Include="tests\odata-perf-tests.js" />
+    <Content Include="tests\odata-read-crossdomain-functional-tests.html" />
+    <Content Include="tests\odata-read-crossdomain-functional-tests.js" />
+    <Content Include="tests\odata-read-functional-tests.html" />
+    <Content Include="tests\odata-request-functional-tests.html" />
+    <Content Include="tests\odata-request-functional-tests.js" />
+    <Content Include="tests\odata-read-functional-tests.js" />
+    <Content Include="tests\odata-qunit-tests.htm" />
+    <Content Include="tests\odata-tests.js" />
+    <Content Include="tests\odata-xml-tests.js" />
+    <Content Include="tests\run-tests.wsf" />
+    <Content Include="tests\store-indexeddb-tests.js" />
+    <Content Include="tests\store-tests.js" />
+    <Content Include="tests\test-list.js" />
+    <Content Include="tests\test-manager.html" />
+    <!-- Configuration file for the web project. -->
+    <Content Include="Web.config">
+      <SubType>Designer</SubType>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="tests\code\CsdlReader.cs" />
+    <Compile Include="tests\code\JsDate.cs" />
+    <Compile Include="tests\code\JsonObject.cs" />
+    <Compile Include="tests\code\ReaderUtils.cs" />
+    <Compile Include="tests\code\ReflectionDataContext.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>packages\Microsoft.OData.Client.6.5.0\lib\net40\Microsoft.OData.Client.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.OData.Core">
+      <HintPath>packages\Microsoft.OData.Core.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.OData.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.OData.Edm">
+      <HintPath>packages\Microsoft.OData.Edm.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.OData.Edm.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>packages\Microsoft.OData.Service.6.5.0\lib\net40\Microsoft.OData.Service.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Spatial">
+      <HintPath>packages\Microsoft.Spatial.6.5.0\lib\portable-net40+sl5+wp8+win8+wpa\Microsoft.Spatial.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Net" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ServiceModel" />
+    <Reference Include="System.ServiceModel.Activation" />
+    <Reference Include="System.ServiceModel.Web" />
+    <Reference Include="System.Web.Extensions" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Linq" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
+  <ProjectExtensions>
+    <VisualStudio>
+      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+        <WebProjectProperties>
+          <UseIIS>False</UseIIS>
+          <AutoAssignPort>True</AutoAssignPort>
+          <DevelopmentServerPort>4002</DevelopmentServerPort>
+          <DevelopmentServerVPath>/</DevelopmentServerVPath>
+          <IISUrl>
+          </IISUrl>
+          <NTLMAuthentication>False</NTLMAuthentication>
+          <UseCustomServer>False</UseCustomServer>
+          <CustomServerUrl>
+          </CustomServerUrl>
+          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+        </WebProjectProperties>
+      </FlavorProperties>
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/JSLib.sln
----------------------------------------------------------------------
diff --git a/odatajs/JSLib.sln b/odatajs/JSLib.sln
new file mode 100644
index 0000000..d265e52
--- /dev/null
+++ b/odatajs/JSLib.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JSLib", "JSLib.csproj", "{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{73ADF1A7-613B-4679-885B-2AE4AFAA9A6A}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/Web.config
----------------------------------------------------------------------
diff --git a/odatajs/Web.config b/odatajs/Web.config
new file mode 100644
index 0000000..e45c79e
--- /dev/null
+++ b/odatajs/Web.config
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <system.web>
+    <compilation debug="true" targetFramework="4.0">
+      <assemblies>
+        <add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
+        <add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
+        <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+        <add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
+        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
+        <add assembly="System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
+        <add assembly="System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+      </assemblies>
+    </compilation>
+  </system.web>
+  <system.webServer>
+    <directoryBrowse enabled="true" />
+  </system.webServer>
+  <system.codedom>
+    <compilers>
+      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+        <providerOption name="CompilerVersion" value="v4.0" />
+      </compiler>
+    </compilers>
+  </system.codedom>
+  <system.net>
+    <defaultProxy>
+      <proxy autoDetect="True" />
+    </defaultProxy>
+  </system.net>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/mypage.html
----------------------------------------------------------------------
diff --git a/odatajs/demo/mypage.html b/odatajs/demo/mypage.html
new file mode 100644
index 0000000..16517a4
--- /dev/null
+++ b/odatajs/demo/mypage.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>data js demo</title>
+    <script type="text/javascript" src="scripts/datajs-2.0.0.js"></script>
+    <script type="text/javascript" src="scripts/jquery-2.0.3.js"></script>
+    <script type="text/javascript" src="scripts/datajs_demo.js"></script>
+    <style type="text/css">.title { font-size: 30px;font-style: italic;}</style>
+</head>
+<body onload="run()"> 
+    <div>
+        <span class="title">Simple Read</span>
+        <pre id="simpleRead"></pre>
+    </div>
+    <div>
+        <span class="title">Simple Read With Metadata</span>
+        <pre id="simpleReadWithMetadata"></pre>
+    </div>
+    <div>
+        <span class="title">Simple Read with JSONP</span>
+        <pre id="simpleReadWithJSONP"></pre>
+    </div>
+    <div>
+        <span class="title">Metadata</span>
+        <pre id="metadata"></pre>
+    </div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/.gitignore
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/.gitignore b/odatajs/demo/scripts/.gitignore
new file mode 100644
index 0000000..f7f55d4
--- /dev/null
+++ b/odatajs/demo/scripts/.gitignore
@@ -0,0 +1,2 @@
+datajs-2*
+tmp/


[14/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc b/odatajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
new file mode 100644
index 0000000..ac1cfe7
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/FoodStoreDataServiceV4.svc
@@ -0,0 +1,590 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.V4.FoodStoreDataService" %>
+
+namespace DataJS.Tests.V4
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using Microsoft.OData.Service.Providers;
+    using System.Linq;
+    using System.ServiceModel.Web;
+    using System.Web;
+    using System.IO;
+    using Microsoft.Spatial;
+    
+    /// <summary>
+    /// Provides a service similar to FoodStoreDataService, but uses V4 and WCF Data Services 6.0.0-beta1
+    /// features.
+    /// </summary>
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class FoodStoreDataService : DataService<FoodContainer>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.UseVerboseErrors = true;
+            // Set Foods page size to 5 for cache testing
+            config.SetEntitySetPageSize("Foods", 5);
+            // Make the Categories set paged to have a paged feed
+            config.SetEntitySetPageSize("Categories", 1);
+        }
+        
+        [WebInvoke]
+        public string ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+            return "Data Reset";
+        }
+
+        [WebGet]
+        public IQueryable<string> FoodsAvailable()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Name);
+        }
+
+        [WebGet]
+        public IQueryable<Package> PackagingTypes()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
+        }
+
+        [WebGet]
+        public string UserNameAndPassword()
+        {
+            var request = WebOperationContext.Current.IncomingRequest;
+            string authorization = request.Headers["Authorization"];
+            if (String.IsNullOrEmpty(authorization))
+            {
+                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
+                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
+            }
+
+            return authorization;
+        }
+    }
+
+    public class FoodContainer : ReflectionDataContext, IUpdatable, IDataServiceStreamProvider2
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Category> Categories
+        {
+            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
+        }
+        
+        public IQueryable<Food> Foods
+        {
+            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            var builder = SpatialImplementation.CurrentImplementation.CreateBuilder();
+            builder.GeometryPipeline.SetCoordinateSystem(CoordinateSystem.DefaultGeography);
+            builder.GeometryPipeline.BeginGeometry(SpatialType.Collection);
+            builder.GeometryPipeline.BeginFigure(new GeometryPosition(5.0, 5.0));
+            builder.GeometryPipeline.EndFigure();
+            builder.GeometryPipeline.EndGeometry();
+            
+            int i = 0;
+            Category[] categories = new Category[]
+            {
+                new Category { CategoryID = i++, Name = "Baking Supplies" },
+                new Category { CategoryID = i++, Name = "Condiments" },
+                new Category { CategoryID = i++, Name = "Empty Category" }
+            };
+            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
+            
+            i = 0;
+            Food[] foods = new Food[]
+            {            
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "flour",
+                    UnitPrice = .19999,
+                    ServingSize = 1,
+                    MeasurementUnit = "Cup",
+                    ProteinGrams = 3,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 20,
+                    CaloriesPerServing = 140,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
+                    ItemGUID = new Guid("27272727272727272727272727272727"),
+                    Weight = 10f,
+                    AvailableUnits = 1,
+                    
+                    Packaging = new Package(){
+                        Type = null, 
+                        Color = String.Empty, 
+                        NumberPerPackage = int.MaxValue, 
+                        RequiresRefridgeration = false, 
+                        PackageDimensions = new Dimensions()
+                        {
+                            Length = Decimal.MaxValue, 
+                            Height = Int16.MaxValue, 
+                            Width = Int64.MaxValue, 
+                            Volume = double.MaxValue,   
+                        },
+                        ShipDate = new DateTime(2000, 12, 29)
+                    },
+                    
+                    CookedSize = new CookedDimensions()
+                    {
+                        Height = 1,
+                        Length = 2,
+                        Width = 3,
+                        Volume = 1 * 2 * 3
+                    },
+                    
+                    Category = categories[0],
+                    
+                    AlternativeNames = new List<string>() {"ground cereal", "ground grain"},
+                    
+                    Providers = new List<Provider> {
+                        new Provider() { 
+                             Name= "Flour Provider", 
+                             Aliases = new List<string>() {"fp1", "flour provider1"},
+                             Details = new ProviderDetails() {
+                                 Telephone= "555-555-555",
+                                 PreferredCode = 1001
+                             }
+                        },
+                        new Provider() { 
+                             Name= "Ground Grains", 
+                             Aliases = new List<string>()
+                        }
+                    },
+                    
+                    SpatialData = (GeometryCollection)builder.ConstructedGeometry 
+                },
+                
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "sugar",
+                    UnitPrice = .2,
+                    ServingSize = 1,
+                    MeasurementUnit = "tsp",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 4,
+                    CaloriesPerServing = 16,
+                    IsAvailable = false,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
+                    Weight = 0.1f,
+                    AvailableUnits = 0,
+
+                    Packaging = new Package(){
+                        Type = " ",
+                        Color = "BLUE",
+                        NumberPerPackage = int.MinValue,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = Decimal.MinValue,
+                            Height = Int16.MinValue,
+                            Width = Int64.MinValue,
+                            Volume = double.MinValue,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = categories[1],
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "1 Chicken Egg",
+                    UnitPrice = 0.55,
+                    MeasurementUnit = null,
+                    ServingSize = 1,
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 1,
+                    CaloriesPerServing = 70,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("00000000000000000000000000000000"),
+                    Weight = 0,
+                    AvailableUnits = -128,
+                    
+                    Packaging = new Package(){
+                        Type = "18     - Carton",
+                        Color = " brown ",
+                        NumberPerPackage = 0,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = null,
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = null,
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "Brown Sugar",
+                    UnitPrice = 1.6,
+                    ServingSize = 1,
+                    MeasurementUnit = "TSP.",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 5, 
+                    CaloriesPerServing = 16,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 4.5f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Cobb Salad",
+                    UnitPrice = 1.99,
+                    ServingSize = -1,
+                    MeasurementUnit = "cups",
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 3, 
+                    CaloriesPerServing = 5,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 5.674f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                    Instructions = "1.) Open 2.) Eat",
+                    NumberOfIngredients = 4,
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Lasagna",
+                    UnitPrice = 0,
+                    ServingSize = 8,
+                    MeasurementUnit = " servings",
+                    ProteinGrams = 100,
+                    FatGrams = 4,
+                    CarbohydrateGrams = 27, 
+                    CaloriesPerServing = 389,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(1904, 2, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 0,
+                    AvailableUnits = 4,
+                    Packaging = new Package(){
+                        Type = "box",
+                        Color = " 1 ",
+                        NumberPerPackage = 1,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = 3,
+                            Height = 1,
+                            Width = 5,
+                            Volume = 1.5,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    Category = categories[0],
+                    Instructions = "Bake in oven",
+                    NumberOfIngredients = 15,
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Chocolate"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Pizza"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Avocados"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Quinoa"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Oatmeal"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Peanut Butter"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Banana"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Yam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Clam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Spam"
+                }
+            };
+            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
+
+            categories[0].Foods.Add(foods[0]);
+            categories[1].Foods.Add(foods[2]);
+            categories[1].Foods.Add(foods[3]);
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+
+        public Stream GetReadStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            return new MemoryStream();
+        }
+
+        public Uri GetReadStreamUri(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            if (streamProperty.Name == "Icon")
+            {
+                return null;
+            }
+            return new Uri(operationContext.AbsoluteServiceUri, streamProperty.Name);
+        }
+
+        public string GetStreamContentType(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            if (streamProperty.Name == "Icon")
+            {
+                return "image/gif";
+            }
+            return "image/png";
+        }
+
+        public string GetStreamETag(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
+        {
+            return "W/\"123456789\"";
+        }
+
+        public Stream GetWriteStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            return new MemoryStream();
+        }
+
+        public void DeleteStream(object entity, DataServiceOperationContext operationContext)
+        {
+            // do nothing.
+        }
+
+        public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
+        {
+            throw new NotImplementedException();
+        }
+
+        public int StreamBufferSize
+        {
+            get { return 1024; }
+        }
+    }
+
+    /// <summary>
+    /// The Category class is a simple class with V1-compatible feed customizations.
+    /// </summary>
+    public class Category
+    {
+        public Category()
+        {
+            this.Foods = new List<Food>();
+        }
+        
+        public int CategoryID { get; set; }
+        public string Name { get; set; }
+        public List<Food> Foods { get; set; }
+    }
+    
+    /// <summary>
+    /// The Food class has a mixture of V1-compatible and incompatible feed
+    /// customizations (thus it's V2), and custom mappings.
+    /// </summary>
+    public class Food
+    {
+        private List<string> alternativeNames = new List<string>();
+        private List<Provider> providers = new List<Provider>();
+        
+        // Primitive types
+        public int FoodID { get; set; }
+        public string Name { get; set; }
+        public double UnitPrice { get; set; }
+        public Decimal ServingSize { get; set; }
+        public string MeasurementUnit { get; set; }
+        public Byte ProteinGrams { get; set; }
+        public Int16 FatGrams { get; set; }
+        public Int32 CarbohydrateGrams { get; set; }
+        public Int64 CaloriesPerServing { get; set; }
+        public Boolean IsAvailable { get; set; }
+        public DateTime ExpirationDate { get; set; }
+        public Guid ItemGUID { get; set; }
+        public Single Weight { get; set; }
+        public sbyte AvailableUnits { get; set; }
+
+        // Complex types
+        public Package Packaging { get; set; }
+        public CookedDimensions CookedSize { get; set; }
+
+        // Navigation properties
+        public Category Category { get; set; }
+
+        // Collection properties
+        public List<string> AlternativeNames
+        {
+            get { return alternativeNames; }
+            set { alternativeNames = value; }
+        }
+
+        public List<Provider> Providers
+        {
+            get { return providers; }
+            set { providers = value; }
+        }
+
+        public GeometryCollection SpatialData
+        {
+            get;
+            set;
+        }
+        
+    }
+
+    public class Provider
+    {
+        public string Name { get; set; }
+        public List<string> Aliases { get; set; }
+        public ProviderDetails Details { get; set; }
+    }
+
+    public class ProviderDetails
+    {
+        public string Telephone { get; set; }
+        public int PreferredCode { get; set; }
+    }
+    
+    public class Package
+    {
+        public string Type { get; set; }
+        public string Color { get; set; }
+        public int NumberPerPackage { get; set; }
+        public Boolean RequiresRefridgeration { get; set; }
+        public DateTime ShipDate { get; set; }
+        public Dimensions PackageDimensions { get; set; }
+    }
+
+    public class Dimensions
+    {
+        public Decimal Length { get; set; }
+        public Int16 Height { get; set; }
+        public Int64 Width { get; set; }
+        public double Volume { get; set; }
+    }
+
+    public class CookedDimensions
+    {
+        public Decimal Length { get; set; }
+        public Int16 Height { get; set; }
+        public Int64 Width { get; set; }
+        public double Volume { get; set; }
+    }
+
+    public class PreparedFood : Food
+    {
+        public string Instructions { get; set; }
+        public float NumberOfIngredients { get; set; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/LargeCollectionService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/LargeCollectionService.svc b/odatajs/tests-tmp/endpoints/LargeCollectionService.svc
new file mode 100644
index 0000000..bfbd3ef
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/LargeCollectionService.svc
@@ -0,0 +1,113 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.LargeCollectionService" %>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Web;
+    using System.Web;
+
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class LargeCollectionService : DataService<LargeCollection>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.UseVerboseErrors = true;
+        }
+
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+    }
+
+    public class LargeCollection : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Customer> Customers
+        {
+            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+        }
+
+        public IQueryable<Supplier> Suppliers
+        {
+            get { return this.GetResourceSetEntities<Supplier>("Suppliers").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+            foreach (int i in Enumerable.Range(1, 2 * 1024 * 1024))
+            {
+                customers.Add(new Customer()
+                {
+                    ID = i,
+                    Name = "Customer " + i
+                });
+            }
+
+            IList<Supplier> suppliers = this.GetResourceSetEntities<Supplier>("Suppliers");
+            foreach (int i in Enumerable.Range(1, 5000))
+            {
+                suppliers.Add(new Supplier()
+                {
+                    ID = i,
+                    Name = "Supplier " + i
+                });
+            }
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Customer
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+
+    public class Supplier
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/web.config
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/web.config b/odatajs/tests-tmp/endpoints/web.config
new file mode 100644
index 0000000..116a567
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/web.config
@@ -0,0 +1,46 @@
+<?xml version='1.0'?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+-->
+<configuration>
+  <system.web>
+    <compilation debug='true'>
+      <assemblies>
+        <add assembly='System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
+        <add assembly='System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
+        <add assembly='System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
+        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
+      </assemblies>
+    </compilation>
+  </system.web>
+  <system.codedom>
+    <compilers>
+      <compiler language='c#;cs;csharp' extension='.cs' type='Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>
+        <providerOption name='CompilerVersion' value='v4.0' />
+      </compiler>
+    </compilers>
+  </system.codedom>
+</configuration>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/odata-json-tests-todo-analyse.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/odata-json-tests-todo-analyse.js b/odatajs/tests-tmp/odata-json-tests-todo-analyse.js
new file mode 100644
index 0000000..702e015
--- /dev/null
+++ b/odatajs/tests-tmp/odata-json-tests-todo-analyse.js
@@ -0,0 +1,828 @@
+/*
+ * 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) {
+    djstest.addTest(function jsonParserTest() {
+        var tests = [
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: {} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata",
+                    value: [
+                      {
+                          name: "Products",
+                          kind: "EntitySet",
+                          url: "Products"
+                      },
+                      {
+                          name: "ProductDetails",
+                          kind: "EntitySet",
+                          url: "ProductDetails"
+                      }
+                  ]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    value: [
+                      {
+                          name: "Products",
+                          kind: "EntitySet",
+                          url: "http://foo/OData.svc/Products"
+                      },
+                      {
+                          name: "ProductDetails",
+                          kind: "EntitySet",
+                          url: "http://foo/OData.svc/ProductDetails"
+                      }
+                  ]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { "@odata.context": "http://foo/OData.svc/$metadata#Products(0)/Name", value: "Bread"} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
+                    value: [
+                      {
+                          "@odata.type": "#ODataDemo.Product",
+                          "@odata.id": "http://foo/OData.svc/Products(0)",
+                          "@odata.editLink": "Products(0)",
+                          "Categories@odata.navigationLink": "Products(0)/Categories",
+                          "Categories@odata.associationLink": "Products(0)/Categories/$ref",
+                          "Supplier@odata.navigationLink": "Products(0)/Supplier",
+                          "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
+                          "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
+                          "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          "ReleaseDate@odata.type": "#DateTimeOffset",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          "Rating@odata.type": "#Int16",
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                }
+            },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    "@odata.context": "http://foo/OData.svc/$metadata#Products",
+                    value: [
+                      {
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                }
+            },
+             { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                 expected: {
+                     value: [
+                      {
+                          ID: 0,
+                          Name: "Bread",
+                          Description: "Whole grain bread",
+                          ReleaseDate: "1992-01-01T00:00:00Z",
+                          DiscontinuedDate: null,
+                          Rating: 4,
+                          Price: 2.5
+                      }]
+                 }
+             },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
+                      "@odata.type": "#ODataDemo.Product",
+                      "@odata.id": "http://foo/OData.svc/Products(0)",
+                      "@odata.editLink": "Products(0)",
+                      "Categories@odata.navigationLink": "Products(0)/Categories",
+                      "Categories@odata.associationLink": "Products(0)/Categories/$ref",
+                      "Supplier@odata.navigationLink": "Products(0)/Supplier",
+                      "Supplier@odata.associationLink": "Products(0)/Supplier/$ref",
+                      "ProductDetail@odata.navigationLink": "Products(0)/ProductDetail",
+                      "ProductDetail@odata.associationLink": "Products(0)/ProductDetail/$ref",
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      "ReleaseDate@odata.type": "#DateTimeOffset",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      "Rating@odata.type": "#Int16",
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/OData.svc/$metadata#Products/$entry",
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      ID: 0,
+                      Name: "Bread",
+                      Description: "Whole grain bread",
+                      ReleaseDate: "1992-01-01T00:00:00Z",
+                      DiscontinuedDate: null,
+                      Rating: 4,
+                      Price: 2.5
+                  }
+              },
+              { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                  expected: {
+                      "@odata.context": "http://foo/$metadata#Customer(-10)/PrimaryContactInfo/AlternativeNames",
+                      "@odata.type": "#Collection(String)",
+                      value: [
+                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
+                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
+                      "btsnhqrjqryqzgxducl",
+                      "qbtlssjhunufmzdv",
+                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
+                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
+                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
+                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
+                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
+                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
+                     ]
+                  }
+              }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var data = JSON.stringify(tests[i].expected);
+            var actual = window.odatajs.oData.json.jsonParser(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
+            djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected data");
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function jsonSerializerTest() {
+        var tests = [
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: ""} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" }, expected: { value: []} },
+            { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+                expected: {
+                    ID: 0,
+                    Name: "Bread",
+                    Description: "Whole grain bread",
+                    ReleaseDate: "1992-01-01T00:00:00Z",
+                    DiscontinuedDate: null,
+                    Rating: 4,
+                    Price: 2.5
+                }
+            },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   value: [
+                      "グぁマせぺネソぁぼソひバたぴソ歹九ネボボяポソ畚クяせべ歹珱Я欲タハバミ裹ぼボをヲ歹んひ九ひ匚ぁa",
+                      "qckrnuruxcbhjfimnsykgfquffobcadpsaocixoeljhspxrhebkudppgndgcrlyvynqhbujrnvyxyymhnroemigogsqulvgallta",
+                      "btsnhqrjqryqzgxducl",
+                      "qbtlssjhunufmzdv",
+                      "ボんЯぜチべゼボボほa匚ミぼ九ぁひチ珱黑ミんぁタび暦クソソボゾんんあゼぞひタボタぜん弌ひべ匚",
+                      "vicqasfdkxsuyuzspjqunxpyfuhlxfhgfqnlcpdfivqnxqoothnfsbuykfguftgulgldnkkzufssbae",
+                      "九ソミせボぜゾボёaをぜЯまゾタぜタひ縷ダんaバたゼソ",
+                      "ぽマタぁぁ黑ソゼミゼ匚zソダマぁァゾぽミaタゾ弌ミゼタそzぺポせ裹バポハハヲぺチあマ匚ミ",
+                      "hssiißuamtctgqhglmusexyikhcsqctusonubxorssyizhyqpbtbdßjnelxqttkhdalabibuqhiubtßsptrmzelud",
+                      "gbjssllxzzxkmßppyyrhgmoeßizlcmsuqqnvjßudszevtfunflqzqcuubukypßqjcix"
+                     ]
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   ID: 0,
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                   "@odata.editLink": "Foods(0)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                   ID: 0,
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   value : [{
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   }]
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.editLink": "Foods(0)",
+                   value : [{
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       ComplexInLayerOne:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                           ID: 1,
+                           ComplexInLayerTwo:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                               ID: 2,
+                               ComplexInLayerThreeList: [
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               },
+                               {
+                                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                                   "@odata.id": "Foods(4)",
+                                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                                   "@odata.editLink": "Foods(0)",
+                                   "@odata.type": "#DataJS.Tests.V4.Food",
+                                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                                   ID: 3,
+                                   Name: "BreadInLayer3",
+                                   Description: "Whole grain bread inLayer3",
+                                   ReleaseDate: "1992-01-01T00:00:00Z",
+                                   DiscontinuedDate: null,
+                                   Rating: 7,
+                                   Price: 5.5
+                               }],
+                               Name: "BreadInLayer2",
+                               Description: "Whole grain bread inLayer2",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 6,
+                               Price: 4.5
+                           },
+                           Name: ["BreadInLayer1", "BreadInLayer12", "BreadInLayer13"],
+                           Description: "Whole grain bread inLayer1",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 5,
+                           Price: 3.5
+                       },
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   }]
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   "@odata.id": "Foods(4)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   ID: 0,
+                   ComplexInLayerOne:
+                   {
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 1,
+                       ComplexInLayerTwo:
+                       {
+                           "@odata.id": "Foods(4)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           ID: 2,
+                           ComplexInLayerThree:
+                           {
+                               "@odata.id": "Foods(4)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               ID: 3,
+                               Name: "BreadInLayer3",
+                               Description: "Whole grain bread inLayer3",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 7,
+                               Price: 5.5
+                           },
+                           Name: "BreadInLayer2",
+                           Description: "Whole grain bread inLayer2",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 6,
+                           Price: 4.5
+                       },
+                       Name: "BreadInLayer1",
+                       Description: "Whole grain bread inLayer1",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 5,
+                       Price: 3.5
+                   },
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               },
+               data: {
+                   "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                   "@odata.id": "Foods(4)",
+                   "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                   "@odata.editLink": "Foods(0)",
+                   "@odata.type": "#DataJS.Tests.V4.Food",
+                   "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                   "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                   "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                   "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                   ID: 0,
+                   ComplexInLayerOne:
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer1",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer1",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer1",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer1",
+                       ID: 1,
+                       ComplexInLayerTwo:
+                       {
+                           "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                           "@odata.id": "Foods(4)",
+                           "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                           "@odata.editLink": "Foods(0)",
+                           "@odata.type": "#DataJS.Tests.V4.Food",
+                           "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer2",
+                           "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer2",
+                           "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer2",
+                           "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer2",
+                           ID: 2,
+                           ComplexInLayerThree:
+                           {
+                               "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                               "@odata.id": "Foods(4)",
+                               "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                               "@odata.editLink": "Foods(0)",
+                               "@odata.type": "#DataJS.Tests.V4.Food",
+                               "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink/layer3",
+                               "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink/layer3",
+                               "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType/layer3",
+                               "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag/layer3",
+                               ID: 3,
+                               Name: "BreadInLayer3",
+                               Description: "Whole grain bread inLayer3",
+                               ReleaseDate: "1992-01-01T00:00:00Z",
+                               DiscontinuedDate: null,
+                               Rating: 7,
+                               Price: 5.5
+                           },
+                           Name: "BreadInLayer2",
+                           Description: "Whole grain bread inLayer2",
+                           ReleaseDate: "1992-01-01T00:00:00Z",
+                           DiscontinuedDate: null,
+                           Rating: 6,
+                           Price: 4.5
+                       },
+                       Name: "BreadInLayer1",
+                       Description: "Whole grain bread inLayer1",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 5,
+                       Price: 3.5
+                   },
+                   Name: "Bread",
+                   Description: "Whole grain bread",
+                   ReleaseDate: "1992-01-01T00:00:00Z",
+                   DiscontinuedDate: null,
+                   Rating: 4,
+                   Price: 2.5
+               }
+           },
+           { context: { response: { requestUri: "http://base.org" }, dataServiceVersion: "4.0" },
+               expected: {
+                   value: [{
+                       "@odata.id": "Foods(4)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 0,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.id": "Foods(2)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       ID: 1,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1999-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 6,
+                       Price: 3.5
+                   }]
+               },
+               data: {
+                   value: [{
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(4)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(0)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag",
+                       ID: 0,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1992-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 4,
+                       Price: 2.5
+                   },
+                   {
+                       "@odata.context": "http://base.org/$metadata#Foods/$entity",
+                       "@odata.id": "Foods(2)",
+                       "@odata.etag": "W/MjAxMy0wNS0yN1QxMTo1OFo=",
+                       "@odata.editLink": "Foods(2)",
+                       "@odata.type": "#DataJS.Tests.V4.Food",
+                       "@odata.mediaEditLink": "http://base.org/$metadata#Foods/mediaEditLink2",
+                       "@odata.mediaReadLink": "http://base.org/$metadata#Foods/mediaReadLink2",
+                       "@odata.mediaContentType": "http://base.org/$metadata#Foods/mediaContentType2",
+                       "@odata.mediaEtag": "http://base.org/$metadata#Foods/mediaEtag2",
+                       ID: 1,
+                       Name: "Bread",
+                       Description: "Whole grain bread",
+                       ReleaseDate: "1999-01-01T00:00:00Z",
+                       DiscontinuedDate: null,
+                       Rating: 6,
+                       Price: 3.5
+                   }]
+               }
+           }
+          ];
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var data = tests[i].data ? tests[i].data : tests[i].expected;
+            var actual = window.odatajs.oData.json.jsonSerializer(window.odatajs.oData.json.jsonHandler, data, tests[i].context);
+            var expected = JSON.stringify(tests[i].expected);
+            djstest.assertAreEqualDeep(actual, expected, "test " + i + "didn't return the expected data");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function normalizeHeadersReadTest() {
+        // Verifies that headers are normalized for reading.
+        // See issue at http://datajs.codeplex.com/workitem/148
+        MockHttpClient.clear();
+
+        MockHttpClient.clear().addResponse("/foo", {
+            statusCode: 200,
+            body: { "@odata.context": "http://foo", value: [] },
+            headers: { "unknown": "u", "Content-Encoding": "compress, gzip", "Content-Length": "8042",
+                "Content-Type": "application/json", "OData-Version": "4.0", "Etag": "Vetag", "Location": "foo", "OData-EntityId": "entityId",
+                "Preference-Applied": "prefered", "Retry-After": "retry"
+            }
+        });
+
+        odatajs.oData.read("/foo", function (data, response) {
+            // djstest.assertAreEqual(data.results.length, 2, "data.results.length has two entries");
+            djstest.assertAreEqual(response.headers.unknown, "u", "u unmodified");
+            djstest.assertAreEqual(response.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
+            djstest.assertAreEqual(response.headers["Content-Length"], "8042", "Content-Length available");
+            djstest.assertAreEqual(response.headers["Content-Type"], "application/json", "Content-Type available");
+            djstest.assertAreEqual(response.headers["ETag"], "Vetag", "Content-Type available");
+            djstest.assertAreEqual(response.headers["Location"], "foo", "Content-Type available");
+            djstest.assertAreEqual(response.headers["OData-EntityId"], "entityId", "OData-EntityId available");
+            djstest.assertAreEqual(response.headers["Preference-Applied"], "prefered", "Preference-Applied available");
+            djstest.assertAreEqual(response.headers["Retry-After"], "retry", "Retry available");
+            djstest.assertAreEqual(response.headers["OData-Version"], "4.0", "OData-Version available");
+            djstest.done();
+        }, undefined, undefined, MockHttpClient);
+    });
+
+    djstest.addTest(function normalizeHeadersWriteTest() {
+
+        // Verifies that headers are normalized for writing.
+        // See issue at http://datajs.codeplex.com/workitem/148
+
+        MockHttpClient.clear().addRequestVerifier("/foo", function (request) {
+            djstest.assertAreEqual(request.headers.Accept, "application/json", "Accept available");
+            djstest.assertAreEqual(request.headers["Content-Type"], "application/json", "json found");
+            djstest.assertAreEqual(request.headers["Content-Encoding"], "compress, gzip", "Content-Encoding available");
+            djstest.assertAreEqual(request.headers["Content-Length"], "8042", "Content-Length available");
+            djstest.assertAreEqual(request.headers["OData-Version"], "4.0", "OData-Version available");
+            djstest.assertAreEqual(request.headers["Accept-Charset"], "Accept-Charset", "Accept-Charset available");
+            djstest.assertAreEqual(request.headers["If-Match"], "true", "If-Match available");
+            djstest.assertAreEqual(request.headers["If-None-Match"], "false", "If-None-Match available");
+            djstest.assertAreEqual(request.headers["OData-Isolation"], "isolation", "OData-Isolation available");
+            djstest.assertAreEqual(request.headers["OData-MaxVersion"], "4.0", "OData-MaxVersion available");
+            djstest.assertAreEqual(request.headers["Prefer"], "prefer", "prefer available");
+            djstest.done();
+        });
+
+        var request = {
+            method: "POST",
+            requestUri: "/foo",
+            data: { value: 123 },
+            headers: { "Accept": "application/json", "Content-Encoding": "compress, gzip", "Content-Length": "8042", "content-type": "application/json", "OData-Version": "4.0",
+                "accept-charset": "Accept-Charset", "if-match": "true", "if-none-match": "false", "odata-isolation": "isolation",
+                "odata-maxversion": "4.0", "prefer": "prefer"
+            }
+        };
+        odatajs.oData.request(request, function (data) { }, undefined, undefined, MockHttpClient);
+
+    });
+
+
+})(window);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/odata-qunit-tests-launcher.htm
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/odata-qunit-tests-launcher.htm b/odatajs/tests-tmp/odata-qunit-tests-launcher.htm
new file mode 100644
index 0000000..4f8a390
--- /dev/null
+++ b/odatajs/tests-tmp/odata-qunit-tests-launcher.htm
@@ -0,0 +1,61 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+  <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="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.5/rx.all.js"></script>
+
+    
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+
+    <script type="text/javascript" src="./common/logging.js"></script>
+
+    <script type="text/javascript" src="./common/odataCacheVerifier.js"></script>
+    <script type="text/javascript" src="./common/odataVerifyReader.js"></script>
+    
+
+    <script type="text/javascript" src="./common/mockHttpClient.js"></script>
+
+    
+
+    <script type="text/javascript" src="./common/djstest.js"></script>
+    <script type="text/javascript" src="./common/djstest-browser.js"></script>
+
+
+    <script type="text/javascript" src="./bn-odata-json-tests.js"></script>
+    <script type="text/javascript" src="./a-odata-json-tests.js"></script>
+    <script type="text/javascript" src="./b-cache-tests.js"></script>
+  <body>
+    <div id="qunit"></div>
+  </body>
+  
+</html>
\ No newline at end of file


[24/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/datajs-1.1.1.min.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/datajs-1.1.1.min.js b/odatajs/demo/scripts/datajs-1.1.1.min.js
new file mode 100644
index 0000000..0d862a1
--- /dev/null
+++ b/odatajs/demo/scripts/datajs-1.1.1.min.js
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft.  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.
+
+(function(n,t){var pt=n.datajs||{},r=n.OData||{},co,lo,ei,ly,ip;typeof define=="function"&&define.amd?(define("datajs",pt),define("OData",r)):(n.datajs=pt,n.OData=r),pt.version={major:1,minor:1,build:1};var bo=function(t){return n.ActiveXObject?new n.ActiveXObject(t):null},ot=function(n){return n!==null&&n!==t},fr=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return!0;return!1},it=function(n,i){return n!==t?n:i},o=function(t){if(arguments.length===1){n.setTimeout(t,0);return}var i=Array.prototype.slice.call(arguments,1);n.setTimeout(function(){t.apply(this,i)},0)},g=function(n,t){for(var i in t)n[i]=t[i];return n},er=function(n,t){if(n)for(var i=0,r=n.length;i<r;i++)if(t(n[i]))return n[i];return null},e=function(n){return Object.prototype.toString.call(n)==="[object Array]"},cf=function(n){return Object.prototype.toString.call(n)==="[object Date]"},lf=function(n){return typeof n=="object"},s=function(n){return parseInt(n,10)},iu=function(n,t,i){n.hasOwnProperty(t)&&(n[
 i]=n[t],delete n[t])},ru=function(n){throw n;},ko=function(n){return n.trim?n.trim():n.replace(/^\s+|\s+$/g,"")},af=function(n,i){return n!==t?n:i},rp=/^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/,go=["scheme","authority","path","query","fragment"],vf=function(n){var i={isAbsolute:!1},r,t,u;if(n){if(r=rp.exec(n),r)for(t=0,u=go.length;t<u;t++)r[t+1]&&(i[go[t]]=r[t+1]);i.scheme&&(i.isAbsolute=!0)}return i},ns=function(n){return"".concat(n.scheme||"",n.authority||"",n.path||"",n.query||"",n.fragment||"")},up=/^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/,fp=/%[0-9A-F]{2}/ig,ep=function(n){var i=vf(n),r=i.scheme,u=i.authority,t;return r&&(i.scheme=r.toLowerCase(),u&&(t=up.exec(u),t&&(i.authority="//"+(t[1]?t[1]+"@":"")+t[2].toLowerCase()+(t[3]?":"+t[3]:"")))),n=ns(i),n.replace(fp,function(n){return n.toLowerCase()})},c=function(n,t){var i,u,r,f;return t?(i=vf(n),i.isAbsolute)?n:(u=vf(t),r={},i.authority?(r.authority=i.authority,f=i.path,r.query=i.query):(i.path?(f=i.path.charA
 t(0)==="/"?i.path:op(i.path,u.path),r.query=i.query):(f=u.path,r.query=i.query||u.query),r.authority=u.authority),r.path=sp(f),r.scheme=u.scheme,r.fragment=i.fragment,ns(r)):n},op=function(n,t){var i="/",r;return t&&(r=t.lastIndexOf("/"),i=t.substring(0,r),i.charAt(i.length-1)!=="/"&&(i=i+"/")),i+n},sp=function(n){for(var t="",r="",i;n;)n.indexOf("..")===0||n.indexOf(".")===0?n=n.replace(/^\.\.?\/?/g,""):n.indexOf("/..")===0?(n=n.replace(/^\/\..\/?/g,"/"),i=t.lastIndexOf("/"),t=i===-1?"":t.substring(0,i)):n.indexOf("/.")===0?n=n.replace(/^\/\.\/?/g,"/"):(r=n,i=n.indexOf("/",1),i!==-1&&(r=n.substring(0,i)),t=t+r,n=n.replace(r,""));return t},hp=function(i){var r=[],o,u,f,s,e,h;if(n.atob===t)r=cp(i);else for(o=n.atob(i),u=0;u<o.length;u++)r.push(o.charCodeAt(u));for(f="",s="0123456789ABCDEF",e=0;e<r.length;e++)h=r[e],f+=s[h>>4],f+=s[h&15];return f},cp=function(n){for(var i="",r,u,f,e,o,t=0;t<n.length;t++)r=lp(n[t]),u="",r!==null&&(u=r.toString(2),i+=ap(u));for(f=[],e=parseInt(i.length/
 8,10),t=0;t<e;t++)o=parseInt(i.substring(t*8,(t+1)*8),2),f.push(o);return f},lp=function(n){var t=n.charCodeAt(0),i=65,r=6;return t>=65&&t<=90?t-i:t>=97&&t<=122?t-i-r:t>=48&&t<=57?t+4:n=="+"?62:n=="/"?63:null},ap=function(n){while(n.length<6)n="0"+n;return n},uu="http://",or=uu+"www.w3.org/",ts=or+"1999/xhtml",sr=or+"2000/xmlns/",yi=or+"XML/1998/namespace",is=uu+"www.mozilla.org/newlayout/xml/parsererror.xml",vp=function(n){var t=/(^\s)|(\s$)/;return t.test(n)},yp=function(n){var t=/^\s*$/;return n===null||t.test(n)},pp=function(n){while(n!==null&&n.nodeType===1){var t=st(n,"space",yi);if(t==="preserve")return!0;if(t==="default")break;else n=n.parentNode}return!1},wp=function(n){var t=n.nodeName;return t=="xmlns"||t.indexOf("xmlns:")===0},fu=function(n,t,i){try{n.setProperty(t,i)}catch(r){}},bp=function(){var n=bo("Msxml2.DOMDocument.3.0");return n&&(fu(n,"ProhibitDTD",!0),fu(n,"MaxElementDepth",256),fu(n,"AllowDocumentFunction",!1),fu(n,"AllowXsltScript",!1)),n},rs=function(){try{v
 ar n=bo("Msxml2.DOMDocument.6.0");return n&&(n.async=!0),n}catch(t){return bp()}},kp=function(n){var t=rs(),i;return t?(t.loadXML(n),i=t.parseError,i.errorCode!==0&&hr(i.reason,i.srcText,n),t):null},hr=function(n,t,i){typeof n=="string"&&(n={message:n});throw g(n,{srcText:t||"",errorXmlText:i||""});},eu=function(t){var s=n.DOMParser&&new n.DOMParser,r,e,l;if(!s)return r=kp(t),r||hr("XML DOM parser not supported"),r;try{r=s.parseFromString(t,"text/xml")}catch(v){hr(v,"",t)}var i=r.documentElement,h=i.namespaceURI,c=f(i);if(c==="parsererror"&&h===is&&(e=b(i,is,"sourcetext"),l=e?bi(e):"",hr(k(i)||"",l,t)),c==="h3"&&h===ts||nw(i,ts,"h3")){for(var o="",a=[],u=i.firstChild;u;)u.nodeType===1&&(o+=k(u)||""),a.push(u.nextSibling),u=u.firstChild||a.shift();o+=k(i)||"",hr(o,"",t)}return r},wt=function(n,t){return n?n+":"+t:t},dp=function(n,t){if(vp(t.data)){var i=wi(n,yi,"space");i||(i=si(n.ownerDocument,yi,wt("xml","space")),l(n,i)),i.value="preserve"}return n.appendChild(t),n},pi=function(n,
 t){for(var r=n.attributes,i=0,u=r.length;i<u;i++)t(r.item(i))},st=function(n,t,i){var r=wi(n,t,i);return r?bi(r):null},wi=function(n,t,i){var r=n.attributes;return r.getNamedItemNS?r.getNamedItemNS(i||null,t):r.getQualifiedItem(t,i)||null},rt=function(n,t){var i=wi(n,"base",yi);return(i?c(i.value,t):t)||null},p=function(n,t){yf(n,!1,function(n){return n.nodeType===1&&t(n),!0})},us=function(n,t,i){for(var u=i.split("/"),r=0,f=u.length;r<f;r++)n=n&&b(n,t,u[r]);return n||null},gp=function(n,t,i){var f=i.lastIndexOf("/"),r=i.substring(f+1),e=i.substring(0,f),u=e?us(n,t,e):n;return u?r.charAt(0)==="@"?wi(u,r.substring(1),t):b(u,t,r):null},b=function(n,t,i){return fs(n,t,i,!1)},nw=function(n,t,i){if(n.getElementsByTagNameNS){var r=n.getElementsByTagNameNS(t,i);return r.length>0?r[0]:null}return fs(n,t,i,!0)},fs=function(n,t,i,r){var e=null;return yf(n,r,function(n){if(n.nodeType===1){var r=!t||u(n)===t,o=!i||f(n)===i;r&&o&&(e=n)}return e===null}),e},k=function(n){var i=null,r=n.nodeType==
 =9&&n.documentElement?n.documentElement:n,f=r.ownerDocument.preserveWhiteSpace===!1,u;return yf(r,!1,function(n){if(n.nodeType===3||n.nodeType===4){var e=bi(n),o=f||!yp(e);o||(u===t&&(u=pp(r)),o=u),o&&(i?i+=e:i=e)}return!0}),i},f=function(n){return n.localName||n.baseName},u=function(n){return n.namespaceURI||null},bi=function(n){return n.nodeType===1?k(n):n.nodeValue},yf=function(n,t,i){for(var f=[],r=n.firstChild,u=!0;r&&u;)u=i(r),u&&(t&&r.firstChild&&f.push(r.firstChild),r=r.nextSibling||f.shift())},tw=function(n,t,i){for(var r=n.nextSibling,e,o;r;){if(r.nodeType===1&&(e=!t||u(r)===t,o=!i||f(r)===i,e&&o))return r;r=r.nextSibling}return null},es=function(){var t=n.document.implementation;return t&&t.createDocument?t.createDocument(null,null,null):rs()},ou=function(n,t){if(!e(t))return l(n,t);for(var i=0,r=t.length;i<r;i++)t[i]&&l(n,t[i]);return n},l=function(n,t){if(t){if(typeof t=="string")return dp(n,rw(n.ownerDocument,t));t.nodeType===2?n.setAttributeNodeNS?n.setAttributeNodeNS
 (t):n.setAttributeNode(t):n.appendChild(t)}return n},si=function(n,i,r,u){var f=n.createAttributeNS&&n.createAttributeNS(i,r)||n.createNode(2,r,i||t);return f.value=u||"",f},cr=function(n,i,r,u){var f=n.createElementNS&&n.createElementNS(i,r)||n.createNode(1,r,i||t);return ou(f,u||[])},os=function(n,t,i){return si(n,sr,wt("xmlns",i),t)},iw=function(n,t){for(var f="<c>"+t+"<\/c>",e=eu(f),r=e.documentElement,o=("importNode"in n)?n.importNode(r,!0):r,u=n.createDocumentFragment(),i=o.firstChild;i;)u.appendChild(i),i=i.nextSibling;return u},rw=function(n,t){return n.createTextNode(t)},uw=function(n,t,i,r,u){for(var f="",h=u.split("/"),c=b,a=cr,o=t,e,s=0,v=h.length;s<v;s++)f=h[s],f.charAt(0)==="@"&&(f=f.substring(1),c=wi,a=si),e=c(o,i,f),e||(e=a(n,i,wt(r,f)),l(o,e)),o=e;return o},pf=function(t){var i=n.XMLSerializer,r;if(i)return r=new i,r.serializeToString(t);if(t.xml)return t.xml;throw{message:"XML serialization unsupported"};},fw=function(n){var f=n.childNodes,t,r=f.length,i;if(r===0)r
 eturn"";var e=n.ownerDocument,o=e.createDocumentFragment(),u=e.createElement("c");for(o.appendChild(u),t=0;t<r;t++)u.appendChild(f[t]);for(i=pf(o),i=i.substr(3,i.length-7),t=0;t<r;t++)n.appendChild(u.childNodes[t]);return i},vit=function(i){var r=i.xml,u;if(r!==t)return r;if(n.XMLSerializer)return u=new n.XMLSerializer,u.serializeToString(i);throw{message:"XML serialization unsupported"};},ew=function(n,t,i){return function(){return n[t].apply(n,arguments),i}},ki=function(){this._arguments=t,this._done=t,this._fail=t,this._resolved=!1,this._rejected=!1};ki.prototype={then:function(n,t){return n&&(this._done?this._done.push(n):this._done=[n]),t&&(this._fail?this._fail.push(t):this._fail=[t]),this._resolved?this.resolve.apply(this,this._arguments):this._rejected&&this.reject.apply(this,this._arguments),this},resolve:function(){if(this._done){for(var n=0,i=this._done.length;n<i;n++)this._done[n].apply(null,arguments);this._done=t,this._resolved=!1,this._arguments=t}else this._resolved=
 !0,this._arguments=arguments},reject:function(){if(this._fail){for(var n=0,i=this._fail.length;n<i;n++)this._fail[n].apply(null,arguments);this._fail=t,this._rejected=!1,this._arguments=t}else this._rejected=!0,this._arguments=arguments},promise:function(){var n={};return n.then=ew(this,"then",n),n}};var su=function(){return n.jQuery&&n.jQuery.Deferred?new n.jQuery.Deferred:new ki},ss=function(n,t){var i=(n&&n.__metadata||{}).type;return i||(t?t.type:null)},v="Edm.",hs=v+"Binary",cs=v+"Boolean",ls=v+"Byte",hu=v+"DateTime",cu=v+"DateTimeOffset",as=v+"Decimal",vs=v+"Double",ys=v+"Guid",ps=v+"Int16",ws=v+"Int32",bs=v+"Int64",ks=v+"SByte",ds=v+"Single",lr=v+"String",lu=v+"Time",ht=v+"Geography",gs=ht+"Point",nh=ht+"LineString",th=ht+"Polygon",ih=ht+"Collection",rh=ht+"MultiPolygon",uh=ht+"MultiLineString",fh=ht+"MultiPoint",et=v+"Geometry",eh=et+"Point",oh=et+"LineString",sh=et+"Polygon",hh=et+"Collection",ch=et+"MultiPolygon",lh=et+"MultiLineString",ah=et+"MultiPoint",wf="Point",bf="Li
 neString",kf="Polygon",df="MultiPoint",gf="MultiLineString",ne="MultiPolygon",te="GeometryCollection",ow=[lr,ws,bs,cs,vs,ds,hu,cu,lu,as,ys,ls,ps,ks,hs],sw=[et,eh,oh,sh,hh,ch,lh,ah],hw=[ht,gs,nh,th,ih,rh,uh,fh],hi=function(n,t){if(!n)return null;if(e(n)){for(var r,i=0,u=n.length;i<u;i++)if(r=hi(n[i],t),r)return r;return null}return n.dataServices?hi(n.dataServices.schema,t):t(n)},vh=function(n,t){return n=n===0?"":"."+a(n.toString(),3),t>0&&(n===""&&(n=".000"),n+=a(t.toString(),4)),n},yh=function(n){var u,t,e;if(typeof n=="string")return n;if(u=vw(n),t=wh(n.__offset),u&&t!=="Z"){n=new Date(n.valueOf());var i=ec(t),o=n.getUTCHours()+i.d*i.h,s=n.getUTCMinutes()+i.d*i.m;n.setUTCHours(o,s)}else u||(t="");var r=n.getUTCFullYear(),h=n.getUTCMonth()+1,f="";return r<=0&&(r=-(r-1),f="-"),e=vh(n.getUTCMilliseconds(),n.__ns),f+a(r,4)+"-"+a(h,2)+"-"+a(n.getUTCDate(),2)+"T"+a(n.getUTCHours(),2)+":"+a(n.getUTCMinutes(),2)+":"+a(n.getUTCSeconds(),2)+e+t},ph=function(n){var t=n.ms,e="",i,r,u,f;retur
 n t<0&&(e="-",t=-t),i=Math.floor(t/864e5),t-=864e5*i,r=Math.floor(t/36e5),t-=36e5*r,u=Math.floor(t/6e4),t-=6e4*u,f=Math.floor(t/1e3),t-=f*1e3,e+"P"+a(i,2)+"DT"+a(r,2)+"H"+a(u,2)+"M"+a(f,2)+vh(t,n.ns)+"S"},a=function(n,t,i){for(var r=n.toString(10);r.length<t;)i?r+="0":r="0"+r;return r},wh=function(n){return!n||n==="Z"||n==="+00:00"||n==="-00:00"?"Z":n},au=function(n){if(typeof n=="string"){var t=n.indexOf(")",10);if(n.indexOf("Collection(")===0&&t>0)return n.substring(11,t)}return null},cw=function(n,i,r,u,f,e){return f.request(n,function(f){try{f.headers&&ee(f.headers),f.data===t&&f.statusCode!==204&&u.read(f,e)}catch(o){o.request===t&&(o.request=n),o.response===t&&(o.response=f),r(o);return}i(f.data,f)},r)},lw=function(n){return d(n)&&e(n.__batchRequests)},aw=/Collection\((.*)\)/,bh=function(n,t){var i=n&&n.results||n;return!!i&&vu(t)||!t&&e(i)&&!d(i[0])},vu=function(n){return aw.test(n)},d=function(n){return!!n&&lf(n)&&!e(n)&&!cf(n)},vw=function(n){return n.__edmType==="Edm.DateT
 imeOffset"||!n.__edmType&&n.__offset},kh=function(n){if(!n&&!d(n))return!1;var t=n.__metadata||{},i=n.__deferred||{};return!t.type&&!!i.uri},dh=function(n){return d(n)&&n.__metadata&&"uri"in n.__metadata},ar=function(n,t){var i=n&&n.results||n;return e(i)&&!vu(t)&&d(i[0])},ie=function(n){return fr(hw,n)},re=function(n){return fr(sw,n)},gh=function(n){if(!n&&!d(n))return!1;var i=n.__metadata,t=n.__mediaresource;return!i&&!!t&&!!t.media_src},yu=function(n){return cf(n)||typeof n=="string"||typeof n=="number"||typeof n=="boolean"},ue=function(n){return fr(ow,n)},nc=function(n,i){return kh(n)?"deferred":dh(n)?"entry":ar(n)?"feed":i&&i.relationship?n===null||n===t||!ar(n)?"entry":"feed":null},bt=function(n,t){return er(n,function(n){return n.name===t})},fe=function(n,t,i){return n?hi(t,function(t){return dw(n,t,i)}):null},yw=function(n,t){return er(n,function(n){return n.name===t})},di=function(n,t){return fe(n,t,"complexType")},kt=function(n,t){return fe(n,t,"entityType")},tc=function(n
 ){return hi(n,function(n){return er(n.entityContainer,function(n){return oe(n.isDefaultEntityContainer)})})},ic=function(n,t){return fe(n,t,"entityContainer")},pw=function(n,t){return er(n,function(n){return n.name===t})},ww=function(n,t){var u=null,f,i,r;return n&&(f=n.relationship,i=hi(t,function(n){var r=rc(n.namespace,f),i=n.association,t,u;if(r&&i)for(t=0,u=i.length;t<u;t++)if(i[t].name===r)return i[t];return null}),i&&(r=i.end[0],r.role!==n.toRole&&(r=i.end[1]),u=r.type)),u},bw=function(n,t,i){if(n){var u=n.relationship,r=hi(i,function(n){for(var f=n.entityContainer,t,i,r=0;r<f.length;r++)if(t=f[r].associationSet,t)for(i=0;i<t.length;i++)if(t[i].association==u)return t[i];return null});if(r&&r.end[0]&&r.end[1])return r.end[0].entitySet==t?r.end[1].entitySet:r.end[0].entitySet}return null},kw=function(n,t){return hi(t,function(t){for(var f=t.entityContainer,r,u,i=0;i<f.length;i++)if(r=f[i].entitySet,r)for(u=0;u<r.length;u++)if(r[u].name==n)return{entitySet:r[u],containerName:f[
 i].name,functionImport:f[i].functionImport};return null})},rc=function(n,t){return t.indexOf(n)===0&&t.charAt(n.length)==="."?t.substr(n.length+1):null},dw=function(n,t,i){if(n&&t){var r=rc(t.namespace,n);if(r)return er(t[i],function(n){return n.name===r})}return null},ct=function(n,t){var i,f,e;if(n===t)return n;var r=n.split("."),u=t.split("."),o=r.length>=u.length?r.length:u.length;for(i=0;i<o;i++){if(f=r[i]&&s(r[i]),e=u[i]&&s(u[i]),f>e)return n;if(f<e)return t}},gw={accept:"Accept","content-type":"Content-Type",dataserviceversion:"DataServiceVersion",maxdataserviceversion:"MaxDataServiceVersion"},ee=function(n){var t,r,i,u;for(t in n)r=t.toLowerCase(),i=gw[r],i&&t!==i&&(u=n[t],delete n[t],n[i]=u)},oe=function(n){return typeof n=="boolean"?n:typeof n=="string"&&n.toLowerCase()==="true"},nb=/^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/,uc=function(n,t,i){var r=nb.exec(n),o=r?wh(r[8]):null,h,u,e,c,l,f;if(!r||!t&&o!=="Z"){if(i)return null;throw{message:
 "Invalid date/time value"};}if(h=s(r[1]),h<=0&&h++,u=r[7],e=0,u){if(u.length>7){if(i)return null;throw{message:"Cannot parse date/time value to given precision."};}e=a(u.substring(3),4,!0),u=a(u.substring(0,3),3,!0),u=s(u),e=s(e)}else u=0;var v=s(r[4]),y=s(r[5]),p=s(r[6])||0;if(o!=="Z"&&(c=ec(o),l=-c.d,v+=c.h*l,y+=c.m*l),f=new Date,f.setUTCFullYear(h,s(r[2])-1,s(r[3])),f.setUTCHours(v,y,p,u),isNaN(f.valueOf())){if(i)return null;throw{message:"Invalid date/time value"};}return t&&(f.__edmType="Edm.DateTimeOffset",f.__offset=o),e&&(f.__ns=e),f},pu=function(n,t){return uc(n,!1,t)},se=function(n,t){return uc(n,!0,t)},fc=/^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/,yit=function(n){fc.test(n)},he=function(n){var i=fc.exec(n),t,r,u;if(i===null)throw{message:"Invalid duration value."};var f=i[2]||"0",e=i[3]||"0",o=s(i[4]||0),h=s(i[5]||0),c=s(i[6]||0),l=parseFloat(i[7]||0);if(f!=="0"||e!=="0")throw{message:"Unsupported duration value."};if(t
 =i[8],r=0,t){if(t.length>7)throw{message:"Cannot parse duration value to given precision."};r=a(t.substring(3),4,!0),t=a(t.substring(0,3),3,!0),t=s(t),r=s(r)}else t=0;return t+=l*1e3+c*6e4+h*36e5+o*864e5,i[1]==="-"&&(t=-t),u={ms:t,__edmType:"Edm.Time"},r&&(u.ns=r),u},ec=function(n){var t=n.substring(0,1),i,r;return t=t==="+"?1:-1,i=s(n.substring(1)),r=s(n.substring(n.indexOf(":")+1)),{d:t,h:i,m:r}},oc=function(n,i,r){n.method||(n.method="GET"),n.headers?ee(n.headers):n.headers={},n.headers.Accept===t&&(n.headers.Accept=i.accept),ot(n.data)&&n.body===t&&i.write(n,r),ot(n.headers.MaxDataServiceVersion)||(n.headers.MaxDataServiceVersion=i.maxDataServiceVersion||"1.0")},sc=function(n,i,r){var u,e,f;if(n&&typeof n=="object")for(u in n)e=n[u],f=sc(e,u,r),f=r(u,f,i),f!==e&&(e===t?delete n[u]:n[u]=f);return n},tb=function(n,t){return t("",sc(n,"",t))},wu=0,ib=function(n){return n.method&&n.method!=="GET"?!1:!0},rb=function(t){var i=n.document.createElement("IFRAME");i.style.display="none";v
 ar r=t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/\</g,"&lt;"),u='<html><head><script type="text/javascript" src="'+r+'"><\/script><\/head><body><\/body><\/html>',f=n.document.getElementsByTagName("BODY")[0];return f.appendChild(i),hc(i,u),i},ub=function(){if(n.XMLHttpRequest)return new n.XMLHttpRequest;var t;if(n.ActiveXObject)try{return new n.ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(i){try{return new n.ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(r){t=r}}else t={message:"XMLHttpRequest not supported"};throw t;},fb=function(n){return n.indexOf("http://")===0||n.indexOf("https://")===0||n.indexOf("file://")===0},eb=function(t){if(!fb(t))return!0;var i=n.location,r=i.protocol+"//"+i.host+"/";return t.indexOf(r)===0},ob=function(i,r){try{delete n[i]}catch(u){n[i]=t,r===wu-1&&(wu-=1)}},bu=function(n){return n&&(hc(n,""),n.parentNode.removeChild(n)),null},sb=function(n,t){for(var r=n.getAllResponseHeaders().split(/\r?\n/),u,i=0,f=r.length;i<f;i++)r[i]&&(u=r[i].split(": "),t[u[0
 ]]=u[1])},hc=function(n,t){var i=n.contentWindow?n.contentWindow.document:n.contentDocument.document;i.open(),i.write(t),i.close()};r.defaultHttpClient={callbackParameterName:"$callback",formatQueryString:"$format=json",enableJsonpCallback:!1,request:function(i,r,u){var y={},f=null,h=!1,s,a,w,b,k,d,l,v;y.abort=function(){(s=bu(s),h)||(h=!0,f&&(f.abort(),f=null),u({message:"Request aborted"}))};var p=function(){s=bu(s),h||(h=!0,f=null,u({message:"Request timed out"}))},c,e=i.requestUri,g=it(i.enableJsonpCallback,this.enableJsonpCallback),nt=it(i.callbackParameterName,this.callbackParameterName),tt=it(i.formatQueryString,this.formatQueryString);if(!g||eb(e)){if(f=ub(),f.onreadystatechange=function(){var t,n,o,s;h||f===null||f.readyState!==4||(t=f.statusText,n=f.status,n===1223&&(n=204,t="No Content"),o=[],sb(f,o),s={requestUri:e,statusCode:n,statusText:t,headers:o,body:f.responseText},h=!0,f=null,n>=200&&n<=299?r(s):u({message:"HTTP request failed",request:i,response:s}))},f.open(i.me
 thod||"GET",e,!0,i.user,i.password),i.headers)for(c in i.headers)f.setRequestHeader(c,i.headers[c]);i.timeoutMS&&(f.timeout=i.timeoutMS,f.ontimeout=p),f.send(i.body)}else{if(!ib(i))throw{message:"Request is not local and cannot be done through JSONP."};a=wu,wu+=1,w=a.toString(),b=!1,c="handleJSONP_"+w,n[c]=function(i){if(s=bu(s),!h){b=!0,n.clearTimeout(k),ob(c,a),n.ActiveXObject&&(i=n.JSON.parse(n.JSON.stringify(i)));var u;u=i.d===t?{"Content-Type":"application/json;odata.metadata=minimal",dataServiceVersion:"4.0"}:{"Content-Type":"application/json"},o(function(){bu(s),r({body:i,statusCode:200,headers:u})})}},d=i.timeoutMS?i.timeoutMS:12e4,k=n.setTimeout(p,d),l=nt+"=parent."+c,this.formatQueryString&&(l+="&"+tt),v=e.indexOf("?"),e=v===-1?e+"?"+l:v===e.length-1?e+l:e+"&"+l,s=rb(e)}return y}};var ci="4.0",gi=function(n){var t,r,i,f,u;if(!n)return null;for(t=n.split(";"),r={},i=1,f=t.length;i<f;i++)u=t[i].split("="),r[ko(u[0])]=u[1];return{mediaType:ko(t[0]),properties:r}},hb=function(
 n){if(!n)return t;var r=n.mediaType,i;for(i in n.properties)r+=";"+i+"="+n.properties[i];return r},cc=function(n,t,i,r){var u={};return g(u,i),g(u,{contentType:n,dataServiceVersion:t,handler:r}),u},lc=function(n,t,i){if(n){var r=n.headers;r[t]||(r[t]=i)}},cb=function(n,t){if(n){var i=n.headers,r=i.DataServiceVersion;i.DataServiceVersion=r?ct(r,t):t}},ac=function(n,i){var r=n.headers;return r&&r[i]||t},vc=function(n){return gi(ac(n,"Content-Type"))},lb=/^\s?(\d+\.\d+);?.*$/,yc=function(n){var i=ac(n,"DataServiceVersion"),t;if(i&&(t=lb.exec(i),t&&t.length))return t[1]},pc=function(n,t){return n.accept.indexOf(t.mediaType)>=0},ab=function(n,i,r,u){var f;if(!r||!r.headers)return!1;var e=vc(r),s=yc(r)||"",o=r.body;return ot(o)?pc(n,e)?(f=cc(e,s,u,n),f.response=r,r.data=i(n,o,f),r.data!==t):!1:!1},vb=function(n,i,r,u){var e,o,f;return!r||!r.headers?!1:(e=vc(r),o=yc(r),(!e||pc(n,e))&&(f=cc(e,o,u,n),f.request=r,r.body=i(n,r.data,f),r.body!==t))?(cb(r,f.dataServiceVersion||"1.0"),lc(r,"Conte
 nt-Type",hb(f.contentType)),lc(r,"MaxDataServiceVersion",n.maxDataServiceVersion),!0):!1},li=function(n,t,i,r){return{accept:i,maxDataServiceVersion:r,read:function(t,i){return ab(this,n,t,i)},write:function(n,i){return vb(this,t,n,i)}}},yb=function(n,t){return t},pb=function(n,i){return ot(i)?i.toString():t};r.textHandler=li(yb,pb,"text/plain",ci);var wc=uu+"www.opengis.net",ut=wc+"/gml",bc=wc+"/def/crs/EPSG/0/",kc="gml",vr=function(n,t,i){var r={type:n};return r[t]=i,r},ce=function(n){if(e(n)&&n.length>=2){var t=n[0];n[0]=n[1],n[1]=t}return n},le=function(n,t,i,r,u,f){var e=dc(n,i,r,u,f);return vr(t,"coordinates",e)},dc=function(n,t,i,r,e){var o=[];return p(n,function(n){var s,h,c;if(u(n)===ut){if(s=f(n),s===t){h=b(n,ut),h&&(c=r(h,e),c&&o.push(c));return}s===i&&p(n,function(n){if(u(n)===ut){var t=r(n,e);t&&o.push(t)}})}}),o},wb=function(n,t){var i=dc(n,"geometryMember","geometryMembers",tl,t);return vr(te,"geometries",i)},bb=function(n,t){return vr(bf,"coordinates",ae(n,t))},kb=fu
 nction(n,t){return le(n,gf,"curveMember","curveMembers",ae,t)},db=function(n,t){return le(n,df,"pointMember","pointMembers",ve,t)},gb=function(n,t){return le(n,ne,"surfaceMember","surfaceMembers",gc,t)},nk=function(n,t){return vr(wf,"coordinates",ve(n,t))},tk=function(n,t){return vr(kf,"coordinates",gc(n,t))},ae=function(n,t){var i=[];return p(n,function(n){var e=u(n),r;if(e===ut){if(r=f(n),r==="posList"){i=rk(n,t);return}if(r==="pointProperty"){i.push(ik(n,t));return}if(r==="pos"){i.push(ye(n,t));return}}}),i},ve=function(n,t){var i=b(n,ut,"pos");return i?ye(i,t):[]},ik=function(n,t){var i=b(n,ut,"Point");return i?ve(i,t):[]},gc=function(n,t){var i=[],r=!1;return p(n,function(n){if(u(n)===ut){var e=f(n);if(e==="exterior"){r=!0,i.unshift(nl(n,t));return}if(e==="interior"){i.push(nl(n,t));return}}}),!r&&i.length>0&&i.unshift([[]]),i},nl=function(n,t){var i=[];return p(n,function(n){u(n)===ut&&f(n)==="LinearRing"&&(i=ae(n,t))}),i},rk=function(n,t){var f=ye(n,!1),e=f.length,r,i,u;if(e%
 2!=0)throw{message:"GML posList element has an uneven number of numeric values"};for(r=[],i=0;i<e;i+=2)u=f.slice(i,i+2),r.push(t?ce(u):u);return r},ye=function(n,t){var u=[],o=" \t\r\n",r=k(n),f;if(r)for(var s=r.length,e=0,i=0;i<=s;)o.indexOf(r.charAt(i))!==-1&&(f=r.substring(e,i),f&&u.push(parseFloat(f)),e=i+1),i++;return t?ce(u):u},tl=function(n,t){var o=f(n),i,u,r,e;switch(o){case"Point":i=nk;break;case"Polygon":i=tk;break;case"LineString":i=bb;break;case"MultiPoint":i=db;break;case"MultiCurve":i=kb;break;case"MultiSurface":i=gb;break;case"MultiGeometry":i=wb;break;default:throw{message:"Unsupported element: "+o,element:n};}if(u=i(n,t),r=st(n,"srsName",ut)||st(n,"srsName"),r){if(r.indexOf(bc)!==0)throw{message:"Unsupported srs name: "+r,element:n};e=r.substring(bc.length),e&&(u.crs={type:"name",properties:{name:"EPSG:"+e}})}return u},il=function(n,t,i,r){var u,o,e,s,f,h,c;switch(i){case wf:u=uk;break;case bf:u=fk;break;case kf:u=ek;break;case df:u=ok;break;case gf:u=sk;break;case
  ne:u=hk;break;case te:u=lk;break;default:return null}return o=u(n,t,r),e=t.crs,e&&e.type==="name"&&(s=e.properties,f=s&&s.name,f&&f.indexOf("ESPG:")===0&&f.length>5&&(h=f.substring(5),c=si(n,null,"srsName",kc+h),l(o,c))),o},dt=function(n,t,i){return cr(n,ut,wt(kc,t),i)},rl=function(n,t,i){var r=e(t)?t:[];return r=i?ce(r):r,dt(n,"pos",r.join(" "))},ul=function(n,t,i,r){var f=dt(n,t),u,o;if(e(i)){for(u=0,o=i.length;u<o;u++)l(f,rl(n,i[u],r));o===0&&l(f,dt(n,"posList"))}return f},fl=function(n,t,i){return dt(n,"Point",rl(n,t,i))},el=function(n,t,i){return ul(n,"LineString",t,i)},ol=function(n,t,i,r){var u=dt(n,t),f;return e(i)&&i.length>0&&(f=ul(n,"LinearRing",i,r),l(u,f)),u},sl=function(n,t,i){var f=t&&t.length,u=dt(n,"Polygon"),r;if(e(t)&&f>0)for(l(u,ol(n,"exterior",t[0],i)),r=1;r<f;r++)l(u,ol(n,"interior",t[r],i));return u},uk=function(n,t,i){return fl(n,t.coordinates,i)},fk=function(n,t,i){return el(n,t.coordinates,i)},ek=function(n,t,i){return sl(n,t.coordinates,i)},ku=function(n,
 t,i,r,u,f){var h=r&&r.length,c=dt(n,t),s,o;if(e(r)&&h>0){for(s=dt(n,i),o=0;o<h;o++)l(s,u(n,r[o],f));l(c,s)}return c},ok=function(n,t,i){return ku(n,"MultiPoint","pointMembers",t.coordinates,fl,i)},sk=function(n,t,i){return ku(n,"MultiCurve","curveMembers",t.coordinates,el,i)},hk=function(n,t,i){return ku(n,"MultiSurface","surfaceMembers",t.coordinates,sl,i)},ck=function(n,t,i){return il(n,t,t.type,i)},lk=function(n,t,i){return ku(n,"MultiGeometry","geometryMembers",t.geometries,ck,i)},du="application/xml",ak=uu+"docs.oasis-open.org/odata/",lt=ak+"ns",gu=lt+"/edmx",vk=lt+"/edm",at=lt,nt=lt+"/metadata",pe=lt+"/related/",hl=lt+"/scheme",cl="d",we="m",gt=function(n,t){var i={name:f(n),value:n.value};return i[t?"namespaceURI":"namespace"]=u(n),i},yr=function(n,t){for(var s=[],h=[],c=n.attributes,e,i,o,r=0,l=c.length;r<l;r++)e=c[r],u(e)!==sr&&s.push(gt(e,t));for(i=n.firstChild;i!=null;)i.nodeType===1&&h.push(yr(i,t)),i=i.nextSibling;return o={name:f(n),value:k(n),attributes:s,children:h},
 o[t?"namespaceURI":"namespace"]=u(n),o},be=function(n){return u(n)===at&&f(n)==="element"},ll=function(n,t){return{type:n,extensions:t}},yk=function(n){var t,i;return b(n,ut)?et:(t=b(n,at),!t)?lr:be(t)&&(i=tw(t,at),i&&be(i))?"Collection()":null},al=function(n){var t=null,i=!1,r=[];return pi(n,function(n){var e=u(n),o=f(n),s=bi(n);if(e===nt){if(o==="null"){i=s.toLowerCase()==="true";return}if(o==="type"){t=s;return}}if(e!==yi&&e!==sr){r.push(gt(n,!0));return}}),{type:!t&&i?lr:t,isNull:i,extensions:r}},vl=function(n){if(u(n)!==at)return null;var e=f(n),t=al(n),o=t.isNull,i=t.type,r=ll(i,t.extensions),s=o?null:yl(n,i,r);return{name:e,value:s,metadata:r}},yl=function(n,t,i){t||(t=yk(n),i.type=t);var r=ie(t);return r||re(t)?pk(n,t,r):ue(t)?pl(n,t):vu(t)?bk(n,t,i):wk(n,t,i)},pk=function(n,t,i){var u=b(n,ut),r=tl(u,i);return r.__metadata={type:t},r},pl=function(n,t){var i=bi(n)||"";switch(t){case cs:return oe(i);case hs:case as:case ys:case bs:case lr:return i;case ls:case ps:case ws:case 
 ks:return s(i);case vs:case ds:return parseFloat(i);case lu:return he(i);case hu:return pu(i);case cu:return se(i)}return i},wk=function(n,t,i){var r={__metadata:{type:t}};return p(n,function(n){var t=vl(n),u=t.name;i.properties=i.properties||{},i.properties[u]=t.metadata,r[u]=t.value}),r},bk=function(n,t,i){var r=[],u=i.elements=[],f=au(t);return p(n,function(n){if(be(n)){var t=al(n),o=t.extensions,i=t.type||f,e=ll(i,o),s=yl(n,i,e);r.push(s),u.push(e)}}),{__metadata:{type:t==="Collection()"?null:t},results:r}},kk=function(n,i){if(u(n)===at){i=rt(n,i);var r=f(n);if(r==="links")return dk(n,i);if(r==="uri")return wl(n,i)}return t},dk=function(n,t){var i=[];return p(n,function(n){f(n)==="uri"&&u(n)===at&&i.push(wl(n,t))}),{results:i}},wl=function(n,t){var i=k(n)||"";return{uri:c(i,t)}},gk=function(n,t){return t===et||t===ht?n&&n.type:t===eh||t===gs?wf:t===oh||t===nh?bf:t===sh||t===th?kf:t===hh||t===ih?te:t===ch||t===rh?ne:t===lh||t===uh?gf:t===ah||t===fh?df:null},bl=function(n,t,i){ret
 urn cr(n,nt,wt(we,t),i)},ke=function(n,t,i){return si(n,nt,wt(we,t),i)},kl=function(n,t,i){return cr(n,at,wt(cl,t),i)},nd=function(n,t){return t===hu||t===cu||cf(n)?yh(n):t===lu?ph(n):n.toString()},vt=function(n,t){return{element:n,dsv:t}},pr=function(n,t,i,r){var u=i?ke(n,"type",i):null,f=kl(n,t,u);return ou(f,r)},td=function(n,t,i,r){var u=nd(i,r),f=pr(n,t,r,u);return vt(f,"1.0")},id=function(n,t,i,r){var u=ke(n,"null","true"),f=pr(n,t,i,u),e=di(i,r)?"2.0":"1.0";return vt(f,e)},rd=function(n,t,i,r,u,f,o){var c=au(r),a=e(i)?i:i.results,v=r?{type:c}:{},h,s,y,p,w;for(v.properties=u.properties,h=pr(n,t,c?r:null),s=0,y=a.length;s<y;s++)p=a[s],w=de(n,"element",p,v,f,o),l(h,w.element);return vt(h,"4.0")},ud=function(n,t,i,r,u,f,e){var h=pr(n,t,r),a=u.properties||{},v=di(r,e)||{},s="1.0",o;for(o in i)if(o!=="__metadata"){var y=i[o],p=bt(v.property,o),w=a[o]||{},c=de(n,o,y,w,p,e);s=ct(s,c.dsv),l(h,c.element)}return vt(h,s)},fd=function(n,t,i,r,u){var f=gk(i,r),e=il(n,i,f,u),o=pr(n,t,r,e);r
 eturn vt(o,".0")},de=function(n,t,i,r,u,f){var e=ss(i,r,u),o,s;return yu(i)?td(n,t,i,e||lr):(o=ie(e),o||re(e))?fd(n,t,i,e,o):bh(i,e)?rd(n,t,i,e,r,u,f):gh(i)?null:(s=nc(i,u),s!==null)?null:i===null?id(n,t,e):ud(n,t,i,e,r,u,f)},ed=function(n){if(n&&lf(n)){var t=es();return l(t,kl(t,"uri",n.uri))}},od=function(n,t){if(t){var r=eu(t),i=b(r);if(i)return kk(i)}},sd=function(n,i,r){var u=r.contentType=r.contentType||gi(du);return u&&u.mediaType===du?pf(ed(i)):t};r.xmlHandler=li(od,sd,du,ci);var dl="a",ni=or+"2005/Atom",wr=or+"2007/app",gl=lt+"/edit-media/",na=lt+"/mediaresource/",ta=lt+"/relatedlinks/",ia=["application/atom+xml","application/atomsvc+xml","application/xml"],ra=ia[0],hd=[ni,wr,yi,sr],cd={SyndicationAuthorEmail:"author/email",SyndicationAuthorName:"author/name",SyndicationAuthorUri:"author/uri",SyndicationContributorEmail:"contributor/email",SyndicationContributorName:"contributor/name",SyndicationContributorUri:"contributor/uri",SyndicationPublished:"published",SyndicationRi
 ghts:"rights",SyndicationSummary:"summary",SyndicationTitle:"title",SyndicationUpdated:"updated"},ld=function(n){return cd[n]||n},br=function(n){return!fr(hd,n)},ua=function(n,t,i,r,u){var f;if(u=u||"",f=n["FC_TargetPath"+u],!f)return null;var e=n["FC_SourcePath"+u],s=ld(f),o=r?r+(e?"/"+e:""):e,l=o&&bd(i,t,o),h=n["FC_NsUri"+u]||null,c=n["FC_NsPrefix"+u]||null,a=n["FC_KeepInContent"+u]||"";return f!==s&&(h=ni,c=dl),{contentKind:n["FC_ContentKind"+u],keepInContent:a.toLowerCase()==="true",nsPrefix:c,nsURI:h,propertyPath:o,propertyType:l,entryPath:s}},fa=function(n,t,i){for(var c=[],l,r,f,u,e;n;){for(l=n.FC_SourcePath,r=ua(n,n,t),r&&i(r),f=n.property||[],u=0,e=f.length;u<e;u++)for(var o=f[u],s=0,h="";r=ua(o,n,t,o.name,h);)i(r),s++,h="_"+s;n=kt(n.baseType,t)}return c},nf=function(n){var t=[];return pi(n,function(n){var i=u(n);br(i)&&t.push(gt(n,!0))}),t},ea=function(n){return yr(n,!0)},oa=function(n,t,i){var e=u(n),r=f(n);if(e===wr&&r==="service")return fg(n,t);if(e===ni){if(r==="feed")
 return ad(n,t,i);if(r==="entry")return aa(n,t,i)}},sa=function(n,t){var r=[],i={extensions:r};return pi(n,function(e){var o=f(e),s=u(e),h=bi(e);if(s===null){if(o==="title"||o==="metadata"){i[o]=h;return}if(o==="target"){i.target=c(h,rt(n,t));return}}br(s)&&r.push(gt(e,!0))}),i},ha=function(n,t,i){var r=i.actions=i.actions||[];r.push(sa(n,t))},ca=function(n,t,i){var r=i.functions=i.functions||[];r.push(sa(n,t))},ad=function(n,t,i){var o=nf(n),r={feed_extensions:o},s=[],e={__metadata:r,results:s};return t=rt(n,t),p(n,function(n){var l=u(n),h=f(n);if(l===nt){if(h==="count"){e.__count=parseInt(k(n),10);return}if(h==="action"){ha(n,t,r);return}if(h==="function"){ca(n,t,r);return}}if(br(l)){o.push(yr(n));return}if(h==="entry"){s.push(aa(n,t,i));return}if(h==="link"){vd(n,e,t);return}if(h==="id"){r.uri=c(k(n),t),r.uri_extensions=nf(n);return}if(h==="title"){r.title=k(n)||"",r.title_extensions=nf(n);return}}),e},vd=function(n,t,i){var r=la(n,i),f=r.href,e=r.rel,o=r.extensions,u=t.__metadata
 ;if(e==="next"){t.__next=f,u.next_extensions=o;return}if(e==="self"){u.self=f,u.self_extensions=o;return}},la=function(n,t){t=rt(n,t);var r=[],i={extensions:r,baseURI:t};if(pi(n,function(n){var s=u(n),e=f(n),o=n.value;if(e==="href"){i.href=c(o,t);return}if(e==="type"||e==="rel"){i[e]=o;return}br(s)&&r.push(gt(n,!0))}),!i.href)throw{error:"href attribute missing on link element",element:n};return i},yd=function(n,i){if(n.indexOf("/")===-1)return i[n];for(var u=n.split("/"),r=0,f=u.length;r<f;r++){if(i===null)return t;if(i=i[u[r]],i===t)return i}return i},pd=function(n,i,r,u){var o,s,f,h,e;if(n.indexOf("/")===-1)i[n]=r,o=n;else{for(s=n.split("/"),f=0,h=s.length-1;f<h;f++){if(e=i[s[f]],e===t)e={},i[s[f]]=e;else if(e===null)return;i=e}o=s[f],i[o]=r}if(u){var c=i.__metadata=i.__metadata||{},l=c.properties=c.properties||{},a=l[o]=l[o]||{};a.type=u}},wd=function(n,t,i){var e=n.propertyPath,r,u,f;n.keepInContent||yd(e,i)===null||(r=gp(t,n.nsURI,n.entryPath),r)&&(u=n.propertyType,f=n.content
 Kind==="xhtml"?fw(r):pl(r,u||"Edm.String"),pd(e,i,f,u))},bd=function(n,t,i){for(var s=i.split("/"),u,h,f,e,o,r;t;){for(f=t,u=0,h=s.length;u<h;u++){if(e=f.property,!e)break;if(o=bt(e,s[u]),!o)break;if(r=o.type,!r||ue(r))return r||null;if(f=di(r,n),!f)return null}t=kt(t.baseType,n)}return null},aa=function(n,t,i){var r={},e={__metadata:r},o=st(n,"etag",nt),s;return o&&(r.etag=o),t=rt(n,t),p(n,function(n){var s=u(n),o=f(n);if(s===ni){if(o==="id"){kd(n,r,t);return}if(o==="category"){dd(n,r);return}if(o==="content"){gd(n,e,r,t);return}if(o==="link"){ng(n,e,r,t,i);return}return}if(s===nt){if(o==="properties"){pa(n,e,r);return}if(o==="action"){ha(n,t,r);return}if(o==="function"){ca(n,t,r);return}}}),s=kt(r.type,i),fa(s,i,function(t){wd(t,n,e)}),e},kd=function(n,t,i){t.uri=c(k(n),rt(n,i)),t.uri_extensions=nf(n)},dd=function(n,t){if(st(n,"scheme")===hl){if(t.type)throw{message:"Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry",elem
 ent:n};var i=[];pi(n,function(n){var t=u(n),r=f(n);if(!t){r!=="scheme"&&r!=="term"&&i.push(gt(n,!0));return}br(t)&&i.push(gt(n,!0))}),t.type=st(n,"term"),t.type_extensions=i}},gd=function(n,t,i,r){var e=st(n,"src"),o=st(n,"type");if(e){if(!o)throw{message:"Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",element:n};i.media_src=c(e,rt(n,r)),i.content_type=o}p(n,function(r){if(e)throw{message:"Invalid AtomPub document: content element must not have child elements if the src attribute is specified",element:n};u(r)===nt&&f(r)==="properties"&&pa(r,t,i)})},ng=function(n,t,i,r,u){var f=la(n,r),e=f.rel,s=f.href,o=f.extensions;if(e==="self"){i.self=s,i.self_link_extensions=o;return}if(e==="edit"){i.edit=s,i.edit_link_extensions=o;return}if(e==="edit-media"){i.edit_media=f.href,i.edit_media_extensions=o,ya(f,i);return}if(e.indexOf(gl)===0){rg(f,t,i);return}if(e.indexOf(na)===0){ug(f,t,i);return}if(e.indexOf(pe)===0){ig(n,f,t,i,u
 );return}if(e.indexOf(ta)===0){tg(f,i);return}},tg=function(n,t){var r=n.rel.substring(ta.length),i;t.properties=t.properties||{},i=t.properties[r]=t.properties[r]||{},i.associationuri=n.href,i.associationuri_extensions=n.extensions},ig=function(n,t,i,r,u){var e,o=b(n,nt,"inline"),s,h,f,c;o?(s=b(o),h=rt(o,t.baseURI),e=s?oa(s,h,u):null):e={__deferred:{uri:t.href}},f=t.rel.substring(pe.length),i[f]=e,r.properties=r.properties||{},c=r.properties[f]=r.properties[f]||{},c.extensions=t.extensions},rg=function(n,t,i){var o=n.rel.substring(gl.length),f=va(o,t,i),r=f.value,u=f.metadata,e=n.href;r.edit_media=e,r.content_type=n.type,u.edit_media_extensions=n.extensions,r.media_src=r.media_src||e,u.media_src_extensions=u.media_src_extensions||[],ya(n,r)},ug=function(n,t,i){var f=n.rel.substring(na.length),r=va(f,t,i),u=r.value,e=r.metadata;u.media_src=n.href,e.media_src_extensions=n.extensions,u.content_type=n.type},va=function(n,t,i){i.properties=i.properties||{};var u=i.properties[n],r=t[n]&&
 t[n].__mediaresource;return r||(r={},t[n]={__mediaresource:r},i.properties[n]=u={}),{value:r,metadata:u}},ya=function(n,t){for(var r=n.extensions,i=0,u=r.length;i<u;i++)if(r[i].namespaceURI===nt&&r[i].name==="etag"){t.media_etag=r[i].value,r.splice(i,1);return}},pa=function(n,t,i){p(n,function(n){var r=vl(n),u,f;r&&(u=r.name,f=i.properties=i.properties||{},f[u]=r.metadata,t[u]=r.value)})},fg=function(n,t){var i=[],r=[];if(t=rt(n,t),p(n,function(n){if(u(n)===wr&&f(n)==="workspace"){i.push(eg(n,t));return}r.push(yr(n))}),i.length===0)throw{message:"Invalid AtomPub service document: No workspace element found.",element:n};return{workspaces:i,extensions:r}},eg=function(n,i){var e=[],o=[],r;return i=rt(n,i),p(n,function(n){var s=u(n),h=f(n);if(s===ni&&h==="title"){if(r!==t)throw{message:"Invalid AtomPub service document: workspace has more than one child title element",element:n};r=k(n);return}if(s===wr){h==="collection"&&e.push(og(n,i));return}o.push(ea(n))}),{title:r||"",collections:e,
 extensions:o}},og=function(n,i){var r=st(n,"href"),o,e;if(!r)throw{message:"Invalid AtomPub service document: collection has no href attribute",element:n};if(i=rt(n,i),r=c(r,rt(n,i)),o=[],p(n,function(i){var r=u(i),s=f(i);if(r===ni){if(s==="title"){if(e!==t)throw{message:"Invalid AtomPub service document: collection has more than one child title element",element:i};e=k(i)}return}r!==wr&&o.push(ea(n))}),!e)throw{message:"Invalid AtomPub service document: collection has no title element",element:n};return{title:e,href:r,extensions:o}},ti=function(n,t,i){return cr(n,ni,wt(dl,t),i)},nr=function(n,t,i){return si(n,null,t,i)},sg=function(n){var t,e,i,o,r;if(n.childNodes.length>0)return!1;for(t=!0,e=n.attributes,i=0,o=e.length;i<o&&t;i++)r=e[i],t=t&&wp(r)||u(r)==nt&&f(r)==="type";return t},hg=function(n,t,i,r,u){var s=null,e=null,f=null,o="",h;return i!=="deferred"?(s=nr(n,"type","application/atom+xml;type="+i),e=bl(n,"inline"),r&&(o=r.__metadata&&r.__metadata.uri||"",f=wa(n,r,u)||ge(n,r,u
 ),l(e,f.element))):o=r.__deferred.uri,h=ti(n,"link",[nr(n,"href",o),nr(n,"rel",c(t,pe)),s,e]),vt(h,f?f.dsv:"1.0")},cg=function(n,t,i,r,u,f){var e,o;return gh(i)?null:(e=de(n,t,i,r,u,f),e||(o=nc(i,u),e=hg(n,t,o,i,f)),e)},lg=function(n,t,i,r){var u=us(i,at,r.propertyPath),l=u&&wi(u,"null",nt),o,s="1.0",f,e,h,c;if(l&&l.value==="true")return s;if(u&&(o=k(u)||"",!r.keepInContent))for(s="2.0",f=u.parentNode,e=f,f.removeChild(u);e!==i&&sg(e);)f=e.parentNode,f.removeChild(e),e=f;return(h=uw(n,t,r.nsURI,r.nsPrefix,r.entryPath),h.nodeType===2)?(h.value=o,s):(c=r.contentKind,ou(h,[c&&si(n,null,"type",c),c==="xhtml"?iw(n,o):o]),s)},ge=function(n,t,i){var e=t.__metadata||{},b=e.properties||{},y=e.etag,p=e.uri,s=e.type,o=kt(s,i),h=bl(n,"properties"),c=ti(n,"entry",[ti(n,"author",ti(n,"name")),y&&ke(n,"etag",y),p&&ti(n,"id",p),s&&ti(n,"category",[nr(n,"term",s),nr(n,"scheme",hl)]),ti(n,"content",[nr(n,"type","application/xml"),h])]),f="1.0",r,v,w;for(r in t)if(r!=="__metadata"){var k=b[r]||{},d=o&
 &(bt(o.property,r)||bt(o.navigationProperty,r)),a=cg(n,r,t[r],k,d,i);a&&(v=a.element,w=u(v)===ni?c:h,l(w,v),f=ct(f,a.dsv))}return fa(o,i,function(t){var i=lg(n,c,h,t);f=ct(f,i)}),vt(c,f)},wa=function(n,t,i){var f=e(t)?t:t.results,r,o,u,h,s;if(!f)return null;for(r="1.0",o=ti(n,"feed"),u=0,h=f.length;u<h;u++)s=ge(n,f[u],i),l(o,s.element),r=ct(r,s.dsv);return vt(o,r)},ag=function(n,t){var u,i,r,f;return n&&(u=ar(n)&&wa||lf(n)&&ge,u&&(i=es(),r=u(i,n,t),r))?(f=r.element,ou(f,[os(i,nt,we),os(i,at,cl)]),vt(l(i,f),r.dsv)):null},vg=function(n,t,i){if(t){var u=eu(t),r=b(u);if(r)return oa(r,null,i.metadata)}},yg=function(n,t,i){var u=i.contentType=i.contentType||gi(ra),r;if(u&&u.mediaType===ra&&(r=ag(t,i.metadata),r))return i.dataServiceVersion=ct(i.dataServiceVersion||"1.0",r.dsv),pf(r.element)};r.atomHandler=li(vg,yg,ia.join(","),ci);var i=function(n,t,i,r){return{attributes:n,elements:t,text:i||!1,ns:r}},tt={elements:{Annotations:i(["Target","Qualifier"],["TypeAnnotation*","ValueAnnotation*
 "]),Association:i(["Name"],["End*","ReferentialConstraint","TypeAnnotation*","ValueAnnotation*"]),AssociationSet:i(["Name","Association"],["End*","TypeAnnotation*","ValueAnnotation*"]),Binary:i(null,null,!0),Bool:i(null,null,!0),Collection:i(null,["String*","Int*","Float*","Decimal*","Bool*","DateTime*","DateTimeOffset*","Guid*","Binary*","Time*","Collection*","Record*"]),CollectionType:i(["ElementType","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"],["CollectionType","ReferenceType","RowType","TypeRef"]),ComplexType:i(["Name","BaseType","Abstract"],["Property*","TypeAnnotation*","ValueAnnotation*"]),DateTime:i(null,null,!0),DateTimeOffset:i(null,null,!0),Decimal:i(null,null,!0),DefiningExpression:i(null,null,!0),Dependent:i(["Role"],["PropertyRef*"]),Documentation:i(null,null,!0),End:i(["Type","Role","Multiplicity","EntitySet"],["OnDelete"]),EntityContainer:i(["Name","Extends"],["EntitySet*","AssociationSet*","FunctionImport*","
 TypeAnnotation*","ValueAnnotation*"]),EntitySet:i(["Name","EntityType"],["TypeAnnotation*","ValueAnnotation*"]),EntityType:i(["Name","BaseType","Abstract","OpenType"],["Key","Property*","NavigationProperty*","TypeAnnotation*","ValueAnnotation*"]),EnumType:i(["Name","UnderlyingType","IsFlags"],["Member*"]),Float:i(null,null,!0),Function:i(["Name","ReturnType"],["Parameter*","DefiningExpression","ReturnType","TypeAnnotation*","ValueAnnotation*"]),FunctionImport:i(["Name","ReturnType","EntitySet","IsSideEffecting","IsComposable","IsBindable","EntitySetPath"],["Parameter*","ReturnType","TypeAnnotation*","ValueAnnotation*"]),Guid:i(null,null,!0),Int:i(null,null,!0),Key:i(null,["PropertyRef*"]),LabeledElement:i(["Name"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),Member:i(["Name","Value"]),NavigationProperty:i(["Name","Relationship","ToRole","FromRole","ContainsTarget"],["TypeAnnotation*
 ","ValueAnnotation*"]),Null:i(null,null),OnDelete:i(["Action"]),Path:i(null,null,!0),Parameter:i(["Name","Type","Mode","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","SRID"],["CollectionType","ReferenceType","RowType","TypeRef","TypeAnnotation*","ValueAnnotation*"]),Principal:i(["Role"],["PropertyRef*"]),Property:i(["Name","Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","CollectionKind","SRID"],["CollectionType","ReferenceType","RowType","TypeAnnotation*","ValueAnnotation*"]),PropertyRef:i(["Name"]),PropertyValue:i(["Property","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ReferenceType:i(["Type"]),ReferentialConstraint:i(null,["Principal","Dependent"]),
 ReturnType:i(["ReturnType","Type","EntitySet"],["CollectionType","ReferenceType","RowType"]),RowType:i(["Property*"]),String:i(null,null,!0),Schema:i(["Namespace","Alias"],["Using*","EntityContainer*","EntityType*","Association*","ComplexType*","Function*","ValueTerm*","Annotations*"]),Time:i(null,null,!0),TypeAnnotation:i(["Term","Qualifier"],["PropertyValue*"]),TypeRef:i(["Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"]),Using:i(["Namespace","Alias"]),ValueAnnotation:i(["Term","Qualifier","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ValueTerm:i(["Name","Type"],["TypeAnnotation*","ValueAnnotation*"]),Edmx:i(["Version"],["DataServices","Reference*","AnnotationsReference*"],!1,gu),DataServices:i(null,["Schema*"],!1,gu)}},ba=["m
 :FC_ContentKind","m:FC_KeepInContent","m:FC_NsPrefix","m:FC_NsUri","m:FC_SourcePath","m:FC_TargetPath"];tt.elements.Property.attributes=tt.elements.Property.attributes.concat(ba),tt.elements.EntityType.attributes=tt.elements.EntityType.attributes.concat(ba),tt.elements.Edmx={attributes:["Version"],elements:["DataServices"],ns:gu},tt.elements.DataServices={elements:["Schema*"],ns:gu},tt.elements.EntityContainer.attributes.push("m:IsDefaultEntityContainer"),tt.elements.Property.attributes.push("m:MimeType"),tt.elements.FunctionImport.attributes.push("m:HttpMethod"),tt.elements.FunctionImport.attributes.push("m:IsAlwaysBindable"),tt.elements.EntityType.attributes.push("m:HasStream"),tt.elements.DataServices.attributes=["m:DataServiceVersion","m:MaxDataServiceVersion"];var ka=function(n){if(!n)return n;if(n.length>1){var t=n.substr(0,2);return t===t.toUpperCase()?n:n.charAt(0).toLowerCase()+n.substr(1)}return n.charAt(0).toLowerCase()},pg=function(n,t){var r,u,e,i,f,o;if(t==="Documentat
 ion")return{isArray:!0,propertyName:"documentation"};if(r=n.elements,!r)return null;for(u=0,e=r.length;u<e;u++)if(i=r[u],f=!1,i.charAt(i.length-1)==="*"&&(f=!0,i=i.substr(0,i.length-1)),t===i)return o=ka(i),{isArray:f,propertyName:o};return null},wg=/^(m:FC_.*)_[0-9]+$/,da=function(n){return n===vk},no=function(n){var o=f(n),e=u(n),i=tt.elements[o];if(!i)return null;if(i.ns){if(e!==i.ns)return null}else if(!da(e))return null;var t={},r=[],s=i.attributes||[];return pi(n,function(n){var c=f(n),e=u(n),l=n.value,i,o,h;e!==sr&&(i=null,o=!1,da(e)||e===null?i="":e===nt&&(i="m:"),i!==null&&(i+=c,h=wg.exec(i),h&&(i=h[1]),fr(s,i)&&(o=!0,t[ka(c)]=l)),o||r.push(gt(n)))}),p(n,function(n){var o=f(n),u=pg(i,o),e;u?u.isArray?(e=t[u.propertyName],e||(e=[],t[u.propertyName]=e),e.push(no(n))):t[u.propertyName]=no(n):r.push(yr(n))}),i.text&&(t.text=k(n)),r.length&&(t.extensions=r),t},ga=function(n,i){var r=eu(i),u=b(r);return no(u)||t};r.metadataHandler=li(ga,null,du,ci);var nv="o",to="f",tv="p",iv="c"
 ,rv="s",uv="l",bg="odata",ii=bg+".",kg="@"+ii+"bind",io=ii+"metadata",fv=ii+"navigationLinkUrl",tr=ii+"type",tf={readLink:"self",editLink:"edit",nextLink:"__next",mediaReadLink:"media_src",mediaEditLink:"edit_media",mediaContentType:"content_type",mediaETag:"media_etag",count:"__count",media_src:"mediaReadLink",edit_media:"mediaEditLink",content_type:"mediaContentType",media_etag:"mediaETag",url:"uri"},h={metadata:"odata.metadata",count:"odata.count",next:"odata.nextLink",id:"odata.id",etag:"odata.etag",read:"odata.readLink",edit:"odata.editLink",mediaRead:"odata.mediaReadLink",mediaEdit:"odata.mediaEditLink",mediaEtag:"odata.mediaETag",mediaContentType:"odata.mediaContentType",actions:"odata.actions",functions:"odata.functions",navigationUrl:"odata.navigationLinkUrl",associationUrl:"odata.associationLinkUrl",type:"odata.type"},dg=function(n){if(n.indexOf(".")>0){var t=n.indexOf("@"),r=t>-1?n.substring(0,t):null,i=n.substring(t+1);return{target:r,name:i,isOData:i.indexOf(ii)===0}}re
 turn null},ro=function(n,t,i,r,u){return d(t)&&t[tr]||i&&i[n+"@"+tr]||r&&r.type||ww(r,u)||null},uo=function(n,t){return t?bt(t.property,n)||bt(t.navigationProperty,n):null},ev=function(n){return d(n)&&ii+"id"in n},gg=function(n,t,i){if(!!t[n+"@"+fv]||i&&i.relationship)return!0;var r=e(t[n])?t[n][0]:t[n];return ev(r)},fo=function(n){return ue(n)||ie(n)||re(n)},ri=function(n,t,i,r,u){var f,e;for(f in n)if(f.indexOf(".")>0&&f.charAt(0)!=="#"&&(e=dg(f),e)){var c=e.name,o=e.target,s=null,h=null;o&&(s=uo(o,r),h=ro(o,n[o],n,s,u)),e.isOData?nn(c,o,h,n[f],n,t,i):t[f]=n[f]}return t},nn=function(n,t,i,r,u,f,e){var o=n.substring(ii.length);switch(o){case"navigationLinkUrl":fn(o,t,i,r,u,f,e);return;case"nextLink":case"count":rn(o,t,r,f,e);return;case"mediaReadLink":case"mediaEditLink":case"mediaContentType":case"mediaETag":un(o,t,i,r,f,e);return;default:tn(o,t,r,f,e);return}},tn=function(n,t,i,r,u){var f=r.__metadata=r.__metadata||{},e=tf[n]||n,s,o;if(n==="editLink"){f.uri=c(i,u),f[e]=f.uri;retu
 rn}if((n==="readLink"||n==="associationLinkUrl")&&(i=c(i,u)),t){if(s=f.properties=f.properties||{},o=s[t]=s[t]||{},n==="type"){o[e]=o[e]||i;return}o[e]=i;return}f[e]=i},rn=function(n,t,i,r,u){var f=tf[n],e=t?r[t]:r;e[f]=n==="nextLink"?c(i,u):i},un=function(n,t,i,r,u,f){var e=u.__metadata=u.__metadata||{},h=tf[n],o,s;if((n==="mediaReadLink"||n==="mediaEditLink")&&(r=c(r,f)),t){o=e.properties=e.properties||{},s=o[t]=o[t]||{},s.type=s.type||i,u.__metadata=e,u[t]=u[t]||{__mediaresource:{}},u[t].__mediaresource[h]=r;return}e[h]=r},fn=function(n,t,i,r,u,f,e){var s=f.__metadata=f.__metadata||{},h=s.properties=s.properties||{},o=h[t]=h[t]||{},l=c(r,e);if(u.hasOwnProperty(t)){o.navigationLinkUrl=l;return}f[t]={__deferred:{uri:l}},o.type=o.type||i},eo=function(n,t,i,r,u,f,o){if(typeof n=="string")return en(n,t,o);if(!fo(t)){if(e(n))return ov(n,t,i,r,f,o);if(d(n))return on(n,t,i,r,f,o)}return n},en=function(n,t,i){switch(t){case lu:return he(n);case hu:return pu(n,!1);case cu:return se(n,!1)}r
 eturn i?pu(n,!0)||se(n,!0)||n:n},ov=function(n,t,i,r,u,f){for(var a=au(t),o=[],h=[],e=0,c=n.length;e<c;e++){var s=ro(null,n[e])||a,l={type:s},v=eo(n[e],s,l,r,null,u,f);fo(s)||yu(n[e])||o.push(l),h.push(v)}return o.length>0&&(i.elements=o),{__metadata:{type:t},results:h}},on=function(n,t,i,r,u,f){var e=rf(n,{type:t},r,u,f),o=e.__metadata,s=o.properties;return s&&(i.properties=s,delete o.properties),e},sn=function(n,t,i,r,u){return e(n)?hv(n,t,i,r,u):d(n)?rf(n,t,i,r,u):null},rf=function(n,i,r,u,f){var d,v,g,o,y,h,c,nt;i=i||{};var l=n[tr]||i.type||null,s=kt(l,u),k=!0;s||(k=!1,s=di(l,u));var p={type:l},a={__metadata:p},w={},e;if(k&&s&&i.entitySet&&i.contentTypeOdata=="minimalmetadata"){for(d=r.substring(0,r.lastIndexOf("$metadata")),e=null,s.key||(e=s);!!e&&!e.key&&e.baseType;)e=kt(e.baseType,u);(s.key||!!e&&e.key)&&(v=s.key?cv(n,s):cv(n,e),v&&(g={key:v,entitySet:i.entitySet,functionImport:i.functionImport,containerName:i.containerName},hn(n,g,l,d,s,e)))}for(o in n)if(o.indexOf("#")===0
 )sv(o.substring(1),n[o],a,r,u);else if(o.indexOf(".")===-1){for(p.properties||(p.properties=w),y=n[o],h=h=uo(o,s),e=s;!!s&&h===null&&e.baseType;)e=kt(e.baseType,u),h=h=uo(o,e);var tt=gg(o,n,h),b=ro(o,y,n,h,u),it=w[o]=w[o]||{type:b};tt?(c={},i.entitySet!==t&&(nt=bw(h,i.entitySet.name,u),c=kw(nt,u)),c.contentTypeOdata=i.contentTypeOdata,c.kind=i.kind,c.type=b,a[o]=sn(y,c,r,u,f)):a[o]=eo(y,b,it,r,h,u,f)}return ri(n,a,r,s,u)},sv=function(n,t,i,r,u){var f,s,g,nt;if(n&&(e(t)||d(t))){var l=!1,h=n.lastIndexOf("."),a=n.substring(h+1),v=h>-1?n.substring(0,h):"",y=a===n||v.indexOf(".")===-1?tc(u):ic(v,u);y&&(f=pw(y.functionImport,a),f&&!!f.isSideEffecting&&(l=!oe(f.isSideEffecting)));for(var p=i.__metadata,w=l?"functions":"actions",tt=c(n,r),b=e(t)?t:[t],o=0,k=b.length;o<k;o++)s=b[o],s&&(g=p[w]=p[w]||[],nt={metadata:tt,title:s.title,target:c(s.target,r)},g.push(nt))}},hv=function(n,t,i,r,u){for(var h=e(n)?n:n.value,c=[],l,f,s,o=0,a=h.length;o<a;o++)l=rf(h[o],t,i,r,u),c.push(l);if(f={results:c}
 ,d(n)){for(s in n)s.indexOf("#")===0&&(f.__metadata=f.__metadata||{},sv(s.substring(1),n[s],f,i,r));f=ri(n,f,i)}return f},cv=function(n,t){var r,i=t.key.propertyRef,f,e,u;if(r="(",i.length==1)f=bt(t.property,i[0].name).type,r+=oo(n[i[0].name],f);else for(e=!0,u=0;u<i.length;u++)e?e=!1:r+=",",f=bt(t.property,i[u].name).type,r+=i[u].name+"="+oo(n[i[u].name],f);return r+=")"},hn=function(n,t,i,r,u,f){var o=n[h.id]||n[h.read]||n[h.edit]||t.entitySet.name+t.key,e;n[h.id]=r+o,n[h.edit]||(n[h.edit]=t.entitySet.name+t.key,t.entitySet.entityType!=i&&(n[h.edit]+="/"+i)),n[h.read]=n[h.read]||n[h.edit],n[h.etag]||(e=cn(n,u,f),!e||(n[h.etag]=e)),yn(n,u,f),ln(n,u,f),vn(n,t)},cn=function(n,t,i){for(var u="",f,r=0;t.property&&r<t.property.length;r++)f=t.property[r],u=lv(n,u,f);if(i)for(r=0;i.property&&r<i.property.length;r++)f=i.property[r],u=lv(n,u,f);return u.length>0?u+'"':null},lv=function(n,t,i){return i.concurrencyMode=="Fixed"&&(t+=t.length>0?",":'W/"',t+=n[i.name]!==null?oo(n[i.name],i.type
 ):"null"),t},ln=function(n,i,r){for(var s="@odata.navigationLinkUrl",c="@odata.associationLinkUrl",u,e,o,f=0;i.navigationProperty&&f<i.navigationProperty.length;f++)u=i.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u));if(r&&r.navigationProperty)for(f=0;f<r.navigationProperty.length;f++)u=r.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u))},oo=function(n,t){n=""+an(n,t),n=encodeURIComponent(n.replace("'","''"));switch(t){case"Edm.Binary":return"X'"+n+"'";case"Edm.DateTime":return"datetime'"+n+"'";case"Edm.DateTimeOffset":return"datetimeoffset'"+n+"'";case"Edm.Decimal":return n+"M";case"Edm.Guid":return"guid'"+n+"'";case"Edm.Int64":return n+"L";case"Edm.Float":return n+"f";case"Edm.Double":return n+"D";case"Edm.Geography":return"geography'"+n+"'";case"Edm.Geometry":return"geometry'"+
 n+"'";case"Edm.Time":return"time'"+n+"'";case"Edm.String":return"'"+n+"'";default:return n}},an=function(n,t){switch(t){case"Edm.Binary":return hp(n);default:return n}},vn=function(n,i){for(var u=i.functionImport||[],f,r=0;r<u.length;r++)u[r].isBindable&&u[r].parameter[0]&&u[r].parameter[0].type==i.entitySet.entityType&&(f="#"+i.containerName+"."+u[r].name,n[f]==t&&(n[f]={title:u[r].name,target:n[h.edit]+"/"+u[r].name}))},yn=function(n,t,i){(t.hasStream||i&&i.hasStream)&&(n[h.mediaEdit]=n[h.mediaEdit]||n[h.mediaEdit]+"/$value",n[h.mediaRead]=n[h.mediaRead]||n[h.mediaEdit])},pn=function(n,t,i,r){var u={type:t},f=eo(n.value,t,u,i,null,null,r);return ri(n,{__metadata:u,value:f},i)},wn=function(n,t,i,r,u){var f={},e=ov(n.value,t,f,i,r,u);return g(e.__metadata,f),ri(n,e,i)},bn=function(n,t){var r=n.value,u,i,f,o;if(!e(r))return av(n,t);for(u=[],i=0,f=r.length;i<f;i++)u.push(av(r[i],t));return o={results:u},ri(n,o,t)},av=function(n,t){var i={uri:c(n.url,t)},u,r;return i=ri(n,i,t),u=i.__me
 tadata||{},r=u.properties||{},uf(r.url),iu(r,"url","uri"),i},uf=function(n){n&&delete n.type},kn=function(n,t){var o=n.value,s=[],h=ri(n,{collections:s},t),e=h.__metadata||{},i=e.properties||{},u,l,f,r;for(uf(i.value),iu(i,"value","collections"),u=0,l=o.length;u<l;u++)f=o[u],r={title:f.name,href:c(f.url,t)},r=ri(f,r,t),e=r.__metadata||{},i=e.properties||{},uf(i.name),uf(i.url),iu(i,"name","title"),iu(i,"url","href"),s.push(r);return{workspaces:[h]}},ui=function(n,t){return{kind:n,type:t||null}},dn=function(n,t,i){var f=n[io],s,v,o,y,l,r,p,h,c,w,b,u,k;if(!f||typeof f!="string")return null;if(s=f.lastIndexOf("#"),s===-1)return ui(rv);if(v=f.indexOf("@Element",s),o=v-1,o<0&&(o=f.indexOf("?",s),o===-1&&(o=f.length)),y=f.substring(s+1,o),y.indexOf("/$links/")>0)return ui(uv);if(l=y.split("/"),l.length>=0){if(r=l[0],p=l[1],fo(r))return ui(tv,r);if(vu(r))return ui(iv,r);if(h=p,!p){var d=r.lastIndexOf("."),g=r.substring(d+1),a=g===r?tc(t):ic(r.substring(0,d),t);a&&(c=yw(a.entitySet,g),w=a.f
 unctionImport,b=a.name,h=!c?null:c.entityType)}return v>0?(u=ui(nv,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):h?(u=ui(to,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):e(n.value)&&!di(r,t)&&(k=n.value[0],!yu(k)&&(ev(k)||!i))?ui(to,null):ui(nv,r)}return null},gn=function(n,t,i,r,u){var e,f,o;if(!d(n))return n;if(u=u||"minimalmetadata",e=n[io],f=dn(n,t,r),ot(f)&&(f.contentTypeOdata=u),o=null,f){delete n[io],o=f.type;switch(f.kind){case to:return hv(n,f,e,t,i);case iv:return wn(n,o,e,t,i);case tv:return pn(n,o,e,i);case rv:return kn(n,e);case uv:return bn(n,e)}}return rf(n,f,e,t,i)},vv=["type","etag","media_src","edit_media","content_type","media_etag"],yv=function(n,t){var u=/\/\$links\//,i={},r=n.__metadata,f=t&&u.test(t.request.requestUri);return so(n,r&&r.properties,i,f),i},ntt=function(n,t){var i,u,r,f;if(n)for(i=0,u=vv.length;i<u;i++)r=vv[i],f=ii+(tf[r]||r),kr(f,null,n[r],t)},so=function(n,t,i,r){var u,f;for(u in n)f=n[u],u==="__metadata"?ntt(f,i):u.indexO
 f(".")===-1?r&&u==="uri"?itt(f,i):ttt(u,f,t,i,r):i[u]=f},ttt=function(n,i,r,u){var e=r&&r[n]||{properties:t,type:t},f=ss(i,e);if(yu(i)||!i){kr(tr,n,f,u),u[n]=i;return}if(ar(i,f)||dh(i)){ftt(n,i,u);return}if(!f&&kh(i)){rtt(n,i,u);return}if(bh(i,f)){au(f)&&kr(tr,n,f,u),utt(n,i,u);return}u[n]={},kr(tr,null,f,u[n]),so(i,e.properties,u[n])},itt=function(n,t){t.url=n},rtt=function(n,t,i){kr(fv,n,t.__deferred.uri,i)},utt=function(n,t,i){i[n]=[];var r=e(t)?t:t.results;so(r,null,i[n])},ftt=function(n,t,i){if(ar(t)){i[n]=[];for(var u=e(t)?t:t.results,r=0,f=u.length;r<f;r++)pv(n,u[r],!0,i);return}pv(n,t,!1,i)},pv=function(n,t,i,r){var f=t.__metadata&&t.__metadata.uri,u;if(f){ett(n,f,i,r);return}if(u=yv(t),i){r[n].push(u);return}r[n]=u},ett=function(n,t,i,r){var u=n+kg;if(i){r[u]=r[u]||[],r[u].push(t);return}r[u]=t},kr=function(n,i,r,u){r!==t&&(i?u[i+"@"+n]=r:u[n]=r)},wv="application/json",bv=gi(wv),kv=function(n){var r=[],t,i,u;for(t in n)for(i=0,u=n[t].length;i<u;i++)r.push(g({metadata:t},n[t
 ][i]));return r},ott=function(n,t,i,r){var c,f,l,u,o,s,v,e,h,a;if(n&&typeof n=="object")if(f=n.__metadata,f&&(f.actions&&(f.actions=kv(f.actions)),f.functions&&(f.functions=kv(f.functions)),c=f&&f.type),l=kt(c,t)||di(c,t),l){if(o=l.property,o)for(s=0,v=o.length;s<v;s++)if(e=o[s],h=e.name,u=n[h],e.type==="Edm.DateTime"||e.type==="Edm.DateTimeOffset"){if(u){if(u=i(u),!u)throw{message:"Invalid date/time value"};n[h]=u}}else e.type==="Edm.Time"&&(n[h]=he(u))}else if(r)for(a in n)u=n[a],typeof u=="string"&&(n[a]=i(u)||u);return n},dv=function(n){if(n){var t=n.properties.odata;return t==="nometadata"||t==="minimalmetadata"||t==="fullmetadata"}return!1},stt=function(n,t){for(var u={collections:[]},r,e,i=0,f=n.EntitySets.length;i<f;i++)r=n.EntitySets[i],e={title:r,href:c(r,t)},u.collections.push(e);return{workspaces:[u]}},htt=/^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/,ctt=function(n){var t,i;return n<0?(t="-",n=-n):t="+",i=Math.floor(n/60),n=n-60*i,t+a(i,2)+":"+a(n,2)},ltt=function(n){var i=n&&ht
 t.exec(n),t,r,u;if(i&&(t=new Date(s(i[1])),i[2]&&(r=s(i[3]),i[2]==="-"&&(r=-r),u=t.getUTCMinutes(),t.setUTCMinutes(u-r),t.__edmType="Edm.DateTimeOffset",t.__offset=ctt(r)),!isNaN(t.valueOf())))return t},att=function(t,i,r){var f=it(r.recognizeDates,t.recognizeDates),h=it(r.inferJsonLightFeedAsObject,t.inferJsonLightFeedAsObject),e=r.metadata,o=r.dataServiceVersion,s=ltt,u=typeof i=="string"?n.JSON.parse(i):i;if(ct("4.0",o)===o){if(dv(r.contentType))return gn(u,e,f,h,r.contentType.properties.odata);s=pu}return u=tb(u.d,function(n,t){return ott(t,e,s,f)}),u=wtt(u,r.dataServiceVersion),ptt(u,r.response.requestUri)},gv=function(t){var i,r=Date.prototype.toJSON;try{Date.prototype.toJSON=function(){return yh(this)},i=n.JSON.stringify(t,ytt)}finally{Date.prototype.toJSON=r}return i},vtt=function(n,i,r){var e=r.dataServiceVersion||"1.0",o=it(r.useJsonLight,n.useJsonLight),u=r.contentType=r.contentType||bv,f;return u&&u.mediaType===bv.mediaType?(f=i,o||dv(u))?(r.dataServiceVersion=ct(e,"4.0"
 ),f=yv(i,r),gv(f)):(ct("4.0",e)===e&&(u.properties.odata="verbose",r.contentType=u),gv(f)):t},ytt=function(n,t){return t&&t.__edmType==="Edm.Time"?ph(t):t},ptt=function(n,t){var i=d(n)&&!n.__metadata&&e(n.EntitySets);return i?stt(n,t):n},wtt=function(n,t){return t&&t.lastIndexOf(";")===t.length-1&&(t=t.substr(0,t.length-1)),t&&t!=="1.0"||e(n)&&(n={results:n}),n},ff=li(att,vtt,wv,ci);ff.recognizeDates=!1,ff.useJsonLight=!1,ff.inferJsonLightFeedAsObject=!1,r.jsonHandler=ff;var dr="multipart/mixed",btt=/^HTTP\/1\.\d (\d{3}) (.*)$/i,ktt=/^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/,ho=function(){return Math.floor((1+Math.random())*65536).toString(16).substr(1)},ny=function(n){return n+ho()+"-"+ho()+"-"+ho()},ty=function(n){return n.handler.partHandler},iy=function(n){var t=n.boundaries;return t[t.length-1]},dtt=function(n,t,i){var r=i.contentType.properties.boundary;return{__batchResponses:ry(t,{boundaries:[r],handlerContext:i})}},gtt=function(n,t,i){var r=i.contentType=i.contentType||gi(
 dr);if(r.mediaType===dr)return nit(t,i)},ry=function(n,t){var f="--"+iy(t),u,o,s,r,e,i;for(ef(n,t,f),ir(n,t),u=[];o!=="--"&&t.position<n.length;){if(s=uy(n,t),r=gi(s["Content-Type"]),r&&r.mediaType===dr){t.boundaries.push(r.properties.boundary);try{e=ry(n,t)}catch(h){h.response=fy(n,t,f),e=[h]}u.push({__changeResponses:e}),t.boundaries.pop(),ef(n,t,"--"+iy(t))}else{if(!r||r.mediaType!=="application/http")throw{message:"invalid MIME part type "};ir(n,t),i=fy(n,t,f);try{i.statusCode>=200&&i.statusCode<=299?ty(t.handlerContext).read(i,t.handlerContext):i={message:"HTTP request failed",response:i}}catch(h){i=h}u.push(i)}o=n.substr(t.position,2),ir(n,t)}return u},uy=function(n,t){var r={},i,u,f;do f=t.position,u=ir(n,t),i=ktt.exec(u),i!==null?r[i[1]]=i[2]:t.position=f;while(u&&i);return ee(r),r},fy=function(n,t,i){var o=t.position,r=btt.exec(ir(n,t)),u,f,e;return r?(u=r[1],f=r[2],e=uy(n,t),ir(n,t)):t.position=o,{statusCode:u,statusText:f,headers:e,body:ef(n,t,"\r\n"+i)}},ir=function(n,t)
 {return ef(n,t,"\r\n")},ef=function(n,t,i){var u=t.position||0,r=n.length;if(i){if(r=n.indexOf(i,u),r===-1)return null;t.position=r+i.length}else t.position=r;return n.substring(u,r)},nit=function(n,t){var o;if(!lw(n))throw{message:"Data is not a batch object."};for(var r=ny("batch_"),f=n.__batchRequests,u="",i=0,e=f.length;i<e;i++)u+=of(r,!1)+ey(f[i],t);return u+=of(r,!0),o=t.contentType.properties,o.boundary=r,u},of=function(n,t){var i="\r\n--"+n;return t&&(i+="--"),i+"\r\n"},ey=function(n,t,i){var s=n.__changeRequests,r,f,o,h,u;if(e(s)){if(i)throw{message:"Not Supported: change set nested in other change set"};for(f=ny("changeset_"),r="Content-Type: "+dr+"; boundary="+f+"\r\n",o=0,h=s.length;o<h;o++)r+=of(f,!1)+ey(s[o],t,!0);r+=of(f,!0)}else r="Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\n",u=g({},t),u.handler=li,u.request=n,u.contentType=null,oc(n,ty(t),u),r+=tit(n);return r},tit=function(n){var t=(n.method?n.method:"GET")+" "+n.requestUri+" HTTP/1.
 1\r\n",i;for(i in n.headers)n.headers[i]&&(t=t+i+": "+n.headers[i]+"\r\n");return t+="\r\n",n.body&&(t+=n.body),t};r.batchHandler=li(dtt,gtt,dr,ci),co=[r.jsonHandler,r.atomHandler,r.xmlHandler,r.textHandler],lo=function(n,t,i){for(var r=0,u=co.length;r<u&&!co[r][n](t,i);r++);if(r===u)throw{message:"no handler for data"};},r.defaultSuccess=function(t){n.alert(n.JSON.stringify(t))},r.defaultError=ru,r.defaultHandler={read:function(n,t){n&&ot(n.body)&&n.headers["Content-Type"]&&lo("read",n,t)},write:function(n,t){lo("write",n,t)},maxDataServiceVersion:ci,accept:"application/atomsvc+xml;q=0.8, application/json;odata.metadata=full;q=0.7, application/json;q=0.5, */*;q=0.1"},r.defaultMetadata=[],r.read=function(n,t,i,u,f,e){var o;return o=n instanceof String||typeof n=="string"?{requestUri:n}:n,r.request(o,t,i,u,f,e)},r.request=function(n,t,i,u,f,e){t=t||r.defaultSuccess,i=i||r.defaultError,u=u||r.defaultHandler,f=f||r.defaultHttpClient,e=e||r.defaultMetadata,n.recognizeDates=it(n.recogniz
 eDates,r.jsonHandler.recognizeDates),n.callbackParameterName=it(n.callbackParameterName,r.defaultHttpClient.callbackParameterName),n.formatQueryString=it(n.formatQueryString,r.defaultHttpClient.formatQueryString),n.enableJsonpCallback=it(n.enableJsonpCallback,r.defaultHttpClient.enableJsonpCallback),n.useJsonLight=it(n.useJsonLight,r.jsonHandler.enableJsonpCallback),n.inferJsonLightFeedAsObject=it(n.inferJsonLightFeedAsObject,r.jsonHandler.inferJsonLightFeedAsObject);var o={metadata:e,recognizeDates:n.recognizeDates,callbackParameterName:n.callbackParameterName,formatQueryString:n.formatQueryString,enableJsonpCallback:n.enableJsonpCallback,useJsonLight:n.useJsonLight,inferJsonLightFeedAsObject:n.inferJsonLightFeedAsObject};try{return oc(n,u,o),cw(n,t,i,u,f,o)}catch(s){i(s)}},r.parseMetadata=function(n){return ga(null,n)},r.batchHandler.partHandler=r.defaultHandler;var ft=null,iit=function(){var t={v:this.valueOf(),t:"[object Date]"},n;for(n in this)t[n]=this[n];return t},rit=functio
 n(n,t){var r,i;if(t&&t.t==="[object Date]"){r=new Date(t.v);for(i in t)i!=="t"&&i!=="v"&&(r[i]=t[i]);t=r}return t},sf=function(n,t){return n.name+"#!#"+t},oy=function(n,t){return t.replace(n.name+"#!#","")},y=function(n){this.name=n};y.create=function(t){if(y.isSupported())return ft=ft||n.localStorage,new y(t);throw{message:"Web Storage not supported by the browser"};},y.isSupported=function(){return!!n.localStorage},y.prototype.add=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?o(r,{message:"key already exists",key:n}):u.addOrUpdate(n,t,i,r)},r)},y.prototype.addOrUpdate=function(i,r,u,f){var s,h,e;if(f=f||this.defaultError,i instanceof Array)f({message:"Array of keys not supported"});else{s=sf(this,i),h=Date.prototype.toJSON;try{e=r,e!==t&&(Date.prototype.toJSON=iit,e=n.JSON.stringify(r)),ft.setItem(s,e),o(u,i,r)}catch(c){c.code===22||c.number===2147942414?o(f,{name:"QUOTA_EXCEEDED_ERR",error:c}):o(f,c)}finally{Date.prototype.toJSON=h}}},y.prototy
 pe.clear=function(n,t){var i,r,u,f;t=t||this.defaultError;try{for(i=0,r=ft.length;r>0&&i<r;)u=ft.key(i),f=oy(this,u),u!==f?(ft.removeItem(u),r=ft.length):i++;o(n)}catch(e){o(t,e)}},y.prototype.close=function(){},y.prototype.contains=function(n,t,i){i=i||this.defaultError;try{var r=sf(this,n),u=ft.getItem(r);o(t,u!==null)}catch(f){o(i,f)}},y.prototype.defaultError=ru,y.prototype.getAllKeys=function(n,t){var r,i,e,u,f;t=t||this.defaultError,r=[];try{for(i=0,e=ft.length;i<e;i++)u=ft.key(i),f=oy(this,u),u!==f&&r.push(f);o(n,r)}catch(s){o(t,s)}},y.prototype.mechanism="dom",y.prototype.read=function(i,r,u){if(u=u||this.defaultError,i instanceof Array)u({message:"Array of keys not supported"});else try{var e=sf(this,i),f=ft.getItem(e);f=f!==null&&f!=="undefined"?n.JSON.parse(f,rit):t,o(r,i,f)}catch(s){o(u,s)}},y.prototype.remove=function(n,t,i){if(i=i||this.defaultError,n instanceof Array)i({message:"Batches not supported"});else try{var r=sf(this,n);ft.removeItem(r),o(t)}catch(u){o(i,u)}}
 ,y.prototype.update=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?u.addOrUpdate(n,t,i,r):o(r,{message:"key not found",key:n})},r)};var sy=n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB||n.indexedDB,uit=n.IDBKeyRange||n.webkitIDBKeyRange,hy=n.IDBTransaction||n.webkitIDBTransaction||{},cy=hy.READ_ONLY||"readonly",rr=hy.READ_WRITE||"readwrite",yt=function(n,t){return function(i){var r=n||t,u,f;if(r){if(Object.prototype.toString.call(i)==="[object IDBDatabaseException]"){if(i.code===11){r({name:"QuotaExceededError",error:i});return}r(i);return}try{f=i.target.error||i,u=f.name}catch(e){u=i.type==="blocked"?"IndexedDBBlocked":"UnknownError"}r({name:u,error:i})}}},fit=function(n,t,i){var u=n.name,f="_datajs_"+u,r=sy.open(f);r.onblocked=i,r.onerror=i,r.onupgradeneeded=function(){var n=r.result;n.objectStoreNames.contains(u)||n.createObjectStore(u)},r.onsuccess=function(n){var f=r.result,e;if(!f.objectStoreNames.contains(u)){if("setVersion"in f){e=f.setV
 ersion("1.0"),e.onsuccess=function(){var n=e.transaction;n.oncomplete=function(){t(f)},f.createObjectStore(u,null,!1)},e.onerror=i,e.onblocked=i;return}n.target.error={name:"DBSchemaMismatch"},i(n);return}f.onversionchange=function(n){n.target.close()},t(f)}},fi=function(n,t,i,r){var u=n.name,f=n.db,e=yt(r,n.defaultError);if(f){i(f.transaction(u,t));return}fit(n,function(r){n.db=r,i(r.transaction(u,t))},e)},w=function(n){this.name=n};w.create=function(n){if(w.isSupported())return new w(n);throw{message:"IndexedDB is not supported on this browser"};},w.isSupported=function(){return!!sy},w.prototype.add=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){s.onabort=yt(r,o,n,"add"),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)};for(var h=0;h<u.length&&h<f.length;h++)s.objectStore(e).add({v:f[h]},u[h])},r)},w.prototype.addOrUpdate=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n inst
 anceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){var h,c;for(s.onabort=yt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c={v:f[h]},s.objectStore(e).put(c,u[h])},r)},w.prototype.clear=function(n,t){var i=this.name,r=this.defaultError;fi(this,rr,function(u){u.onerror=yt(t,r),u.oncomplete=function(){n()},u.objectStore(i).clear()},t)},w.prototype.close=function(){this.db&&(this.db.close(),this.db=null)},w.prototype.contains=function(n,t,i){var r=this.name,u=this.defaultError;fi(this,cy,function(f){var e=f.objectStore(r),o=e.get(n);f.oncomplete=function(){t(!!o.result)},f.onerror=yt(i,u)},i)},w.prototype.defaultError=ru,w.prototype.getAllKeys=function(n,t){var i=this.name,r=this.defaultError;fi(this,rr,function(u){var e=[],f;u.oncomplete=function(){n(e)},f=u.objectStore(i).openCursor(),f.onerror=yt(t,r),f.onsuccess=function(n){var t=n.target.result;t&&(e.push(t.key),t["continue"].call(t))}},t)},w.prototype.mechanism="indexeddb",w
 .prototype.read=function(n,i,r){var f=this.name,e=this.defaultError,u=n instanceof Array?n:[n];fi(this,cy,function(o){var h=[],s,c,l;for(o.onerror=yt(r,e,n,"read"),o.oncomplete=function(){n instanceof Array?i(u,h):i(u[0],h[0])},s=0;s<u.length;s++)c=o.objectStore(f),l=c.get.call(c,u[s]),l.onsuccess=function(n){var i=n.target.result;h.push(i?i.v:t)}},r)},w.prototype.remove=function(n,t,i){var u=this.name,f=this.defaultError,r=n instanceof Array?n:[n];fi(this,rr,function(n){var e,o;for(n.onerror=yt(i,f),n.oncomplete=function(){t()},e=0;e<r.length;e++)o=n.objectStore(u),o["delete"].call(o,r[e])},i)},w.prototype.update=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,rr,function(s){var h,c,l;for(s.onabort=yt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c=s.objectStore(e).openCursor(uit.only(u[h])),l={v:f[h]},c.pair={key:u[h],value:l},c.onsuccess=function(n){var t=n.target.re
 sult;t?t.update(n.target.pair.value):s.abort()}},r)},ei=function(n){var e=[],r=[],i={},u,f;this.name=n,u=function(n){return n||this.defaultError},f=function(n,i){var r;return(n instanceof Array&&(r="Array of keys not supported"),(n===t||n===null)&&(r="Invalid key"),r)?(o(i,{message:r}),!1):!0},this.add=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?e({message:"key already exists",key:n}):this.addOrUpdate(n,t,r,e))},this.addOrUpdate=function(n,s,h,c){if(c=u(c),f(n,c)){var l=i[n];l===t&&(l=e.length>0?e.splice(0,1):r.length),r[l]=s,i[n]=l,o(h,n,s)}},this.clear=function(n){r=[],i={},e=[],o(n)},this.contains=function(n,t){var r=i.hasOwnProperty(n);o(t,r)},this.getAllKeys=function(n){var t=[],r;for(r in i)t.push(r);o(n,t)},this.read=function(n,t,e){if(e=u(e),f(n,e)){var s=i[n];o(t,n,r[s])}},this.remove=function(n,s,h){if(h=u(h),f(n,h)){var c=i[n];c!==t&&(c===r.length-1?r.pop():(r[c]=t,e.push(c)),delete i[n],r.length===0&&(e=[])),o(s)}},this.update=function(n,t,r,e){e=u(e),f(n,e)&&(
 i.hasOwnProperty(n)?this.addOrUpdate(n,t,r,e):e({message:"key not found",key:n}))}},ei.create=function(n){return new ei(n)},ei.isSupported=function(){return!0},ei.prototype.close=function(){},ei.prototype.defaultError=ru,ei.prototype.mechanism="memory",ly={indexeddb:w,dom:y,memory:ei},pt.defaultStoreMechanism="best",pt.createStore=function(n,t){t||(t=pt.defaultStoreMechanism),t==="best"&&(t=y.isSupported()?"dom":"memory");var i=ly[t];if(i)return i.create(n);throw{message:"Failed to create store",name:n,mechanism:t};};var eit=function(n,t){var i=n.indexOf("?")>=0?"&":"?";return n+i+t},oit=function(n,t){var i=n.indexOf("?"),r="";return i>=0&&(r=n.substr(i),n=n.substr(0,i)),n[n.length-1]!=="/"&&(n+="/"),n+t+r},ay=function(n,t){return{method:"GET",requestUri:n,user:t.user,password:t.password,enableJsonpCallback:t.enableJsonpCallback,callbackParameterName:t.callbackParameterName,formatQueryString:t.formatQueryString}},pit=function(n,t){var u=-1,r=n.indexOf("?"),i;return r!==-1&&(i=n.inde
 xOf("?"+t+"=",r),i===-1&&(i=n.indexOf("&"+t+"=",r)),i!==-1&&(u=i+t.length+2)),u},sit=function(n,t,i,r){return vy(n,t,[],i,r)},vy=function(n,i,u,f,e){var s=ay(n,i),o=r.request(s,function(n){var t=n.__next,r=n.results;u=u.concat(r),t?o=vy(t,i,u,f,e):f(u)},e,t,i.httpClient,i.metadata);return{abort:function(){o.abort()}}},hit=function(n){var i=this,u=n.source;return i.identifier=ep(encodeURI(decodeURI(u))),i.options=n,i.count=function(n,f){var e=i.options;return r.request(ay(oit(u,"$count"),e),function(t){var i=s(t.toString());isNaN(i)?f({message:"Count is NaN",count:i}):n(i)},f,t,e.httpClient,e.metadata)},i.read=function(n,t,r,f){var e="$skip="+n+"&$top="+t;return sit(eit(u,e),i.options,r,f)},i},cit=function(n,t){var r=lit(n,t),i,u;r&&(i=r.i-t.i,u=i+(n.c-n.d.length),n.d=n.d.concat(t.d.slice(i,u)))},lit=function(n,t){var r=n.i+n.c,u=t.i+t.c,i=n.i>t.i?n.i:t.i,f=r<u?r:u,e;return f>=i&&(e={i:i,c:f-i}),e},yy=function(n,i){if(n===t||typeof n!="number")throw{message:"'"+i+"' must be a number.
 "};if(isNaN(n)||n<0||!isFinite(n))throw{message:"'"+i+"' must be greater than or equal to zero."};},ait=function(n,i){if(n!==t){if(typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<=0||!isFinite(n))throw{message:"'"+i+"' must be greater than zero."};}},py=function(n,i){if(n!==t&&(typeof n!="number"||isNaN(n)||!isFinite(n)))throw{message:"'"+i+"' must be a number."};},ao=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return n.splice(i,1),!0;return!1},wy=function(n){var t=0,r=typeof n,i;if(r==="object"&&n)for(i in n)t+=i.length*2+wy(n[i]);else t=r==="string"?n.length*2:8;return t},by=function(n,t,i){return n=Math.floor(n/i)*i,t=Math.ceil((t+1)/i)*i,{i:n,c:t-n}},hf="destroy",ai="idle",ky="init",vo="read",yo="prefetch",po="write",gr="cancel",oi="end",wo="error",vi="start",dy="wait",gy="clear",nu="done",tu="local",np="save",tp="source",ur=function(n,t,i,r,u,f,e){var h,c,o=this,l,s;return o.p=t,o.i=r,o.c=u,o.d=f,o.s=vi,o.canceled=!1,o.pending=e,o.oncom
 plete=null,o.cancel=function(){if(i){var n=o.s;n!==wo&&n!==oi&&n!==gr&&(o.canceled=!0,s(gr,h))}},o.complete=function(){s(oi,h)},o.error=function(n){o.canceled||s(wo,n)},o.run=function(n){c=n,o.transition(o.s,h)},o.wait=function(n){s(dy,n)},l=function(t,i,r){switch(t){case vi:i!==ky&&n(o,t,i,r);break;case dy:n(o,t,i,r);break;case gr:n(o,t,i,r),o.fireCanceled(),s(oi);break;case wo:n(o,t,i,r),o.canceled=!0,o.fireRejected(r),s(oi);break;case oi:if(o.oncomplete)o.oncomplete(o);o.canceled||o.fireResolved(),n(o,t,i,r);break;default:n(o,t,i,r)}},s=function(n,t){o.s=n,h=t,l(n,c,t)},o.transition=s,o};ur.prototype.fireResolved=function(){var n=this.p;n&&(this.p=null,n.resolve(this.d))},ur.prototype.fireRejected=function(n){var t=this.p;t&&(this.p=null,t.reject(n))},ur.prototype.fireCanceled=function(){this.fireRejected({canceled:!0,message:"Operation canceled"})},ip=function(i){var it=ky,y={counts:0,netReads:0,prefetches:0,cacheReads:0},c=[],b=[],p=[],nt=0,l=!1,k=af(i.cacheSize,1048576),a=0,h=
 0,d=0,tt=k===0,r=af(i.pageSize,50),ut=af(i.prefetchSize,r),ht="1.0",f,ft=0,w=i.source,v,u;typeof w=="string"&&(w=new hit(i)),w.options=i,v=pt.createStore(i.name,i.mechanism),u=this,u.onidle=i.idle,u.stats=y,u.count=function(){var n,i,t;if(f)throw f;return(n=su(),i=!1,l)?(o(function(){n.resolve(a)}),n.promise()):(t=w.count(function(i){t=null,y.counts++,n.resolve(i)},function(r){t=null,n.reject(g(r,{canceled:i}))}),g(n.promise(),{cancel:function(){t&&(i=!0,t.abort(),t=null)}}))},u.clear=function(){if(f)throw f;if(c.length===0){var n=su(),t=new ur(ii,n,!1);return et(t,c),n.promise()}return c[0].p},u.filterForward=function(n,t,i){return lt(n,t,i,!1)},u.filterBack=function(n,t,i){return lt(n,t,i,!0)},u.readRange=function(n,t){if(yy(n,"index"),yy(t,"count"),f)throw f;var i=su(),r=new ur(ui,i,!0,n,t,[],0);return et(r,b),g(i.promise(),{cancel:function(){r.cancel()}})},u.ToObservable=u.toObservable=function(){if(!n.Rx||!n.Rx.Observable)throw{message:"Rx library not available - include rx.js"
 };if(f)throw f;return n.Rx.Observable.CreateWithDisposable(function(n){var t=!1,i=0,f=function(i){t||n.OnError(i)},e=function(o){if(!t){for(var s=0,h=o.length;s<h;s++)n.OnNext(o[s]);o.length<r?n.OnCompleted():(i+=r,u.readRange(i,r).then(e,f))}};return u.readRange(i,r).then(e,f),{Dispose:function(){t=!0}}})};var rt=function(n){return function(t){f={message:n,error:t};for(var i=0,r=b.length;i<r;i++)b[i].fireRejected(f);for(i=0,r=c.length;i<r;i++)c[i].fireRejected(f);b=c=null}},e=function(n){if(n!==it){it=n;for(var i=c.concat(b,p),t=0,r=i.length;t<r;t++)i[t].run(it)}},ct=function(){var n=new ki;return v.clear(function(){nt=0,l=!1,a=0,h=0,d=0,tt=k===0,y={counts:0,netReads:0,prefetches:0,cacheReads:0},u.stats=y,v.close(),n.resolve()},function(t){n.reject(t)}),n},kt=function(n){var t=ao(c,n);t||(t=ao(b,n),t||ao(p,n)),ft--,e(ai)},dt=function(n){var t=new ki,u=!1,i=w.read(n,r,function(i){var r={i:n,c:i.length,d:i};t.resolve(r)},function(n){t.reject(n)});return g(t,{cancel:function(){i&&(i.a
 bort(),u=!0,i=null)}})},lt=function(n,t,i,e){if(n=s(n),t=s(t),isNaN(n))throw{message:"'index' must be a valid number.",index:n};if(isNaN(t))throw{message:"'count' must be a valid number.",count:t};if(f)throw f;n=Math.max(n,0);var h=su(),o=[],a=!1,l=null,v=function(n,f){a||(t>=0&&o.length>=t?h.resolve(o):l=u.readRange(n,f).then(function(u){for(var l,a,y,p,s=0,c=u.length;s<c&&(t<0||o.length<t);s++)l=e?c-s-1:s,a=u[l],i(a)&&(y={index:n+l,item:a},e?o.unshift(y):o.push(y));!e&&u.length<f||e&&n<=0?h.resolve(o):(p=e?Math.max(n-r,0):n+f,v(p,r))},function(n){h.reject(n)}))},c=by(n,n,r),y=e?c.i:n,p=e?n-c.i+1:c.i+c.c-n;return v(y,p),g(h.promise(),{cancel:function(){l&&l.cancel(),a=!0}})},at=function(){u.onidle&&ft===0&&u.onidle()},gt=function(n){if(!l&&ut!==0&&!tt&&(p.length===0||p[0]&&p[0].c!==-1)){var t=new ur(ri,null,!0,n,ut,null,ut);et(t,p)}},et=function(n,t){n.oncomplete=kt,t.push(n),ft++,n.run(it)},ni=function(n){var r=!1,i=g(new ki,{cancel:function(){r=!0}}),u=vt(i,"Read page from store 
 failure");return v.contains(n,function(f){if(!r){if(f){v.read(n,function(n,u){r||i.resolve(u!==t,u)},u);return}i.resolve(!1)}},u),i},ti=function(n,t){var e=!1,i=g(new ki,{cancel:function(){e=!0}}),r=vt(i,"Save page to store failure"),u=function(){i.resolve(!0)},f;return t.c>0?(f=wy(t),tt=k>=0&&k<nt+f,tt?u():v.addOrUpdate(n,t,function(){yt(t,f),st(u,r)},r)):(yt(t,0),st(u,r)),i},st=function(n,t){var i={actualCacheSize:nt,allDataLocal:l,cacheSize:k,collectionCount:a,highestSavedPage:h,highestSavedPageSize:d,pageSize:r,sourceId:w.identifier,version:ht};v.addOrUpdate("__settings",i,n,t)},vt=function(n){return function(){n.resolve(!1)}},yt=function(n,t){var i=n.c,u=n.i;i===0?h===u-r&&(a=h+d):(h=Math.max(h,u),h===u&&(d=i),nt+=t,i<r&&!a&&(a=u+i)),l||a!==h+d||(l=!0)},wt=function(n,t,i,r){var u=n.canceled&&t!==oi;return u&&t===gr&&r&&r.cancel&&r.cancel(),u},ii=function(n,t,i){var r=n.transition;if(i!==hf)return e(hf),!0;switch(t){case vi:r(gy);break;case oi:at();break;case gy:ct().then(functi
 on(){n.complete()}),n.wait();break;default:return!1}return!0},ri=function(n,t,i,u){var o,f;if(!wt(n,t,i,u)){if(o=n.transition,i!==yo)return i===hf?t!==gr&&n.cancel():i===ai&&e(yo),!0;switch(t){case vi:p[0]===n&&o(tu,n.i);break;case nu:f=n.pending,f>0&&(f-=Math.min(f,u.c)),l||f===0||u.c<r||tt?n.complete():(n.pending=f,o(tu,u.i+r));break;default:return bt(n,t,i,u,!0)}}return!0},ui=function(n,t,i,u){var f,o,s;if(!wt(n,t,i,u)){if(f=n.transition,i!==vo&&t!==vi)return i===hf?t!==vi&&n.cancel():i!==po&&e(vo),!0;switch(t){case vi:(i===ai||i===yo)&&(e(vo),n.c>0?(o=by(n.i,n.c,r),f(tu,o.i)):f(nu,n));break;case nu:cit(n,u),s=n.d.length,n.c===s||u.c<r?(y.cacheReads++,gt(u.i+u.c),n.complete()):f(tu,u.i+r);break;default:return bt(n,t,i,u,!1)}}return!0},bt=function(n,t,i,r,u){var s=n.error,o=n.transition,h=n.wait,f;switch(t){case oi:at();break;case tu:f=ni(r).then(function(t,i){n.canceled||(t?o(nu,i):o(tp,r))});break;case tp:f=dt(r).then(function(t){n.canceled||(u?y.prefetches++:y.netReads++,o(np,t
 ))},s);break;case np:i!==po&&(e(po),f=ti(r.i,r).then(function(t){n.canceled||(!t&&u&&(n.pending=0),o(nu,r)),e(ai)}));break;default:return!1}return f&&(n.canceled?f.cancel():n.s===t&&h(f)),!0};return v.read("__settings",function(n,t){if(ot(t)){var i=t.version;if(!i||i.indexOf("1.")!==0){rt("Unsupported cache store version "+i)();return}r!==t.pageSize||w.identifier!==t.sourceId?ct().then(function(){e(ai)},rt("Unable to clear store during initialization")):(nt=t.actualCacheSize,l=t.allDataLocal,k=t.cacheSize,a=t.collectionCount,h=t.highestSavedPage,d=t.highestSavedPageSize,ht=i,e(ai))}else st(function(){e(ai)},rt("Unable to write settings during initialization."))},rt("Unable to read settings from store.")),u},pt.createDataCache=function(n){if(ait(n.pageSize,"pageSize"),py(n.cacheSize,"cacheSize"),py(n.prefetchSize,"prefetchSize"),!ot(n.name))throw{message:"Undefined or null name",options:n};if(!ot(n.source))throw{message:"Undefined source",options:n};return new ip(n)}})(this)
\ No newline at end of file


[47/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/datajs-1.1.2.min.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/datajs-1.1.2.min.js b/datajs/demo/scripts/datajs-1.1.2.min.js
deleted file mode 100644
index 9b65217..0000000
--- a/datajs/demo/scripts/datajs-1.1.2.min.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-(function(n,t){var yt=n.datajs||{},r=n.OData||{},lo,ao,ei,ay,rp;typeof define=="function"&&define.amd?(define("datajs",yt),define("OData",r)):(n.datajs=yt,n.OData=r),yt.version={major:1,minor:1,build:1};var ko=function(t){return n.ActiveXObject?new n.ActiveXObject(t):null},ot=function(n){return n!==null&&n!==t},er=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return!0;return!1},it=function(n,i){return n!==t?n:i},o=function(t){if(arguments.length===1){n.setTimeout(t,0);return}var i=Array.prototype.slice.call(arguments,1);n.setTimeout(function(){t.apply(this,i)},0)},g=function(n,t){for(var i in t)n[i]=t[i];return n},or=function(n,t){if(n)for(var i=0,r=n.length;i<r;i++)if(t(n[i]))return n[i];return null},e=function(n){return Object.prototype.toString.call(n)==="[object Array]"},lf=function(n){return Object.prototype.toString.call(n)==="[object Date]"},af=function(n){return typeof n=="object"},s=function(n){return parseInt(n,10)},ru=function(n,t,i){n.hasOwnProperty(t)&&(n[
 i]=n[t],delete n[t])},uu=function(n){throw n;},go=function(n){return n.trim?n.trim():n.replace(/^\s+|\s+$/g,"")},vf=function(n,i){return n!==t?n:i},up=/^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/,ns=["scheme","authority","path","query","fragment"],yf=function(n){var i={isAbsolute:!1},r,t,u;if(n){if(r=up.exec(n),r)for(t=0,u=ns.length;t<u;t++)r[t+1]&&(i[ns[t]]=r[t+1]);i.scheme&&(i.isAbsolute=!0)}return i},ts=function(n){return"".concat(n.scheme||"",n.authority||"",n.path||"",n.query||"",n.fragment||"")},fp=/^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/,ep=/%[0-9A-F]{2}/ig,op=function(n){var i=yf(n),r=i.scheme,u=i.authority,t;return r&&(i.scheme=r.toLowerCase(),u&&(t=fp.exec(u),t&&(i.authority="//"+(t[1]?t[1]+"@":"")+t[2].toLowerCase()+(t[3]?":"+t[3]:"")))),n=ts(i),n.replace(ep,function(n){return n.toLowerCase()})},c=function(n,t){var i,u,r,f;return t?(i=yf(n),i.isAbsolute)?n:(u=yf(t),r={},i.authority?(r.authority=i.authority,f=i.path,r.query=i.query):(i.path?(f=i.path.charA
 t(0)==="/"?i.path:sp(i.path,u.path),r.query=i.query):(f=u.path,r.query=i.query||u.query),r.authority=u.authority),r.path=hp(f),r.scheme=u.scheme,r.fragment=i.fragment,ts(r)):n},sp=function(n,t){var i="/",r;return t&&(r=t.lastIndexOf("/"),i=t.substring(0,r),i.charAt(i.length-1)!=="/"&&(i=i+"/")),i+n},hp=function(n){for(var t="",r="",i;n;)n.indexOf("..")===0||n.indexOf(".")===0?n=n.replace(/^\.\.?\/?/g,""):n.indexOf("/..")===0?(n=n.replace(/^\/\..\/?/g,"/"),i=t.lastIndexOf("/"),t=i===-1?"":t.substring(0,i)):n.indexOf("/.")===0?n=n.replace(/^\/\.\/?/g,"/"):(r=n,i=n.indexOf("/",1),i!==-1&&(r=n.substring(0,i)),t=t+r,n=n.replace(r,""));return t},cp=function(i){var r=[],o,u,f,s,e,h;if(n.atob===t)r=lp(i);else for(o=n.atob(i),u=0;u<o.length;u++)r.push(o.charCodeAt(u));for(f="",s="0123456789ABCDEF",e=0;e<r.length;e++)h=r[e],f+=s[h>>4],f+=s[h&15];return f},lp=function(n){for(var i="",r,u,f,e,o,t=0;t<n.length;t++)r=ap(n[t]),u="",r!==null&&(u=r.toString(2),i+=vp(u));for(f=[],e=parseInt(i.length/
 8,10),t=0;t<e;t++)o=parseInt(i.substring(t*8,(t+1)*8),2),f.push(o);return f},ap=function(n){var t=n.charCodeAt(0),i=65,r=6;return t>=65&&t<=90?t-i:t>=97&&t<=122?t-i-r:t>=48&&t<=57?t+4:n=="+"?62:n=="/"?63:null},vp=function(n){while(n.length<6)n="0"+n;return n},fu="http://",sr=fu+"www.w3.org/",is=sr+"1999/xhtml",hr=sr+"2000/xmlns/",pi=sr+"XML/1998/namespace",rs=fu+"www.mozilla.org/newlayout/xml/parsererror.xml",yp=function(n){var t=/(^\s)|(\s$)/;return t.test(n)},pp=function(n){var t=/^\s*$/;return n===null||t.test(n)},wp=function(n){while(n!==null&&n.nodeType===1){var t=st(n,"space",pi);if(t==="preserve")return!0;if(t==="default")break;else n=n.parentNode}return!1},bp=function(n){var t=n.nodeName;return t=="xmlns"||t.indexOf("xmlns:")===0},eu=function(n,t,i){try{n.setProperty(t,i)}catch(r){}},kp=function(){var n=ko("Msxml2.DOMDocument.3.0");return n&&(eu(n,"ProhibitDTD",!0),eu(n,"MaxElementDepth",256),eu(n,"AllowDocumentFunction",!1),eu(n,"AllowXsltScript",!1)),n},us=function(){try{v
 ar n=ko("Msxml2.DOMDocument.6.0");return n&&(n.async=!0),n}catch(t){return kp()}},dp=function(n){var t=us(),i;return t?(t.loadXML(n),i=t.parseError,i.errorCode!==0&&cr(i.reason,i.srcText,n),t):null},cr=function(n,t,i){typeof n=="string"&&(n={message:n});throw g(n,{srcText:t||"",errorXmlText:i||""});},ou=function(t){var s=n.DOMParser&&new n.DOMParser,r,e,l;if(!s)return r=dp(t),r||cr("XML DOM parser not supported"),r;try{r=s.parseFromString(t,"text/xml")}catch(v){cr(v,"",t)}var i=r.documentElement,h=i.namespaceURI,c=f(i);if(c==="parsererror"&&h===rs&&(e=b(i,rs,"sourcetext"),l=e?ki(e):"",cr(k(i)||"",l,t)),c==="h3"&&h===is||tw(i,is,"h3")){for(var o="",a=[],u=i.firstChild;u;)u.nodeType===1&&(o+=k(u)||""),a.push(u.nextSibling),u=u.firstChild||a.shift();o+=k(i)||"",cr(o,"",t)}return r},pt=function(n,t){return n?n+":"+t:t},gp=function(n,t){if(yp(t.data)){var i=bi(n,pi,"space");i||(i=si(n.ownerDocument,pi,pt("xml","space")),l(n,i)),i.value="preserve"}return n.appendChild(t),n},wi=function(n,
 t){for(var r=n.attributes,i=0,u=r.length;i<u;i++)t(r.item(i))},st=function(n,t,i){var r=bi(n,t,i);return r?ki(r):null},bi=function(n,t,i){var r=n.attributes;return r.getNamedItemNS?r.getNamedItemNS(i||null,t):r.getQualifiedItem(t,i)||null},rt=function(n,t){var i=bi(n,"base",pi);return(i?c(i.value,t):t)||null},p=function(n,t){pf(n,!1,function(n){return n.nodeType===1&&t(n),!0})},fs=function(n,t,i){for(var u=i.split("/"),r=0,f=u.length;r<f;r++)n=n&&b(n,t,u[r]);return n||null},nw=function(n,t,i){var f=i.lastIndexOf("/"),r=i.substring(f+1),e=i.substring(0,f),u=e?fs(n,t,e):n;return u?r.charAt(0)==="@"?bi(u,r.substring(1),t):b(u,t,r):null},b=function(n,t,i){return es(n,t,i,!1)},tw=function(n,t,i){if(n.getElementsByTagNameNS){var r=n.getElementsByTagNameNS(t,i);return r.length>0?r[0]:null}return es(n,t,i,!0)},es=function(n,t,i,r){var e=null;return pf(n,r,function(n){if(n.nodeType===1){var r=!t||u(n)===t,o=!i||f(n)===i;r&&o&&(e=n)}return e===null}),e},k=function(n){var i=null,r=n.nodeType==
 =9&&n.documentElement?n.documentElement:n,f=r.ownerDocument.preserveWhiteSpace===!1,u;return pf(r,!1,function(n){if(n.nodeType===3||n.nodeType===4){var e=ki(n),o=f||!pp(e);o||(u===t&&(u=wp(r)),o=u),o&&(i?i+=e:i=e)}return!0}),i},f=function(n){return n.localName||n.baseName},u=function(n){return n.namespaceURI||null},ki=function(n){return n.nodeType===1?k(n):n.nodeValue},pf=function(n,t,i){for(var f=[],r=n.firstChild,u=!0;r&&u;)u=i(r),u&&(t&&r.firstChild&&f.push(r.firstChild),r=r.nextSibling||f.shift())},iw=function(n,t,i){for(var r=n.nextSibling,e,o;r;){if(r.nodeType===1&&(e=!t||u(r)===t,o=!i||f(r)===i,e&&o))return r;r=r.nextSibling}return null},os=function(){var t=n.document.implementation;return t&&t.createDocument?t.createDocument(null,null,null):us()},su=function(n,t){if(!e(t))return l(n,t);for(var i=0,r=t.length;i<r;i++)t[i]&&l(n,t[i]);return n},l=function(n,t){if(t){if(typeof t=="string")return gp(n,uw(n.ownerDocument,t));t.nodeType===2?n.setAttributeNodeNS?n.setAttributeNodeNS
 (t):n.setAttributeNode(t):n.appendChild(t)}return n},si=function(n,i,r,u){var f=n.createAttributeNS&&n.createAttributeNS(i,r)||n.createNode(2,r,i||t);return f.value=u||"",f},lr=function(n,i,r,u){var f=n.createElementNS&&n.createElementNS(i,r)||n.createNode(1,r,i||t);return su(f,u||[])},ss=function(n,t,i){return si(n,hr,pt("xmlns",i),t)},rw=function(n,t){for(var f="<c>"+t+"<\/c>",e=ou(f),r=e.documentElement,o=("importNode"in n)?n.importNode(r,!0):r,u=n.createDocumentFragment(),i=o.firstChild;i;)u.appendChild(i),i=i.nextSibling;return u},uw=function(n,t){return n.createTextNode(t)},fw=function(n,t,i,r,u){for(var f="",h=u.split("/"),c=b,a=lr,o=t,e,s=0,v=h.length;s<v;s++)f=h[s],f.charAt(0)==="@"&&(f=f.substring(1),c=bi,a=si),e=c(o,i,f),e||(e=a(n,i,pt(r,f)),l(o,e)),o=e;return o},wf=function(t){var i=n.XMLSerializer,r;if(i)return r=new i,r.serializeToString(t);if(t.xml)return t.xml;throw{message:"XML serialization unsupported"};},ew=function(n){var f=n.childNodes,t,r=f.length,i;if(r===0)r
 eturn"";var e=n.ownerDocument,o=e.createDocumentFragment(),u=e.createElement("c");for(o.appendChild(u),t=0;t<r;t++)u.appendChild(f[t]);for(i=wf(o),i=i.substr(3,i.length-7),t=0;t<r;t++)n.appendChild(u.childNodes[t]);return i},kit=function(i){var r=i.xml,u;if(r!==t)return r;if(n.XMLSerializer)return u=new n.XMLSerializer,u.serializeToString(i);throw{message:"XML serialization unsupported"};},ow=function(n,t,i){return function(){return n[t].apply(n,arguments),i}},di=function(){this._arguments=t,this._done=t,this._fail=t,this._resolved=!1,this._rejected=!1};di.prototype={then:function(n,t){return n&&(this._done?this._done.push(n):this._done=[n]),t&&(this._fail?this._fail.push(t):this._fail=[t]),this._resolved?this.resolve.apply(this,this._arguments):this._rejected&&this.reject.apply(this,this._arguments),this},resolve:function(){if(this._done){for(var n=0,i=this._done.length;n<i;n++)this._done[n].apply(null,arguments);this._done=t,this._resolved=!1,this._arguments=t}else this._resolved=
 !0,this._arguments=arguments},reject:function(){if(this._fail){for(var n=0,i=this._fail.length;n<i;n++)this._fail[n].apply(null,arguments);this._fail=t,this._rejected=!1,this._arguments=t}else this._rejected=!0,this._arguments=arguments},promise:function(){var n={};return n.then=ow(this,"then",n),n}};var hu=function(){return n.jQuery&&n.jQuery.Deferred?new n.jQuery.Deferred:new di},hs=function(n,t){var i=(n&&n.__metadata||{}).type;return i||(t?t.type:null)},v="Edm.",cs=v+"Binary",ls=v+"Boolean",as=v+"Byte",cu=v+"DateTime",lu=v+"DateTimeOffset",vs=v+"Decimal",ys=v+"Double",ps=v+"Guid",ws=v+"Int16",bs=v+"Int32",ks=v+"Int64",ds=v+"SByte",gs=v+"Single",ar=v+"String",au=v+"Time",ht=v+"Geography",nh=ht+"Point",th=ht+"LineString",ih=ht+"Polygon",rh=ht+"Collection",uh=ht+"MultiPolygon",fh=ht+"MultiLineString",eh=ht+"MultiPoint",et=v+"Geometry",oh=et+"Point",sh=et+"LineString",hh=et+"Polygon",ch=et+"Collection",lh=et+"MultiPolygon",ah=et+"MultiLineString",vh=et+"MultiPoint",bf="Point",kf="Li
 neString",df="Polygon",gf="MultiPoint",ne="MultiLineString",te="MultiPolygon",ie="GeometryCollection",sw=[ar,bs,ks,ls,ys,gs,cu,lu,au,vs,ps,as,ws,ds,cs],hw=[et,oh,sh,hh,ch,lh,ah,vh],cw=[ht,nh,th,ih,rh,uh,fh,eh],hi=function(n,t){if(!n)return null;if(e(n)){for(var r,i=0,u=n.length;i<u;i++)if(r=hi(n[i],t),r)return r;return null}return n.dataServices?hi(n.dataServices.schema,t):t(n)},yh=function(n,t){return n=n===0?"":"."+a(n.toString(),3),t>0&&(n===""&&(n=".000"),n+=a(t.toString(),4)),n},ph=function(n){var u,t,e;if(typeof n=="string")return n;if(u=yw(n),t=bh(n.__offset),u&&t!=="Z"){n=new Date(n.valueOf());var i=oc(t),o=n.getUTCHours()+i.d*i.h,s=n.getUTCMinutes()+i.d*i.m;n.setUTCHours(o,s)}else u||(t="");var r=n.getUTCFullYear(),h=n.getUTCMonth()+1,f="";return r<=0&&(r=-(r-1),f="-"),e=yh(n.getUTCMilliseconds(),n.__ns),f+a(r,4)+"-"+a(h,2)+"-"+a(n.getUTCDate(),2)+"T"+a(n.getUTCHours(),2)+":"+a(n.getUTCMinutes(),2)+":"+a(n.getUTCSeconds(),2)+e+t},wh=function(n){var t=n.ms,e="",i,r,u,f;retur
 n t<0&&(e="-",t=-t),i=Math.floor(t/864e5),t-=864e5*i,r=Math.floor(t/36e5),t-=36e5*r,u=Math.floor(t/6e4),t-=6e4*u,f=Math.floor(t/1e3),t-=f*1e3,e+"P"+a(i,2)+"DT"+a(r,2)+"H"+a(u,2)+"M"+a(f,2)+yh(t,n.ns)+"S"},a=function(n,t,i){for(var r=n.toString(10);r.length<t;)i?r+="0":r="0"+r;return r},bh=function(n){return!n||n==="Z"||n==="+00:00"||n==="-00:00"?"Z":n},vu=function(n){if(typeof n=="string"){var t=n.indexOf(")",10);if(n.indexOf("Collection(")===0&&t>0)return n.substring(11,t)}return null},lw=function(n,i,r,u,f,e){return f.request(n,function(f){try{f.headers&&oe(f.headers),f.data===t&&f.statusCode!==204&&u.read(f,e)}catch(o){o.request===t&&(o.request=n),o.response===t&&(o.response=f),r(o);return}i(f.data,f)},r)},aw=function(n){return d(n)&&e(n.__batchRequests)},vw=/Collection\((.*)\)/,kh=function(n,t){var i=n&&n.results||n;return!!i&&yu(t)||!t&&e(i)&&!d(i[0])},yu=function(n){return vw.test(n)},d=function(n){return!!n&&af(n)&&!e(n)&&!lf(n)},yw=function(n){return n.__edmType==="Edm.DateT
 imeOffset"||!n.__edmType&&n.__offset},dh=function(n){if(!n&&!d(n))return!1;var t=n.__metadata||{},i=n.__deferred||{};return!t.type&&!!i.uri},gh=function(n){return d(n)&&n.__metadata&&"uri"in n.__metadata},vr=function(n,t){var i=n&&n.results||n;return e(i)&&!yu(t)&&d(i[0])},re=function(n){return er(cw,n)},ue=function(n){return er(hw,n)},nc=function(n){if(!n&&!d(n))return!1;var i=n.__metadata,t=n.__mediaresource;return!i&&!!t&&!!t.media_src},pu=function(n){return lf(n)||typeof n=="string"||typeof n=="number"||typeof n=="boolean"},fe=function(n){return er(sw,n)},tc=function(n,i){return dh(n)?"deferred":gh(n)?"entry":vr(n)?"feed":i&&i.relationship?n===null||n===t||!vr(n)?"entry":"feed":null},wt=function(n,t){return or(n,function(n){return n.name===t})},ee=function(n,t,i){return n?hi(t,function(t){return gw(n,t,i)}):null},pw=function(n,t){return or(n,function(n){return n.name===t})},gi=function(n,t){return ee(n,t,"complexType")},bt=function(n,t){return ee(n,t,"entityType")},ic=function(n
 ){return hi(n,function(n){return or(n.entityContainer,function(n){return se(n.isDefaultEntityContainer)})})},rc=function(n,t){return ee(n,t,"entityContainer")},ww=function(n,t){return or(n,function(n){return n.name===t})},bw=function(n,t){var u=null,f,i,r;return n&&(f=n.relationship,i=hi(t,function(n){var r=uc(n.namespace,f),i=n.association,t,u;if(r&&i)for(t=0,u=i.length;t<u;t++)if(i[t].name===r)return i[t];return null}),i&&(r=i.end[0],r.role!==n.toRole&&(r=i.end[1]),u=r.type)),u},kw=function(n,t,i){if(n){var u=n.relationship,r=hi(i,function(n){for(var f=n.entityContainer,t,i,r=0;r<f.length;r++)if(t=f[r].associationSet,t)for(i=0;i<t.length;i++)if(t[i].association==u)return t[i];return null});if(r&&r.end[0]&&r.end[1])return r.end[0].entitySet==t?r.end[1].entitySet:r.end[0].entitySet}return null},dw=function(n,t){return hi(t,function(t){for(var f=t.entityContainer,r,u,i=0;i<f.length;i++)if(r=f[i].entitySet,r)for(u=0;u<r.length;u++)if(r[u].name==n)return{entitySet:r[u],containerName:f[
 i].name,functionImport:f[i].functionImport};return null})},uc=function(n,t){return t.indexOf(n)===0&&t.charAt(n.length)==="."?t.substr(n.length+1):null},gw=function(n,t,i){if(n&&t){var r=uc(t.namespace,n);if(r)return or(t[i],function(n){return n.name===r})}return null},ct=function(n,t){var i,f,e;if(n===t)return n;var r=n.split("."),u=t.split("."),o=r.length>=u.length?r.length:u.length;for(i=0;i<o;i++){if(f=r[i]&&s(r[i]),e=u[i]&&s(u[i]),f>e)return n;if(f<e)return t}},nb={accept:"Accept","content-type":"Content-Type",dataserviceversion:"DataServiceVersion",maxdataserviceversion:"MaxDataServiceVersion"},oe=function(n){var t,r,i,u;for(t in n)r=t.toLowerCase(),i=nb[r],i&&t!==i&&(u=n[t],delete n[t],n[i]=u)},se=function(n){return typeof n=="boolean"?n:typeof n=="string"&&n.toLowerCase()==="true"},tb=/^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/,fc=function(n,t,i){var r=tb.exec(n),o=r?bh(r[8]):null,h,u,e,c,l,f;if(!r||!t&&o!=="Z"){if(i)return null;throw{message:
 "Invalid date/time value"};}if(h=s(r[1]),h<=0&&h++,u=r[7],e=0,u){if(u.length>7){if(i)return null;throw{message:"Cannot parse date/time value to given precision."};}e=a(u.substring(3),4,!0),u=a(u.substring(0,3),3,!0),u=s(u),e=s(e)}else u=0;var v=s(r[4]),y=s(r[5]),p=s(r[6])||0;if(o!=="Z"&&(c=oc(o),l=-c.d,v+=c.h*l,y+=c.m*l),f=new Date,f.setUTCFullYear(h,s(r[2])-1,s(r[3])),f.setUTCHours(v,y,p,u),isNaN(f.valueOf())){if(i)return null;throw{message:"Invalid date/time value"};}return t&&(f.__edmType="Edm.DateTimeOffset",f.__offset=o),e&&(f.__ns=e),f},wu=function(n,t){return fc(n,!1,t)},he=function(n,t){return fc(n,!0,t)},ec=/^([+-])?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?/,dit=function(n){ec.test(n)},ce=function(n){var i=ec.exec(n),t,r,u;if(i===null)throw{message:"Invalid duration value."};var f=i[2]||"0",e=i[3]||"0",o=s(i[4]||0),h=s(i[5]||0),c=s(i[6]||0),l=parseFloat(i[7]||0);if(f!=="0"||e!=="0")throw{message:"Unsupported duration value."};if(t
 =i[8],r=0,t){if(t.length>7)throw{message:"Cannot parse duration value to given precision."};r=a(t.substring(3),4,!0),t=a(t.substring(0,3),3,!0),t=s(t),r=s(r)}else t=0;return t+=l*1e3+c*6e4+h*36e5+o*864e5,i[1]==="-"&&(t=-t),u={ms:t,__edmType:"Edm.Time"},r&&(u.ns=r),u},oc=function(n){var t=n.substring(0,1),i,r;return t=t==="+"?1:-1,i=s(n.substring(1)),r=s(n.substring(n.indexOf(":")+1)),{d:t,h:i,m:r}},sc=function(n,i,r){n.method||(n.method="GET"),n.headers?oe(n.headers):n.headers={},n.headers.Accept===t&&(n.headers.Accept=i.accept),ot(n.data)&&n.body===t&&i.write(n,r),ot(n.headers.MaxDataServiceVersion)||(n.headers.MaxDataServiceVersion=i.maxDataServiceVersion||"1.0")},hc=function(n,i,r){var u,e,f;if(n&&typeof n=="object")for(u in n)e=n[u],f=hc(e,u,r),f=r(u,f,i),f!==e&&(e===t?delete n[u]:n[u]=f);return n},ib=function(n,t){return t("",hc(n,"",t))},bu=0,rb=function(n){return n.method&&n.method!=="GET"?!1:!0},ub=function(t){var i=n.document.createElement("IFRAME");i.style.display="none";v
 ar r=t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/\</g,"&lt;"),u='<html><head><script type="text/javascript" src="'+r+'"><\/script><\/head><body><\/body><\/html>',f=n.document.getElementsByTagName("BODY")[0];return f.appendChild(i),cc(i,u),i},fb=function(){if(n.XMLHttpRequest)return new n.XMLHttpRequest;var t;if(n.ActiveXObject)try{return new n.ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(i){try{return new n.ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(r){t=r}}else t={message:"XMLHttpRequest not supported"};throw t;},eb=function(n){return n.indexOf("http://")===0||n.indexOf("https://")===0||n.indexOf("file://")===0},ob=function(t){if(!eb(t))return!0;var i=n.location,r=i.protocol+"//"+i.host+"/";return t.indexOf(r)===0},sb=function(i,r){try{delete n[i]}catch(u){n[i]=t,r===bu-1&&(bu-=1)}},ku=function(n){return n&&(cc(n,""),n.parentNode.removeChild(n)),null},hb=function(n,t){for(var r=n.getAllResponseHeaders().split(/\r?\n/),u,i=0,f=r.length;i<f;i++)r[i]&&(u=r[i].split(": "),t[u[0
 ]]=u[1])},cc=function(n,t){var i=n.contentWindow?n.contentWindow.document:n.contentDocument.document;i.open(),i.write(t),i.close()};r.defaultHttpClient={callbackParameterName:"$callback",formatQueryString:"$format=json",enableJsonpCallback:!1,request:function(i,r,u){var y={},f=null,h=!1,s,a,w,b,k,d,l,v;y.abort=function(){(s=ku(s),h)||(h=!0,f&&(f.abort(),f=null),u({message:"Request aborted"}))};var p=function(){s=ku(s),h||(h=!0,f=null,u({message:"Request timed out"}))},c,e=i.requestUri,g=it(i.enableJsonpCallback,this.enableJsonpCallback),nt=it(i.callbackParameterName,this.callbackParameterName),tt=it(i.formatQueryString,this.formatQueryString);if(!g||ob(e)){if(f=fb(),f.onreadystatechange=function(){var t,n,o,s;h||f===null||f.readyState!==4||(t=f.statusText,n=f.status,n===1223&&(n=204,t="No Content"),o=[],hb(f,o),s={requestUri:e,statusCode:n,statusText:t,headers:o,body:f.responseText},h=!0,f=null,n>=200&&n<=299?r(s):u({message:"HTTP request failed",request:i,response:s}))},f.open(i.me
 thod||"GET",e,!0,i.user,i.password),i.headers)for(c in i.headers)f.setRequestHeader(c,i.headers[c]);i.timeoutMS&&(f.timeout=i.timeoutMS,f.ontimeout=p),f.send(i.body)}else{if(!rb(i))throw{message:"Request is not local and cannot be done through JSONP."};a=bu,bu+=1,w=a.toString(),b=!1,c="handleJSONP_"+w,n[c]=function(i){if(s=ku(s),!h){b=!0,n.clearTimeout(k),sb(c,a),n.ActiveXObject&&(i=n.JSON.parse(n.JSON.stringify(i)));var u;u=i.d===t?{"Content-Type":"application/json;odata=minimalmetadata",dataServiceVersion:"3.0"}:{"Content-Type":"application/json"},o(function(){ku(s),r({body:i,statusCode:200,headers:u})})}},d=i.timeoutMS?i.timeoutMS:12e4,k=n.setTimeout(p,d),l=nt+"=parent."+c,this.formatQueryString&&(l+="&"+tt),v=e.indexOf("?"),e=v===-1?e+"?"+l:v===e.length-1?e+l:e+"&"+l,s=ub(e)}return y}};var ci="3.0",nr=function(n){var t,r,i,f,u;if(!n)return null;for(t=n.split(";"),r={},i=1,f=t.length;i<f;i++)u=t[i].split("="),r[go(u[0])]=u[1];return{mediaType:go(t[0]),properties:r}},cb=function(n
 ){if(!n)return t;var r=n.mediaType,i;for(i in n.properties)r+=";"+i+"="+n.properties[i];return r},lc=function(n,t,i,r){var u={};return g(u,i),g(u,{contentType:n,dataServiceVersion:t,handler:r}),u},ac=function(n,t,i){if(n){var r=n.headers;r[t]||(r[t]=i)}},lb=function(n,t){if(n){var i=n.headers,r=i.DataServiceVersion;i.DataServiceVersion=r?ct(r,t):t}},vc=function(n,i){var r=n.headers;return r&&r[i]||t},yc=function(n){return nr(vc(n,"Content-Type"))},ab=/^\s?(\d+\.\d+);?.*$/,pc=function(n){var i=vc(n,"DataServiceVersion"),t;if(i&&(t=ab.exec(i),t&&t.length))return t[1]},wc=function(n,t){return n.accept.indexOf(t.mediaType)>=0},vb=function(n,i,r,u){var f;if(!r||!r.headers)return!1;var e=yc(r),s=pc(r)||"",o=r.body;return ot(o)?wc(n,e)?(f=lc(e,s,u,n),f.response=r,r.data=i(n,o,f),r.data!==t):!1:!1},yb=function(n,i,r,u){var e,o,f;return!r||!r.headers?!1:(e=yc(r),o=pc(r),(!e||wc(n,e))&&(f=lc(e,o,u,n),f.request=r,r.body=i(n,r.data,f),r.body!==t))?(lb(r,f.dataServiceVersion||"1.0"),ac(r,"Conten
 t-Type",cb(f.contentType)),ac(r,"MaxDataServiceVersion",n.maxDataServiceVersion),!0):!1},li=function(n,t,i,r){return{accept:i,maxDataServiceVersion:r,read:function(t,i){return vb(this,n,t,i)},write:function(n,i){return yb(this,t,n,i)}}},pb=function(n,t){return t},wb=function(n,i){return ot(i)?i.toString():t};r.textHandler=li(pb,wb,"text/plain",ci);var bc=fu+"www.opengis.net",ut=bc+"/gml",kc=bc+"/def/crs/EPSG/0/",dc="gml",yr=function(n,t,i){var r={type:n};return r[t]=i,r},le=function(n){if(e(n)&&n.length>=2){var t=n[0];n[0]=n[1],n[1]=t}return n},ae=function(n,t,i,r,u,f){var e=gc(n,i,r,u,f);return yr(t,"coordinates",e)},gc=function(n,t,i,r,e){var o=[];return p(n,function(n){var s,h,c;if(u(n)===ut){if(s=f(n),s===t){h=b(n,ut),h&&(c=r(h,e),c&&o.push(c));return}s===i&&p(n,function(n){if(u(n)===ut){var t=r(n,e);t&&o.push(t)}})}}),o},bb=function(n,t){var i=gc(n,"geometryMember","geometryMembers",il,t);return yr(ie,"geometries",i)},kb=function(n,t){return yr(kf,"coordinates",ve(n,t))},db=fun
 ction(n,t){return ae(n,ne,"curveMember","curveMembers",ve,t)},gb=function(n,t){return ae(n,gf,"pointMember","pointMembers",ye,t)},nk=function(n,t){return ae(n,te,"surfaceMember","surfaceMembers",nl,t)},tk=function(n,t){return yr(bf,"coordinates",ye(n,t))},ik=function(n,t){return yr(df,"coordinates",nl(n,t))},ve=function(n,t){var i=[];return p(n,function(n){var e=u(n),r;if(e===ut){if(r=f(n),r==="posList"){i=uk(n,t);return}if(r==="pointProperty"){i.push(rk(n,t));return}if(r==="pos"){i.push(pe(n,t));return}}}),i},ye=function(n,t){var i=b(n,ut,"pos");return i?pe(i,t):[]},rk=function(n,t){var i=b(n,ut,"Point");return i?ye(i,t):[]},nl=function(n,t){var i=[],r=!1;return p(n,function(n){if(u(n)===ut){var e=f(n);if(e==="exterior"){r=!0,i.unshift(tl(n,t));return}if(e==="interior"){i.push(tl(n,t));return}}}),!r&&i.length>0&&i.unshift([[]]),i},tl=function(n,t){var i=[];return p(n,function(n){u(n)===ut&&f(n)==="LinearRing"&&(i=ve(n,t))}),i},uk=function(n,t){var f=pe(n,!1),e=f.length,r,i,u;if(e%2
 !=0)throw{message:"GML posList element has an uneven number of numeric values"};for(r=[],i=0;i<e;i+=2)u=f.slice(i,i+2),r.push(t?le(u):u);return r},pe=function(n,t){var u=[],o=" \t\r\n",r=k(n),f;if(r)for(var s=r.length,e=0,i=0;i<=s;)o.indexOf(r.charAt(i))!==-1&&(f=r.substring(e,i),f&&u.push(parseFloat(f)),e=i+1),i++;return t?le(u):u},il=function(n,t){var o=f(n),i,u,r,e;switch(o){case"Point":i=tk;break;case"Polygon":i=ik;break;case"LineString":i=kb;break;case"MultiPoint":i=gb;break;case"MultiCurve":i=db;break;case"MultiSurface":i=nk;break;case"MultiGeometry":i=bb;break;default:throw{message:"Unsupported element: "+o,element:n};}if(u=i(n,t),r=st(n,"srsName",ut)||st(n,"srsName"),r){if(r.indexOf(kc)!==0)throw{message:"Unsupported srs name: "+r,element:n};e=r.substring(kc.length),e&&(u.crs={type:"name",properties:{name:"EPSG:"+e}})}return u},rl=function(n,t,i,r){var u,o,e,s,f,h,c;switch(i){case bf:u=fk;break;case kf:u=ek;break;case df:u=ok;break;case gf:u=sk;break;case ne:u=hk;break;case 
 te:u=ck;break;case ie:u=ak;break;default:return null}return o=u(n,t,r),e=t.crs,e&&e.type==="name"&&(s=e.properties,f=s&&s.name,f&&f.indexOf("ESPG:")===0&&f.length>5&&(h=f.substring(5),c=si(n,null,"srsName",dc+h),l(o,c))),o},kt=function(n,t,i){return lr(n,ut,pt(dc,t),i)},ul=function(n,t,i){var r=e(t)?t:[];return r=i?le(r):r,kt(n,"pos",r.join(" "))},fl=function(n,t,i,r){var f=kt(n,t),u,o;if(e(i)){for(u=0,o=i.length;u<o;u++)l(f,ul(n,i[u],r));o===0&&l(f,kt(n,"posList"))}return f},el=function(n,t,i){return kt(n,"Point",ul(n,t,i))},ol=function(n,t,i){return fl(n,"LineString",t,i)},sl=function(n,t,i,r){var u=kt(n,t),f;return e(i)&&i.length>0&&(f=fl(n,"LinearRing",i,r),l(u,f)),u},hl=function(n,t,i){var f=t&&t.length,u=kt(n,"Polygon"),r;if(e(t)&&f>0)for(l(u,sl(n,"exterior",t[0],i)),r=1;r<f;r++)l(u,sl(n,"interior",t[r],i));return u},fk=function(n,t,i){return el(n,t.coordinates,i)},ek=function(n,t,i){return ol(n,t.coordinates,i)},ok=function(n,t,i){return hl(n,t.coordinates,i)},du=function(n,t
 ,i,r,u,f){var h=r&&r.length,c=kt(n,t),s,o;if(e(r)&&h>0){for(s=kt(n,i),o=0;o<h;o++)l(s,u(n,r[o],f));l(c,s)}return c},sk=function(n,t,i){return du(n,"MultiPoint","pointMembers",t.coordinates,el,i)},hk=function(n,t,i){return du(n,"MultiCurve","curveMembers",t.coordinates,ol,i)},ck=function(n,t,i){return du(n,"MultiSurface","surfaceMembers",t.coordinates,hl,i)},lk=function(n,t,i){return rl(n,t,t.type,i)},ak=function(n,t,i){return du(n,"MultiGeometry","geometryMembers",t.geometries,lk,i)},gu="application/xml",dt=fu+"schemas.microsoft.com/ado/",ai=dt+"2007/08/dataservices",nf=dt+"2007/06/edmx",vk=dt+"2006/04/edm",yk=dt+"2007/05/edm",pk=dt+"2008/01/edm",wk=dt+"2008/09/edm",bk=dt+"2009/08/edm",kk=dt+"2009/11/edm",lt=ai,nt=ai+"/metadata",we=ai+"/related/",cl=ai+"/scheme",ll="d",be="m",gt=function(n,t){var i={name:f(n),value:n.value};return i[t?"namespaceURI":"namespace"]=u(n),i},pr=function(n,t){for(var s=[],h=[],c=n.attributes,e,i,o,r=0,l=c.length;r<l;r++)e=c[r],u(e)!==hr&&s.push(gt(e,t));f
 or(i=n.firstChild;i!=null;)i.nodeType===1&&h.push(pr(i,t)),i=i.nextSibling;return o={name:f(n),value:k(n),attributes:s,children:h},o[t?"namespaceURI":"namespace"]=u(n),o},ke=function(n){return u(n)===lt&&f(n)==="element"},al=function(n,t){return{type:n,extensions:t}},dk=function(n){var t,i;return b(n,ut)?et:(t=b(n,lt),!t)?ar:ke(t)&&(i=iw(t,lt),i&&ke(i))?"Collection()":null},vl=function(n){var t=null,i=!1,r=[];return wi(n,function(n){var e=u(n),o=f(n),s=ki(n);if(e===nt){if(o==="null"){i=s.toLowerCase()==="true";return}if(o==="type"){t=s;return}}if(e!==pi&&e!==hr){r.push(gt(n,!0));return}}),{type:!t&&i?ar:t,isNull:i,extensions:r}},yl=function(n){if(u(n)!==lt)return null;var e=f(n),t=vl(n),o=t.isNull,i=t.type,r=al(i,t.extensions),s=o?null:pl(n,i,r);return{name:e,value:s,metadata:r}},pl=function(n,t,i){t||(t=dk(n),i.type=t);var r=re(t);return r||ue(t)?gk(n,t,r):fe(t)?wl(n,t):yu(t)?td(n,t,i):nd(n,t,i)},gk=function(n,t,i){var u=b(n,ut),r=il(u,i);return r.__metadata={type:t},r},wl=function
 (n,t){var i=ki(n)||"";switch(t){case ls:return se(i);case cs:case vs:case ps:case ks:case ar:return i;case as:case ws:case bs:case ds:return s(i);case ys:case gs:return parseFloat(i);case au:return ce(i);case cu:return wu(i);case lu:return he(i)}return i},nd=function(n,t,i){var r={__metadata:{type:t}};return p(n,function(n){var t=yl(n),u=t.name;i.properties=i.properties||{},i.properties[u]=t.metadata,r[u]=t.value}),r},td=function(n,t,i){var r=[],u=i.elements=[],f=vu(t);return p(n,function(n){if(ke(n)){var t=vl(n),o=t.extensions,i=t.type||f,e=al(i,o),s=pl(n,i,e);r.push(s),u.push(e)}}),{__metadata:{type:t==="Collection()"?null:t},results:r}},id=function(n,i){if(u(n)===lt){i=rt(n,i);var r=f(n);if(r==="links")return rd(n,i);if(r==="uri")return bl(n,i)}return t},rd=function(n,t){var i=[];return p(n,function(n){f(n)==="uri"&&u(n)===lt&&i.push(bl(n,t))}),{results:i}},bl=function(n,t){var i=k(n)||"";return{uri:c(i,t)}},ud=function(n,t){return t===et||t===ht?n&&n.type:t===oh||t===nh?bf:t===s
 h||t===th?kf:t===hh||t===ih?df:t===ch||t===rh?ie:t===lh||t===uh?te:t===ah||t===fh?ne:t===vh||t===eh?gf:null},kl=function(n,t,i){return lr(n,nt,pt(be,t),i)},de=function(n,t,i){return si(n,nt,pt(be,t),i)},dl=function(n,t,i){return lr(n,lt,pt(ll,t),i)},fd=function(n,t){return t===cu||t===lu||lf(n)?ph(n):t===au?wh(n):n.toString()},at=function(n,t){return{element:n,dsv:t}},wr=function(n,t,i,r){var u=i?de(n,"type",i):null,f=dl(n,t,u);return su(f,r)},ed=function(n,t,i,r){var u=fd(i,r),f=wr(n,t,r,u);return at(f,"1.0")},od=function(n,t,i,r){var u=de(n,"null","true"),f=wr(n,t,i,u),e=gi(i,r)?"2.0":"1.0";return at(f,e)},sd=function(n,t,i,r,u,f,o){var c=vu(r),a=e(i)?i:i.results,v=r?{type:c}:{},h,s,y,p,w;for(v.properties=u.properties,h=wr(n,t,c?r:null),s=0,y=a.length;s<y;s++)p=a[s],w=ge(n,"element",p,v,f,o),l(h,w.element);return at(h,"3.0")},hd=function(n,t,i,r,u,f,e){var h=wr(n,t,r),a=u.properties||{},v=gi(r,e)||{},s="1.0",o;for(o in i)if(o!=="__metadata"){var y=i[o],p=wt(v.property,o),w=a[o]||{
 },c=ge(n,o,y,w,p,e);s=ct(s,c.dsv),l(h,c.element)}return at(h,s)},cd=function(n,t,i,r,u){var f=ud(i,r),e=rl(n,i,f,u),o=wr(n,t,r,e);return at(o,"3.0")},ge=function(n,t,i,r,u,f){var e=hs(i,r,u),o,s;return pu(i)?ed(n,t,i,e||ar):(o=re(e),o||ue(e))?cd(n,t,i,e,o):kh(i,e)?sd(n,t,i,e,r,u,f):nc(i)?null:(s=tc(i,u),s!==null)?null:i===null?od(n,t,e):hd(n,t,i,e,r,u,f)},ld=function(n){if(n&&af(n)){var t=os();return l(t,dl(t,"uri",n.uri))}},ad=function(n,t){if(t){var r=ou(t),i=b(r);if(i)return id(i)}},vd=function(n,i,r){var u=r.contentType=r.contentType||nr(gu);return u&&u.mediaType===gu?wf(ld(i)):t};r.xmlHandler=li(ad,vd,gu,ci);var gl="a",ni=sr+"2005/Atom",br=sr+"2007/app",na=ai+"/edit-media/",ta=ai+"/mediaresource/",ia=ai+"/relatedlinks/",ra=["application/atom+xml","application/atomsvc+xml","application/xml"],ua=ra[0],yd=[ni,br,pi,hr],pd={SyndicationAuthorEmail:"author/email",SyndicationAuthorName:"author/name",SyndicationAuthorUri:"author/uri",SyndicationContributorEmail:"contributor/email",Synd
 icationContributorName:"contributor/name",SyndicationContributorUri:"contributor/uri",SyndicationPublished:"published",SyndicationRights:"rights",SyndicationSummary:"summary",SyndicationTitle:"title",SyndicationUpdated:"updated"},wd=function(n){return pd[n]||n},kr=function(n){return!er(yd,n)},fa=function(n,t,i,r,u){var f;if(u=u||"",f=n["FC_TargetPath"+u],!f)return null;var e=n["FC_SourcePath"+u],s=wd(f),o=r?r+(e?"/"+e:""):e,l=o&&tg(i,t,o),h=n["FC_NsUri"+u]||null,c=n["FC_NsPrefix"+u]||null,a=n["FC_KeepInContent"+u]||"";return f!==s&&(h=ni,c=gl),{contentKind:n["FC_ContentKind"+u],keepInContent:a.toLowerCase()==="true",nsPrefix:c,nsURI:h,propertyPath:o,propertyType:l,entryPath:s}},ea=function(n,t,i){for(var c=[],l,r,f,u,e;n;){for(l=n.FC_SourcePath,r=fa(n,n,t),r&&i(r),f=n.property||[],u=0,e=f.length;u<e;u++)for(var o=f[u],s=0,h="";r=fa(o,n,t,o.name,h);)i(r),s++,h="_"+s;n=bt(n.baseType,t)}return c},tf=function(n){var t=[];return wi(n,function(n){var i=u(n);kr(i)&&t.push(gt(n,!0))}),t},oa
 =function(n){return pr(n,!0)},sa=function(n,t,i){var e=u(n),r=f(n);if(e===br&&r==="service")return cg(n,t);if(e===ni){if(r==="feed")return bd(n,t,i);if(r==="entry")return va(n,t,i)}},ha=function(n,t){var r=[],i={extensions:r};return wi(n,function(e){var o=f(e),s=u(e),h=ki(e);if(s===null){if(o==="title"||o==="metadata"){i[o]=h;return}if(o==="target"){i.target=c(h,rt(n,t));return}}kr(s)&&r.push(gt(e,!0))}),i},ca=function(n,t,i){var r=i.actions=i.actions||[];r.push(ha(n,t))},la=function(n,t,i){var r=i.functions=i.functions||[];r.push(ha(n,t))},bd=function(n,t,i){var o=tf(n),r={feed_extensions:o},s=[],e={__metadata:r,results:s};return t=rt(n,t),p(n,function(n){var l=u(n),h=f(n);if(l===nt){if(h==="count"){e.__count=parseInt(k(n),10);return}if(h==="action"){ca(n,t,r);return}if(h==="function"){la(n,t,r);return}}if(kr(l)){o.push(pr(n));return}if(h==="entry"){s.push(va(n,t,i));return}if(h==="link"){kd(n,e,t);return}if(h==="id"){r.uri=c(k(n),t),r.uri_extensions=tf(n);return}if(h==="title"){r.
 title=k(n)||"",r.title_extensions=tf(n);return}}),e},kd=function(n,t,i){var r=aa(n,i),f=r.href,e=r.rel,o=r.extensions,u=t.__metadata;if(e==="next"){t.__next=f,u.next_extensions=o;return}if(e==="self"){u.self=f,u.self_extensions=o;return}},aa=function(n,t){t=rt(n,t);var r=[],i={extensions:r,baseURI:t};if(wi(n,function(n){var s=u(n),e=f(n),o=n.value;if(e==="href"){i.href=c(o,t);return}if(e==="type"||e==="rel"){i[e]=o;return}kr(s)&&r.push(gt(n,!0))}),!i.href)throw{error:"href attribute missing on link element",element:n};return i},dd=function(n,i){if(n.indexOf("/")===-1)return i[n];for(var u=n.split("/"),r=0,f=u.length;r<f;r++){if(i===null)return t;if(i=i[u[r]],i===t)return i}return i},gd=function(n,i,r,u){var o,s,f,h,e;if(n.indexOf("/")===-1)i[n]=r,o=n;else{for(s=n.split("/"),f=0,h=s.length-1;f<h;f++){if(e=i[s[f]],e===t)e={},i[s[f]]=e;else if(e===null)return;i=e}o=s[f],i[o]=r}if(u){var c=i.__metadata=i.__metadata||{},l=c.properties=c.properties||{},a=l[o]=l[o]||{};a.type=u}},ng=functi
 on(n,t,i){var e=n.propertyPath,r,u,f;n.keepInContent||dd(e,i)===null||(r=nw(t,n.nsURI,n.entryPath),r)&&(u=n.propertyType,f=n.contentKind==="xhtml"?ew(r):wl(r,u||"Edm.String"),gd(e,i,f,u))},tg=function(n,t,i){for(var s=i.split("/"),u,h,f,e,o,r;t;){for(f=t,u=0,h=s.length;u<h;u++){if(e=f.property,!e)break;if(o=wt(e,s[u]),!o)break;if(r=o.type,!r||fe(r))return r||null;if(f=gi(r,n),!f)return null}t=bt(t.baseType,n)}return null},va=function(n,t,i){var r={},e={__metadata:r},o=st(n,"etag",nt),s;return o&&(r.etag=o),t=rt(n,t),p(n,function(n){var s=u(n),o=f(n);if(s===ni){if(o==="id"){ig(n,r,t);return}if(o==="category"){rg(n,r);return}if(o==="content"){ug(n,e,r,t);return}if(o==="link"){fg(n,e,r,t,i);return}return}if(s===nt){if(o==="properties"){wa(n,e,r);return}if(o==="action"){ca(n,t,r);return}if(o==="function"){la(n,t,r);return}}}),s=bt(r.type,i),ea(s,i,function(t){ng(t,n,e)}),e},ig=function(n,t,i){t.uri=c(k(n),rt(n,i)),t.uri_extensions=tf(n)},rg=function(n,t){if(st(n,"scheme")===cl){if(t.typ
 e)throw{message:"Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry",element:n};var i=[];wi(n,function(n){var t=u(n),r=f(n);if(!t){r!=="scheme"&&r!=="term"&&i.push(gt(n,!0));return}kr(t)&&i.push(gt(n,!0))}),t.type=st(n,"term"),t.type_extensions=i}},ug=function(n,t,i,r){var e=st(n,"src"),o=st(n,"type");if(e){if(!o)throw{message:"Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",element:n};i.media_src=c(e,rt(n,r)),i.content_type=o}p(n,function(r){if(e)throw{message:"Invalid AtomPub document: content element must not have child elements if the src attribute is specified",element:n};u(r)===nt&&f(r)==="properties"&&wa(r,t,i)})},fg=function(n,t,i,r,u){var f=aa(n,r),e=f.rel,s=f.href,o=f.extensions;if(e==="self"){i.self=s,i.self_link_extensions=o;return}if(e==="edit"){i.edit=s,i.edit_link_extensions=o;return}if(e==="edit-media"){i.edit_media=f.href,i.edit_media_extensio
 ns=o,pa(f,i);return}if(e.indexOf(na)===0){sg(f,t,i);return}if(e.indexOf(ta)===0){hg(f,t,i);return}if(e.indexOf(we)===0){og(n,f,t,i,u);return}if(e.indexOf(ia)===0){eg(f,i);return}},eg=function(n,t){var r=n.rel.substring(ia.length),i;t.properties=t.properties||{},i=t.properties[r]=t.properties[r]||{},i.associationuri=n.href,i.associationuri_extensions=n.extensions},og=function(n,t,i,r,u){var e,o=b(n,nt,"inline"),s,h,f,c;o?(s=b(o),h=rt(o,t.baseURI),e=s?sa(s,h,u):null):e={__deferred:{uri:t.href}},f=t.rel.substring(we.length),i[f]=e,r.properties=r.properties||{},c=r.properties[f]=r.properties[f]||{},c.extensions=t.extensions},sg=function(n,t,i){var o=n.rel.substring(na.length),f=ya(o,t,i),r=f.value,u=f.metadata,e=n.href;r.edit_media=e,r.content_type=n.type,u.edit_media_extensions=n.extensions,r.media_src=r.media_src||e,u.media_src_extensions=u.media_src_extensions||[],pa(n,r)},hg=function(n,t,i){var f=n.rel.substring(ta.length),r=ya(f,t,i),u=r.value,e=r.metadata;u.media_src=n.href,e.medi
 a_src_extensions=n.extensions,u.content_type=n.type},ya=function(n,t,i){i.properties=i.properties||{};var u=i.properties[n],r=t[n]&&t[n].__mediaresource;return r||(r={},t[n]={__mediaresource:r},i.properties[n]=u={}),{value:r,metadata:u}},pa=function(n,t){for(var r=n.extensions,i=0,u=r.length;i<u;i++)if(r[i].namespaceURI===nt&&r[i].name==="etag"){t.media_etag=r[i].value,r.splice(i,1);return}},wa=function(n,t,i){p(n,function(n){var r=yl(n),u,f;r&&(u=r.name,f=i.properties=i.properties||{},f[u]=r.metadata,t[u]=r.value)})},cg=function(n,t){var i=[],r=[];if(t=rt(n,t),p(n,function(n){if(u(n)===br&&f(n)==="workspace"){i.push(lg(n,t));return}r.push(pr(n))}),i.length===0)throw{message:"Invalid AtomPub service document: No workspace element found.",element:n};return{workspaces:i,extensions:r}},lg=function(n,i){var e=[],o=[],r;return i=rt(n,i),p(n,function(n){var s=u(n),h=f(n);if(s===ni&&h==="title"){if(r!==t)throw{message:"Invalid AtomPub service document: workspace has more than one child tit
 le element",element:n};r=k(n);return}if(s===br){h==="collection"&&e.push(ag(n,i));return}o.push(oa(n))}),{title:r||"",collections:e,extensions:o}},ag=function(n,i){var r=st(n,"href"),o,e;if(!r)throw{message:"Invalid AtomPub service document: collection has no href attribute",element:n};if(i=rt(n,i),r=c(r,rt(n,i)),o=[],p(n,function(i){var r=u(i),s=f(i);if(r===ni){if(s==="title"){if(e!==t)throw{message:"Invalid AtomPub service document: collection has more than one child title element",element:i};e=k(i)}return}r!==br&&o.push(oa(n))}),!e)throw{message:"Invalid AtomPub service document: collection has no title element",element:n};return{title:e,href:r,extensions:o}},ti=function(n,t,i){return lr(n,ni,pt(gl,t),i)},tr=function(n,t,i){return si(n,null,t,i)},vg=function(n){var t,e,i,o,r;if(n.childNodes.length>0)return!1;for(t=!0,e=n.attributes,i=0,o=e.length;i<o&&t;i++)r=e[i],t=t&&bp(r)||u(r)==nt&&f(r)==="type";return t},yg=function(n,t,i,r,u){var s=null,e=null,f=null,o="",h;return i!=="defe
 rred"?(s=tr(n,"type","application/atom+xml;type="+i),e=kl(n,"inline"),r&&(o=r.__metadata&&r.__metadata.uri||"",f=ba(n,r,u)||no(n,r,u),l(e,f.element))):o=r.__deferred.uri,h=ti(n,"link",[tr(n,"href",o),tr(n,"rel",c(t,we)),s,e]),at(h,f?f.dsv:"1.0")},pg=function(n,t,i,r,u,f){var e,o;return nc(i)?null:(e=ge(n,t,i,r,u,f),e||(o=tc(i,u),e=yg(n,t,o,i,f)),e)},wg=function(n,t,i,r){var u=fs(i,lt,r.propertyPath),l=u&&bi(u,"null",nt),o,s="1.0",f,e,h,c;if(l&&l.value==="true")return s;if(u&&(o=k(u)||"",!r.keepInContent))for(s="2.0",f=u.parentNode,e=f,f.removeChild(u);e!==i&&vg(e);)f=e.parentNode,f.removeChild(e),e=f;return(h=fw(n,t,r.nsURI,r.nsPrefix,r.entryPath),h.nodeType===2)?(h.value=o,s):(c=r.contentKind,su(h,[c&&si(n,null,"type",c),c==="xhtml"?rw(n,o):o]),s)},no=function(n,t,i){var e=t.__metadata||{},b=e.properties||{},y=e.etag,p=e.uri,s=e.type,o=bt(s,i),h=kl(n,"properties"),c=ti(n,"entry",[ti(n,"author",ti(n,"name")),y&&de(n,"etag",y),p&&ti(n,"id",p),s&&ti(n,"category",[tr(n,"term",s),tr(n,"
 scheme",cl)]),ti(n,"content",[tr(n,"type","application/xml"),h])]),f="1.0",r,v,w;for(r in t)if(r!=="__metadata"){var k=b[r]||{},d=o&&(wt(o.property,r)||wt(o.navigationProperty,r)),a=pg(n,r,t[r],k,d,i);a&&(v=a.element,w=u(v)===ni?c:h,l(w,v),f=ct(f,a.dsv))}return ea(o,i,function(t){var i=wg(n,c,h,t);f=ct(f,i)}),at(c,f)},ba=function(n,t,i){var f=e(t)?t:t.results,r,o,u,h,s;if(!f)return null;for(r="1.0",o=ti(n,"feed"),u=0,h=f.length;u<h;u++)s=no(n,f[u],i),l(o,s.element),r=ct(r,s.dsv);return at(o,r)},bg=function(n,t){var u,i,r,f;return n&&(u=vr(n)&&ba||af(n)&&no,u&&(i=os(),r=u(i,n,t),r))?(f=r.element,su(f,[ss(i,nt,be),ss(i,lt,ll)]),at(l(i,f),r.dsv)):null},kg=function(n,t,i){if(t){var u=ou(t),r=b(u);if(r)return sa(r,null,i.metadata)}},dg=function(n,t,i){var u=i.contentType=i.contentType||nr(ua),r;if(u&&u.mediaType===ua&&(r=bg(t,i.metadata),r))return i.dataServiceVersion=ct(i.dataServiceVersion||"1.0",r.dsv),wf(r.element)};r.atomHandler=li(kg,dg,ra.join(","),ci);var i=function(n,t,i,r){retu
 rn{attributes:n,elements:t,text:i||!1,ns:r}},tt={elements:{Annotations:i(["Target","Qualifier"],["TypeAnnotation*","ValueAnnotation*"]),Association:i(["Name"],["End*","ReferentialConstraint","TypeAnnotation*","ValueAnnotation*"]),AssociationSet:i(["Name","Association"],["End*","TypeAnnotation*","ValueAnnotation*"]),Binary:i(null,null,!0),Bool:i(null,null,!0),Collection:i(null,["String*","Int*","Float*","Decimal*","Bool*","DateTime*","DateTimeOffset*","Guid*","Binary*","Time*","Collection*","Record*"]),CollectionType:i(["ElementType","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"],["CollectionType","ReferenceType","RowType","TypeRef"]),ComplexType:i(["Name","BaseType","Abstract"],["Property*","TypeAnnotation*","ValueAnnotation*"]),DateTime:i(null,null,!0),DateTimeOffset:i(null,null,!0),Decimal:i(null,null,!0),DefiningExpression:i(null,null,!0),Dependent:i(["Role"],["PropertyRef*"]),Documentation:i(null,null,!0),End:i(["Type","Role
 ","Multiplicity","EntitySet"],["OnDelete"]),EntityContainer:i(["Name","Extends"],["EntitySet*","AssociationSet*","FunctionImport*","TypeAnnotation*","ValueAnnotation*"]),EntitySet:i(["Name","EntityType"],["TypeAnnotation*","ValueAnnotation*"]),EntityType:i(["Name","BaseType","Abstract","OpenType"],["Key","Property*","NavigationProperty*","TypeAnnotation*","ValueAnnotation*"]),EnumType:i(["Name","UnderlyingType","IsFlags"],["Member*"]),Float:i(null,null,!0),Function:i(["Name","ReturnType"],["Parameter*","DefiningExpression","ReturnType","TypeAnnotation*","ValueAnnotation*"]),FunctionImport:i(["Name","ReturnType","EntitySet","IsSideEffecting","IsComposable","IsBindable","EntitySetPath"],["Parameter*","ReturnType","TypeAnnotation*","ValueAnnotation*"]),Guid:i(null,null,!0),Int:i(null,null,!0),Key:i(null,["PropertyRef*"]),LabeledElement:i(["Name"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Nu
 ll"]),Member:i(["Name","Value"]),NavigationProperty:i(["Name","Relationship","ToRole","FromRole","ContainsTarget"],["TypeAnnotation*","ValueAnnotation*"]),Null:i(null,null),OnDelete:i(["Action"]),Path:i(null,null,!0),Parameter:i(["Name","Type","Mode","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","SRID"],["CollectionType","ReferenceType","RowType","TypeRef","TypeAnnotation*","ValueAnnotation*"]),Principal:i(["Role"],["PropertyRef*"]),Property:i(["Name","Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","ConcurrencyMode","CollectionKind","SRID"],["CollectionType","ReferenceType","RowType","TypeAnnotation*","ValueAnnotation*"]),PropertyRef:i(["Name"]),PropertyValue:i(["Property","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time
 ","Collection","Record","LabeledElement","Null"]),ReferenceType:i(["Type"]),ReferentialConstraint:i(null,["Principal","Dependent"]),ReturnType:i(["ReturnType","Type","EntitySet"],["CollectionType","ReferenceType","RowType"]),RowType:i(["Property*"]),String:i(null,null,!0),Schema:i(["Namespace","Alias"],["Using*","EntityContainer*","EntityType*","Association*","ComplexType*","Function*","ValueTerm*","Annotations*"]),Time:i(null,null,!0),TypeAnnotation:i(["Term","Qualifier"],["PropertyValue*"]),TypeRef:i(["Type","Nullable","DefaultValue","MaxLength","FixedLength","Precision","Scale","Unicode","Collation","SRID"]),Using:i(["Namespace","Alias"]),ValueAnnotation:i(["Term","Qualifier","Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time"],["Path","String","Int","Float","Decimal","Bool","DateTime","DateTimeOffset","Guid","Binary","Time","Collection","Record","LabeledElement","Null"]),ValueTerm:i(["Name","Type"],["TypeAnnotation*","ValueAnnotation
 *"]),Edmx:i(["Version"],["DataServices","Reference*","AnnotationsReference*"],!1,nf),DataServices:i(null,["Schema*"],!1,nf)}},ka=["m:FC_ContentKind","m:FC_KeepInContent","m:FC_NsPrefix","m:FC_NsUri","m:FC_SourcePath","m:FC_TargetPath"];tt.elements.Property.attributes=tt.elements.Property.attributes.concat(ka),tt.elements.EntityType.attributes=tt.elements.EntityType.attributes.concat(ka),tt.elements.Edmx={attributes:["Version"],elements:["DataServices"],ns:nf},tt.elements.DataServices={elements:["Schema*"],ns:nf},tt.elements.EntityContainer.attributes.push("m:IsDefaultEntityContainer"),tt.elements.Property.attributes.push("m:MimeType"),tt.elements.FunctionImport.attributes.push("m:HttpMethod"),tt.elements.FunctionImport.attributes.push("m:IsAlwaysBindable"),tt.elements.EntityType.attributes.push("m:HasStream"),tt.elements.DataServices.attributes=["m:DataServiceVersion","m:MaxDataServiceVersion"];var da=function(n){if(!n)return n;if(n.length>1){var t=n.substr(0,2);return t===t.toUpper
 Case()?n:n.charAt(0).toLowerCase()+n.substr(1)}return n.charAt(0).toLowerCase()},gg=function(n,t){var r,u,e,i,f,o;if(t==="Documentation")return{isArray:!0,propertyName:"documentation"};if(r=n.elements,!r)return null;for(u=0,e=r.length;u<e;u++)if(i=r[u],f=!1,i.charAt(i.length-1)==="*"&&(f=!0,i=i.substr(0,i.length-1)),t===i)return o=da(i),{isArray:f,propertyName:o};return null},nn=/^(m:FC_.*)_[0-9]+$/,ga=function(n){return n===vk||n===yk||n===pk||n===wk||n===bk||n===kk},to=function(n){var o=f(n),e=u(n),i=tt.elements[o];if(!i)return null;if(i.ns){if(e!==i.ns)return null}else if(!ga(e))return null;var t={},r=[],s=i.attributes||[];return wi(n,function(n){var c=f(n),e=u(n),l=n.value,i,o,h;e!==hr&&(i=null,o=!1,ga(e)||e===null?i="":e===nt&&(i="m:"),i!==null&&(i+=c,h=nn.exec(i),h&&(i=h[1]),er(s,i)&&(o=!0,t[da(c)]=l)),o||r.push(gt(n)))}),p(n,function(n){var o=f(n),u=gg(i,o),e;u?u.isArray?(e=t[u.propertyName],e||(e=[],t[u.propertyName]=e),e.push(to(n))):t[u.propertyName]=to(n):r.push(pr(n))}),
 i.text&&(t.text=k(n)),r.length&&(t.extensions=r),t},nv=function(n,i){var r=ou(i),u=b(r);return to(u)||t};r.metadataHandler=li(nv,null,gu,ci);var tv="o",io="f",iv="p",rv="c",uv="s",fv="l",tn="odata",ii=tn+".",rn="@"+ii+"bind",ro=ii+"metadata",ev=ii+"navigationLinkUrl",ir=ii+"type",rf={readLink:"self",editLink:"edit",nextLink:"__next",mediaReadLink:"media_src",mediaEditLink:"edit_media",mediaContentType:"content_type",mediaETag:"media_etag",count:"__count",media_src:"mediaReadLink",edit_media:"mediaEditLink",content_type:"mediaContentType",media_etag:"mediaETag",url:"uri"},h={metadata:"odata.metadata",count:"odata.count",next:"odata.nextLink",id:"odata.id",etag:"odata.etag",read:"odata.readLink",edit:"odata.editLink",mediaRead:"odata.mediaReadLink",mediaEdit:"odata.mediaEditLink",mediaEtag:"odata.mediaETag",mediaContentType:"odata.mediaContentType",actions:"odata.actions",functions:"odata.functions",navigationUrl:"odata.navigationLinkUrl",associationUrl:"odata.associationLinkUrl",type
 :"odata.type"},un=function(n){if(n.indexOf(".")>0){var t=n.indexOf("@"),r=t>-1?n.substring(0,t):null,i=n.substring(t+1);return{target:r,name:i,isOData:i.indexOf(ii)===0}}return null},uo=function(n,t,i,r,u){return d(t)&&t[ir]||i&&i[n+"@"+ir]||r&&r.type||bw(r,u)||null},fo=function(n,t){return t?wt(t.property,n)||wt(t.navigationProperty,n):null},ov=function(n){return d(n)&&ii+"id"in n},fn=function(n,t,i){if(!!t[n+"@"+ev]||i&&i.relationship)return!0;var r=e(t[n])?t[n][0]:t[n];return ov(r)},eo=function(n){return fe(n)||re(n)||ue(n)},ri=function(n,t,i,r,u){var f,e;for(f in n)if(f.indexOf(".")>0&&f.charAt(0)!=="#"&&(e=un(f),e)){var c=e.name,o=e.target,s=null,h=null;o&&(s=fo(o,r),h=uo(o,n[o],n,s,u)),e.isOData?en(c,o,h,n[f],n,t,i):t[f]=n[f]}return t},en=function(n,t,i,r,u,f,e){var o=n.substring(ii.length);switch(o){case"navigationLinkUrl":cn(o,t,i,r,u,f,e);return;case"nextLink":case"count":sn(o,t,r,f,e);return;case"mediaReadLink":case"mediaEditLink":case"mediaContentType":case"mediaETag":hn(
 o,t,i,r,f,e);return;default:on(o,t,r,f,e);return}},on=function(n,t,i,r,u){var f=r.__metadata=r.__metadata||{},e=rf[n]||n,s,o;if(n==="editLink"){f.uri=c(i,u),f[e]=f.uri;return}if((n==="readLink"||n==="associationLinkUrl")&&(i=c(i,u)),t){if(s=f.properties=f.properties||{},o=s[t]=s[t]||{},n==="type"){o[e]=o[e]||i;return}o[e]=i;return}f[e]=i},sn=function(n,t,i,r,u){var f=rf[n],e=t?r[t]:r;e[f]=n==="nextLink"?c(i,u):i},hn=function(n,t,i,r,u,f){var e=u.__metadata=u.__metadata||{},h=rf[n],o,s;if((n==="mediaReadLink"||n==="mediaEditLink")&&(r=c(r,f)),t){o=e.properties=e.properties||{},s=o[t]=o[t]||{},s.type=s.type||i,u.__metadata=e,u[t]=u[t]||{__mediaresource:{}},u[t].__mediaresource[h]=r;return}e[h]=r},cn=function(n,t,i,r,u,f,e){var s=f.__metadata=f.__metadata||{},h=s.properties=s.properties||{},o=h[t]=h[t]||{},l=c(r,e);if(u.hasOwnProperty(t)){o.navigationLinkUrl=l;return}f[t]={__deferred:{uri:l}},o.type=o.type||i},oo=function(n,t,i,r,u,f,o){if(typeof n=="string")return ln(n,t,o);if(!eo(t))
 {if(e(n))return sv(n,t,i,r,f,o);if(d(n))return an(n,t,i,r,f,o)}return n},ln=function(n,t,i){switch(t){case au:return ce(n);case cu:return wu(n,!1);case lu:return he(n,!1)}return i?wu(n,!0)||he(n,!0)||n:n},sv=function(n,t,i,r,u,f){for(var a=vu(t),o=[],h=[],e=0,c=n.length;e<c;e++){var s=uo(null,n[e])||a,l={type:s},v=oo(n[e],s,l,r,null,u,f);eo(s)||pu(n[e])||o.push(l),h.push(v)}return o.length>0&&(i.elements=o),{__metadata:{type:t},results:h}},an=function(n,t,i,r,u,f){var e=uf(n,{type:t},r,u,f),o=e.__metadata,s=o.properties;return s&&(i.properties=s,delete o.properties),e},vn=function(n,t,i,r,u){return e(n)?cv(n,t,i,r,u):d(n)?uf(n,t,i,r,u):null},uf=function(n,i,r,u,f){var d,v,g,o,y,h,c,nt;i=i||{};var l=n[ir]||i.type||null,s=bt(l,u),k=!0;s||(k=!1,s=gi(l,u));var p={type:l},a={__metadata:p},w={},e;if(k&&s&&i.entitySet&&i.contentTypeOdata=="minimalmetadata"){for(d=r.substring(0,r.lastIndexOf("$metadata")),e=null,s.key||(e=s);!!e&&!e.key&&e.baseType;)e=bt(e.baseType,u);(s.key||!!e&&e.key)&&(
 v=s.key?lv(n,s):lv(n,e),v&&(g={key:v,entitySet:i.entitySet,functionImport:i.functionImport,containerName:i.containerName},yn(n,g,l,d,s,e)))}for(o in n)if(o.indexOf("#")===0)hv(o.substring(1),n[o],a,r,u);else if(o.indexOf(".")===-1){for(p.properties||(p.properties=w),y=n[o],h=h=fo(o,s),e=s;!!s&&h===null&&e.baseType;)e=bt(e.baseType,u),h=h=fo(o,e);var tt=fn(o,n,h),b=uo(o,y,n,h,u),it=w[o]=w[o]||{type:b};tt?(c={},i.entitySet!==t&&(nt=kw(h,i.entitySet.name,u),c=dw(nt,u)),c.contentTypeOdata=i.contentTypeOdata,c.kind=i.kind,c.type=b,a[o]=vn(y,c,r,u,f)):a[o]=oo(y,b,it,r,h,u,f)}return ri(n,a,r,s,u)},hv=function(n,t,i,r,u){var f,s,g,nt;if(n&&(e(t)||d(t))){var l=!1,h=n.lastIndexOf("."),a=n.substring(h+1),v=h>-1?n.substring(0,h):"",y=a===n||v.indexOf(".")===-1?ic(u):rc(v,u);y&&(f=ww(y.functionImport,a),f&&!!f.isSideEffecting&&(l=!se(f.isSideEffecting)));for(var p=i.__metadata,w=l?"functions":"actions",tt=c(n,r),b=e(t)?t:[t],o=0,k=b.length;o<k;o++)s=b[o],s&&(g=p[w]=p[w]||[],nt={metadata:tt,title
 :s.title,target:c(s.target,r)},g.push(nt))}},cv=function(n,t,i,r,u){for(var h=e(n)?n:n.value,c=[],l,f,s,o=0,a=h.length;o<a;o++)l=uf(h[o],t,i,r,u),c.push(l);if(f={results:c},d(n)){for(s in n)s.indexOf("#")===0&&(f.__metadata=f.__metadata||{},hv(s.substring(1),n[s],f,i,r));f=ri(n,f,i)}return f},lv=function(n,t){var r,i=t.key.propertyRef,f,e,u;if(r="(",i.length==1)f=wt(t.property,i[0].name).type,r+=so(n[i[0].name],f);else for(e=!0,u=0;u<i.length;u++)e?e=!1:r+=",",f=wt(t.property,i[u].name).type,r+=i[u].name+"="+so(n[i[u].name],f);return r+=")"},yn=function(n,t,i,r,u,f){var o=n[h.id]||n[h.read]||n[h.edit]||t.entitySet.name+t.key,e;n[h.id]=r+o,n[h.edit]||(n[h.edit]=t.entitySet.name+t.key,t.entitySet.entityType!=i&&(n[h.edit]+="/"+i)),n[h.read]=n[h.read]||n[h.edit],n[h.etag]||(e=pn(n,u,f),!e||(n[h.etag]=e)),dn(n,u,f),wn(n,u,f),kn(n,t)},pn=function(n,t,i){for(var u="",f,r=0;t.property&&r<t.property.length;r++)f=t.property[r],u=av(n,u,f);if(i)for(r=0;i.property&&r<i.property.length;r++)f=i.
 property[r],u=av(n,u,f);return u.length>0?u+'"':null},av=function(n,t,i){return i.concurrencyMode=="Fixed"&&(t+=t.length>0?",":'W/"',t+=n[i.name]!==null?so(n[i.name],i.type):"null"),t},wn=function(n,i,r){for(var s="@odata.navigationLinkUrl",c="@odata.associationLinkUrl",u,e,o,f=0;i.navigationProperty&&f<i.navigationProperty.length;f++)u=i.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u));if(r&&r.navigationProperty)for(f=0;f<r.navigationProperty.length;f++)u=r.navigationProperty[f].name,e=u+s,n[e]===t&&(n[e]=n[h.edit]+"/"+encodeURIComponent(u)),o=u+c,n[o]===t&&(n[o]=n[h.edit]+"/$links/"+encodeURIComponent(u))},so=function(n,t){n=""+bn(n,t),n=encodeURIComponent(n.replace("'","''"));switch(t){case"Edm.Binary":return"X'"+n+"'";case"Edm.DateTime":return"datetime'"+n+"'";case"Edm.DateTimeOffset":return"datetimeoffset'"+n+"'";case"Edm.Decimal":return n+"M";case"Edm.Guid":return"guid'"+n+"'
 ";case"Edm.Int64":return n+"L";case"Edm.Float":return n+"f";case"Edm.Double":return n+"D";case"Edm.Geography":return"geography'"+n+"'";case"Edm.Geometry":return"geometry'"+n+"'";case"Edm.Time":return"time'"+n+"'";case"Edm.String":return"'"+n+"'";default:return n}},bn=function(n,t){switch(t){case"Edm.Binary":return cp(n);default:return n}},kn=function(n,i){for(var u=i.functionImport||[],f,r=0;r<u.length;r++)u[r].isBindable&&u[r].parameter[0]&&u[r].parameter[0].type==i.entitySet.entityType&&(f="#"+i.containerName+"."+u[r].name,n[f]==t&&(n[f]={title:u[r].name,target:n[h.edit]+"/"+u[r].name}))},dn=function(n,t,i){(t.hasStream||i&&i.hasStream)&&(n[h.mediaEdit]=n[h.mediaEdit]||n[h.mediaEdit]+"/$value",n[h.mediaRead]=n[h.mediaRead]||n[h.mediaEdit])},gn=function(n,t,i,r){var u={type:t},f=oo(n.value,t,u,i,null,null,r);return ri(n,{__metadata:u,value:f},i)},ntt=function(n,t,i,r,u){var f={},e=sv(n.value,t,f,i,r,u);return g(e.__metadata,f),ri(n,e,i)},ttt=function(n,t){var r=n.value,u,i,f,o;if(!
 e(r))return vv(n,t);for(u=[],i=0,f=r.length;i<f;i++)u.push(vv(r[i],t));return o={results:u},ri(n,o,t)},vv=function(n,t){var i={uri:c(n.url,t)},u,r;return i=ri(n,i,t),u=i.__metadata||{},r=u.properties||{},ff(r.url),ru(r,"url","uri"),i},ff=function(n){n&&delete n.type},itt=function(n,t){var o=n.value,s=[],h=ri(n,{collections:s},t),e=h.__metadata||{},i=e.properties||{},u,l,f,r;for(ff(i.value),ru(i,"value","collections"),u=0,l=o.length;u<l;u++)f=o[u],r={title:f.name,href:c(f.url,t)},r=ri(f,r,t),e=r.__metadata||{},i=e.properties||{},ff(i.name),ff(i.url),ru(i,"name","title"),ru(i,"url","href"),s.push(r);return{workspaces:[h]}},ui=function(n,t){return{kind:n,type:t||null}},rtt=function(n,t,i){var f=n[ro],s,v,o,y,l,r,p,h,c,w,b,u,k;if(!f||typeof f!="string")return null;if(s=f.lastIndexOf("#"),s===-1)return ui(uv);if(v=f.indexOf("@Element",s),o=v-1,o<0&&(o=f.indexOf("?",s),o===-1&&(o=f.length)),y=f.substring(s+1,o),y.indexOf("/$links/")>0)return ui(fv);if(l=y.split("/"),l.length>=0){if(r=l[0]
 ,p=l[1],eo(r))return ui(iv,r);if(yu(r))return ui(rv,r);if(h=p,!p){var d=r.lastIndexOf("."),g=r.substring(d+1),a=g===r?ic(t):rc(r.substring(0,d),t);a&&(c=pw(a.entitySet,g),w=a.functionImport,b=a.name,h=!c?null:c.entityType)}return v>0?(u=ui(tv,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):h?(u=ui(io,h),u.entitySet=c,u.functionImport=w,u.containerName=b,u):e(n.value)&&!gi(r,t)&&(k=n.value[0],!pu(k)&&(ov(k)||!i))?ui(io,null):ui(tv,r)}return null},utt=function(n,t,i,r,u){var e,f,o;if(!d(n))return n;if(u=u||"minimalmetadata",e=n[ro],f=rtt(n,t,r),ot(f)&&(f.contentTypeOdata=u),o=null,f){delete n[ro],o=f.type;switch(f.kind){case io:return cv(n,f,e,t,i);case rv:return ntt(n,o,e,t,i);case iv:return gn(n,o,e,i);case uv:return itt(n,e);case fv:return ttt(n,e)}}return uf(n,f,e,t,i)},yv=["type","etag","media_src","edit_media","content_type","media_etag"],pv=function(n,t){var u=/\/\$links\//,i={},r=n.__metadata,f=t&&u.test(t.request.requestUri);return ho(n,r&&r.properties,i,f),i},ftt=fu
 nction(n,t){var i,u,r,f;if(n)for(i=0,u=yv.length;i<u;i++)r=yv[i],f=ii+(rf[r]||r),dr(f,null,n[r],t)},ho=function(n,t,i,r){var u,f;for(u in n)f=n[u],u==="__metadata"?ftt(f,i):u.indexOf(".")===-1?r&&u==="uri"?ott(f,i):ett(u,f,t,i,r):i[u]=f},ett=function(n,i,r,u){var e=r&&r[n]||{properties:t,type:t},f=hs(i,e);if(pu(i)||!i){dr(ir,n,f,u),u[n]=i;return}if(vr(i,f)||gh(i)){ctt(n,i,u);return}if(!f&&dh(i)){stt(n,i,u);return}if(kh(i,f)){vu(f)&&dr(ir,n,f,u),htt(n,i,u);return}u[n]={},dr(ir,null,f,u[n]),ho(i,e.properties,u[n])},ott=function(n,t){t.url=n},stt=function(n,t,i){dr(ev,n,t.__deferred.uri,i)},htt=function(n,t,i){i[n]=[];var r=e(t)?t:t.results;ho(r,null,i[n])},ctt=function(n,t,i){if(vr(t)){i[n]=[];for(var u=e(t)?t:t.results,r=0,f=u.length;r<f;r++)wv(n,u[r],!0,i);return}wv(n,t,!1,i)},wv=function(n,t,i,r){var f=t.__metadata&&t.__metadata.uri,u;if(f){ltt(n,f,i,r);return}if(u=pv(t),i){r[n].push(u);return}r[n]=u},ltt=function(n,t,i,r){var u=n+rn;if(i){r[u]=r[u]||[],r[u].push(t);return}r[u]=t},
 dr=function(n,i,r,u){r!==t&&(i?u[i+"@"+n]=r:u[n]=r)},bv="application/json",kv=nr(bv),dv=function(n){var r=[],t,i,u;for(t in n)for(i=0,u=n[t].length;i<u;i++)r.push(g({metadata:t},n[t][i]));return r},att=function(n,t,i,r){var c,f,l,u,o,s,v,e,h,a;if(n&&typeof n=="object")if(f=n.__metadata,f&&(f.actions&&(f.actions=dv(f.actions)),f.functions&&(f.functions=dv(f.functions)),c=f&&f.type),l=bt(c,t)||gi(c,t),l){if(o=l.property,o)for(s=0,v=o.length;s<v;s++)if(e=o[s],h=e.name,u=n[h],e.type==="Edm.DateTime"||e.type==="Edm.DateTimeOffset"){if(u){if(u=i(u),!u)throw{message:"Invalid date/time value"};n[h]=u}}else e.type==="Edm.Time"&&(n[h]=ce(u))}else if(r)for(a in n)u=n[a],typeof u=="string"&&(n[a]=i(u)||u);return n},gv=function(n){if(n){var t=n.properties.odata;return t==="nometadata"||t==="minimalmetadata"||t==="fullmetadata"}return!1},vtt=function(n,t){for(var u={collections:[]},r,e,i=0,f=n.EntitySets.length;i<f;i++)r=n.EntitySets[i],e={title:r,href:c(r,t)},u.collections.push(e);return{workspa
 ces:[u]}},ytt=/^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/,ptt=function(n){var t,i;return n<0?(t="-",n=-n):t="+",i=Math.floor(n/60),n=n-60*i,t+a(i,2)+":"+a(n,2)},wtt=function(n){var i=n&&ytt.exec(n),t,r,u;if(i&&(t=new Date(s(i[1])),i[2]&&(r=s(i[3]),i[2]==="-"&&(r=-r),u=t.getUTCMinutes(),t.setUTCMinutes(u-r),t.__edmType="Edm.DateTimeOffset",t.__offset=ptt(r)),!isNaN(t.valueOf())))return t},btt=function(t,i,r){var f=it(r.recognizeDates,t.recognizeDates),h=it(r.inferJsonLightFeedAsObject,t.inferJsonLightFeedAsObject),e=r.metadata,o=r.dataServiceVersion,s=wtt,u=typeof i=="string"?n.JSON.parse(i):i;if(ct("3.0",o)===o){if(gv(r.contentType))return utt(u,e,f,h,r.contentType.properties.odata);s=wu}return u=ib(u.d,function(n,t){return att(t,e,s,f)}),u=nit(u,r.dataServiceVersion),gtt(u,r.response.requestUri)},ny=function(t){var i,r=Date.prototype.toJSON;try{Date.prototype.toJSON=function(){return ph(this)},i=n.JSON.stringify(t,dtt)}finally{Date.prototype.toJSON=r}return i},ktt=function(n,i,r){var e=r.
 dataServiceVersion||"1.0",o=it(r.useJsonLight,n.useJsonLight),u=r.contentType=r.contentType||kv,f;return u&&u.mediaType===kv.mediaType?(f=i,o||gv(u))?(r.dataServiceVersion=ct(e,"3.0"),f=pv(i,r),ny(f)):(ct("3.0",e)===e&&(u.properties.odata="verbose",r.contentType=u),ny(f)):t},dtt=function(n,t){return t&&t.__edmType==="Edm.Time"?wh(t):t},gtt=function(n,t){var i=d(n)&&!n.__metadata&&e(n.EntitySets);return i?vtt(n,t):n},nit=function(n,t){return t&&t.lastIndexOf(";")===t.length-1&&(t=t.substr(0,t.length-1)),t&&t!=="1.0"||e(n)&&(n={results:n}),n},ef=li(btt,ktt,bv,ci);ef.recognizeDates=!1,ef.useJsonLight=!1,ef.inferJsonLightFeedAsObject=!1,r.jsonHandler=ef;var gr="multipart/mixed",tit=/^HTTP\/1\.\d (\d{3}) (.*)$/i,iit=/^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/,co=function(){return Math.floor((1+Math.random())*65536).toString(16).substr(1)},ty=function(n){return n+co()+"-"+co()+"-"+co()},iy=function(n){return n.handler.partHandler},ry=function(n){var t=n.boundaries;return t[t.length-1]},ri
 t=function(n,t,i){var r=i.contentType.properties.boundary;return{__batchResponses:uy(t,{boundaries:[r],handlerContext:i})}},uit=function(n,t,i){var r=i.contentType=i.contentType||nr(gr);if(r.mediaType===gr)return fit(t,i)},uy=function(n,t){var f="--"+ry(t),u,o,s,r,e,i;for(of(n,t,f),rr(n,t),u=[];o!=="--"&&t.position<n.length;){if(s=fy(n,t),r=nr(s["Content-Type"]),r&&r.mediaType===gr){t.boundaries.push(r.properties.boundary);try{e=uy(n,t)}catch(h){h.response=ey(n,t,f),e=[h]}u.push({__changeResponses:e}),t.boundaries.pop(),of(n,t,"--"+ry(t))}else{if(!r||r.mediaType!=="application/http")throw{message:"invalid MIME part type "};rr(n,t),i=ey(n,t,f);try{i.statusCode>=200&&i.statusCode<=299?iy(t.handlerContext).read(i,t.handlerContext):i={message:"HTTP request failed",response:i}}catch(h){i=h}u.push(i)}o=n.substr(t.position,2),rr(n,t)}return u},fy=function(n,t){var r={},i,u,f;do f=t.position,u=rr(n,t),i=iit.exec(u),i!==null?r[i[1]]=i[2]:t.position=f;while(u&&i);return oe(r),r},ey=function(n
 ,t,i){var o=t.position,r=tit.exec(rr(n,t)),u,f,e;return r?(u=r[1],f=r[2],e=fy(n,t),rr(n,t)):t.position=o,{statusCode:u,statusText:f,headers:e,body:of(n,t,"\r\n"+i)}},rr=function(n,t){return of(n,t,"\r\n")},of=function(n,t,i){var u=t.position||0,r=n.length;if(i){if(r=n.indexOf(i,u),r===-1)return null;t.position=r+i.length}else t.position=r;return n.substring(u,r)},fit=function(n,t){var o;if(!aw(n))throw{message:"Data is not a batch object."};for(var r=ty("batch_"),f=n.__batchRequests,u="",i=0,e=f.length;i<e;i++)u+=sf(r,!1)+oy(f[i],t);return u+=sf(r,!0),o=t.contentType.properties,o.boundary=r,u},sf=function(n,t){var i="\r\n--"+n;return t&&(i+="--"),i+"\r\n"},oy=function(n,t,i){var s=n.__changeRequests,r,f,o,h,u;if(e(s)){if(i)throw{message:"Not Supported: change set nested in other change set"};for(f=ty("changeset_"),r="Content-Type: "+gr+"; boundary="+f+"\r\n",o=0,h=s.length;o<h;o++)r+=sf(f,!1)+oy(s[o],t,!0);r+=sf(f,!0)}else r="Content-Type: application/http\r\nContent-Transfer-Encodi
 ng: binary\r\n\r\n",u=g({},t),u.handler=li,u.request=n,u.contentType=null,sc(n,iy(t),u),r+=eit(n);return r},eit=function(n){var t=(n.method?n.method:"GET")+" "+n.requestUri+" HTTP/1.1\r\n",i;for(i in n.headers)n.headers[i]&&(t=t+i+": "+n.headers[i]+"\r\n");return t+="\r\n",n.body&&(t+=n.body),t};r.batchHandler=li(rit,uit,gr,ci),lo=[r.jsonHandler,r.atomHandler,r.xmlHandler,r.textHandler],ao=function(n,t,i){for(var r=0,u=lo.length;r<u&&!lo[r][n](t,i);r++);if(r===u)throw{message:"no handler for data"};},r.defaultSuccess=function(t){n.alert(n.JSON.stringify(t))},r.defaultError=uu,r.defaultHandler={read:function(n,t){n&&ot(n.body)&&n.headers["Content-Type"]&&ao("read",n,t)},write:function(n,t){ao("write",n,t)},maxDataServiceVersion:ci,accept:"application/atomsvc+xml;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1"},r.defaultMetadata=[],r.read=function(n,t,i,u,f,e){var o;return o=n instanceof String||typeof n=="string"?{requestUri:n}:n,r.request(o,t,i,u
 ,f,e)},r.request=function(n,t,i,u,f,e){t=t||r.defaultSuccess,i=i||r.defaultError,u=u||r.defaultHandler,f=f||r.defaultHttpClient,e=e||r.defaultMetadata,n.recognizeDates=it(n.recognizeDates,r.jsonHandler.recognizeDates),n.callbackParameterName=it(n.callbackParameterName,r.defaultHttpClient.callbackParameterName),n.formatQueryString=it(n.formatQueryString,r.defaultHttpClient.formatQueryString),n.enableJsonpCallback=it(n.enableJsonpCallback,r.defaultHttpClient.enableJsonpCallback),n.useJsonLight=it(n.useJsonLight,r.jsonHandler.enableJsonpCallback),n.inferJsonLightFeedAsObject=it(n.inferJsonLightFeedAsObject,r.jsonHandler.inferJsonLightFeedAsObject);var o={metadata:e,recognizeDates:n.recognizeDates,callbackParameterName:n.callbackParameterName,formatQueryString:n.formatQueryString,enableJsonpCallback:n.enableJsonpCallback,useJsonLight:n.useJsonLight,inferJsonLightFeedAsObject:n.inferJsonLightFeedAsObject};try{return sc(n,u,o),lw(n,t,i,u,f,o)}catch(s){i(s)}},r.parseMetadata=function(n){re
 turn nv(null,n)},r.batchHandler.partHandler=r.defaultHandler;var ft=null,oit=function(){var t={v:this.valueOf(),t:"[object Date]"},n;for(n in this)t[n]=this[n];return t},sit=function(n,t){var r,i;if(t&&t.t==="[object Date]"){r=new Date(t.v);for(i in t)i!=="t"&&i!=="v"&&(r[i]=t[i]);t=r}return t},hf=function(n,t){return n.name+"#!#"+t},sy=function(n,t){return t.replace(n.name+"#!#","")},y=function(n){this.name=n};y.create=function(t){if(y.isSupported())return ft=ft||n.localStorage,new y(t);throw{message:"Web Storage not supported by the browser"};},y.isSupported=function(){return!!n.localStorage},y.prototype.add=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?o(r,{message:"key already exists",key:n}):u.addOrUpdate(n,t,i,r)},r)},y.prototype.addOrUpdate=function(i,r,u,f){var s,h,e;if(f=f||this.defaultError,i instanceof Array)f({message:"Array of keys not supported"});else{s=hf(this,i),h=Date.prototype.toJSON;try{e=r,e!==t&&(Date.prototype.toJSON=oit,e=n
 .JSON.stringify(r)),ft.setItem(s,e),o(u,i,r)}catch(c){c.code===22||c.number===2147942414?o(f,{name:"QUOTA_EXCEEDED_ERR",error:c}):o(f,c)}finally{Date.prototype.toJSON=h}}},y.prototype.clear=function(n,t){var i,r,u,f;t=t||this.defaultError;try{for(i=0,r=ft.length;r>0&&i<r;)u=ft.key(i),f=sy(this,u),u!==f?(ft.removeItem(u),r=ft.length):i++;o(n)}catch(e){o(t,e)}},y.prototype.close=function(){},y.prototype.contains=function(n,t,i){i=i||this.defaultError;try{var r=hf(this,n),u=ft.getItem(r);o(t,u!==null)}catch(f){o(i,f)}},y.prototype.defaultError=uu,y.prototype.getAllKeys=function(n,t){var r,i,e,u,f;t=t||this.defaultError,r=[];try{for(i=0,e=ft.length;i<e;i++)u=ft.key(i),f=sy(this,u),u!==f&&r.push(f);o(n,r)}catch(s){o(t,s)}},y.prototype.mechanism="dom",y.prototype.read=function(i,r,u){if(u=u||this.defaultError,i instanceof Array)u({message:"Array of keys not supported"});else try{var e=hf(this,i),f=ft.getItem(e);f=f!==null&&f!=="undefined"?n.JSON.parse(f,sit):t,o(r,i,f)}catch(s){o(u,s)}},y
 .prototype.remove=function(n,t,i){if(i=i||this.defaultError,n instanceof Array)i({message:"Batches not supported"});else try{var r=hf(this,n);ft.removeItem(r),o(t)}catch(u){o(i,u)}},y.prototype.update=function(n,t,i,r){r=r||this.defaultError;var u=this;this.contains(n,function(f){f?u.addOrUpdate(n,t,i,r):o(r,{message:"key not found",key:n})},r)};var hy=n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB||n.indexedDB,hit=n.IDBKeyRange||n.webkitIDBKeyRange,cy=n.IDBTransaction||n.webkitIDBTransaction||{},ly=cy.READ_ONLY||"readonly",ur=cy.READ_WRITE||"readwrite",vt=function(n,t){return function(i){var r=n||t,u,f;if(r){if(Object.prototype.toString.call(i)==="[object IDBDatabaseException]"){if(i.code===11){r({name:"QuotaExceededError",error:i});return}r(i);return}try{f=i.target.error||i,u=f.name}catch(e){u=i.type==="blocked"?"IndexedDBBlocked":"UnknownError"}r({name:u,error:i})}}},cit=function(n,t,i){var u=n.name,f="_datajs_"+u,r=hy.open(f);r.onblocked=i,r.onerror=i,r.onupgradeneeded=functio
 n(){var n=r.result;n.objectStoreNames.contains(u)||n.createObjectStore(u)},r.onsuccess=function(n){var f=r.result,e;if(!f.objectStoreNames.contains(u)){if("setVersion"in f){e=f.setVersion("1.0"),e.onsuccess=function(){var n=e.transaction;n.oncomplete=function(){t(f)},f.createObjectStore(u,null,!1)},e.onerror=i,e.onblocked=i;return}n.target.error={name:"DBSchemaMismatch"},i(n);return}f.onversionchange=function(n){n.target.close()},t(f)}},fi=function(n,t,i,r){var u=n.name,f=n.db,e=vt(r,n.defaultError);if(f){i(f.transaction(u,t));return}cit(n,function(r){n.db=r,i(r.transaction(u,t))},e)},w=function(n){this.name=n};w.create=function(n){if(w.isSupported())return new w(n);throw{message:"IndexedDB is not supported on this browser"};},w.isSupported=function(){return!!hy},w.prototype.add=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){s.onabort=vt(r,o,n,"add"),s.oncomplete=function(){n instanceof Array?i(u,f):i
 (n,t)};for(var h=0;h<u.length&&h<f.length;h++)s.objectStore(e).add({v:f[h]},u[h])},r)},w.prototype.addOrUpdate=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){var h,c;for(s.onabort=vt(r,o),s.oncomplete=function(){n instanceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c={v:f[h]},s.objectStore(e).put(c,u[h])},r)},w.prototype.clear=function(n,t){var i=this.name,r=this.defaultError;fi(this,ur,function(u){u.onerror=vt(t,r),u.oncomplete=function(){n()},u.objectStore(i).clear()},t)},w.prototype.close=function(){this.db&&(this.db.close(),this.db=null)},w.prototype.contains=function(n,t,i){var r=this.name,u=this.defaultError;fi(this,ly,function(f){var e=f.objectStore(r),o=e.get(n);f.oncomplete=function(){t(!!o.result)},f.onerror=vt(i,u)},i)},w.prototype.defaultError=uu,w.prototype.getAllKeys=function(n,t){var i=this.name,r=this.defaultError;fi(this,ur,function(u){var e=[],f;u.oncomplete=function(){n(e
 )},f=u.objectStore(i).openCursor(),f.onerror=vt(t,r),f.onsuccess=function(n){var t=n.target.result;t&&(e.push(t.key),t["continue"].call(t))}},t)},w.prototype.mechanism="indexeddb",w.prototype.read=function(n,i,r){var f=this.name,e=this.defaultError,u=n instanceof Array?n:[n];fi(this,ly,function(o){var h=[],s,c,l;for(o.onerror=vt(r,e,n,"read"),o.oncomplete=function(){n instanceof Array?i(u,h):i(u[0],h[0])},s=0;s<u.length;s++)c=o.objectStore(f),l=c.get.call(c,u[s]),l.onsuccess=function(n){var i=n.target.result;h.push(i?i.v:t)}},r)},w.prototype.remove=function(n,t,i){var u=this.name,f=this.defaultError,r=n instanceof Array?n:[n];fi(this,ur,function(n){var e,o;for(n.onerror=vt(i,f),n.oncomplete=function(){t()},e=0;e<r.length;e++)o=n.objectStore(u),o["delete"].call(o,r[e])},i)},w.prototype.update=function(n,t,i,r){var e=this.name,o=this.defaultError,u=[],f=[];n instanceof Array?(u=n,f=t):(u=[n],f=[t]),fi(this,ur,function(s){var h,c,l;for(s.onabort=vt(r,o),s.oncomplete=function(){n instan
 ceof Array?i(u,f):i(n,t)},h=0;h<u.length&&h<f.length;h++)c=s.objectStore(e).openCursor(hit.only(u[h])),l={v:f[h]},c.pair={key:u[h],value:l},c.onsuccess=function(n){var t=n.target.result;t?t.update(n.target.pair.value):s.abort()}},r)},ei=function(n){var e=[],r=[],i={},u,f;this.name=n,u=function(n){return n||this.defaultError},f=function(n,i){var r;return(n instanceof Array&&(r="Array of keys not supported"),(n===t||n===null)&&(r="Invalid key"),r)?(o(i,{message:r}),!1):!0},this.add=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?e({message:"key already exists",key:n}):this.addOrUpdate(n,t,r,e))},this.addOrUpdate=function(n,s,h,c){if(c=u(c),f(n,c)){var l=i[n];l===t&&(l=e.length>0?e.splice(0,1):r.length),r[l]=s,i[n]=l,o(h,n,s)}},this.clear=function(n){r=[],i={},e=[],o(n)},this.contains=function(n,t){var r=i.hasOwnProperty(n);o(t,r)},this.getAllKeys=function(n){var t=[],r;for(r in i)t.push(r);o(n,t)},this.read=function(n,t,e){if(e=u(e),f(n,e)){var s=i[n];o(t,n,r[s])}},this.remove=f
 unction(n,s,h){if(h=u(h),f(n,h)){var c=i[n];c!==t&&(c===r.length-1?r.pop():(r[c]=t,e.push(c)),delete i[n],r.length===0&&(e=[])),o(s)}},this.update=function(n,t,r,e){e=u(e),f(n,e)&&(i.hasOwnProperty(n)?this.addOrUpdate(n,t,r,e):e({message:"key not found",key:n}))}},ei.create=function(n){return new ei(n)},ei.isSupported=function(){return!0},ei.prototype.close=function(){},ei.prototype.defaultError=uu,ei.prototype.mechanism="memory",ay={indexeddb:w,dom:y,memory:ei},yt.defaultStoreMechanism="best",yt.createStore=function(n,t){t||(t=yt.defaultStoreMechanism),t==="best"&&(t=y.isSupported()?"dom":"memory");var i=ay[t];if(i)return i.create(n);throw{message:"Failed to create store",name:n,mechanism:t};};var lit=function(n,t){var i=n.indexOf("?")>=0?"&":"?";return n+i+t},ait=function(n,t){var i=n.indexOf("?"),r="";return i>=0&&(r=n.substr(i),n=n.substr(0,i)),n[n.length-1]!=="/"&&(n+="/"),n+t+r},vy=function(n,t){return{method:"GET",requestUri:n,user:t.user,password:t.password,enableJsonpCallba
 ck:t.enableJsonpCallback,callbackParameterName:t.callbackParameterName,formatQueryString:t.formatQueryString}},git=function(n,t){var u=-1,r=n.indexOf("?"),i;return r!==-1&&(i=n.indexOf("?"+t+"=",r),i===-1&&(i=n.indexOf("&"+t+"=",r)),i!==-1&&(u=i+t.length+2)),u},vit=function(n,t,i,r){return yy(n,t,[],i,r)},yy=function(n,i,u,f,e){var s=vy(n,i),o=r.request(s,function(n){var t=n.__next,r=n.results;u=u.concat(r),t?o=yy(t,i,u,f,e):f(u)},e,t,i.httpClient,i.metadata);return{abort:function(){o.abort()}}},yit=function(n){var i=this,u=n.source;return i.identifier=op(encodeURI(decodeURI(u))),i.options=n,i.count=function(n,f){var e=i.options;return r.request(vy(ait(u,"$count"),e),function(t){var i=s(t.toString());isNaN(i)?f({message:"Count is NaN",count:i}):n(i)},f,t,e.httpClient,e.metadata)},i.read=function(n,t,r,f){var e="$skip="+n+"&$top="+t;return vit(lit(u,e),i.options,r,f)},i},pit=function(n,t){var r=wit(n,t),i,u;r&&(i=r.i-t.i,u=i+(n.c-n.d.length),n.d=n.d.concat(t.d.slice(i,u)))},wit=funct
 ion(n,t){var r=n.i+n.c,u=t.i+t.c,i=n.i>t.i?n.i:t.i,f=r<u?r:u,e;return f>=i&&(e={i:i,c:f-i}),e},py=function(n,i){if(n===t||typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<0||!isFinite(n))throw{message:"'"+i+"' must be greater than or equal to zero."};},bit=function(n,i){if(n!==t){if(typeof n!="number")throw{message:"'"+i+"' must be a number."};if(isNaN(n)||n<=0||!isFinite(n))throw{message:"'"+i+"' must be greater than zero."};}},wy=function(n,i){if(n!==t&&(typeof n!="number"||isNaN(n)||!isFinite(n)))throw{message:"'"+i+"' must be a number."};},vo=function(n,t){for(var i=0,r=n.length;i<r;i++)if(n[i]===t)return n.splice(i,1),!0;return!1},by=function(n){var t=0,r=typeof n,i;if(r==="object"&&n)for(i in n)t+=i.length*2+by(n[i]);else t=r==="string"?n.length*2:8;return t},ky=function(n,t,i){return n=Math.floor(n/i)*i,t=Math.ceil((t+1)/i)*i,{i:n,c:t-n}},cf="destroy",vi="idle",dy="init",yo="read",po="prefetch",wo="write",nu="cancel",oi="end",bo="error",yi="start",
 gy="wait",np="clear",tu="done",iu="local",tp="save",ip="source",fr=function(n,t,i,r,u,f,e){var h,c,o=this,l,s;return o.p=t,o.i=r,o.c=u,o.d=f,o.s=yi,o.canceled=!1,o.pending=e,o.oncomplete=null,o.cancel=function(){if(i){var n=o.s;n!==bo&&n!==oi&&n!==nu&&(o.canceled=!0,s(nu,h))}},o.complete=function(){s(oi,h)},o.error=function(n){o.canceled||s(bo,n)},o.run=function(n){c=n,o.transition(o.s,h)},o.wait=function(n){s(gy,n)},l=function(t,i,r){switch(t){case yi:i!==dy&&n(o,t,i,r);break;case gy:n(o,t,i,r);break;case nu:n(o,t,i,r),o.fireCanceled(),s(oi);break;case bo:n(o,t,i,r),o.canceled=!0,o.fireRejected(r),s(oi);break;case oi:if(o.oncomplete)o.oncomplete(o);o.canceled||o.fireResolved(),n(o,t,i,r);break;default:n(o,t,i,r)}},s=function(n,t){o.s=n,h=t,l(n,c,t)},o.transition=s,o};fr.prototype.fireResolved=function(){var n=this.p;n&&(this.p=null,n.resolve(this.d))},fr.prototype.fireRejected=function(n){var t=this.p;t&&(this.p=null,t.reject(n))},fr.prototype.fireCanceled=function(){this.fireRejec
 ted({canceled:!0,message:"Operation canceled"})},rp=function(i){var it=dy,y={counts:0,netReads:0,prefetches:0,cacheReads:0},c=[],b=[],p=[],nt=0,l=!1,k=vf(i.cacheSize,1048576),a=0,h=0,d=0,tt=k===0,r=vf(i.pageSize,50),ut=vf(i.prefetchSize,r),ht="1.0",f,ft=0,w=i.source,v,u;typeof w=="string"&&(w=new yit(i)),w.options=i,v=yt.createStore(i.name,i.mechanism),u=this,u.onidle=i.idle,u.stats=y,u.count=function(){var n,i,t;if(f)throw f;return(n=hu(),i=!1,l)?(o(function(){n.resolve(a)}),n.promise()):(t=w.count(function(i){t=null,y.counts++,n.resolve(i)},function(r){t=null,n.reject(g(r,{canceled:i}))}),g(n.promise(),{cancel:function(){t&&(i=!0,t.abort(),t=null)}}))},u.clear=function(){if(f)throw f;if(c.length===0){var n=hu(),t=new fr(ii,n,!1);return et(t,c),n.promise()}return c[0].p},u.filterForward=function(n,t,i){return lt(n,t,i,!1)},u.filterBack=function(n,t,i){return lt(n,t,i,!0)},u.readRange=function(n,t){if(py(n,"index"),py(t,"count"),f)throw f;var i=hu(),r=new fr(ui,i,!0,n,t,[],0);return
  et(r,b),g(i.promise(),{cancel:function(){r.cancel()}})},u.ToObservable=u.toObservable=function(){if(!n.Rx||!n.Rx.Observable)throw{message:"Rx library not available - include rx.js"};if(f)throw f;return n.Rx.Observable.CreateWithDisposable(function(n){var t=!1,i=0,f=function(i){t||n.OnError(i)},e=function(o){if(!t){for(var s=0,h=o.length;s<h;s++)n.OnNext(o[s]);o.length<r?n.OnCompleted():(i+=r,u.readRange(i,r).then(e,f))}};return u.readRange(i,r).then(e,f),{Dispose:function(){t=!0}}})};var rt=function(n){return function(t){f={message:n,error:t};for(var i=0,r=b.length;i<r;i++)b[i].fireRejected(f);for(i=0,r=c.length;i<r;i++)c[i].fireRejected(f);b=c=null}},e=function(n){if(n!==it){it=n;for(var i=c.concat(b,p),t=0,r=i.length;t<r;t++)i[t].run(it)}},ct=function(){var n=new di;return v.clear(function(){nt=0,l=!1,a=0,h=0,d=0,tt=k===0,y={counts:0,netReads:0,prefetches:0,cacheReads:0},u.stats=y,v.close(),n.resolve()},function(t){n.reject(t)}),n},kt=function(n){var t=vo(c,n);t||(t=vo(b,n),t||vo
 (p,n)),ft--,e(vi)},dt=function(n){var t=new di,u=!1,i=w.read(n,r,function(i){var r={i:n,c:i.length,d:i};t.resolve(r)},function(n){t.reject(n)});return g(t,{cancel:function(){i&&(i.abort(),u=!0,i=null)}})},lt=function(n,t,i,e){if(n=s(n),t=s(t),isNaN(n))throw{message:"'index' must be a valid number.",index:n};if(isNaN(t))throw{message:"'count' must be a valid number.",count:t};if(f)throw f;n=Math.max(n,0);var h=hu(),o=[],a=!1,l=null,v=function(n,f){a||(t>=0&&o.length>=t?h.resolve(o):l=u.readRange(n,f).then(function(u){for(var l,a,y,p,s=0,c=u.length;s<c&&(t<0||o.length<t);s++)l=e?c-s-1:s,a=u[l],i(a)&&(y={index:n+l,item:a},e?o.unshift(y):o.push(y));!e&&u.length<f||e&&n<=0?h.resolve(o):(p=e?Math.max(n-r,0):n+f,v(p,r))},function(n){h.reject(n)}))},c=ky(n,n,r),y=e?c.i:n,p=e?n-c.i+1:c.i+c.c-n;return v(y,p),g(h.promise(),{cancel:function(){l&&l.cancel(),a=!0}})},at=function(){u.onidle&&ft===0&&u.onidle()},gt=function(n){if(!l&&ut!==0&&!tt&&(p.length===0||p[0]&&p[0].c!==-1)){var t=new fr(ri,n
 ull,!0,n,ut,null,ut);et(t,p)}},et=function(n,t){n.oncomplete=kt,t.push(n),ft++,n.run(it)},ni=function(n){var r=!1,i=g(new di,{cancel:function(){r=!0}}),u=vt(i,"Read page from store failure");return v.contains(n,function(f){if(!r){if(f){v.read(n,function(n,u){r||i.resolve(u!==t,u)},u);return}i.resolve(!1)}},u),i},ti=function(n,t){var e=!1,i=g(new di,{cancel:function(){e=!0}}),r=vt(i,"Save page to store failure"),u=function(){i.resolve(!0)},f;return t.c>0?(f=by(t),tt=k>=0&&k<nt+f,tt?u():v.addOrUpdate(n,t,function(){pt(t,f),st(u,r)},r)):(pt(t,0),st(u,r)),i},st=function(n,t){var i={actualCacheSize:nt,allDataLocal:l,cacheSize:k,collectionCount:a,highestSavedPage:h,highestSavedPageSize:d,pageSize:r,sourceId:w.identifier,version:ht};v.addOrUpdate("__settings",i,n,t)},vt=function(n){return function(){n.resolve(!1)}},pt=function(n,t){var i=n.c,u=n.i;i===0?h===u-r&&(a=h+d):(h=Math.max(h,u),h===u&&(d=i),nt+=t,i<r&&!a&&(a=u+i)),l||a!==h+d||(l=!0)},wt=function(n,t,i,r){var u=n.canceled&&t!==oi;r
 eturn u&&t===nu&&r&&r.cancel&&r.cancel(),u},ii=function(n,t,i){var r=n.transition;if(i!==cf)return e(cf),!0;switch(t){case yi:r(np);break;case oi:at();break;case np:ct().then(function(){n.complete()}),n.wait();break;default:return!1}return!0},ri=function(n,t,i,u){var o,f;if(!wt(n,t,i,u)){if(o=n.transition,i!==po)return i===cf?t!==nu&&n.cancel():i===vi&&e(po),!0;switch(t){case yi:p[0]===n&&o(iu,n.i);break;case tu:f=n.pending,f>0&&(f-=Math.min(f,u.c)),l||f===0||u.c<r||tt?n.complete():(n.pending=f,o(iu,u.i+r));break;default:return bt(n,t,i,u,!0)}}return!0},ui=function(n,t,i,u){var f,o,s;if(!wt(n,t,i,u)){if(f=n.transition,i!==yo&&t!==yi)return i===cf?t!==yi&&n.cancel():i!==wo&&e(yo),!0;switch(t){case yi:(i===vi||i===po)&&(e(yo),n.c>0?(o=ky(n.i,n.c,r),f(iu,o.i)):f(tu,n));break;case tu:pit(n,u),s=n.d.length,n.c===s||u.c<r?(y.cacheReads++,gt(u.i+u.c),n.complete()):f(iu,u.i+r);break;default:return bt(n,t,i,u,!1)}}return!0},bt=function(n,t,i,r,u){var s=n.error,o=n.transition,h=n.wait,f;switc
 h(t){case oi:at();break;case iu:f=ni(r).then(function(t,i){n.canceled||(t?o(tu,i):o(ip,r))});break;case ip:f=dt(r).then(function(t){n.canceled||(u?y.prefetches++:y.netReads++,o(tp,t))},s);break;case tp:i!==wo&&(e(wo),f=ti(r.i,r).then(function(t){n.canceled||(!t&&u&&(n.pending=0),o(tu,r)),e(vi)}));break;default:return!1}return f&&(n.canceled?f.cancel():n.s===t&&h(f)),!0};return v.read("__settings",function(n,t){if(ot(t)){var i=t.version;if(!i||i.indexOf("1.")!==0){rt("Unsupported cache store version "+i)();return}r!==t.pageSize||w.identifier!==t.sourceId?ct().then(function(){e(vi)},rt("Unable to clear store during initialization")):(nt=t.actualCacheSize,l=t.allDataLocal,k=t.cacheSize,a=t.collectionCount,h=t.highestSavedPage,d=t.highestSavedPageSize,ht=i,e(vi))}else st(function(){e(vi)},rt("Unable to write settings during initialization."))},rt("Unable to read settings from store.")),u},yt.createDataCache=function(n){if(bit(n.pageSize,"pageSize"),wy(n.cacheSize,"cacheSize"),wy(n.prefe
 tchSize,"prefetchSize"),!ot(n.name))throw{message:"Undefined or null name",options:n};if(!ot(n.source))throw{message:"Undefined source",options:n};return new rp(n)}})(this)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/demo/scripts/datajs_demo.js
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/datajs_demo.js b/datajs/demo/scripts/datajs_demo.js
deleted file mode 100644
index 24ac24d..0000000
--- a/datajs/demo/scripts/datajs_demo.js
+++ /dev/null
@@ -1,124 +0,0 @@
-var run = function() {
-    //testJQueryReadMetadata();
-    runSimpleReadRequest();
-    runSimpleReadRequestWithMetadata();
-    //    readWithJsonP();
-    //alert(OData.odataRelatedLinksPrefix);
-    //OData.odataRelatedLinksPrefix = "dasfs";
-    //alert(OData.odataRelatedLinksPrefix);
-    //var time = new Date("1992-08-06T00:00:00+01:00");
-    //var jsonTime = {value : time};
-    //var jsonstring = window.JSON.stringify(jsonTime);
-    //alert(jsonstring);
-
-    //time.offset = 100;
-    //alert(time.offset);
-    //var offsite = time.getTimezoneOffset();
-    //alert(offsite);
-};
-
-var runSimpleReadRequest = function() {
-    var oHeaders = {
-        'Accept': 'application/json',
-        "Odata-Version": "4.0",
-        "OData-MaxVersion": "4.0"
-    };
-
-    var request =
-    {
-        headers: oHeaders,
-        // requestUri: "http://services.odata.org/OData/OData.svc/Categories",
-        requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories",
-        data: null,
-    };
-    var successFunction = function (data) {
-        document.getElementById("simpleRead").innerHTML = JSON.stringify(data, undefined, 2);
-    };
-    var failFunction = function (err) {
-        alert("err");
-        alert(JSON.stringify(err));
-    };
-    odatajs.oData.read(request, successFunction, failFunction);
-};
-
-var runSimpleReadRequestWithMetadata = function () {
-    var oHeaders = {
-        'Accept': 'text/html,application/xhtml+xml,application/xml,application/json;odata.metadata=minimal',
-        "Odata-Version": "4.0",
-        "OData-MaxVersion": "4.0",
-        "Prefer": "odata.allow-entityreferences"
-    };
-    
-    var readMetadataSuccess = function (metadata) {
-        document.getElementById("metadata").innerHTML = JSON.stringify(metadata, undefined, 2);
-        var request =
-        {
-            headers: oHeaders,
-            // requestUri: "http://services.odata.org/OData/OData.svc/Categories",
-            requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Products",
-            data: null,
-        };
-        var successFunction = function(data) {
-            document.getElementById("simpleReadWithMetadata").innerHTML = JSON.stringify(data, undefined, 2);
-        };
-        var failFunction = function(err) {
-            alert("err");
-            alert(JSON.stringify(err));
-        };
-        odatajs.oData.read(request, successFunction, failFunction, null, null, metadata);
-    };
-
-    var readMetadataFail = function (err) {
-        alert("err");
-        alert(JSON.stringify(err));
-    };
-    
-    var metadataRequest =
-    {
-        headers: oHeaders,
-        // requestUri: "http://services.odata.org/OData/OData.svc/$metadata",
-        requestUri: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/$metadata", 
-        // "http://localhost:6630/PrimitiveKeys.svc/$metadata",
-        data: null,
-    };
-
-    odatajs.oData.read(metadataRequest, readMetadataSuccess, readMetadataFail, odatajs.V4.oData.metadataHandler);
-};
-
-var readWithJsonP = function() {
-    var sUrl2 = "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc?$expand=Category";
-
-    var oRequest = {
-        requestUri: sUrl2,
-        enableJsonpCallback: true,
-    };
-
-    odatajs.oData.read(oRequest, function (data) {
-        document.getElementById("simpleReadWithJSONP").innerHTML = JSON.stringify(data, undefined, 2);
-    },
-    function (oError) {
-        alert(oError.message);
-    });
-};
-
-var testJQueryReadMetadata = function () {
-    $.ajax({
-        url: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/$metadata",
-        headers: {
-            '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"
-        },
-        type: "GET",
-        converters: { "text xml": OData.metadataParser },
-        dataType: "xml",
-        success: function (xml, textStatus, jqXHR) {
-            var data = OData.metadataParser2(xml) || undefined;
-            document.getElementById("simpleReadWithMetadata").innerHTML = JSON.stringify(data, undefined, 2);
-        },
-        error: function (jqXHR, textStatus, errorThrown) {
-            alert("err");
-        }
-    });
-};


[45/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/cache.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/cache.js b/datajs/src/lib/cache.js
deleted file mode 100644
index dd872aa..0000000
--- a/datajs/src/lib/cache.js
+++ /dev/null
@@ -1,1447 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- /** @module cache */
-
-var odatajs = require('./datajs.js');
-var utils = odatajs.utils;
-var deferred = odatajs.deferred;
-var storeReq = odatajs.store;
-var cacheSource = require('./cache/source');
-
-
-var assigned = utils.assigned;
-var delay = utils.delay;
-var extend = utils.extend;
-var djsassert = utils.djsassert;
-var isArray = utils.isArray;
-var normalizeURI = utils.normalizeURI;
-var parseInt10 = utils.parseInt10;
-var undefinedDefault = utils.undefinedDefault;
-
-var createDeferred = deferred.createDeferred;
-var DjsDeferred = deferred.DjsDeferred;
-
-
-var getJsonValueArraryLength = utils.getJsonValueArraryLength;
-var sliceJsonValueArray = utils.sliceJsonValueArray;
-var concatJsonValueArray = utils.concatJsonValueArray;
-
-
-
-/** Appends a page's data to the operation data.
- * @param {Object} operation - Operation with  (i)ndex, (c)ount and (d)ata.
- * @param {Object} page - Page with (i)ndex, (c)ount and (d)ata.
- */
-function appendPage(operation, page) {
-
-    var intersection = intersectRanges(operation, page);
-    var start = 0;
-    var end = 0;
-    if (intersection) {
-        start = intersection.i - page.i;
-        end = start + (operation.c - getJsonValueArraryLength(operation.d));
-    }
-
-    operation.d = concatJsonValueArray(operation.d, sliceJsonValueArray(page.d, start, end));
-}
-
-/** Returns the {(i)ndex, (c)ount} range for the intersection of x and y.
- * @param {Object} x - Range with (i)ndex and (c)ount members.
- * @param {Object} y - Range with (i)ndex and (c)ount members.
- * @returns {Object} The intersection (i)ndex and (c)ount; undefined if there is no intersection.
- */
-function intersectRanges(x, y) {
-
-    var xLast = x.i + x.c;
-    var yLast = y.i + y.c;
-    var resultIndex = (x.i > y.i) ? x.i : y.i;
-    var resultLast = (xLast < yLast) ? xLast : yLast;
-    var result;
-    if (resultLast >= resultIndex) {
-        result = { i: resultIndex, c: resultLast - resultIndex };
-    }
-
-    return result;
-}
-
-/** Checks whether val is a defined number with value zero or greater.
- * @param {Number} val - Value to check.
- * @param {String} name - Parameter name to use in exception.
- * @throws Throws an exception if the check fails
- */
-function checkZeroGreater(val, name) {
-
-    if (val === undefined || typeof val !== "number") {
-        throw { message: "'" + name + "' must be a number." };
-    }
-
-    if (isNaN(val) || val < 0 || !isFinite(val)) {
-        throw { message: "'" + name + "' must be greater than or equal to zero." };
-    }
-}
-
-/** Checks whether val is undefined or a number with value greater than zero.
- * @param {Number} val - Value to check.
- * @param {String} name - Parameter name to use in exception.
- * @throws Throws an exception if the check fails
- */
-function checkUndefinedGreaterThanZero(val, name) {
-
-    if (val !== undefined) {
-        if (typeof val !== "number") {
-            throw { message: "'" + name + "' must be a number." };
-        }
-
-        if (isNaN(val) || val <= 0 || !isFinite(val)) {
-            throw { message: "'" + name + "' must be greater than zero." };
-        }
-    }
-}
-
-/** Checks whether val is undefined or a number
- * @param {Number} val - Value to check.
- * @param {String} name - Parameter name to use in exception.
- * @throws Throws an exception if the check fails
- */
-function checkUndefinedOrNumber(val, name) {
-    if (val !== undefined && (typeof val !== "number" || isNaN(val) || !isFinite(val))) {
-        throw { message: "'" + name + "' must be a number." };
-    }
-}
-
-/** Performs a linear search on the specified array and removes the first instance of 'item'.
- * @param {Array} arr - Array to search.
- * @param {*} item - Item being sought.
- * @returns {Boolean} true if the item was removed otherwise false
- */
-function removeFromArray(arr, item) {
-
-    var i, len;
-    for (i = 0, len = arr.length; i < len; i++) {
-        if (arr[i] === item) {
-            arr.splice(i, 1);
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/** Estimates the size of an object in bytes.
- * Object trees are traversed recursively
- * @param {Object} object - Object to determine the size of.
- * @returns {Integer} Estimated size of the object in bytes.
- */
-function estimateSize(object) {
-    var size = 0;
-    var type = typeof object;
-
-    if (type === "object" && object) {
-        for (var name in object) {
-            size += name.length * 2 + estimateSize(object[name]);
-        }
-    } else if (type === "string") {
-        size = object.length * 2;
-    } else {
-        size = 8;
-    }
-    return size;
-}
-
-/** Snaps low and high indices into page sizes and returns a range.
- * @param {Number} lowIndex - Low index to snap to a lower value.
- * @param {Number} highIndex - High index to snap to a higher value.
- * @param {Number} pageSize - Page size to snap to.
- * @returns {Object} A range with (i)ndex and (c)ount of elements.
- */
-function snapToPageBoundaries(lowIndex, highIndex, pageSize) {
-    lowIndex = Math.floor(lowIndex / pageSize) * pageSize;
-    highIndex = Math.ceil((highIndex + 1) / pageSize) * pageSize;
-    return { i: lowIndex, c: highIndex - lowIndex };
-}
-
-// The DataCache is implemented using state machines.  The following constants are used to properly
-// identify and label the states that these machines transition to.
-var CACHE_STATE_DESTROY  = "destroy";
-var CACHE_STATE_IDLE     = "idle";
-var CACHE_STATE_INIT     = "init";
-var CACHE_STATE_READ     = "read";
-var CACHE_STATE_PREFETCH = "prefetch";
-var CACHE_STATE_WRITE    = "write";
-
-// DataCacheOperation state machine states.
-// Transitions on operations also depend on the cache current of the cache.
-var OPERATION_STATE_CANCEL = "cancel";
-var OPERATION_STATE_END    = "end";
-var OPERATION_STATE_ERROR  = "error";
-var OPERATION_STATE_START  = "start";
-var OPERATION_STATE_WAIT   = "wait";
-
-// Destroy state machine states
-var DESTROY_STATE_CLEAR = "clear";
-
-// Read / Prefetch state machine states
-var READ_STATE_DONE   = "done";
-var READ_STATE_LOCAL  = "local";
-var READ_STATE_SAVE   = "save";
-var READ_STATE_SOURCE = "source";
-
-/** Creates a new operation object.
- * @class DataCacheOperation
- * @param {Function} stateMachine - State machine that describes the specific behavior of the operation.
- * @param {DjsDeferred} promise - Promise for requested values.
- * @param {Boolean} isCancelable - Whether this operation can be canceled or not.
- * @param {Number} index - Index of first item requested.
- * @param {Number} count - Count of items requested.
- * @param {Array} data - Array with the items requested by the operation.
- * @param {Number} pending - Total number of pending prefetch records.
- * @returns {DataCacheOperation} A new data cache operation instance.
- */
-function DataCacheOperation(stateMachine, promise, isCancelable, index, count, data, pending) {
-
-    /// <field name="p" type="DjsDeferred">Promise for requested values.</field>
-    /// <field name="i" type="Number">Index of first item requested.</field>
-    /// <field name="c" type="Number">Count of items requested.</field>
-    /// <field name="d" type="Array">Array with the items requested by the operation.</field>
-    /// <field name="s" type="Array">Current state of the operation.</field>
-    /// <field name="canceled" type="Boolean">Whether the operation has been canceled.</field>
-    /// <field name="pending" type="Number">Total number of pending prefetch records.</field>
-    /// <field name="oncomplete" type="Function">Callback executed when the operation reaches the end state.</field>
-
-    var stateData;
-    var cacheState;
-    var that = this;
-
-    that.p = promise;
-    that.i = index;
-    that.c = count;
-    that.d = data;
-    that.s = OPERATION_STATE_START;
-
-    that.canceled = false;
-    that.pending = pending;
-    that.oncomplete = null;
-
-    /** Transitions this operation to the cancel state and sets the canceled flag to true.
-     * The function is a no-op if the operation is non-cancelable.</summary>
-     * @method DataCacheOperation#cancel
-     */
-    that.cancel = function cancel() {
-
-        if (!isCancelable) {
-            return;
-        }
-
-        var state = that.s;
-        if (state !== OPERATION_STATE_ERROR && state !== OPERATION_STATE_END && state !== OPERATION_STATE_CANCEL) {
-            that.canceled = true;
-            transition(OPERATION_STATE_CANCEL, stateData);
-        }
-    };
-
-    /** Transitions this operation to the end state.
-     * @method DataCacheOperation#complete
-     */
-    that.complete = function () {
-
-        djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.complete() - operation is in the end state", that);
-        transition(OPERATION_STATE_END, stateData);
-    };
-
-    /** Transitions this operation to the error state.
-     * @method DataCacheOperation#error
-     */
-    that.error = function (err) {
-        if (!that.canceled) {
-            djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.error() - operation is in the end state", that);
-            djsassert(that.s !== OPERATION_STATE_ERROR, "DataCacheOperation.error() - operation is in the error state", that);
-            transition(OPERATION_STATE_ERROR, err);
-        }
-    };
-
-    /** Executes the operation's current state in the context of a new cache state.
-     * @method DataCacheOperation#run
-     * @param {Object} state - New cache state.
-     */
-    that.run = function (state) {
-
-        cacheState = state;
-        that.transition(that.s, stateData);
-    };
-
-    /** Transitions this operation to the wait state.
-     * @method DataCacheOperation#wait
-     */
-    that.wait = function (data) {
-
-        djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.wait() - operation is in the end state", that);
-        transition(OPERATION_STATE_WAIT, data);
-    };
-
-    /** State machine that describes all operations common behavior.
-     * @method DataCacheOperation#operationStateMachine
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-     * @param {Object} [data] - Additional data passed to the state.
-     */
-    var operationStateMachine = function (opTargetState, cacheState, data) {
-
-        switch (opTargetState) {
-            case OPERATION_STATE_START:
-                // Initial state of the operation. The operation will remain in this state until the cache has been fully initialized.
-                if (cacheState !== CACHE_STATE_INIT) {
-                    stateMachine(that, opTargetState, cacheState, data);
-                }
-                break;
-
-            case OPERATION_STATE_WAIT:
-                // Wait state indicating that the operation is active but waiting for an asynchronous operation to complete.
-                stateMachine(that, opTargetState, cacheState, data);
-                break;
-
-            case OPERATION_STATE_CANCEL:
-                // Cancel state.
-                stateMachine(that, opTargetState, cacheState, data);
-                that.fireCanceled();
-                transition(OPERATION_STATE_END);
-                break;
-
-            case OPERATION_STATE_ERROR:
-                // Error state. Data is expected to be an object detailing the error condition.
-                stateMachine(that, opTargetState, cacheState, data);
-                that.canceled = true;
-                that.fireRejected(data);
-                transition(OPERATION_STATE_END);
-                break;
-
-            case OPERATION_STATE_END:
-                // Final state of the operation.
-                if (that.oncomplete) {
-                    that.oncomplete(that);
-                }
-                if (!that.canceled) {
-                    that.fireResolved();
-                }
-                stateMachine(that, opTargetState, cacheState, data);
-                break;
-
-            default:
-                // Any other state is passed down to the state machine describing the operation's specific behavior.
-                // DATAJS INTERNAL START 
-                if (true) {
-                    // Check that the state machine actually handled the sate.
-                    var handled = stateMachine(that, opTargetState, cacheState, data);
-                    djsassert(handled, "Bad operation state: " + opTargetState + " cacheState: " + cacheState, this);
-                } else {
-                    // DATAJS INTERNAL END 
-                    stateMachine(that, opTargetState, cacheState, data);
-                    // DATAJS INTERNAL START
-                }
-                // DATAJS INTERNAL END
-                break;
-        }
-    };
-
-
-
-    /** Transitions this operation to a new state.
-     * @method DataCacheOperation#transition
-     * @param {Object} state - State to transition the operation to.
-     * @param {Object} [data] - 
-     */
-    var transition = function (state, data) {
-        that.s = state;
-        stateData = data;
-        operationStateMachine(state, cacheState, data);
-    };
-    
-    that.transition = transition;
-    
-    return that;
-}
-
-/** Fires a resolved notification as necessary.
- * @method DataCacheOperation#fireResolved
- */
-DataCacheOperation.prototype.fireResolved = function () {
-
-    // Fire the resolve just once.
-    var p = this.p;
-    if (p) {
-        this.p = null;
-        p.resolve(this.d);
-    }
-};
-
-/** Fires a rejected notification as necessary.
- * @method DataCacheOperation#fireRejected
- */
-DataCacheOperation.prototype.fireRejected = function (reason) {
-
-    // Fire the rejection just once.
-    var p = this.p;
-    if (p) {
-        this.p = null;
-        p.reject(reason);
-    }
-};
-
-/** Fires a canceled notification as necessary.
- * @method DataCacheOperation#fireCanceled
- */
-DataCacheOperation.prototype.fireCanceled = function () {
-
-    this.fireRejected({ canceled: true, message: "Operation canceled" });
-};
-
-
-/** Creates a data cache for a collection that is efficiently loaded on-demand.
- * @class DataCache
- * @param options - Options for the data cache, including name, source, pageSize,
- * prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
- * @returns {DataCache} A new data cache instance.
- */
-function DataCache(options) {
-
-    var state = CACHE_STATE_INIT;
-    var stats = { counts: 0, netReads: 0, prefetches: 0, cacheReads: 0 };
-
-    var clearOperations = [];
-    var readOperations = [];
-    var prefetchOperations = [];
-
-    var actualCacheSize = 0;                                             // Actual cache size in bytes.
-    var allDataLocal = false;                                            // Whether all data is local.
-    var cacheSize = undefinedDefault(options.cacheSize, 1048576);        // Requested cache size in bytes, default 1 MB.
-    var collectionCount = 0;                                             // Number of elements in the server collection.
-    var highestSavedPage = 0;                                            // Highest index of all the saved pages.
-    var highestSavedPageSize = 0;                                        // Item count of the saved page with the highest index.
-    var overflowed = cacheSize === 0;                                    // If the cache has overflowed (actualCacheSize > cacheSize or cacheSize == 0);
-    var pageSize = undefinedDefault(options.pageSize, 50);               // Number of elements to store per page.
-    var prefetchSize = undefinedDefault(options.prefetchSize, pageSize); // Number of elements to prefetch from the source when the cache is idling.
-    var version = "1.0";
-    var cacheFailure;
-
-    var pendingOperations = 0;
-
-    var source = options.source;
-    if (typeof source === "string") {
-        // Create a new cache source.
-        source = new cacheSource.ODataCacheSource(options);
-    }
-    source.options = options;
-
-    // Create a cache local store.
-    var store = storeReq.createStore(options.name, options.mechanism);
-
-    var that = this;
-
-    that.onidle = options.idle;
-    that.stats = stats;
-
-    /** Counts the number of items in the collection.
-     * @method DataCache#count
-     * @returns {Object} A promise with the number of items.
-     */
-    that.count = function () {
-
-        if (cacheFailure) {
-            throw cacheFailure;
-        }
-
-        var deferred = createDeferred();
-        var canceled = false;
-
-        if (allDataLocal) {
-            delay(function () {
-                deferred.resolve(collectionCount);
-            });
-
-            return deferred.promise();
-        }
-
-        // TODO: Consider returning the local data count instead once allDataLocal flag is set to true.
-        var request = source.count(function (count) {
-            request = null;
-            stats.counts++;
-            deferred.resolve(count);
-        }, function (err) {
-            request = null;
-            deferred.reject(extend(err, { canceled: canceled }));
-        });
-
-        return extend(deferred.promise(), {
-
-             /** Aborts the count operation (used within promise callback)
-              * @method DataCache#cancelCount
-              */
-            cancel: function () {
-               
-                if (request) {
-                    canceled = true;
-                    request.abort();
-                    request = null;
-                }
-            }
-        });
-    };
-
-    /** Cancels all running operations and clears all local data associated with this cache.
-     * New read requests made while a clear operation is in progress will not be canceled.
-     * Instead they will be queued for execution once the operation is completed.
-     * @method DataCache#clear
-     * @returns {Object} A promise that has no value and can't be canceled.
-     */
-    that.clear = function () {
-
-        if (cacheFailure) {
-            throw cacheFailure;
-        }
-
-        if (clearOperations.length === 0) {
-            var deferred = createDeferred();
-            var op = new DataCacheOperation(destroyStateMachine, deferred, false);
-            queueAndStart(op, clearOperations);
-            return deferred.promise();
-        }
-        return clearOperations[0].p;
-    };
-
-    /** Filters the cache data based a predicate.
-     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-     * @method DataCache#filterForward
-     * @param {Number} index - The index of the item to start filtering forward from.
-     * @param {Number} count - Maximum number of items to include in the result.
-     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
-     * @returns {DjsDeferred} A promise for an array of results.
-     */
-    that.filterForward = function (index, count, predicate) {
-        return filter(index, count, predicate, false);
-    };
-
-    /** Filters the cache data based a predicate.
-     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-     * @method DataCache#filterBack
-     * @param {Number} index - The index of the item to start filtering backward from.
-     * @param {Number} count - Maximum number of items to include in the result.
-     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
-     * @returns {DjsDeferred} A promise for an array of results.
-     */
-    that.filterBack = function (index, count, predicate) {
-        return filter(index, count, predicate, true);
-    };
-
-    /** Reads a range of adjacent records.
-     * New read requests made while a clear operation is in progress will not be canceled.
-     * Instead they will be queued for execution once the operation is completed.
-     * @method DataCache#readRange
-     * @param {Number} index - Zero-based index of record range to read.
-     * @param {Number} count - Number of records in the range.
-     * @returns {DjsDeferred} A promise for an array of records; less records may be returned if the
-     * end of the collection is found.
-     */
-    that.readRange = function (index, count) {
-
-        checkZeroGreater(index, "index");
-        checkZeroGreater(count, "count");
-
-        if (cacheFailure) {
-            throw cacheFailure;
-        }
-
-        var deferred = createDeferred();
-
-        // Merging read operations would be a nice optimization here.
-        var op = new DataCacheOperation(readStateMachine, deferred, true, index, count, {}, 0);
-        queueAndStart(op, readOperations);
-
-        return extend(deferred.promise(), {
-            cancel: function () {
-                /** Aborts the readRange operation  (used within promise callback)
-                 * @method DataCache#cancelReadRange
-                 */
-                op.cancel();
-            }
-        });
-    };
-
-    /** Creates an Observable object that enumerates all the cache contents.
-     * @method DataCache#toObservable
-     * @returns A new Observable object that enumerates all the cache contents.
-     */
-    that.ToObservable = that.toObservable = function () {
-        if ( !utils.inBrowser()) {
-            throw { message: "Only in broser supported" };
-        }
-
-        if (!window.Rx || !window.Rx.Observable) {
-            throw { message: "Rx library not available - include rx.js" };
-        }
-
-        if (cacheFailure) {
-            throw cacheFailure;
-        }
-
-        return new window.Rx.Observable(function (obs) {
-            var disposed = false;
-            var index = 0;
-
-            var errorCallback = function (error) {
-                if (!disposed) {
-                    obs.onError(error);
-                }
-            };
-
-            var successCallback = function (data) {
-                if (!disposed) {
-                    var i, len;
-                    for (i = 0, len = data.value.length; i < len; i++) {
-                        // The wrapper automatically checks for Dispose
-                        // on the observer, so we don't need to check it here.
-                        obs.onNext(data.value[i]);
-                    }
-
-                    if (data.value.length < pageSize) {
-                        obs.onCompleted();
-                    } else {
-                        index += pageSize;
-                        that.readRange(index, pageSize).then(successCallback, errorCallback);
-                    }
-                }
-            };
-
-            that.readRange(index, pageSize).then(successCallback, errorCallback);
-
-            return { Dispose: function () { disposed = true; } };
-        });
-    };
-
-    /** Creates a function that handles a callback by setting the cache into failure mode.
-     * @method DataCache~cacheFailureCallback
-     * @param {String} message - Message text.
-     * @returns {Function} Function to use as error callback.
-     * This function will specifically handle problems with critical store resources
-     * during cache initialization.
-     */
-    var cacheFailureCallback = function (message) {
-        
-
-        return function (error) {
-            cacheFailure = { message: message, error: error };
-
-            // Destroy any pending clear or read operations.
-            // At this point there should be no prefetch operations.
-            // Count operations will go through but are benign because they
-            // won't interact with the store.
-            djsassert(prefetchOperations.length === 0, "prefetchOperations.length === 0");
-            var i, len;
-            for (i = 0, len = readOperations.length; i < len; i++) {
-                readOperations[i].fireRejected(cacheFailure);
-            }
-            for (i = 0, len = clearOperations.length; i < len; i++) {
-                clearOperations[i].fireRejected(cacheFailure);
-            }
-
-            // Null out the operation arrays.
-            readOperations = clearOperations = null;
-        };
-    };
-
-    /** Updates the cache's state and signals all pending operations of the change.
-     * @method DataCache~changeState
-     * @param {Object} newState - New cache state.
-     * This method is a no-op if the cache's current state and the new state are the same.</remarks>
-     */
-    var changeState = function (newState) {
-
-        if (newState !== state) {
-            state = newState;
-            var operations = clearOperations.concat(readOperations, prefetchOperations);
-            var i, len;
-            for (i = 0, len = operations.length; i < len; i++) {
-                operations[i].run(state);
-            }
-        }
-    };
-
-    /** Removes all the data stored in the cache.
-     * @method DataCache~clearStore
-     * @returns {DjsDeferred} A promise with no value.
-     */
-    var clearStore = function () {
-        djsassert(state === CACHE_STATE_DESTROY || state === CACHE_STATE_INIT, "DataCache.clearStore() - cache is not on the destroy or initialize state, current sate = " + state);
-
-        var deferred = new DjsDeferred();
-        store.clear(function () {
-
-            // Reset the cache settings.
-            actualCacheSize = 0;
-            allDataLocal = false;
-            collectionCount = 0;
-            highestSavedPage = 0;
-            highestSavedPageSize = 0;
-            overflowed = cacheSize === 0;
-
-            // version is not reset, in case there is other state in eg V1.1 that is still around.
-
-            // Reset the cache stats.
-            stats = { counts: 0, netReads: 0, prefetches: 0, cacheReads: 0 };
-            that.stats = stats;
-
-            store.close();
-            deferred.resolve();
-        }, function (err) {
-            deferred.reject(err);
-        });
-        return deferred;
-    };
-
-    /** Removes an operation from the caches queues and changes the cache state to idle.
-     * @method DataCache~dequeueOperation
-     * @param {DataCacheOperation} operation - Operation to dequeue.
-     * This method is used as a handler for the operation's oncomplete event.</remarks>
-    */
-    var dequeueOperation = function (operation) {
-
-        var removed = removeFromArray(clearOperations, operation);
-        if (!removed) {
-            removed = removeFromArray(readOperations, operation);
-            if (!removed) {
-                removeFromArray(prefetchOperations, operation);
-            }
-        }
-
-        pendingOperations--;
-        changeState(CACHE_STATE_IDLE);
-    };
-
-    /** Requests data from the cache source.
-     * @method DataCache~fetchPage
-     * @param {Number} start - Zero-based index of items to request.
-     * @returns {DjsDeferred} A promise for a page object with (i)ndex, (c)ount, (d)ata.
-     */
-    var fetchPage = function (start) {
-
-        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.fetchPage() - cache is on the destroy state");
-        djsassert(state !== CACHE_STATE_IDLE, "DataCache.fetchPage() - cache is on the idle state");
-
-        var deferred = new DjsDeferred();
-        var canceled = false;
-
-        var request = source.read(start, pageSize, function (data) {
-            var length = getJsonValueArraryLength(data);
-            var page = { i: start, c: length, d: data };
-            deferred.resolve(page);
-        }, function (err) {
-            deferred.reject(err);
-        });
-
-        return extend(deferred, {
-            cancel: function () {
-                if (request) {
-                    request.abort();
-                    canceled = true;
-                    request = null;
-                }
-            }
-        });
-    };
-
-    /** Filters the cache data based a predicate.
-     * @method DataCache~filter
-     * @param {Number} index - The index of the item to start filtering from.
-     * @param {Number} count - Maximum number of items to include in the result.
-     * @param {Function} predicate - Callback function returning a boolean that determines whether an item should be included in the result or not.
-     * @param {Boolean} backwards - True if the filtering should move backward from the specified index, falsey otherwise.
-     * Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-     * @returns {DjsDeferred} A promise for an array of results.
-     */
-    var filter = function (index, count, predicate, backwards) {
-
-        index = parseInt10(index);
-        count = parseInt10(count);
-
-        if (isNaN(index)) {
-            throw { message: "'index' must be a valid number.", index: index };
-        }
-        if (isNaN(count)) {
-            throw { message: "'count' must be a valid number.", count: count };
-        }
-
-        if (cacheFailure) {
-            throw cacheFailure;
-        }
-
-        index = Math.max(index, 0);
-
-        var deferred = createDeferred();
-        var returnData = {};
-        returnData.value = [];
-        var canceled = false;
-        var pendingReadRange = null;
-
-        var readMore = function (readIndex, readCount) {
-            if (!canceled) {
-                if (count > 0 && returnData.value.length >= count) {
-                    deferred.resolve(returnData);
-                } else {
-                    pendingReadRange = that.readRange(readIndex, readCount).then(function (data) {
-                        if (data["@odata.context"] && !returnData["@odata.context"]) {
-                            returnData["@odata.context"] = data["@odata.context"];
-                        }
-                        
-                        for (var i = 0, length = data.value.length; i < length && (count < 0 || returnData.value.length < count); i++) {
-                            var dataIndex = backwards ? length - i - 1 : i;
-                            var item = data.value[dataIndex];
-                            if (predicate(item)) {
-                                var element = {
-                                    index: readIndex + dataIndex,
-                                    item: item
-                                };
-
-                                backwards ? returnData.value.unshift(element) : returnData.value.push(element);
-                            }
-                        }
-
-                        // Have we reached the end of the collection?
-                        if ((!backwards && data.value.length < readCount) || (backwards && readIndex <= 0)) {
-                            deferred.resolve(returnData);
-                        } else {
-                            var nextIndex = backwards ? Math.max(readIndex - pageSize, 0) : readIndex + readCount;
-                            readMore(nextIndex, pageSize);
-                        }
-                    }, function (err) {
-                        deferred.reject(err);
-                    });
-                }
-            }
-        };
-
-        // Initially, we read from the given starting index to the next/previous page boundary
-        var initialPage = snapToPageBoundaries(index, index, pageSize);
-        var initialIndex = backwards ? initialPage.i : index;
-        var initialCount = backwards ? index - initialPage.i + 1 : initialPage.i + initialPage.c - index;
-        readMore(initialIndex, initialCount);
-
-        return extend(deferred.promise(), {
-            /** Aborts the filter operation (used within promise callback)
-            * @method DataCache#cancelFilter
-             */
-            cancel: function () {
-
-                if (pendingReadRange) {
-                    pendingReadRange.cancel();
-                }
-                canceled = true;
-            }
-        });
-    };
-
-    /** Fires an onidle event if any functions are assigned.
-     * @method DataCache~fireOnIdle
-    */
-    var fireOnIdle = function () {
-
-        if (that.onidle && pendingOperations === 0) {
-            that.onidle();
-        }
-    };
-
-    /** Creates and starts a new prefetch operation.
-     * @method DataCache~prefetch
-     * @param {Number} start - Zero-based index of the items to prefetch.
-     * This method is a no-op if any of the following conditions is true:
-     *     1.- prefetchSize is 0
-     *     2.- All data has been read and stored locally in the cache.
-     *     3.- There is already an all data prefetch operation queued.
-     *     4.- The cache has run out of available space (overflowed).
-    */
-    var prefetch = function (start) {
-        
-
-        if (allDataLocal || prefetchSize === 0 || overflowed) {
-            return;
-        }
-
-        djsassert(state === CACHE_STATE_READ, "DataCache.prefetch() - cache is not on the read state, current state: " + state);
-
-        if (prefetchOperations.length === 0 || (prefetchOperations[0] && prefetchOperations[0].c !== -1)) {
-            // Merging prefetch operations would be a nice optimization here.
-            var op = new DataCacheOperation(prefetchStateMachine, null, true, start, prefetchSize, null, prefetchSize);
-            queueAndStart(op, prefetchOperations);
-        }
-    };
-
-    /** Queues an operation and runs it.
-     * @param {DataCacheOperation} op - Operation to queue.
-     * @param {Array} queue - Array that will store the operation.
-     */
-    var queueAndStart = function (op, queue) {
-
-        op.oncomplete = dequeueOperation;
-        queue.push(op);
-        pendingOperations++;
-        op.run(state);
-    };
-
-    /** Requests a page from the cache local store.
-     * @method DataCache~readPage    
-     * @param {Number} key - Zero-based index of the reuqested page.
-     * @returns {DjsDeferred} A promise for a found flag and page object with (i)ndex, (c)ount, (d)ata, and (t)icks.
-     */
-    var readPage = function (key) {
-
-        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.readPage() - cache is on the destroy state");
-
-        var canceled = false;
-        var deferred = extend(new DjsDeferred(), {
-            /** Aborts the readPage operation. (used within promise callback)
-             * @method DataCache#cancelReadPage
-             */
-            cancel: function () {
-                canceled = true;
-            }
-        });
-
-        var error = storeFailureCallback(deferred, "Read page from store failure");
-
-        store.contains(key, function (contained) {
-            if (canceled) {
-                return;
-            }
-            if (contained) {
-                store.read(key, function (_, data) {
-                    if (!canceled) {
-                        deferred.resolve(data !== undefined, data);
-                    }
-                }, error);
-                return;
-            }
-            deferred.resolve(false);
-        }, error);
-        return deferred;
-    };
-
-    /** Saves a page to the cache local store.
-     * @method DataCache~savePage    
-     * @param {Number} key - Zero-based index of the requested page.
-     * @param {Object} page - Object with (i)ndex, (c)ount, (d)ata, and (t)icks.
-     * @returns {DjsDeferred} A promise with no value.
-     */
-    var savePage = function (key, page) {
-
-        djsassert(state !== CACHE_STATE_DESTROY, "DataCache.savePage() - cache is on the destroy state");
-        djsassert(state !== CACHE_STATE_IDLE, "DataCache.savePage() - cache is on the idle state");
-
-        var canceled = false;
-
-        var deferred = extend(new DjsDeferred(), {
-            /** Aborts the savePage operation. (used within promise callback)
-             * @method DataCache#cancelReadPage
-             */
-            cancel: function () {
-                canceled = true;
-            }
-        });
-
-        var error = storeFailureCallback(deferred, "Save page to store failure");
-
-        var resolve = function () {
-            deferred.resolve(true);
-        };
-
-        if (page.c > 0) {
-            var pageBytes = estimateSize(page);
-            overflowed = cacheSize >= 0 && cacheSize < actualCacheSize + pageBytes;
-
-            if (!overflowed) {
-                store.addOrUpdate(key, page, function () {
-                    updateSettings(page, pageBytes);
-                    saveSettings(resolve, error);
-                }, error);
-            } else {
-                resolve();
-            }
-        } else {
-            updateSettings(page, 0);
-            saveSettings(resolve, error);
-        }
-        return deferred;
-    };
-
-    /** Saves the cache's current settings to the local store.
-     * @method DataCache~saveSettings    
-     * @param {Function} success - Success callback.
-     * @param {Function} error - Errror callback.
-     */
-    var saveSettings = function (success, error) {
-
-        var settings = {
-            actualCacheSize: actualCacheSize,
-            allDataLocal: allDataLocal,
-            cacheSize: cacheSize,
-            collectionCount: collectionCount,
-            highestSavedPage: highestSavedPage,
-            highestSavedPageSize: highestSavedPageSize,
-            pageSize: pageSize,
-            sourceId: source.identifier,
-            version: version
-        };
-
-        store.addOrUpdate("__settings", settings, success, error);
-    };
-
-    /** Creates a function that handles a store error.
-     * @method DataCache~storeFailureCallback    
-     * @param {DjsDeferred} deferred - Deferred object to resolve.
-     * @param {String} message - Message text.
-     * @returns {Function} Function to use as error callback.
-    
-     * This function will specifically handle problems when interacting with the store.
-     */
-    var storeFailureCallback = function (deferred/*, message*/) {
-        
-
-        return function (/*error*/) {
-            // var console = windo1w.console;
-            // if (console && console.log) {
-            //    console.log(message);
-            //    console.dir(error);
-            // }
-            deferred.resolve(false);
-        };
-    };
-
-    /** Updates the cache's settings based on a page object.
-     * @method DataCache~updateSettings    
-     * @param {Object} page - Object with (i)ndex, (c)ount, (d)ata.
-     * @param {Number} pageBytes - Size of the page in bytes.
-     */
-    var updateSettings = function (page, pageBytes) {
-
-        var pageCount = page.c;
-        var pageIndex = page.i;
-
-        // Detect the collection size.
-        if (pageCount === 0) {
-            if (highestSavedPage === pageIndex - pageSize) {
-                collectionCount = highestSavedPage + highestSavedPageSize;
-            }
-        } else {
-            highestSavedPage = Math.max(highestSavedPage, pageIndex);
-            if (highestSavedPage === pageIndex) {
-                highestSavedPageSize = pageCount;
-            }
-            actualCacheSize += pageBytes;
-            if (pageCount < pageSize && !collectionCount) {
-                collectionCount = pageIndex + pageCount;
-            }
-        }
-
-        // Detect the end of the collection.
-        if (!allDataLocal && collectionCount === highestSavedPage + highestSavedPageSize) {
-            allDataLocal = true;
-        }
-    };
-
-    /** State machine describing the behavior for cancelling a read or prefetch operation.
-     * @method DataCache~cancelStateMachine    
-     * @param {DataCacheOperation} operation - Operation being run.
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-     * @param {Object} [data] - 
-     * This state machine contains behavior common to read and prefetch operations.
-     */
-    var cancelStateMachine = function (operation, opTargetState, cacheState, data) {
-        
-
-        var canceled = operation.canceled && opTargetState !== OPERATION_STATE_END;
-        if (canceled) {
-            if (opTargetState === OPERATION_STATE_CANCEL) {
-                // Cancel state.
-                // Data is expected to be any pending request made to the cache.
-                if (data && data.cancel) {
-                    data.cancel();
-                }
-            }
-        }
-        return canceled;
-    };
-
-    /** State machine describing the behavior of a clear operation.
-     * @method DataCache~destroyStateMachine    
-     * @param {DataCacheOperation} operation - Operation being run.
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-    
-     * Clear operations have the highest priority and can't be interrupted by other operations; however,
-     * they will preempt any other operation currently executing.
-     */
-    var destroyStateMachine = function (operation, opTargetState, cacheState) {
-        
-
-        var transition = operation.transition;
-
-        // Signal the cache that a clear operation is running.
-        if (cacheState !== CACHE_STATE_DESTROY) {
-            changeState(CACHE_STATE_DESTROY);
-            return true;
-        }
-
-        switch (opTargetState) {
-            case OPERATION_STATE_START:
-                // Initial state of the operation.
-                transition(DESTROY_STATE_CLEAR);
-                break;
-
-            case OPERATION_STATE_END:
-                // State that signals the operation is done.
-                fireOnIdle();
-                break;
-
-            case DESTROY_STATE_CLEAR:
-                // State that clears all the local data of the cache.
-                clearStore().then(function () {
-                    // Terminate the operation once the local store has been cleared.
-                    operation.complete();
-                });
-                // Wait until the clear request completes.
-                operation.wait();
-                break;
-
-            default:
-                return false;
-        }
-        return true;
-    };
-
-    /** State machine describing the behavior of a prefetch operation.
-     * @method DataCache~prefetchStateMachine    
-     * @param {DataCacheOperation} operation - Operation being run.
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-     * @param {Object} [data] - 
-    
-     *  Prefetch operations have the lowest priority and will be interrupted by operations of
-     *  other kinds. A preempted prefetch operation will resume its execution only when the state
-     *  of the cache returns to idle.
-     * 
-     *  If a clear operation starts executing then all the prefetch operations are canceled,
-     *  even if they haven't started executing yet.
-     */
-    var prefetchStateMachine = function (operation, opTargetState, cacheState, data) {
-        
-
-        // Handle cancelation
-        if (!cancelStateMachine(operation, opTargetState, cacheState, data)) {
-
-            var transition = operation.transition;
-
-            // Handle preemption
-            if (cacheState !== CACHE_STATE_PREFETCH) {
-                if (cacheState === CACHE_STATE_DESTROY) {
-                    if (opTargetState !== OPERATION_STATE_CANCEL) {
-                        operation.cancel();
-                    }
-                } else if (cacheState === CACHE_STATE_IDLE) {
-                    // Signal the cache that a prefetch operation is running.
-                    changeState(CACHE_STATE_PREFETCH);
-                }
-                return true;
-            }
-
-            switch (opTargetState) {
-                case OPERATION_STATE_START:
-                    // Initial state of the operation.
-                    if (prefetchOperations[0] === operation) {
-                        transition(READ_STATE_LOCAL, operation.i);
-                    }
-                    break;
-
-                case READ_STATE_DONE:
-                    // State that determines if the operation can be resolved or has to
-                    // continue processing.
-                    // Data is expected to be the read page.
-                    var pending = operation.pending;
-
-                    if (pending > 0) {
-                        pending -= Math.min(pending, data.c);
-                    }
-
-                    // Are we done, or has all the data been stored?
-                    if (allDataLocal || pending === 0 || data.c < pageSize || overflowed) {
-                        operation.complete();
-                    } else {
-                        // Continue processing the operation.
-                        operation.pending = pending;
-                        transition(READ_STATE_LOCAL, data.i + pageSize);
-                    }
-                    break;
-
-                default:
-                    return readSaveStateMachine(operation, opTargetState, cacheState, data, true);
-            }
-        }
-        return true;
-    };
-
-    /** State machine describing the behavior of a read operation.
-     * @method DataCache~readStateMachine    
-     * @param {DataCacheOperation} operation - Operation being run.
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-     * @param {Object} [data] - 
-    
-     * Read operations have a higher priority than prefetch operations, but lower than
-     * clear operations. They will preempt any prefetch operation currently running
-     * but will be interrupted by a clear operation.
-     *          
-     * If a clear operation starts executing then all the currently running
-     * read operations are canceled. Read operations that haven't started yet will
-     * wait in the start state until the destory operation finishes.
-     */
-    var readStateMachine = function (operation, opTargetState, cacheState, data) {
-        
-
-        // Handle cancelation
-        if (!cancelStateMachine(operation, opTargetState, cacheState, data)) {
-
-            var transition = operation.transition;
-
-            // Handle preemption
-            if (cacheState !== CACHE_STATE_READ && opTargetState !== OPERATION_STATE_START) {
-                if (cacheState === CACHE_STATE_DESTROY) {
-                    if (opTargetState !== OPERATION_STATE_START) {
-                        operation.cancel();
-                    }
-                } else if (cacheState !== CACHE_STATE_WRITE) {
-                    // Signal the cache that a read operation is running.
-                    djsassert(state == CACHE_STATE_IDLE || state === CACHE_STATE_PREFETCH, "DataCache.readStateMachine() - cache is not on the read or idle state.");
-                    changeState(CACHE_STATE_READ);
-                }
-
-                return true;
-            }
-
-            switch (opTargetState) {
-                case OPERATION_STATE_START:
-                    // Initial state of the operation.
-                    // Wait until the cache is idle or prefetching.
-                    if (cacheState === CACHE_STATE_IDLE || cacheState === CACHE_STATE_PREFETCH) {
-                        // Signal the cache that a read operation is running.
-                        changeState(CACHE_STATE_READ);
-                        if (operation.c >= 0) {
-                            // Snap the requested range to a page boundary.
-                            var range = snapToPageBoundaries(operation.i, operation.c, pageSize);
-                            transition(READ_STATE_LOCAL, range.i);
-                        } else {
-                            transition(READ_STATE_DONE, operation);
-                        }
-                    }
-                    break;
-
-                case READ_STATE_DONE:
-                    // State that determines if the operation can be resolved or has to
-                    // continue processing.
-                    // Data is expected to be the read page.
-                    appendPage(operation, data);
-                    var len = getJsonValueArraryLength(operation.d);
-                    // Are we done?
-                    if (operation.c === len || data.c < pageSize) {
-                        // Update the stats, request for a prefetch operation.
-                        stats.cacheReads++;
-                        prefetch(data.i + data.c);
-                        // Terminate the operation.
-                        operation.complete();
-                    } else {
-                        // Continue processing the operation.
-                        transition(READ_STATE_LOCAL, data.i + pageSize);
-                    }
-                    break;
-
-                default:
-                    return readSaveStateMachine(operation, opTargetState, cacheState, data, false);
-            }
-        }
-
-        return true;
-    };
-
-    /** State machine describing the behavior for reading and saving data into the cache.
-     * @method DataCache~readSaveStateMachine    
-     * @param {DataCacheOperation} operation - Operation being run.
-     * @param {Object} opTargetState - Operation state to transition to.
-     * @param {Object} cacheState - Current cache state.
-     * @param {Object} [data] - 
-     * @param {Boolean} isPrefetch - Flag indicating whether a read (false) or prefetch (true) operation is running.
-     * This state machine contains behavior common to read and prefetch operations.
-    */
-    var readSaveStateMachine = function (operation, opTargetState, cacheState, data, isPrefetch) {
-
-        var error = operation.error;
-        var transition = operation.transition;
-        var wait = operation.wait;
-        var request;
-
-        switch (opTargetState) {
-            case OPERATION_STATE_END:
-                // State that signals the operation is done.
-                fireOnIdle();
-                break;
-
-            case READ_STATE_LOCAL:
-                // State that requests for a page from the local store.
-                // Data is expected to be the index of the page to request.
-                request = readPage(data).then(function (found, page) {
-                    // Signal the cache that a read operation is running.
-                    if (!operation.canceled) {
-                        if (found) {
-                            // The page is in the local store, check if the operation can be resolved.
-                            transition(READ_STATE_DONE, page);
-                        } else {
-                            // The page is not in the local store, request it from the source.
-                            transition(READ_STATE_SOURCE, data);
-                        }
-                    }
-                });
-                break;
-
-            case READ_STATE_SOURCE:
-                // State that requests for a page from the cache source.
-                // Data is expected to be the index of the page to request.
-                request = fetchPage(data).then(function (page) {
-                    // Signal the cache that a read operation is running.
-                    if (!operation.canceled) {
-                        // Update the stats and save the page to the local store.
-                        if (isPrefetch) {
-                            stats.prefetches++;
-                        } else {
-                            stats.netReads++;
-                        }
-                        transition(READ_STATE_SAVE, page);
-                    }
-                }, error);
-                break;
-
-            case READ_STATE_SAVE:
-                // State that saves a  page to the local store.
-                // Data is expected to be the page to save.
-                // Write access to the store is exclusive.
-                if (cacheState !== CACHE_STATE_WRITE) {
-                    changeState(CACHE_STATE_WRITE);
-                    request = savePage(data.i, data).then(function (saved) {
-                        if (!operation.canceled) {
-                            if (!saved && isPrefetch) {
-                                operation.pending = 0;
-                            }
-                            // Check if the operation can be resolved.
-                            transition(READ_STATE_DONE, data);
-                        }
-                        changeState(CACHE_STATE_IDLE);
-                    });
-                }
-                break;
-
-            default:
-                // Unknown state that can't be handled by this state machine.
-                return false;
-        }
-
-        if (request) {
-            // The operation might have been canceled between stack frames do to the async calls.
-            if (operation.canceled) {
-                request.cancel();
-            } else if (operation.s === opTargetState) {
-                // Wait for the request to complete.
-                wait(request);
-            }
-        }
-
-        return true;
-    };
-
-    // Initialize the cache.
-    store.read("__settings", function (_, settings) {
-        if (assigned(settings)) {
-            var settingsVersion = settings.version;
-            if (!settingsVersion || settingsVersion.indexOf("1.") !== 0) {
-                cacheFailureCallback("Unsupported cache store version " + settingsVersion)();
-                return;
-            }
-
-            if (pageSize !== settings.pageSize || source.identifier !== settings.sourceId) {
-                // The shape or the source of the data was changed so invalidate the store.
-                clearStore().then(function () {
-                    // Signal the cache is fully initialized.
-                    changeState(CACHE_STATE_IDLE);
-                }, cacheFailureCallback("Unable to clear store during initialization"));
-            } else {
-                // Restore the saved settings.
-                actualCacheSize = settings.actualCacheSize;
-                allDataLocal = settings.allDataLocal;
-                cacheSize = settings.cacheSize;
-                collectionCount = settings.collectionCount;
-                highestSavedPage = settings.highestSavedPage;
-                highestSavedPageSize = settings.highestSavedPageSize;
-                version = settingsVersion;
-
-                // Signal the cache is fully initialized.
-                changeState(CACHE_STATE_IDLE);
-            }
-        } else {
-            // This is a brand new cache.
-            saveSettings(function () {
-                // Signal the cache is fully initialized.
-                changeState(CACHE_STATE_IDLE);
-            }, cacheFailureCallback("Unable to write settings during initialization."));
-        }
-    }, cacheFailureCallback("Unable to read settings from store."));
-
-    return that;
-}
-
-/** Creates a data cache for a collection that is efficiently loaded on-demand.
- * @param options 
- * Options for the data cache, including name, source, pageSize, TODO check doku
- * prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
- * @returns {DataCache} A new data cache instance.
- */
-function createDataCache (options) {
-    checkUndefinedGreaterThanZero(options.pageSize, "pageSize");
-    checkUndefinedOrNumber(options.cacheSize, "cacheSize");
-    checkUndefinedOrNumber(options.prefetchSize, "prefetchSize");
-
-    if (!assigned(options.name)) {
-        throw { message: "Undefined or null name", options: options };
-    }
-
-    if (!assigned(options.source)) {
-        throw { message: "Undefined source", options: options };
-    }
-
-    return new DataCache(options);
-}
-
-
-/** estimateSize (see {@link estimateSize}) */
-exports.estimateSize = estimateSize;
-
-/** createDataCache */  
-exports.createDataCache = createDataCache;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/cache/source.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/cache/source.js b/datajs/src/lib/cache/source.js
deleted file mode 100644
index edc41b2..0000000
--- a/datajs/src/lib/cache/source.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- /** @module cache/source */
- 
-var utils = require("./../datajs.js").utils;
-var odataRequest = require("./../odata.js");
-
-var parseInt10 = utils.parseInt10;
-var normalizeURICase = utils.normalizeURICase;
-
-
-
-
-/** Appends the specified escaped query option to the specified URI.
- * @param {String} uri - URI to append option to.
- * @param {String} queryOption - Escaped query option to append.
- */
-function appendQueryOption(uri, queryOption) {
-    var separator = (uri.indexOf("?") >= 0) ? "&" : "?";
-    return uri + separator + queryOption;
-}
-
-/** Appends the specified segment to the given URI.
- * @param {String} uri - URI to append a segment to.
- * @param {String} segment - Segment to append.
- * @returns {String} The original URI with a new segment appended.
- */
-function appendSegment(uri, segment) {
-    var index = uri.indexOf("?");
-    var queryPortion = "";
-    if (index >= 0) {
-        queryPortion = uri.substr(index);
-        uri = uri.substr(0, index);
-    }
-
-    if (uri[uri.length - 1] !== "/") {
-        uri += "/";
-    }
-    return uri + segment + queryPortion;
-}
-
-/** Builds a request object to GET the specified URI.
- * @param {String} uri - URI for request.
- * @param {Object} options - Additional options.
- */
-function buildODataRequest(uri, options) {
-    return {
-        method: "GET",
-        requestUri: uri,
-        user: options.user,
-        password: options.password,
-        enableJsonpCallback: options.enableJsonpCallback,
-        callbackParameterName: options.callbackParameterName,
-        formatQueryString: options.formatQueryString
-    };
-}
-
-/** Finds the index where the value of a query option starts.
- * @param {String} uri - URI to search in.
- * @param {String} name - Name to look for.
- * @returns {Number} The index where the query option starts.
- */
-function findQueryOptionStart(uri, name) {
-    var result = -1;
-    var queryIndex = uri.indexOf("?");
-    if (queryIndex !== -1) {
-        var start = uri.indexOf("?" + name + "=", queryIndex);
-        if (start === -1) {
-            start = uri.indexOf("&" + name + "=", queryIndex);
-        }
-        if (start !== -1) {
-            result = start + name.length + 2;
-        }
-    }
-    return result;
-}
-
-/** Gets data from an OData service.
- * @param {String} uri - URI to the OData service.
- * @param {Object} options - Object with additional well-known request options.
- * @param {Function} success - Success callback.
- * @param {Function} error - Error callback.
- * @returns {Object} Object with an abort method.
- */
-function queryForData (uri, options, success, error) {
-    var request = queryForDataInternal(uri, options, {}, success, error);
-    return request;
-}
-
-/** Gets data from an OData service taking into consideration server side paging.
- * @param {String} uri - URI to the OData service.
- * @param {Object} options - Object with additional well-known request options.
- * @param {Array} data - Array that stores the data provided by the OData service.
- * @param {Function} success - Success callback.
- * @param {Function} error - Error callback.
- * @returns {Object} Object with an abort method.
- */
-function queryForDataInternal(uri, options, data, success, error) {
-
-    var request = buildODataRequest(uri, options);
-    var currentRequest = odataRequest.request(request, function (newData) {
-        var nextLink = newData["@odata.nextLink"];
-        if (nextLink) {
-            var index = uri.indexOf(".svc/", 0);
-            if (index != -1) {
-                nextLink = uri.substring(0, index + 5) + nextLink;
-            }
-        }
-
-        if (data.value && newData.value) {
-            data.value = data.value.concat(newData.value);
-        }
-        else {
-            for (var property in newData) {
-                if (property != "@odata.nextLink") {
-                    data[property] = newData[property];
-                }
-            }
-        }
-
-        if (nextLink) {
-            currentRequest = queryForDataInternal(nextLink, options, data, success, error);
-        }
-        else {
-            success(data);
-        }
-    }, error, undefined, options.httpClient, options.metadata);
-
-    return {
-        abort: function () {
-            currentRequest.abort();
-        }
-    };
-}
-
-/** Creates a data cache source object for requesting data from an OData service.
- * @class ODataCacheSource
- * @param options - Options for the cache data source.
- * @returns {ODataCacheSource} A new data cache source instance.
- */
-function ODataCacheSource (options) {
-    var that = this;
-    var uri = options.source;
-    
-    that.identifier = normalizeURICase(encodeURI(decodeURI(uri)));
-    that.options = options;
-
-    /** Gets the number of items in the collection.
-     * @method ODataCacheSource#count
-     * @param {Function} success - Success callback with the item count.
-     * @param {Function} error - Error callback.
-     * @returns {Object} Request object with an abort method.
-     */
-    that.count = function (success, error) {
-        var options = that.options;
-        return odataRequest.request(
-            buildODataRequest(appendSegment(uri, "$count"), options),
-            function (data) {
-                var count = parseInt10(data.toString());
-                if (isNaN(count)) {
-                    error({ message: "Count is NaN", count: count });
-                } else {
-                    success(count);
-                }
-            }, error, undefined, options.httpClient, options.metadata
-        );
-    };
-    
-    /** Gets a number of consecutive items from the collection.
-     * @method ODataCacheSource#read
-     * @param {Number} index - Zero-based index of the items to retrieve.
-     * @param {Number} count - Number of items to retrieve.
-     * @param {Function} success - Success callback with the requested items.
-     * @param {Function} error - Error callback.
-     * @returns {Object} Request object with an abort method.
-    */
-    that.read = function (index, count, success, error) {
-
-        var queryOptions = "$skip=" + index + "&$top=" + count;
-        return queryForData(appendQueryOption(uri, queryOptions), that.options, success, error);
-    };
-
-    return that;
-}
-
-
-
-/** ODataCacheSource (see {@link ODataCacheSource}) */
-exports.ODataCacheSource = ODataCacheSource;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/datajs.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/datajs.js b/datajs/src/lib/datajs.js
deleted file mode 100644
index 3c1e67a..0000000
--- a/datajs/src/lib/datajs.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module datajs */
-
-//expose all external usable functions via self.apiFunc = function
-exports.version = {
-    major: 1,
-    minor: 1,
-    build: 1
-};
-
-exports.deferred = require('./datajs/deferred.js');
-exports.utils = require('./datajs/utils.js');
-exports.xml = require('./datajs/xml.js');
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/datajs/deferred.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/datajs/deferred.js b/datajs/src/lib/datajs/deferred.js
deleted file mode 100644
index 7d5fd68..0000000
--- a/datajs/src/lib/datajs/deferred.js
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module datajs/deferred */
-
-
-
-/** Creates a new function to forward a call.
- * @param {Object} thisValue - Value to use as the 'this' object.
- * @param {String} name - Name of function to forward to.
- * @param {Object} returnValue - Return value for the forward call (helps keep identity when chaining calls).
- * @returns {Function} A new function that will forward a call.
- */
-function forwardCall(thisValue, name, returnValue) {
-    return function () {
-        thisValue[name].apply(thisValue, arguments);
-        return returnValue;
-    };
-}
-
-/** Initializes a new DjsDeferred object.
- * <ul>
- * <li> Compability Note A - Ordering of callbacks through chained 'then' invocations <br>
- *
- * The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
- * implies that .then() returns a distinct object.
- *
- * For compatibility with http://api.jquery.com/category/deferred-object/
- * we return this same object. This affects ordering, as
- * the jQuery version will fire callbacks in registration
- * order regardless of whether they occur on the result
- * or the original object.
- * </li>
- * <li>Compability Note B - Fulfillment value <br>
- *
- * The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
- * implies that the result of a success callback is the
- * fulfillment value of the object and is received by
- * other success callbacks that are chained.
- *
- * For compatibility with http://api.jquery.com/category/deferred-object/
- * we disregard this value instead.
- * </li></ul>
- * @class DjsDeferred 
- */
- function DjsDeferred() {
-    this._arguments = undefined;
-    this._done = undefined;
-    this._fail = undefined;
-    this._resolved = false;
-    this._rejected = false;
-}
-
-
-DjsDeferred.prototype = {
-
-    /** Adds success and error callbacks for this deferred object.
-     * See Compatibility Note A.
-     * @method DjsDeferred#then
-     * @param {function} [fulfilledHandler] - Success callback ( may be null)
-     * @param {function} [errorHandler] - Error callback ( may be null)
-     */
-    then: function (fulfilledHandler, errorHandler) {
-
-        if (fulfilledHandler) {
-            if (!this._done) {
-                this._done = [fulfilledHandler];
-            } else {
-                this._done.push(fulfilledHandler);
-            }
-        }
-
-        if (errorHandler) {
-            if (!this._fail) {
-                this._fail = [errorHandler];
-            } else {
-                this._fail.push(errorHandler);
-            }
-        }
-
-        //// See Compatibility Note A in the DjsDeferred constructor.
-        //// if (!this._next) {
-        ////    this._next = createDeferred();
-        //// }
-        //// return this._next.promise();
-
-        if (this._resolved) {
-            this.resolve.apply(this, this._arguments);
-        } else if (this._rejected) {
-            this.reject.apply(this, this._arguments);
-        }
-
-        return this;
-    },
-
-    /** Invokes success callbacks for this deferred object.
-     * All arguments are forwarded to success callbacks.
-     * @method DjsDeferred#resolve
-     */
-    resolve: function (/* args */) {
-        if (this._done) {
-            var i, len;
-            for (i = 0, len = this._done.length; i < len; i++) {
-                //// See Compability Note B - Fulfillment value.
-                //// var nextValue =
-                this._done[i].apply(null, arguments);
-            }
-
-            //// See Compatibility Note A in the DjsDeferred constructor.
-            //// this._next.resolve(nextValue);
-            //// delete this._next;
-
-            this._done = undefined;
-            this._resolved = false;
-            this._arguments = undefined;
-        } else {
-            this._resolved = true;
-            this._arguments = arguments;
-        }
-    },
-
-    /** Invokes error callbacks for this deferred object.
-     * All arguments are forwarded to error callbacks.
-     * @method DjsDeferred#reject
-     */
-    reject: function (/* args */) {
-        
-        if (this._fail) {
-            var i, len;
-            for (i = 0, len = this._fail.length; i < len; i++) {
-                this._fail[i].apply(null, arguments);
-            }
-
-            this._fail = undefined;
-            this._rejected = false;
-            this._arguments = undefined;
-        } else {
-            this._rejected = true;
-            this._arguments = arguments;
-        }
-    },
-
-    /** Returns a version of this object that has only the read-only methods available.
-     * @method DjsDeferred#promise
-     * @returns An object with only the promise object.
-     */
-
-    promise: function () {
-        var result = {};
-        result.then = forwardCall(this, "then", result);
-        return result;
-    }
-};
-
-/** Creates a deferred object.
- * @returns {DjsDeferred} A new deferred object. If jQuery is installed, then a jQueryDeferred object is returned, which provides a superset of features.
-*/
-function createDeferred() {
-    if (window.jQuery && window.jQuery.Deferred) {
-        return new window.jQuery.Deferred();
-    } else {
-        return new DjsDeferred();
-    }
-};
-
-
-
-
-/** createDeferred (see {@link module:datajs/deferred~createDeferred}) */
-exports.createDeferred = createDeferred;
-
-/** DjsDeferred (see {@link DjsDeferred}) */
-exports.DjsDeferred = DjsDeferred;
\ No newline at end of file


[23/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/demo/scripts/datajs-1.1.2.js
----------------------------------------------------------------------
diff --git a/odatajs/demo/scripts/datajs-1.1.2.js b/odatajs/demo/scripts/datajs-1.1.2.js
new file mode 100644
index 0000000..5040efc
--- /dev/null
+++ b/odatajs/demo/scripts/datajs-1.1.2.js
@@ -0,0 +1,10577 @@
+// 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.
+
+// odatajs.js
+
+(function (window, undefined) {
+
+    var datajs = window.odatajs || {};
+    var odata = window.OData || {};
+
+    // AMD support
+    if (typeof define === 'function' && define.amd) {
+        define('datajs', datajs);
+        define('OData', odata);
+    } else {
+        window.odatajs = datajs;
+        window.OData = odata;
+    }
+
+    odatajs.version = {
+        major: 1,
+        minor: 1,
+        build: 1
+    };
+
+
+    var activeXObject = function (progId) {
+        /// <summary>Creates a new ActiveXObject from the given progId.</summary>
+        /// <param name="progId" type="String" mayBeNull="false" optional="false">
+        ///    ProgId string of the desired ActiveXObject.
+        /// </param>
+        /// <remarks>
+        ///    This function throws whatever exception might occur during the creation
+        ///    of the ActiveXObject.
+        /// </remarks>
+        /// <returns type="Object">
+        ///     The ActiveXObject instance. Null if ActiveX is not supported by the
+        ///     browser.
+        /// </returns>
+        if (window.ActiveXObject) {
+            return new window.ActiveXObject(progId);
+        }
+        return null;
+    };
+
+    var assigned = function (value) {
+        /// <summary>Checks whether the specified value is different from null and undefined.</summary>
+        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
+        /// <returns type="Boolean">true if the value is assigned; false otherwise.</returns>
+        return value !== null && value !== undefined;
+    };
+
+    var contains = function (arr, item) {
+        /// <summary>Checks whether the specified item is in the array.</summary>
+        /// <param name="arr" type="Array" optional="false" mayBeNull="false">Array to check in.</param>
+        /// <param name="item">Item to look for.</param>
+        /// <returns type="Boolean">true if the item is contained, false otherwise.</returns>
+
+        var i, len;
+        for (i = 0, len = arr.length; i < len; i++) {
+            if (arr[i] === item) {
+                return true;
+            }
+        }
+
+        return false;
+    };
+
+    var defined = function (a, b) {
+        /// <summary>Given two values, picks the first one that is not undefined.</summary>
+        /// <param name="a">First value.</param>
+        /// <param name="b">Second value.</param>
+        /// <returns>a if it's a defined value; else b.</returns>
+        return (a !== undefined) ? a : b;
+    };
+
+    var delay = function (callback) {
+        /// <summary>Delays the invocation of the specified function until execution unwinds.</summary>
+        /// <param name="callback" type="Function">Callback function.</param>
+        if (arguments.length === 1) {
+            window.setTimeout(callback, 0);
+            return;
+        }
+
+        var args = Array.prototype.slice.call(arguments, 1);
+        window.setTimeout(function () {
+            callback.apply(this, args);
+        }, 0);
+    };
+
+
+    var extend = function (target, values) {
+        /// <summary>Extends the target with the specified values.</summary>
+        /// <param name="target" type="Object">Object to add properties to.</param>
+        /// <param name="values" type="Object">Object with properties to add into target.</param>
+        /// <returns type="Object">The target object.</returns>
+
+        for (var name in values) {
+            target[name] = values[name];
+        }
+
+        return target;
+    };
+
+    var find = function (arr, callback) {
+        /// <summary>Returns the first item in the array that makes the callback function true.</summary>
+        /// <param name="arr" type="Array" optional="false" mayBeNull="true">Array to check in.</param>
+        /// <param name="callback" type="Function">Callback function to invoke once per item in the array.</param>
+        /// <returns>The first item that makes the callback return true; null otherwise or if the array is null.</returns>
+
+        if (arr) {
+            var i, len;
+            for (i = 0, len = arr.length; i < len; i++) {
+                if (callback(arr[i])) {
+                    return arr[i];
+                }
+            }
+        }
+        return null;
+    };
+
+    var isArray = function (value) {
+        /// <summary>Checks whether the specified value is an array object.</summary>
+        /// <param name="value">Value to check.</param>
+        /// <returns type="Boolean">true if the value is an array object; false otherwise.</returns>
+
+        return Object.prototype.toString.call(value) === "[object Array]";
+    };
+
+    var isDate = function (value) {
+        /// <summary>Checks whether the specified value is a Date object.</summary>
+        /// <param name="value">Value to check.</param>
+        /// <returns type="Boolean">true if the value is a Date object; false otherwise.</returns>
+
+        return Object.prototype.toString.call(value) === "[object Date]";
+    };
+
+    var isObject = function (value) {
+        /// <summary>Tests whether a value is an object.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <remarks>
+        ///     Per javascript rules, null and array values are objects and will cause this function to return true.
+        /// </remarks>
+        /// <returns type="Boolean">True is the value is an object; false otherwise.</returns>
+
+        return typeof value === "object";
+    };
+
+    var parseInt10 = function (value) {
+        /// <summary>Parses a value in base 10.</summary>
+        /// <param name="value" type="String">String value to parse.</param>
+        /// <returns type="Number">The parsed value, NaN if not a valid value.</returns>
+
+        return parseInt(value, 10);
+    };
+
+    var renameProperty = function (obj, oldName, newName) {
+        /// <summary>Renames a property in an object.</summary>
+        /// <param name="obj" type="Object">Object in which the property will be renamed.</param>
+        /// <param name="oldName" type="String">Name of the property that will be renamed.</param>
+        /// <param name="newName" type="String">New name of the property.</param>
+        /// <remarks>
+        ///    This function will not do anything if the object doesn't own a property with the specified old name.
+        /// </remarks>
+
+        if (obj.hasOwnProperty(oldName)) {
+            obj[newName] = obj[oldName];
+            delete obj[oldName];
+        }
+    };
+
+    var throwErrorCallback = function (error) {
+        /// <summary>Default error handler.</summary>
+        /// <param name="error" type="Object">Error to handle.</param>
+        throw error;
+    };
+
+    var trimString = function (str) {
+        /// <summary>Removes leading and trailing whitespaces from a string.</summary>
+        /// <param name="str" type="String" optional="false" mayBeNull="false">String to trim</param>
+        /// <returns type="String">The string with no leading or trailing whitespace.</returns>
+
+        if (str.trim) {
+            return str.trim();
+        }
+
+        return str.replace(/^\s+|\s+$/g, '');
+    };
+
+    var undefinedDefault = function (value, defaultValue) {
+        /// <summary>Returns a default value in place of undefined.</summary>
+        /// <param name="value" mayBeNull="true" optional="true">Value to check.</param>
+        /// <param name="defaultValue">Value to return if value is undefined.</param>
+        /// <returns>value if it's defined; defaultValue otherwise.</returns>
+        /// <remarks>
+        /// This should only be used for cases where falsy values are valid;
+        /// otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
+        /// </remarks>
+        return (value !== undefined) ? value : defaultValue;
+    };
+
+    // Regular expression that splits a uri into its components:
+    // 0 - is the matched string.
+    // 1 - is the scheme.
+    // 2 - is the authority.
+    // 3 - is the path.
+    // 4 - is the query.
+    // 5 - is the fragment.
+    var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
+    var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
+
+    var getURIInfo = function (uri) {
+        /// <summary>Gets information about the components of the specified URI.</summary>
+        /// <param name="uri" type="String">URI to get information from.</param>
+        /// <returns type="Object">
+        /// An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
+        /// </returns>
+
+        var result = { isAbsolute: false };
+
+        if (uri) {
+            var matches = uriRegEx.exec(uri);
+            if (matches) {
+                var i, len;
+                for (i = 0, len = uriPartNames.length; i < len; i++) {
+                    if (matches[i + 1]) {
+                        result[uriPartNames[i]] = matches[i + 1];
+                    }
+                }
+            }
+            if (result.scheme) {
+                result.isAbsolute = true;
+            }
+        }
+
+        return result;
+    };
+
+    var getURIFromInfo = function (uriInfo) {
+        /// <summary>Builds a URI string from its components.</summary>
+        /// <param name="uriInfo" type="Object"> An object with uri parts (scheme, authority, etc.).</param>
+        /// <returns type="String">URI string.</returns>
+
+        return "".concat(
+            uriInfo.scheme || "",
+            uriInfo.authority || "",
+            uriInfo.path || "",
+            uriInfo.query || "",
+            uriInfo.fragment || "");
+    };
+
+    // Regular expression that splits a uri authority into its subcomponents:
+    // 0 - is the matched string.
+    // 1 - is the userinfo subcomponent.
+    // 2 - is the host subcomponent.
+    // 3 - is the port component.
+    var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
+
+    // Regular expression that matches percentage enconded octects (i.e %20 or %3A);
+    var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
+
+    var normalizeURICase = function (uri) {
+        /// <summary>Normalizes the casing of a URI.</summary>
+        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
+        /// <returns type="String">The URI normalized to lower case.</returns>
+
+        var uriInfo = getURIInfo(uri);
+        var scheme = uriInfo.scheme;
+        var authority = uriInfo.authority;
+
+        if (scheme) {
+            uriInfo.scheme = scheme.toLowerCase();
+            if (authority) {
+                var matches = uriAuthorityRegEx.exec(authority);
+                if (matches) {
+                    uriInfo.authority = "//" +
+                    (matches[1] ? matches[1] + "@" : "") +
+                    (matches[2].toLowerCase()) +
+                    (matches[3] ? ":" + matches[3] : "");
+                }
+            }
+        }
+
+        uri = getURIFromInfo(uriInfo);
+
+        return uri.replace(pctEncodingRegEx, function (str) {
+            return str.toLowerCase();
+        });
+    };
+
+    var normalizeURI = function (uri, base) {
+        /// <summary>Normalizes a possibly relative URI with a base URI.</summary>
+        /// <param name="uri" type="String">URI to normalize, absolute or relative.</param>
+        /// <param name="base" type="String" mayBeNull="true">Base URI to compose with.</param>
+        /// <returns type="String">The composed URI if relative; the original one if absolute.</returns>
+
+        if (!base) {
+            return uri;
+        }
+
+        var uriInfo = getURIInfo(uri);
+        if (uriInfo.isAbsolute) {
+            return uri;
+        }
+
+        var baseInfo = getURIInfo(base);
+        var normInfo = {};
+        var path;
+
+        if (uriInfo.authority) {
+            normInfo.authority = uriInfo.authority;
+            path = uriInfo.path;
+            normInfo.query = uriInfo.query;
+        } else {
+            if (!uriInfo.path) {
+                path = baseInfo.path;
+                normInfo.query = uriInfo.query || baseInfo.query;
+            } else {
+                if (uriInfo.path.charAt(0) === '/') {
+                    path = uriInfo.path;
+                } else {
+                    path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
+                }
+                normInfo.query = uriInfo.query;
+            }
+            normInfo.authority = baseInfo.authority;
+        }
+
+        normInfo.path = removeDotsFromPath(path);
+
+        normInfo.scheme = baseInfo.scheme;
+        normInfo.fragment = uriInfo.fragment;
+
+        return getURIFromInfo(normInfo);
+    };
+
+    var mergeUriPathWithBase = function (uriPath, basePath) {
+        /// <summary>Merges the path of a relative URI and a base URI.</summary>
+        /// <param name="uriPath" type="String>Relative URI path.</param>
+        /// <param name="basePath" type="String">Base URI path.</param>
+        /// <returns type="String">A string with the merged path.</returns>
+
+        var path = "/";
+        var end;
+
+        if (basePath) {
+            end = basePath.lastIndexOf("/");
+            path = basePath.substring(0, end);
+
+            if (path.charAt(path.length - 1) !== "/") {
+                path = path + "/";
+            }
+        }
+
+        return path + uriPath;
+    };
+
+    var removeDotsFromPath = function (path) {
+        /// <summary>Removes the special folders . and .. from a URI's path.</summary>
+        /// <param name="path" type="string">URI path component.</param>
+        /// <returns type="String">Path without any . and .. folders.</returns>
+
+        var result = "";
+        var segment = "";
+        var end;
+
+        while (path) {
+            if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
+                path = path.replace(/^\.\.?\/?/g, "");
+            } else if (path.indexOf("/..") === 0) {
+                path = path.replace(/^\/\..\/?/g, "/");
+                end = result.lastIndexOf("/");
+                if (end === -1) {
+                    result = "";
+                } else {
+                    result = result.substring(0, end);
+                }
+            } else if (path.indexOf("/.") === 0) {
+                path = path.replace(/^\/\.\/?/g, "/");
+            } else {
+                segment = path;
+                end = path.indexOf("/", 1);
+                if (end !== -1) {
+                    segment = path.substring(0, end);
+                }
+                result = result + segment;
+                path = path.replace(segment, "");
+            }
+        }
+        return result;
+    };
+
+    var convertByteArrayToHexString = function (str) {
+        var arr = [];
+        if (window.atob === undefined) {
+            arr = decodeBase64(str);
+        } else {
+            var binaryStr = window.atob(str);
+            for (var i = 0; i < binaryStr.length; i++) {
+                arr.push(binaryStr.charCodeAt(i));
+            }
+        }
+        var hexValue = "";
+        var hexValues = "0123456789ABCDEF";
+        for (var j = 0; j < arr.length; j++) {
+            var t = arr[j];
+            hexValue += hexValues[t >> 4];
+            hexValue += hexValues[t & 0x0F];
+        }
+        return hexValue;
+    };
+
+    var decodeBase64 = function (str) {
+        var binaryString = "";
+        for (var i = 0; i < str.length; i++) {
+            var base65IndexValue = getBase64IndexValue(str[i]);
+            var binaryValue = "";
+            if (base65IndexValue !== null) {
+                binaryValue = base65IndexValue.toString(2);
+                binaryString += addBase64Padding(binaryValue);
+            }
+        }
+        var byteArray = [];
+        var numberOfBytes = parseInt(binaryString.length / 8, 10);
+        for (i = 0; i < numberOfBytes; i++) {
+            var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
+            byteArray.push(intValue);
+        }
+        return byteArray;
+    };
+
+    var getBase64IndexValue = function (character) {
+        var asciiCode = character.charCodeAt(0);
+        var asciiOfA = 65;
+        var differenceBetweenZanda = 6;
+        if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
+            return asciiCode - asciiOfA;
+        } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
+            return asciiCode - asciiOfA - differenceBetweenZanda;
+        } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
+            return asciiCode + 4;
+        } else if (character == "+") {
+            return 62;
+        } else if (character == "/") {
+            return 63;
+        } else {
+            return null;
+        }
+    };
+
+    var addBase64Padding = function (binaryString) {
+        while (binaryString.length < 6) {
+            binaryString = "0" + binaryString;
+        }
+        return binaryString;
+    };
+
+
+    // URI prefixes to generate smaller code.
+    var http = "http://";
+    var w3org = http + "www.w3.org/";               // http://www.w3.org/
+
+    var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
+    var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
+    var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
+
+    var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
+
+    var hasLeadingOrTrailingWhitespace = function (text) {
+        /// <summary>Checks whether the specified string has leading or trailing spaces.</summary>
+        /// <param name="text" type="String">String to check.</param>
+        /// <returns type="Boolean">true if text has any leading or trailing whitespace; false otherwise.</returns>
+
+        var re = /(^\s)|(\s$)/;
+        return re.test(text);
+    };
+
+    var isWhitespace = function (text) {
+        /// <summary>Determines whether the specified text is empty or whitespace.</summary>
+        /// <param name="text" type="String">Value to inspect.</param>
+        /// <returns type="Boolean">true if the text value is empty or all whitespace; false otherwise.</returns>
+
+        var ws = /^\s*$/;
+        return text === null || ws.test(text);
+    };
+
+    var isWhitespacePreserveContext = function (domElement) {
+        /// <summary>Determines whether the specified element has xml:space='preserve' applied.</summary>
+        /// <param name="domElement">Element to inspect.</param>
+        /// <returns type="Boolean">Whether xml:space='preserve' is in effect.</returns>
+
+        while (domElement !== null && domElement.nodeType === 1) {
+            var val = xmlAttributeValue(domElement, "space", xmlNS);
+            if (val === "preserve") {
+                return true;
+            } else if (val === "default") {
+                break;
+            } else {
+                domElement = domElement.parentNode;
+            }
+        }
+
+        return false;
+    };
+
+    var isXmlNSDeclaration = function (domAttribute) {
+        /// <summary>Determines whether the attribute is a XML namespace declaration.</summary>
+        /// <param name="domAttribute">Element to inspect.</param>
+        /// <returns type="Boolean">
+        ///    True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
+        /// </returns>
+
+        var nodeName = domAttribute.nodeName;
+        return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
+    };
+
+    var safeSetProperty = function (obj, name, value) {
+        /// <summary>Safely set as property in an object by invoking obj.setProperty.</summary>
+        /// <param name="obj">Object that exposes a setProperty method.</param>
+        /// <param name="name" type="String" mayBeNull="false">Property name.</param>
+        /// <param name="value">Property value.</param>
+
+        try {
+            obj.setProperty(name, value);
+        } catch (_) { }
+    };
+
+    var msXmlDom3 = function () {
+        /// <summary>Creates an configures new MSXML 3.0 ActiveX object.</summary>
+        /// <remakrs>
+        ///    This function throws any exception that occurs during the creation
+        ///    of the MSXML 3.0 ActiveX object.
+        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
+
+        var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
+        if (msxml3) {
+            safeSetProperty(msxml3, "ProhibitDTD", true);
+            safeSetProperty(msxml3, "MaxElementDepth", 256);
+            safeSetProperty(msxml3, "AllowDocumentFunction", false);
+            safeSetProperty(msxml3, "AllowXsltScript", false);
+        }
+        return msxml3;
+    };
+
+    var msXmlDom = function () {
+        /// <summary>Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.</summary>
+        /// <remakrs>
+        ///    This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
+        ///    it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
+        ///    happens during the creation of the MSXML 6.0 will be handled by the function while
+        ///    the ones that happend during the creation of the MSXML 3.0 will be thrown.
+        /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns>
+
+        try {
+            var msxml = activeXObject("Msxml2.DOMDocument.6.0");
+            if (msxml) {
+                msxml.async = true;
+            }
+            return msxml;
+        } catch (_) {
+            return msXmlDom3();
+        }
+    };
+
+    var msXmlParse = function (text) {
+        /// <summary>Parses an XML string using the MSXML DOM.</summary>
+        /// <remakrs>
+        ///    This function throws any exception that occurs during the creation
+        ///    of the MSXML ActiveX object.  It also will throw an exception
+        ///    in case of a parsing error.
+        /// <returns type="Object">New MSXML DOMDocument node representing the parsed XML string.</returns>
+
+        var dom = msXmlDom();
+        if (!dom) {
+            return null;
+        }
+
+        dom.loadXML(text);
+        var parseError = dom.parseError;
+        if (parseError.errorCode !== 0) {
+            xmlThrowParserError(parseError.reason, parseError.srcText, text);
+        }
+        return dom;
+    };
+
+    var xmlThrowParserError = function (exceptionOrReason, srcText, errorXmlText) {
+        /// <summary>Throws a new exception containing XML parsing error information.</summary>
+        /// <param name="exceptionOrReason">
+        ///    String indicatin the reason of the parsing failure or
+        ///    Object detailing the parsing error.
+        /// </param>
+        /// <param name="srcText" type="String">
+        ///    String indicating the part of the XML string that caused the parsing error.
+        /// </param>
+        /// <param name="errorXmlText" type="String">XML string for wich the parsing failed.</param>
+
+        if (typeof exceptionOrReason === "string") {
+            exceptionOrReason = { message: exceptionOrReason };
+        }
+        throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
+    };
+
+    var xmlParse = function (text) {
+        /// <summary>Returns an XML DOM document from the specified text.</summary>
+        /// <param name="text" type="String">Document text.</param>
+        /// <returns>XML DOM document.</returns>
+        /// <remarks>This function will throw an exception in case of a parse error.</remarks>
+
+        var domParser = window.DOMParser && new window.DOMParser();
+        var dom;
+
+        if (!domParser) {
+            dom = msXmlParse(text);
+            if (!dom) {
+                xmlThrowParserError("XML DOM parser not supported");
+            }
+            return dom;
+        }
+
+        try {
+            dom = domParser.parseFromString(text, "text/xml");
+        } catch (e) {
+            xmlThrowParserError(e, "", text);
+        }
+
+        var element = dom.documentElement;
+        var nsURI = element.namespaceURI;
+        var localName = xmlLocalName(element);
+
+        // Firefox reports errors by returing the DOM for an xml document describing the problem.
+        if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
+            var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
+            var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
+            xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
+        }
+
+        // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
+        // The error may be localized, so instead we simply check for a header as the
+        // top element or descendant child of the document.
+        if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
+            var reason = "";
+            var siblings = [];
+            var cursor = element.firstChild;
+            while (cursor) {
+                if (cursor.nodeType === 1) {
+                    reason += xmlInnerText(cursor) || "";
+                }
+                siblings.push(cursor.nextSibling);
+                cursor = cursor.firstChild || siblings.shift();
+            }
+            reason += xmlInnerText(element) || "";
+            xmlThrowParserError(reason, "", text);
+        }
+
+        return dom;
+    };
+
+    var xmlQualifiedName = function (prefix, name) {
+        /// <summary>Builds a XML qualified name string in the form of "prefix:name".</summary>
+        /// <param name="prefix" type="String" maybeNull="true">Prefix string.</param>
+        /// <param name="name" type="String">Name string to qualify with the prefix.</param>
+        /// <returns type="String">Qualified name.</returns>
+
+        return prefix ? prefix + ":" + name : name;
+    };
+
+    var xmlAppendText = function (domNode, textNode) {
+        /// <summary>Appends a text node into the specified DOM element node.</summary>
+        /// <param name="domNode">DOM node for the element.</param>
+        /// <param name="text" type="String" mayBeNull="false">Text to append as a child of element.</param>
+        if (hasLeadingOrTrailingWhitespace(textNode.data)) {
+            var attr = xmlAttributeNode(domNode, xmlNS, "space");
+            if (!attr) {
+                attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
+                xmlAppendChild(domNode, attr);
+            }
+            attr.value = "preserve";
+        }
+        domNode.appendChild(textNode);
+        return domNode;
+    };
+
+    var xmlAttributes = function (element, onAttributeCallback) {
+        /// <summary>Iterates through the XML element's attributes and invokes the callback function for each one.</summary>
+        /// <param name="element">Wrapped element to iterate over.</param>
+        /// <param name="onAttributeCallback" type="Function">Callback function to invoke with wrapped attribute nodes.</param>
+
+        var attributes = element.attributes;
+        var i, len;
+        for (i = 0, len = attributes.length; i < len; i++) {
+            onAttributeCallback(attributes.item(i));
+        }
+    };
+
+    var xmlAttributeValue = function (domNode, localName, nsURI) {
+        /// <summary>Returns the value of a DOM element's attribute.</summary>
+        /// <param name="domNode">DOM node for the owning element.</param>
+        /// <param name="localName" type="String">Local name of the attribute.</param>
+        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
+        /// <returns type="String" maybeNull="true">The attribute value, null if not found.</returns>
+
+        var attribute = xmlAttributeNode(domNode, localName, nsURI);
+        return attribute ? xmlNodeValue(attribute) : null;
+    };
+
+    var xmlAttributeNode = function (domNode, localName, nsURI) {
+        /// <summary>Gets an attribute node from a DOM element.</summary>
+        /// <param name="domNode">DOM node for the owning element.</param>
+        /// <param name="localName" type="String">Local name of the attribute.</param>
+        /// <param name="nsURI" type="String">Namespace URI of the attribute.</param>
+        /// <returns>The attribute node, null if not found.</returns>
+
+        var attributes = domNode.attributes;
+        if (attributes.getNamedItemNS) {
+            return attributes.getNamedItemNS(nsURI || null, localName);
+        }
+
+        return attributes.getQualifiedItem(localName, nsURI) || null;
+    };
+
+    var xmlBaseURI = function (domNode, baseURI) {
+        /// <summary>Gets the value of the xml:base attribute on the specified element.</summary>
+        /// <param name="domNode">Element to get xml:base attribute value from.</param>
+        /// <param name="baseURI" mayBeNull="true" optional="true">Base URI used to normalize the value of the xml:base attribute.</param>
+        /// <returns type="String">Value of the xml:base attribute if found; the baseURI or null otherwise.</returns>
+
+        var base = xmlAttributeNode(domNode, "base", xmlNS);
+        return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
+    };
+
+
+    var xmlChildElements = function (domNode, onElementCallback) {
+        /// <summary>Iterates through the XML element's child DOM elements and invokes the callback function for each one.</summary>
+        /// <param name="element">DOM Node containing the DOM elements to iterate over.</param>
+        /// <param name="onElementCallback" type="Function">Callback function to invoke for each child DOM element.</param>
+
+        xmlTraverse(domNode, /*recursive*/false, function (child) {
+            if (child.nodeType === 1) {
+                onElementCallback(child);
+            }
+            // continue traversing.
+            return true;
+        });
+    };
+
+    var xmlFindElementByPath = function (root, namespaceURI, path) {
+        /// <summary>Gets the descendant element under root that corresponds to the specified path and namespace URI.</summary>
+        /// <param name="root">DOM element node from which to get the descendant element.</param>
+        /// <param name="namespaceURI" type="String">The namespace URI of the element to match.</param>
+        /// <param name="path" type="String">Path to the desired descendant element.</param>
+        /// <returns>The element specified by path and namespace URI.</returns>
+        /// <remarks>
+        ///     All the elements in the path are matched against namespaceURI.
+        ///     The function will stop searching on the first element that doesn't match the namespace and the path.
+        /// </remarks>
+
+        var parts = path.split("/");
+        var i, len;
+        for (i = 0, len = parts.length; i < len; i++) {
+            root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
+        }
+        return root || null;
+    };
+
+    var xmlFindNodeByPath = function (root, namespaceURI, path) {
+        /// <summary>Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.</summary>
+        /// <param name="root">DOM element node from which to get the descendant node.</param>
+        /// <param name="namespaceURI" type="String">The namespace URI of the node to match.</param>
+        /// <param name="path" type="String">Path to the desired descendant node.</param>
+        /// <returns>The node specified by path and namespace URI.</returns>
+        /// <remarks>
+        ///     This function will traverse the path and match each node associated to a path segement against the namespace URI.
+        ///     The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
+        ///
+        ///     The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
+        /// </remarks>
+
+        var lastSegmentStart = path.lastIndexOf("/");
+        var nodePath = path.substring(lastSegmentStart + 1);
+        var parentPath = path.substring(0, lastSegmentStart);
+
+        var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
+        if (node) {
+            if (nodePath.charAt(0) === "@") {
+                return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
+            }
+            return xmlFirstChildElement(node, namespaceURI, nodePath);
+        }
+        return null;
+    };
+
+    var xmlFirstChildElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the child DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
+    };
+
+    var xmlFirstDescendantElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        if (domNode.getElementsByTagNameNS) {
+            var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
+            return result.length > 0 ? result[0] : null;
+        }
+        return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
+    };
+
+    var xmlFirstElementMaybeRecursive = function (domNode, namespaceURI, localName, recursive) {
+        /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary>
+        /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <param name="recursive" type="Boolean">
+        ///     True if the search should include all the descendants of the DOM node.
+        ///     False if the search should be scoped only to the direct children of the DOM node.
+        /// </param>
+        /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
+
+        var firstElement = null;
+        xmlTraverse(domNode, recursive, function (child) {
+            if (child.nodeType === 1) {
+                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
+                var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
+
+                if (isExpectedNamespace && isExpectedNodeName) {
+                    firstElement = child;
+                }
+            }
+            return firstElement === null;
+        });
+        return firstElement;
+    };
+
+    var xmlInnerText = function (xmlElement) {
+        /// <summary>Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.</summary>
+        /// <param name="domElement">Element to get values for.</param>
+        /// <returns type="String">Text for all direct children.</returns>
+
+        var result = null;
+        var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
+        var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
+        var whitespacePreserveContext;
+
+        xmlTraverse(root, false, function (child) {
+            if (child.nodeType === 3 || child.nodeType === 4) {
+                // isElementContentWhitespace indicates that this is 'ignorable whitespace',
+                // but it's not defined by all browsers, and does not honor xml:space='preserve'
+                // in some implementations.
+                //
+                // If we can't tell either way, we walk up the tree to figure out whether
+                // xml:space is set to preserve; otherwise we discard pure-whitespace.
+                //
+                // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
+                var text = xmlNodeValue(child);
+                var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
+                if (!shouldInclude) {
+                    // Walk up the tree to figure out whether we are in xml:space='preserve' context
+                    // for the cursor (needs to happen only once).
+                    if (whitespacePreserveContext === undefined) {
+                        whitespacePreserveContext = isWhitespacePreserveContext(root);
+                    }
+
+                    shouldInclude = whitespacePreserveContext;
+                }
+
+                if (shouldInclude) {
+                    if (!result) {
+                        result = text;
+                    } else {
+                        result += text;
+                    }
+                }
+            }
+            // Continue traversing?
+            return true;
+        });
+        return result;
+    };
+
+    var xmlLocalName = function (domNode) {
+        /// <summary>Returns the localName of a XML node.</summary>
+        /// <param name="domNode">DOM node to get the value from.</param>
+        /// <returns type="String">localName of domNode.</returns>
+
+        return domNode.localName || domNode.baseName;
+    };
+
+    var xmlNamespaceURI = function (domNode) {
+        /// <summary>Returns the namespace URI of a XML node.</summary>
+        /// <param name="node">DOM node to get the value from.</param>
+        /// <returns type="String">Namespace URI of domNode.</returns>
+
+        return domNode.namespaceURI || null;
+    };
+
+    var xmlNodeValue = function (domNode) {
+        /// <summary>Returns the value or the inner text of a XML node.</summary>
+        /// <param name="node">DOM node to get the value from.</param>
+        /// <returns>Value of the domNode or the inner text if domNode represents a DOM element node.</returns>
+        
+        if (domNode.nodeType === 1) {
+            return xmlInnerText(domNode);
+        }
+        return domNode.nodeValue;
+    };
+
+    var xmlTraverse = function (domNode, recursive, onChildCallback) {
+        /// <summary>Walks through the descendants of the domNode and invokes a callback for each node.</summary>
+        /// <param name="domNode">DOM node whose descendants are going to be traversed.</param>
+        /// <param name="recursive" type="Boolean">
+        ///    True if the traversal should include all the descenants of the DOM node.
+        ///    False if the traversal should be scoped only to the direct children of the DOM node.
+        /// </param>
+        /// <returns type="String">Namespace URI of node.</returns>
+
+        var subtrees = [];
+        var child = domNode.firstChild;
+        var proceed = true;
+        while (child && proceed) {
+            proceed = onChildCallback(child);
+            if (proceed) {
+                if (recursive && child.firstChild) {
+                    subtrees.push(child.firstChild);
+                }
+                child = child.nextSibling || subtrees.shift();
+            }
+        }
+    };
+
+    var xmlSiblingElement = function (domNode, namespaceURI, localName) {
+        /// <summary>Returns the next sibling DOM element of the specified DOM node.</summary>
+        /// <param name="domNode">DOM node from which the next sibling is going to be retrieved.</param>
+        /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param>
+        /// <param name="localName" type="String" optional="true">Name of the element to match.</param>
+        /// <returns>The node's next sibling DOM element, null if there is none.</returns>
+
+        var sibling = domNode.nextSibling;
+        while (sibling) {
+            if (sibling.nodeType === 1) {
+                var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
+                var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
+
+                if (isExpectedNamespace && isExpectedNodeName) {
+                    return sibling;
+                }
+            }
+            sibling = sibling.nextSibling;
+        }
+        return null;
+    };
+
+    var xmlDom = function () {
+        /// <summary>Creates a new empty DOM document node.</summary>
+        /// <returns>New DOM document node.</returns>
+        /// <remarks>
+        ///    This function will first try to create a native DOM document using
+        ///    the browsers createDocument function.  If the browser doesn't
+        ///    support this but supports ActiveXObject, then an attempt to create
+        ///    an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
+        ///    for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
+        ///    the browser doesn't support ActiveXObject then an exception will be thrown.
+        /// </remarks>
+
+        var implementation = window.document.implementation;
+        return (implementation && implementation.createDocument) ?
+           implementation.createDocument(null, null, null) :
+           msXmlDom();
+    };
+
+    var xmlAppendChildren = function (parent, children) {
+        /// <summary>Appends a collection of child nodes or string values to a parent DOM node.</summary>
+        /// <param name="parent">DOM node to which the children will be appended.</param>
+        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be appended to the parent.</param>
+        /// <returns>The parent with the appended children or string values.</returns>
+        /// <remarks>
+        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
+        ///    for it and then appended to the parent.
+        /// </remarks>
+
+        if (!isArray(children)) {
+            return xmlAppendChild(parent, children);
+        }
+
+        var i, len;
+        for (i = 0, len = children.length; i < len; i++) {
+            children[i] && xmlAppendChild(parent, children[i]);
+        }
+        return parent;
+    };
+
+    var xmlAppendChild = function (parent, child) {
+        /// <summary>Appends a child node or a string value to a parent DOM node.</summary>
+        /// <param name="parent">DOM node to which the child will be appended.</param>
+        /// <param name="child">Child DOM node or string value to append to the parent.</param>
+        /// <returns>The parent with the appended child or string value.</returns>
+        /// <remarks>
+        ///    If child is a string value, then a new DOM text node is going to be created
+        ///    for it and then appended to the parent.
+        /// </remarks>
+
+        if (child) {
+            if (typeof child === "string") {
+                return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
+            }
+            if (child.nodeType === 2) {
+                parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
+            } else {
+                parent.appendChild(child);
+            }
+        }
+        return parent;
+    };
+
+    var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) {
+        /// <summary>Creates a new DOM attribute node.</summary>
+        /// <param name="dom">DOM document used to create the attribute.</param>
+        /// <param name="prefix" type="String">Namespace prefix.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI.</param>
+        /// <returns>DOM attribute node for the namespace declaration.</returns>
+
+        var attribute =
+            dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
+            dom.createNode(2, qualifiedName, namespaceURI || undefined);
+
+        attribute.value = value || "";
+        return attribute;
+    };
+
+    var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) {
+        /// <summary>Creates a new DOM element node.</summary>
+        /// <param name="dom">DOM document used to create the DOM element.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element.</param>
+        /// <param name="qualifiedName" type="String">Qualified name in the form of "prefix:name" of the new DOM element.</param>
+        /// <param name="children" type="Array" optional="true">
+        ///     Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
+        /// </param>
+        /// <returns>New DOM element.</returns>
+        /// <remarks>
+        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
+        ///    for it and then appended to the new DOM element.
+        /// </remarks>
+
+        var element =
+            dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
+            dom.createNode(1, qualifiedName, nampespaceURI || undefined);
+
+        return xmlAppendChildren(element, children || []);
+    };
+
+    var xmlNewNSDeclaration = function (dom, namespaceURI, prefix) {
+        /// <summary>Creates a namespace declaration attribute.</summary>
+        /// <param name="dom">DOM document used to create the attribute.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI.</param>
+        /// <param name="prefix" type="String">Namespace prefix.</param>
+        /// <returns>DOM attribute node for the namespace declaration.</returns>
+
+        return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
+    };
+
+    var xmlNewFragment = function (dom, text) {
+        /// <summary>Creates a new DOM document fragment node for the specified xml text.</summary>
+        /// <param name="dom">DOM document from which the fragment node is going to be created.</param>
+        /// <param name="text" type="String" mayBeNull="false">XML text to be represented by the XmlFragment.</param>
+        /// <returns>New DOM document fragment object.</returns>
+
+        var value = "<c>" + text + "</c>";
+        var tempDom = xmlParse(value);
+        var tempRoot = tempDom.documentElement;
+        var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
+        var fragment = dom.createDocumentFragment();
+
+        var importedChild = imported.firstChild;
+        while (importedChild) {
+            fragment.appendChild(importedChild);
+            importedChild = importedChild.nextSibling;
+        }
+        return fragment;
+    };
+
+    var xmlNewText = function (dom, text) {
+        /// <summary>Creates new DOM text node.</summary>
+        /// <param name="dom">DOM document used to create the text node.</param>
+        /// <param name="text" type="String">Text value for the DOM text node.</param>
+        /// <returns>DOM text node.</returns>
+
+        return dom.createTextNode(text);
+    };
+
+    var xmlNewNodeByPath = function (dom, root, namespaceURI, prefix, path) {
+        /// <summary>Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.</summary>
+        /// <param name="dom">DOM document used to create the new node.</param>
+        /// <param name="root">DOM element node used as root of the subtree on which the new nodes are going to be created.</param>
+        /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element or attribute.</param>
+        /// <param name="namespacePrefix" type="String">Prefix used to qualify the name of the new DOM element or attribute.</param>
+        /// <param name="Path" type="String">Path string describing the location of the new DOM element or attribute from the root element.</param>
+        /// <returns>DOM element or attribute node for the last segment of the path.</returns>
+        /// <remarks>
+        ///     This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
+        ///     for each segment that doesn't have a matching element under root.
+        ///
+        ///     The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
+        ///     will be created.
+        /// </remarks>
+
+        var name = "";
+        var parts = path.split("/");
+        var xmlFindNode = xmlFirstChildElement;
+        var xmlNewNode = xmlNewElement;
+        var xmlNode = root;
+
+        var i, len;
+        for (i = 0, len = parts.length; i < len; i++) {
+            name = parts[i];
+            if (name.charAt(0) === "@") {
+                name = name.substring(1);
+                xmlFindNode = xmlAttributeNode;
+                xmlNewNode = xmlNewAttribute;
+            }
+
+            var childNode = xmlFindNode(xmlNode, namespaceURI, name);
+            if (!childNode) {
+                childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
+                xmlAppendChild(xmlNode, childNode);
+            }
+            xmlNode = childNode;
+        }
+        return xmlNode;
+    };
+
+    var xmlSerialize = function (domNode) {
+        /// <summary>
+        /// Returns the text representation of the document to which the specified node belongs.
+        /// </summary>
+        /// <param name="root">Wrapped element in the document to serialize.</param>
+        /// <returns type="String">Serialized document.</returns>
+
+        var xmlSerializer = window.XMLSerializer;
+        if (xmlSerializer) {
+            var serializer = new xmlSerializer();
+            return serializer.serializeToString(domNode);
+        }
+
+        if (domNode.xml) {
+            return domNode.xml;
+        }
+
+        throw { message: "XML serialization unsupported" };
+    };
+
+    var xmlSerializeDescendants = function (domNode) {
+        /// <summary>Returns the XML representation of the all the descendants of the node.</summary>
+        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
+        /// <returns type="String">The XML representation of all the descendants of the node.</returns>
+
+        var children = domNode.childNodes;
+        var i, len = children.length;
+        if (len === 0) {
+            return "";
+        }
+
+        // Some implementations of the XMLSerializer don't deal very well with fragments that
+        // don't have a DOMElement as their first child. The work around is to wrap all the
+        // nodes in a dummy root node named "c", serialize it and then just extract the text between
+        // the <c> and the </c> substrings.
+
+        var dom = domNode.ownerDocument;
+        var fragment = dom.createDocumentFragment();
+        var fragmentRoot = dom.createElement("c");
+
+        fragment.appendChild(fragmentRoot);
+        // Move the children to the fragment tree.
+        for (i = 0; i < len; i++) {
+            fragmentRoot.appendChild(children[i]);
+        }
+
+        var xml = xmlSerialize(fragment);
+        xml = xml.substr(3, xml.length - 7);
+
+        // Move the children back to the original dom tree.
+        for (i = 0; i < len; i++) {
+            domNode.appendChild(fragmentRoot.childNodes[i]);
+        }
+
+        return xml;
+    };
+
+    var xmlSerializeNode = function (domNode) {
+        /// <summary>Returns the XML representation of the node and all its descendants.</summary>
+        /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param>
+        /// <returns type="String">The XML representation of the node and all its descendants.</returns>
+
+        var xml = domNode.xml;
+        if (xml !== undefined) {
+            return xml;
+        }
+
+        if (window.XMLSerializer) {
+            var serializer = new window.XMLSerializer();
+            return serializer.serializeToString(domNode);
+        }
+
+        throw { message: "XML serialization unsupported" };
+    };
+
+
+
+
+    var forwardCall = function (thisValue, name, returnValue) {
+        /// <summary>Creates a new function to forward a call.</summary>
+        /// <param name="thisValue" type="Object">Value to use as the 'this' object.</param>
+        /// <param name="name" type="String">Name of function to forward to.</param>
+        /// <param name="returnValue" type="Object">Return value for the forward call (helps keep identity when chaining calls).</param>
+        /// <returns type="Function">A new function that will forward a call.</returns>
+
+        return function () {
+            thisValue[name].apply(thisValue, arguments);
+            return returnValue;
+        };
+    };
+
+    var DjsDeferred = function () {
+        /// <summary>Initializes a new DjsDeferred object.</summary>
+        /// <remarks>
+        /// Compability Note A - Ordering of callbacks through chained 'then' invocations
+        ///
+        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+        /// implies that .then() returns a distinct object.
+        ////
+        /// For compatibility with http://api.jquery.com/category/deferred-object/
+        /// we return this same object. This affects ordering, as
+        /// the jQuery version will fire callbacks in registration
+        /// order regardless of whether they occur on the result
+        /// or the original object.
+        ///
+        /// Compability Note B - Fulfillment value
+        ///
+        /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A
+        /// implies that the result of a success callback is the
+        /// fulfillment value of the object and is received by
+        /// other success callbacks that are chained.
+        ///
+        /// For compatibility with http://api.jquery.com/category/deferred-object/
+        /// we disregard this value instead.
+        /// </remarks>
+
+        this._arguments = undefined;
+        this._done = undefined;
+        this._fail = undefined;
+        this._resolved = false;
+        this._rejected = false;
+    };
+
+    DjsDeferred.prototype = {
+        then: function (fulfilledHandler, errorHandler /*, progressHandler */) {
+            /// <summary>Adds success and error callbacks for this deferred object.</summary>
+            /// <param name="fulfilledHandler" type="Function" mayBeNull="true" optional="true">Success callback.</param>
+            /// <param name="errorHandler" type="Function" mayBeNull="true" optional="true">Error callback.</param>
+            /// <remarks>See Compatibility Note A.</remarks>
+
+            if (fulfilledHandler) {
+                if (!this._done) {
+                    this._done = [fulfilledHandler];
+                } else {
+                    this._done.push(fulfilledHandler);
+                }
+            }
+
+            if (errorHandler) {
+                if (!this._fail) {
+                    this._fail = [errorHandler];
+                } else {
+                    this._fail.push(errorHandler);
+                }
+            }
+
+            //// See Compatibility Note A in the DjsDeferred constructor.
+            //// if (!this._next) {
+            ////    this._next = createDeferred();
+            //// }
+            //// return this._next.promise();
+
+            if (this._resolved) {
+                this.resolve.apply(this, this._arguments);
+            } else if (this._rejected) {
+                this.reject.apply(this, this._arguments);
+            }
+
+            return this;
+        },
+
+        resolve: function (/* args */) {
+            /// <summary>Invokes success callbacks for this deferred object.</summary>
+            /// <remarks>All arguments are forwarded to success callbacks.</remarks>
+
+
+            if (this._done) {
+                var i, len;
+                for (i = 0, len = this._done.length; i < len; i++) {
+                    //// See Compability Note B - Fulfillment value.
+                    //// var nextValue =
+                    this._done[i].apply(null, arguments);
+                }
+
+                //// See Compatibility Note A in the DjsDeferred constructor.
+                //// this._next.resolve(nextValue);
+                //// delete this._next;
+
+                this._done = undefined;
+                this._resolved = false;
+                this._arguments = undefined;
+            } else {
+                this._resolved = true;
+                this._arguments = arguments;
+            }
+        },
+
+        reject: function (/* args */) {
+            /// <summary>Invokes error callbacks for this deferred object.</summary>
+            /// <remarks>All arguments are forwarded to error callbacks.</remarks>
+            if (this._fail) {
+                var i, len;
+                for (i = 0, len = this._fail.length; i < len; i++) {
+                    this._fail[i].apply(null, arguments);
+                }
+
+                this._fail = undefined;
+                this._rejected = false;
+                this._arguments = undefined;
+            } else {
+                this._rejected = true;
+                this._arguments = arguments;
+            }
+        },
+
+        promise: function () {
+            /// <summary>Returns a version of this object that has only the read-only methods available.</summary>
+            /// <returns>An object with only the promise object.</returns>
+
+            var result = {};
+            result.then = forwardCall(this, "then", result);
+            return result;
+        }
+    };
+
+    var createDeferred = function () {
+        /// <summary>Creates a deferred object.</summary>
+        /// <returns type="DjsDeferred">
+        /// A new deferred object. If jQuery is installed, then a jQuery
+        /// Deferred object is returned, which provides a superset of features.
+        /// </returns>
+
+        if (window.jQuery && window.jQuery.Deferred) {
+            return new window.jQuery.Deferred();
+        } else {
+            return new DjsDeferred();
+        }
+    };
+
+
+
+
+    var dataItemTypeName = function (value, metadata) {
+        /// <summary>Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property.</summary>
+        /// <param name="value">Value of the data item from which the type name is going to be retrieved.</param>
+        /// <param name="metadata" type="object" optional="true">Object containing metadata about the data tiem.</param>
+        /// <remarks>
+        ///    This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise
+        ///    it will try to recover it from the metadata.  If both attempts fail, it will return null.
+        /// </remarks>
+        /// <returns type="String">Data item type name; null if the type name cannot be found within the value or the metadata</returns>
+
+        var valueTypeName = ((value && value.__metadata) || {}).type;
+        return valueTypeName || (metadata ? metadata.type : null);
+    };
+
+    var EDM = "Edm.";
+    var EDM_BINARY = EDM + "Binary";
+    var EDM_BOOLEAN = EDM + "Boolean";
+    var EDM_BYTE = EDM + "Byte";
+    var EDM_DATETIME = EDM + "DateTime";
+    var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset";
+    var EDM_DECIMAL = EDM + "Decimal";
+    var EDM_DOUBLE = EDM + "Double";
+    var EDM_GUID = EDM + "Guid";
+    var EDM_INT16 = EDM + "Int16";
+    var EDM_INT32 = EDM + "Int32";
+    var EDM_INT64 = EDM + "Int64";
+    var EDM_SBYTE = EDM + "SByte";
+    var EDM_SINGLE = EDM + "Single";
+    var EDM_STRING = EDM + "String";
+    var EDM_TIME = EDM + "Time";
+
+    var EDM_GEOGRAPHY = EDM + "Geography";
+    var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point";
+    var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString";
+    var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon";
+    var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection";
+    var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon";
+    var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString";
+    var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint";
+
+    var EDM_GEOMETRY = EDM + "Geometry";
+    var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point";
+    var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString";
+    var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon";
+    var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection";
+    var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon";
+    var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString";
+    var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint";
+
+    var GEOJSON_POINT = "Point";
+    var GEOJSON_LINESTRING = "LineString";
+    var GEOJSON_POLYGON = "Polygon";
+    var GEOJSON_MULTIPOINT = "MultiPoint";
+    var GEOJSON_MULTILINESTRING = "MultiLineString";
+    var GEOJSON_MULTIPOLYGON = "MultiPolygon";
+    var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection";
+
+    var primitiveEdmTypes = [
+        EDM_STRING,
+        EDM_INT32,
+        EDM_INT64,
+        EDM_BOOLEAN,
+        EDM_DOUBLE,
+        EDM_SINGLE,
+        EDM_DATETIME,
+        EDM_DATETIMEOFFSET,
+        EDM_TIME,
+        EDM_DECIMAL,
+        EDM_GUID,
+        EDM_BYTE,
+        EDM_INT16,
+        EDM_SBYTE,
+        EDM_BINARY
+    ];
+
+    var geometryEdmTypes = [
+        EDM_GEOMETRY,
+        EDM_GEOMETRY_POINT,
+        EDM_GEOMETRY_LINESTRING,
+        EDM_GEOMETRY_POLYGON,
+        EDM_GEOMETRY_COLLECTION,
+        EDM_GEOMETRY_MULTIPOLYGON,
+        EDM_GEOMETRY_MULTILINESTRING,
+        EDM_GEOMETRY_MULTIPOINT
+    ];
+
+    var geographyEdmTypes = [
+        EDM_GEOGRAPHY,
+        EDM_GEOGRAPHY_POINT,
+        EDM_GEOGRAPHY_LINESTRING,
+        EDM_GEOGRAPHY_POLYGON,
+        EDM_GEOGRAPHY_COLLECTION,
+        EDM_GEOGRAPHY_MULTIPOLYGON,
+        EDM_GEOGRAPHY_MULTILINESTRING,
+        EDM_GEOGRAPHY_MULTIPOINT
+    ];
+
+    var forEachSchema = function (metadata, callback) {
+        /// <summary>Invokes a function once per schema in metadata.</summary>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <param name="callback" type="Function">Callback function to invoke once per schema.</param>
+        /// <returns>
+        /// The first truthy value to be returned from the callback; null or the last falsy value otherwise.
+        /// </returns>
+
+        if (!metadata) {
+            return null;
+        }
+
+        if (isArray(metadata)) {
+            var i, len, result;
+            for (i = 0, len = metadata.length; i < len; i++) {
+                result = forEachSchema(metadata[i], callback);
+                if (result) {
+                    return result;
+                }
+            }
+
+            return null;
+        } else {
+            if (metadata.dataServices) {
+                return forEachSchema(metadata.dataServices.schema, callback);
+            }
+
+            return callback(metadata);
+        }
+    };
+
+    var formatMilliseconds = function (ms, ns) {
+        /// <summary>Formats a millisecond and a nanosecond value into a single string.</summary>
+        /// <param name="ms" type="Number" mayBeNull="false">Number of milliseconds to format.</param>
+        /// <param name="ns" type="Number" mayBeNull="false">Number of nanoseconds to format.</param>
+        /// <returns type="String">Formatted text.</returns>
+        /// <remarks>If the value is already as string it's returned as-is.</remarks>
+
+        // Avoid generating milliseconds if not necessary.
+        if (ms === 0) {
+            ms = "";
+        } else {
+            ms = "." + formatNumberWidth(ms.toString(), 3);
+        }
+        if (ns > 0) {
+            if (ms === "") {
+                ms = ".000";
+            }
+            ms += formatNumberWidth(ns.toString(), 4);
+        }
+        return ms;
+    };
+
+    var formatDateTimeOffset = function (value) {
+        /// <summary>Formats a DateTime or DateTimeOffset value a string.</summary>
+        /// <param name="value" type="Date" mayBeNull="false">Value to format.</param>
+        /// <returns type="String">Formatted text.</returns>
+        /// <remarks>If the value is already as string it's returned as-is.</remarks>
+
+        if (typeof value === "string") {
+            return value;
+        }
+
+        var hasOffset = isDateTimeOffset(value);
+        var offset = getCanonicalTimezone(value.__offset);
+        if (hasOffset && offset !== "Z") {
+            // We're about to change the value, so make a copy.
+            value = new Date(value.valueOf());
+
+            var timezone = parseTimezone(offset);
+            var hours = value.getUTCHours() + (timezone.d * timezone.h);
+            var minutes = value.getUTCMinutes() + (timezone.d * timezone.m);
+
+            value.setUTCHours(hours, minutes);
+        } else if (!hasOffset) {
+            // Don't suffix a 'Z' for Edm.DateTime values.
+            offset = "";
+        }
+
+        var year = value.getUTCFullYear();
+        var month = value.getUTCMonth() + 1;
+        var sign = "";
+        if (year <= 0) {
+            year = -(year - 1);
+            sign = "-";
+        }
+
+        var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns);
+
+        return sign +
+            formatNumberWidth(year, 4) + "-" +
+            formatNumberWidth(month, 2) + "-" +
+            formatNumberWidth(value.getUTCDate(), 2) + "T" +
+            formatNumberWidth(value.getUTCHours(), 2) + ":" +
+            formatNumberWidth(value.getUTCMinutes(), 2) + ":" +
+            formatNumberWidth(value.getUTCSeconds(), 2) +
+            ms + offset;
+    };
+
+    var formatDuration = function (value) {
+        /// <summary>Converts a duration to a string in xsd:duration format.</summary>
+        /// <param name="value" type="Object">Object with ms and __edmType properties.</param>
+        /// <returns type="String">String representation of the time object in xsd:duration format.</returns>
+
+        var ms = value.ms;
+
+        var sign = "";
+        if (ms < 0) {
+            sign = "-";
+            ms = -ms;
+        }
+
+        var days = Math.floor(ms / 86400000);
+        ms -= 86400000 * days;
+        var hours = Math.floor(ms / 3600000);
+        ms -= 3600000 * hours;
+        var minutes = Math.floor(ms / 60000);
+        ms -= 60000 * minutes;
+        var seconds = Math.floor(ms / 1000);
+        ms -= seconds * 1000;
+
+        return sign + "P" +
+               formatNumberWidth(days, 2) + "DT" +
+               formatNumberWidth(hours, 2) + "H" +
+               formatNumberWidth(minutes, 2) + "M" +
+               formatNumberWidth(seconds, 2) +
+               formatMilliseconds(ms, value.ns) + "S";
+    };
+
+    var formatNumberWidth = function (value, width, append) {
+        /// <summary>Formats the specified value to the given width.</summary>
+        /// <param name="value" type="Number">Number to format (non-negative).</param>
+        /// <param name="width" type="Number">Minimum width for number.</param>
+        /// <param name="append" type="Boolean">Flag indicating if the value is padded at the beginning (false) or at the end (true).</param>
+        /// <returns type="String">Text representation.</returns>
+        var result = value.toString(10);
+        while (result.length < width) {
+            if (append) {
+                result += "0";
+            } else {
+                result = "0" + result;
+            }
+        }
+
+        return result;
+    };
+
+    var getCanonicalTimezone = function (timezone) {
+        /// <summary>Gets the canonical timezone representation.</summary>
+        /// <param name="timezone" type="String">Timezone representation.</param>
+        /// <returns type="String">An 'Z' string if the timezone is absent or 0; the timezone otherwise.</returns>
+
+        return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone;
+    };
+
+    var getCollectionType = function (typeName) {
+        /// <summary>Gets the type of a collection type name.</summary>
+        /// <param name="typeName" type="String">Type name of the collection.</param>
+        /// <returns type="String">Type of the collection; null if the type name is not a collection type.</returns>
+
+        if (typeof typeName === "string") {
+            var end = typeName.indexOf(")", 10);
+            if (typeName.indexOf("Collection(") === 0 && end > 0) {
+                return typeName.substring(11, end);
+            }
+        }
+        return null;
+    };
+
+    var invokeRequest = function (request, success, error, handler, httpClient, context) {
+        /// <summary>Sends a request containing OData payload to a server.</summary>
+        /// <param name="request">Object that represents the request to be sent..</param>
+        /// <param name="success">Callback for a successful read operation.</param>
+        /// <param name="error">Callback for handling errors.</param>
+        /// <param name="handler">Handler for data serialization.</param>
+        /// <param name="httpClient">HTTP client layer.</param>
+        /// <param name="context">Context used for processing the request</param>
+
+        return httpClient.request(request, function (response) {
+            try {
+                if (response.headers) {
+                    normalizeHeaders(response.headers);
+                }
+
+                if (response.data === undefined && response.statusCode !== 204) {
+                    handler.read(response, context);
+                }
+            } catch (err) {
+                if (err.request === undefined) {
+                    err.request = request;
+                }
+                if (err.response === undefined) {
+                    err.response = response;
+                }
+                error(err);
+                return;
+            }
+
+            success(response.data, response);
+        }, error);
+    };
+
+    var isBatch = function (value) {
+        /// <summary>Tests whether a value is a batch object in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a batch object; false otherwise.</returns>
+
+        return isComplex(value) && isArray(value.__batchRequests);
+    };
+
+    // Regular expression used for testing and parsing for a collection type.
+    var collectionTypeRE = /Collection\((.*)\)/;
+
+    var isCollection = function (value, typeName) {
+        /// <summary>Tests whether a value is a collection value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
+        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
+
+        var colData = value && value.results || value;
+        return !!colData &&
+            (isCollectionType(typeName)) ||
+            (!typeName && isArray(colData) && !isComplex(colData[0]));
+    };
+
+    var isCollectionType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a collection type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is the name of a collection type; false otherwise.</returns>
+        return collectionTypeRE.test(typeName);
+    };
+
+    var isComplex = function (value) {
+        /// <summary>Tests whether a value is a complex type value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a complex type value; false otherwise.</returns>
+
+        return !!value &&
+            isObject(value) &&
+            !isArray(value) &&
+            !isDate(value);
+    };
+
+    var isDateTimeOffset = function (value) {
+        /// <summary>Checks whether a Date object is DateTimeOffset value</summary>
+        /// <param name="value" type="Date" mayBeNull="false">Value to check.</param>
+        /// <returns type="Boolean">true if the value is a DateTimeOffset, false otherwise.</returns>
+        return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset));
+    };
+
+    var isDeferred = function (value) {
+        /// <summary>Tests whether a value is a deferred navigation property in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a deferred navigation property; false otherwise.</returns>
+
+        if (!value && !isComplex(value)) {
+            return false;
+        }
+        var metadata = value.__metadata || {};
+        var deferred = value.__deferred || {};
+        return !metadata.type && !!deferred.uri;
+    };
+
+    var isEntry = function (value) {
+        /// <summary>Tests whether a value is an entry object in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is an entry object; false otherwise.</returns>
+
+        return isComplex(value) && value.__metadata && "uri" in value.__metadata;
+    };
+
+    var isFeed = function (value, typeName) {
+        /// <summary>Tests whether a value is a feed value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param>
+        /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns>
+
+        var feedData = value && value.results || value;
+        return isArray(feedData) && (
+            (!isCollectionType(typeName)) &&
+            (isComplex(feedData[0]))
+        );
+    };
+
+    var isGeographyEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a geography EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a geography EDM type; false otherwise.</returns>
+
+        return contains(geographyEdmTypes, typeName);
+    };
+
+    var isGeometryEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a geometry EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a geometry EDM type; false otherwise.</returns>
+
+        return contains(geometryEdmTypes, typeName);
+    };
+
+    var isNamedStream = function (value) {
+        /// <summary>Tests whether a value is a named stream value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <returns type="Boolean">True is the value is a named stream; false otherwise.</returns>
+
+        if (!value && !isComplex(value)) {
+            return false;
+        }
+        var metadata = value.__metadata;
+        var mediaResource = value.__mediaresource;
+        return !metadata && !!mediaResource && !!mediaResource.media_src;
+    };
+
+    var isPrimitive = function (value) {
+        /// <summary>Tests whether a value is a primitive type value in the library's internal representation.</summary>
+        /// <param name="value">Value to test.</param>
+        /// <remarks>
+        ///    Date objects are considered primitive types by the library.
+        /// </remarks>
+        /// <returns type="Boolean">True is the value is a primitive type value.</returns>
+
+        return isDate(value) ||
+            typeof value === "string" ||
+            typeof value === "number" ||
+            typeof value === "boolean";
+    };
+
+    var isPrimitiveEdmType = function (typeName) {
+        /// <summary>Checks whether the specified type name is a primitive EDM type.</summary>
+        /// <param name="typeName" type="String">Name of type to check.</param>
+        /// <returns type="Boolean">True if the type is a primitive EDM type; false otherwise.</returns>
+
+        return contains(primitiveEdmTypes, typeName);
+    };
+
+    var navigationPropertyKind = function (value, propertyModel) {
+        /// <summary>Gets the kind of a navigation property value.</summary>
+        /// <param name="value">Value of the navigation property.</param>
+        /// <param name="propertyModel" type="Object" optional="true">
+        ///     Object that describes the navigation property in an OData conceptual schema.
+        /// </param>
+        /// <remarks>
+        ///     The returned string is as follows
+        /// </remarks>
+        /// <returns type="String">String value describing the kind of the navigation property; null if the kind cannot be determined.</returns>
+
+        if (isDeferred(value)) {
+            return "deferred";
+        }
+        if (isEntry(value)) {
+            return "entry";
+        }
+        if (isFeed(value)) {
+            return "feed";
+        }
+        if (propertyModel && propertyModel.relationship) {
+            if (value === null || value === undefined || !isFeed(value)) {
+                return "entry";
+            }
+            return "feed";
+        }
+        return null;
+    };
+
+    var lookupProperty = function (properties, name) {
+        /// <summary>Looks up a property by name.</summary>
+        /// <param name="properties" type="Array" mayBeNull="true">Array of property objects as per EDM metadata.</param>
+        /// <param name="name" type="String">Name to look for.</param>
+        /// <returns type="Object">The property object; null if not found.</returns>
+
+        return find(properties, function (property) {
+            return property.name === name;
+        });
+    };
+
+    var lookupInMetadata = function (name, metadata, kind) {
+        /// <summary>Looks up a type object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
+        /// <returns>An type description if the name is found; null otherwise.</returns>
+
+        return (name) ? forEachSchema(metadata, function (schema) {
+            return lookupInSchema(name, schema, kind);
+        }) : null;
+    };
+
+    var lookupEntitySet = function (entitySets, 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(entitySets, function (entitySet) {
+            return entitySet.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>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>A complex type description if the name is found; null otherwise.</returns>
+
+        return lookupInMetadata(name, metadata, "complexType");
+    };
+
+    var lookupEntityType = function (name, metadata) {
+        /// <summary>Looks up an entity type object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity type description if the name is found; null otherwise.</returns>
+
+        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>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity container description if the name is found; null otherwise.</returns>
+
+        return forEachSchema(metadata, function (schema) {
+            return find(schema.entityContainer, function (container) {
+                return parseBool(container.isDefaultEntityContainer);
+            });
+        });
+    };
+
+    var lookupEntityContainer = function (name, metadata) {
+        /// <summary>Looks up an entity container object by name.</summary>
+        /// <param name="name" type="String">Name, possibly null or empty.</param>
+        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
+        /// <returns>An entity container description if the name is found; null otherwise.</returns>
+
+        return lookupInMetadata(name, metadata, "entityContainer");
+    };
+
+    var lookupFunctionImport = function (functionImports, name) {
+        /// <summary>Looks up a function import by name.</summary>
+        /// <param name="properties" type="Array" mayBeNull="true">Array of function import 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(functionImports, function (functionImport) {
+            return functionImport.name === name;
+        });
+    };
+
+    var lookupNavigationPropertyType = function (navigationProperty, metadata) {
+        /// <summary>Looks up the target entity type for a navigation property.</summary>
+        /// <param name="navigationProperty" type="Object"></param>
+        /// <param name="metadata" type="Object"></param>
+        /// <returns type="String">The entity type name for the specified property, null if not found.</returns>
+
+        var result = null;
+        if (navigationProperty) {
+            var rel = navigationProperty.relationship;
+            var association = forEachSchema(metadata, function (schema) {
+                // The name should be the namespace qualified name in 'ns'.'type' format.
+                var nameOnly = removeNamespace(schema["namespace"], rel);
+                var associations = schema.association;
+                if (nameOnly && associations) {
+                    var i, len;
+                    for (i = 0, len = associations.length; i < len; i++) {
+                        if (associations[i].name === nameOnly) {
+                            return associations[i];
+                        }
+                    }
+                }
+                return null;
+            });
+
+            if (association) {
+                var end = association.end[0];
+                if (end.role !== navigationProperty.toRole) {
+                    end = association.end[1];
+                    // For metadata to be valid, end.role === navigationProperty.toRole now.
+                }
+                result = end.type;
+            }
+        }
+        return result;
+    };
+
+    var lookupNavigationPropertyEntitySet = function (navigationProperty, sourceEntitySetName, metadata) {
+        /// <summary>Looks up the target entityset name for a navigation property.</summary>
+        /// <param name="navigationProperty" type="Object"></param>
+        /// <param name="metadata" type="Object"></param>
+        /// <returns type="String">The entityset name for the specified property, null if not found.</returns>
+
+        if (navigationProperty) {
+            var rel = navigationProperty.relationship;
+            var associationSet = forEachSchema(metadata, function (schema) {
+                var containers = schema.entityContainer;
+                for (var i = 0; i < containers.length; i++) {
+                    var associationSets = containers[i].associationSet;
+                    if (associationSets) {
+                        for (var j = 0; j < associationSets.length; j++) {
+                            if (associationSets[j].association == rel) {
+                                return associationSets[j];
+                            }
+                        }
+                    }
+                }
+                return null;
+            });
+            if (associationSet && associationSet.end[0] && associationSet.end[1]) {
+                return (associationSet.end[0].entitySet == sourceEntitySetName) ? associationSet.end[1].entitySet : associationSet.end[0].entitySet;
+            }
+        }
+        return null;
+    };
+
+    var getEntitySetInfo = function (entitySetName, metadata) {
+        /// <summary>Gets the entitySet info, container name and functionImports for an entitySet</summary>
+        /// <param name="navigationProperty" type="Object"></param>
+        /// <param name="metadata" type="Object"></param>
+        /// <returns type="Object">The info about the entitySet.</returns>
+
+        var info = forEachSchema(metadata, function (schema) {
+            var containers

<TRUNCATED>

[03/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-crossdomain-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-crossdomain-functional-tests.js b/odatajs/tests/odata-read-crossdomain-functional-tests.js
new file mode 100644
index 0000000..9e8aca9
--- /dev/null
+++ b/odatajs/tests/odata-read-crossdomain-functional-tests.js
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var fixConstructors = function (obj) {
+        /** Fix the constructors of the supplied object graph.
+        */
+        
+        /// When using IE9 or a non-IE browser, the JSONP support in the library creates objects in a separate IFRAME,
+        /// causing the constructor property to be different to that of objects created by the oracle. This function
+        /// stringifies and then re-parses the object, which fixes the constructors.
+        
+        if (!window.ActiveXObject || window.DOMParser) {
+            return window.JSON.parse(window.JSON.stringify(obj));
+        } else {
+            return obj;
+        }
+    };
+
+    var handlerAcceptStrings = [
+        "*/*",
+        "application/json",
+        undefined
+    ];
+
+    var formatJsonStrings = [
+        "application/json",
+        "application/json;odata.metadata=none",
+        "application/json;odata.metadata=minimal",
+        "application/json;odata.metadata=full", // to do: all the full metadata scenarios fail currently, need to fix.
+        undefined
+    ];
+    var azureOdataService = "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/";
+    var azureOdataFeed = azureOdataService + "Categories";
+    var crossDomainTimeout = 45000;
+
+    module("CrossDomain", {
+        setup: function () {
+            this.oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
+        },
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = this.oldEnableJsonpCallback;
+        }
+    });
+
+    for (var i = 0; i < handlerAcceptStrings.length; i++) {
+        for (var j = 0; j < formatJsonStrings.length; j++) {
+            djstest.addTest(function readCrossDomainFullFeedTest(params) {
+                djstest.assertsExpected(1);
+                var request = { requestUri: azureOdataFeed, headers: { Accept: params.handlerAccept}, enableJsonpCallback: true };
+                if (params.formatJsonString != undefined) {
+                    request.formatQueryString = "$format=" + params.formatJsonString;
+                }
+
+                djstest.log("Reading data over the wire.");
+                odatajs.oData.read(request, function (data, response) {
+                    djstest.log("Verifying data over the wire from Oracle.");
+                    window.ODataReadOracle.readFeed(azureOdataFeed, function (expectedData) {
+                        data = fixConstructors(data);
+                        djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
+                        djstest.done();
+                    }, params.formatJsonString);
+                }, unexpectedErrorHandler);
+            }, "Testing valid read of cross domain feed collection with " + handlerAcceptStrings[i] + "," + formatJsonStrings[j], { handlerAccept: handlerAcceptStrings[i], formatJsonString: formatJsonStrings[j] }, crossDomainTimeout);
+        }
+
+        djstest.addTest(function readCrossDomainEntryTest(handlerAccept) {
+            var endPoint = azureOdataFeed + "(1)";
+            djstest.assertsExpected(1);
+            djstest.log("Reading data over the wire.");
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
+                djstest.log("Verifying data over the wire from Oracle.");
+                window.ODataReadOracle.readEntry(endPoint, function (expectedData) {
+                    data = fixConstructors(data);
+                    djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, "application/json");
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of cross domain entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i], crossDomainTimeout);
+    }
+
+    var prefetchSizes = [-1, 0, 15];
+    var cacheSizes = [-1, 0, 15];
+    var skipValues = [
+        0,
+        14, // < pageSize
+        15, // = pageSize
+        16 // > pageSize but < pageSize + prefetchSize
+    ];
+
+    var createTestName = function (params) {
+        return "Testing ReadRange of " + params.feed + " skip " + params.skip + " take " + params.take + " with pageSize " +
+            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+    };
+
+    var dataCacheReadRangeSingleTest = function (params) {
+        var options = { name: "cache", source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+        window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
+        var cache = odatajs.cache.createDataCache(options);
+        cache.readRange(params.skip, params.take).then(function (data) {
+            validateExpectedRange(cache, data, params.feed, params.skip, params.take);
+        }, unexpectedErrorHandler);
+    };
+
+    var validateExpectedRange = function (cache, data, feed, skipValue, takeValue) {
+        var expectedRangeUrl = feed + "?$skip=" + skipValue + "&$top=" + takeValue;
+        window.ODataReadOracle.readFeed(expectedRangeUrl, function (expectedData) {
+            if (expectedData.results) {
+                expectedData = expectedData.results;
+            }
+            data = fixConstructors(data);
+            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+            djstest.destroyCacheAndDone(cache);
+        });
+    };
+
+    $.each(prefetchSizes, function (_, prefetchSizeValue) {
+        $.each(cacheSizes, function (_, cacheSizeValue) {
+            var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: 0, take: 5, pageSize: 15, prefetchSize: prefetchSizeValue, cacheSize: cacheSizeValue };
+            djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters);
+        });
+    });
+
+    $.each(skipValues, function (_, skipValue) {
+        var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: skipValue, take: 14, pageSize: 5, prefetchSize: 5, cacheSize: 5 };
+        djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters, crossDomainTimeout);
+    });
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-functional-tests.html b/odatajs/tests/odata-read-functional-tests.html
new file mode 100644
index 0000000..11d930d
--- /dev/null
+++ b/odatajs/tests/odata-read-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData tests against local service</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>   
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-read-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">OData.Read tests against local in-memory service</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-functional-tests.js b/odatajs/tests/odata-read-functional-tests.js
new file mode 100644
index 0000000..6253856
--- /dev/null
+++ b/odatajs/tests/odata-read-functional-tests.js
@@ -0,0 +1,594 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var validServiceDocumentAcceptHeaders = [
+            "*/*",
+            "application/json",
+            undefined
+          ];
+
+    var validMetadataAcceptHeaders = [
+            "*/*",
+            "application/xml",
+            undefined
+          ];
+
+    var invalidServiceDocumentAcceptHeaders = [
+        "application/atom+xml"
+    ];
+
+    var invalidMetadataAcceptHeaders = [
+            "application/json"
+        ];
+
+    var handlerAcceptStrings = [
+        "*/*",
+        "application/json",
+         undefined
+      ];
+
+    var httpStatusCode = {
+        notFound: 404,
+        badRequest: 400,
+        unsupportedMediaType: 415
+    };
+
+    var service = "./endpoints/FoodStoreDataServiceV4.svc/";
+    var epmService = "./endpoints/EpmDataService.svc/";
+    var feed = service + "Foods";
+    var categoriesFeed = service + "Categories";
+
+    var expectedErrorMessage = "HTTP request failed";
+
+    module("Functional", {
+        setup: function () {
+            djstest.wait(function (done) {
+                $.post(service + "ResetData", done);
+            });
+            window.odatajs.oData.json.jsonHandler.recognizeDates = false;
+        }
+    });
+
+    for (var i = 0; i < handlerAcceptStrings.length; i++) {
+
+        djstest.addTest(function readFullFeedTest(handlerAccept) {
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: feed, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(feed,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of full feed collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readMaxAndNullValueEntryTest(handlerAccept) {
+            var endPoint = feed + "(0)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of entry with max numbers, complex types, and null and empty strings " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readMinAndZeroValueEntryTest(handlerAccept) {
+            var endPoint = feed + "(1)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: "./endpoints/FoodStoreDataServiceV4.svc/Foods(1)", headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endPoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Testing valid read of minimum and zero values " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullNestedComplexTypeEntryTest(handlerAccept) {
+            var endPoint = feed + "(2)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of null nested complex type and navigation property " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullComplexTypeEntryTest(handlerAccept) {
+            var endPoint = feed + "(3)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of null top level complex type" + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullPropertiesDerivedEntryTest(handlerAccept) {
+            djstest.assertsExpected(1);
+            var endPoint = feed + "(4)";
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of derived type null properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNextComplexTypeDerivedEntryTest(handlerAccept) {
+
+            djstest.assertsExpected(1);
+            var endPoint = feed + "(5)";
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of derived type with full nested complex type properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithInlineFeedTest(handlerAccept) {
+            var endpoint = categoriesFeed + "(0)?$expand=Foods";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing read of entry with inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithEmptyInlineFeedTest(handlerAccept) {
+            var endpoint = categoriesFeed + "?$filter=Name eq 'Empty Category'&$expand=Foods";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of entry with empty inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithInlineEntryTest(handlerAccept) {
+            var endpoint = feed + "(0)?$expand=Category";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.Category, expectedData.Category, "Verify inline entry");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of entry with inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithNullInlineEntryTest(handlerAccept) {
+            var endpoint = feed + "?$expand=Category&$filter=Category eq null";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept);
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of feed with null inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithInlineCountTest(handlerAccept) {
+            var endpoint = feed + "?$count=true";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqual(data["@odata.count"], expectedData["@odata.count"], "Verify count in response data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing read of collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectSinglePropertyOnEntryTest(handlerAccept) {
+            var endpoint = feed + "(0)?$select=Name";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select single property of entry " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectComplexTypeOnFeedTest(handlerAccept) {
+            var endpoint = feed + "?$select=Packaging";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readFeed(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select single complex type property of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectMultiplePropertiesOnEntryTest(handlerAccept) {
+            var endpoint = feed + "(3)?$select=Packaging,ExpirationDate,IsAvailable";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select multiple primitive properties of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readPagedCategoriesCollectionTest(handlerAccept) {
+            var endpoint = categoriesFeed;
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of paged collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readPagedCollectionWithInlineCountTest(handlerAccept) {
+            var endpoint = categoriesFeed + "?$count=true";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqual(data["@odata.context"], expectedData["@odata.context"], "Verify count in response data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of paged collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithNamedStreams(handlerAccept) {
+            var endpoint = feed + "(1)?$expand=Category";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of entry with named streams " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithCollectionProperties(handlerAccept) {
+            var endpoint = feed + "(0)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of entry with collection properties " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function invalidEntryReadTest(handlerAccept) {
+            var endPoint = feed + "(16)";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        djstest.assert(false, "We should not get here because data is not valid.");
+                        djstest.done()
+                    },
+                    function (err) {
+                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
+                        djstest.done();
+                    });
+        }, "Testing invalid entry read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function invalidFeedReadTest(handlerAccept) {
+            var endPoint = feed + "Invalid";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        djstest.assert(false, "We should not get here because data is not valid.");
+                        djstest.done();
+                    },
+                    function (err) {
+                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
+                        djstest.done();
+                    });
+        }, "Testing invalid feed read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function standardErrorReadTest(handlerAccept) {
+            var endPoint = feed + "?$foo=bar";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                                    function (data, response) {
+                                        djstest.assert(false, "We should not get here because data is not valid.");
+                                        djstest.done()
+                                    },
+                                    function (err) {
+                                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.badRequest, "Response status code");
+                                        djstest.done();
+                                    });
+        }, "Testing standard error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function inStreamErrorReadTest(handlerAccept) {
+            var endPoint = "./endpoints/ErrorDataService.svc/Entities";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
+                djstest.assert(false, "Unexpected call to success handler with response: " + djstest.toString(response));
+                djstest.done()
+            }, function (err) {
+                djstest.assert(err.response.body.indexOf("An error occurred while processing this request") > -1, "Error handler was called with the correct response body");
+                djstest.done();
+            });
+        }, "Testing in-stream error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        var user = "djsUser";
+        var password = "djsPassword";
+
+        djstest.addTest(function readFullFeedBasicAuthTest(handlerAccept) {
+            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
+                window.ODataReadOracle.readFeed({ url: endpoint, user: user, password: password }, function (expectedData) {
+                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, handlerAccept);
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of full feed collection on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryBasicAuthTest(handlerAccept) {
+            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers(1)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
+                window.ODataReadOracle.readEntry({ url: endpoint, user: user, password: password }, function (expectedData) {
+                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, handlerAccept);
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of entry on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+    }
+
+    var services = [
+            service,
+            epmService
+        ];
+
+    $.each(services, function (_, serviceName) {
+        $.each(validServiceDocumentAcceptHeaders, function (_, validServiceDocumentAcceptHeader) {
+            var parameters = { handlerAccept: validServiceDocumentAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function validReadServiceDocumentTest(params) {
+                djstest.assertsExpected(1);
+                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
+                        function (data, response) {
+                            window.ODataReadOracle.readServiceDocument(serviceName,
+                                function (expectedData) {
+                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                    djstest.done();
+                                }, params.handlerAccept
+                            );
+                        },
+                        unexpectedErrorHandler
+                    );
+            }, "Testing valid read of service document " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+
+        $.each(invalidServiceDocumentAcceptHeaders, function (_, invalidServiceDocumentAcceptHeader) {
+            var parameters = { handlerAccept: invalidServiceDocumentAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function invalidReadServiceDocumentTest(params) {
+                djstest.assertsExpected(2);
+                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
+                        function success(data, response) {
+                            djstest.fail("Reading service document should produce error with " + params.handlerAccept);
+                            djstest.done();
+                        },
+                        function (err) {
+                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
+                            djstest.done();
+                        }
+                    );
+            }, "Testing read of service document with invalid MIME type " + parameters.invalidServiceDocumentAcceptHeader + " on service " + serviceName, parameters);
+        });
+
+        //to do:
+        $.each(validMetadataAcceptHeaders, function (_, validMetadataAcceptHeader) {
+            var parameters = { handlerAccept: validMetadataAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function validReadMetadataTest(params) {
+                djstest.assertsExpected(1);
+                var endPoint = params.serviceName + "$metadata";
+                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
+                        function (data, response) {
+                            window.ODataReadOracle.readMetadata(endPoint,
+                                function (expectedData) {
+                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                    djstest.done();
+                                }
+                            );
+                        },
+                        unexpectedErrorHandler,
+                        OData.metadataHandler
+                    );
+            }, "Testing valid read metadata " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+
+        $.each(invalidMetadataAcceptHeaders, function (_, invalidMetadataAcceptHeader) {
+            var parameters = { handlerAccept: invalidMetadataAcceptHeader, serviceName: serviceName };
+            djstest.addTest(function invlaidReadMetadataTest(params) {
+                djstest.assertsExpected(2);
+                var endPoint = params.serviceName + "$metadata";
+                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
+                        function success(data, response) {
+                            djstest.fail("Reading metadata should produce error with " + params.handlerAccept);
+                            djstest.done();
+                        },
+                        function (err) {
+                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
+                            djstest.done();
+                        },
+                        OData.metadataHandler
+                    );
+            }, "Testing read metadata with invalid MIME type " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+    });
+
+    // To do: update the test data for enabling the annotation test
+    djstest.addFullTest(true, function metadataElementExtensionsTest() {
+        var csdlFile = "./endpoints/CustomAnnotations.xml";
+        var modifyTypeHttpClient = {};
+        var originalHttpClient = window.odatajs.oData.net.defaultHttpClient;
+
+        // Modify the content-type of the response so that it is accepted by the metadataHandler.
+        // By default, the content-type of CustomAnnotations.xml comes back as text/xml
+        modifyTypeHttpClient.request = function (request, success, error) {
+            return originalHttpClient.request(request, function (response) {
+                response.headers["Content-Type"] = "application/xml";
+                success(response);
+            }, error);
+        }
+
+        window.odatajs.oData.net.defaultHttpClient = modifyTypeHttpClient;
+
+        odatajs.oData.read({ requestUri: csdlFile, headers: { Accept: "text/xml"} },
+            function (data) {
+                window.ODataReadOracle.readMetadata(csdlFile,
+                    function (expectedData) {
+                        djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                        djstest.done();
+                    }
+                )
+            },
+            unexpectedErrorHandler, OData.metadataHandler
+         );
+    });
+
+    djstest.addTest(function verifyNonDefaultReadMethodCalled() {
+        var endPoint = feed + "(0)";
+        djstest.assertsExpected(2);
+        odatajs.oData.read(
+                { requestUri: endPoint },
+                function success(data, response) {
+                    djstest.assert(true, "Test executed");
+                    djstest.done();
+                },
+                null,
+                {
+                    read: function (response) {
+                        djstest.assert(true, "Non-default read reached");
+                        djstest.done();
+                    },
+                    accept: "*/*"
+                }
+            );
+    }, "Testing nondefault read is called.");
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-request-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-request-functional-tests.html b/odatajs/tests/odata-request-functional-tests.html
new file mode 100644
index 0000000..4148634
--- /dev/null
+++ b/odatajs/tests/odata-request-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>odata.request tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-request-functional-tests.js"></script>
+</head>
+<body>
+    <h1 id="qunit-header">odata.request 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/d5ec5557/odatajs/tests/odata-request-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-request-functional-tests.js b/odatajs/tests/odata-request-functional-tests.js
new file mode 100644
index 0000000..82e4258
--- /dev/null
+++ b/odatajs/tests/odata-request-functional-tests.js
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var verifyRequest = function (request, done) {
+        if (request.method == "POST") {
+            verifyPost(request, done);
+        }
+        else if (request.method == "PUT") {
+            verifyPut(request, done);
+        }
+        else if (request.method == "PATCH") {
+            verifyPatch(request, done);
+        }
+    };
+
+    var tryRemoveOdataType = function (data) {
+        if (data && data["@odata.type"]) {
+            delete data["@odata.type"];
+        }
+
+        return data;
+    };
+
+    var verifyPost = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        odatajs.oData.request(request, function (data, response) {
+            djstest.log("Status code:" + response.statusCode);
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
+            djstest.log("Uri:" + request.requestUri);
+            ODataReadOracle.readEntry(response.headers["Location"], function (expectedData) {
+                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPut = function(request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        odatajs.oData.request(request, function(data, response) {
+            djstest.log("Status code:" + response.statusCode);
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+            djstest.log("Uri:" + request.requestUri);
+            ODataReadOracle.readEntry(request.requestUri, function(actualData) {
+                var requestData = tryRemoveOdataType(request.data);
+                djstest.assertAreEqualDeep(subset(actualData, requestData), requestData, "Verify updated entry: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPatch = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        ODataReadOracle.readEntry(request.requestUri, function (originalData) {
+            odatajs.oData.request(request, function (data, response) {
+                djstest.log("Status code:" + response.statusCode);
+                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                djstest.log("Uri:" + request.requestUri);
+                ODataReadOracle.readEntry(request.requestUri, function (actualData) {
+
+                    // Merge the original data with the updated data to get the expected data
+                    var expectedData = $.extend(true, {}, originalData, request.data);
+                    djstest.assertAreEqualDeep(actualData, tryRemoveOdataType(expectedData), "Verify merged data");
+                    done();
+                }, request.headers["Content-Type"]);
+            }, unexpectedErrorHandler);
+        }, request.headers["Content-Type"]);
+    };
+
+    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
+    var subset = function (object, subsetObject) {
+        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
+            var result = {};
+            for (subsetProp in subsetObject) {
+                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
+            }
+            return result;
+        }
+        else {
+            return object;
+        }
+    };
+
+    var foodData = {
+        "@odata.type": "#DataJS.Tests.V4.Food",
+        FoodID: 42,
+        Name: "olive oil",
+        UnitPrice: 3.14,
+        ServingSize: 1,
+        MeasurementUnit: "",
+        ProteinGrams: 5,
+        FatGrams: 9,
+        CarbohydrateGrams: 2,
+        CaloriesPerServing: 6,
+        IsAvailable: true,
+        ExpirationDate: "2010-12-25T12:00:00Z",
+        ItemGUID: "27272727-2727-2727-2727-272727272727",
+        Weight: 10,
+        AvailableUnits: 1,
+        Packaging: {
+            Type: "Can",
+            Color: null,
+            NumberPerPackage: 1,
+            RequiresRefridgeration: false,
+            PackageDimensions: {
+                Length: 4,
+                Height: 3,
+                Width: 2,
+                Volume: 1
+            },
+            ShipDate: "2010-12-25T12:00:00Z"
+        }
+    };
+
+    var testServices = {
+        V4: "./endpoints/FoodStoreDataServiceV4.svc"
+    };
+
+    var testData = {
+        V4: $.extend(true, {}, foodData, {
+            AlternativeNames: ["name1", "name2"],
+            Providers:
+                    [{
+                        Name: "Provider",
+                        Aliases: ["alias1"],
+                        Details: {
+                            Telephone: "555-555-555",
+                            PreferredCode: 999
+                        }
+                    },
+                    {
+                        Name: "Provider2",
+                        Aliases: [],
+                        Details: null
+                    }
+                ]
+        })
+    };
+
+    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
+
+    var httpStatusCode = {
+        created: 201,
+        noContent: 204,
+        notFound: 404
+    };
+
+    $.each(testServices, function (serviceName, service) {
+        var newFood = testData[serviceName];
+
+        var foodsFeed = service + "/Foods";
+        var categoriesFeed = service + "/Categories";
+
+        module("Functional", {
+            setup: function () {
+                djstest.log("Resetting data");
+                djstest.wait(function (done) {
+                    $.post(service + "/ResetData", done);
+                });
+            }
+        });
+
+        $.each(mimeTypes, function (_, mimeType) {
+            // Provide coverage for both undefined and specific DSVs
+            // For all other cases DSV = undefined is a valid scenario
+            var dataServiceVersions = ["4.0"];
+
+            $.each(dataServiceVersions, function (_, dataServiceVersion) {
+                var headers;
+                if (mimeType || dataServiceVersion) {
+                    headers = {
+                        "Content-Type": mimeType,
+                        Accept: mimeType,
+                        "OData-Version": dataServiceVersion
+                    };
+                }
+
+                djstest.addTest(function addEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "New Category"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithUTF16CharTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "\u00f6 New Category \u00f1"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new entity with UTF-16 character to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods",
+                        method: "POST",
+                        headers: headers,
+                        data: newFood
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithInlineFeedTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "Olive Products",
+                            Foods: [newFood]
+                        }
+                    };
+
+                    djstest.assertsExpected(3);
+                    verifyRequest(request, function () {
+                        ODataReadOracle.readEntry(foodsFeed + "(" + newFood.FoodID + ")", function (actualData) {
+                            djstest.assertAreEqual(actualData.Name, newFood.Name, "Verify inline entities were added");
+                            djstest.done();
+                        }, headers ? headers.Accept : undefined);
+                    });
+                }, "Add new entity with inline feed to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithInlineEntryTest(headers) {
+                    var request = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: $.extend({}, newFood, {
+                            Category: {
+                                CategoryID: 42,
+                                Name: "Olive Products"
+                            }
+                        })
+                    };
+
+                    djstest.assertsExpected(3);
+                    verifyRequest(request, function () {
+                        ODataReadOracle.readEntry(categoriesFeed + "(" + request.data.Category.CategoryID + ")", function (actualData) {
+                            djstest.assertAreEqual(actualData.Name, request.data.Category.Name, "Verify inline entities were added");
+                            djstest.done();
+                        }, headers ? headers.Accept : undefined);
+                    });
+                }, "Add new entity with inline entry to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function updateEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            CategoryID: 0,
+                            Name: "Updated Category"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                if (serviceName === "V4") {
+                    djstest.addTest(function updateEntityTest(headers) {
+                        var request = {
+                            requestUri: foodsFeed + "(0)",
+                            method: "PATCH",
+                            headers: headers,
+                            data: {
+                                "@odata.type": "#DataJS.Tests.V4.Food",
+                                AlternativeNames: ["one", "two"]
+                            }
+                        };
+
+                        djstest.assertsExpected(2);
+                        verifyRequest(request, djstest.done);
+                    }, "Update collection property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+                }
+
+                djstest.addTest(function updatePrimitivePropertyTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Name",
+                        method: "PUT",
+                        headers: headers,
+                        data: { value: "Updated Category" }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update primitive property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function updateLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            "@odata.type": "#DataJS.Tests.V4.Food",
+                            Name: "Updated Food"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function mergeEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)",
+                        method: "PATCH",
+                        headers: headers,
+                        data: { Name: "Merged Category" }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Merge entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function mergeLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PATCH",
+                        headers: headers,
+                        data: {
+                            "@odata.type": "#DataJS.Tests.V4.Food",
+                            Name: "Merged Food"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Merge linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function deleteEntityTest(headers) {
+                    var endpoint = categoriesFeed + "(0)";
+                    djstest.assertsExpected(2);
+                    odatajs.oData.request({
+                        requestUri: endpoint,
+                        method: "DELETE",
+                        headers: headers
+                    }, function (data, response) {
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                        $.ajax({
+                            url: endpoint,
+                            error: function (xhr) {
+                                djstest.assertAreEqual(xhr.status, httpStatusCode.notFound, "Verify response code of attempted retrieval after delete");
+                                djstest.done();
+                            },
+                            success: function () {
+                                djstest.fail("Delete failed: querying the endpoint did not return expected response code");
+                                djstest.done();
+                            }
+                        });
+                    }, unexpectedErrorHandler);
+                }, "Delete entity from " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+            });
+        });
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-roundtrip-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-roundtrip-functional-tests.js b/odatajs/tests/odata-roundtrip-functional-tests.js
new file mode 100644
index 0000000..6e3c356
--- /dev/null
+++ b/odatajs/tests/odata-roundtrip-functional-tests.js
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var verifyRequest = function (request, done) {
+        if (request.method == "POST") {
+            if (request.headers && request.headers["X-HTTP-Method"] == "MERGE") {
+                verifyMerge(request, done);
+            }
+            else {
+                verifyPost(request, done);
+            }
+        }
+        else if (request.method == "PUT") {
+            verifyPut(request, done);
+        }
+    };
+
+    var verifyPost = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        odatajs.oData.request(request, function (data, response) {
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
+            ODataReadOracle.readJson(data.__metadata.uri, function (expectedData) {
+                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPut = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        odatajs.oData.request(request, function (data, response) {
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+            ODataReadOracle.readJson(request.requestUri, function (actualData) {
+                djstest.assertAreEqualDeep(actualData, request.data, "Verify updated entry: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    }
+
+    var verifyMerge = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        ODataReadOracle.readJson(request.requestUri, function (originalData) {
+            odatajs.oData.request(request, function (data, response) {
+                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                ODataReadOracle.readJson(request.requestUri, function (actualData) {
+                    // Merge the original data with the updated data to get the expected data
+                    var expectedData = $.extend(true, {}, originalData, request.data);
+                    djstest.assertAreEqualDeep(actualData, expectedData, "Verify merged data");
+                    done();
+                }, request.headers["Content-Type"]);
+            }, unexpectedErrorHandler);
+        }, request.headers["Content-Type"]);
+    }
+
+    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
+    var subset = function (object, subsetObject) {
+        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
+            var result = {};
+            for (subsetProp in subsetObject) {
+                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
+            }
+            return result;
+        }
+        else {
+            return object;
+        }
+    };
+
+    var service = "./endpoints/FoodStoreDataService.svc";
+    var foodsFeed = service + "/Foods";
+    var categoriesFeed = service + "/Categories";
+    //var mimeTypes = [undefined, "application/json", "application/atom+xml"];
+    var mimeTypes = ["application/json", "application/atom+xml"];
+
+    var httpStatusCode = {
+        created: 201,
+        noContent: 204,
+        notFound: 404
+    };
+
+    var newFood = {
+        "__metadata": {
+            type: "DataJS.Tests.Food"
+        },
+        FoodID: 42,
+        Name: "olive oil",
+        UnitPrice: 3.14,
+        ServingSize: "1",
+        MeasurementUnit: "Cup",
+        ProteinGrams: 5,
+        FatGrams: 9,
+        CarbohydrateGrams: 2,
+        CaloriesPerServing: "6",
+        IsAvailable: true,
+        ExpirationDate: new Date("2011/05/03 12:00:00 PM"),
+        ItemGUID: "27272727-2727-2727-2727-272727272727",
+        Weight: 10,
+        AvailableUnits: 1,
+        Packaging: {
+            Type: "Can",
+            Color: "White",
+            NumberPerPackage: 1,
+            RequiresRefridgeration: false,
+            PackageDimensions: {
+                Length: "4",
+                Height: 3,
+                Width: "2",
+                Volume: 1
+            },
+            ShipDate: new Date("2011/01/01 12:00:00 PM")
+        }
+    };
+
+    var newFoodLinks = {
+        uri: foodsFeed + "(1)"
+    }
+
+    module("Functional", {
+        setup: function () {
+            $.ajax({ async: false, type: "POST", url: service + "/ResetData" });
+        }
+    });
+
+    $.each(mimeTypes, function (_, mimeType) {
+        var headers = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
+
+                djstest.addTest(function addEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "New Category"
+                        }
+                    };
+
+                    verifyRequest(request, function () {
+                        odatajs.oData.read({ requestUri: categoriesFeed + "(42)", headers: { Accept: mimeType} }, function (actualData, response) {
+                            actualData.CategoryID = 27;
+                            var newRequest = {
+                                requestUri: categoriesFeed,
+                                method: "POST",
+                                headers: headers,
+                                data: actualData
+                            };
+                            verifyRequest(newRequest, function () { djstest.done(); });
+                        }, request.headers["Content-Type"]);
+                    });
+
+                }, "Post, read posted data, post read data (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addLinkedEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(0)/Foods",
+                method: "POST",
+                headers: headers,
+                data: newFood
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(42)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.FoodID = 94;
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(0)/Foods",
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                }, request.headers["Content-Type"]);
+            });
+        }, "POST, read, POST an entry " + mimeType + ")", headers);
+
+
+        djstest.addTest(function addLinkedEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(0)/Foods(0)",
+                method: "PUT",
+                headers: headers,
+                data: newFood
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(0)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            "__metadata": { type: "DataJS.Tests.Food" },
+                            Name: "New Food" 
+                        }
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+        }, "PUT, read, PUT a new linked entry " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityWithInlineFeedTest(headers) {
+            var request = {
+                requestUri: categoriesFeed,
+                method: "POST",
+                headers: headers,
+                data: {
+                    CategoryID: 42,
+                    Name: "Olive Products",
+                    Foods: [newFood]
+                }
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
+                    var newRequest = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 27,
+                            Name: "Olive Products",
+                            Foods: [actualData]
+                        }
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+
+        }, "POST, read, POST an entity with inline feed " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityWithInlineEntryTest(headers) {
+            var request = {
+                requestUri: foodsFeed,
+                method: "POST",
+                headers: headers,
+                data: $.extend({}, newFood, {
+                    Category: {
+                        "__metadata": { uri: "" },
+                        CategoryID: 42,
+                        Name: "Olive Products"
+                    }
+                })
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.FoodID = 76;
+                    var newRequest = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: $.extend({}, actualData, {
+                            Category: {
+                                "__metadata": { uri: "" },
+                                CategoryID: 27,
+                                Name: "Olive Products"
+                            }
+                        })
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+        }, "Add new entity with inline entry (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(1)",
+                method: "PUT",
+                headers: headers,
+                data: {
+                    CategoryID: 1,
+                    Name: "New Category"
+                }
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(1)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.CategoryID = 2;
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(2)",
+                        method: "PUT",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                }, request.headers["Content-Type"]);
+            });
+
+        }, "Put, read put data, put read data (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: foodsFeed + "(0)", headers: { Accept: mimeType} },
+                function (actualData, response) {
+                    actualData.CategoryID = 216;
+                    var request = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request,
+                        function () {
+                            odatajs.oData.read({ requestUri: foodsFeed + "(216)", headers: { Accept: mimeType} },
+                                function (data, response) {
+                                    ODataReadOracle.readJson(foodsFeed + "(216)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        });
+                                });
+                        });
+                });
+        }, "Read data with dates, post read data with dates to new ID, read new ID data with dates" + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} }, 
+                function (actualData, response) {
+                    actualData.CategoryID = 81;
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request, 
+                        function () { 
+                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} }, 
+                                function (data, response) {
+                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        }
+                                    );
+                                }
+                            );
+                        }
+                    );
+                }
+            );
+        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
+
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} },
+                function (actualData, response) {
+                    actualData.CategoryID = 81;
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request,
+                        function () {
+                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} },
+                                function (data, response) {
+                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        });
+                                });
+                        });
+                });
+        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
+    });
+})(this);
\ No newline at end of file


[12/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/code/ReflectionDataContext.cs
----------------------------------------------------------------------
diff --git a/odatajs/tests/code/ReflectionDataContext.cs b/odatajs/tests/code/ReflectionDataContext.cs
new file mode 100644
index 0000000..1635d54
--- /dev/null
+++ b/odatajs/tests/code/ReflectionDataContext.cs
@@ -0,0 +1,743 @@
+/*
+ * 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.
+ */
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.Collections.ObjectModel;
+    using Microsoft.OData.Service;
+    using System.Globalization;
+    using System.Linq;
+    using System.Reflection;
+
+    /// <summary>
+    /// Provides a reflection-based, updatable data context.
+    /// </summary>
+    public abstract class ReflectionDataContext
+    {
+        // Fields
+        private List<object> deletedObjects = new List<object>();
+        private List<Action> pendingChanges;
+        private static Dictionary<Type, Dictionary<string, IList>> resourceSetsByContextTypeStorage = new Dictionary<Type, Dictionary<string, IList>>();
+
+        // Methods
+        protected ReflectionDataContext()
+        {
+            this.MetadataHelper = new ReflectionMetadataHelper(this);
+            this.pendingChanges = new List<Action>();
+            if (!resourceSetsByContextTypeStorage.ContainsKey(base.GetType()))
+            {
+                resourceSetsByContextTypeStorage.Add(base.GetType(), new Dictionary<string, IList>());
+                foreach (string resourceSetName in this.MetadataHelper.GetResourceSetNames())
+                {
+                    Type resourceType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
+                    IList listOfTInstance = Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { resourceType })) as IList;
+                    this.ResourceSetsStorage.Add(resourceSetName, listOfTInstance);
+                }
+            }
+            this.EnsureDataIsInitialized();
+        }
+
+        public virtual void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
+            ExceptionUtilities.CheckArgumentNotNull(resourceToBeAdded, "resourceToBeAdded");
+            UpdatableToken targetToken = UpdatableToken.AssertIsToken(targetResource, "targetResource");
+            targetResource = targetToken.Resource;
+            resourceToBeAdded = UpdatableToken.AssertIsTokenAndResolve(resourceToBeAdded, "resourceToBeAdded");
+            IList list = this.GetValue(targetToken, propertyName) as IList;
+            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
+            this.pendingChanges.Add(delegate {
+                list.Add(resourceToBeAdded);
+            });
+        }
+
+        public virtual void ClearChanges()
+        {
+            this.pendingChanges.Clear();
+        }
+
+        public void ClearData()
+        {
+            this.ResourceSetsStorage.Clear();
+        }
+
+        private static bool CompareETagValues(Dictionary<string, object> resourceCookieValues, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
+        {
+            if (concurrencyValues.Count<KeyValuePair<string, object>>() != resourceCookieValues.Count)
+            {
+                return false;
+            }
+            foreach (KeyValuePair<string, object> keyValuePair in concurrencyValues)
+            {
+                if (!resourceCookieValues.ContainsKey(keyValuePair.Key))
+                {
+                    return false;
+                }
+                if (keyValuePair.Value == null)
+                {
+                    return (resourceCookieValues[keyValuePair.Key] == null);
+                }
+                if (!keyValuePair.Value.Equals(resourceCookieValues[keyValuePair.Key]))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public virtual object CreateResource(string containerName, string fullTypeName)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(fullTypeName, "fullTypeName");
+            UpdatableToken token = this.InstantiateResourceType(fullTypeName);
+            if (containerName != null)
+            {
+                this.pendingChanges.Add(delegate {
+                    this.GetResourceSetEntities(containerName).Add(token.Resource);
+                });
+            }
+            return token;
+        }
+
+        private void DeleteAllReferences(object targetResource)
+        {
+            foreach (string currentSetName in this.MetadataHelper.GetResourceSetNames())
+            {
+                Type currentEntityType = this.MetadataHelper.GetResourceTypeOfSet(currentSetName);
+                IList entitySetList = this.GetResourceSetEntities(currentSetName);
+                foreach (NavigationPropertyInfo navigationProperty in this.MetadataHelper.GetNavigationProperties(GetResourceTypeFullName(currentEntityType)))
+                {
+                    if (navigationProperty.CollectionElementType != null)
+                    {
+                        foreach (object currentEntityInstance in entitySetList)
+                        {
+                            this.RemoveResourceFromCollectionOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
+                        }
+                    }
+                    else
+                    {
+                        ExceptionUtilities.CheckObjectNotNull(navigationProperty.PropertyInfo, "Invalid navigation property info", new object[0]);
+                        foreach (object currentEntityInstance in entitySetList)
+                        {
+                            this.SetEntityReferenceToNullOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
+                        }
+                    }
+                }
+            }
+        }
+
+        public virtual void DeleteResource(object targetResource)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            targetResource = UpdatableToken.AssertIsTokenAndResolve(targetResource, "targetResource");
+            string resourceSetName = this.GetResourceSetOfTargetResource(targetResource);
+            ExceptionUtilities.CheckObjectNotNull(resourceSetName, "Unable to find set of the resource to delete", new object[0]);
+            this.deletedObjects.Add(targetResource);
+            IList resourceSetList = this.GetResourceSetEntities(resourceSetName);
+            this.DeleteAllReferences(targetResource);
+            this.pendingChanges.Add(delegate {
+                resourceSetList.Remove(targetResource);
+            });
+        }
+
+        protected abstract void EnsureDataIsInitialized();
+
+        protected virtual Type GetCollectionPropertyType(string fullTypeName, string propertyName)
+        {
+            Type type = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
+            Type collectionType = null;
+            if (type != null)
+            {
+                PropertyInfo property = type.GetProperty(propertyName);
+                if (property != null)
+                {
+                    collectionType = property.PropertyType;
+                }
+            }
+            return collectionType;
+        }
+
+        private Dictionary<string, object> GetConcurrencyValues(object targetResource)
+        {
+            Dictionary<string, object> etagValues = new Dictionary<string, object>();
+            foreach (string etagProperty in this.MetadataHelper.GetETagPropertiesOfType(GetResourceTypeFullName(targetResource.GetType())))
+            {
+                etagValues.Add(etagProperty, targetResource.GetType().GetProperty(etagProperty).GetValue(targetResource, null));
+            }
+            return etagValues;
+        }
+
+        public virtual object GetResource(IQueryable query, string fullTypeName)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(query, "query");
+            object resource = null;
+            foreach (object r in query)
+            {
+                ExceptionUtilities.Assert(resource == null, "Invalid Uri specified. The query '{0}' must refer to a single resource", new object[] { query.ToString() });
+                resource = r;
+            }
+            if (resource == null)
+            {
+                return null;
+            }
+            if (fullTypeName != null)
+            {
+                this.ValidateResourceType(resource, fullTypeName);
+            }
+            return new UpdatableToken(resource);
+        }
+
+        public IList<T> GetResourceSetEntities<T>(string resourceSetName)
+        {
+            return (IList<T>) this.GetResourceSetEntities(resourceSetName);
+        }
+
+        internal IList GetResourceSetEntities(string resourceSetName)
+        {
+            IList entities;
+            if (!this.ResourceSetsStorage.TryGetValue(resourceSetName, out entities))
+            {
+                Type elementType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
+                entities = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { elementType }));
+                this.ResourceSetsStorage[resourceSetName] = entities;
+            }
+            return entities;
+        }
+
+        private string GetResourceSetOfTargetResource(object targetResource)
+        {
+            foreach (string currentResourceSetName in this.MetadataHelper.GetResourceSetNames())
+            {
+                if (this.GetResourceSetEntities(currentResourceSetName).Contains(targetResource))
+                {
+                    return currentResourceSetName;
+                }
+            }
+            return null;
+        }
+
+        public static string GetResourceTypeFullName(Type type)
+        {
+            return type.FullName.Replace('+', '_');
+        }
+
+        public virtual object GetValue(object targetResource, string propertyName)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
+            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
+            if (token.PendingPropertyUpdates.ContainsKey(propertyName))
+            {
+                return token.PendingPropertyUpdates[propertyName];
+            }
+            targetResource = token.Resource;
+            PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
+            ExceptionUtilities.CheckObjectNotNull(pi, "Cannot find the property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
+            object value = pi.GetValue(targetResource, null);
+            if ((value != null) && (pi.PropertyType.Assembly == base.GetType().Assembly))
+            {
+                ExceptionUtilities.Assert(!this.MetadataHelper.IsTypeAnEntityType(pi.PropertyType), "GetValue should never be called for reference properties. Type was '{0}', property was '{1}'", new object[] { pi.PropertyType.FullName, propertyName });
+                value = new UpdatableToken(value);
+            }
+            return value;
+        }
+
+        private UpdatableToken InstantiateResourceType(string fullTypeName)
+        {
+            Type t = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
+            object instance = Activator.CreateInstance(t);
+            UpdatableToken token = new UpdatableToken(instance);
+            foreach (PropertyInfo p in t.GetProperties())
+            {
+                object generatedValue;
+                PropertyInfo property = p;
+                if (this.IsCollectionProperty(property))
+                {
+                    Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(t), property.Name);
+                    if (collectionType != null)
+                    {
+                        object newCollection = Activator.CreateInstance(collectionType);
+                        token.PendingPropertyUpdates[property.Name] = newCollection;
+                        this.pendingChanges.Add(delegate {
+                            property.SetValue(instance, newCollection, null);
+                        });
+                    }
+                }
+                if (this.TryGetStoreGeneratedValue(fullTypeName, property.Name, out generatedValue))
+                {
+                    token.PendingPropertyUpdates[property.Name] = generatedValue;
+                    this.pendingChanges.Add(delegate {
+                        property.SetValue(instance, generatedValue, null);
+                    });
+                }
+            }
+            return token;
+        }
+
+        protected virtual bool IsCollectionProperty(PropertyInfo propertyInfo)
+        {
+            return ((typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType) && (propertyInfo.PropertyType != typeof(string))) && (propertyInfo.PropertyType != typeof(byte[])));
+        }
+
+        public virtual void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
+            ExceptionUtilities.CheckArgumentNotNull(resourceToBeRemoved, "resourceToBeRemoved");
+            UpdatableToken.AssertIsToken(targetResource, "targetResource");
+            resourceToBeRemoved = UpdatableToken.AssertIsTokenAndResolve(resourceToBeRemoved, "resourceToBeRemoved");
+            IList list = this.GetValue(targetResource, propertyName) as IList;
+            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
+            this.pendingChanges.Add(delegate {
+                list.Remove(resourceToBeRemoved);
+            });
+        }
+
+        private void RemoveResourceFromCollectionOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
+        {
+            IEnumerable childCollectionObject = navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) as IEnumerable;
+            if (childCollectionObject.Cast<object>().Any<object>(delegate (object o) {
+                return o == targetResource;
+            }))
+            {
+                MethodInfo removeMethod = navigationPropertyInfo.PropertyInfo.PropertyType.GetMethod("Remove");
+                this.pendingChanges.Add(delegate {
+                    removeMethod.Invoke(childCollectionObject, new object[] { targetResource });
+                });
+            }
+        }
+
+        public virtual object ResetResource(object resource)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
+            UpdatableToken token = UpdatableToken.AssertIsToken(resource, "resource");
+            resource = token.Resource;
+            token = new UpdatableToken(resource);
+            object newInstance = Activator.CreateInstance(resource.GetType());
+            ExceptionUtilities.CheckObjectNotNull(newInstance, "Cannot reset resource because unable to creating new instance of type '{0}' returns null", new object[] { resource.GetType().Name });
+            foreach (string propertyToReset in this.MetadataHelper.GetPropertiesToReset(GetResourceTypeFullName(resource.GetType())))
+            {
+                PropertyInfo pi = newInstance.GetType().GetProperty(propertyToReset);
+                ExceptionUtilities.CheckObjectNotNull(pi, "Cannot reset resource because unable to find property '{0}'", new object[] { propertyToReset });
+                object newValue = pi.GetValue(newInstance, null);
+                this.pendingChanges.Add(delegate {
+                    pi.SetValue(resource, newValue, null);
+                });
+                token.PendingPropertyUpdates[propertyToReset] = newValue;
+            }
+            return token;
+        }
+
+        public virtual object ResolveResource(object resource)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
+            return UpdatableToken.AssertIsTokenAndResolve(resource, "resource");
+        }
+
+        public virtual void SaveChanges()
+        {
+            foreach (Action pendingChange in this.pendingChanges)
+            {
+                pendingChange();
+            }
+            this.pendingChanges.Clear();
+            foreach (object deleted in this.deletedObjects)
+            {
+                foreach (object entity in this.ResourceSetsStorage.SelectMany<KeyValuePair<string, IList>, object>(delegate (KeyValuePair<string, IList> p) {
+                    return p.Value.Cast<object>();
+                }))
+                {
+                    ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, entity), "Found deleted entity!", new object[0]);
+                    foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties())
+                    {
+                        object value = propertyInfo.GetValue(entity, null);
+                        ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, value), "Found deleted entity!", new object[0]);
+                        IEnumerable enumerable = value as IEnumerable;
+                        if (enumerable != null)
+                        {
+                            foreach (object valueElement in enumerable.Cast<object>())
+                            {
+                                ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, valueElement), "Found deleted entity!", new object[0]);
+                            }
+                        }
+                    }
+                }
+            }
+            this.deletedObjects.Clear();
+        }
+
+        protected virtual void SetCollectionPropertyValue(object targetResource, PropertyInfo propertyInfo, IEnumerable propertyValue)
+        {
+            object collection;
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyInfo, "propertyInfo");
+            ExceptionUtilities.CheckArgumentNotNull(propertyValue, "propertyValue");
+            Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(propertyInfo.ReflectedType), propertyInfo.Name);
+            ExceptionUtilities.CheckObjectNotNull(collectionType, "Could not infer collection type for property", new object[0]);
+            propertyValue = propertyValue.Cast<object>().Select<object, object>(delegate (object o) {
+                return UpdatableToken.ResolveIfToken(o);
+            });
+            ConstructorInfo enumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable) });
+            if (enumerableConstructor != null)
+            {
+                collection = enumerableConstructor.Invoke(new object[] { propertyValue });
+            }
+            else if (collectionType.IsGenericType && (collectionType.GetGenericArguments().Count<Type>() == 1))
+            {
+                Type typeArgument = collectionType.GetGenericArguments().Single<Type>();
+                ConstructorInfo typedEnumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable<>).MakeGenericType(new Type[] { typeArgument }) });
+                if (typedEnumerableConstructor != null)
+                {
+                    object typedEnumerable = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new Type[] { typeArgument }).Invoke(null, new object[] { propertyValue });
+                    collection = typedEnumerableConstructor.Invoke(new object[] { typedEnumerable });
+                }
+                else
+                {
+                    MethodInfo typedAddMethod = collectionType.GetMethod("Add", new Type[] { typeArgument });
+                    ExceptionUtilities.CheckObjectNotNull(typedAddMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
+                    collection = Activator.CreateInstance(collectionType);
+                    foreach (object element in propertyValue)
+                    {
+                        typedAddMethod.Invoke(collection, new object[] { element });
+                    }
+                }
+            }
+            else
+            {
+                MethodInfo addMethod = collectionType.GetMethod("Add");
+                ExceptionUtilities.CheckObjectNotNull(addMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
+                collection = Activator.CreateInstance(collectionType);
+                foreach (object element in propertyValue)
+                {
+                    addMethod.Invoke(collection, new object[] { element });
+                }
+            }
+            propertyInfo.SetValue(targetResource, collection, null);
+        }
+
+        public virtual void SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(resourceCookie, "resourceCookie");
+            ExceptionUtilities.ThrowDataServiceExceptionIfFalse(checkForEquality.HasValue, 0x1a1, "Missing concurrency token for update operation", new object[0]);
+            ExceptionUtilities.Assert(checkForEquality.Value, "Should not be called with check for equality parameter equal to false", new object[0]);
+            ExceptionUtilities.CheckArgumentNotNull(concurrencyValues, "concurrencyValues");
+            if (concurrencyValues.Any<KeyValuePair<string, object>>())
+            {
+                resourceCookie = UpdatableToken.AssertIsTokenAndResolve(resourceCookie, "resourceCookie");
+                ExceptionUtilities.ThrowDataServiceExceptionIfFalse(CompareETagValues(this.GetConcurrencyValues(resourceCookie), concurrencyValues), 0x19c, "Concurrency tokens do not match", new object[0]);
+            }
+        }
+
+        private void SetEntityReferenceToNullOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
+        {
+            if (navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) == targetResource)
+            {
+                this.pendingChanges.Add(delegate {
+                    navigationPropertyInfo.PropertyInfo.SetValue(currentEntityInstance, null, null);
+                });
+            }
+        }
+
+        public virtual void SetReference(object targetResource, string propertyName, object propertyValue)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
+            if (propertyValue != null)
+            {
+                UpdatableToken.AssertIsToken(propertyValue, "propertyValue");
+            }
+            this.SetValue(targetResource, propertyName, propertyValue);
+        }
+
+        public virtual void SetValue(object targetResource, string propertyName, object propertyValue)
+        {
+            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
+            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
+            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
+            targetResource = token.Resource;
+            token.PendingPropertyUpdates[propertyName] = propertyValue;
+            this.pendingChanges.Add(delegate {
+                object generatedValue;
+                Type t = targetResource.GetType();
+                PropertyInfo pi = t.GetProperty(propertyName);
+                ExceptionUtilities.CheckObjectNotNull(pi, "Unable to find property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
+                if (this.TryGetStoreGeneratedValue(GetResourceTypeFullName(t), propertyName, out generatedValue))
+                {
+                    propertyValue = generatedValue;
+                }
+                if (this.IsCollectionProperty(pi))
+                {
+                    ExceptionUtilities.CheckObjectNotNull(propertyValue, "Collection property value was null", new object[0]);
+                    IEnumerable enumerable = propertyValue as IEnumerable;
+                    ExceptionUtilities.CheckObjectNotNull(enumerable, "Collection property value was not an enumerable", new object[0]);
+                    this.SetCollectionPropertyValue(targetResource, pi, enumerable);
+                }
+                else
+                {
+                    propertyValue = UpdatableToken.ResolveIfToken(propertyValue);
+                    pi.SetValue(targetResource, propertyValue, null);
+                }
+            });
+        }
+
+        protected virtual bool TryGetStoreGeneratedValue(string fullTypeName, string propertyName, out object propertyValue)
+        {
+            propertyValue = null;
+            return false;
+        }
+
+        private void ValidateResourceType(object targetResource, string fullTypeName)
+        {
+            ExceptionUtilities.Assert(this.MetadataHelper.FindClrTypeByFullName(fullTypeName).IsAssignableFrom(targetResource.GetType()), "Invalid uri specified. expected type: '{0}', actual type: '{1}'", new object[] { fullTypeName, targetResource.GetType().FullName });
+        }
+
+        // Properties
+        internal ReflectionMetadataHelper MetadataHelper { get; set; }
+
+        internal Dictionary<string, IList> ResourceSetsStorage
+        {
+            get
+            {
+                Dictionary<string, IList> resourceSetsLookup = null;
+                Type currentContextType = base.GetType();
+                ExceptionUtilities.Assert(resourceSetsByContextTypeStorage.TryGetValue(currentContextType, out resourceSetsLookup), "Cannot find resource sets by the context type '{0}'", new object[] { currentContextType });
+                return resourceSetsLookup;
+            }
+        }
+
+        #region Inner types.
+    
+        internal class ReflectionMetadataHelper
+        {
+            // Fields
+            private ReflectionDataContext reflectionDataContext;
+
+            // Methods
+            public ReflectionMetadataHelper(ReflectionDataContext reflectionDataContext)
+            {
+                this.reflectionDataContext = reflectionDataContext;
+            }
+
+            public Type FindClrTypeByFullName(string resourceTypeFullName)
+            {
+                Type type = this.reflectionDataContext.GetType().Assembly.GetTypes().Where<Type>(delegate (Type t) {
+                    return (ReflectionDataContext.GetResourceTypeFullName(t) == resourceTypeFullName);
+                }).FirstOrDefault<Type>();
+                ExceptionUtilities.CheckObjectNotNull(type, "Unable to find type '{0}'", new object[] { resourceTypeFullName });
+                return type;
+            }
+
+            public string[] GetETagPropertiesOfType(string fullTypeName)
+            {
+                Type type = this.FindClrTypeByFullName(fullTypeName);
+                List<string> etags = new List<string>();
+                foreach (ETagAttribute customAttribute in type.GetCustomAttributes(typeof(ETagAttribute), true))
+                {
+                    etags.AddRange(customAttribute.PropertyNames);
+                }
+                
+                return etags.ToArray();
+            }
+
+            public string[] GetKeyProperties(string fullTypeName)
+            {
+                Type type = this.FindClrTypeByFullName(fullTypeName);
+                List<string> keyPropertyList = new List<string>();
+                foreach (PropertyInfo keyProperty in type.GetProperties().Where(pi => pi.Name.Contains("ID")))
+                {
+                    keyPropertyList.Add(keyProperty.Name);
+                }
+                
+                return keyPropertyList.ToArray();
+            }
+
+            public NavigationPropertyInfo[] GetNavigationProperties(string fullTypeName)
+            {
+                Type type = this.FindClrTypeByFullName(fullTypeName);
+                var navigationProperties = new List<NavigationPropertyInfo>();
+                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
+                foreach (PropertyInfo pi in type.GetProperties())
+                {
+                    if (!keyProperties.Contains(pi.Name))
+                    {
+                        if (this.IsTypeAnEntityType(pi.PropertyType))
+                        {
+                            navigationProperties.Add(new NavigationPropertyInfo(pi, null));
+                        }
+
+                        if (pi.PropertyType.IsGenericType && ((pi.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) || (pi.PropertyType.GetGenericTypeDefinition() == typeof(Collection<>))))
+                        {
+                            Type elementType = pi.PropertyType.GetGenericArguments()[0];
+                            if (this.IsTypeAnEntityType(elementType))
+                            {
+                                navigationProperties.Add(new NavigationPropertyInfo(pi, elementType));
+                            }
+                        }
+                    }
+                }
+
+                return navigationProperties.ToArray();
+            }
+
+            public string[] GetPropertiesToReset(string fullTypeName)
+            {
+                Type type = this.FindClrTypeByFullName(fullTypeName);
+                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
+                var navigationProperties = new List<string>(this.GetNavigationProperties(fullTypeName).Select(ni =>ni.PropertyInfo.Name));
+                return type.GetProperties().Where(
+                    pi => !keyProperties.Contains(pi.Name) && !navigationProperties.Contains(pi.Name)
+                ).Select(pi => pi.Name).ToArray();
+            }
+
+            public string[] GetResourceSetNames()
+            {
+                return this.reflectionDataContext.GetType().GetProperties().Where(
+                    pi => pi.PropertyType.IsGenericType && (pi.PropertyType.GetGenericTypeDefinition() == typeof(IQueryable<>))
+                ).Select(pi => pi.Name).ToArray();
+            }
+
+            public Type GetResourceTypeOfSet(string resourceSetName)
+            {
+                PropertyInfo resourceSetPropertyInfo = this.reflectionDataContext.GetType().GetProperties().Where(pi => pi.Name == resourceSetName).FirstOrDefault();
+                ExceptionUtilities.CheckObjectNotNull(resourceSetPropertyInfo, "Error finding type of set '{0}'", new object[] { resourceSetName });
+                return resourceSetPropertyInfo.PropertyType.GetGenericArguments()[0];
+            }
+
+            public bool IsTypeAnEntityType(Type t)
+            {
+                foreach (string setName in this.GetResourceSetNames())
+                {
+                    if (this.GetResourceTypeOfSet(setName).IsAssignableFrom(t))
+                    {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        }
+
+        internal static class ExceptionUtilities
+        {
+            // Methods
+            public static void Assert(bool condition, string errorMessage, params object[] messageArguments)
+            {
+                if (!condition)
+                {
+                    throw new InvalidOperationException("Assertion failed: " + string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
+                }
+            }
+
+            public static void CheckArgumentNotNull(object argument, string argumentName)
+            {
+                if (argument == null)
+                {
+                    throw new ArgumentNullException(argumentName);
+                }
+            }
+
+            public static void CheckCollectionNotEmpty<TElement>(IEnumerable<TElement> argument, string argumentName)
+            {
+                CheckArgumentNotNull(argument, argumentName);
+                if (!argument.Any<TElement>())
+                {
+                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Collection argument '{0}' must have at least one element.", new object[] { argumentName }));
+                }
+            }
+
+            public static void CheckObjectNotNull(object value, string exceptionMessageFormatText, params object[] messageArguments)
+            {
+                Assert(exceptionMessageFormatText != null, "message cannnot be null", new object[0]);
+                Assert(messageArguments != null, "messageArguments cannnot be null", new object[0]);
+                if (value == null)
+                {
+                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, exceptionMessageFormatText, messageArguments));
+                }
+            }
+
+            public static void ThrowDataServiceExceptionIfFalse(bool condition, int statusCode, string errorMessage, params object[] messageArguments)
+            {
+                if (!condition)
+                {
+                    throw new DataServiceException(statusCode, string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
+                }
+            }
+        }
+
+        public class UpdatableToken
+        {
+            // Methods
+            public UpdatableToken(object resource)
+            {
+                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
+                this.Resource = resource;
+                this.PendingPropertyUpdates = new Dictionary<string, object>();
+            }
+
+            public static UpdatableToken AssertIsToken(object resource, string name)
+            {
+                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
+                UpdatableToken token = resource as UpdatableToken;
+                ExceptionUtilities.CheckObjectNotNull(token, "{0} was not a token. Type was: '{1}'", new object[] { name, resource.GetType() });
+                return token;
+            }
+
+            public static object AssertIsTokenAndResolve(object resource, string name)
+            {
+                return AssertIsToken(resource, name).Resource;
+            }
+
+            public static object ResolveIfToken(object resource)
+            {
+                UpdatableToken token = resource as UpdatableToken;
+                if (token != null)
+                {
+                    resource = token.Resource;
+                }
+                return resource;
+            }
+
+            // Properties
+            public IDictionary<string, object> PendingPropertyUpdates { get; set; }
+
+            public object Resource { get; set; }
+        }
+
+        internal class NavigationPropertyInfo
+        {
+            // Methods
+            internal NavigationPropertyInfo(PropertyInfo pi, Type collectionElementType)
+            {
+                this.PropertyInfo = pi;
+                this.CollectionElementType = collectionElementType;
+            }
+
+            // Properties
+            public Type CollectionElementType { get; set; }
+
+            public PropertyInfo PropertyInfo { get; set; }
+        }
+
+        #endregion Inner types.
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/code/csdlreader.cs
----------------------------------------------------------------------
diff --git a/odatajs/tests/code/csdlreader.cs b/odatajs/tests/code/csdlreader.cs
new file mode 100644
index 0000000..c88333e
--- /dev/null
+++ b/odatajs/tests/code/csdlreader.cs
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+/// <summary>
+/// Class used to parse csdl to create the metatdata object
+/// </summary>
+/// 
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using System.Xml.Linq;
+
+
+    public static class CsdlReader
+    {
+        static readonly string knownNamespace = "http://docs.oasis-open.org";
+        static readonly string[] repeatingElements = 
+            {
+                "Action",
+                "ActionImport",
+                "Annotation",
+                "Annotations",
+                "Apply",
+                "Binary",
+                "Bool",
+                "Cast",
+                "Collection",
+                "ComplexType",
+                "Date",
+                "DateTimeOffset",
+                "Decimal",
+                "Duration",
+                "EntitySet",
+                "EntityType",
+                "EnumMember",
+                "EnumType",
+                "Float",
+                "Function",
+                "FunctionImport",
+                "Guid",
+                "If",
+                "Int",
+                "IsOf",
+                "Key",
+                "LabeledElement",
+                "LabeledElementReference",
+                "Member",
+                "NavigationProperty",
+                "NavigationPropertyBinding",
+                "NavigationPropertyPath",
+                "Null",
+                "OnDelete",
+                "Path",
+                "Parameter",
+                "Property",
+                "PropertyPath",
+                "PropertyRef",
+                "PropertyValue",
+                "Record",
+                "ReferentialConstraint",
+                "String",
+                "Schema",
+                "Singleton",
+                "Term",
+                "TimeOfDay",
+                "TypeDefinition",
+                "UrlRef",
+                "Reference",
+                "Include",
+                "IncludeAnnotations"
+            };
+
+        public static Dictionary<string, object> ReadCsdl(TextReader payload)
+        {
+            return BuildElementJsonObject(XElement.Load(payload));
+        }
+
+        /// <summary>
+        /// Build the attribute object 
+        /// </summary>
+        /// <param name="xmlAttributes">IEnumberable of XAttributes to build the attribute object</param>
+        /// <returns>The JsonObject containing the name-value pairs for an element's attributes</returns>
+        static Dictionary<string, object> BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes)
+        {
+            Dictionary<string, object> jsonObject = new Dictionary<string, object>();
+
+            foreach (XAttribute attribute in xmlAttributes)
+            {
+                if (!attribute.IsNamespaceDeclaration)
+                {
+                    string attributeNamespace = attribute.Name.Namespace.ToString();
+                    if (string.IsNullOrEmpty(attributeNamespace) ||
+                        attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
+                    {
+                        jsonObject[MakeFirstLetterLowercase(attribute.Name.LocalName)] = attribute.Value;
+                    }
+                }
+            }
+
+            return jsonObject;
+        }
+
+        /// <summary>
+        /// Creates a JsonObject from an XML container element with each attribute or subelement as a property
+        /// </summary>
+        /// <param name="container">The XML container</param>
+        /// <param name="buildValue">Function that builds a value from a property element</param>
+        /// <returns>The JsonObject containing the name-value pairs</returns>
+        public static Dictionary<string, object> BuildElementJsonObject(XElement container)
+        {
+            if (container == null)
+            {
+                return null;
+            }
+
+            Dictionary<string, object> jsonObject = new Dictionary<string, object>();
+            string keyName = MakeFirstLetterLowercase(container.Name.LocalName);
+
+            if (container.HasAttributes || container.HasElements)
+            {
+                Dictionary<string, List<Dictionary<string, object>>> repeatingObjectArrays = new Dictionary<string, List<Dictionary<string, object>>>();
+
+                jsonObject = BuildAttributeJsonObject(container.Attributes());
+
+                foreach (XElement propertyElement in container.Elements())
+                {
+                    string propertyName = MakeFirstLetterLowercase(propertyElement.Name.LocalName);
+                    string properyNamespace = propertyElement.Name.Namespace.ToString();
+
+                    if (string.IsNullOrEmpty(properyNamespace) || properyNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase))
+                    {
+                        // Check to see if the element is repeating and needs to be an array
+                        if (repeatingElements.Contains(propertyElement.Name.LocalName))
+                        {
+                            // See if property was already created as an array, if not then create it
+                            if (!repeatingObjectArrays.ContainsKey(propertyName))
+                            {
+                                repeatingObjectArrays.Add(propertyName, new List<Dictionary<string, object>>());
+                            }
+
+                            repeatingObjectArrays[propertyName].Add(BuildElementJsonObject(propertyElement));
+                        }
+                        else
+                        {
+                            jsonObject[propertyName] = BuildElementJsonObject(propertyElement);
+                        }
+                    }
+                }
+
+                foreach (string key in repeatingObjectArrays.Keys)
+                {
+                    jsonObject[key] = repeatingObjectArrays[key].ToArray();
+                }
+            }
+            else
+            {
+                jsonObject[MakeFirstLetterLowercase(container.Name.LocalName)] = container.Value;
+            }
+
+            return jsonObject;
+        }
+
+        /// <summary>
+        /// Makes the first letter of a string lowercase
+        /// </summary>
+        /// <param name="name">The string to be modified</param>
+        /// <returns>Modified string</returns>
+        private static string MakeFirstLetterLowercase(string str)
+        {
+            if (!string.IsNullOrWhiteSpace(str))
+            {
+                if (str.Length > 1 && !(str[1].ToString() == str[1].ToString().ToUpper()))
+                {
+                    return str[0].ToString().ToLower() + str.Substring(1);
+                }
+                else
+                {
+                    return str;
+                }
+            }
+
+            return str;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/code/jsdate.cs
----------------------------------------------------------------------
diff --git a/odatajs/tests/code/jsdate.cs b/odatajs/tests/code/jsdate.cs
new file mode 100644
index 0000000..06f995d
--- /dev/null
+++ b/odatajs/tests/code/jsdate.cs
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+/// <summary>
+/// The oracle's representation of a Javascript date object as deserialized by the library
+/// </summary>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using System.Net;
+    using System.Runtime.Serialization;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Syndication;
+    using System.ServiceModel.Web;
+    using System.Xml;
+    using System.Xml.Linq;
+    using Microsoft.Spatial;
+    using Microsoft.OData.Core;
+
+    [Serializable]
+    public class JsDate : JsonObject
+    {
+        private static readonly DateTime JsEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+        public JsDate(DateTime dateTime)
+            : base()
+        {
+            this["milliseconds"] = dateTime.Subtract(JsEpoch).TotalMilliseconds;
+        }
+
+        public JsDate(DateTimeOffset dateTimeOffset)
+            : this(dateTimeOffset.UtcDateTime)
+        {
+            this["__edmType"] = "Edm.DateTimeOffset";
+            this["__offset"] = (dateTimeOffset.Offset < TimeSpan.Zero ? "-" : "+") + dateTimeOffset.Offset.ToString("hh':'mm");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/code/jsonobject.cs
----------------------------------------------------------------------
diff --git a/odatajs/tests/code/jsonobject.cs b/odatajs/tests/code/jsonobject.cs
new file mode 100644
index 0000000..27f4b9b
--- /dev/null
+++ b/odatajs/tests/code/jsonobject.cs
@@ -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.
+ */
+
+/// <summary>
+/// A weakly typed representation of a JSON object using a dictionary implementation
+/// </summary>
+/// <typeparam name="T">The CLR type of the values of the properties</typeparam>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Runtime.Serialization;
+
+    [Serializable]
+    [KnownType(typeof(JsonObject))]
+    [KnownType(typeof(JsonObject[]))]
+    [KnownType(typeof(JsDate))]
+    [KnownType(typeof(List<object>))]
+    public class JsonObject : ISerializable, IEnumerable<KeyValuePair<string, object>>
+    {
+        Dictionary<string, object> dictionary = new Dictionary<string, object>();
+
+        public void Remove(string key)
+        {
+            dictionary.Remove(key);
+        }
+
+        public object this[string key]
+        {
+            get
+            {
+                return this.dictionary[key];
+            }
+            set
+            {
+                this.dictionary[key] = value;
+            }
+        }
+
+        public bool ContainsKey(string key)
+        {
+            return this.dictionary.ContainsKey(key);
+        }
+
+        public static JsonObject Merge(JsonObject first, JsonObject second)
+        {
+            if (first == null)
+            {
+                return second;
+            }
+
+            if (second != null)
+            {
+                JsonObject merged = new JsonObject();
+                merged.dictionary = new Dictionary<string, object>(first.dictionary);
+                foreach (var pair in second.dictionary)
+                {
+                    merged.dictionary[pair.Key] = pair.Value;
+                }
+                return merged;
+            }
+            return first;
+        }
+
+        public void GetObjectData(SerializationInfo info, StreamingContext context)
+        {
+            this.dictionary.ToList().ForEach(pair => info.AddValue(pair.Key, pair.Value));
+        }
+
+        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+        {
+            return this.dictionary.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return this.dictionary.GetEnumerator();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/code/readerutils.cs
----------------------------------------------------------------------
diff --git a/odatajs/tests/code/readerutils.cs b/odatajs/tests/code/readerutils.cs
new file mode 100644
index 0000000..094a70c
--- /dev/null
+++ b/odatajs/tests/code/readerutils.cs
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Web.Script.Serialization;
+
+namespace DataJS.Tests
+{
+    public static class ReaderUtils
+    {
+        public static JsonObject CreateEntryPropertyMetadata(string type)
+        {
+            return CreateEntryPropertyMetadata(type, true);
+        }
+
+        public static JsonObject CreateEntryPropertyMetadata(string type, bool withExtensions)
+        {
+            JsonObject json = new JsonObject();
+            json["type"] = type;
+
+
+            // TODO: add proper support for property extensions
+            if (withExtensions)
+            {
+                json["extensions"] = new JsonObject[] { };
+            }
+
+            return json;
+        }
+
+        public static JsonObject CreateExtension(string name, string nameSpace, string value)
+        {
+            JsonObject json = new JsonObject();
+            json["name"] = name;
+            json["namespaceURI"] = nameSpace;
+            json["value"] = value;
+            return json;
+        }
+
+        public static WebRequest CreateRequest(string url, string user = null, string password = null)
+        {
+            WebRequest request = WebRequest.Create(url);
+            if (user != null || password != null)
+            {
+                request.Credentials = new NetworkCredential(user, password);
+                request.PreAuthenticate = true;
+            }
+
+            return request;
+        }
+
+        public static Stream ConvertDictionarytoJsonlightStream(Dictionary<string, object> dict)
+        {
+            MemoryStream stream = new MemoryStream();
+            if (dict == null)
+            {
+                return stream;
+            }
+
+            string jsonString = new JavaScriptSerializer().Serialize(dict);
+            StreamWriter writer = new StreamWriter(stream);
+            writer.Write(jsonString);
+            writer.Flush();
+            stream.Position = 0;
+            return stream;
+        }
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/CacheOracle.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/CacheOracle.js b/odatajs/tests/common/CacheOracle.js
new file mode 100644
index 0000000..d34d79f
--- /dev/null
+++ b/odatajs/tests/common/CacheOracle.js
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+// CacheOracle.js
+// This object verifies the operation of the cache.
+// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
+
+(function (window, undefined) {
+
+    var CacheOracle = function (baseUri, pageSize, total, cacheSize) {
+        /** Creates a new CacheOracle
+         * @param {String} baseUri - The base URI of the collection
+         * @param {Integer} pageSize - The page size used in the cache
+         * @param {Integer} total - The total number of items in the collection
+         * @param {Integer} cacheSize - Cache size in bytes
+         */
+        this.baseUri = baseUri;
+        this.pageSize = pageSize;
+        this.total = total;
+        this.cacheSize = (cacheSize !== undefined) ? cacheSize : 1024 * 1024;
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.cachedPages = [];
+        this.exactPageCount = (total % pageSize === 0);
+        this.maxPage = Math.floor(total / pageSize);
+        this.overflowed = this.cacheSize === 0;
+    };
+
+    CacheOracle.mechanisms = {
+        memory: "memory",
+        indexeddb: "indexeddb",
+        dom: "dom",
+        best: "best"
+    };
+
+    CacheOracle.isMechanismAvailable = function (mechanism) {
+        /** Determines if the specified local storage mechanism is available
+         * @param mechanism - The name of the mechanism
+         * @returns Whether the mechanism is available
+         */
+        switch (mechanism) {
+            case CacheOracle.mechanisms.indexeddb:
+                if (window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.indexedDB) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheOracle.mechanisms.dom:
+                if (window.localStorage) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheOracle.mechanisms.memory:
+            case CacheOracle.mechanisms.best:
+            case undefined:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    CacheOracle.prototype.clear = function () {
+        /** Clears the cache in the oracle
+        */
+        this.cachedPages = [];
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.overflowed = this.cacheSize === 0;
+    }
+
+    CacheOracle.prototype.verifyRequests = function (requests, responses, index, count, description, backwards, isPrefetch) {
+        /** Verifies the HTTP requests for a single data request, and updates the oracle with cached pages
+         * @param {Array} requests - The sequence of request objects (from OData.defaultHttpClient)
+         * @param {Array} responses - The sequence of response objects (from OData.defaultHttpClient)
+         * @param {Integer} index - The starting index of the read
+         * @param {Integer} count - The count of items in the read
+         * @param {String} description - The description of the requests being verified
+         * @param {Boolean} backwards - Whether or not filterBack is being verified
+         * @param {Boolean} isPrefetch - Whether the requests being verified come from the prefetcher
+         */
+        var that = this;
+
+        index = (index < 0 ? 0 : index);
+        var pageIndex = function (index) {
+            /** Returns the page index that the given item index belongs to
+             * @param {Integer} index - The item index
+             * @returns The page index
+             */
+            return Math.floor(index / that.pageSize);
+        };
+
+        var estimateSize = function (obj) {
+            /** Estimates the size of an object in bytes.
+             * @param {Object} obj - Object to determine the size of.
+             * @returns {Number} Estimated size of the object in bytes.
+             */
+
+            var size = 0;
+            var type = typeof obj;
+
+            if (type === "object" && obj) {
+                for (var name in obj) {
+                    size += name.length * 2 + estimateSize(obj[name]);
+                }
+            } else if (type === "string") {
+                size = obj.length * 2;
+            } else {
+                size = 8;
+            }
+            return size;
+        };
+
+        var expectedUris = [];
+        var responseIndex = 0;
+        if (count >= 0) {
+            var minPage = pageIndex(index);
+            var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(this.total));
+
+            // In the case that the index is outside the range of the collection the minPage will be greater than the maxPage  
+            maxPage = Math.max(minPage, maxPage);
+
+            if (!(isPrefetch && !this.exactPageCount && minPage > this.maxPage)) {
+                for (var page = minPage; page <= maxPage && this.actualCount <= this.total && !(isPrefetch && this.overflowed); page++) {
+                    if (!this.cachedPages[page]) {
+
+                        expectedUris.push(that.baseUri + "?$skip=" + page * this.pageSize + "&$top=" + (this.pageSize));
+
+                        var actualPageSize = 0;
+                        var actualPageCount = 0;
+                        if (responses[responseIndex] && responses[responseIndex].data) {
+                            actualPageSize += estimateSize(responses[responseIndex].data);
+                            actualPageCount += responses[responseIndex].data.value.length;
+                            // Handle server paging skipToken requests
+                            while (responses[responseIndex].data["@odata.nextLink"]) {
+                                var nextLink = responses[responseIndex].data["@odata.nextLink"];
+                                if (nextLink) {
+                                    var index = that.baseUri.indexOf(".svc/", 0);
+                                    if (index != -1) {
+                                        nextLink = that.baseUri.substring(0, index + 5) + nextLink;
+                                    }
+                                }
+
+                                expectedUris.push(nextLink);
+                                responseIndex++;
+                                actualPageSize += estimateSize(responses[responseIndex].data);
+                                actualPageCount += responses[responseIndex].data.value.length;
+                            }
+
+                            actualPageSize += 24; // 24 byte overhead for the pages (i)ndex, and (c)ount fields
+                        }
+
+                        responseIndex++;
+
+                        this.overflowed = this.cacheSize >= 0 && this.actualSize + actualPageSize > this.cacheSize;
+                        if (!this.overflowed) {
+                            this.cachedPages[page] = true;
+                            this.actualSize += actualPageSize;
+                            this.actualCount += actualPageCount;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (backwards) {
+            expectedUris.reverse();
+        }
+
+        var actualUris = $.map(requests, function (r) { return r.requestUri; });
+        djstest.assertAreEqualDeep(actualUris, expectedUris, description);
+    };
+
+    CacheOracle.getExpectedFilterResults = function (data, filterIndex, filterCount, predicate, backwards) {
+        /** Verifies the cache filter returns the correct data
+         * @param {Array} collection - Array of items in the collection
+         * @param {Integer} filterIndex - The index value
+         * @param {Integer} filterCount - The count value
+         * @param {Function} predicate - Predicate to be applied in filter, takes an item
+         * @param {Boolean} backwards - Whether or not filterBackwards is being verified
+         */
+        if (!data || !data.value) {
+            return data;
+        }
+
+        var value = [];
+        if (filterCount !== 0) {
+            // Convert [item0, item1, ...] into [{ index: 0, item: item0 }, { index: 1, item: item1 }, ...]
+            var indexedCollection = $.map(data.value, function (item, index) {
+                return { index: index, item: item };
+            });
+
+            var grepPredicate = function (element, index) {
+                return predicate(element.item);
+            };
+
+            var index = filterIndex < 0 ? 0 : filterIndex;
+            var count = filterCount < 0 ? indexedCollection.length : filterCount;
+
+            value = backwards ?
+            // Slice up to 'index', filter, then slice 'count' number of items from the end
+                $.grep(indexedCollection.slice(0, index + 1), grepPredicate).slice(-count) :
+            // Slice from 'index' to the end, filter, then slice 'count' number of items from the beginning
+                $.grep(indexedCollection.slice(index), grepPredicate).slice(0, count);
+        }
+
+        var expectedResults = {};
+        for (var property in data) {
+            if (property == "value") {
+                expectedResults[property] = value;
+            } else {
+                expectedResults[property] = data[property];
+            }
+        }
+
+        return expectedResults;
+    };
+
+    window.CacheOracle = CacheOracle;
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/Instrument.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/Instrument.js b/odatajs/tests/common/Instrument.js
new file mode 100644
index 0000000..fab583a
--- /dev/null
+++ b/odatajs/tests/common/Instrument.js
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+// Instrument.js
+// Instrumentation utilities
+
+(function (window, undefined) {
+
+    var warmedUp = false;
+    var getBrowserMemorySize = function (success) {
+        /** Gets the memory size (in bytes) of the browser process
+         * @param {Function} success - The success callback
+         */
+        var makeRequest = function (success) {
+            $.get("./common/Instrument.svc/GetBrowserMemorySize", function (data) {
+                success(parseInt(data));
+            }, "text");
+        };
+
+        if (window.CollectGarbage) {
+            window.CollectGarbage();
+        }
+
+        if (!warmedUp) {
+            // Make a dummy request to warm it up
+            makeRequest(function () {
+                warmedUp = true;
+                makeRequest(success);
+            });
+        } else {
+            makeRequest(success);
+        }
+    }
+
+    window.Instrument = {
+        getBrowserMemorySize: getBrowserMemorySize
+    };
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/Instrument.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/Instrument.svc b/odatajs/tests/common/Instrument.svc
new file mode 100644
index 0000000..111020f
--- /dev/null
+++ b/odatajs/tests/common/Instrument.svc
@@ -0,0 +1,77 @@
+/*
+ * 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.
+*/
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
+    Service="DataJS.Tests.Instrument" %>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.IO;
+    using System.Linq;
+    using System.Runtime.Serialization;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Syndication;
+    using System.ServiceModel.Web;
+    using System.Text;
+
+    /// <summary>
+    /// Instrumentation utilities
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class Instrument
+    {
+        static readonly Dictionary<string, string> userAgents = new Dictionary<string,string>
+        {
+            { "MSIE", "iexplore" },
+            { "Firefox", "firefox" },
+            { "Chrome", "chrome" },
+            { "Safari", "safari" }
+        };
+        
+        /// <summary>
+        /// Gets the memory size used by the browser
+        /// </summary>
+        /// <returns>The memory size used by the browser (in bytes), or zero if browser is not supported</returns>
+        [OperationContract]
+        [WebGet]
+        public Stream GetBrowserMemorySize()
+        {
+            string userAgentString = WebOperationContext.Current.IncomingRequest.UserAgent;
+            string userAgentKey = Instrument.userAgents.Keys.FirstOrDefault(ua => userAgentString.Contains(ua));
+
+            if (userAgentKey != null)
+            {
+                string processName = userAgents[userAgentKey];
+                long totalMemory = Process.GetProcessesByName(processName).Select(p => p.WorkingSet64).Sum();
+                
+                return new MemoryStream(Encoding.UTF8.GetBytes(totalMemory.ToString()));
+            }
+            else
+            {
+                return new MemoryStream(Encoding.UTF8.GetBytes("0"));
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/ODataReadOracle.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/ODataReadOracle.js b/odatajs/tests/common/ODataReadOracle.js
new file mode 100644
index 0000000..83967ce
--- /dev/null
+++ b/odatajs/tests/common/ODataReadOracle.js
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+ 
+
+// Client for the odata.read oracle service
+
+(function (window, undefined) {
+    var jsonMime = "application/json";
+    var universalMime = "*/*";
+
+    var readFeed = function (url, success, mimeType, recognizeDates) {
+        /** Calls the ReadFeed endpoint with the specified URL
+         * @param {String} url - The URL to read the feed from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) {
+            success(data);
+        });
+    };
+
+    var readEntry = function (url, success, mimeType, recognizeDates) {
+        /** Calls the ReadEntry endpoint with the specified URL
+         * @param {String} url - The URL to read the entry from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, success);
+    };
+
+    var readLinksEntry = function (url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            success
+        );
+    };
+
+    var readLinksFeed = function (url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            function (data) {
+                success(data);
+            }
+        );
+    };
+
+    var readMetadata = function (url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success);
+    };
+
+    var readServiceDocument = function (url, success, mimeType) {
+        /** Calls the ReadServiceDocument endpoint with the specified URL
+         * @param {String} url - The URL to the service
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME type being tested
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success);
+    };
+
+    var readJson = function (url, success) {
+        $.ajax({
+            url: url,
+            accepts: null,
+            dataType: "json",
+            beforeSend: function (xhr) {
+                xhr.setRequestHeader("Accept", jsonMime);
+                xhr.setRequestHeader("OData-MaxVersion", "4.0");
+            },
+            success: function (data) {
+                success(data);
+            }
+        });
+    };
+
+    var readJsonAcrossServerPages = function (url, success) {
+        var data = {};
+        var readPage = function (url) {
+            readJson(url, function (feedData) {
+                var nextLink = feedData["@odata.nextLink"];
+                if (nextLink) {
+                    var index = url.indexOf(".svc/", 0);
+                    if (index != -1) {
+                        nextLink = url.substring(0, index + 5) + nextLink;
+                    }
+                }
+
+                if (data.value && feedData.value) {
+                    data.value = data.value.concat(feedData.value);
+                }
+                else {
+                    for (var property in feedData) {
+                        if (property != "@odata.nextLink") {
+                            data[property] = feedData[property];
+                        }
+                    }
+                }
+
+                if (nextLink) {
+                    readPage(nextLink);
+                }
+                else {
+                    success(data);
+                }
+            });
+        };
+
+        readPage(url);
+    };
+
+    var getReadMethod = function (mimeType) {
+        switch (mimeType) {
+            case jsonMime:
+            case universalMime:
+            default:
+                return "ReadJson";
+        }
+    };
+
+    var oracleRequest = function (method, endpoint, data, mimeType, recognizeDates, success) {
+        /** Requests a JSON object from the oracle service, removing WCF-specific artifacts
+         * @param {String} method - The HTTP method (GET or POST)
+         * @param {String} endpoint - The oracle endpoint
+         * @param {Object} data - The data to send with the request
+         * @param {Function} reviver - The reviver function to run on each deserialized object
+         * @param {Function} success - Success callback
+         */
+        var url = "./common/ODataReadOracle.svc/" + endpoint;
+        if (mimeType) {
+            data.mimeType = mimeType;
+        }
+
+        $.ajax({
+            type: method,
+            url: url,
+            data: data,
+            dataType: "text",
+            success: function (data) {
+                var json = JSON.parse(data);
+                success(json);
+            }
+        });
+    };
+
+    var removeProperty = function (data, property) {
+        /** Removes the specified property recursively from the given object
+         * @param {Object} data - The object to operate on
+         * @param {String} property - The name of the property to remove
+         */
+        if (typeof data === "object" && data !== null) {
+            if (data[property]) {
+                delete data[property];
+            }
+
+            for (prop in data) {
+                removeProperty(data[prop], property);
+            }
+        }
+    };
+
+    window.ODataReadOracle = {
+        readFeed: readFeed,
+        readEntry: readEntry,
+        readLinksEntry: readLinksEntry,
+        readLinksFeed: readLinksFeed,
+        readJson: readJson,
+        readJsonAcrossServerPages: readJsonAcrossServerPages,
+        readMetadata: readMetadata,
+        readServiceDocument: readServiceDocument
+    };
+})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/ODataReadOracle.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/ODataReadOracle.svc b/odatajs/tests/common/ODataReadOracle.svc
new file mode 100644
index 0000000..339666c
--- /dev/null
+++ b/odatajs/tests/common/ODataReadOracle.svc
@@ -0,0 +1,114 @@
+/*
+ * 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.
+*/
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
+    Service="DataJS.Tests.ODataReadOracle" %>
+
+//uncomment this line to debug JSON serialization.
+//#define DEBUG_SERIALIZATION
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using System.Net;
+    using System.Runtime.Serialization;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Syndication;
+    using System.ServiceModel.Web;
+    using System.Xml;
+    using System.Xml.Linq;
+    using Microsoft.Spatial;
+    using Microsoft.OData.Core;
+    using System.Web.Script.Serialization;
+
+    /// <summary>
+    /// Oracle for the OData.read library function
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class ODataReadOracle
+    {
+        const string jsonlightMediaType = "application/json";
+
+        /// <summary>
+        /// Reads a URI that will return a metadata object
+        /// </summary>
+        /// <param name="url">The URL to send the request to</param>
+        /// <returns>Stream of metadata in json light format</returns>
+        [OperationContract]
+        [WebGet]
+        public Stream ReadMetadata(string url)
+        {
+            WebResponse response = WebRequest.Create(ResolveUri(url, UriKind.Absolute)).GetResponse();
+            Dictionary<string, object> jsonObject = CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream()));
+            return ReaderUtils.ConvertDictionarytoJsonlightStream(jsonObject);
+        }
+        
+        /// <summary>
+        /// Reads a URI that will get the Json response and return the stream
+        /// </summary>
+        /// <param name="url">URL of the entry</param>
+        /// <param name="user">The username for basic authentication</param>
+        /// <param name="password">The password for basic authentication</param>
+        /// <returns>Stream of the Json response expected to be returned by OData.read</returns>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public Stream ReadJson(string url, string mimeType, string user, string password)
+        {
+            if (mimeType == null)
+            {
+                mimeType = jsonlightMediaType + ";odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8";
+            }
+            
+            HttpWebRequest request = (HttpWebRequest)ReaderUtils.CreateRequest(ResolveUri(url, UriKind.Absolute), user, password);
+            request.Accept = mimeType;
+            WebResponse response = request.GetResponse();
+
+            return response.GetResponseStream();
+        }
+
+        /// <summary>
+        /// Resolves the given url string to a URI
+        /// </summary>
+        /// <param name="url">The given URL string</param>
+        /// <param name="urlKind">URI kind to resolve to</param>
+        /// <returns>The resolved URI</returns>
+        private static string ResolveUri(string url, UriKind uriKind)
+        {
+            Uri resolvedUri = new Uri(url, UriKind.RelativeOrAbsolute);
+            if (!resolvedUri.IsAbsoluteUri)
+            {
+                // If the given URI is relative, then base it on the Referer URI
+                Uri baseUri = new Uri(WebOperationContext.Current.IncomingRequest.Headers["Referer"]);
+                resolvedUri = new Uri(baseUri, resolvedUri);
+                if (uriKind == UriKind.Relative)
+                {
+                    resolvedUri = baseUri.MakeRelativeUri(resolvedUri);
+                }
+            }
+
+            return resolvedUri.ToString();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/ObservableHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/ObservableHttpClient.js b/odatajs/tests/common/ObservableHttpClient.js
new file mode 100644
index 0000000..9be75f8
--- /dev/null
+++ b/odatajs/tests/common/ObservableHttpClient.js
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+// ObservableHttpClient.js
+// This object extends OData's default httpClient by supporting request and response recording sessions, and firing a custom
+// JQuery event for each request/response.
+//
+// The events fired by this object are:
+//      request: Before a request is made
+//      success: Before the primary success handler is called
+//
+// To bind to an event, JQuery event attachers can be used on the object, e.g.
+//      $(observableHttpClient).bind("request", function (request) { ... });
+//
+// To begin a new recording session, use:
+//      var session = observableHttpClient.newSession();
+//
+// Requests and responses are then recorded in session.requests and session.responses. Session can be ended by session.end().
+// Multiple simultaneous sessions are supported.
+
+(function (window, undefined) {
+
+    var ObservableHttpClient = function (provider) {
+        this.provider = provider ? provider : window.odatajs.oData.net.defaultHttpClient;
+    };
+
+    ObservableHttpClient.prototype.newSession = function () {
+        return new Session(this);
+    };
+
+    ObservableHttpClient.prototype.request = function (request, success, error) {
+        var that = this;
+
+        $(this).triggerHandler("request", request);
+        return this.provider.request(request, function (response) {
+            $(that).triggerHandler("success", response);
+            success(response);
+        }, error);
+    };
+
+
+    var Session = function (client) {
+        var that = this;
+
+        this.client = client;
+        this.clear();
+
+        this.requestHandler = function (event, request) { that.requests.push(request); };
+        $(client).bind("request", this.requestHandler);
+
+        this.successHandler = function (event, response) { that.responses.push(response); };
+        $(client).bind("success", this.successHandler);
+    };
+
+    Session.prototype.clear = function () {
+        this.requests = [];
+        this.responses = [];
+    }
+
+    Session.prototype.end = function () {
+        $(this.client).unbind("request", this.requestHandler);
+        $(this.client).unbind("success", this.successHandler);
+    };
+
+    window.ObservableHttpClient = ObservableHttpClient;
+    window.Session = Session;
+
+})(this);
\ No newline at end of file


[04/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-metadata-awareness-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-metadata-awareness-functional-tests.js b/odatajs/tests/odata-metadata-awareness-functional-tests.js
new file mode 100644
index 0000000..a5d2887
--- /dev/null
+++ b/odatajs/tests/odata-metadata-awareness-functional-tests.js
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var service = "./endpoints/EpmDataService.svc";
+    var metadataUri = service + "/$metadata";
+
+    var httpStatusCode = {
+        ok: 200,
+        created: 201,
+        noContent: 204
+    };
+
+    var acceptHeaders = { Accept: "application/json" };
+    var mimeHeaders = { "Content-Type": "application/json", Accept: "application/json" };
+    var keepInContentVariations = [true, false];
+    var feedUris = { "true": service + "/ReplicatedEntries", "false": service + "/MappedEntries" };
+    var typeNames = { "true": "DataJS.Tests.ReplicatedEntry", "false": "DataJS.Tests.MappedEntry" };
+    var selectProperties = ["Published", "Author", "CustomElement", "NestedElement1", "Published,Author,CustomElement,NestedElement1"];
+
+    var newEntry = {
+        UnmappedField: "Unmapped100",
+        Author: {
+            Email: "AuthorEmail100",
+            Name: "AuthorName100",
+            Uri: "http://www.example.com/AuthorUri100",
+            Contributor: {
+                Email: "ContributorEmail100",
+                Name: "ContributorName100",
+                Uri: "http://www.example.com/ContributorUri1000"
+            }
+        },
+        Published: "2100-01-01T00:00:00-08:00",
+        Rights: "Rights100",
+        Summary: "<xmlElement xmlns=\"http://www.example.com/dummy\" attr=\"value100\">Summary100</xmlElement>",
+        Title: "Title<b>100</b>",
+        Updated: "2100-01-01T00:00:00-08:00",
+        CustomElement: "CustomElement100",
+        CustomAttribute: "CustomAttribute100",
+        NestedElement1: "NestedElement1_100",
+        NestedElement2: "NestedElement2_100",
+        CommonAttribute1: "CommonAttribute1_100",
+        CommonAttribute2: "CommonAttribute2_100",
+        Location: {
+            Lat: 1.23,
+            Long: 4.56
+        }
+    };
+
+    var newSpecialValuesEntry = $.extend(true, {}, newEntry, {
+        Author: {
+            Email: null,
+            Name: "",
+            Uri: " ",
+            Contributor: {
+                Email: null,
+                Name: "",
+                Uri: " "
+            }
+        },
+        Rights: null,
+        Summary: "",
+        Title: " ",
+        CustomElement: null,
+        NestedElement1: "",
+        NestedElement2: " ",
+        CustomAttribute: null,
+        CommonAttribute1: "",
+        CommonAttribute2: " "
+    });
+
+    var nullComplexTypeEntry = $.extend(true, {}, newEntry, {
+        Author: { Contributor: null },
+        Location: null
+    });
+
+    var testEntries = [
+        { data: newEntry, description: "entry" },
+        { data: newSpecialValuesEntry, description: "entry containing null and empty string" },
+        { data: nullComplexTypeEntry, description: "entry containing null complex type value" }
+    ];
+
+    var serviceMetadata;
+    var getMetadata = function (callback) {
+        /** Common function for tests to get and cache metadata, to reduce network calls made by tests
+        */
+        if (!serviceMetadata) {
+            odatajs.oData.read(metadataUri, function (metadata) {
+                serviceMetadata = metadata;
+                callback(metadata);
+            }, unexpectedErrorHandler, OData.metadataHandler);
+        }
+        else {
+            callback(serviceMetadata);
+        }
+    }
+
+    module("Functional", {
+        setup: function () {
+            djstest.wait(function (done) {
+                $.post(service + "/ResetData", done);
+            });
+            OData.defaultMetadata = [];
+            OData.jsonHandler.recognizeDates = false;
+        }
+    });
+
+    $.each(selectProperties, function (_, selectProperty) {
+        djstest.addTest(function getSelectPropertiesOnEntry(propertyToSelect) {
+            var entryUri = feedUris["true"] + "(0)?$select=" + propertyToSelect;
+            djstest.assertsExpected(2);
+            getMetadata(function (metadata) {
+                OData.defaultMetadata.push(metadata);
+                odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
+                    djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
+                    ODataReadOracle.readJson(entryUri, function (expectedData) {
+                        djstest.assertWithoutMetadata(data, expectedData, "Verify data");
+                        djstest.done();
+                    })
+                }, unexpectedErrorHandler);
+            }, unexpectedErrorHandler, OData.metadataHandler);
+        }, "GET with mapped properties selecting " + selectProperty + " with keepInContent = true", selectProperty);
+    });
+
+    $.each(keepInContentVariations, function (_, keepInContent) {
+        var feedUri = feedUris[keepInContent];
+
+        $.each(testEntries, function (entryIndex, testEntry) {
+            params = {
+                feedUri: feedUri,
+                testEntry: $.extend(true, {}, testEntry, {
+                    data: {
+                        "__metadata": { type: typeNames[keepInContent] }
+                    }
+                })
+            };
+
+            djstest.addTest(function getMappedEntry(params) {
+                var entryUri = params.feedUri + "(" + entryIndex + ")";
+                djstest.assertsExpected(2);
+                getMetadata(function (metadata) {
+                    OData.defaultMetadata.push(metadata);
+                    odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
+                        ODataReadOracle.readJson(entryUri, function (expectedData) {
+                            djstest.assertWithoutMetadata(data, expectedData, "Verify data");
+                            djstest.done();
+                        })
+                    }, unexpectedErrorHandler);
+                }, unexpectedErrorHandler, OData.metadataHandler);
+            }, "GET " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
+
+            djstest.addTest(function postMappedEntry(params) {
+                var postEntry = $.extend(true, {}, params.testEntry.data, { ID: 100 });
+                djstest.assertsExpected(2);
+                getMetadata(function (metadata) {
+                    odatajs.oData.request({ requestUri: params.feedUri, method: "POST", headers: djstest.clone(mimeHeaders), data: postEntry }, function (data, response) {
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code");
+                        ODataReadOracle.readJson(feedUri + "(" + postEntry.ID + ")", function (actualData) {
+                            djstest.assertWithoutMetadata(actualData, postEntry, "Verify new entry data against server");
+                            djstest.done();
+                        })
+                    }, unexpectedErrorHandler, undefined, undefined, metadata);
+                }, unexpectedErrorHandler, OData.metadataHandler);
+            }, "POST " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
+
+            djstest.addTest(function putMappedEntry(params) {
+                var entryUri = params.feedUri + "(0)";
+                djstest.assertsExpected(2);
+                getMetadata(function (metadata) {
+                    OData.defaultMetadata.push(metadata);
+                    odatajs.oData.request({ requestUri: entryUri, method: "PUT", headers: djstest.clone(mimeHeaders), data: params.testEntry.data }, function (data, response) {
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                        ODataReadOracle.readJson(entryUri, function (actualData) {
+                            djstest.assertWithoutMetadata(actualData, $.extend({ ID: 0 }, params.testEntry.data), "Verify updated entry data against server");
+                            djstest.done();
+                        })
+                    }, unexpectedErrorHandler);
+                }, unexpectedErrorHandler, OData.metadataHandler);
+            }, "PUT " + params.testEntry.description + " with mapped properties: keepInContent = " + keepInContent, params);
+        });
+    });
+
+    var descriptions = ["base type", "derived type"];
+    $.each(descriptions, function (index, _) {
+        djstest.addTest(function getHierarchicalEntry(index) {
+            var entryUri = service + "/HierarchicalEntries(" + index + ")";
+            djstest.assertsExpected(2);
+            getMetadata(function (metadata) {
+                odatajs.oData.read({ requestUri: entryUri, headers: acceptHeaders }, function (data, response) {
+                    djstest.assertAreEqual(response.statusCode, httpStatusCode.ok, "Verify response code");
+                    ODataReadOracle.readJson(entryUri, function (expectedData) {
+                        djstest.assertWithoutMetadata(data, expectedData, "Verify data");
+                        djstest.done();
+                    })
+                }, unexpectedErrorHandler, undefined, undefined, metadata);
+            }, unexpectedErrorHandler, OData.metadataHandler);
+        }, "GET " + descriptions[index] + " with mapped properties: keepInContent = false", index);
+    });
+
+    $.each([false, true], function (_, recognizeDates) {
+        djstest.addTest(function readDateTimeWithMetadataTest(params) {
+            var foodStoreDataService = "./endpoints/FoodStoreDataServiceV4.svc";
+            var specialDaysEndpoint = foodStoreDataService + "/SpecialDays";
+
+            djstest.assertsExpected(1);
+            OData.jsonHandler.recognizeDates = params.recognizeDates;
+            odatajs.oData.read(foodStoreDataService + "/$metadata", function (metadata) {
+                odatajs.oData.read({ requestUri: specialDaysEndpoint, headers: { Accept: params.accept} }, function (data, response) {
+                    // Because our oracle isn't metadata aware, it is not 100% correct, so we will pass in recognizeDates = true
+                    // in all cases and manually fix up the property that was incorrectly converted
+                    window.ODataReadOracle.readFeed(specialDaysEndpoint, function (expectedData) {
+                        // Fix up the string property that has a "date-like" string deliberately injected
+                        expectedData.results[2].Name = "/Date(" + expectedData.results[2].Name.valueOf() + ")/";
+                        djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                        djstest.done();
+                    }, params.accept, true);
+                }, unexpectedErrorHandler, undefined, undefined, metadata);
+            }, unexpectedErrorHandler, OData.metadataHandler);
+        }, "GET metadata-aware JSON dates with recognizeDates=" + recognizeDates, { recognizeDates: recognizeDates, accept: "application/json;odata.metadata=minimal" });
+    });
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-metadata-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-metadata-tests.js b/odatajs/tests/odata-metadata-tests.js
new file mode 100644
index 0000000..525dd62
--- /dev/null
+++ b/odatajs/tests/odata-metadata-tests.js
@@ -0,0 +1,499 @@
+/*
+ * 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-metadata-tests.js
+
+(function (window, undefined) {
+    djstest.addTest(function testMetadataHandler() {
+        // Test cases as result / model tuples.
+        var cases = [
+            { i: {}, e: undefined },
+            { i: { headers: { "Content-Type": "application/xml" }, body: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" />' },
+                e: { version: "4.0" }
+            }
+        ];
+
+        var i, len;
+        for (i = 0, len = cases.length; i < len; i++) {
+            var response = cases[i].i;
+            var testClient = { request: function (r, success, error) { success(response); } };
+            window.odatajs.oData.read("foo", function (data) {
+                djstest.assertAreEqualDeep(data, cases[i].e, "handler result matches target");
+            }, function (err) {
+                djstest.fail(err.message);
+            }, window.odatajs.oData.metadataHandler, testClient);
+        }
+
+        djstest.done();
+    });
+
+    // DATAJS INTERNAL START
+    djstest.addTest(function testScriptCase() {
+        // Test cases as input/result pairs.
+        var cases = [
+            { i: null, e: null },
+            { i: "", e: "" },
+            { i: "a", e: "a" },
+            { i: "A", e: "a" },
+            { i: "TestCase", e: "testCase" },
+            { i: "123abc", e: "123abc" },
+            { i: "ITEM", e: "ITEM" }
+        ];
+
+        var i, len;
+        for (i = 0, len = cases.length; i < len; i++) {
+            djstest.assertAreEqual(window.odatajs.oData.metadata.scriptCase(cases[i].i), cases[i].e, "processed input matches expected value");
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function testGetChildSchema() {
+        // Test cases as input parent / input element / result tuples.
+        var schema = window.odatajs.oData.metadata.schema;
+        var cases = [
+            { ip: schema.elements.EntityType, ie: "Property", e: { isArray: true, propertyName: "property"} },
+            { ip: schema.elements.EntityType, ie: "Key", e: { isArray: true, propertyName: "key"} },
+            { ip: schema.elements.EntitySet, ie: "SomethingElse", e: null },
+            { ip: schema.elements.Property, ie: "Name", e: null} // this is an attribute, not an element, thus it's no found
+        ];
+
+        var i, len;
+        for (i = 0, len = cases.length; i < len; i++) {
+            var result = window.odatajs.oData.metadata.getChildSchema(cases[i].ip, cases[i].ie);
+            djstest.assertAreEqualDeep(result, cases[i].e, "getChildSchema matches target");
+        }
+
+        djstest.done();
+    });
+
+    var testFullCsdl = '' +
+        '<?xml version="1.0" encoding="utf-8"?>\r\n' +
+        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">\r\n' +
+        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
+        '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="TestCatalog.Model">\r\n' +
+        '      <EntityType Name="Genre">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
+        '        <NavigationProperty Name="Titles" Type="Collection(TestCatalog.Model.Title)" Partner="Series" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Language">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" />\r\n' +
+        '        <NavigationProperty Name="Titles" Type="Collection(TestCatalog.Model.Title)" Partner="Languages" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Person">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.Int32" Nullable="false" />\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="true" />\r\n' +
+        '        <NavigationProperty Name="Awards" Type="Collection(TestCatalog.Model.TitleAward)" Partner="Person"/>\r\n' +
+        '        <NavigationProperty Name="TitlesActedIn" Type="Collection(TestCatalog.Model.Title)" Partner="Cast"/>\r\n' +
+        '        <NavigationProperty Name="TitlesDirected" Type="Collection(TestCatalog.Model.Title)" Partner="Directors"/>\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="TitleAudioFormat">\r\n' +
+        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Language" /><PropertyRef Name="Format" /></Key>\r\n' +
+        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
+        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" />\r\n' +
+        '        <Property Name="Language" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="AudioFormats" >\r\n' +
+        '            <ReferentialConstraint Property="TitleId" ReferencedProperty="Id" />' +
+        '        </NavigationProperty>' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="TitleAward">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.Guid" Nullable="false" />\r\n' +
+        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" />\r\n' +
+        '        <Property Name="Category" Type="Edm.String" Nullable="false" MaxLength="60" Unicode="false" />\r\n' +
+        '        <Property Name="Year" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Won" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="Awards"/>\r\n' +
+        '        <NavigationProperty Name="Person" Type="TestCatalog.Model.Person" Partner="Awards"/>\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Title" HasStream="true">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
+        '        <Property Name="Synopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" />\r\n' +
+        '        <Property Name="ShortSynopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" />\r\n' +
+        '        <Property Name="AverageRating" Type="Edm.Double" Nullable="true" />\r\n' +
+        '        <Property Name="ReleaseYear" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Url" Type="Edm.String" Nullable="true" MaxLength="200" Unicode="false" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
+        '        <Property Name="DateModified" Type="Edm.DateTime" Nullable="false" />\r\n' +
+        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="8" Unicode="false" />\r\n' +
+        '        <Property Name="BoxArt" Type="TestCatalog.Model.BoxArt" Nullable="false" />\r\n' +
+        '        <Property Name="ShortName" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" />\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" />\r\n' +
+        '        <Property Name="Instant" Type="TestCatalog.Model.InstantAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="Dvd" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="BluRay" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="TinyUrl" Type="Edm.String" Nullable="false" />\r\n' +
+        '        <Property Name="WebsiteUrl" Type="Edm.String" Nullable="true" />\r\n' +
+        '        <Property Name="TestApiId" Type="Edm.String" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="AudioFormats" Type="Collection(TestCatalog.Model.TitleAudioFormat)" Partner="Title" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Awards" Type="Collection(TestCatalog.Model.TitleAward)" Partner="Title" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Disc" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
+        '        <NavigationProperty Name="Movie" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
+        '        <NavigationProperty Name="Season" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
+        '        <NavigationProperty Name="Series" Type="Collection(TestCatalog.Model.Title)" />\r\n' +
+        '        <NavigationProperty Name="ScreenFormats" Type="Collection(TestCatalog.Model.TitleScreenFormat)" Partner="Title" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Cast" Type="Collection(TestCatalog.Model.Person)" Partner="TitlesActedIn" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Languages" Type="Collection(TestCatalog.Model.Language)" Partner="Titles" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Directors" Type="Collection(TestCatalog.Model.Person)" Partner="TitlesDirected" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Genres" Type="Collection(TestCatalog.Model.Genre)" Partner="Titles" Nullable="false" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <ComplexType Name="BoxArt">\r\n' +
+        '        <Property Name="SmallUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
+        '        <Property Name="MediumUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
+        '        <Property Name="LargeUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
+        '        <Property Name="HighDefinitionUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <ComplexType Name="InstantAvailability">\r\n' +
+        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="HighDefinitionAvailable" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <ComplexType Name="DeliveryFormatAvailability">\r\n' +
+        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <EntityType Name="TitleScreenFormat">\r\n' +
+        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Format" /></Key>\r\n' +
+        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
+        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" />\r\n' +
+        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Type="TestCatalog.Model.Title" Partner="ScreenFormats" >\r\n' +
+        '            <ReferentialConstraint Property="TitleId" ReferencedProperty="Id" />' +
+        '        </NavigationProperty>' +
+        '      </EntityType>\r\n' +
+        '      <Function Name="ProductsByRating">' +
+        '        <ReturnType Type="Collection(TestCatalog.Model.Title)" />\r\n' +
+        '      </Function>\r\n' +
+        '    </Schema>\r\n' +
+        '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Test.Catalog">\r\n' +
+        '      <EntityContainer Name="TestCatalog" >\r\n' +
+        '        <FunctionImport Name="Movies" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
+        '        <FunctionImport Name="Series" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
+        '        <FunctionImport Name="Seasons" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
+        '        <FunctionImport Name="Discs" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
+        '        <FunctionImport Name="Episodes" EntitySet="Titles" Function="estCatalog.Model.GetTitles" />\r\n' +
+        '        <EntitySet Name="Genres" EntityType="TestCatalog.Model.Genre" >\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Titles" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '        <EntitySet Name="Languages" EntityType="TestCatalog.Model.Language" >\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Languages" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '        <EntitySet Name="People" EntityType="TestCatalog.Model.Person" >\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Cast" />\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Directors" />\r\n' +
+        '        </EntitySet>' +
+        '        <EntitySet Name="TitleAudioFormats" EntityType="TestCatalog.Model.TitleAudioFormat" >\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="AudioFormats" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '        <EntitySet Name="TitleAwards" EntityType="TestCatalog.Model.TitleAward" >\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Awards" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '        <EntitySet Name="Titles" EntityType="TestCatalog.Model.Title" >\r\n' +
+        '            <NavigationPropertyBinding Target="TitleAudioFormats" Path="Title" />\r\n' +
+        '            <NavigationPropertyBinding Target="TitleAwards" Path="Title" />\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Disc" />\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Movie" />\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Season" />\r\n' +
+        '            <NavigationPropertyBinding Target="Titles" Path="Series" />\r\n' +
+        '            <NavigationPropertyBinding Target="TitleScreenFormats" Path="ScreenFormats" />\r\n' +
+        '            <NavigationPropertyBinding Target="People" Path="TitlesActedIn" />\r\n' +
+        '            <NavigationPropertyBinding Target="Languages" Path="Titles" />\r\n' +
+        '            <NavigationPropertyBinding Target="People" Path="TitlesDirected" />\r\n' +
+        '            <NavigationPropertyBinding Target="Genres" Path="Genres" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '        <EntitySet Name="TitleScreenFormats" EntityType="TestCatalog.Model.TitleScreenFormat" >\r\n' +
+        '            <NavigationPropertyBinding Target="TitleScreenFormats" Path="Title" />\r\n' +
+        '        </EntitySet>\r\n' +
+        '      </EntityContainer>\r\n' +
+        '    </Schema>\r\n' +
+        '  </edmx:DataServices>\r\n' +
+        '</edmx:Edmx>\r\n' +
+        '';
+
+    var testFullMetadataResult = {
+        "version": "4.0",
+        "dataServices": {
+            "dataServiceVersion": "4.0",
+            "maxDataServiceVersion": "4.0",
+            "schema": [{
+                "namespace": "TestCatalog.Model",
+                "entityType": [{
+                    "name": "Genre",
+                    "key": [{ "propertyRef": [{ "name": "Name"}] }],
+                    "property": [{ "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "50", "unicode": "false"}],
+                    "navigationProperty": [{ "name": "Titles", "partner": "Series", "type": "Collection(TestCatalog.Model.Title)"}]
+                }, {
+                    "name": "Language",
+                    "key": [{ "propertyRef": [{ "name": "Name"}] }],
+                    "property": [{ "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "80", "unicode": "false"}],
+                    "navigationProperty": [{ "name": "Titles", "partner": "Languages", "type": "Collection(TestCatalog.Model.Title)"}]
+                }, {
+                    "name": "Person",
+                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
+                    "property": [
+                        { "name": "Id", "type": "Edm.Int32", "nullable": "false" },
+                        { "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "80", "unicode": "true" }
+                    ],
+                    "navigationProperty": [
+                        { "name": "Awards", "partner": "Person", "type": "Collection(TestCatalog.Model.TitleAward)" },
+                        { "name": "TitlesActedIn", "partner": "Cast", "type": "Collection(TestCatalog.Model.Title)" },
+                        { "name": "TitlesDirected", "partner": "Directors", "type": "Collection(TestCatalog.Model.Title)" }
+                    ]
+                }, {
+                    "name": "TitleAudioFormat",
+                    "key": [{ "propertyRef": [{ "name": "TitleId" }, { "name": "DeliveryFormat" }, { "name": "Language" }, { "name": "Format"}] }],
+                    "property": [
+                        { "name": "TitleId", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
+                        { "name": "DeliveryFormat", "type": "Edm.String", "nullable": "false", "maxLength": "10", "unicode": "false" },
+                        { "name": "Language", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" },
+                        { "name": "Format", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" }
+                    ],
+                    "navigationProperty": [{ "name": "Title", "partner": "AudioFormats", "referentialConstraint": [{"property": "TitleId", "referencedProperty": "Id"}], "type": "TestCatalog.Model.Title" }]
+                }, {
+                    "name": "TitleAward",
+                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
+                    "property": [
+                        { "name": "Id", "type": "Edm.Guid", "nullable": "false" },
+                        { "name": "Type", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" },
+                        { "name": "Category", "type": "Edm.String", "nullable": "false", "maxLength": "60", "unicode": "false" },
+                        { "name": "Year", "type": "Edm.Int32", "nullable": "true" }, { "name": "Won", "type": "Edm.Boolean", "nullable": "false" }
+                    ],
+                    "navigationProperty": [
+                        { "name": "Title", "partner": "Awards", "type": "TestCatalog.Model.Title" },
+                        { "name": "Person", "partner": "Awards", "type": "TestCatalog.Model.Person" }
+                    ]
+                }, {
+                    "name": "Title",
+                    "hasStream": "true",
+                    "key": [{ "propertyRef": [{ "name": "Id"}] }],
+                    "property": [
+                        { "name": "Id", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
+                        { "name": "Synopsis", "type": "Edm.String", "nullable": "true", "maxLength": "Max", "unicode": "false" },
+                        { "name": "ShortSynopsis", "type": "Edm.String", "nullable": "true", "maxLength": "Max", "unicode": "false" },
+                        { "name": "AverageRating", "type": "Edm.Double", "nullable": "true" }, { "name": "ReleaseYear", "type": "Edm.Int32", "nullable": "true" },
+                        { "name": "Url", "type": "Edm.String", "nullable": "true", "maxLength": "200", "unicode": "false" },
+                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
+                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" },
+                        { "name": "DateModified", "type": "Edm.DateTime", "nullable": "false"},
+                        { "name": "Type", "type": "Edm.String", "nullable": "false", "maxLength": "8", "unicode": "false" },
+                        { "name": "BoxArt", "type": "TestCatalog.Model.BoxArt", "nullable": "false" },
+                        { "name": "ShortName", "type": "Edm.String", "nullable": "false", "maxLength": "200", "unicode": "false" },
+                        { "name": "Name", "type": "Edm.String", "nullable": "false", "maxLength": "200", "unicode": "false" },
+                        { "name": "Instant", "type": "TestCatalog.Model.InstantAvailability", "nullable": "false" },
+                        { "name": "Dvd", "type": "TestCatalog.Model.DeliveryFormatAvailability", "nullable": "false" },
+                        { "name": "BluRay", "type": "TestCatalog.Model.DeliveryFormatAvailability", "nullable": "false" },
+                        { "name": "TinyUrl", "type": "Edm.String", "nullable": "false" },
+                        { "name": "WebsiteUrl", "type": "Edm.String", "nullable": "true" },
+                        { "name": "TestApiId", "type": "Edm.String", "nullable": "false" }
+                    ],
+                    "navigationProperty": [
+                        { "name": "AudioFormats", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleAudioFormat)" },
+                        { "name": "Awards", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleAward)" },
+                        { "name": "Disc", "type": "Collection(TestCatalog.Model.Title)" },
+                        { "name": "Movie", "type": "Collection(TestCatalog.Model.Title)" },
+                        { "name": "Season", "type": "Collection(TestCatalog.Model.Title)" },
+                        { "name": "Series", "type": "Collection(TestCatalog.Model.Title)" },
+                        { "name": "ScreenFormats", "nullable": "false", "partner": "Title", "type": "Collection(TestCatalog.Model.TitleScreenFormat)" },
+                        { "name": "Cast", "nullable": "false", "partner": "TitlesActedIn", "type": "Collection(TestCatalog.Model.Person)" },
+                        { "name": "Languages", "nullable": "false", "partner": "Titles", "type": "Collection(TestCatalog.Model.Language)" },
+                        { "name": "Directors", "nullable": "false", "partner": "TitlesDirected", "type": "Collection(TestCatalog.Model.Person)" },
+                        { "name": "Genres", "nullable": "false", "partner": "Titles", "type": "Collection(TestCatalog.Model.Genre)" }
+                    ]
+                }, {
+                    "name": "TitleScreenFormat",
+                    "key": [{ "propertyRef": [{ "name": "TitleId" }, { "name": "DeliveryFormat" }, { "name": "Format"}]}],
+                    "property": [
+                        { "name": "TitleId", "type": "Edm.String", "nullable": "false", "maxLength": "30" },
+                        { "name": "DeliveryFormat", "type": "Edm.String", "nullable": "false", "maxLength": "10", "unicode": "false" },
+                        { "name": "Format", "type": "Edm.String", "nullable": "false", "maxLength": "30", "unicode": "false" }
+                    ],
+                    "navigationProperty": [{ "name": "Title", "partner": "ScreenFormats", "referentialConstraint": [{"property": "TitleId", "referencedProperty": "Id"}], "type": "TestCatalog.Model.Title" }]
+                }],
+                "complexType": [{
+                    "name": "BoxArt",
+                    "property": [
+                        { "name": "SmallUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
+                        { "name": "MediumUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
+                        { "name": "LargeUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" },
+                        { "name": "HighDefinitionUrl", "type": "Edm.String", "nullable": "true", "maxLength": "80", "unicode": "false" }
+                    ]
+                }, {
+                    "name": "InstantAvailability",
+                    "property": [
+                        { "name": "Available", "type": "Edm.Boolean", "nullable": "false" },
+                        { "name": "AvailableFrom", "type": "Edm.DateTime", "nullable": "true" },
+                        { "name": "AvailableTo", "type": "Edm.DateTime", "nullable": "true" },
+                        { "name": "HighDefinitionAvailable", "type": "Edm.Boolean", "nullable": "false" },
+                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
+                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" }
+                    ]
+                }, {
+                    "name": "DeliveryFormatAvailability",
+                    "property": [
+                        { "name": "Available", "type": "Edm.Boolean", "nullable": "false" },
+                        { "name": "AvailableFrom", "type": "Edm.DateTime", "nullable": "true" },
+                        { "name": "AvailableTo", "type": "Edm.DateTime", "nullable": "true" },
+                        { "name": "Runtime", "type": "Edm.Int32", "nullable": "true" },
+                        { "name": "Rating", "type": "Edm.String", "nullable": "true", "maxLength": "10", "unicode": "false" }
+                    ]
+                }],
+                "function": [
+                {
+                   "name": "ProductsByRating",
+                   "returnType": {"type": "Collection(TestCatalog.Model.Title)" }
+                }]
+            }, {
+                "namespace": "Test.Catalog",
+                "entityContainer": {
+                    "name": "TestCatalog",
+                    "functionImport": [
+                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Movies"},
+                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Series"},
+                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Seasons" },
+                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Discs" },
+                        { "entitySet": "Titles", "function": "estCatalog.Model.GetTitles", "name": "Episodes" }
+                    ], "entitySet": [
+                        { "name": "Genres", "entityType": "TestCatalog.Model.Genre", "navigationPropertyBinding": [{"path": "Titles", "target": "Titles"}] },
+                        { "name": "Languages", "entityType": "TestCatalog.Model.Language", "navigationPropertyBinding": [{ "path": "Languages", "target": "Titles"}] },
+                        { "name": "People", "entityType": "TestCatalog.Model.Person", "navigationPropertyBinding": [{ "path": "Cast", "target": "Titles" }, { "path": "Directors", "target": "Titles"}] },
+                        { "name": "TitleAudioFormats", "entityType": "TestCatalog.Model.TitleAudioFormat", "navigationPropertyBinding": [{ "path": "AudioFormats", "target": "Titles"}] },
+                        { "name": "TitleAwards", "entityType": "TestCatalog.Model.TitleAward", "navigationPropertyBinding": [{ "path": "Awards", "target": "Titles"}] },
+                        { "name": "Titles", "entityType": "TestCatalog.Model.Title", "navigationPropertyBinding": [{ "path": "Title", "target": "TitleAudioFormats" }, { "path": "Title", "target": "TitleAwards" }, { "path": "Disc", "target": "Titles" }, { "path": "Movie", "target": "Titles" }, { "path": "Season", "target": "Titles" }, { "path": "Series", "target": "Titles" }, { "path": "ScreenFormats", "target": "TitleScreenFormats" }, { "path": "TitlesActedIn", "target": "People" }, { "path": "Titles", "target": "Languages" }, { "path": "TitlesDirected", "target": "People" }, { "path": "Genres", "target": "Genres"}] },
+                        { "name": "TitleScreenFormats", "entityType": "TestCatalog.Model.TitleScreenFormat", "navigationPropertyBinding": [{ "path": "Title", "target": "TitleScreenFormats"}] }
+                    ]
+                }
+            }]
+        }
+    };
+
+    var testCsdlV4 = '' +
+    '<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">\r\n' +
+    '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
+    '    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="TestCatalog.Model"/>\r\n' +
+    '  </edmx:DataServices>\r\n' +
+    '</edmx:Edmx>';
+
+    var testMetadataV4 = {
+        "version": "4.0",
+        "dataServices": {
+            "maxDataServiceVersion": "4.0",
+            "dataServiceVersion": "4.0",
+            "schema": [{
+                "namespace": "TestCatalog.Model"
+            }]
+        }
+    };
+
+    djstest.addTest(function testParseConceptualModelElement() {
+        // Test cases as input XML text / result tuples.
+        var cases = [
+            { i: "<foo />", e: null },
+            { i: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" />', e: { version: "4.0"} },
+            { i: '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx-invalid" />', e: null },
+            { i: testCsdlV4, e: testMetadataV4 },
+            { i: testFullCsdl, e: testFullMetadataResult }
+        ];
+
+        var i, len;
+        for (i = 0, len = cases.length; i < len; i++) {
+            var doc = window.odatajs.xml.xmlParse(cases[i].i);
+            var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
+            djstest.assertAreEqualDeep(schema, cases[i].e, "parseConceptualModelElement result matches target");
+        }
+
+        djstest.done();
+    });
+
+    djstest.addTest(function metadataVocabularyTest() {
+        var testCsdl = '' +
+        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
+        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" >\r\n' +
+        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
+        '    <Schema Namespace="TestCatalog.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">\r\n' +
+        '          <Term Name="Rating" Type="Edm.Int32" />\r\n' +
+        '          <Term Name="CanEdit" Type="Edm.String" />\r\n' +
+        '      <EntityType Name="Genre">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
+        '      </EntityType></Schema></edmx:DataServices></edmx:Edmx>';
+
+
+        var doc = window.odatajs.xml.xmlParse(testCsdl);
+        var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
+
+        djstest.assertAreEqual(schema.dataServices.schema[0].term.length, 2, "schema.DataServices.Schema.Term.length === 2");
+        djstest.assertAreEqual(schema.dataServices.schema[0].term[0].name, "Rating", "schema.DataServices.Schema.Term[0].name === 'Rating'");
+        djstest.assertAreEqual(schema.dataServices.schema[0].term[1].name, "CanEdit", "schema.DataServices.Schema.Term[1].name === 'CanEdit'");
+        djstest.done();
+    });
+
+    djstest.addTest(function metadataAnnotationTest() {
+        var testCsdl = '' +
+        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
+        '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" >\r\n' +
+        '  <edmx:DataServices xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:MaxDataServiceVersion="4.0" m:DataServiceVersion="4.0">\r\n' +
+        '    <Schema Namespace="TestCatalog.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm">\r\n' +
+        '      <EntityType Name="Genre">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Language">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" />\r\n' +
+        '        <Property Name="Id" Type="Edm.Int32" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <Annotations Target="TestCatalog.Model.Genre/Name">\r\n' +
+        '        <Annotation String="Genre Name" Term="Org.OData.Display.V1.DisplayName"/>\r\n' +
+        '      </Annotations>\r\n' +
+        '      <Annotations Target="TestCatalog.Model.Language/Name">\r\n' +
+        '        <Annotation String="Language Name" Term="Org.OData.Display.V1.DisplayName"/>\r\n' +
+        '        <Annotation String="Language Name 2" Term="Org.OData.Display.V1.DisplayName 2"/>\r\n' +
+        '      </Annotations>\r\n' +
+        '    </Schema></edmx:DataServices></edmx:Edmx>';
+
+
+        var doc = window.odatajs.xml.xmlParse(testCsdl);
+        var schema = window.odatajs.oData.metadata.parseConceptualModelElement(doc.documentElement);
+
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations.length, 2, "Annotations number");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation.length, 1, "Annotation number");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation[0].string, "Genre Name", "Annotation name");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[0].annotation[0].term, "Org.OData.Display.V1.DisplayName", "Annotation term");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation.length, 2, "Annotation number");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[0].string, "Language Name", "Annotation name");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[0].term, "Org.OData.Display.V1.DisplayName", "Annotation term");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[1].string, "Language Name 2", "Annotation name");
+        djstest.assertAreEqual(schema.dataServices.schema[0].annotations[1].annotation[1].term, "Org.OData.Display.V1.DisplayName 2", "Annotation term");
+        djstest.done();
+    });
+
+    // DATAJS INTERNAL END
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-net-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-net-tests.js b/odatajs/tests/odata-net-tests.js
new file mode 100644
index 0000000..351b197
--- /dev/null
+++ b/odatajs/tests/odata-net-tests.js
@@ -0,0 +1,301 @@
+/*
+ * 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-net-tests.js
+(function (window, undefined) {
+    module("Unit");
+    djstest.addTest(function httpClientSendRequestTest() {
+        var tests = [
+            { url: "http://localhost/test1", response: { headers: {}, status: 200, body: "test"} },
+            { url: "http://localhost/test2", response: { headers: {}, status: 204, body: "test"} },
+            { url: "http://localhost/test3", response: { headers: {}, status: 299, body: "test"} },
+            { url: "http://localhost/test4", response: { headers: {}, status: 500, body: "error"} }
+        ];
+
+        djstest.assertsExpected(12);
+
+        var sentCount = 0;
+        MockXMLHttpRequest.onAfterSend = function () {
+            sentCount++;
+        };
+
+        var oldXmlHttpRequest = window.XMLHttpRequest;
+        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+        try {
+            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
+            var i, len;
+            for (i = 0, len = tests.length; i < len; i++) {
+                MockXMLHttpRequest.addResponse(tests[i].url, tests[i].response);
+
+                window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
+                //Need a closure to capture the current test being executed. 
+                (function (test) {
+                    window.odatajs.oData.net.defaultHttpClient.request(
+                    { requestUri: test.url, headers: {} },
+                    function (response) {
+                        djstest.assert(response.statusCode >= 200 & response.statusCode <= 299, "response status is in the success range");
+                        djstest.assertAreEqual(response.body, test.response.body, "response body is the expected one");
+                        djstest.assertAreEqualDeep(response.headers, [], "response headers are the expected ones");
+                    },
+                    function (error) {
+                        djstest.assert(error.response.statusCode > 299, "response status is in the error range");
+                        djstest.assertAreEqual(error.response.body, test.response.body, "response body is the expected one");
+                        djstest.assertAreEqualDeep(error.response.headers, [], "response headers are the expected ones");
+                    });
+                })(tests[i]);
+            }
+        }
+        finally {
+            //Cleanup and finish the test after all requests have been sent and processed. Poll every 50 ms
+            var timer = setInterval(function () {
+                if (sentCount === tests.length) {
+                    clearInterval(timer)
+                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+                    window.XMLHttpRequest = oldXmlHttpRequest;
+                    MockXMLHttpRequest.reset();
+                    djstest.done();
+                }
+            }, 50);
+        }
+    });
+
+    djstest.addTest(function httpClientRequestTimeoutTest() {
+        var oldXmlHttpRequest = window.XMLHttpRequest;
+        var testDone = false;
+
+        djstest.assertsExpected(1);
+
+        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+        try {
+            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
+
+            window.odatajs.oData.net.defaultHttpClient.request(
+               { requestUri: "http://test1", timeoutMS: 10, headers: { MockTimeOut: true} },
+               function (response) {
+                   djstest.fail("success method was hit when not expected");
+                   testDone = true;
+               },
+               function (error) {
+                   djstest.assertAreEqual(error.message, "Request timed out", "error method executes and error is the expected one");
+                   testDone = true;
+               });
+        }
+        finally {
+            //Cleanup and finish the test after all requests have been sent and processed. Poll every 50 ms
+            var timer = setInterval(function () {
+                if (testDone) {
+                    clearInterval(timer);
+                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+                    window.XMLHttpRequest = oldXmlHttpRequest;
+                    MockXMLHttpRequest.reset();
+                    djstest.done();
+                }
+            }, 50);
+        }
+    });
+
+    djstest.addTest(function httpClientRequestAbortTest() {
+
+        var oldXmlHttpRequest = window.XMLHttpRequest;
+
+        djstest.assertsExpected(1);
+
+        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+        try {
+            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
+
+            var result = window.odatajs.oData.net.defaultHttpClient.request(
+               { requestUri: "http://test1", headers: { MockNoOp: true} },
+               function (response) {
+                   djstest.fail("success method was hit when not expected");
+               },
+               function (error) {
+                   djstest.assertAreEqual(error.message, "Request aborted", "error method executes and error is the expected one");
+               });
+
+            result.abort();
+        }
+        finally {
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+            window.XMLHttpRequest = oldXmlHttpRequest;
+            MockXMLHttpRequest.reset();
+            djstest.done();
+        }
+    });
+
+    djstest.addTest(function httpClientRequestAbortOnCompletedRequestTest() {
+
+        var oldXmlHttpRequest = window.XMLHttpRequest;
+        var testDone = false;
+
+        djstest.assertsExpected(1);
+
+        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+        try {
+            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
+
+            MockXMLHttpRequest.addResponse("http://test1", { headers: {}, status: 200, body: "test body" });
+
+            MockXMLHttpRequest.onAfterSend = function () {
+                result.abort();
+                testDone = true;
+            };
+
+            result = window.odatajs.oData.net.defaultHttpClient.request(
+               { requestUri: "http://test1", headers: {} },
+               function (response) {
+                   djstest.pass("success method was hit");
+               },
+               function (error) {
+                   djstest.fail("success method was hit when not expected - [" + error.message + "]");
+               });
+        }
+        finally {
+            // Cleanup after test is done, poll eavery 50ms
+            var timer = setInterval(function () {
+                if (testDone) {
+                    clearInterval(timer);
+                    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+                    window.XMLHttpRequest = oldXmlHttpRequest;
+                    MockXMLHttpRequest.reset();
+                    djstest.done();
+                }
+            }, 50);
+        }
+    });
+
+    djstest.addTest(function httpClientRequestSendsRequestCorrectlyTest() {
+        var tests = [
+            {
+                request: { requestUri: "http://test1", headers: {}, body: "test" },
+                expected: { headers: {}, url: "http://test1", method: "GET", body: "test", async: true, user: undefined, password: undefined }
+            },
+            {
+                request: { requestUri: "http://test2", headers: {}, method: "POST", body: "test" },
+                expected: { headers: {}, url: "http://test2", method: "POST", body: "test", async: true, user: undefined, password: undefined }
+            },
+            {
+                request: { requestUri: "http://test3", headers: { header1: "value1", header2: "value2" }, body: "test" },
+                expected: { headers: { header1: "value1", header2: "value2" }, url: "http://test3", method: "GET", body: "test", async: true, user: undefined, password: undefined }
+            }
+        ];
+
+        var oldXmlHttpRequest = window.XMLHttpRequest;
+        var oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+        try {
+            window.XMLHttpRequest = MockXMLHttpRequest.XMLHttpRequest;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = false;
+            var i, len;
+
+            for (i = 0, len = tests.length; i < len; i++) {
+
+                MockXMLHttpRequest.addRequestVerifier(tests[i].request.requestUri, function (request) {
+                    djstest.assertAreEqualDeep(request, tests[i].expected, "request matches target");
+                });
+
+                window.odatajs.oData.net.defaultHttpClient.request(
+                    tests[i].request,
+                    function (response) { });
+            }
+        }
+        finally {
+            // Restore original values.
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+            window.XMLHttpRequest = oldXmlHttpRequest;
+        }
+        djstest.done();
+    });
+
+    // DATAJS INTERNAL START
+    djstest.addTest(function canUseJSONPTest() {
+        var tests = [
+            { pass: true, input: {} },
+            { pass: true, input: { method: "GET"} },
+            { pass: false, input: { method: "PUT"} },
+            { pass: false, input: { method: "get"} },
+            { pass: true, input: { accept: "*/*"} },
+            { pass: true, input: { accept: "application/json"} },
+            { pass: true, input: { accept: "text/javascript"} },
+            { pass: true, input: { accept: "application/javascript"} },
+            { pass: true, input: { accept: "application/xml"} },
+            { pass: true, input: { headers: { Accept: "application/xml"}} }
+        ];
+        for (var i = 0; i < tests.length; i++) {
+            var actual = window.odatajs.oData.net.canUseJSONP(tests[i].input);
+            djstest.assert(actual === tests[i].pass, "test " + i + " didn't actually match pass (" + tests[i].pass + ")");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function isAbsoluteUrlTest() {
+        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("http://something/"));
+        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("http://malformed url/"));
+        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("https://localhost/"));
+        djstest.assert(window.odatajs.oData.net.isAbsoluteUrl("file://another-protocol/"));
+        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("/path"));
+        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("?query-string"));
+        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl(""));
+        djstest.assert(!window.odatajs.oData.net.isAbsoluteUrl("mailto:someone"));
+        djstest.done();
+    });
+
+    djstest.addTest(function isLocalUrlTest() {
+        var thisUrl = window.location.href;
+        var localUrls = [
+            "", ".", "/howdy.htm", "  ", "?queryparam",
+            thisUrl, thisUrl + "/foo", thisUrl + "?something-else"
+        ];
+        var remoteUrls = [
+            "http://www.microsoft.com/",
+            "https://www.microsoft.com/",
+            "https://" + window.location.host,
+            "https://" + window.location.hostname,
+        // 21 is FTP, so the test shouldn't collide
+            "http://" + window.location.hostname + ":21"
+        ];
+        var i, len;
+        for (i = 0, len = localUrls.length; i < len; i++) {
+            djstest.assert(window.odatajs.oData.net.isLocalUrl(localUrls[i]), "is local: [" + localUrls[i] + "]");
+        }
+        for (i = 0, len = remoteUrls.length; i < len; i++) {
+            djstest.assert(!window.odatajs.oData.net.isLocalUrl(remoteUrls[i]), "is not local: [" + remoteUrls[i] + "]");
+        }
+        djstest.done();
+    });
+
+    // DATAJS INTERNAL END
+
+    djstest.addTest(function userPasswordTest() {
+        odatajs.oData.request({
+            requestUri: "./endpoints/FoodStoreDataServiceV4.svc/UserNameAndPassword",
+            user: "the-user",
+            password: "the-password"
+        }, function (data) {
+            djstest.assertAreEqualDeep(data.value, "Basic dGhlLXVzZXI6dGhlLXBhc3N3b3Jk", "response matches");
+            djstest.done();
+        }, function (err) {
+            djstest.fail("error: " + err.message);
+            djstest.done();
+        });
+    });
+
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-perf-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-perf-tests.html b/odatajs/tests/odata-perf-tests.html
new file mode 100644
index 0000000..238246f
--- /dev/null
+++ b/odatajs/tests/odata-perf-tests.html
@@ -0,0 +1,50 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData perf tests</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script> 
+    <script type="text/javascript" src="common/common.js"></script> 
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/Instrument.js"></script>
+
+    <script type="text/javascript" src="odata-perf-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">OData perf 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/d5ec5557/odatajs/tests/odata-perf-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-perf-tests.js b/odatajs/tests/odata-perf-tests.js
new file mode 100644
index 0000000..cd465fe
--- /dev/null
+++ b/odatajs/tests/odata-perf-tests.js
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var timedHttpClient = {
+        duration: 0,
+        provider: window.odatajs.oData.net.defaultHttpClient,
+        request: function (request, success, error) {
+            var startTime = new Date();
+            return timedHttpClient.provider.request(request, function () {
+                timedHttpClient.duration = new Date() - startTime;
+                success.apply(this, arguments);
+            }, error);
+        }
+    };
+
+    var largeCollectionService = "./endpoints/LargeCollectionService.svc/";
+
+    // null "service" indicates the feed is read-only
+    var feeds = [
+        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=minimal" },
+        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=full" },
+        { service: largeCollectionService, uri: largeCollectionService + "Customers", mimeType: "application/json;odata.metadata=none" },
+        { service: largeCollectionService, uri: largeCollectionService + "Suppliers", mimeType: "application/json" },
+        { service: null, uri: "http://odata.netflix.com/Catalog/Titles", mimeType: "application/json" }
+    ];
+
+    module("Performance", {
+        setup: function () {
+            djstest.wait(function (done) {
+                $.post(largeCollectionService + "ResetData", done);
+            });
+        },
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = timedHttpClient.provider;
+        }
+    });
+
+    window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
+    $.each(feeds, function (_, feed) {
+        $.each([5, 500], function (_, items) {
+            var params = $.extend({}, feed, { items: items, readUri: feed.uri + "?$top=" + items });
+            djstest.addTest(function readPerfTest(params) {
+                var measureRead = function (metadata) {
+                    var startTime = new Date();
+                    odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function () {
+                        var duration = new Date() - startTime - timedHttpClient.duration;
+                        djstest.pass("Duration: " + duration + " ms (Network: " + timedHttpClient.duration + " ms)");
+                        djstest.done();
+                    }, unexpectedErrorHandler, undefined, undefined, metadata);
+                };
+
+                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
+                djstest.assertsExpected(1);
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measureRead();
+                }
+            }, "Time to read (once) " + params.readUri + " with " + params.mimeType, params);
+
+            djstest.addTest(function readParallelMemoryTest(params) {
+                var total = 10;
+                var count = 0;
+                var measureRead = function (metadata) {
+                    Instrument.getBrowserMemorySize(function (memoryBefore) {
+                        for (var i = 0; i < total; i++) {
+                            odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function (_, response) {
+                                count++;
+                                if (count >= total) {
+                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
+                                        var memory = memoryAfter - memoryBefore;
+                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
+                                        djstest.done();
+                                    });
+                                }
+                            }, unexpectedErrorHandler, undefined, undefined, metadata);
+                        }
+                    });
+                };
+
+                djstest.assertsExpected(1);
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measureRead();
+                }
+            }, "Memory to read (x10 parallel) " + params.readUri + " with " + params.mimeType, params, 300000);
+
+            djstest.addTest(function readSerialMemoryTest(params) {
+                var total = 10;
+                var count = 0;
+                var measureRead = function (metadata) {
+                    Instrument.getBrowserMemorySize(function (memoryBefore) {
+                        var makeRequest = function () {
+                            odatajs.oData.read({ requestUri: params.readUri, headers: { Accept: params.mimeType }, enableJsonpCallback: true }, function (_, response) {
+                                count++;
+                                if (count < total) {
+                                    setTimeout(makeRequest, 0);
+                                } else {
+                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
+                                        var memory = memoryAfter - memoryBefore;
+                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
+                                        djstest.done();
+                                    });
+                                }
+                            }, unexpectedErrorHandler, undefined, undefined, metadata);
+                        };
+
+                        makeRequest();
+                    });
+                };
+
+                djstest.assertsExpected(1);
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measureRead, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measureRead();
+                }
+            }, "Memory to read (x10 serial) " + params.readUri + " with " + params.mimeType, params, 300000);
+        });
+
+        if (feed.service) {
+            var params = $.extend({}, feed, {
+                request: {
+                    requestUri: feed.uri,
+                    method: "POST",
+                    headers: { "Content-Type": feed.mimeType, Accept: feed.mimeType },
+                    data: {
+                        ID: -1,
+                        Name: "New Entity"
+                    }
+                }
+            });
+
+            djstest.addTest(function postPerfTest(params) {
+                var measurePost = function (metadata) {
+                    var startTime = new Date();
+                    odatajs.oData.request(params.request, function () {
+                        var duration = new Date() - startTime - timedHttpClient.duration;
+                        djstest.pass("Duration: " + duration + " ms (Network: " + timedHttpClient.duration + " ms)");
+                        djstest.done();
+                    }, unexpectedErrorHandler, undefined, undefined, metadata);
+                };
+
+                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
+                djstest.assertsExpected(1);
+
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measurePost();
+                }
+            }, "Time to POST " + params.uri + " with " + params.mimeType, params);
+
+            djstest.addTest(function postParallelMemoryTest(params) {
+                var total = 10;
+                var count = 0;
+                var measurePost = function (metadata) {
+                    Instrument.getBrowserMemorySize(function (memoryBefore) {
+                        for (var i = 0; i < total; i++) {
+                            odatajs.oData.request(params.request, function (_, response) {
+                                count++;
+                                if (count >= total) {
+                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
+                                        var memory = memoryAfter - memoryBefore;
+                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
+                                        djstest.done();
+                                    });
+                                }
+                            }, unexpectedErrorHandler, undefined, undefined, metadata);
+                        }
+                    });
+                };
+
+                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
+                djstest.assertsExpected(1);
+
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measurePost();
+                }
+            }, "Memory to POST (x10 parallel) " + params.uri + " with " + params.mimeType, params);
+
+            djstest.addTest(function postSerialMemoryTest(params) {
+                var total = 10;
+                var count = 0;
+                var measurePost = function (metadata) {
+                    Instrument.getBrowserMemorySize(function (memoryBefore) {
+                        var makeRequest = function () {
+                            odatajs.oData.request(params.request, function (_, response) {
+                                count++;
+                                if (count < total) {
+                                    setTimeout(makeRequest, 0);
+                                } else {
+                                    Instrument.getBrowserMemorySize(function (memoryAfter) {
+                                        var memory = memoryAfter - memoryBefore;
+                                        djstest.pass("Memory: " + memory + " bytes (Network: " + response.headers["Content-Length"] + " bytes)");
+                                        djstest.done();
+                                    });
+                                }
+                            }, unexpectedErrorHandler, undefined, undefined, metadata);
+                        };
+
+                        makeRequest();
+                    });
+                };
+
+                window.odatajs.oData.net.defaultHttpClient = timedHttpClient;
+                djstest.assertsExpected(1);
+
+                if (params.metadata) {
+                    odatajs.oData.read(params.service + "$metadata", measurePost, unexpectedErrorHandler, OData.metadataHandler);
+                } else {
+                    measurePost();
+                }
+            }, "Memory to POST (x10 serial) " + params.uri + " with " + params.mimeType, params);
+        }
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-qunit-tests.htm
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-qunit-tests.htm b/odatajs/tests/odata-qunit-tests.htm
new file mode 100644
index 0000000..3054691
--- /dev/null
+++ b/odatajs/tests/odata-qunit-tests.htm
@@ -0,0 +1,76 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+  <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/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+
+    <!--<script type="text/javascript" src="common/rx.js"></script>-->
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.5/rx.all.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>
+
+    <script type="text/javascript" src="./common/mockHttpClient.js"></script>
+    <script type="text/javascript" src="./common/mockXMLHttpRequest.js"></script>
+
+    <script type="text/javascript" src="./common/djstest.js"></script>
+    <script type="text/javascript" src="./common/djstest-browser.js"></script>
+    <script type="text/javascript" src="./common/CacheOracle.js"></script>
+
+<!--bingl: disable the failure test case. Will fix them in the next change set-->
+<!--    <script type="text/javascript" src="odata-tests.js"></script>-->
+    <script type="text/javascript" src="odata-json-tests.js"></script>
+<!--    <script type="text/javascript" src="odata-json-light-tests.js"></script>-->
+    <script type="text/javascript" src="odata-links-functional-tests.js"></script>
+    <script type="text/javascript" src="odata-metadata-tests.js"></script>
+    <script type="text/javascript" src="odata-xml-tests.js"></script>
+    <script type="text/javascript" src="odata-handler-tests.js"></script>
+    <script type="text/javascript" src="odata-net-tests.js"></script>
+    <script type="text/javascript" src="odata-batch-tests.js"></script>
+    <script type="text/javascript" src="cache-tests.js"></script>
+    <script type="text/javascript" src="store-tests.js"></script>
+    <script type="text/javascript" src="store-indexeddb-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/d5ec5557/odatajs/tests/odata-read-crossdomain-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-crossdomain-functional-tests.html b/odatajs/tests/odata-read-crossdomain-functional-tests.html
new file mode 100644
index 0000000..86ce093
--- /dev/null
+++ b/odatajs/tests/odata-read-crossdomain-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData tests against local service</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script> 
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-read-crossdomain-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">OData.Read tests against cross domain endpoints</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
\ No newline at end of file


[18/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/json.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/json.js b/odatajs/src/lib/odata/json.js
new file mode 100644
index 0000000..bed98ff
--- /dev/null
+++ b/odatajs/src/lib/odata/json.js
@@ -0,0 +1,918 @@
+/*
+ * 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.
+ */
+
+/** @module odata/json */
+
+
+
+var utils        = require('./../datajs.js').utils;
+var oDataUtils   = require('./utils.js');
+var oDataHandler = require('./handler.js');
+
+var odataNs = "odata";
+var odataAnnotationPrefix = odataNs + ".";
+var contextUrlAnnotation = "@" + odataAnnotationPrefix + "context";
+
+var assigned = utils.assigned;
+var defined = utils.defined;
+var isArray = utils.isArray;
+//var isDate = utils.isDate;
+var isObject = utils.isObject;
+//var normalizeURI = utils.normalizeURI;
+var parseInt10 = utils.parseInt10;
+var getFormatKind = utils.getFormatKind;
+
+var formatDateTimeOffset = oDataUtils.formatDateTimeOffset;
+var formatDuration = oDataUtils.formatDuration;
+var formatNumberWidth = oDataUtils.formatNumberWidth;
+var getCanonicalTimezone = oDataUtils.getCanonicalTimezone;
+var handler = oDataUtils.handler;
+var isComplex = oDataUtils.isComplex;
+var isPrimitive = oDataUtils.isPrimitive;
+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 XXXparseDateTime = oDataUtils.XXXparseDateTime;
+
+var isPrimitiveEdmType = oDataUtils.isPrimitiveEdmType;
+var isGeographyEdmType = oDataUtils.isGeographyEdmType;
+var isGeometryEdmType = oDataUtils.isGeometryEdmType;
+
+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);
+
+
+// The regular expression corresponds to something like this:
+// /Date(123+60)/
+//
+// This first number is date ticks, the + may be a - and is optional,
+// with the second number indicating a timezone offset in minutes.
+//
+// On the wire, the leading and trailing forward slashes are
+// escaped without being required to so the chance of collisions is reduced;
+// however, by the time we see the objects, the characters already
+// look like regular forward slashes.
+var jsonDateRE = /^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/;
+
+/** Formats the given minutes into (+/-)hh:mm format.
+ * @param {Number} minutes - Number of minutes to format.
+ * @returns {String} The minutes in (+/-)hh:mm format.
+ */
+function minutesToOffset(minutes) {
+
+    var sign;
+    if (minutes < 0) {
+        sign = "-";
+        minutes = -minutes;
+    } else {
+        sign = "+";
+    }
+
+    var hours = Math.floor(minutes / 60);
+    minutes = minutes - (60 * hours);
+
+    return sign + formatNumberWidth(hours, 2) + ":" + formatNumberWidth(minutes, 2);
+}
+
+/** Parses the JSON Date representation into a Date object.
+ * @param {String} value - String value.
+ * @returns {Date} A Date object if the value matches one; falsy otherwise.
+ */
+function parseJsonDateString(value) {
+
+    var arr = value && jsonDateRE.exec(value);
+    if (arr) {
+        // 0 - complete results; 1 - ticks; 2 - sign; 3 - minutes
+        var result = new Date(parseInt10(arr[1]));
+        if (arr[2]) {
+            var mins = parseInt10(arr[3]);
+            if (arr[2] === "-") {
+                mins = -mins;
+            }
+
+            // The offset is reversed to get back the UTC date, which is
+            // what the API will eventually have.
+            var current = result.getUTCMinutes();
+            result.setUTCMinutes(current - mins);
+            result.__edmType = "Edm.DateTimeOffset";
+            result.__offset = minutesToOffset(mins);
+        }
+        if (!isNaN(result.valueOf())) {
+            return result;
+        }
+    }
+
+    // Allow undefined to be returned.
+}
+
+// Some JSON implementations cannot produce the character sequence \/
+// which is needed to format DateTime and DateTimeOffset into the
+// JSON string representation defined by the OData protocol.
+// See the history of this file for a candidate implementation of
+// a 'formatJsonDateString' function.
+
+/** Parses a JSON OData payload.
+ * @param handler - This handler.
+ * @param text - Payload text (this parser also handles pre-parsed objects).
+ * @param {Object} context - Object with parsing context.
+ * @return An object representation of the OData payload.</returns>
+ */
+function jsonParser(handler, text, context) {
+
+    var recognizeDates = defined(context.recognizeDates, handler.recognizeDates);
+    var model = context.metadata;
+    var json = (typeof text === "string") ? JSON.parse(text) : text;
+    var metadataContentType;
+    if (assigned(context.contentType) && assigned(context.contentType.properties)) {
+        metadataContentType = context.contentType.properties["odata.metadata"]; //TODO convert to lower before comparism
+    }
+
+    var payloadFormat = getFormatKind(metadataContentType, 1); // none: 0, minimal: 1, full: 2
+
+    // No errors should be throw out if we could not parse the json payload, instead we should just return the original json object.
+    if (payloadFormat === 0) {
+        return json;
+    }
+    else if (payloadFormat === 1) {
+        return readPayloadMinimal(json, model, recognizeDates);
+    }
+    else if (payloadFormat === 2) {
+        // to do: using the EDM Model to get the type of each property instead of just guessing.
+        return readPayloadFull(json, model, recognizeDates);
+    }
+    else {
+        return json;
+    }
+}
+
+
+function addType(data, name, value ) {
+    var fullName = name + '@odata.type';
+
+    if ( data[fullName] === undefined) {
+        data[fullName] = value;
+    }
+}
+
+function addTypeNoEdm(data, name, value ) {
+    var fullName = name + '@odata.type';
+
+    if ( data[fullName] === undefined) {
+        if ( value.substring(0,4)==='Edm.') {
+            data[fullName] = value.substring(4);
+        } else {
+            data[fullName] = value;
+        }
+
+    }
+}
+
+function addTypeColNoEdm(data, name, value ) {
+    var fullName = name + '@odata.type';
+
+    if ( data[fullName] === undefined) {
+        if ( value.substring(0,4)==='Edm.') {
+            data[fullName] = 'Collection('+value.substring(4)+ ')';
+        } else {
+            data[fullName] = 'Collection('+value+ ')';
+        }
+    }
+}
+
+
+/* Adds typeinformation for String, Boolean and numerical EDM-types. 
+ * The type is determined from the odata-json-format-v4.0.doc specification
+ * @param data - Date which will be extendet
+ * @param {Boolean} recognizeDates - True if strings formatted as datetime values should be treated as datetime values. False otherwise.
+ * @returns An object representation of the OData payload.
+ */
+function readPayloadFull(data, model, recognizeDates) {
+    var type;
+    if (utils.isObject(data)) {
+        for (var key in data) {
+            if (data.hasOwnProperty(key)) {
+                if (key.indexOf('@') === -1) {
+                    if (utils.isArray(data[key])) {
+                        for (var i = 0; i < data[key].length; ++i) {
+                            readPayloadFull(data[key][i], model, recognizeDates);
+                        }
+                    } else if (utils.isObject(data[key])) {
+                        if (data[key] !== null) {
+                            //don't step into geo.. objects
+                            var isGeo = false;
+                            type = data[key+'@odata.type'];
+                            if (type && (isGeographyEdmType(type) || isGeometryEdmType(type))) {
+                                // is gemometry type
+                            } else {
+                                readPayloadFull(data[key], model, recognizeDates);
+                            }
+                        }
+                    } else {
+                        type = data[key + '@odata.type'];
+
+                        // On .Net OData library, some basic EDM type is omitted, e.g. Edm.String, Edm.Int, and etc.
+                        // For the full metadata payload, we need to full fill the @data.type for each property if it is missing. 
+                        // We do this is to help the OlingoJS consumers to easily get the type of each property.
+                        if (!assigned(type)) {
+                            // Guessing the "type" from the type of the value is not the right way here. 
+                            // To do: we need to get the type from metadata instead of guessing. 
+                            var typeFromObject = typeof data[key];
+                            if (typeFromObject === 'string') {
+                                addType(data, key, '#String');
+                            } else if (typeFromObject === 'boolean') {
+                                addType(data, key, '#Boolean');
+                            } else if (typeFromObject === 'number') {
+                                if (data[key] % 1 === 0) { // has fraction 
+                                    addType(data, key, '#Int32'); // the biggst integer
+                                } else {
+                                    addType(data, key, '#Decimal'); // the biggst float single,doulbe,decimal
+                                }
+                            }
+                        }
+                        else {
+                            if (recognizeDates) {
+                                convertDatesNoEdm(data, key, type.substring(1));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return data;
+}
+
+/** Serializes the data by returning its string representation.
+ * @param handler - This handler.
+ * @param data - Data to serialize.
+ * @param {Object} context - Object with serialization context.
+ * @returns {String} The string representation of data.
+ */
+function jsonSerializer(handler, data, context) {
+
+    var dataServiceVersion = context.dataServiceVersion || "4.0";
+    var cType = context.contentType = context.contentType || jsonContentType;
+
+    if (cType && cType.mediaType === jsonContentType.mediaType) {
+        context.dataServiceVersion = maxVersion(dataServiceVersion, "4.0");
+        var newdata = formatJsonRequestPayload(data);
+        if (newdata) {
+            return JSON.stringify(newdata);
+        }
+    }
+
+    return undefined;
+}
+
+function formatJsonRequestPayload(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] = formatJsonRequestPayload(data[i]);
+        }
+
+        return newArrayData;
+    }
+
+    var newdata = {};
+    for (var property in data) {
+        if (isJsonSerializableProperty(property)) {
+            newdata[property] = formatJsonRequestPayload(data[property]);
+        }
+    }
+
+    return newdata;
+}
+
+/** JSON replacer function for converting a value to its JSON representation.
+ * @param {Object} value - Value to convert.</param>
+ * @returns {String} JSON representation of the input value.
+ * This method is used during JSON serialization and invoked only by the JSON.stringify function.
+ * It should never be called directly.
+ */
+function jsonReplacer(_, value) {
+    
+
+    if (value && value.__edmType === "Edm.Time") {
+        return formatDuration(value);
+    } else {
+        return value;
+    }
+}
+
+
+/** Creates an object containing information for the json payload.
+ * @param {String} kind - JSON payload kind, one of the PAYLOADTYPE_XXX constant values.
+ * @param {String} typeName - Type name of the JSON payload.
+ * @returns {Object} Object with kind and type fields.
+ */
+function jsonMakePayloadInfo(kind, type) {
+
+    /// TODO docu
+    /// <field name="kind" type="String">Kind of the JSON payload. One of the PAYLOADTYPE_XXX constant values.</field>
+    /// <field name="type" type="String">Data type of the JSON payload.</field>
+
+    return { kind: kind, type: type || null };
+}
+
+/** Creates an object containing information for the context
+ * TODO check dou layout
+ * @returns {Object} Object with type information
+ * @returns {Object.detectedPayloadKind(optional)}  see constants starting with PAYLOADTYPE_
+ * @returns {Object.deltaKind(optional)}  deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
+ * @returns {Object.typeName(optional)}  name of the type
+ * @returns {Object.type(optional)}  object containing type information for entity- and complex-types ( null if a typeName is a primitive)
+*/
+function parseContextUriFragment( 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("/");
+    var type;
+    
+    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;
+
+                    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;
+                }
+            }
+
+
+            if (jsonIsPrimitiveType(fragment)) {
+                ret.typeName = fragment;
+                ret.type = null;
+                ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
+                continue;
+            }
+
+            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;
+            }
+
+            
+
+            //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;
+                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) {
+                    //PAYLOADTYPE_COLLECTION
+                    ret.typeName = property.type;
+                    
+                    
+                    if (utils.startsWith(property.type, 'Collection')) {
+                        ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
+                        var tmp12 =  property.type.substring(10+1,property.type.length - 1);
+                        ret.typeName = tmp12;
+                        ret.type = lookupComplexType(tmp12, model);    
+                        ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
+                    } else {
+                        ret.type = lookupComplexType(property.type, model);    
+                        ret.detectedPayloadKind = PAYLOADTYPE_PROPERTY;
+                    }    
+
+                    ret.name = fragment;
+                    // 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;
+}
+
+/** Infers the information describing the JSON payload from its metadata annotation, structure, and data model.
+ * @param {Object} data - Json response payload object.
+ * @param {Object} model - Object describing an OData conceptual schema.
+ * 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 payload.
+ * @return Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
+*/
+function createPayloadInfo(data, model) {
+    
+
+    var metadataUri = data[contextUrlAnnotation];
+    if (!metadataUri || typeof metadataUri !== "string") {
+        return null;
+    }
+
+    var fragmentStart = metadataUri.lastIndexOf("#");
+    if (fragmentStart === -1) {
+        return jsonMakePayloadInfo(PAYLOADTYPE_SVCDOC);
+    }
+
+    var fragment = metadataUri.substring(fragmentStart + 1);
+    return parseContextUriFragment(fragment,model);
+}
+
+/** Processe a JSON response payload with metadata-minimal
+ * @param {Object} data - Json response payload object
+ * @param {Object} model - Object describing an OData conceptual schema
+ * @param {Boolean} recognizeDates - Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.
+ * @returns {Object} Object in the library's representation.
+ */
+function readPayloadMinimal(data, model, recognizeDates) {
+
+    if (!assigned(model) || isArray(model)) {
+        return data;
+    }
+
+    var baseURI = data[contextUrlAnnotation];
+    var payloadInfo = createPayloadInfo(data, model);
+
+    switch (payloadInfo.detectedPayloadKind) {
+        case PAYLOADTYPE_VALUE:
+            return readPayloadMinimalProperty(data, model, payloadInfo, baseURI, recognizeDates);
+        case PAYLOADTYPE_FEED:
+            return readPayloadMinimalFeed(data, model, payloadInfo, baseURI, recognizeDates);
+        case PAYLOADTYPE_ENTRY:
+            return readPayloadMinimalEntry(data, model, payloadInfo, baseURI, recognizeDates);
+        case PAYLOADTYPE_COLLECTION:
+            return readPayloadMinimalCollection(data, model, payloadInfo, baseURI, recognizeDates);
+        case PAYLOADTYPE_PROPERTY:
+            return readPayloadMinimalProperty(data, model, payloadInfo, baseURI, recognizeDates);
+        case PAYLOADTYPE_SVCDOC:
+            return data;
+        case PAYLOADTYPE_LINKS:
+            return data;
+    }
+
+    return data;
+}
+
+/** Gets the key of an entry.
+ * @param {Object} data - JSON entry.
+ *
+ * @returns {string} Entry instance key.
+ */
+function jsonGetEntryKey(data, entityModel) {
+
+    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;
+}
+
+function readPayloadMinimalProperty(data, model, collectionInfo, baseURI, recognizeDates) {
+    if (collectionInfo.type !== null) {
+        readPayloadMinimalObject(data, collectionInfo, baseURI, model, recognizeDates);
+    } else {
+        addTypeNoEdm(data,'value', collectionInfo.typeName);
+        //data['value@odata.type'] = '#'+collectionInfo.typeName;
+    }
+    return data;
+}
+
+function readPayloadMinimalCollection(data, model, collectionInfo, baseURI, recognizeDates) {
+    //data['@odata.type'] = '#Collection('+collectionInfo.typeName + ')';
+    addTypeColNoEdm(data,'', collectionInfo.typeName);
+
+    if (collectionInfo.type !== null) {
+        var entries = [];
+
+        var items = data.value;
+        for (i = 0, len = items.length; i < len; i++) {
+            var item = items[i];
+            if ( defined(item['@odata.type'])) { // in case of mixed collections
+                var typeName = item['@odata.type'].substring(1);
+                var type = lookupEntityType( typeName, model);
+                var entryInfo = {
+                    contentTypeOdata : collectionInfo.contentTypeOdata,
+                    detectedPayloadKind : collectionInfo.detectedPayloadKind,
+                    name : collectionInfo.name,
+                    type : type,
+                    typeName : typeName
+                };
+
+                entry = readPayloadMinimalObject(item, entryInfo, baseURI, model, recognizeDates);
+            } else {
+                entry = readPayloadMinimalObject(item, collectionInfo, baseURI, model, recognizeDates);
+            }
+            
+            entries.push(entry);
+        }
+        data.value = entries;
+    }
+    return data;
+}
+
+function readPayloadMinimalFeed(data, model, feedInfo, baseURI, recognizeDates) {
+    var entries = [];
+    var items = data.value;
+    for (i = 0, len = items.length; i < len; i++) {
+        var item = items[i];
+        if ( defined(item['@odata.type'])) { // in case of mixed feeds
+            var typeName = item['@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 = readPayloadMinimalObject(item, entryInfo, baseURI, model, recognizeDates);
+        } else {
+            entry = readPayloadMinimalObject(item, feedInfo, baseURI, model, recognizeDates);
+        }
+        
+        entries.push(entry);
+    }
+    data.value = entries;
+    return data;
+}
+
+function readPayloadMinimalEntry(data, model, entryInfo, baseURI, recognizeDates) {
+    return readPayloadMinimalObject(data, entryInfo, baseURI, model, recognizeDates);
+}
+
+/** Formats a value according to Uri literal format
+ * @param value - Value to be formatted.
+ * @param type - Edm type of the value
+ * @returns {string} Value after formatting
+ */
+function formatLiteral(value, type) {
+
+    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;
+    }
+}
+
+function formatRowLiteral(value, type) {
+    switch (type) {
+        case "Edm.Binary":
+            return convertByteArrayToHexString(value);
+        default:
+            return value;
+    }
+}
+
+function convertDates(data, propertyName,type) {
+    if (type === 'Edm.Date') {
+        data[propertyName] = oDataUtils.parseDate(data[propertyName], true);
+    } else if (type === 'Edm.DateTimeOffset') {
+        data[propertyName] = oDataUtils.parseDateTimeOffset(data[propertyName], true);
+    } else if (type === 'Edm.Duration') {
+        data[propertyName] = oDataUtils.parseDuration(data[propertyName], true);
+    } else if (type === 'Edm.Time') {
+        data[propertyName] = oDataUtils.parseTime(data[propertyName], true);
+    }
+}
+
+function convertDatesNoEdm(data, propertyName,type) {
+    if (type === 'Date') {
+        data[propertyName] = oDataUtils.parseDate(data[propertyName], true);
+    } else if (type === 'DateTimeOffset') {
+        data[propertyName] = oDataUtils.parseDateTimeOffset(data[propertyName], true);
+    } else if (type === 'Duration') {
+        data[propertyName] = oDataUtils.parseDuration(data[propertyName], true);
+    } else if (type === 'Time') {
+        data[propertyName] = oDataUtils.parseTime(data[propertyName], true);
+    }
+}
+
+function checkProperties(data, objectInfoType, baseURI, model, recognizeDates) {
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var curType = objectInfoType;
+            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 ( isArray(propertyValue)) {
+                //data[name+'@odata.type'] = '#' + property.type;
+                if (isCollectionType(property.type)) {
+                    addTypeColNoEdm(data,name,property.type.substring(11,property.type.length-1));
+                } else {
+                    addTypeNoEdm(data,name,property.type);
+                }
+
+
+                for ( var i = 0; i < propertyValue.length; i++) {
+                    readPayloadMinimalComplexObject(propertyValue[i], property, baseURI, model, recognizeDates);
+                }
+            } else if (isObject(propertyValue) && (propertyValue !== null)) {
+                readPayloadMinimalComplexObject(propertyValue, property, baseURI, model, recognizeDates);
+            } else {
+                //data[name+'@odata.type'] = '#' + property.type;
+                addTypeNoEdm(data,name,property.type);
+                if (recognizeDates) {
+                    convertDates(data, name, property.type);
+                }
+            }
+        }
+    }
+}
+
+function readPayloadMinimalComplexObject(data, property, baseURI, model, recognizeDates) {
+    var type = property.type;
+    if (isCollectionType(property.type)) {
+        type =property.type.substring(11,property.type.length-1);
+    }
+
+    //data['@odata.type'] = '#'+type;
+    addType(data,'',property.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
+    }
+  
+    checkProperties(data, propertyType, baseURI, model, recognizeDates);
+}
+
+function readPayloadMinimalObject(data, objectInfo, baseURI, model, recognizeDates) {
+    //data['@odata.type'] = '#'+objectInfo.typeName;
+    addType(data,'',objectInfo.typeName);
+
+    var keyType = objectInfo.type;
+    while ((defined(keyType)) && ( keyType.key === undefined) && (keyType.baseType !== undefined)) {
+        keyType = lookupEntityType(keyType.baseType, model);
+    }
+
+    //if ((keyType !== undefined) && (keyType.key !== undefined)) { 
+    if (keyType.key !== undefined) { 
+        var lastIdSegment = objectInfo.name + jsonGetEntryKey(data, keyType);
+        data['@odata.id'] = baseURI.substring(0, baseURI.lastIndexOf("$metadata")) + lastIdSegment;
+        data['@odata.editLink'] = lastIdSegment;
+    }
+
+    var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
+    //json ComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
+
+    checkProperties(data, objectInfo.type, baseURI, model, recognizeDates);
+    
+    return data;
+}
+
+var jsonSerializableMetadata = ["@odata.id", "@odata.type"];
+
+function isJsonSerializableProperty(property) {
+    if (!property) {
+        return false;
+    }
+
+    if (property.indexOf("@odata.") == -1) {
+        return true;
+    } 
+
+    var i, len;
+    for (i = 0, len = jsonSerializableMetadata.length; i < len; i++) {
+        var name = jsonSerializableMetadata[i];
+        if (property.indexOf(name) != -1) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/** Determines whether a type name is a primitive type in a JSON payload.
+ * @param {String} typeName - Type name to test.
+ * @returns {Boolean} True if the type name an EDM primitive type or an OData spatial type; false otherwise.
+ */
+function jsonIsPrimitiveType(typeName) {
+
+    return isPrimitiveEdmType(typeName) || isGeographyEdmType(typeName) || isGeometryEdmType(typeName);
+}
+
+
+var jsonHandler = oDataHandler.handler(jsonParser, jsonSerializer, jsonMediaType, MAX_DATA_SERVICE_VERSION);
+jsonHandler.recognizeDates = false;
+
+
+
+exports.createPayloadInfo = createPayloadInfo;
+exports.jsonHandler = jsonHandler;
+exports.jsonParser = jsonParser;
+exports.jsonSerializer = jsonSerializer;
+exports.parseJsonDateString = parseJsonDateString;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/metadata.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/metadata.js b/odatajs/src/lib/odata/metadata.js
new file mode 100644
index 0000000..5ad70b6
--- /dev/null
+++ b/odatajs/src/lib/odata/metadata.js
@@ -0,0 +1,523 @@
+/*
+ * 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.
+ */
+
+/** @module odata/metadata */
+
+var utils    = require('./../datajs.js').utils;
+var oDSxml    = require('./../datajs.js').xml;
+var odataHandler    = require('./handler.js');
+
+
+
+// imports 
+var contains = utils.contains;
+var normalizeURI = utils.normalizeURI;
+var xmlAttributes = oDSxml.xmlAttributes;
+var xmlChildElements = oDSxml.xmlChildElements;
+var xmlFirstChildElement = oDSxml.xmlFirstChildElement;
+var xmlInnerText = oDSxml.xmlInnerText;
+var xmlLocalName = oDSxml.xmlLocalName;
+var xmlNamespaceURI = oDSxml.xmlNamespaceURI;
+var xmlNS = oDSxml.xmlNS;
+var xmlnsNS = oDSxml.xmlnsNS;
+var xmlParse = oDSxml.xmlParse;
+
+var ado = oDSxml.http + "docs.oasis-open.org/odata/";      // http://docs.oasis-open.org/odata/
+var adoDs = ado + "ns";                             // http://docs.oasis-open.org/odata/ns
+var edmxNs = adoDs + "/edmx";                       // http://docs.oasis-open.org/odata/ns/edmx
+var edmNs1 = adoDs + "/edm";                        // http://docs.oasis-open.org/odata/ns/edm
+var odataMetaXmlNs = adoDs + "/metadata";           // http://docs.oasis-open.org/odata/ns/metadata
+var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
+
+var xmlMediaType = "application/xml";
+
+/** Creates an object that describes an element in an schema.
+ * @param {Array} attributes - List containing the names of the attributes allowed for this element.
+ * @param {Array} elements - List containing the names of the child elements allowed for this element.
+ * @param {Boolean} text - Flag indicating if the element's text value is of interest or not.
+ * @param {String} ns - Namespace to which the element belongs to.
+ * If a child element name ends with * then it is understood by the schema that that child element can appear 0 or more times.
+ * @returns {Object} Object with attributes, elements, text, and ns fields.
+ */
+function schemaElement(attributes, elements, text, ns) {
+
+    return {
+        attributes: attributes,
+        elements: elements,
+        text: text || false,
+        ns: ns
+    };
+}
+
+// It's assumed that all elements may have Documentation children and Annotation elements.
+// See http://docs.oasis-open.org/odata/odata/v4.0/cs01/part3-csdl/odata-v4.0-cs01-part3-csdl.html for a CSDL reference.
+var schema = {
+    elements: {
+        Action: schemaElement(
+        /*attributes*/["Name", "IsBound", "EntitySetPath"],
+        /*elements*/["ReturnType", "Parameter*", "Annotation*"]
+        ),
+        ActionImport: schemaElement(
+        /*attributes*/["Name", "Action", "EntitySet", "Annotation*"]
+        ),
+        Annotation: schemaElement(
+        /*attributes*/["Term", "Qualifier", "Binary", "Bool", "Date", "DateTimeOffset", "Decimal", "Duration", "EnumMember", "Float", "Guid", "Int", "String", "TimeOfDay", "AnnotationPath", "NavigationPropertyPath", "Path", "PropertyPath", "UrlRef"],
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
+        ),
+        AnnotationPath: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Annotations: schemaElement(
+        /*attributes*/["Target", "Qualifier"],
+        /*elements*/["Annotation*"]
+        ),
+        Apply: schemaElement(
+        /*attributes*/["Function"],
+        /*elements*/["String*", "Path*", "LabeledElement*", "Annotation*"]
+        ),
+        And: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Or: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Not: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Eq: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Ne: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Gt: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Ge: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Lt: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Le: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Binary: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Bool: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Cast: schemaElement(
+        /*attributes*/["Type"],
+        /*elements*/["Path*", "Annotation*"]
+        ),
+        Collection: schemaElement(
+        /*attributes*/null,
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*"]
+        ),
+        ComplexType: schemaElement(
+        /*attributes*/["Name", "BaseType", "Abstract", "OpenType"],
+        /*elements*/["Property*", "NavigationProperty*", "Annotation*"]
+        ),
+        Date: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        DateTimeOffset: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Decimal: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Duration: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        EntityContainer: schemaElement(
+        /*attributes*/["Name", "Extends"],
+        /*elements*/["EntitySet*", "Singleton*", "ActionImport*", "FunctionImport*", "Annotation*"]
+        ),
+        EntitySet: schemaElement(
+        /*attributes*/["Name", "EntityType", "IncludeInServiceDocument"],
+        /*elements*/["NavigationPropertyBinding*", "Annotation*"]
+        ),
+        EntityType: schemaElement(
+        /*attributes*/["Name", "BaseType", "Abstract", "OpenType", "HasStream"],
+        /*elements*/["Key*", "Property*", "NavigationProperty*", "Annotation*"]
+        ),
+        EnumMember: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        EnumType: schemaElement(
+        /*attributes*/["Name", "UnderlyingType", "IsFlags"],
+        /*elements*/["Member*"]
+        ),
+        Float: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Function: schemaElement(
+        /*attributes*/["Name", "IsBound", "IsComposable", "EntitySetPath"],
+        /*elements*/["ReturnType", "Parameter*", "Annotation*"]
+        ),
+        FunctionImport: schemaElement(
+        /*attributes*/["Name", "Function", "EntitySet", "IncludeInServiceDocument", "Annotation*"]
+        ),
+        Guid: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        If: schemaElement(
+        /*attributes*/null,
+        /*elements*/["Path*", "String*", "Annotation*"]
+        ),
+        Int: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        IsOf: schemaElement(
+        /*attributes*/["Type", "MaxLength", "Precision", "Scale", "Unicode", "SRID", "DefaultValue", "Annotation*"],
+        /*elements*/["Path*"]
+        ),
+        Key: schemaElement(
+        /*attributes*/null,
+        /*elements*/["PropertyRef*"]
+        ),
+        LabeledElement: schemaElement(
+        /*attributes*/["Name"],
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
+        ),
+        LabeledElementReference: schemaElement(
+        /*attributes*/["Term"],
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*"]
+        ),
+        Member: schemaElement(
+        /*attributes*/["Name", "Value"],
+        /*element*/["Annotation*"]
+        ),
+        NavigationProperty: schemaElement(
+        /*attributes*/["Name", "Type", "Nullable", "Partner", "ContainsTarget"],
+        /*elements*/["ReferentialConstraint*", "OnDelete*", "Annotation*"]
+        ),
+        NavigationPropertyBinding: schemaElement(
+        /*attributes*/["Path", "Target"]
+        ),
+        NavigationPropertyPath: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Null: schemaElement(
+        /*attributes*/null,
+        /*elements*/["Annotation*"]
+        ),
+        OnDelete: schemaElement(
+        /*attributes*/["Action"],
+        /*elements*/["Annotation*"]
+        ),
+        Path: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Parameter: schemaElement(
+        /*attributes*/["Name", "Type", "Nullable", "MaxLength", "Precision", "Scale", "SRID"],
+        /*elements*/["Annotation*"]
+        ),
+        Property: schemaElement(
+        /*attributes*/["Name", "Type", "Nullable", "MaxLength", "Precision", "Scale", "Unicode", "SRID", "DefaultValue"],
+        /*elements*/["Annotation*"]
+        ),
+        PropertyPath: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        PropertyRef: schemaElement(
+        /*attributes*/["Name", "Alias"]
+        ),
+        PropertyValue: schemaElement(
+        /*attributes*/["Property", "Path"],
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
+        ),
+        Record: schemaElement(
+        /*attributes*/null,
+        /*Elements*/["PropertyValue*", "Property*", "Annotation*"]
+        ),
+        ReferentialConstraint: schemaElement(
+        /*attributes*/["Property", "ReferencedProperty", "Annotation*"]
+        ),
+        ReturnType: schemaElement(
+        /*attributes*/["Type", "Nullable", "MaxLength", "Precision", "Scale", "SRID"]
+        ),
+        String: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        Schema: schemaElement(
+        /*attributes*/["Namespace", "Alias"],
+        /*elements*/["Action*", "Annotations*", "Annotation*", "ComplexType*", "EntityContainer", "EntityType*", "EnumType*", "Function*", "Term*", "TypeDefinition*", "Annotation*"]
+        ),
+        Singleton: schemaElement(
+        /*attributes*/["Name", "Type"],
+        /*elements*/["NavigationPropertyBinding*", "Annotation*"]
+        ),
+        Term: schemaElement(
+        /*attributes*/["Name", "Type", "BaseTerm", "DefaultValue ", "AppliesTo", "Nullable", "MaxLength", "Precision", "Scale", "SRID"],
+        /*elements*/["Annotation*"]
+        ),
+        TimeOfDay: schemaElement(
+        /*attributes*/null,
+        /*elements*/null,
+        /*text*/true
+        ),
+        TypeDefinition: schemaElement(
+        /*attributes*/["Name", "UnderlyingType", "MaxLength", "Unicode", "Precision", "Scale", "SRID"],
+        /*elements*/["Annotation*"]
+        ),
+        UrlRef: schemaElement(
+        /*attributes*/null,
+        /*elements*/["Binary*", "Bool*", "Date*", "DateTimeOffset*", "Decimal*", "Duration*", "EnumMember*", "Float*", "Guid*", "Int*", "String*", "TimeOfDay*", "And*", "Or*", "Not*", "Eq*", "Ne*", "Gt*", "Ge*", "Lt*", "Le*", "AnnotationPath*", "Apply*", "Cast*", "Collection*", "If*", "IsOf*", "LabeledElement*", "LabeledElementReference*", "Null*", "NavigationPropertyPath*", "Path*", "PropertyPath*", "Record*", "UrlRef*", "Annotation*"]
+        ),
+
+        // See http://msdn.microsoft.com/en-us/library/dd541238(v=prot.10) for an EDMX reference.
+        Edmx: schemaElement(
+        /*attributes*/["Version"],
+        /*elements*/["DataServices", "Reference*"],
+        /*text*/false,
+        /*ns*/edmxNs
+        ),
+        DataServices: schemaElement(
+        /*attributes*/["m:MaxDataServiceVersion", "m:DataServiceVersion"],
+        /*elements*/["Schema*"],
+        /*text*/false,
+        /*ns*/edmxNs
+        ),
+        Reference: schemaElement(
+        /*attributes*/["Uri"],
+        /*elements*/["Include*", "IncludeAnnotations*", "Annotation*"]
+        ),
+        Include: schemaElement(
+        /*attributes*/["Namespace", "Alias"]
+        ),
+        IncludeAnnotations: schemaElement(
+        /*attributes*/["TermNamespace", "Qualifier", "TargetNamespace"]
+        )
+    }
+};
+
+
+/** Converts a Pascal-case identifier into a camel-case identifier.
+ * @param {String} text - Text to convert.
+ * @returns {String} Converted text.
+ * If the text starts with multiple uppercase characters, it is left as-is.</remarks>
+ */
+function scriptCase(text) {
+
+    if (!text) {
+        return text;
+    }
+
+    if (text.length > 1) {
+        var firstTwo = text.substr(0, 2);
+        if (firstTwo === firstTwo.toUpperCase()) {
+            return text;
+        }
+
+        return text.charAt(0).toLowerCase() + text.substr(1);
+    }
+
+    return text.charAt(0).toLowerCase();
+}
+
+/** Gets the schema node for the specified element.
+ * @param {Object} parentSchema - Schema of the parent XML node of 'element'.
+ * @param candidateName - XML element name to consider.
+ * @returns {Object} The schema that describes the specified element; null if not found.
+ */
+function getChildSchema(parentSchema, candidateName) {
+
+    var elements = parentSchema.elements;
+    if (!elements) {
+        return null;
+    }
+
+    var i, len;
+    for (i = 0, len = elements.length; i < len; i++) {
+        var elementName = elements[i];
+        var multipleElements = false;
+        if (elementName.charAt(elementName.length - 1) === "*") {
+            multipleElements = true;
+            elementName = elementName.substr(0, elementName.length - 1);
+        }
+
+        if (candidateName === elementName) {
+            var propertyName = scriptCase(elementName);
+            return { isArray: multipleElements, propertyName: propertyName };
+        }
+    }
+
+    return null;
+}
+
+/** Checks whether the specifies namespace URI is one of the known CSDL namespace URIs.
+ * @param {String} nsURI - Namespace URI to check.
+ * @returns {Boolean} true if nsURI is a known CSDL namespace; false otherwise.
+ */
+function isEdmNamespace(nsURI) {
+
+    return nsURI === edmNs1;
+}
+
+/** Parses a CSDL document.
+ * @param element - DOM element to parse.
+ * @returns {Object} An object describing the parsed element.
+ */
+function parseConceptualModelElement(element) {
+
+    var localName = xmlLocalName(element);
+    var nsURI = xmlNamespaceURI(element);
+    var elementSchema = schema.elements[localName];
+    if (!elementSchema) {
+        return null;
+    }
+
+    if (elementSchema.ns) {
+        if (nsURI !== elementSchema.ns) {
+            return null;
+        }
+    } else if (!isEdmNamespace(nsURI)) {
+        return null;
+    }
+
+    var item = {};
+    var attributes = elementSchema.attributes || [];
+    xmlAttributes(element, function (attribute) {
+
+        var localName = xmlLocalName(attribute);
+        var nsURI = xmlNamespaceURI(attribute);
+        var value = attribute.value;
+
+        // Don't do anything with xmlns attributes.
+        if (nsURI === xmlnsNS) {
+            return;
+        }
+
+        // Currently, only m: for metadata is supported as a prefix in the internal schema table,
+        // un-prefixed element names imply one a CSDL element.
+        var schemaName = null;
+        var handled = false;
+        if (isEdmNamespace(nsURI) || nsURI === null) {
+            schemaName = "";
+        } else if (nsURI === odataMetaXmlNs) {
+            schemaName = "m:";
+        }
+
+        if (schemaName !== null) {
+            schemaName += localName;
+
+            if (contains(attributes, schemaName)) {
+                item[scriptCase(localName)] = value;
+            }
+        }
+
+    });
+
+    xmlChildElements(element, function (child) {
+        var localName = xmlLocalName(child);
+        var childSchema = getChildSchema(elementSchema, localName);
+        if (childSchema) {
+            if (childSchema.isArray) {
+                var arr = item[childSchema.propertyName];
+                if (!arr) {
+                    arr = [];
+                    item[childSchema.propertyName] = arr;
+                }
+                arr.push(parseConceptualModelElement(child));
+            } else {
+                item[childSchema.propertyName] = parseConceptualModelElement(child);
+            }
+        } 
+    });
+
+    if (elementSchema.text) {
+        item.text = xmlInnerText(element);
+    }
+
+    return item;
+}
+
+/** Parses a metadata document.
+ * @param handler - This handler.
+ * @param {String} text - Metadata text.
+ * @returns An object representation of the conceptual model.</returns>
+ */
+function metadataParser(handler, text) {
+
+    var doc = xmlParse(text);
+    var root = xmlFirstChildElement(doc);
+    return parseConceptualModelElement(root) || undefined;
+}
+
+
+
+exports.metadataHandler = odataHandler.handler(metadataParser, null, xmlMediaType, MAX_DATA_SERVICE_VERSION);
+
+exports.schema = schema;
+exports.scriptCase = scriptCase;
+exports.getChildSchema = getChildSchema;
+exports.parseConceptualModelElement = parseConceptualModelElement;
+exports.metadataParser = metadataParser;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/src/lib/odata/net.js
----------------------------------------------------------------------
diff --git a/odatajs/src/lib/odata/net.js b/odatajs/src/lib/odata/net.js
new file mode 100644
index 0000000..9821892
--- /dev/null
+++ b/odatajs/src/lib/odata/net.js
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+/** @module odata/net */
+
+
+
+var utils    = require('./../datajs.js').utils;
+// Imports.
+
+var defined = utils.defined;
+var delay = utils.delay;
+
+var ticks = 0;
+
+/* Checks whether the specified request can be satisfied with a JSONP request.
+ * @param request - Request object to check.
+ * @returns {Boolean} true if the request can be satisfied; false otherwise.
+
+ * Requests that 'degrade' without changing their meaning by going through JSONP
+ * are considered usable.
+ *
+ * We allow data to come in a different format, as the servers SHOULD honor the Accept
+ * request but may in practice return content with a different MIME type.
+ */
+function canUseJSONP(request) {
+    
+    if (request.method && request.method !== "GET") {
+        return false;
+    }
+
+    return true;
+}
+
+/** Creates an IFRAME tag for loading the JSONP script
+ * @param {String} url - The source URL of the script
+ * @returns {HTMLElement} The IFRAME tag
+ */
+function createIFrame(url) {
+    var iframe = window.document.createElement("IFRAME");
+    iframe.style.display = "none";
+
+    var attributeEncodedUrl = url.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
+    var html = "<html><head><script type=\"text/javascript\" src=\"" + attributeEncodedUrl + "\"><\/script><\/head><body><\/body><\/html>";
+
+    var body = window.document.getElementsByTagName("BODY")[0];
+    body.appendChild(iframe);
+
+    writeHtmlToIFrame(iframe, html);
+    return iframe;
+};
+
+/** Creates a XmlHttpRequest object.
+ * @returns {XmlHttpRequest} XmlHttpRequest object.
+ */
+function createXmlHttpRequest() {
+    if (window.XMLHttpRequest) {
+        return new window.XMLHttpRequest();
+    }
+    var exception;
+    if (window.ActiveXObject) {
+        try {
+            return new window.ActiveXObject("Msxml2.XMLHTTP.6.0");
+        } catch (_) {
+            try {
+                return new window.ActiveXObject("Msxml2.XMLHTTP.3.0");
+            } catch (e) {
+                exception = e;
+            }
+        }
+    } else {
+        exception = { message: "XMLHttpRequest not supported" };
+    }
+    throw exception;
+}
+
+/** Checks whether the specified URL is an absolute URL.
+ * @param {String} url - URL to check.
+ * @returns {Boolean} true if the url is an absolute URL; false otherwise.
+*/
+function isAbsoluteUrl(url) {
+    return url.indexOf("http://") === 0 ||
+        url.indexOf("https://") === 0 ||
+        url.indexOf("file://") === 0;
+}
+
+/** Checks whether the specified URL is local to the current context.
+ * @param {String} url - URL to check.
+ * @returns {Boolean} true if the url is a local URL; false otherwise.
+ */
+function isLocalUrl(url) {
+
+    if (!isAbsoluteUrl(url)) {
+        return true;
+    }
+
+    // URL-embedded username and password will not be recognized as same-origin URLs.
+    var location = window.location;
+    var locationDomain = location.protocol + "//" + location.host + "/";
+    return (url.indexOf(locationDomain) === 0);
+}
+
+/** Removes a callback used for a JSONP request.
+ * @param {String} name - Function name to remove.
+ * @param {Number} tick - Tick count used on the callback.
+ */
+function removeCallback(name, tick) {
+    try {
+        delete window[name];
+    } catch (err) {
+        window[name] = undefined;
+        if (tick === ticks - 1) {
+            ticks -= 1;
+        }
+    }
+};
+
+/** Removes an iframe.
+ * @param {Object} iframe - The iframe to remove.
+ * @returns {Object} Null value to be assigned to iframe reference.
+ */
+function removeIFrame(iframe) {
+    if (iframe) {
+        writeHtmlToIFrame(iframe, "");
+        iframe.parentNode.removeChild(iframe);
+    }
+
+    return null;
+};
+
+/** Reads response headers into array.
+ * @param {XMLHttpRequest} xhr - HTTP request with response available.
+ * @param {Array} headers - Target array to fill with name/value pairs.
+ */
+function readResponseHeaders(xhr, headers) {
+
+    var responseHeaders = xhr.getAllResponseHeaders().split(/\r?\n/);
+    var i, len;
+    for (i = 0, len = responseHeaders.length; i < len; i++) {
+        if (responseHeaders[i]) {
+            var header = responseHeaders[i].split(": ");
+            headers[header[0]] = header[1];
+        }
+    }
+}
+
+/** Writes HTML to an IFRAME document.
+ * @param {HTMLElement} iframe - The IFRAME element to write to.
+ * @param {String} html - The HTML to write.
+ */
+function writeHtmlToIFrame(iframe, html) {
+    var frameDocument = (iframe.contentWindow) ? iframe.contentWindow.document : iframe.contentDocument.document;
+    frameDocument.open();
+    frameDocument.write(html);
+    frameDocument.close();
+}
+
+exports.defaultHttpClient = {
+    callbackParameterName: "$callback",
+
+    formatQueryString: "$format=json",
+
+    enableJsonpCallback: false,
+
+    /** Performs a network request.
+     * @param {Object} request - Request description
+     * @param {Function} success - Success callback with the response object.
+     * @param {Function} error - Error callback with an error object.
+     * @returns {Object} Object with an 'abort' method for the operation.
+     */
+    request: function (request, success, error) {
+
+        var result = {};
+        var xhr = null;
+        var done = false;
+        var iframe;
+
+        result.abort = function () {
+            iframe = removeIFrame(iframe);
+            if (done) {
+                return;
+            }
+
+            done = true;
+            if (xhr) {
+                xhr.abort();
+                xhr = null;
+            }
+
+            error({ message: "Request aborted" });
+        };
+
+        var handleTimeout = function () {
+            iframe = removeIFrame(iframe);
+            if (!done) {
+                done = true;
+                xhr = null;
+                error({ message: "Request timed out" });
+            }
+        };
+
+        var name;
+        var url = request.requestUri;
+        var enableJsonpCallback = defined(request.enableJsonpCallback, this.enableJsonpCallback);
+        var callbackParameterName = defined(request.callbackParameterName, this.callbackParameterName);
+        var formatQueryString = defined(request.formatQueryString, this.formatQueryString);
+        if (!enableJsonpCallback || isLocalUrl(url)) {
+
+            xhr = createXmlHttpRequest();
+            xhr.onreadystatechange = function () {
+                if (done || xhr === null || xhr.readyState !== 4) {
+                    return;
+                }
+
+                // Workaround for XHR behavior on IE.
+                var statusText = xhr.statusText;
+                var statusCode = xhr.status;
+                if (statusCode === 1223) {
+                    statusCode = 204;
+                    statusText = "No Content";
+                }
+
+                var headers = [];
+                readResponseHeaders(xhr, headers);
+
+                var response = { requestUri: url, statusCode: statusCode, statusText: statusText, headers: headers, body: xhr.responseText };
+
+                done = true;
+                xhr = null;
+                if (statusCode >= 200 && statusCode <= 299) {
+                    success(response);
+                } else {
+                    error({ message: "HTTP request failed", request: request, response: response });
+                }
+            };
+
+            xhr.open(request.method || "GET", url, true, request.user, request.password);
+
+            // Set the name/value pairs.
+            if (request.headers) {
+                for (name in request.headers) {
+                    xhr.setRequestHeader(name, request.headers[name]);
+                }
+            }
+
+            // Set the timeout if available.
+            if (request.timeoutMS) {
+                xhr.timeout = request.timeoutMS;
+                xhr.ontimeout = handleTimeout;
+            }
+
+            xhr.send(request.body);
+        } else {
+            if (!canUseJSONP(request)) {
+                throw { message: "Request is not local and cannot be done through JSONP." };
+            }
+
+            var tick = ticks;
+            ticks += 1;
+            var tickText = tick.toString();
+            var succeeded = false;
+            var timeoutId;
+            name = "handleJSONP_" + tickText;
+            window[name] = function (data) {
+                iframe = removeIFrame(iframe);
+                if (!done) {
+                    succeeded = true;
+                    window.clearTimeout(timeoutId);
+                    removeCallback(name, tick);
+
+                    // Workaround for IE8 and IE10 below where trying to access data.constructor after the IFRAME has been removed
+                    // throws an "unknown exception"
+                    if (window.ActiveXObject) {
+                        data = window.JSON.parse(window.JSON.stringify(data));
+                    }
+
+
+                    var headers;
+                    if (!formatQueryString || formatQueryString == "$format=json") {
+                        headers = { "Content-Type": "application/json;odata.metadata=minimal", "OData-Version": "4.0" };
+                    } else {
+                        // the formatQueryString should be in the format of "$format=xxx", xxx should be one of the application/json;odata.metadata=minimal(none or full)
+                        // set the content-type with the string xxx which stars from index 8.
+                        headers = { "Content-Type": formatQueryString.substring(8), "OData-Version": "4.0" };
+                    }
+
+                    // Call the success callback in the context of the parent window, instead of the IFRAME
+                    delay(function () {
+                        removeIFrame(iframe);
+                        success({ body: data, statusCode: 200, headers: headers });
+                    });
+                }
+            };
+
+            // Default to two minutes before timing out, 1000 ms * 60 * 2 = 120000.
+            var timeoutMS = (request.timeoutMS) ? request.timeoutMS : 120000;
+            timeoutId = window.setTimeout(handleTimeout, timeoutMS);
+
+            var queryStringParams = callbackParameterName + "=parent." + name;
+            if (formatQueryString) {
+                queryStringParams += "&" + formatQueryString;
+            }
+
+            var qIndex = url.indexOf("?");
+            if (qIndex === -1) {
+                url = url + "?" + queryStringParams;
+            } else if (qIndex === url.length - 1) {
+                url = url + queryStringParams;
+            } else {
+                url = url + "&" + queryStringParams;
+            }
+
+            iframe = createIFrame(url);
+        }
+
+        return result;
+    }
+};
+
+
+
+exports.canUseJSONP = canUseJSONP;
+exports.isAbsoluteUrl = isAbsoluteUrl;
+exports.isLocalUrl = isLocalUrl;
\ No newline at end of file


[11/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/TestLogger.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/TestLogger.svc b/odatajs/tests/common/TestLogger.svc
new file mode 100644
index 0000000..164d207
--- /dev/null
+++ b/odatajs/tests/common/TestLogger.svc
@@ -0,0 +1,852 @@
+/*
+ * 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.
+*/
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="DataJS.Tests.TestSynchronizerFactory" Service="DataJS.Tests.TestSynchronizer" %>
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Net;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Channels;
+    using System.ServiceModel.Description;
+    using System.ServiceModel.Dispatcher;
+    using System.ServiceModel.Web;
+    using System.Text;
+    using System.Threading;
+    using System.Xml;
+    
+    /// <summary>
+    /// This factory supports reconfiguring the service to allow incoming messages
+    /// to be larger than the default.
+    /// </summary>
+    public class TestSynchronizerFactory : WebScriptServiceHostFactory
+    {
+        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
+        {
+            var result = base.CreateServiceHost(serviceType, baseAddresses);
+            result.Opening += ServiceHostOpening;
+            return result;
+        }
+
+        private static void UpdateService(ServiceDescription description)
+        {
+            const long LargeMaxReceivedMessageSize = 1024 * 1024 * 16;
+            foreach (var endpoint in description.Endpoints)
+            {
+                var basic = endpoint.Binding as BasicHttpBinding;
+                if (basic != null)
+                {
+                    basic.MaxReceivedMessageSize = LargeMaxReceivedMessageSize;
+                }
+
+                var http = endpoint.Binding as WebHttpBinding;
+                if (http != null)
+                {
+                    http.MaxReceivedMessageSize = LargeMaxReceivedMessageSize;
+                }
+            }
+        }
+
+        private void ServiceHostOpening(object sender, EventArgs e)
+        {
+            UpdateService((sender as ServiceHost).Description);
+        }        
+    }
+
+    /// <summary>Use this class to log test activity.</summary>
+    /// <remarks>
+    /// A test run can be created by invoking CreateTestRun. With a test
+    /// run ID, the following operations can be invoked:
+    ///
+    /// - AddTestPages: adds test pages to be made available to future callers (typically to support tests from different files)
+    /// - SetTestNamePrefix: sets a string that will be prefixed to every test name in logs (typically to include a browser name)
+    /// - MarkInProgress: resets the test run to "in-progress" for another variation (typically to run a different browser)
+    /// - IsTestRunInProgress: checks whether it's still in progress
+    /// - GetTestRunResults: returns the test results in TRX format
+    /// - LogAssert: logs a single assertion in the current test for the run
+    /// - LogTestStart: logs a test that has begun execution
+    /// - LogTestDone: logs a test that has ended execution
+    /// - TestCompleted: logs that a test has completed execution; returns the next page with tests or an empty string
+    /// </remarks>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class TestSynchronizer
+    {
+        private static readonly Dictionary<string, TestRunContext> testRuns = new Dictionary<string, TestRunContext>();
+        private const string Inconclusive = "Inconclusive";
+        private const string InProgress = "InProgress";
+        private const string Failed = "Failed";
+        private const string Passed = "Passed";
+        private const string Completed = "Completed";
+        
+        /// <summary>
+        /// Adds test pages to the specified runs; replaces existing files (helps with reliablity when something
+        /// fails part-way).
+        /// </summary>
+        /// <remarks>This method is typically called by the test harness.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public int AddTestPages(string testRunId, string pages, string filter)
+        {
+            DisableResponseCaching();
+            
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                context.TestPages.Clear();
+                context.TestPages.AddRange(pages.Split(',').Select(page => page + "?testRunId=" + testRunId + (filter == null ? string.Empty : "?filter=" + filter)));
+                return context.TestPages.Count;
+            }
+        }
+
+        /// <remarks>This method is typically called by the test harness.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public string CreateTestRun()
+        {
+            DisableResponseCaching();
+
+            Guid value = Guid.NewGuid();
+            string result = value.ToString();
+            TestRunContext context = CreateTestRunContextWithId(value);
+            
+            lock (testRuns)
+            {
+                testRuns.Add(result, context);
+            }
+
+            return result;
+        }
+
+        /// <summary>Checks whether the test run is in progress.</summary>
+        /// <remarks>This method is typically called by the test harness.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public bool IsTestRunInProgress(string testRunId)
+        {
+            DisableResponseCaching();
+
+            TestRunContext context = GetTestRunContext(testRunId);
+            return context.TestRun.ResultSummary.Outcome == InProgress;
+        }
+        
+        /// <summary>Provides a list of all test runs being tracked.</summary>
+        [OperationContract]
+        [WebGet(ResponseFormat=WebMessageFormat.Json)]
+        public IEnumerable<string> GetActiveTestRuns()
+        {
+            DisableResponseCaching();
+
+            List<string> result;
+            lock (testRuns)
+            {
+                result = new List<string>(testRuns.Keys);
+            }
+            
+            return result;
+        }
+
+        /// <remarks>This method is typically called by the test harness.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Xml)]
+        public Message GetTestRunResults(string testRunId)
+        {
+            DisableResponseCaching();
+
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                TestRun run = context.TestRun;
+                this.CompleteTestRun(run);
+
+                TestRunXmlBodyWriter writer = new TestRunXmlBodyWriter(run);
+                return Message.CreateMessage(
+                    MessageVersion.None,
+                    OperationContext.Current.OutgoingMessageHeaders.Action,
+                    writer);
+            }
+        }
+
+        /// <remarks>This method is typically called by the test case.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public void LogAssert(string testRunId, bool pass, string message, string name, string actual, string expected)
+        {
+            DisableResponseCaching();
+
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                TestRun run = context.TestRun;
+                string prefixedName = context.TestNamePrefix + name;
+                TestResult result = run.TestResults.LastOrDefault(r => r.TestName == prefixedName);
+                if (result == null)
+                {
+                    throw new InvalidOperationException("Unable to find test " + prefixedName + " in run " + testRunId);
+                }
+                
+                result.DebugTrace.AppendLine(message);
+                if (!pass)
+                {
+                    result.ErrorMessages.AppendLine(message);
+                    result.ErrorMessages.AppendLine("Expected: " + expected);
+                    result.ErrorMessages.AppendLine("Actual: " + actual);
+                }
+            }
+        }
+        
+        /// <remarks>This method is typically called by the test case.</remarks>
+        [OperationContract]
+        [WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
+        public void LogBatch(string[] urls)
+        {
+            DisableResponseCaching();
+            
+            foreach (var url in urls)
+            {
+                Uri parsed = new Uri(OperationContext.Current.Channel.LocalAddress.Uri, url);
+                string methodName = parsed.Segments[parsed.Segments.Length - 1];
+                System.Reflection.MethodInfo method = this.GetType().GetMethod(methodName);
+                System.Reflection.ParameterInfo[] parameterInfos = method.GetParameters();
+                object[] parameters = new object[parameterInfos.Length];
+                System.Collections.Specialized.NameValueCollection query = System.Web.HttpUtility.ParseQueryString(parsed.Query);
+                for (int i = 0; i < parameters.Length; i++)
+                {
+                    object value = query[parameterInfos[i].Name];
+                    parameters[i] = Convert.ChangeType(value, parameterInfos[i].ParameterType, System.Globalization.CultureInfo.InvariantCulture);
+                }
+                
+                method.Invoke(this, parameters);
+            }            
+        }
+
+        /// <remarks>This method is typically called by the test case.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public void LogTestStart(string testRunId, string name, DateTime startTime)
+        {
+            DisableResponseCaching();
+            
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                TestRun run = context.TestRun;
+                string prefixedName = context.TestNamePrefix + name;
+                Guid testId = Guid.NewGuid();
+                Guid executionId = Guid.NewGuid();
+                Guid testListId = run.TestLists.Single().Id;
+                run.TestDefinitions.Add(new TestDefinition()
+                {
+                    Id = testId,
+                    Name = prefixedName,
+                    ExecutionId = executionId,
+                });
+                run.TestEntries.Add(new TestEntry()
+                {
+                    TestId = testId,
+                    ExecutionId = executionId,
+                    TestListId = testListId
+                });
+                run.TestResults.Add(new TestResult()
+                {
+                    ExecutionId = executionId,
+                    TestId = testId,
+                    TestListId = testListId,
+                    TestName = prefixedName,
+                    ComputerName = Environment.MachineName,
+                    StartTime = startTime,
+                    EndTime = startTime,
+                    TestType = Guid.Parse("13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"),
+                    Outcome = InProgress,
+                    // RelativeResultsDirectory?
+                });
+            }
+        }
+
+        /// <remarks>This method is typically called by the test case.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public void LogTestDone(string testRunId, string name, int failures, int total, DateTime endTime)
+        {
+            DisableResponseCaching();
+
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                TestRun run = context.TestRun;
+                string prefixedName = context.TestNamePrefix + name;
+                TestResult result = run.TestResults.LastOrDefault(r => r.TestName == prefixedName);
+                if (failures > 0)
+                {
+                    result.Outcome = Failed;
+                }
+                else
+                {
+                    result.Outcome = Passed;
+                }
+
+                result.EndTime = endTime;
+            }
+        }
+
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public void MarkInProgress(string testRunId)
+        {
+            DisableResponseCaching();
+
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                context.TestRun.ResultSummary.Outcome = InProgress;
+            }
+        }
+
+        /// <remarks>This method is typically called by the test harness.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public void SetTestNamePrefix(string testRunId, string prefix)
+        {
+            DisableResponseCaching();
+            
+            TestRunContext context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                context.TestNamePrefix = prefix;
+            }
+        }
+
+        /// <remarks>This method is typically called by the test case.</remarks>
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public string TestCompleted(string testRunId, int failures, int total)
+        {
+            DisableResponseCaching();
+            
+            var context = GetTestRunContext(testRunId);
+            lock (context)
+            {
+                string result;
+                if (context.TestPages.Count == 0)
+                {
+                    context.TestRun.ResultSummary.Outcome = Completed;
+                    result = "";
+                }
+                else
+                {
+                    result = context.TestPages[0];
+                    context.TestPages.RemoveAt(0);
+                }
+
+                return result;
+            }
+        }
+
+        private static TestRunContext CreateTestRunContextWithId(Guid value)
+        {
+            TestRun run = new TestRun();
+            run.Id = value;
+            run.Name = "Test run";
+            run.TestTimes.Creation = DateTime.Now;
+            run.TestTimes.Queueing = DateTime.Now;
+            run.TestLists.Add(new TestList()
+            {
+                Name = "All Results",
+                Id = Guid.NewGuid()
+            });
+
+            // For the time being, set up a fake test settings.
+            run.TestSettings.Id = Guid.NewGuid();
+
+            run.ResultSummary.Outcome = InProgress;
+
+            TestRunContext context = new TestRunContext();
+            context.TestRun = run;
+
+            return context;
+        }
+
+        private static void DisableResponseCaching()
+        {
+            WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.CacheControl] = "no-cache";            
+        }
+
+        private static TestRunContext GetTestRunContext(string testRunId)
+        {
+            if (testRunId == null)
+            {
+                throw new ArgumentNullException("testRunId");
+            }
+            
+            lock (testRuns)
+            {
+                // For an 0-filled GUID, allow create-on-demand to simplify ad-hoc testing.
+                // Something like:
+                // http://localhost:8989/tests/odata-qunit-tests.htm?testRunId=00000000-0000-0000-0000-000000000000
+                if (!testRuns.ContainsKey(testRunId))
+                {
+                    Guid value = Guid.Parse(testRunId);
+                    if (value == Guid.Empty)
+                    {
+                        TestRunContext context = CreateTestRunContextWithId(value);
+                        testRuns.Add(testRunId, context);
+                    }
+                }
+                
+                return testRuns[testRunId];
+            }
+        }
+
+        private void CompleteTestRun(TestRun run)
+        {
+            run.TestTimes.Finish = DateTime.Now;
+
+            // Fill counts in result object.
+            var summary = run.ResultSummary;
+            summary.Executed = 0;
+            summary.Error = 0;
+            summary.Failed = 0;
+            summary.Timeout = 0;
+            summary.Aborted = 0;
+            summary.Inconclusive = 0;
+            summary.PassedButRunAborted = 0;
+            summary.NotRunnable = 0;
+            summary.NotExecuted = 0;
+            summary.Disconnected = 0;
+            summary.Warning = 0;
+            summary.Passed = 0;
+            summary.Completed = 0;
+            summary.InProgress = 0;
+            summary.Pending = 0;
+
+            foreach (var testResult in run.TestResults)
+            {
+                string outcome = testResult.Outcome;
+                switch (outcome)
+                {
+                    case InProgress:
+                        summary.Executed++;
+                        summary.InProgress++;
+                        break;
+                    case Failed:
+                        summary.Executed++;
+                        summary.Completed++;
+                        summary.Failed++;
+                        break;
+                    case Passed:
+                        summary.Executed++;
+                        summary.Completed++;
+                        summary.Passed++;
+                        break;
+                    default:
+                        summary.Failed++;
+                        break;
+                }
+            }
+
+            summary.Total = run.TestResults.Count;
+
+            if (summary.Failed != 0)
+            {
+                summary.Outcome = Failed;
+            }
+            else if (summary.Total <= 0 || summary.Passed < summary.Total)
+            {
+                summary.Outcome = Inconclusive;
+            }
+            else
+            {
+                summary.Outcome = Passed;
+            }
+        }
+    }
+
+    public class TestRunContext
+    {
+        public TestRunContext()
+        {
+            this.TestPages = new List<string>();
+        }
+        
+        public TestRun TestRun { get; set; }
+        public string TestNamePrefix { get; set; }
+        public List<string> TestPages { get; set; }
+    }
+
+    public class TestResultWriter
+    {
+        private const string TestNamespace = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010";
+
+        public static void WriteTestRun(TestRun run, string path)
+        {
+            if (run == null)
+            {
+                throw new ArgumentNullException("run");
+            }
+            if (path == null)
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            using (XmlWriter writer = XmlWriter.Create(path))
+            {
+                WriteTestRun(run, path);
+            }
+        }
+
+        public static void WriteTestRun(TestRun run, XmlWriter writer)
+        {
+            if (run == null)
+            {
+                throw new ArgumentNullException("run");
+            }
+            if (writer == null)
+            {
+                throw new ArgumentNullException("writer");
+            }
+
+            writer.WriteStartElement("TestRun", TestNamespace);
+            writer.WriteGuidIfPresent("id", run.Id);
+            writer.WriteAttributeString("name", run.Name);
+            writer.WriteAttributeString("runUser", run.RunUser);
+
+            WriteTestSettings(run.TestSettings, writer);
+            WriteResultSummary(run.ResultSummary, writer);
+
+            // Write test definitions.
+            writer.WriteStartElement("TestDefinitions", TestNamespace);
+            foreach (var definition in run.TestDefinitions)
+            {
+                WriteTestDefinition(definition, writer);
+            }
+
+            writer.WriteEndElement();
+
+            // Write test lists.
+            writer.WriteStartElement("TestLists", TestNamespace);
+            foreach (var list in run.TestLists)
+            {
+                WriteTestList(list, writer);
+            }
+
+            writer.WriteEndElement();
+
+            // Write test entries.
+            writer.WriteStartElement("TestEntries", TestNamespace);
+            foreach (var entry in run.TestEntries)
+            {
+                WriteTestEntry(entry, writer);
+            }
+
+            writer.WriteEndElement();
+
+            // Write test results.
+            writer.WriteStartElement("Results", TestNamespace);
+            foreach (var result in run.TestResults)
+            {
+                WriteTestResults(result, writer);
+            }
+
+            writer.WriteEndElement();
+
+            // Close the test run element.
+            writer.WriteEndElement();
+        }
+
+        private static void WriteTestResults(TestResult result, XmlWriter writer)
+        {
+            if (result == null)
+            {
+                throw new ArgumentNullException("result");
+            }
+
+            writer.WriteStartElement("UnitTestResult", TestNamespace);
+            writer.WriteGuidIfPresent("testId", result.TestId);
+            writer.WriteGuidIfPresent("testListId", result.TestListId);
+            writer.WriteGuidIfPresent("executionId", result.ExecutionId);
+            writer.WriteGuidIfPresent("RelativeResultsDirectory", result.RelativeResultsDirectory);
+
+            writer.WriteAttributeString("testName", result.TestName);
+            writer.WriteAttributeString("computerName", result.ComputerName);
+            writer.WriteAttributeString("duration", result.Duration.ToString());
+            writer.WriteAttributeString("startTime", XmlConvert.ToString(result.StartTime));
+            writer.WriteAttributeString("endTime", XmlConvert.ToString(result.EndTime));
+            writer.WriteAttributeString("outcome", result.Outcome);
+
+            writer.WriteGuidIfPresent("testType", result.TestType);
+
+            if (result.DebugTrace.Length > 0)
+            {
+                writer.WriteStartElement("Output");
+
+                writer.WriteStartElement("DebugTrace");
+                writer.WriteString(result.DebugTrace.ToString());
+                writer.WriteEndElement();
+
+                writer.WriteStartElement("ErrorInfo");
+                writer.WriteStartElement("Message");
+                writer.WriteString(result.ErrorMessages.ToString());
+                writer.WriteEndElement();
+                writer.WriteEndElement();
+
+                writer.WriteEndElement();
+            }
+            
+            writer.WriteEndElement();
+        }
+
+        private static void WriteTestEntry(TestEntry entry, XmlWriter writer)
+        {
+            if (entry == null)
+            {
+                throw new ArgumentNullException("entry");
+            }
+
+            writer.WriteStartElement("TestEntry", TestNamespace);
+            writer.WriteGuidIfPresent("testId", entry.TestId);
+            writer.WriteGuidIfPresent("testListId", entry.TestListId);
+            writer.WriteGuidIfPresent("executionId", entry.ExecutionId);
+            writer.WriteEndElement();
+        }
+
+        private static void WriteTestList(TestList list, XmlWriter writer)
+        {
+            if (list == null)
+            {
+                throw new ArgumentNullException("list");
+            }
+
+            writer.WriteStartElement("TestList", TestNamespace);
+            writer.WriteAttributeString("name", list.Name);
+            writer.WriteGuidIfPresent("id", list.Id);
+            writer.WriteEndElement();
+        }
+
+        private static void WriteTestDefinition(TestDefinition definition, XmlWriter writer)
+        {
+            if (definition == null)
+            {
+                throw new ArgumentNullException("definition");
+            }
+
+            writer.WriteStartElement("UnitTest", TestNamespace);
+            writer.WriteAttributeString("name", definition.Name);
+            writer.WriteAttributeString("storage", definition.Storage);
+            writer.WriteGuidIfPresent("id", definition.Id);
+            
+            // There are more thing we could write here: DeploymentItems, Execution, TestMethod
+            
+            // This is the minimum needed to load the test in the IDE.
+            writer.WriteStartElement("Execution", TestNamespace);
+            writer.WriteGuidIfPresent("id", definition.ExecutionId);
+            writer.WriteEndElement();
+
+            writer.WriteStartElement("TestMethod", TestNamespace);
+            writer.WriteAttributeString("codeBase", "fake-test-file.js");
+            writer.WriteAttributeString("adapterTypeName", "Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+            writer.WriteAttributeString("className", "FakeClassName, TestLogging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
+            writer.WriteAttributeString("name", definition.Name);
+            writer.WriteEndElement();
+            
+            writer.WriteEndElement();
+        }
+
+        private static void WriteResultSummary(ResultSummary resultSummary, XmlWriter writer)
+        {
+            if (resultSummary == null)
+            {
+                throw new ArgumentNullException("resultSummary");
+            }
+
+            writer.WriteStartElement("ResultSummary", TestNamespace);
+            writer.WriteAttributeString("outcome", resultSummary.Outcome);
+
+            writer.WriteStartElement("Counters", TestNamespace);
+            
+            foreach (var p in typeof(ResultSummary).GetProperties())
+            {
+                if (p.PropertyType != typeof(int))
+                {
+                    continue;
+                }
+
+                int value = (int)p.GetValue(resultSummary, null);
+                string attributeName = p.Name;
+                attributeName = attributeName.Substring(0, 1).ToLowerInvariant() +  attributeName.Substring(1);
+                writer.WriteAttributeString(attributeName, value.ToString());
+            }
+            
+            writer.WriteEndElement();
+            writer.WriteEndElement();
+        }
+
+        private static void WriteTestSettings(TestSettings testSettings, XmlWriter writer)
+        {
+            if (testSettings == null)
+            {
+                throw new ArgumentNullException("testSettings");
+            }
+            
+            writer.WriteStartElement("TestSettings", TestNamespace);
+            writer.WriteAttributeString("name", testSettings.Name);
+            writer.WriteGuidIfPresent("id", testSettings.Id);
+            // There are more things we could write here.
+            writer.WriteEndElement();
+        }
+    }
+
+    public static class XmlWriterExtensions
+    {
+        public static void WriteGuidIfPresent(this XmlWriter writer, string attributeName, Guid value)
+        {
+            if (value != Guid.Empty)
+            {
+                writer.WriteAttributeString(attributeName, value.ToString());
+            }
+        }
+    }
+
+    public class TestRun
+    {
+        public TestRun()
+        {
+            this.TestDefinitions = new List<TestDefinition>();
+            this.TestLists = new List<TestList>();
+            this.TestEntries = new List<TestEntry>();
+            this.TestResults = new List<TestResult>();
+            this.ResultSummary = new ResultSummary();
+            this.TestTimes = new TestTimes();
+            this.TestSettings = new TestSettings();
+            
+            this.Id = Guid.NewGuid();
+            this.RunUser = Environment.UserDomainName + "\\" + Environment.UserName;
+        }
+
+        public Guid Id { get; set; }
+        public string Name { get; set; }
+        public string RunUser { get; set; }
+        public TestSettings TestSettings { get; set; }
+        public TestTimes TestTimes { get; set; }
+        public ResultSummary ResultSummary { get; set; }
+        public List<TestDefinition> TestDefinitions { get; set; }
+        public List<TestList> TestLists { get; set; }
+        public List<TestEntry> TestEntries { get; set; }
+        public List<TestResult> TestResults { get; set; }
+    }
+
+    public class TestSettings
+    {
+        public Guid Id { get; set; }
+        public string Name { get; set; }
+    }
+
+    public class TestTimes
+    {
+        public DateTime Creation { get; set; }
+        public DateTime Queueing { get; set; }
+        public DateTime Start { get; set; }
+        public DateTime Finish { get; set; }
+    }
+
+    public class ResultSummary
+    {
+        public string Outcome { get; set; }
+        public int Total { get; set; }
+        public int Executed { get; set; }
+        public int Error { get; set; }
+        public int Failed { get; set; }
+        public int Timeout { get; set; }
+        public int Aborted { get; set; }
+        public int Inconclusive { get; set; }
+        public int PassedButRunAborted { get; set; }
+        public int NotRunnable { get; set; }
+        public int NotExecuted { get; set; }
+        public int Disconnected { get; set; }
+        public int Warning { get; set; }
+        public int Passed { get; set; }
+        public int Completed { get; set; }
+        public int InProgress { get; set; }
+        public int Pending { get; set; }
+    }
+
+    public class TestDefinition
+    {
+        public string Name { get; set; }
+        public string Storage { get; set; }
+        public Guid Id { get; set; }
+        public Guid ExecutionId { get; set; }
+    }
+
+    public class TestList
+    {
+        public string Name { get; set; }
+        public Guid Id { get; set; }
+    }
+
+    public class TestEntry
+    {
+        public Guid TestId { get; set; }
+        public Guid ExecutionId { get; set; }
+        public Guid TestListId { get; set; }
+    }
+
+    public class TestResult
+    {
+        public TestResult()
+        {
+            this.DebugTrace = new StringBuilder();
+            this.ErrorMessages = new StringBuilder();
+        }
+        
+        public Guid ExecutionId { get; set; }
+        public Guid TestId { get; set; }
+        public string TestName { get; set; }
+        public string ComputerName { get; set; }
+        public TimeSpan Duration { get { return this.EndTime - this.StartTime; } }
+        public DateTime StartTime { get; set; }
+        public DateTime EndTime { get; set; }
+        public Guid TestType { get; set; }
+        public string Outcome { get; set; }
+        public Guid TestListId { get; set; }
+        public Guid RelativeResultsDirectory { get; set; }
+        public StringBuilder DebugTrace { get; set; }
+        public StringBuilder ErrorMessages { get; set; }
+    }
+
+    class TestRunXmlBodyWriter : BodyWriter
+    {
+        private readonly TestRun run;
+
+        public TestRunXmlBodyWriter(TestRun run)
+            : base(true)
+        {
+            this.run = run;
+        }
+
+        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
+        {
+            TestResultWriter.WriteTestRun(this.run, writer);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/TestSynchronizerClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/TestSynchronizerClient.js b/odatajs/tests/common/TestSynchronizerClient.js
new file mode 100644
index 0000000..157654e
--- /dev/null
+++ b/odatajs/tests/common/TestSynchronizerClient.js
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+// TestSynchronizer Client
+// Use to log assert pass/fails and notify mstest a test has completed execution
+
+(function (window, undefined) {
+    var testRunId = "";
+    var serviceRoot = "./common/TestLogger.svc/";
+    var recording = null;
+    var recordingLength = 0;
+    var maxStringLength = 8192;
+    var maxPostLength = 2097152;
+
+    var callTestSynchronizer = function (methodName, parameterUrl) {
+        /** Invokes a function on the test synchronizer.
+         * @param {String} [partialUrl] - 
+         * @returns {String} A response from the server, possibly null.
+        
+         * If the recording variable is assigned, then the call is logged
+         * but nothing is invoked.
+         */
+        
+
+        var partialUrl;
+        if (testRunId) {
+            partialUrl = methodName + "?testRunId=" + testRunId + "&" + parameterUrl;
+        }
+        else {
+            partialUrl = methodName + "?" + parameterUrl;
+        }
+
+        var url = serviceRoot + partialUrl;
+
+        if (recording) {
+            if (url.length > maxStringLength) {
+                url = url.substr(0, maxStringLength);
+            }
+
+            recordingLength += url.length;
+            if (recordingLength > maxPostLength) {
+                submitRecording();
+                recording = [];
+                recordingLength = url.length;
+            }
+
+            recording.push(url);
+            return null;
+        }
+
+        var xhr;
+        if (window.XMLHttpRequest) {
+            xhr = new window.XMLHttpRequest();
+        } else {
+            xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
+        }
+
+        xhr.open("GET", url, false);
+        xhr.send();
+        return xhr.responseText;
+    };
+
+    var getLogPrefix = function (result) {
+        /** Returns the log prefix for a given result
+         * @param {Boolean} result - Whether the result is pass or fail. If null, the log line is assumed to be diagnostic
+         */
+        return "[" + getShortDate() + "] " + (result === true ? "[PASS] " : (result === false ? "[FAIL] " : ""));
+    };
+
+    var getShortDate = function () {
+        /** Returns the current date and time formatted as "yyyy-mm-dd hh:mm:ss.nnn".*/
+        var padToLength = function (number, length) {
+            var result = number + "";
+            var lengthDiff = length - result.length;
+            for (var i = 0; i < lengthDiff; i++) {
+                result = "0" + result;
+            }
+
+            return result;
+        }
+
+        var date = new Date();
+        var day = padToLength(date.getDate(), 2);
+        var month = padToLength(date.getMonth() + 1, 2);
+        var year = date.getFullYear();
+
+        var hours = padToLength(date.getHours(), 2);
+        var minutes = padToLength(date.getMinutes(), 2);
+        var seconds = padToLength(date.getSeconds(), 2);
+        var milliseconds = padToLength(date.getMilliseconds(), 3);
+
+        return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliseconds;
+    };
+
+    var submitRecording = function () {
+        var body = { urls: recording };
+        postToUrl("LogBatch", body);
+    };
+
+    var postToUrl = function (methodName, body) {
+        /** POSTs body to the designated methodName.
+        */
+        var xhr;
+        if (window.XMLHttpRequest) {
+            xhr = new window.XMLHttpRequest();
+        } else {
+            xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
+        }
+
+        var url = serviceRoot + methodName;
+        xhr.open("POST", url, false);
+        xhr.setRequestHeader("Content-Type", "application/json");
+        xhr.send(window.JSON.stringify(body));
+        if (xhr.status < 200 || xhr.status > 299) {
+            throw { message: "Unable to POST to url.\r\n" + xhr.responseText };
+        }
+
+        return xhr.responseText;
+    }
+
+    function LogAssert(result, message, name, expected, actual) {
+        var parameterUrl = "pass=" + result + "&message=" + encodeURIComponent(message) + "&name=" + encodeURIComponent(name);
+
+        if (!result) {
+            parameterUrl += "&actual=" + encodeURIComponent(actual) + "&expected=" + encodeURIComponent(expected);
+        }
+
+        callTestSynchronizer("LogAssert", parameterUrl);
+    }
+
+    function LogTestStart(name) {
+        callTestSynchronizer("LogTestStart", "name=" + encodeURIComponent(name) + "&startTime=" + encodeURIComponent(getShortDate()));
+    }
+
+    function LogTestDone(name, failures, total) {
+        callTestSynchronizer("LogTestDone", "name=" + encodeURIComponent(name) + "&failures=" + failures + "&total=" + total + "&endTime=" + encodeURIComponent(getShortDate()));
+    }
+
+    function TestCompleted(failures, total) {
+        return callTestSynchronizer("TestCompleted", "failures=" + failures + "&total=" + total);
+    }
+
+    var extractTestRunId = function () {
+        /** Extracts the testRunId value from the window query string.
+         * @returns {String} testRunId, possibly empty.
+         */
+        var i, len;
+        var uri = window.location.search;
+        if (uri) {
+            var parameters = uri.split("&");
+            for (i = 0, len = parameters.length; i < len; i++) {
+                var index = parameters[i].indexOf("testRunId=");
+                if (index >= 0) {
+                    return parameters[i].substring(index + "testRunId=".length);
+                }
+            }
+        }
+
+        return "";
+    };
+
+    var init = function (qunit) {
+        /** Initializes the test logger synchronizer.
+        * @param qunit - Unit testing to hook into.
+        * If there is no testRunId present, the QUnit functions are left as they are.</remarks>
+        */
+        var logToConsole = function (context) {
+            if (window.console && window.console.log) {
+                window.console.log(context.result + ' :: ' + context.message);
+            }
+        };
+
+        testRunId = extractTestRunId();
+        if (!testRunId) {
+            qunit.log = logToConsole;
+        } else {
+            recording = [];
+            qunit.log = function (context) {
+                logToConsole(context);
+
+                var name = qunit.config.current.testName;
+                if (!(context.actual && context.expected)) {
+                    context.actual = context.result;
+                    context.expected = true;
+                }
+                LogAssert(context.result, getLogPrefix(context.result) + context.message, name, window.JSON.stringify(context.expected), window.JSON.stringify(context.actual));
+            };
+
+            qunit.testStart = function (context) {
+                LogTestStart(context.name);
+            };
+
+            qunit.testDone = function (context) {
+                LogTestDone(context.name, context.failed, context.total);
+            }
+
+            qunit.done = function (context) {
+                submitRecording();
+                recording = null;
+
+                var nextUrl = TestCompleted(context.failed, context.total);
+                nextUrl = JSON.parse(nextUrl).d;
+                if (nextUrl) {
+                    window.location.href = nextUrl;
+                }
+            }
+        }
+    };
+
+    window.TestSynchronizer = {
+        init: init
+    };
+})(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/common.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/common.js b/odatajs/tests/common/common.js
new file mode 100644
index 0000000..8151fc1
--- /dev/null
+++ b/odatajs/tests/common/common.js
@@ -0,0 +1,25 @@
+/*
+ * 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.
+*/
+(function (window, undefined) {
+        window.temp = window.odatajs;
+        window.temp.store = window.odatajs.store;
+        window.temp.cache = window.odatajs.cache;
+        window.odatajs = window.temp;
+        delete window.temp;
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/djstest-browser.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/djstest-browser.js b/odatajs/tests/common/djstest-browser.js
new file mode 100644
index 0000000..366ca33
--- /dev/null
+++ b/odatajs/tests/common/djstest-browser.js
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+
+// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
+// we define the @namespace djstest here instead of the a @module name djstest
+
+/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
+ * @namespace djstest
+ */
+
+
+var init = function init () {
+
+    var localDjstest = {};
+
+    // Initialize indexedDB if the window object is available
+    localDjstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
+
+    /** Cleans all the test data saved in the IndexedDb database.
+     * @param {Array} storeNames - Array of store objects with a property that is the name of the store
+     * @param {Function} done - Callback function
+     */
+    localDjstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
+        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
+
+        function deleteObjectStores(db) {
+            for ( var i = 0 ; i < db.objectStoreNames.length ; i ++) {
+                db.deleteObjectStore(db.objectStoreNames[i]);
+            }
+        }
+        var job;
+
+        if (localDjstest.indexedDB) {
+            job = new djstest.Job();
+            for ( var i = 0 ; i < storeObjects.length ; i ++) {
+                storeObject = storeObjects[i];
+                job.queue((function (storeObject) {
+                    return function (success, fail) {
+                        var dbname = "_datajs_" + storeObject.name;
+                        var request = localDjstest.indexedDB.open(dbname);
+                        request.onsuccess = function (event) {
+                            var db = request.result;
+
+                            if ("setVersion" in db) {
+                                var versionRequest = db.setVersion("0.1");
+                                versionRequest.onsuccess = function (event) {
+                                    var transaction = versionRequest.transaction;
+                                    transaction.oncomplete = function () {
+                                        db.close();
+                                        success();
+                                    };
+                                    deleteObjectStores(db);
+                                };
+                                versionRequest.onerror = function (e) {
+                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
+                                    fail();
+                                };
+                                return;
+                            }
+
+                            // new api cleanup
+                            db.close();
+                            var deleteRequest = localDjstest.indexedDB.deleteDatabase(dbname);
+                            deleteRequest.onsuccess = function (event) {
+                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
+                                success();
+                            };
+                            deleteRequest.onerror = function (e) {
+                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
+                                fail();
+                            };
+                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
+                        };
+
+                        request.onerror = function (e) {
+                            djstest.fail(e.code + ": " + e.message);
+                        };
+                    };
+                })(storeObject));
+            }
+        }
+
+        if (job) {
+            job.run(function (succeeded) {
+                if (!succeeded) {
+                    djstest.fail("cleanup job failed");
+                }
+                done();
+            });
+        }
+        else {
+            done();
+        }
+    };
+
+
+    // Disable caching to ensure that every test-related AJAX request is actually being sent,
+    // and set up a default error handler
+    if (typeof window !== undefined) {
+        $.ajaxSetup({
+            cache: false,
+            error: function (jqXHR, textStatus, errorThrown) {
+                // Work around bug in IE-Mobile on Windows Phone 7
+                if (jqXHR.status !== 1223) {
+                    var err = {
+                        status: jqXHR.status,
+                        statusText: jqXHR.statusText,
+                        responseText: jqXHR.responseText
+                    };
+                    djstest.fail("AJAX request failed with: " + djstest.toString(err));
+                }
+                djstest.done();
+            }
+        });
+    }
+    return localDjstest;
+};
+
+//export djstest
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    if ( window.djstest === undefined) {
+        window.djstest = init();
+    } else {
+        var tmp = init();
+        $.extend( window.djstest,tmp);
+    }
+} else {
+    //expose in commonjs style
+    module.exports = init();
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/djstest.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/djstest.js b/odatajs/tests/common/djstest.js
new file mode 100644
index 0000000..5dda9ff
--- /dev/null
+++ b/odatajs/tests/common/djstest.js
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+
+
+// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
+// we define the @namespace djstest here instead of the a @module name djstest
+
+/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
+ * @namespace djstest
+ */
+
+
+var init = function init () {
+    var djstest = {};
+  
+
+    /** Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.
+     * @class Job
+     * @constructor
+     * @returns {Object} Job object
+     */
+    djstest.Job = function () {
+        
+        var currentTask = -1;
+        var tasks = [];
+
+        var failedTasks = 0;
+
+        /** Adds a function to the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queue
+         * @param {Function} fn - Function to execute.
+         */
+        this.queue = function (fn) {
+            
+            tasks.push(fn);
+        };
+
+        /** Adds a function to the front of the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queueNext
+         * @param {Function} fn - Function to execute.
+         */
+        this.queueNext = function (fn) {
+        
+            if (currentTask < 0) {
+                tasks.unshift(fn);
+            } else {
+                tasks.splice(currentTask + 1, 0, fn);
+            }
+        };
+
+        /** Starts the execution of this job.
+         * @method djstest.Job#run
+         * @param {Function} done - Callback invoked when the job has finished executing all of its enqueued tasks.
+         */
+        this.run = function (done) {
+            /// This method does nothing if called on a unit of work that is already executing.
+            if (currentTask >= 0) {
+                return;
+            }
+
+            if (tasks.length === 0) {
+                done(true);
+                return;
+            }
+
+            /**
+             * @method djstest.Job~makeTaskDoneCallBack
+            */
+            function makeTaskDoneCallBack(failed) {
+                return function () {
+                    // Track the failed task and continue the execution of the job. 
+                    if (failed) {
+                        failedTasks++;
+                    }
+                    currentTask++;
+                    if (currentTask === tasks.length) {
+                        done(failedTasks === 0);
+                    } else {
+                        runNextTask();
+                    }
+                };
+            }
+
+            /** Executes the next function in the queue.
+             * @method djstest.Job~runNextTask
+            */
+            function runNextTask() {
+                defer(function () {
+                    try {
+                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
+                    } catch (e) {
+                        makeTaskDoneCallBack(true)();
+                    }
+                });
+            }
+
+            currentTask = 0;
+            runNextTask();
+        };
+    };
+
+    /** Defers the execution of an arbitrary function that takes no parameters.
+     * @memberof djstest
+     * @inner
+     * @param {Function} fn - Function to schedule for later execution.
+     */
+    function defer(fn) {
+        setTimeout(fn, 0);
+    }
+
+    /** Exposes date values for Date objects to facilitate debugging
+     * @memberof djstest
+     * @inner
+     * @param {Object} data - The object to operate on
+     */
+    function exposeDateValues(data) {
+     
+        if (typeof data === "object") {
+            if (data instanceof Date) {
+                data.__date__ = data.toUTCString();
+            }
+            else {
+                for (var prop in data) {
+                    exposeDateValues(data[prop]);
+                }
+            }
+        }
+
+        return data;
+    }
+
+    /** Determines the name of a function.
+     * @memberof djstest
+     * @inner
+     * @param {String} text - Function text.
+     * @returns {String} The name of the function from text if found; the original text otherwise.
+     */
+    function extractFunctionName(text) {
+
+        var index = text.indexOf("function ");
+        if (index < 0) {
+            return text;
+        }
+
+        var nameStart = index + "function ".length;
+        var parensIndex = text.indexOf("(", nameStart);
+        if (parensIndex < 0) {
+            return text;
+        }
+
+        var result = text.substr(nameStart, parensIndex - nameStart);
+        if (result.indexOf("test") === 0) {
+            result = result.substr("test".length);
+        }
+
+        return result;
+    }
+
+    /** Removes metadata annotations from the specified object.
+     * @memberof djstest
+     * @inner
+     * @param data - Object to remove metadata from; possibly null.
+     */
+    function removeMetadata(data) {
+
+        if (typeof data === "object" && data !== null) {
+            delete data.__metadata;
+            for (var prop in data) {
+                removeMetadata(data[prop]);
+            }
+        }
+    }
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
+
+        if (disable !== true) {
+            djstest.addTest(fn, name, arg, timeout);
+        }
+    };
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addTest = function (fn, name, arg, timeout) {
+        if (!name) {
+            name = extractFunctionName(fn.toString());
+        }
+
+        test(name, function () {
+            if (!timeout) {
+                timeout = 20000;
+            }
+
+            QUnit.config.testTimeout = timeout;
+            QUnit.stop();
+            fn.call(this, arg);
+        });
+    };
+
+    /** Asserts that a condition is true.
+     * @param {Boolean} test - Condition to test.
+     * @param {String} message - Text message for condition being tested.
+     */
+    djstest.assert = function (test, message) {
+        
+        QUnit.ok(test, message);
+    };
+
+    /** Asserts that the values of the expected and actualobjects are equal.
+     * @memberof djstest
+     * @inner
+     */
+    djstest.assertAreEqual = function (actual, expected, message) {
+        QUnit.equal(actual, expected, message);
+    };
+
+    /** Asserts that the actual and expected objects are the same.
+     */
+    djstest.assertAreEqualDeep = function (actual, expected, message) {
+        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
+    };
+
+    /** Asserts that the actual and expected objects are the same but removes the metadata bevore
+     */
+    djstest.assertWithoutMetadata = function (actual, expected, message) {
+        removeMetadata(actual);
+        removeMetadata(expected);
+        djstest.assertAreEqualDeep(actual, expected, message);
+    };
+
+    /** Calls each async action in asyncActions, passing each action a function which keeps a count and
+     * calls the passed done function when all async actions complete
+     * @param {Array} asyncActions -Array of asynchronous actions to be executed, 
+     * each taking a single parameter - the callback function to call when the action is done.</param>
+     * @param {Function} done - Function to be executed in the last async action to complete.
+     */
+    djstest.asyncDo = function (asyncActions, done) {
+
+        var count = 0;
+        var doneOne = function () {
+            count++;
+            if (count >= asyncActions.length) {
+                done();
+            }
+        };
+
+        if (asyncActions.length > 0) {
+            for ( var i = 0; i < asyncActions.length; i++) {
+                asyncActions[i](doneOne);
+            }
+        } else {
+            done();
+        }
+    };
+
+    /** Makes a deep copy of an object.
+     */
+    djstest.clone = function (object) {
+        if ( object === undefined ) {
+            return undefined;
+        } else if (object === null) {
+            return null;
+        } else if (typeof(object) !== 'object') {
+            return object;
+        } else {
+            var ret = {};
+            for(var key in object) {
+                if(object.hasOwnProperty(key)) {
+                    ret[key] = this.clone(object[key]);
+                }
+            }
+            return ret;
+        }
+        throw("Error cloning an object");
+    };
+
+    /** Destroys the cache and then completes the test
+     * @param cache - The cache to destroy
+     */
+    djstest.destroyCacheAndDone = function (cache) {
+     
+        cache.clear().then(function () {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
+            djstest.done();
+        });
+    };
+
+    /** Indicates that the currently running test has finished.
+     */
+    djstest.done = function () {
+      
+        QUnit.start();
+    };
+
+    /** Test passes if and only if an exception is thrown.
+     */
+    djstest.expectException = function (testFunction, message) {
+     
+        try {
+            testFunction();
+            djstest.fail("Expected exception but function succeeded: " + " " + message);
+        }
+        catch (e) {
+            // Swallow exception.
+            djstest.pass("Thrown exception expected");
+        }
+    };
+
+    /** Indicates the expected number of asserts, fails test if number is not met.
+     * @param {Number} asserts - Number of asserts expected in test.
+     */
+    djstest.assertsExpected = function (asserts) {
+        
+        expect(asserts);
+    };
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.fail = function (message) {
+
+        QUnit.ok(false, message);
+    };
+
+    /** Returns a function that when invoked will fail this test and be done with it.
+     * @param {String} message - Failure message.
+     * @param {Function} [cleanupCallback] - 
+     * @returns {Function} A new function.
+     */
+    djstest.failAndDoneCallback = function (message, cleanupCallback) {
+
+        return function (err) {
+            message = "" + message + (err) ? JSON.stringify(err) : "";
+            djstest.fail(message);
+            if (cleanupCallback) {
+                try {
+                    cleanupCallback();
+                } catch (e) {
+                    djstest.fail("error during cleanupCallback: " + JSON.stringify(e));
+                }
+            }
+
+            djstest.done();
+        };
+    };
+
+    /** Logs a test message.
+     * @param {String} message - Test message.
+     */
+    djstest.log = function (message) {
+
+        var context = { result: true, actual: true, expected: true, message: message };
+        QUnit.log(context);
+    };
+
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.pass = function (message) {
+        QUnit.ok(true, message);
+    };
+
+    /** Dumps the object as a string
+     * @param {Object} obj - Object to dump
+     */
+    djstest.toString = function (obj) {
+
+        return QUnit.jsDump.parse(obj);
+    };
+
+    /** Executes the function, pausing test execution until the callback is called
+     * @param {Function} fn - Function to execute; takes one parameter which is the callback
+     * This function is typically used in asynchronous setup/teardown methods</remarks>
+     */
+    djstest.wait = function (fn) {
+        QUnit.stop();
+        fn(function () {
+            QUnit.start();
+        });
+    };
+
+    return djstest;
+};
+
+//export djstest
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    if ( window.djstest === undefined) {
+        window.djstest = init();
+    } else {
+        var tmp = init();
+        $.extend( window.djstest,tmp);
+    }
+} else {
+    //expose in commonjs style
+    module.exports = init();
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/mockHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/mockHttpClient.js b/odatajs/tests/common/mockHttpClient.js
new file mode 100644
index 0000000..f5b2bd0
--- /dev/null
+++ b/odatajs/tests/common/mockHttpClient.js
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+ 
+//mockHttpClient.js
+//this object allows for associating a uri with a requestVerfier and mock responses that will be sent back to the client of the httpStack.  
+//It can be used to replace OData's httpClient for testing purposes.
+//
+//RequestVerifiers
+//
+//    A request verifier is a function associated to a particular URI that will be executed by the mockHttpClient when it receives a request with the matching URI.
+//    the callback receives as its only parameter the request object passed to the mockHttpClient.
+//
+//    To register a request verifier, simply do 
+//        
+//            MockHttpClient.addRequestVerifier("http://someUri", function(request) {
+//                djstest.assertAreEqual(request.requestUri,"http://someUri");
+//            }
+//
+//Responses
+//    Mock responses can be associated with a particular URI.  When the MockHttpClient receives a request with a URI mapped to a response, then it will, 
+//    depending on the response status code invoke either the success or the error callbacks. 
+//
+//    To register a response,
+//       
+//           MockHttpClient.addResponse("http://someUri", {status: 200, body:"some body"});
+//
+//Exceptions
+//    MockHttpClient will throw an exception if it receives a request to a URI that is not mapped to either a request verifier or a response.
+//
+
+function init(window, undefined) {
+
+    var httpClient = {};
+
+    var responses = {};
+    var requestVerifiers = {};
+
+    httpClient.addRequestVerifier = function (uri, verifier) {
+        requestVerifiers[uri] = verifier;
+        return this;
+    };
+
+    httpClient.addResponse = function (uri, response) {
+        responses[uri] = response;
+        return this;
+    };
+
+    httpClient.async = false;
+
+    httpClient.clear = function () {
+        /** Clears all registered responses and verifiers.
+         * @returns this client
+         */
+        responses = {};
+        requestVerifiers = {};
+        this.async = false;
+        return this;
+    };
+
+    httpClient.request = function (request, success, error) {
+        var uri = request.requestUri;
+        var verifier = requestVerifiers[uri];
+        var response = responses[uri];
+
+        if (verifier === undefined) {
+            verifier = requestVerifiers["*"];
+        }
+
+        if (response === undefined) {
+            response = responses["*"];
+        }
+
+        if (!verifier && !response) {
+            throw { message: "neither verifier or response defined for uri: " + uri };
+        }
+
+        if (verifier) {
+            verifier(request);
+        }
+
+        if (response) {
+            response.requestUri = uri;
+            if (response.statusCode >= 200 && response.statusCode <= 299) {
+                if (this.async) {
+                    setTimeout(function () {
+                        success(response);
+                    });
+                } else {
+                    success(response);
+                }
+            } else {
+                if (this.async) {
+                    setTimeout(function () {
+                        error({ message: "failed test response", request: request, response: response });
+                    });
+                }
+                else {
+                    error({ message: "failed test response", request: request, response: response });
+                }
+            }
+        }
+    };
+
+    httpClient.setAsync = function (value) {
+        this.async = value;
+        return this;
+    };
+
+    return httpClient;
+}
+
+
+
+if (typeof window !== 'undefined') {
+    //in browser call init() directly window as context
+    window.MockHttpClient = init(window);
+} else {
+    //expose function init to be called with a custom context
+    module.exports.init = init;
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/common/mockXMLHttpRequest.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/common/mockXMLHttpRequest.js b/odatajs/tests/common/mockXMLHttpRequest.js
new file mode 100644
index 0000000..fdd6026
--- /dev/null
+++ b/odatajs/tests/common/mockXMLHttpRequest.js
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+ // mockXMLHttpRequest.js
+//
+// This file provides a window.MockXMLHttpRequest object that can be used
+// to replace or wrap the browser's XMLHttpRequest object for testing.
+//
+// Typically the object is installed, a test run, and then the original
+// object restored. The addResponse and addRequest verifier can be
+// used to set up callbacks; reset is used to clear those values.
+//
+// For a sample demonstrating how to use this functionality, see
+// the httpClientSendRequestTest test in odata-net-tests.js.
+
+(function (window, undefined) {
+
+    if (!window.MockXMLHttpRequest) {
+        window.MockXMLHttpRequest = {};
+    }
+
+    var mockXMLHttpRequest = window.MockXMLHttpRequest;
+
+    var responses = {};
+    var verifiers = {};
+
+    mockXMLHttpRequest.addResponse = function (uri, response) {
+        /** Adds a new response to be returned for the specified uri (* for 'anything').
+         * @param {String} uri - URI to match (* to match anything not otherwise specified).
+         * @param {Object} response - Response object.
+         */
+        responses = responses || {};
+        responses[uri] = response;
+
+        return this;
+    };
+
+    mockXMLHttpRequest.addRequestVerifier = function (uri, verifier) {
+        /** Adds a new request verifier to be invoked for the specified uri (* for 'anything').
+         * @param {String} uri - URI to match (* to match anything not otherwise specified).
+         * @param {Function} response - Verifier callback that takes the request.
+        */
+        verifiers = verifiers || {};
+        verifiers[uri] = verifier;
+
+        return this;
+    };
+
+    mockXMLHttpRequest.reset = function () {
+        /** Resets all configuration from the mock XHR object.
+        */
+
+        responses = {};
+        verifiers = {};
+
+        mockXMLHttpRequest.onCreate = undefined;
+        mockXMLHttpRequest.onAfterSend = undefined;
+
+        return this;
+    };
+
+    var xmlHttpRequest = function () {
+        //properties
+        this.readyState = 0;
+        this.responseXML = undefined;
+
+        //events
+        this.ontimeout = undefined;
+        this.onreadystatechange = undefined;
+
+        if (mockXMLHttpRequest.onCreate) {
+            mockXMLHttpRequest.onCreate(this);
+        }
+    };
+
+    xmlHttpRequest.prototype.open = function (method, url, async, user, password) {
+        if (!method) {
+            throw { method: "method parameter is not defined, empty, or null " };
+        }
+        if (!url) {
+            throw { message: "url parameter is not defined, empty, or null " };
+        }
+
+        this._request = {
+            headers: {},
+            url: url,
+            method: method,
+            async: async,
+            user: user,
+            password: password
+        };
+    };
+
+    xmlHttpRequest.prototype.getAllResponseHeaders = function () {
+        if (!this._response) {
+            throw { message: "_response property is undefined, did you forget to call send() or map the request url to a response?" };
+        }
+
+        var result = "";
+        var header;
+        for (header in this._response.headers) {
+            result = result + header + ": " + this._response.headers[header] + "\n\r";
+        }
+        //remove trailing LFCR
+        return result.substring(0, result.length - 2);
+    };
+
+    xmlHttpRequest.prototype.getResponseHeader = function (header) {
+        if (!this._response) {
+            throw { message: "_response property is undefined, did you forget to call send() or map the request url to a response?" };
+        }
+        return this._response.headers[header];
+    };
+
+    xmlHttpRequest.prototype.abort = function () {
+        //do nothing for now.
+    };
+
+    xmlHttpRequest.prototype.setRequestHeader = function (header, value) {
+        if (!this._request) {
+            throw { message: "_request property is undefined, did you forget to call open() first?" };
+        }
+        this._request.headers[header] = value;
+    };
+
+    xmlHttpRequest.prototype.send = function (data) {
+        if (!this._request) {
+            throw { message: "_request property is undefined, did you forget to call open() first?" };
+        }
+
+        if (this._request.headers["MockNoOp"]) {
+            return;
+        }
+
+        if (this._request.headers["MockTimeOut"]) {
+            if (!this.timeout) {
+                throw { message: "timeout property is not set" };
+            }
+
+            if (this.ontimeout) {
+                (function (xhr) {
+                    setTimeout(function () {
+                        xhr.ontimeout();
+                    }, xhr.timeout);
+                })(this);
+            }
+            return;
+        }
+
+        var url = this._request.url;
+        var verifier = verifiers[url];
+        var response = responses[url];
+
+        if (!verifier) {
+            verifier = verifiers["*"];
+        }
+
+        if (!response) {
+            response = responses["*"];
+        }
+
+        if (!verifier && !response) {
+            throw { message: "neither verifier or response defined for url: " + url };
+        }
+
+        this._request.body = data;
+
+        if (verifier) {
+            verifier(this._request);
+        }
+
+        if (response) {
+            // Execute the respone after a 30ms delay.
+            this._response = response;
+            sendResponseDelay(this, response, 60);
+        }
+    };
+
+    var sendResponseDelay = function (xhr, response, delay) {
+        setTimeout(function () {
+            xhr.status = response.status;
+            xhr.responseText = response.body;
+            xhr.responseBody = response.body;
+
+            xhr.readyState = 4;
+            if (xhr.onreadystatechange) {
+                xhr.onreadystatechange();
+                if (mockXMLHttpRequest.onAfterSend) {
+                    mockXMLHttpRequest.onAfterSend();
+                }
+            }
+        }, delay);
+    };
+
+    mockXMLHttpRequest.XMLHttpRequest = xmlHttpRequest;
+
+})(this);


[07/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-functional-tests.js b/odatajs/tests/odata-cache-functional-tests.js
new file mode 100644
index 0000000..ac63460
--- /dev/null
+++ b/odatajs/tests/odata-cache-functional-tests.js
@@ -0,0 +1,631 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var CustomDataSource = function (baseUri) {
+        this.baseUri = baseUri;
+    };
+
+    CustomDataSource.prototype.read = function (index, count, success, error) {
+        var that = this;
+        var url = this.baseUri + "?$skip=" + index + "&$top=" + count;
+        $(this).triggerHandler("request", { requestUri: url });
+        $.ajax({
+            url: url,
+            dataType: "json",
+            success: function (results) {
+                $(that).triggerHandler("success", { data: results });
+                success(results);
+            },
+            error: error
+        });
+    };
+
+    CustomDataSource.prototype.count = function (success, error) {
+        $.ajax({
+            url: "./endpoints/CustomDataService.svc/Count",
+            dataType: "json",
+            success: success,
+            error: error
+        });
+    },
+    CustomDataSource.prototype.toString = function () {
+        return this.baseUri;
+    };
+
+    var sources = [
+        { source: "./endpoints/FoodStoreDataServiceV4.svc/Foods", countSupported: true },
+        { source: new CustomDataSource("./endpoints/CustomDataService.svc/ReadRange"), countSupported: true }
+    ];
+
+    var itemsInCollection = 16;
+
+    // Cache config variations for single readRange with fixed skip/take that spans the entire collection
+    var pageSizes = [
+        1,
+        4,  // factor of total, <= server page size
+        5,  // non-factor of total, <= server page size
+        6,  // non-factor of total, > server page size
+        8,  // factor of total, > server page size
+        itemsInCollection,
+        itemsInCollection + 1
+    ];
+
+    var cacheSizes = [
+        -5,           // All you can store 
+         0,           // Store nothing
+         1024,        // 1 KB
+         2.5 * 1024,  // 2.5 KB
+         100 * 1024,  // 10 KB
+         512 * 1024,  // 512 KB
+         100 * 1024 * 1024, // 100 MB
+         undefined    // Default to 1 MB
+    ];
+
+    // Skip/take variations for single readRange with fixed cache config
+    var fixedPageSize = 6;
+
+    var skipValues = [
+        0,
+        fixedPageSize - 1,
+        fixedPageSize,
+        fixedPageSize + 1,
+        fixedPageSize * 2,
+        itemsInCollection + 1,
+        itemsInCollection + fixedPageSize + 1
+    ];
+
+    var takeValues = [
+        0,
+        fixedPageSize - 1,
+        fixedPageSize,
+        fixedPageSize + 1,
+        fixedPageSize * 2,
+        itemsInCollection + 1
+    ];
+
+    // Skip/take variations for multiple readRanges with fixed cache config
+    var multipleReads = [
+        { skip: 1, take: 2 },   // page 1
+        {skip: 2, take: 7 },   // page 1, 2
+        {skip: 3, take: 10 },  // page 1, 2, 3
+        {skip: 6, take: 2}    // page 2
+    ];
+
+    var invalidSkipValues = [-5, NaN, undefined, Infinity, "not a valid value"];
+    var invalidTakeValues = [-5, NaN, undefined, Infinity, "not a valid value"];
+    var invalidPageSizes = [-5, NaN, Infinity, 0, "not a valid value"];
+
+    // Prefetchsize variations for a single readRange
+    var prefetchSizes = [
+        -5,
+        1,
+        5,
+        itemsInCollection,
+        itemsInCollection + 1
+    ];
+
+    var expectException = function (cache) {
+        djstest.assert(false, "We should not get here because the an exception is expected.");
+        djstest.destroyCacheAndDone(cache);
+    };
+
+    var makeUnexpectedErrorHandler = function (cache) {
+        return function (err) {
+            djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+            if (cache) {
+                djstest.destroyCacheAndDone(cache);
+            } else {
+                djstest.done();
+            }
+        };
+    };
+
+    var validateExpectedRange = function (cache, data, source, skipValue, takeValue, finished) {
+        /** Validates the data returned by readRange
+         * @param {Object} cache - The cache object
+         * @param {Object} data - The data returned by the cache
+         * @param {Object} source - The base URI of the feed, or the custom data source
+         * @param {Integer} skipValue - The skip value
+         * @param {Integer} takeValue - The take value
+         * @param {Function} finished - Callback function called after data is verified
+         */
+        var assertData = function (expectedData) {
+            djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+            finished();
+        };
+
+        if (typeof source === "string") {
+            var expectedRangeUrl = source + "?$skip=" + skipValue + "&$top=" + takeValue;
+            window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, assertData);
+        } else {
+            source.read(skipValue, takeValue, assertData);
+        }
+    };
+
+    var onidleValidation = function () {
+        djstest.assert(true, "expected call to onidle");
+        djstest.done();
+    };
+
+    var createSingleReadTestName = function (params) {
+        return "Testing readRange of " + params.source + " [skip " + params.skip + " take " + params.take + "] with pageSize " +
+            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+    };
+
+    var createMultipleReadTestName = function (params) {
+        return "Testing readRange of " + params.source + " [skip " + params.firstSkip + " take " + params.firstTake + ", " +
+            (params.destroyCacheBetweenReads ? "cache.destroy(), " : "") +
+            "skip " + params.secondSkip + " take " + params.secondTake + "] with pageSize " +
+            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+    };
+
+    var dataCacheSingleReadRangeTest = function (params) {
+        djstest.assertsExpected(2);
+        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+        if (params.mechanism) {
+            options.mechanism = params.mechanism;
+        }
+
+        var cache = this.createAndAddCache(options);
+        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+        cache.readRange(params.skip, params.take).then(function (data) {
+            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+            validateExpectedRange(cache, data, params.source, params.skip, params.take, function () {
+                djstest.destroyCacheAndDone(cache);
+            });
+        }, makeUnexpectedErrorHandler(cache));
+    };
+
+    var dataCacheParallelReadRangeTest = function (params) {
+        djstest.assertsExpected(2);
+        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+        var cache = this.createAndAddCache(options);
+
+        var firstReadRange = function (finished) {
+            cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
+                validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, finished);
+            }, makeUnexpectedErrorHandler(cache));
+        };
+
+        var secondReadRange = function (finished) {
+            cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
+                validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, finished);
+            }, makeUnexpectedErrorHandler(cache));
+        };
+
+        djstest.asyncDo([firstReadRange, secondReadRange], function () {
+            djstest.destroyCacheAndDone(cache);
+        });
+    };
+
+    var dataCacheSerialReadRangeTest = function (params) {
+        djstest.assertsExpected(4);
+        var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+        var secondRead = function () {
+            session.clear();
+            cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
+                cacheOracle.verifyRequests(session.requests, session.responses, params.secondSkip, params.secondTake, "Second readRange requests");
+                validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, djstest.done);
+            }, makeUnexpectedErrorHandler(cache));
+        };
+
+        var cache = this.createAndAddCache(options);
+        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+        cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
+            cacheOracle.verifyRequests(session.requests, session.responses, params.firstSkip, params.firstTake, "First readRange requests");
+            validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, function () {
+                if (params.destroyCacheBetweenReads === true) {
+                    cache.clear().then(function () {
+                        cacheOracle.clear();
+                        secondRead();
+                    }, function (err) {
+                        djstest.fail("Error destroying the cache: " + djstest.toString(err));
+                    });
+                } else {
+                    secondRead();
+                }
+            });
+        }, makeUnexpectedErrorHandler(cache));
+    };
+
+    var dataCachePrefetchTest = function (params) {
+        djstest.assertsExpected(2);
+        var options = {
+            name: "cache" + new Date().valueOf(),
+            source: params.source,
+            pageSize: params.pageSize,
+            prefetchSize: params.prefetchSize,
+            cacheSize: params.cacheSize,
+            user: params.user,
+            password: params.password
+        };
+
+        var cache = this.createAndAddCache(options);
+        var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+        var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+
+        cache.readRange(params.skip, params.take).then(function (data) {
+            cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+            session.clear();
+        }, makeUnexpectedErrorHandler(cache));
+
+        cache.onidle = function () {
+            var prefetchSize = params.prefetchSize < 0 ? itemsInCollection : params.prefetchSize;
+            cacheOracle.verifyRequests(session.requests, session.responses, params.skip + params.take, prefetchSize, "prefetch requests", false, true);
+            cache.onidle = false;
+            djstest.destroyCacheAndDone(cache);
+        };
+    };
+
+    var cleanDomStorage = function (done) {
+        /** Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the 
+         * setup and teardown methods to be consistent with indexedDb's cleanup method.
+         * @param {Function} done - Function to be called after DOM storage is cleared.
+         */
+                 if (window.localStorage) {
+            window.localStorage.clear();
+        }
+        done();
+    };
+
+    var cleanIndexedDb = function (done) {
+        /** Cleans all the data saved in the browser's IndexedDb Storage.
+         * @param {Function} done - Function to be called after indexedDb is cleared.
+         */
+        var caches = this.caches;
+
+        djstest.cleanStoreOnIndexedDb(caches, done);
+    };
+
+    var cleanupAllStorage = function (done) {
+        /** Cleans up all available storage mechanisms in the browser.
+         * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
+         */
+        var that = this;
+        var storeCleanup = [];
+
+        $.each(CacheOracle.mechanisms, function (_, mechanism) {
+            if (CacheOracle.isMechanismAvailable(mechanism)) {
+                storeCleanup.push(function (done) {
+                    if (storageMechanisms[mechanism]) {
+                        storageMechanisms[mechanism].cleanup.call(that, done);
+                    } else {
+                        done();
+                    }
+                });
+            }
+        });
+
+        djstest.asyncDo(storeCleanup, done);
+    };
+
+    var storageMechanisms = {
+        indexeddb: { cleanup: cleanIndexedDb },
+        dom: { cleanup: cleanDomStorage },
+        memory: { cleanup: function (done) { done(); } },
+        best: { cleanup: function (done) { done(); } }
+    };
+
+    module("Functional", {
+        setup: function () {
+            this.createAndAddCache = function (options) {
+                /** Returns a cache created from the options object and 
+                 * @param {Object} options - Object to create a cache from. 
+                 */
+                var cache = odatajs.cache.createDataCache(options);
+                this.caches.push({ name: options.name, cache: cache });
+                return cache;
+            };
+
+            this.observableHttpClient = new ObservableHttpClient();
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
+            this.caches = [];
+            var that = this;
+
+            djstest.wait(function (done) {
+                cleanupAllStorage.call(that, done);
+            });
+        },
+
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient.provider;
+            var clearActions = [];
+            var that = this;
+
+            $.each(this.caches, function (_, cacheObject) {
+                cacheObject.cache.onidle = undefined;
+
+                clearActions.push(function (done) {
+                    cacheObject.cache.clear().then(function () {
+                        done();
+                    },
+                        function (err) {
+                            djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
+                        })
+                });
+            });
+
+            djstest.wait(function (done) {
+                djstest.asyncDo(clearActions, function () {
+                    cleanupAllStorage.call(that, function () {
+                        that.caches = [];
+                        done();
+                    });
+                });
+            });
+        }
+    });
+
+    $.each(CacheOracle.mechanisms, function (_, mechanism) {
+        var parameters = { mechanism: mechanism, source: sources[1].source, take: 5, skip: 0, pageSize: 5, prefetchSize: 5 };
+        if (CacheOracle.isMechanismAvailable(mechanism)) {
+            djstest.addTest(dataCacheSingleReadRangeTest, "Specified mechanism: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
+        }
+        else {
+            djstest.addTest(function (params) {
+                djstest.assertsExpected(1);
+                var options = { name: "cache" + new Date().valueOf(), mechanism: params.mechanism, source: params.source };
+                try {
+                    var cache = this.createAndAddCache(options);
+                    expectException(cache);
+                }
+                catch (e) {
+                    if (mechanism === "indexeddb") {
+                        djstest.assertAreEqual(e.message, "IndexedDB is not supported on this browser", "Validating expected error");
+                    } else if (mechanism === "dom") {
+                        djstest.assertAreEqual(e.message, "Web Storage not supported by the browser", "Validating expected error");
+                    } else {
+                        djstest.fail("Creating cache with mechanism " + mechanism + " should not fail: " + djstest.toString(e));
+                    }
+
+                    djstest.done();
+                }
+            }, "Invalid mechanism for browser: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
+        }
+    });
+
+    $.each(sources, function (_, sourceObject) {
+        $.each(pageSizes, function (_, pageSizeValue) {
+            $.each(cacheSizes, function (_, cacheSizeValue) {
+                var parameters = { source: sourceObject.source, skip: 0, take: itemsInCollection, pageSize: pageSizeValue, prefetchSize: 0, cacheSize: cacheSizeValue };
+                djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
+            });
+        });
+
+        $.each(skipValues, function (_, skipValue) {
+            $.each(takeValues, function (_, takeValue) {
+                var parameters = { source: sourceObject.source, take: takeValue, skip: skipValue, pageSize: 4, prefetchSize: 0, cacheSize: 0 };
+                djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
+            });
+        });
+
+        $.each(multipleReads, function (_, firstRange) {
+            $.each(multipleReads, function (_, secondRange) {
+                var parallelReadParams = { source: sourceObject.source, firstTake: firstRange.take, firstSkip: firstRange.skip, secondTake: secondRange.take, secondSkip: secondRange.skip, pageSize: 5, prefetchSize: 0, cacheSize: 0 };
+                djstest.addTest(dataCacheParallelReadRangeTest, "Parallel: " + createMultipleReadTestName(parallelReadParams), parallelReadParams);
+
+                $.each([false, true], function (_, destroyCacheBetweenReads) {
+                    var serialReadParams = $.extend({}, parallelReadParams, { destroyCacheBetweenReads: destroyCacheBetweenReads });
+                    djstest.addTest(dataCacheSerialReadRangeTest, "Serial: " + createMultipleReadTestName(serialReadParams), serialReadParams);
+                });
+            });
+        });
+
+        var getInvalidValueErrorMessage = function (invalidValue, parameterName) {
+            /** Returns the expected error message for the specified invalid value.
+             * @param {Object} invalidValue - invalid value (anything other than zero or positive integer) to determine the error message from.
+             * @param {String} parameterName - The name of the parameter being verified.
+             * @returns {String} Error message expected.
+             */
+            return (invalidValue === undefined || typeof invalidValue !== "number") ?
+                        "'" + parameterName + "' must be a number." :
+                        "'" + parameterName + "' must be greater than or equal to zero.";
+        };
+
+        $.each(invalidSkipValues, function (_, invalidSkipValue) {
+            var parameters = { source: sourceObject.source, skip: invalidSkipValue, take: 1 };
+            djstest.addTest(function (params) {
+                djstest.assertsExpected(1);
+                var options = { name: "cache" + new Date().valueOf(), source: params.source };
+                var cache = this.createAndAddCache(options);
+                try {
+                    cache.readRange(params.skip, params.take);
+                    expectException(cache);
+                } catch (e) {
+                    djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidSkipValue, "index"), "Error message validation");
+                    djstest.destroyCacheAndDone(cache);
+                }
+            }, "Invalid skip: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        $.each(invalidTakeValues, function (_, invalidTakeValue) {
+            var parameters = { source: sourceObject.source, skip: 0, take: invalidTakeValue };
+            djstest.addTest(function (params) {
+                djstest.assertsExpected(1);
+                var options = { name: "cache" + new Date().valueOf(), source: params.source };
+                var cache = this.createAndAddCache(options);
+                try {
+                    cache.readRange(params.skip, params.take);
+                    expectException(cache);
+                } catch (e) {
+                    djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidTakeValue, "count"), "Error message validation");
+                    djstest.destroyCacheAndDone(cache);
+                }
+            }, "Invalid take: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        $.each(invalidPageSizes, function (_, invalidPageSize) {
+            var parameters = { source: sourceObject.source, skip: 0, take: 5, pageSize: invalidPageSize };
+            djstest.addTest(function (params) {
+                var options = { name: "cache", source: params.source, pageSize: params.pageSize };
+                try {
+                    var cache = this.createAndAddCache(options);
+                    expectException(cache);
+                } catch (e) {
+                    var expectedError = typeof invalidPageSize === "number" ? "'pageSize' must be greater than zero." : getInvalidValueErrorMessage(invalidPageSize, "pageSize");
+                    djstest.assertAreEqual(e.message, expectedError, "Error message validation");
+                }
+                djstest.done();
+            }, "Invalid pageSize: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        $.each(pageSizes, function (_, pageSize) {
+            $.each(cacheSizes, function (_, cacheSize) {
+                var parameters = { source: sourceObject.source, skip: 0, take: pageSize, pageSize: pageSize, prefetchSize: -1, cacheSize: cacheSize };
+                djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+            });
+        });
+
+        $.each(skipValues, function (_, skipValue) {
+            var parameters = { source: sourceObject.source, skip: skipValue, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
+            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        $.each(takeValues, function (_, takeValue) {
+            var parameters = { source: sourceObject.source, skip: 0, take: takeValue, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
+            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        $.each(prefetchSizes, function (_, prefetchSize) {
+            var parameters = { source: sourceObject.source, skip: 0, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: prefetchSize, cacheSize: -1 };
+            djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+        });
+
+        var fixedPrefetchSize = 5;
+
+        djstest.addTest(function (params) {
+            djstest.assertsExpected(1);
+            var cache = this.createAndAddCache({
+                name: "cache" + new Date().valueOf(),
+                source: params.source,
+                prefetchSize: fixedPrefetchSize,
+                idle: onidleValidation,
+                pageSize: 2,
+                mechanism: "memory"
+            });
+            cache.readRange(0, 5);
+
+        }, "onidle in constructor, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+        djstest.addTest(function (params) {
+            djstest.assertsExpected(1);
+            var cache = this.createAndAddCache({
+                name: "cache" + new Date().valueOf(),
+                source: params.source,
+                prefetchSize: fixedPrefetchSize,
+                pageSize: 2,
+                mechanism: "memory"
+            });
+            cache.onidle = onidleValidation;
+            cache.readRange(0, 5);
+        }, "onidle, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+        djstest.addTest(function (params) {
+            djstest.assertsExpected(1);
+            var cache = this.createAndAddCache({
+                name: "cache" + new Date().valueOf(),
+                source: params.source,
+                prefetchSize: fixedPrefetchSize,
+                idle: function () { djstest.assert(false, "unexpected onidle call") },
+                pageSize: 2,
+                mechanism: "memory"
+            });
+            cache.onidle = onidleValidation;
+            cache.readRange(0, 5);
+        }, "onidle override, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+        djstest.addTest(function (params) {
+            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: -1 });
+            var observableSource = typeof params.source === "string" ? this.observableHttpClient : params.source;
+            cache.readRange(0, 1).then(function (data) {
+                // Let one prefetch request go out, to make sure the prefetcher is started, and then destroy the cache
+                $(observableSource).one("success", function () {
+                    var session = new Session(observableSource);
+                    cache.clear().then(function () {
+                        setTimeout(function () {
+                            djstest.assertAreEqualDeep(session.requests, [], "Verify no prefetch requests are sent out after cache.clear() callback");
+                            djstest.done();
+                        }, 1000);
+                    }, function (err) {
+                        djstest.fail("Error destroying the cache: " + djstest.toString(err));
+                    });
+                });
+            });
+        }, "Testing cache.clear() halts the prefetcher" + sourceObject.source, { source: sourceObject.source });
+
+        djstest.addTest(function (params) {
+            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source });
+            if (params.countSupported) {
+                cache.count().then(function (count) {
+                    djstest.assertAreEqual(count, itemsInCollection, "All items accounted for");
+                    djstest.destroyCacheAndDone(cache);
+                }, makeUnexpectedErrorHandler(cache));
+            }
+            else {
+                cache.count().then(function (count) {
+                    djstest.assert(false, "Success should not be called, count not supported");
+                    djstest.destroyCacheAndDone(cache);
+                }, function (err) {
+                    djstest.assertAreEqual(err.message, "HTTP request failed", "Validating expected error");
+                    djstest.destroyCacheAndDone(cache);
+                });
+            }
+        }, "Testing cache.count() on " + sourceObject.source, { source: sourceObject.source, countSupported: sourceObject.countSupported });
+
+        djstest.addTest(function (params) {
+            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
+            var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+            cache.readRange(0, 1).cancel();
+            setTimeout(function () {
+                djstest.assertAreEqualDeep(session.requests, [], "Verify no requests are sent out after readRange is cancelled");
+                djstest.done();
+            }, 1000);
+        }, "Testing cancel()" + sourceObject.source, { source: sourceObject.source });
+
+        djstest.addTest(function (params) {
+            djstest.assertsExpected(1);
+            var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
+            cache.clear().then(function () {
+                cache.clear().then(function () {
+                    djstest.pass("Second clear succeeded");
+                    djstest.done();
+                }, makeUnexpectedErrorHandler(cache));
+            }, makeUnexpectedErrorHandler(cache));
+        }, "Testing .clear().then(cache.clear())" + sourceObject.source, { source: sourceObject.source });
+    });
+
+    var params = {
+        source: "./endpoints/BasicAuthDataService.svc/Customers",
+        skip: 0,
+        take: 5,
+        pageSize: 5,
+        prefetchSize: -1,
+        cacheSize: -1,
+        user: "djsUser",
+        password: "djsPassword"
+    };
+    djstest.addTest(dataCachePrefetchTest, createSingleReadTestName(params), params);
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-rx-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-rx-functional-tests.html b/odatajs/tests/odata-cache-rx-functional-tests.html
new file mode 100644
index 0000000..aab512c
--- /dev/null
+++ b/odatajs/tests/odata-cache-rx-functional-tests.html
@@ -0,0 +1,50 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>>datajs.cache toObservable() tests</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <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="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="common/rx.js"></script>
+    <script type="text/javascript" src="odata-cache-rx-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache toObservable() tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-cache-rx-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-cache-rx-functional-tests.js b/odatajs/tests/odata-cache-rx-functional-tests.js
new file mode 100644
index 0000000..453e586
--- /dev/null
+++ b/odatajs/tests/odata-cache-rx-functional-tests.js
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var feeds = [
+        { uri: "./endpoints/FoodStoreDataServiceV4.svc/Foods" }
+    ];
+
+    var itemsInCollection = 16;
+    var pageSizes = [
+        1,
+        4,  // factor of total, <= server page size
+        5,  // non-factor of total, <= server page size
+        6,  // non-factor of total, > server page size
+        8,  // factor of total, > server page size
+        itemsInCollection,
+        itemsInCollection + 1
+    ];
+
+    var operatorTests = [
+        function (observable) { return observable.Take(0); },
+        function (observable) { return observable.Take(1); },
+        function (observable) { return observable.Skip(1); },
+        function (observable) { return observable.Skip(2).Take(4); },
+        function (observable) { return observable.Select(function (item) { return item.Name; }); },
+        function (observable) { return observable.Where(function (item) { return item.FoodID % 2 === 1; }); }
+    ];
+
+    var assertObservables = function (actual, expected, done) {
+        /** Asserts two finite observables generate the same sequence
+         * @param {IObservable} actual - The actual observable
+         * @param {IObservable} expected - The expected observable
+         * @param {Function} done - The callback function when asserts are done
+         */
+        var toArray = function (observable, callback) {
+            var arr = [];
+            observable.Subscribe(
+                function (item) { arr.push(item); },
+                function (err) { arr.push({ "__error__": err }); },
+                function () { callback(arr); });
+        };
+
+        toArray(actual, function (actualSequence) {
+            toArray(expected, function (expectedSequence) {
+                djstest.assertAreEqualDeep(actualSequence, expectedSequence, "Verify observable sequence");
+                done();
+            });
+        });
+    };
+
+    module("Functional");
+    $.each(feeds, function (_, feed) {
+        $.each(pageSizes, function (_, pageSize) {
+            $.each(operatorTests, function (_, operator) {
+                var params = { feedUri: feed.uri, pageSize: pageSize, operator: operator };
+                djstest.addTest(function (params) {
+                    djstest.assertsExpected(1);
+                    var options = { name: "cache" + new Date().valueOf(), source: params.feedUri, pageSize: params.pageSize, prefetchSize: 0 };
+                    var cache = odatajs.cache.createDataCache(options);
+
+                    ODataReadOracle.readJsonAcrossServerPages(params.feedUri, function (collection) {
+                        assertObservables(params.operator(cache.toObservable()), params.operator(window.Rx.Observable.FromArray(collection.value)), function () {
+                            djstest.destroyCacheAndDone(cache);
+                        });
+                    });
+                }, "feed: " + params.feedUri + ", pageSize: " + params.pageSize + ", operator: " + params.operator.toString(), params);
+            });
+        });
+    });
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-fuzz.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-fuzz.html b/odatajs/tests/odata-fuzz.html
new file mode 100644
index 0000000..270e153
--- /dev/null
+++ b/odatajs/tests/odata-fuzz.html
@@ -0,0 +1,557 @@
+<!--
+/*
+ * 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.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData Fuzzing Tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>   
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript">
+
+        var testCsdl = '' +
+        '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
+        '<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">\r\n' +
+        '  <edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="2.0">\r\n' +
+        '    <Schema Namespace="TestCatalog.Model" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">\r\n' +
+        '      <EntityType Name="Genre">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
+        '        <NavigationProperty Name="Titles" Relationship="TestCatalog.Model.TitleGenres" FromRole="Genres" ToRole="Titles" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Language">\r\n' +
+        '        <Key><PropertyRef Name="Name" /></Key>\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
+        '        <NavigationProperty Name="Titles" Relationship="TestCatalog.Model.TitleLanguages" FromRole="Language" ToRole="Titles" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Person">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.Int32" Nullable="false" />\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="80" Unicode="true" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
+        '        <NavigationProperty Name="Awards" Relationship="TestCatalog.Model.FK_TitleAward_Person" FromRole="People" ToRole="TitleAwards" />\r\n' +
+        '        <NavigationProperty Name="TitlesActedIn" Relationship="TestCatalog.Model.TitleActors" FromRole="People" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="TitlesDirected" Relationship="TestCatalog.Model.TitleDirectors" FromRole="People" ToRole="Titles" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="TitleAudioFormat">\r\n' +
+        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Language" /><PropertyRef Name="Format" /></Key>\r\n' +
+        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
+        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Language" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleAudioFormat_Title" FromRole="TitleAudioFormats" ToRole="Titles" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="TitleAward">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.Guid" Nullable="false" />\r\n' +
+        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Category" Type="Edm.String" Nullable="false" MaxLength="60" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Year" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Won" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleAward_Title" FromRole="TitleAwards" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="Person" Relationship="TestCatalog.Model.FK_TitleAward_Person" FromRole="TitleAwards" ToRole="People" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <EntityType Name="Title" m:HasStream="true">\r\n' +
+        '        <Key><PropertyRef Name="Id" /></Key>\r\n' +
+        '        <Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
+        '        <Property Name="Synopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="html" />\r\n' +
+        '        <Property Name="ShortSynopsis" Type="Edm.String" Nullable="true" MaxLength="Max" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="AverageRating" Type="Edm.Double" Nullable="true" />\r\n' +
+        '        <Property Name="ReleaseYear" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Url" Type="Edm.String" Nullable="true" MaxLength="200" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="DateModified" Type="Edm.DateTime" Nullable="false" ConcurrencyMode="Fixed" m:FC_TargetPath="SyndicationUpdated" m:FC_KeepInContent="false" />\r\n' +
+        '        <Property Name="Type" Type="Edm.String" Nullable="false" MaxLength="8" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="BoxArt" Type="TestCatalog.Model.BoxArt" Nullable="false" />\r\n' +
+        '        <Property Name="ShortName" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="200" Unicode="false" FixedLength="false" m:FC_TargetPath="SyndicationTitle" />\r\n' +
+        '        <Property Name="Instant" Type="TestCatalog.Model.InstantAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="Dvd" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="BluRay" Type="TestCatalog.Model.DeliveryFormatAvailability" Nullable="false" />\r\n' +
+        '        <Property Name="TinyUrl" Type="Edm.String" Nullable="false" MaxLength="30" />\r\n' +
+        '        <Property Name="WebsiteUrl" Type="Edm.String" Nullable="true" MaxLength="200" />\r\n' +
+        '        <Property Name="TestApiId" Type="Edm.String" Nullable="false" MaxLength="200" />\r\n' +
+        '        <NavigationProperty Name="AudioFormats" Relationship="TestCatalog.Model.FK_TitleAudioFormat_Title" FromRole="Titles" ToRole="TitleAudioFormats" />\r\n' +
+        '        <NavigationProperty Name="Awards" Relationship="TestCatalog.Model.FK_TitleAward_Title" FromRole="Titles" ToRole="TitleAwards" />\r\n' +
+        '        <NavigationProperty Name="Disc" Relationship="TestCatalog.Model.FK_Title_Disc" FromRole="Titles1" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="Movie" Relationship="TestCatalog.Model.FK_Title_Movie" FromRole="Titles1" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="Season" Relationship="TestCatalog.Model.FK_Title_Season" FromRole="Titles1" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="Series" Relationship="TestCatalog.Model.FK_Title_Series" FromRole="Titles1" ToRole="Titles" />\r\n' +
+        '        <NavigationProperty Name="ScreenFormats" Relationship="TestCatalog.Model.FK_TitleScreenFormat_Title" FromRole="Titles" ToRole="TitleScreenFormats" />\r\n' +
+        '        <NavigationProperty Name="Cast" Relationship="TestCatalog.Model.TitleActors" FromRole="Titles" ToRole="People" />\r\n' +
+        '        <NavigationProperty Name="Languages" Relationship="TestCatalog.Model.TitleLanguages" FromRole="Titles" ToRole="Language" />\r\n' +
+        '        <NavigationProperty Name="Directors" Relationship="TestCatalog.Model.TitleDirectors" FromRole="Titles" ToRole="People" />\r\n' +
+        '        <NavigationProperty Name="Genres" Relationship="TestCatalog.Model.TitleGenres" FromRole="Titles" ToRole="Genres" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <ComplexType Name="BoxArt">\r\n' +
+        '        <Property Name="SmallUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="MediumUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="LargeUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="HighDefinitionUrl" Type="Edm.String" Nullable="true" MaxLength="80" Unicode="false" FixedLength="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <ComplexType Name="InstantAvailability">\r\n' +
+        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="HighDefinitionAvailable" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <ComplexType Name="DeliveryFormatAvailability">\r\n' +
+        '        <Property Name="Available" Type="Edm.Boolean" Nullable="false" />\r\n' +
+        '        <Property Name="AvailableFrom" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="AvailableTo" Type="Edm.DateTime" Nullable="true" />\r\n' +
+        '        <Property Name="Runtime" Type="Edm.Int32" Nullable="true" />\r\n' +
+        '        <Property Name="Rating" Type="Edm.String" Nullable="true" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
+        '      </ComplexType>\r\n' +
+        '      <EntityType Name="TitleScreenFormat">\r\n' +
+        '        <Key><PropertyRef Name="TitleId" /><PropertyRef Name="DeliveryFormat" /><PropertyRef Name="Format" /></Key>\r\n' +
+        '        <Property Name="TitleId" Type="Edm.String" Nullable="false" MaxLength="30" FixedLength="false" />\r\n' +
+        '        <Property Name="DeliveryFormat" Type="Edm.String" Nullable="false" MaxLength="10" Unicode="false" FixedLength="false" />\r\n' +
+        '        <Property Name="Format" Type="Edm.String" Nullable="false" MaxLength="30" Unicode="false" FixedLength="false" />\r\n' +
+        '        <NavigationProperty Name="Title" Relationship="TestCatalog.Model.FK_TitleScreenFormat_Title" FromRole="TitleScreenFormats" ToRole="Titles" />\r\n' +
+        '      </EntityType>\r\n' +
+        '      <Association Name="FK_TitleAudioFormat_Title">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
+        '        <End Role="TitleAudioFormats" Type="TestCatalog.Model.TitleAudioFormat" Multiplicity="*" />\r\n' +
+        '        <ReferentialConstraint>\r\n' +
+        '          <Principal Role="Titles"><PropertyRef Name="Id" /></Principal>\r\n' +
+        '          <Dependent Role="TitleAudioFormats"><PropertyRef Name="TitleId" /></Dependent>\r\n' +
+        '        </ReferentialConstraint>\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_TitleAward_Title">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
+        '        <End Role="TitleAwards" Type="TestCatalog.Model.TitleAward" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_TitleAward_Person">\r\n' +
+        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="0..1" />\r\n' +
+        '        <End Role="TitleAwards" Type="TestCatalog.Model.TitleAward" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_Title_Disc">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
+        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_Title_Movie">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
+        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_Title_Season">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
+        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_Title_Series">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="0..1" />\r\n' +
+        '        <End Role="Titles1" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="FK_TitleScreenFormat_Title">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="1" />\r\n' +
+        '        <End Role="TitleScreenFormats" Type="TestCatalog.Model.TitleScreenFormat" Multiplicity="*" />\r\n' +
+        '        <ReferentialConstraint>\r\n' +
+        '          <Principal Role="Titles"><PropertyRef Name="Id" /></Principal>\r\n' +
+        '          <Dependent Role="TitleScreenFormats"><PropertyRef Name="TitleId" /></Dependent>\r\n' +
+        '        </ReferentialConstraint>\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="TitleActors">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="TitleLanguages">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '        <End Role="Language" Type="TestCatalog.Model.Language" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="TitleDirectors">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '        <End Role="People" Type="TestCatalog.Model.Person" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '      <Association Name="TitleGenres">\r\n' +
+        '        <End Role="Titles" Type="TestCatalog.Model.Title" Multiplicity="*" />\r\n' +
+        '        <End Role="Genres" Type="TestCatalog.Model.Genre" Multiplicity="*" />\r\n' +
+        '      </Association>\r\n' +
+        '    </Schema>\r\n' +
+        '    <Schema Namespace="Test.Catalog" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">\r\n' +
+        '      <EntityContainer Name="TestCatalog" m:IsDefaultEntityContainer="true">\r\n' +
+        '        <FunctionImport Name="Movies" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
+        '        <FunctionImport Name="Series" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
+        '        <FunctionImport Name="Seasons" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
+        '        <FunctionImport Name="Discs" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
+        '        <FunctionImport Name="Episodes" EntitySet="Titles" ReturnType="Collection(TestCatalog.Model.Title)" m:HttpMethod="GET" />\r\n' +
+        '        <EntitySet Name="Genres" EntityType="TestCatalog.Model.Genre" />\r\n' +
+        '        <EntitySet Name="Languages" EntityType="TestCatalog.Model.Language" />\r\n' +
+        '        <EntitySet Name="People" EntityType="TestCatalog.Model.Person" />\r\n' +
+        '        <EntitySet Name="TitleAudioFormats" EntityType="TestCatalog.Model.TitleAudioFormat" />\r\n' +
+        '        <EntitySet Name="TitleAwards" EntityType="TestCatalog.Model.TitleAward" />\r\n' +
+        '        <EntitySet Name="Titles" EntityType="TestCatalog.Model.Title" />\r\n' +
+        '        <EntitySet Name="TitleScreenFormats" EntityType="TestCatalog.Model.TitleScreenFormat" />\r\n' +
+        '        <AssociationSet Name="FK_TitleAudioFormat_Title" Association="TestCatalog.Model.FK_TitleAudioFormat_Title">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="TitleAudioFormats" EntitySet="TitleAudioFormats" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_TitleAward_Title" Association="TestCatalog.Model.FK_TitleAward_Title">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="TitleAwards" EntitySet="TitleAwards" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_TitleAward_Person" Association="TestCatalog.Model.FK_TitleAward_Person">\r\n' +
+        '          <End Role="People" EntitySet="People" />\r\n' +
+        '          <End Role="TitleAwards" EntitySet="TitleAwards" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_Title_Disc" Association="TestCatalog.Model.FK_Title_Disc">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_Title_Movie" Association="TestCatalog.Model.FK_Title_Movie">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_Title_Season" Association="TestCatalog.Model.FK_Title_Season">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_Title_Series" Association="TestCatalog.Model.FK_Title_Series">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Titles1" EntitySet="Titles" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="FK_TitleScreenFormat_Title" Association="TestCatalog.Model.FK_TitleScreenFormat_Title">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="TitleScreenFormats" EntitySet="TitleScreenFormats" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="TitleActors" Association="TestCatalog.Model.TitleActors">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="People" EntitySet="People" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="TitleLanguages" Association="TestCatalog.Model.TitleLanguages">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Language" EntitySet="Languages" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="TitleDirectors" Association="TestCatalog.Model.TitleDirectors">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="People" EntitySet="People" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '        <AssociationSet Name="TitleGenres" Association="TestCatalog.Model.TitleGenres">\r\n' +
+        '          <End Role="Titles" EntitySet="Titles" />\r\n' +
+        '          <End Role="Genres" EntitySet="Genres" />\r\n' +
+        '        </AssociationSet>\r\n' +
+        '      </EntityContainer>\r\n' +
+        '    </Schema>\r\n' +
+        '  </edmx:DataServices>\r\n' +
+        '</edmx:Edmx>\r\n' +
+        '';
+
+
+        var iterationsRemaining = 0;
+        var iterationsPerRun = 100000;
+        var failureCount = 0;
+        var canary = false;
+
+        function canaryFn() {
+            canary = true;
+        }
+
+        var buildSumAndNormalize = function (table) {
+            // Sum all weights.
+            var total = 0;
+            for (var i = 0; i < table.length; i++) {
+                total += table[i].w;
+            }
+
+            // Record a normalized weight (nw) and the step-ladder threshold.
+            var last = 0;
+            for (var i = 0; i < table.length; i++) {
+                table[i].nw = (table[i].w / total);
+
+                last += table[i].nw;
+                table[i].sl = last;
+            }
+
+            table.total = total;
+        };
+
+        var randomFromWeighted = function (table) {
+            if (table.total === undefined) {
+                buildSumAndNormalize(table);
+            }
+
+            var number = Math.random();
+            for (var i = 0; i < table.length; i++) {
+                if (number < table[i].sl) {
+                    return table[i].v;
+                }
+            }
+
+            return table[table.length - 1].v;
+        };
+
+        // Create a table with relative weight w and value v for text generation.
+        var fuzzingTextTable = [
+            { w: 3, v: "canary=true" },
+            { w: 2, v: "canary=true;" },
+            { w: 3, v: "canary=1" },
+            { w: 1, v: "window.canary=1" },
+            { w: 2, v: "canary=[]" },
+            { w: 2, v: "canary={}" },
+            { w: 1, v: "canaryFn" },
+            { w: 2, v: "canaryFn()" }
+        ];
+
+        var fuzzingTextOpTable = [
+            { w: 1, v: "replace" },
+            { w: 3, v: "insert" }
+        ];
+
+        var fuzzText = function (text) {
+            /** Fuzzes the specified string.
+             * @param {String} text - Text to fuzz.
+             * @returns {String} The fuzzes text.
+
+            var location = Math.round(Math.random() * text.length - 1);
+            var content = randomFromWeighted(fuzzingTextTable);
+            var op = randomFromWeighted(fuzzingTextOpTable);
+            if (op === "replace") {
+                text = text.substr(0, location) + content + text.substr(location + content.length);
+            } else if (op === "insert") {
+                text = text.substr(0, location) + content + text.substr(location);
+            }
+
+            return text;
+        };
+
+        var rarely = function (rare, common) {
+            if (Math.random() < 0.1) {
+                return rare;
+            } else {
+                return common;
+            }
+        };
+
+        var gibberish = function () {
+            var len = Math.random() * 100;
+            var result = "";
+            for (var i = 0; i < len; i++) {
+                result += String.fromCharCode(Math.round(Math.random() * 65000));
+            }
+
+            return result;
+        }
+
+        var generateResponse = function (suggestedContentType, body) {
+            var url = rarely(null, "http://foo/bar");
+            var statusCode = rarely((Math.random() * 1000).toString().substr(0, 3), 200);
+            var statusText = rarely(gibberish(), "OK");
+            var headers = [];
+            headers["Content-Length"] = rarely(Math.random() * 200, undefined);
+            headers["Content-Type"] = rarely("foo bar baz", suggestedContentType);
+
+            var response = { requestUri: url, statusCode: statusCode, statusText: statusText, headers: headers, body: body };
+            return response;
+        };
+
+        var generateRandom = function () {
+            var body = gibberish();
+            return generateResponse("application/octet-stream", body);
+        };
+
+        var generateServiceDoc = function() {
+            var body = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r\n' +
+                        '<service xml:base="http://services.odata.org/OData/OData.svc/"  xmlns:atom="http://www.w3.org/2005/Atom" ' +
+                        ' xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">' +
+                        '<workspace><atom:title>Default</atom:title> <collection href="Products"><atom:title>Products</atom:title></collection>' +
+                        '<collection href="Categories"><atom:title>Categories</atom:title> </collection><collection href="Suppliers"><atom:title>Suppliers</atom:title> </collection></workspace></service>';
+            body = fuzzText(body);
+            return generateResponse("application/atomsvc+xml", body);
+        };
+
+        var generateMetadata = function () {
+            var body = testCsdl;
+            body = fuzzText(body);
+            return generateResponse("application/xml", body);
+        };
+
+        var generateError = function () {
+            var body = testCsdl;
+            body = fuzzText(body);
+            return generateResponse("application/xml", body);
+        };
+
+        var generatePlainText = function () {
+            var body = gibberish();
+            return generateResponse("plain/text", body);
+        };
+
+        var generateBatch = function () {
+            var body = gibberish();
+            return generateResponse("multipart/mixed; boundary=batch(123)", body);
+        };
+
+        var generateXml = function () {
+            // TODO: consider doing something about an XHTML section here
+            var body = '' +
+                '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n' +
+                '<feed xml:base=http://services.odata.org/OData/OData.svc/' +
+                '     xmlns:d=http://schemas.microsoft.com/ado/2007/08/dataservices' +
+                '     xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata' +
+                '     xmlns="http://www.w3.org/2005/Atom">' +
+                '  <title type="text">Categories</title>' +
+                '  <id>http://services.odata.org/OData/OData.svc/Categories</id>' +
+                '  <updated>2010-03-10T08:38:14Z</updated>' +
+                '  <link rel="self" title="Categories" href="Categories" />' +
+                '  <entry>' +
+                '    <id>http://services.odata.org/OData/OData.svc/Categories(0)</id>' +
+                '    <title type="text">Food</title>' +
+                '    <updated>2010-03-10T08:38:14Z</updated>' +
+                '    <author><name /></author>' +
+                '    <link rel="edit" title="Category" href="Categories(0)" />' +
+                '    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products"' +
+                '            type="application/atom+xml;type=feed"' +
+                '            title="Products" href="Categories(0)/Products" />' +
+                '    <category term="ODataDemo.Category"' +
+                '            scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />' +
+                '    <content type="application/xml">' +
+                '      <m:properties>' +
+                '        <d:ID m:type="Edm.Int32">0</d:ID>' +
+                '        <d:Name>Food</d:Name>' +
+                '        <d:AverageRating m:type="Edm.Double">3.6</d:AverageRating>' +
+                '        <d:AvailableFrom m:type="Edm.DateTime">1999-03-23T00:00:00</d:AvailableFrom>' +
+                '        <d:Name>Food</d:Name>' +
+                '      </m:properties>' +
+                '    </content>' +
+                '  </entry>' +
+                '  <!-- <entry> elements representing additional Categories go here -->' +
+                '</feed>';
+            return generateResponse("application/atom+xml", body);
+        };
+
+        var generateJson = function () {
+            var body =  '{ "d" : { ' +
+                        '"results": [ ' +
+                        '{ ' +
+                        '"__metadata": {  ' +
+                        '"uri": "http://services.odata.org/OData/OData.svc/Categories(0)",  ' +
+                        '"type": "DataServiceProviderDemo.Category" ' +
+                        '}, ' +
+                        '"ID": 0, ' +
+                        '"Name": "Food", ' +
+                        '"SomeDate": "Date(123)", ' +
+                        '"Products": { ' +
+                        '"__deferred": { ' +
+                        '"uri": "http://services.odata.org/OData/OData.svc/Categories(0)/Products" ' +
+                        '} } } ], ' +
+                        '"__count": "3", ' +
+                        '"__next": "http://services.odata.org/OData/OData.svc$skiptoken=12" ' +
+                        '} } ' +
+                        '';
+            return generateResponse("application/json", body);
+        };
+
+        // Create a table with relative weight w and value v for response generation.
+        var formatTable = [
+            { w:  1, v: generateRandom },
+            { w:  2, v: generateError },
+            { w:  5, v: generatePlainText },
+            { w:  5, v: generateServiceDoc },
+            { w: 10, v: generateBatch },
+            { w: 10, v: generateMetadata },
+            { w: 40, v: generateXml },
+            { w: 80, v: generateJson }
+        ];
+
+        var fakeHttpClient = {
+            request: function (request, success, error) {
+                /** Performs a network request.
+                 * @param {Function} success - Success callback with the response object.
+                 * @param {Function} error - Error callback with an error object.
+                 * @returns {Object} Object with an 'abort' method for the operation.
+
+                var shouldError = rarely(true, false);
+                var format = randomFromWeighted(formatTable);
+                var response = format();
+
+                window.setTimeout(function () {
+                    if (shouldError) {
+                        error(response);
+                    } else {
+                        success(response);
+                    }
+                }, 1);
+
+                return {};
+            }
+        };
+
+        var startTimeMs = 0;
+
+        function startTest() {
+            failureCount = 0;
+            startTimeMs = new Date().getTime();
+            iterationsRemaining = iterationsPerRun;
+            nextIteration();
+        }
+
+        function readCallback() {
+            // Success or failure don't actually matter.
+            if (canary === true) {
+                canary = false;
+                failureCount++;
+            }
+
+            iterationsRemaining--;
+            nextIteration();
+        }
+
+        function nextIteration() {
+            if (iterationsRemaining === 0) {
+                $("#fuzz-status").text("Tests complete. Failures: #" + failureCount);
+                return;
+            }
+
+            if (iterationsRemaining % 50 === 0) {
+                var text = "Running tests (pending=" + iterationsRemaining + " of " + iterationsPerRun;
+                if (iterationsRemaining !== iterationsPerRun) {
+                    var currentTimeMs = new Date().getTime();
+                    var averageTestTimeMs = (iterationsPerRun - iterationsRemaining) / (currentTimeMs - startTimeMs);
+                    var remainingTimeMs = iterationsRemaining * averageTestTimeMs;
+                    text += ", ETA: " + remainingTimeMs + "ms, avg " + averageTestTimeMs + "ms";
+                }
+
+                text += "). Failures: #" + failureCount;
+                $("#fuzz-status").text(text);
+            }
+
+            OData.read("url", readCallback, readCallback, undefined, fakeHttpClient);
+        }
+
+        $(document).ready(function () {
+            $("#start-button").click(startTest);
+        });
+    </script>
+
+</head>
+<body>
+<h1>OData Fuzzing Tests</h1>
+<p>
+This page fuzzes the OData parsers in the datajs library.
+</p>
+<button id='start-button'>Start</button>
+<p id='fuzz-status'>&nbsp;</p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-handler-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-handler-tests.js b/odatajs/tests/odata-handler-tests.js
new file mode 100644
index 0000000..aa824c7
--- /dev/null
+++ b/odatajs/tests/odata-handler-tests.js
@@ -0,0 +1,364 @@
+/*
+ * 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-handler-tests.js
+
+(function (window, undefined) {
+
+    var dataServiceVersion = "4.0";
+    var endpoint = "./endpoints/FoodStoreDataServiceV4.svc";
+    var mimeType = "application/json;odata.metadata=minimal";
+    var headers = {
+                "Content-Type": mimeType,
+                Accept: mimeType,
+                "OData-Version": "4.0"
+            };
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    djstest.addTest(function createUpdateDeleteTest() {
+        // This is a simple create-update-delete cycle as a high-level test.
+
+        var serviceUri = "./endpoints/FoodStoreDataServiceV4.svc/";
+        var baseUri = serviceUri + "Categories";
+        var testItem;
+        var handledData = { CategoryID: 1001, Name: "Name #1001" };
+        var uri;
+
+        var itemCreatedCallback = function (data, response) {
+            djstest.assert(response.headers["Location"], "location URL in the headers");
+            djstest.assert(data.Name, "Name #1001");
+            
+            uri = response.headers["Location"];
+            testItem = handledData;
+            testItem.Name = "Updated name";
+            
+            odatajs.oData.request({
+                method: "PUT",
+                data: testItem,
+                requestUri: uri,
+            }, itemUpdatedCallback);
+        };
+
+        var itemUpdatedCallback = function (data, response) {
+            djstest.assertAreEqual(response.statusCode, 204, "Expecting no content on update");
+            odatajs.oData.request({
+                method: "DELETE",
+                requestUri: uri
+            }, itemDeletedCallback);
+        };
+
+        var itemDeletedCallback = function (data, response) {
+            djstest.done();
+        };
+
+        $.post(serviceUri + "ResetData", function () {
+            odatajs.oData.request({
+                requestUri: baseUri,
+                method: "POST",
+                data: { CategoryID: 1001, Name: "Name #1001" }
+            }, itemCreatedCallback);
+        });
+    });
+
+    djstest.addTest(function errorHandlerTest() {
+        djstest.assertsExpected(1);
+        odatajs.oData.read("./endpoints/FoodStoreDataServiceV4.svc/Categories?$reserved-misused=true",
+            function (data) {
+                djstest.fail("expected an error callback");
+                djstest.done();
+            },
+            function (err) {
+                djstest.assert(err.response.body, "err.response.body is assigned");
+                djstest.done();
+            });
+    });
+
+    djstest.addTest(function textHandlerParseTest() {
+        djstest.assertsExpected(1);
+        MockHttpClient.clear().addResponse("textHandlerParseTest", {
+            statusCode: 200,
+            body: " text ",
+            headers: { "Content-Type": "text/plain" }
+        });
+        odatajs.oData.read("textHandlerParseTest", function (data) {
+            djstest.assertAreEqual(data, " text ", "data matches");
+            djstest.done();
+        }, function (err) {
+            djstest.fail("expected success");
+            djstest.done();
+        }, undefined, MockHttpClient);
+    });
+
+    djstest.addTest(function textHandlerParseEmptyTest() {
+        djstest.assertsExpected(1);
+        MockHttpClient.clear().addResponse("textHandlerParseTest", {
+            statusCode: 200,
+            body: "",
+            headers: { "Content-Type": "text/plain" }
+        });
+        odatajs.oData.read("textHandlerParseTest", function (data) {
+            djstest.assertAreEqual(data, "", "data matches");
+            djstest.done();
+        }, function (err) {
+            djstest.fail("expected success");
+            djstest.done();
+        }, undefined, MockHttpClient);
+    });
+
+    djstest.addTest(function textHandlerSerializeTest() {
+        djstest.assertsExpected(1);
+        MockHttpClient.clear().addRequestVerifier("uri", function (request) {
+            djstest.assertAreEqual(request.body, "text", "text in request");
+        }).addResponse("uri", { statusCode: 200, body: "", headers: { "Content-Type": "text/plain"} });
+        odatajs.oData.request({ requestUri: "uri", method: "POST", data: "text", headers: { "Content-Type": "text/plain"} }, function (data) {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("expected success");
+            djstest.done();
+        }, undefined, MockHttpClient);
+    });
+
+    djstest.addTest(function textHandlerSerializeBlankTest() {
+        djstest.assertsExpected(1);
+        MockHttpClient.clear().addRequestVerifier("uri", function (request) {
+            djstest.assertAreEqual(request.body, "", "text in request");
+        }).addResponse("uri", { statusCode: 200, body: "", headers: { "Content-Type": "text/plain"} });
+        odatajs.oData.request({ requestUri: "uri", method: "POST", data: "", headers: { "Content-Type": "text/plain"} }, function (data) {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("expected success");
+            djstest.done();
+        }, undefined, MockHttpClient);
+    });
+
+    // DATAJS INTERNAL START
+    djstest.addTest(function handlerReadTest() {
+        var tests = [
+            {
+                response: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: "response 0" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
+            },
+            {
+                response: { headers: { "Content-Type": "application/json" }, body: "response 1" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "" }
+            },
+            {
+                response: { headers: { "Content-Type": "otherMediaType" }, body: "response 2" },
+                shouldHit: false,
+                context: { contentType: window.odatajs.oData.handler.contentType("otherMediaType"), dataServiceVersion: "" }
+            },
+            {
+                response: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, body: "response 3" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
+            },
+            {
+                response: { body: "response 4" },
+                shouldHit: false,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "" }
+            },
+            {
+                response: null,
+                shouldHit: false,
+                context: {}
+            },
+            {
+                response: undefined,
+                shouldHit: false,
+                context: {}
+            }
+        ];
+
+        var i;
+        var test;
+        var testRead = function (handler, body, context) {
+            djstest.assert(test.shouldHit, "method should be hit on item #" + i);
+            djstest.assertAreEqual(handler, testHandler, "handler matches target on item #" + i);
+            djstest.assertAreEqualDeep(context, test.context, "context matches target on item #" + i);
+            djstest.assertAreEqual(body, test.response.body, "body matches target on item #" + i);
+            return body;
+        };
+
+        var testHandler = window.odatajs.oData.handler.handler(testRead, null, "application/json", "4.0");
+
+        var len, expectedAssertCount = 0;
+        for (i = 0, len = tests.length; i < len; i++) {
+            test = tests[i];
+            test.context.handler = testHandler;
+            test.context.response = test.response;
+            if (test.shouldHit) {
+                expectedAssertCount += 4;
+            }
+
+            testHandler.read(test.response, {});
+        }
+
+        djstest.assertsExpected(expectedAssertCount);
+        djstest.done();
+    });
+
+    djstest.addTest(function handlerWriteTest() {
+        var tests = [
+            {
+                request: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, data: "request 0" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
+            },
+            {
+                request: { headers: { "Content-Type": "application/json" }, data: "request 1" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: undefined }
+            },
+            {
+                request: { headers: { "Content-Type": "otherMediaType" }, data: "request 2" },
+                shouldHit: false,
+                context: { contentType: window.odatajs.oData.handler.contentType("otherMediaType"), dataServiceVersion: undefined }
+            },
+            {
+                request: { headers: {}, data: "request 3" },
+                shouldHit: true,
+                context: { contentType: null, dataServiceVersion: undefined }
+            },
+            {
+                request: { headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, data: "request 4" },
+                shouldHit: true,
+                context: { contentType: window.odatajs.oData.handler.contentType("application/json"), dataServiceVersion: "4.0" }
+            },
+            {
+                request: null,
+                shouldHit: false,
+                context: {}
+            },
+            {
+                request: undefined,
+                shouldHit: false,
+                context: {}
+            }
+        ];
+
+        var test;
+        var testWrite = function (handler, data, context) {
+            djstest.assert(test.shouldHit, "method should be hit");
+            djstest.assertAreEqual(handler, testHandler, "handler matches target");
+            djstest.assertAreEqualDeep(context, test.context, "context matches target");
+            djstest.assertAreEqual(data, test.request.data, "body matches target");
+            return data;
+        };
+
+        var testHandler = window.odatajs.oData.handler.handler(null, testWrite, "application/json", "4.0");
+
+        var i, len, expectedAssertCount = 0;
+        for (i = 0, len = tests.length; i < len; i++) {
+            test = tests[i];
+            test.context.handler = testHandler;
+            test.context.request = test.request;
+            if (test.shouldHit) {
+                expectedAssertCount += 4;
+            }
+            testHandler.write(test.request);
+        }
+
+        djstest.assertsExpected(expectedAssertCount);
+        djstest.done();
+    });
+
+    djstest.addTest(function handlerWriteUpdatesRequestContentTypeTest() {
+        var testWrite = function (handler, data, context) {
+            context.contentType = window.odatajs.oData.handler.contentType("my new content type");
+            return data;
+        };
+
+        var testHandler = window.odatajs.oData.handler.handler(null, testWrite, "application/json", "4.0");
+
+        var tests = [
+            { request: { headers: { "Content-Type": "application/json" }, data: "request 0" }, expected: "application/json" },
+            { request: { headers: {}, data: "request 1" }, expected: "my new content type" }
+        ];
+
+        var i, len;
+        for (i = 0, len = tests.length; i < len; i++) {
+            testHandler.write(tests[i].request);
+            djstest.assertAreEqual(tests[i].request.headers["Content-Type"], tests[i].expected, "request content type is the expected");
+        }
+        djstest.done();
+    });
+
+    djstest.addTest(function contentTypeTest() {
+        var tests = [
+            { contentType: "application/json;param1=value1;param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
+            { contentType: "application/json; param1=value1; param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
+            { contentType: "application/json;param1=value1; param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
+            { contentType: "application/json; param1=value1;param2=value2", expected: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"}} },
+            { contentType: "application/json", expected: { mediaType: "application/json", properties: {}} },
+            { contentType: ";param1=value1;param2=value2", expected: { mediaType: "", properties: { param1: "value1", param2: "value2"}} }
+        ];
+
+        var i, len, cTypeString;
+        for (i = 0, len = tests.length; i < len; i++) {
+            var actual = window.odatajs.oData.handler.contentType(tests[i].contentType);
+            djstest.assertAreEqual(actual.mediaType, tests[i].expected.mediaType, "Content type media type is parsed correctly");
+            djstest.assertAreEqualDeep(actual.properties, tests[i].expected.properties, "Content type properties are parsed correctly");
+        }
+
+        djstest.assert(! window.odatajs.oData.handler.contentType(undefined), "contentType returns undefined for undefined input");
+        djstest.assert(! window.odatajs.oData.handler.contentType(null), "contentType returns undefined for null input");
+
+        djstest.done();
+    });
+
+    djstest.addTest(function contentTypeToStringTest() {
+        var tests = [
+            { contentType: { mediaType: "application/json", properties: { param1: "value1", param2: "value2"} }, expected: "application/json;param1=value1;param2=value2" },
+            { contentType: { mediaType: "application/json", properties: {} }, expected: "application/json" },
+            { contentType: { mediaType: "", properties: { param1: "value1", param2: "value2"} }, expected: ";param1=value1;param2=value2" }
+        ];
+
+        var i, len, cTypeString;
+        for (i = 0, len = tests.length; i < len; i++) {
+            cTypeString = window.odatajs.oData.handler.contentTypeToString(tests[i].contentType);
+            djstest.assertAreEqual(cTypeString, tests[i].expected, "contentTypeToString returns the correct contentType string");
+        }
+
+        djstest.done();
+    });
+    
+    djstest.addTest(function readServiceDocumentTest(headers) {
+        odatajs.oData.request({
+            requestUri: endpoint,
+            method: "GET",
+            headers: headers
+        }, function (data, response) {
+            djstest.assertAreEqual(data.value[0].name, "Categories", "Verify .name");
+            djstest.assertAreEqual(data.value[0].kind, "EntitySet", "Verify .kind");
+            djstest.assertAreEqual(data.value[0].url, "Categories", "Verify .url");
+
+            djstest.assertAreEqual(data.value[1].name, "Foods", "Verify .name");
+            djstest.assertAreEqual(data.value[1].kind, "EntitySet", "Verify .kind");
+            djstest.assertAreEqual(data.value[1].url, "Foods", "Verify .url");
+            djstest.done();
+        }, unexpectedErrorHandler);
+     });
+          
+    // DATAJS INTERNAL END
+})(this);
\ No newline at end of file


[44/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/datajs/utils.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/datajs/utils.js b/datajs/src/lib/datajs/utils.js
deleted file mode 100644
index 27af705..0000000
--- a/datajs/src/lib/datajs/utils.js
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module datajs/utils */
-
-
-function inBrowser() {
-    return typeof window !== 'undefined';
-}
-
-/** Creates a new ActiveXObject from the given progId.
- * @param {String} progId - ProgId string of the desired ActiveXObject.
- * @returns {Object} The ActiveXObject instance. Null if ActiveX is not supported by the browser.
- * This function throws whatever exception might occur during the creation
- * of the ActiveXObject.
-*/
-var activeXObject = function (progId) {
-    
-    if (window.ActiveXObject) {
-        return new window.ActiveXObject(progId);
-    }
-    return null;
-};
-
-/** Checks whether the specified value is different from null and undefined.
- * @param [value] Value to check ( may be null)
- * @returns {Boolean} true if the value is assigned; false otherwise.
-*/     
-function assigned(value) {
-    return value !== null && value !== undefined;
-}
-
-/** Checks whether the specified item is in the array.
- * @param {Array} [arr] Array to check in.
- * @param item - Item to look for.
- * @returns {Boolean} true if the item is contained, false otherwise.
-*/
-function contains(arr, item) {
-    var i, len;
-    for (i = 0, len = arr.length; i < len; i++) {
-        if (arr[i] === item) {
-            return true;
-        }
-    }
-    return false;
-}
-
-/** Given two values, picks the first one that is not undefined.
- * @param a - First value.
- * @param b - Second value.
- * @returns a if it's a defined value; else b.</returns>
- */
-function defined(a, b) {
-    return (a !== undefined) ? a : b;
-}
-
-/** Delays the invocation of the specified function until execution unwinds.
- * @param {Function} callback - Callback function.
- */
-function delay(callback) {
-
-    if (arguments.length === 1) {
-        window.setTimeout(callback, 0);
-        return;
-    }
-
-    var args = Array.prototype.slice.call(arguments, 1);
-    window.setTimeout(function () {
-        callback.apply(this, args);
-    }, 0);
-}
-
-/** Throws an exception in case that a condition evaluates to false.
- * @param {Boolean} condition - Condition to evaluate.
- * @param {String} message - Message explaining the assertion.
- * @param {Object} data - Additional data to be included in the exception.
- */
-// DATAJS INTERNAL START
-function djsassert(condition, message, data) {
-
-
-    if (!condition) {
-        throw { message: "Assert fired: " + message, data: data };
-    }
-}
-// DATAJS INTERNAL END
-
-/** Extends the target with the specified values.
- * @param {Object} target - Object to add properties to.
- * @param {Object} values - Object with properties to add into target.
- * @returns {Object} The target object.
-*/
-function extend(target, values) {
-    for (var name in values) {
-        target[name] = values[name];
-    }
-
-    return target;
-}
-
-function find(arr, callback) {
-    /** Returns the first item in the array that makes the callback function true.
-     * @param {Array} [arr] Array to check in. ( may be null)
-     * @param {Function} callback - Callback function to invoke once per item in the array.
-     * @returns The first item that makes the callback return true; null otherwise or if the array is null.
-    */
-
-    if (arr) {
-        var i, len;
-        for (i = 0, len = arr.length; i < len; i++) {
-            if (callback(arr[i])) {
-                return arr[i];
-            }
-        }
-    }
-    return null;
-}
-
-function isArray(value) {
-    /** Checks whether the specified value is an array object.
-     * @param value - Value to check.
-     * @returns {Boolean} true if the value is an array object; false otherwise.
-     */
-
-    return Object.prototype.toString.call(value) === "[object Array]";
-}
-
-/** Checks whether the specified value is a Date object.
- * @param value - Value to check.
- * @returns {Boolean} true if the value is a Date object; false otherwise.
- */
-function isDate(value) {
-    return Object.prototype.toString.call(value) === "[object Date]";
-}
-
-/** Tests whether a value is an object.
- * @param value - Value to test.
- * @returns {Boolean} True is the value is an object; false otherwise.
- * Per javascript rules, null and array values are objects and will cause this function to return true.
- */
-function isObject(value) {
-    return typeof value === "object";
-}
-
-/** Parses a value in base 10.
- * @param {String} value - String value to parse.
- * @returns {Number} The parsed value, NaN if not a valid value.
-*/   
-function parseInt10(value) {
-    return parseInt(value, 10);
-}
-
-/** Renames a property in an object.
- * @param {Object} obj - Object in which the property will be renamed.
- * @param {String} oldName - Name of the property that will be renamed.
- * @param {String} newName - New name of the property.
- * This function will not do anything if the object doesn't own a property with the specified old name.
- */
-function renameProperty(obj, oldName, newName) {
-    if (obj.hasOwnProperty(oldName)) {
-        obj[newName] = obj[oldName];
-        delete obj[oldName];
-    }
-}
-
-/** Default error handler.
- * @param {Object} error - Error to handle.
- */
-function throwErrorCallback(error) {
-    throw error;
-}
-
-/** Removes leading and trailing whitespaces from a string.
- * @param {String str String to trim
- * @returns {String} The string with no leading or trailing whitespace.
- */
-function trimString(str) {
-    if (str.trim) {
-        return str.trim();
-    }
-
-    return str.replace(/^\s+|\s+$/g, '');
-}
-
-/** Returns a default value in place of undefined.
- * @param [value] Value to check (may be null)
- * @param defaultValue - Value to return if value is undefined.
- * @returns value if it's defined; defaultValue otherwise.
- * This should only be used for cases where falsy values are valid;
- * otherwise the pattern should be 'x = (value) ? value : defaultValue;'.
- */
-function undefinedDefault(value, defaultValue) {
-    return (value !== undefined) ? value : defaultValue;
-}
-
-// Regular expression that splits a uri into its components:
-// 0 - is the matched string.
-// 1 - is the scheme.
-// 2 - is the authority.
-// 3 - is the path.
-// 4 - is the query.
-// 5 - is the fragment.
-var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/;
-var uriPartNames = ["scheme", "authority", "path", "query", "fragment"];
-
-/** Gets information about the components of the specified URI.
- * @param {String} uri - URI to get information from.
- * @return  {Object} An object with an isAbsolute flag and part names (scheme, authority, etc.) if available.
- */
-function getURIInfo(uri) {
-    var result = { isAbsolute: false };
-
-    if (uri) {
-        var matches = uriRegEx.exec(uri);
-        if (matches) {
-            var i, len;
-            for (i = 0, len = uriPartNames.length; i < len; i++) {
-                if (matches[i + 1]) {
-                    result[uriPartNames[i]] = matches[i + 1];
-                }
-            }
-        }
-        if (result.scheme) {
-            result.isAbsolute = true;
-        }
-    }
-
-    return result;
-}
-
-/** Builds a URI string from its components.
- * @param {Object} uriInfo -  An object with uri parts (scheme, authority, etc.).
- * @returns {String} URI string.
- */
-function getURIFromInfo(uriInfo) {
-    return "".concat(
-        uriInfo.scheme || "",
-        uriInfo.authority || "",
-        uriInfo.path || "",
-        uriInfo.query || "",
-        uriInfo.fragment || "");
-}
-
-// Regular expression that splits a uri authority into its subcomponents:
-// 0 - is the matched string.
-// 1 - is the userinfo subcomponent.
-// 2 - is the host subcomponent.
-// 3 - is the port component.
-var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/;
-
-// Regular expression that matches percentage enconded octects (i.e %20 or %3A);
-var pctEncodingRegEx = /%[0-9A-F]{2}/ig;
-
-/** Normalizes the casing of a URI.
- * @param {String} uri - URI to normalize, absolute or relative.
- * @returns {String} The URI normalized to lower case.
-*/
-function normalizeURICase(uri) {
-    var uriInfo = getURIInfo(uri);
-    var scheme = uriInfo.scheme;
-    var authority = uriInfo.authority;
-
-    if (scheme) {
-        uriInfo.scheme = scheme.toLowerCase();
-        if (authority) {
-            var matches = uriAuthorityRegEx.exec(authority);
-            if (matches) {
-                uriInfo.authority = "//" +
-                (matches[1] ? matches[1] + "@" : "") +
-                (matches[2].toLowerCase()) +
-                (matches[3] ? ":" + matches[3] : "");
-            }
-        }
-    }
-
-    uri = getURIFromInfo(uriInfo);
-
-    return uri.replace(pctEncodingRegEx, function (str) {
-        return str.toLowerCase();
-    });
-}
-
-/** Normalizes a possibly relative URI with a base URI.
- * @param {String} uri - URI to normalize, absolute or relative
- * @param {String} base - Base URI to compose with (may be null)
- * @returns {String} The composed URI if relative; the original one if absolute.
- */
-function normalizeURI(uri, base) {
-    if (!base) {
-        return uri;
-    }
-
-    var uriInfo = getURIInfo(uri);
-    if (uriInfo.isAbsolute) {
-        return uri;
-    }
-
-    var baseInfo = getURIInfo(base);
-    var normInfo = {};
-    var path;
-
-    if (uriInfo.authority) {
-        normInfo.authority = uriInfo.authority;
-        path = uriInfo.path;
-        normInfo.query = uriInfo.query;
-    } else {
-        if (!uriInfo.path) {
-            path = baseInfo.path;
-            normInfo.query = uriInfo.query || baseInfo.query;
-        } else {
-            if (uriInfo.path.charAt(0) === '/') {
-                path = uriInfo.path;
-            } else {
-                path = mergeUriPathWithBase(uriInfo.path, baseInfo.path);
-            }
-            normInfo.query = uriInfo.query;
-        }
-        normInfo.authority = baseInfo.authority;
-    }
-
-    normInfo.path = removeDotsFromPath(path);
-
-    normInfo.scheme = baseInfo.scheme;
-    normInfo.fragment = uriInfo.fragment;
-
-    return getURIFromInfo(normInfo);
-}
-
-/** Merges the path of a relative URI and a base URI.
- * @param {String} uriPath - Relative URI path.</param>
- * @param {String} basePath - Base URI path.
- * @returns {String} A string with the merged path.
- */
-function mergeUriPathWithBase(uriPath, basePath) {
-    var path = "/";
-    var end;
-
-    if (basePath) {
-        end = basePath.lastIndexOf("/");
-        path = basePath.substring(0, end);
-
-        if (path.charAt(path.length - 1) !== "/") {
-            path = path + "/";
-        }
-    }
-
-    return path + uriPath;
-}
-
-/** Removes the special folders . and .. from a URI's path.
- * @param {string} path - URI path component.
- * @returns {String} Path without any . and .. folders.
- */
-function removeDotsFromPath(path) {
-    var result = "";
-    var segment = "";
-    var end;
-
-    while (path) {
-        if (path.indexOf("..") === 0 || path.indexOf(".") === 0) {
-            path = path.replace(/^\.\.?\/?/g, "");
-        } else if (path.indexOf("/..") === 0) {
-            path = path.replace(/^\/\..\/?/g, "/");
-            end = result.lastIndexOf("/");
-            if (end === -1) {
-                result = "";
-            } else {
-                result = result.substring(0, end);
-            }
-        } else if (path.indexOf("/.") === 0) {
-            path = path.replace(/^\/\.\/?/g, "/");
-        } else {
-            segment = path;
-            end = path.indexOf("/", 1);
-            if (end !== -1) {
-                segment = path.substring(0, end);
-            }
-            result = result + segment;
-            path = path.replace(segment, "");
-        }
-    }
-    return result;
-}
-
-function convertByteArrayToHexString(str) {
-    var arr = [];
-    if (window.atob === undefined) {
-        arr = decodeBase64(str);
-    } else {
-        var binaryStr = window.atob(str);
-        for (var i = 0; i < binaryStr.length; i++) {
-            arr.push(binaryStr.charCodeAt(i));
-        }
-    }
-    var hexValue = "";
-    var hexValues = "0123456789ABCDEF";
-    for (var j = 0; j < arr.length; j++) {
-        var t = arr[j];
-        hexValue += hexValues[t >> 4];
-        hexValue += hexValues[t & 0x0F];
-    }
-    return hexValue;
-}
-
-function decodeBase64(str) {
-    var binaryString = "";
-    for (var i = 0; i < str.length; i++) {
-        var base65IndexValue = getBase64IndexValue(str[i]);
-        var binaryValue = "";
-        if (base65IndexValue !== null) {
-            binaryValue = base65IndexValue.toString(2);
-            binaryString += addBase64Padding(binaryValue);
-        }
-    }
-    var byteArray = [];
-    var numberOfBytes = parseInt(binaryString.length / 8, 10);
-    for (i = 0; i < numberOfBytes; i++) {
-        var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2);
-        byteArray.push(intValue);
-    }
-    return byteArray;
-}
-
-function getBase64IndexValue(character) {
-    var asciiCode = character.charCodeAt(0);
-    var asciiOfA = 65;
-    var differenceBetweenZanda = 6;
-    if (asciiCode >= 65 && asciiCode <= 90) {           // between "A" and "Z" inclusive
-        return asciiCode - asciiOfA;
-    } else if (asciiCode >= 97 && asciiCode <= 122) {   // between 'a' and 'z' inclusive
-        return asciiCode - asciiOfA - differenceBetweenZanda;
-    } else if (asciiCode >= 48 && asciiCode <= 57) {    // between '0' and '9' inclusive
-        return asciiCode + 4;
-    } else if (character == "+") {
-        return 62;
-    } else if (character == "/") {
-        return 63;
-    } else {
-        return null;
-    }
-}
-
-function addBase64Padding(binaryString) {
-    while (binaryString.length < 6) {
-        binaryString = "0" + binaryString;
-    }
-    return binaryString;
-
-}
-
-function getJsonValueArraryLength(data) {
-    if (data && data.value) {
-        return data.value.length;
-    }
-
-    return 0;
-}
-
-function sliceJsonValueArray(data, start, end) {
-    if (data === undefined || data.value === undefined) {
-        return data;
-    }
-
-    if (start < 0) {
-        start = 0;
-    }
-
-    var length = getJsonValueArraryLength(data);
-    if (length < end) {
-        end = length;
-    }
-
-    var newdata = {};
-    for (var property in data) {
-        if (property == "value") {
-            newdata[property] = data[property].slice(start, end);
-        } else {
-            newdata[property] = data[property];
-        }
-    }
-
-    return newdata;
-}
-
-function concatJsonValueArray(data, concatData) {
-    if (concatData === undefined || concatData.value === undefined) {
-        return data;
-    }
-
-    if (data === undefined || Object.keys(data).length === 0) {
-        return concatData;
-    }
-
-    if (data.value === undefined) {
-        data.value = concatData.value;
-        return data;
-    }
-
-    data.value = data.value.concat(concatData.value);
-
-    return data;
-}
-
-function endsWith(input, search) {
-    return input.indexOf(search, input.length - search.length) !== -1;
-}
-
-function startsWith (input, search) {
-    return input.indexOf(search) === 0;
-}
-
-function getFormatKind(format, defaultFormatKind) {
-    var formatKind = defaultFormatKind;
-    if (!assigned(format)) {
-        return formatKind;
-    }
-
-    var normalizedFormat = format.toLowerCase();
-    switch (normalizedFormat) {
-        case "none":
-            formatKind = 0;
-            break;
-        case "minimal":
-            formatKind = 1;
-            break;
-        case "full":
-            formatKind = 2;
-            break;
-        default:
-            break;
-    }
-
-    return formatKind;
-}
-
-
-    
-    
-exports.inBrowser = inBrowser;
-exports.activeXObject = activeXObject;
-exports.assigned = assigned;
-exports.contains = contains;
-exports.defined = defined;
-exports.delay = delay;
-exports.djsassert = djsassert;
-exports.extend = extend;
-exports.find = find;
-exports.getURIInfo = getURIInfo;
-exports.isArray = isArray;
-exports.isDate = isDate;
-exports.isObject = isObject;
-exports.normalizeURI = normalizeURI;
-exports.normalizeURICase = normalizeURICase;
-exports.parseInt10 = parseInt10;
-exports.renameProperty = renameProperty;
-exports.throwErrorCallback = throwErrorCallback;
-exports.trimString = trimString;
-exports.undefinedDefault = undefinedDefault;
-exports.decodeBase64 = decodeBase64;
-exports.convertByteArrayToHexString = convertByteArrayToHexString;
-exports.getJsonValueArraryLength = getJsonValueArraryLength;
-exports.sliceJsonValueArray = sliceJsonValueArray;
-exports.concatJsonValueArray = concatJsonValueArray;
-exports.startsWith = startsWith;
-exports.endsWith = endsWith;
-exports.getFormatKind = getFormatKind;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/datajs/xml.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/datajs/xml.js b/datajs/src/lib/datajs/xml.js
deleted file mode 100644
index b8af4fe..0000000
--- a/datajs/src/lib/datajs/xml.js
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- 
-
-/** @module datajs/xml */
-
-var utils    = require('./utils.js');
-
-var activeXObject = utils.activeXObject;
-var djsassert = utils.djsassert;
-var extend = utils.extend;
-var isArray = utils.isArray;
-var normalizeURI = utils.normalizeURI;
-
-// URI prefixes to generate smaller code.
-var http = "http://";
-var w3org = http + "www.w3.org/";               // http://www.w3.org/
-
-var xhtmlNS = w3org + "1999/xhtml";             // http://www.w3.org/1999/xhtml
-var xmlnsNS = w3org + "2000/xmlns/";            // http://www.w3.org/2000/xmlns/
-var xmlNS = w3org + "XML/1998/namespace";       // http://www.w3.org/XML/1998/namespace
-
-var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml";
-
-/** Checks whether the specified string has leading or trailing spaces.
- * @param {String} text - String to check.
- * @returns {Boolean} true if text has any leading or trailing whitespace; false otherwise.
- */
-function hasLeadingOrTrailingWhitespace(text) {
-    var re = /(^\s)|(\s$)/;
-    return re.test(text);
-}
-
-/** Determines whether the specified text is empty or whitespace.
- * @param {String} text - Value to inspect.
- * @returns {Boolean} true if the text value is empty or all whitespace; false otherwise.
- */
-function isWhitespace(text) {
-
-
-    var ws = /^\s*$/;
-    return text === null || ws.test(text);
-}
-
-/** Determines whether the specified element has xml:space='preserve' applied.
- * @param domElement - Element to inspect.
- * @returns {Boolean} Whether xml:space='preserve' is in effect.
- */
-function isWhitespacePreserveContext(domElement) {
-
-
-    while (domElement !== null && domElement.nodeType === 1) {
-        var val = xmlAttributeValue(domElement, "space", xmlNS);
-        if (val === "preserve") {
-            return true;
-        } else if (val === "default") {
-            break;
-        } else {
-            domElement = domElement.parentNode;
-        }
-    }
-
-    return false;
-}
-
-/** Determines whether the attribute is a XML namespace declaration.
- * @param domAttribute - Element to inspect.
- * @return {Boolean} True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise.
- */
-function isXmlNSDeclaration(domAttribute) {
-    var nodeName = domAttribute.nodeName;
-    return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0;
-}
-
-/** Safely set as property in an object by invoking obj.setProperty.
- * @param obj - Object that exposes a setProperty method.
- * @param {String} name - Property name
- * @param value - Property value.
- */
-function safeSetProperty(obj, name, value) {
-
-
-    try {
-        obj.setProperty(name, value);
-    } catch (_) { }
-}
-
-/** Creates an configures new MSXML 3.0 ActiveX object.
- * @returns {Object} New MSXML 3.0 ActiveX object.
- * This function throws any exception that occurs during the creation
- * of the MSXML 3.0 ActiveX object.
- */
-function msXmlDom3() {
-    var msxml3 = activeXObject("Msxml2.DOMDocument.3.0");
-    if (msxml3) {
-        safeSetProperty(msxml3, "ProhibitDTD", true);
-        safeSetProperty(msxml3, "MaxElementDepth", 256);
-        safeSetProperty(msxml3, "AllowDocumentFunction", false);
-        safeSetProperty(msxml3, "AllowXsltScript", false);
-    }
-    return msxml3;
-}
-
-/** Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.
- * @returns {Object} New MSXML 3.0 ActiveX object.
- * This function will try to create a new MSXML 6.0 ActiveX object. If it fails then
- * it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that
- * happens during the creation of the MSXML 6.0 will be handled by the function while
- * the ones that happend during the creation of the MSXML 3.0 will be thrown.
- */
-function msXmlDom() {
-    try {
-        var msxml = activeXObject("Msxml2.DOMDocument.6.0");
-        if (msxml) {
-            msxml.async = true;
-        }
-        return msxml;
-    } catch (_) {
-        return msXmlDom3();
-    }
-}
-
-/** Parses an XML string using the MSXML DOM.
- * @returns {Object} New MSXML DOMDocument node representing the parsed XML string.
- * This function throws any exception that occurs during the creation
- * of the MSXML ActiveX object.  It also will throw an exception
- * in case of a parsing error.
- */
-function msXmlParse(text) {
-    var dom = msXmlDom();
-    if (!dom) {
-        return null;
-    }
-
-    dom.loadXML(text);
-    var parseError = dom.parseError;
-    if (parseError.errorCode !== 0) {
-        xmlThrowParserError(parseError.reason, parseError.srcText, text);
-    }
-    return dom;
-}
-
-/** Throws a new exception containing XML parsing error information.
- * @param exceptionOrReason - String indicating the reason of the parsing failure or Object detailing the parsing error.
- * @param {String} srcText -     String indicating the part of the XML string that caused the parsing error.
- * @param {String} errorXmlText - XML string for wich the parsing failed.
- */
-function xmlThrowParserError(exceptionOrReason, srcText, errorXmlText) {
-
-    if (typeof exceptionOrReason === "string") {
-        exceptionOrReason = { message: exceptionOrReason };
-    }
-    throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" });
-}
-
-/** Returns an XML DOM document from the specified text.
- * @param {String} text - Document text.
- * @returns XML DOM document.
- * This function will throw an exception in case of a parse error
- */
-function xmlParse(text) {
-    var domParser = window.DOMParser && new window.DOMParser();
-    var dom;
-
-    if (!domParser) {
-        dom = msXmlParse(text);
-        if (!dom) {
-            xmlThrowParserError("XML DOM parser not supported");
-        }
-        return dom;
-    }
-
-    try {
-        dom = domParser.parseFromString(text, "text/xml");
-    } catch (e) {
-        xmlThrowParserError(e, "", text);
-    }
-
-    var element = dom.documentElement;
-    var nsURI = element.namespaceURI;
-    var localName = xmlLocalName(element);
-
-    // Firefox reports errors by returing the DOM for an xml document describing the problem.
-    if (localName === "parsererror" && nsURI === mozillaParserErroNS) {
-        var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext");
-        var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : "";
-        xmlThrowParserError(xmlInnerText(element) || "", srcText, text);
-    }
-
-    // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message.
-    // The error may be localized, so instead we simply check for a header as the
-    // top element or descendant child of the document.
-    if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) {
-        var reason = "";
-        var siblings = [];
-        var cursor = element.firstChild;
-        while (cursor) {
-            if (cursor.nodeType === 1) {
-                reason += xmlInnerText(cursor) || "";
-            }
-            siblings.push(cursor.nextSibling);
-            cursor = cursor.firstChild || siblings.shift();
-        }
-        reason += xmlInnerText(element) || "";
-        xmlThrowParserError(reason, "", text);
-    }
-
-    return dom;
-}
-
-/** Builds a XML qualified name string in the form of "prefix:name".
- * @param {String} prefix - Prefix string (may be null)
- * @param {String} name - Name string to qualify with the prefix.
- * @returns {String} Qualified name.
- */
-function xmlQualifiedName(prefix, name) {
-    return prefix ? prefix + ":" + name : name;
-}
-
-/** Appends a text node into the specified DOM element node.
- * @param domNode - DOM node for the element.
- * @param {String} text - Text to append as a child of element.
-*/
-function xmlAppendText(domNode, textNode) {
-    if (hasLeadingOrTrailingWhitespace(textNode.data)) {
-        var attr = xmlAttributeNode(domNode, xmlNS, "space");
-        if (!attr) {
-            attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space"));
-            xmlAppendChild(domNode, attr);
-        }
-        attr.value = "preserve";
-    }
-    domNode.appendChild(textNode);
-    return domNode;
-}
-
-/** Iterates through the XML element's attributes and invokes the callback function for each one.
- * @param element - Wrapped element to iterate over.
- * @param {Function} onAttributeCallback - Callback function to invoke with wrapped attribute nodes.
-*/
-function xmlAttributes(element, onAttributeCallback) {
-    var attributes = element.attributes;
-    var i, len;
-    for (i = 0, len = attributes.length; i < len; i++) {
-        onAttributeCallback(attributes.item(i));
-    }
-}
-
-/** Returns the value of a DOM element's attribute.
- * @param domNode - DOM node for the owning element.
- * @param {String} localName - Local name of the attribute.
- * @param {String} nsURI - Namespace URI of the attribute.
- * @returns {String} - The attribute value, null if not found (may be null)
- */
-function xmlAttributeValue(domNode, localName, nsURI) {
-
-    var attribute = xmlAttributeNode(domNode, localName, nsURI);
-    return attribute ? xmlNodeValue(attribute) : null;
-}
-
-/** Gets an attribute node from a DOM element.
- * @param domNode - DOM node for the owning element.
- * @param {String} localName - Local name of the attribute.
- * @param {String} nsURI - Namespace URI of the attribute.
- * @returns The attribute node, null if not found.
- */
-function xmlAttributeNode(domNode, localName, nsURI) {
-
-    var attributes = domNode.attributes;
-    if (attributes.getNamedItemNS) {
-        return attributes.getNamedItemNS(nsURI || null, localName);
-    }
-
-    return attributes.getQualifiedItem(localName, nsURI) || null;
-}
-
-/** Gets the value of the xml:base attribute on the specified element.
- * @param domNode - Element to get xml:base attribute value from.
- * @param [baseURI] - Base URI used to normalize the value of the xml:base attribute ( may be null)
- * @returns {String} Value of the xml:base attribute if found; the baseURI or null otherwise.
- */
-function xmlBaseURI(domNode, baseURI) {
-
-    var base = xmlAttributeNode(domNode, "base", xmlNS);
-    return (base ? normalizeURI(base.value, baseURI) : baseURI) || null;
-}
-
-
-/** Iterates through the XML element's child DOM elements and invokes the callback function for each one.
- * @param element - DOM Node containing the DOM elements to iterate over.
- * @param {Function} onElementCallback - Callback function to invoke for each child DOM element.
-*/
-function xmlChildElements(domNode, onElementCallback) {
-
-    xmlTraverse(domNode, /*recursive*/false, function (child) {
-        if (child.nodeType === 1) {
-            onElementCallback(child);
-        }
-        // continue traversing.
-        return true;
-    });
-}
-
-/** Gets the descendant element under root that corresponds to the specified path and namespace URI.
- * @param root - DOM element node from which to get the descendant element.
- * @param {String} namespaceURI - The namespace URI of the element to match.
- * @param {String} path - Path to the desired descendant element.
- * @return The element specified by path and namespace URI.
- * All the elements in the path are matched against namespaceURI.
- * The function will stop searching on the first element that doesn't match the namespace and the path.
- */
-function xmlFindElementByPath(root, namespaceURI, path) {
-    var parts = path.split("/");
-    var i, len;
-    for (i = 0, len = parts.length; i < len; i++) {
-        root = root && xmlFirstChildElement(root, namespaceURI, parts[i]);
-    }
-    return root || null;
-}
-
-/** Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.
- * @param root - DOM element node from which to get the descendant node.
- * @param {String} namespaceURI - The namespace URI of the node to match.
- * @param {String} path - Path to the desired descendant node.
- * @return The node specified by path and namespace URI.</returns>
-
-* This function will traverse the path and match each node associated to a path segement against the namespace URI.
-* The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered.
-* The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute.
-*/
-function xmlFindNodeByPath(root, namespaceURI, path) {
-    
-
-    var lastSegmentStart = path.lastIndexOf("/");
-    var nodePath = path.substring(lastSegmentStart + 1);
-    var parentPath = path.substring(0, lastSegmentStart);
-
-    var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root;
-    if (node) {
-        if (nodePath.charAt(0) === "@") {
-            return xmlAttributeNode(node, nodePath.substring(1), namespaceURI);
-        }
-        return xmlFirstChildElement(node, namespaceURI, nodePath);
-    }
-    return null;
-}
-
-/** Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.
- * @param domNode - DOM node from which the child DOM element is going to be retrieved.
- * @param {String} [namespaceURI] - 
- * @param {String} [localName] - 
- * @return The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns>
- */
-function xmlFirstChildElement(domNode, namespaceURI, localName) {
-
-    return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false);
-}
-
-/** Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
- * @param domNode - DOM node from which the descendant DOM element is going to be retrieved.
- * @param {String} [namespaceURI] - 
- * @param {String} [localName] - 
- * @return The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.
-*/
-function xmlFirstDescendantElement(domNode, namespaceURI, localName) {
-    if (domNode.getElementsByTagNameNS) {
-        var result = domNode.getElementsByTagNameNS(namespaceURI, localName);
-        return result.length > 0 ? result[0] : null;
-    }
-    return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true);
-}
-
-/** Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
- * @param domNode - DOM node from which the descendant DOM element is going to be retrieved.
- * @param {String} [namespaceURI] - 
- * @param {String} [localName] - 
- * @param {Boolean} recursive 
- * - True if the search should include all the descendants of the DOM node.  
- * - False if the search should be scoped only to the direct children of the DOM node.
- * @return The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.
- */
-function xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, recursive) {
-
-    var firstElement = null;
-    xmlTraverse(domNode, recursive, function (child) {
-        if (child.nodeType === 1) {
-            var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI;
-            var isExpectedNodeName = !localName || xmlLocalName(child) === localName;
-
-            if (isExpectedNamespace && isExpectedNodeName) {
-                firstElement = child;
-            }
-        }
-        return firstElement === null;
-    });
-    return firstElement;
-}
-
-/** Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.
- * @param domElement - Element to get values for.
- * @returns {String} Text for all direct children.
- */
-function xmlInnerText(xmlElement) {
-
-    var result = null;
-    var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement;
-    var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false;
-    var whitespacePreserveContext;
-
-    xmlTraverse(root, false, function (child) {
-        if (child.nodeType === 3 || child.nodeType === 4) {
-            // isElementContentWhitespace indicates that this is 'ignorable whitespace',
-            // but it's not defined by all browsers, and does not honor xml:space='preserve'
-            // in some implementations.
-            //
-            // If we can't tell either way, we walk up the tree to figure out whether
-            // xml:space is set to preserve; otherwise we discard pure-whitespace.
-            //
-            // For example <a>  <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'.
-            var text = xmlNodeValue(child);
-            var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text);
-            if (!shouldInclude) {
-                // Walk up the tree to figure out whether we are in xml:space='preserve' context
-                // for the cursor (needs to happen only once).
-                if (whitespacePreserveContext === undefined) {
-                    whitespacePreserveContext = isWhitespacePreserveContext(root);
-                }
-
-                shouldInclude = whitespacePreserveContext;
-            }
-
-            if (shouldInclude) {
-                if (!result) {
-                    result = text;
-                } else {
-                    result += text;
-                }
-            }
-        }
-        // Continue traversing?
-        return true;
-    });
-    return result;
-}
-
-/** Returns the localName of a XML node.
- * @param domNode - DOM node to get the value from.
- * @returns {String} localName of domNode.
- */
-function xmlLocalName(domNode) {
-
-    return domNode.localName || domNode.baseName;
-}
-
-/** Returns the namespace URI of a XML node.
- * @param node - DOM node to get the value from.
- * @returns {String} Namespace URI of domNode.
- */
-function xmlNamespaceURI(domNode) {
-
-    return domNode.namespaceURI || null;
-}
-
-/** Returns the value or the inner text of a XML node.
- * @param node - DOM node to get the value from.
- * @return Value of the domNode or the inner text if domNode represents a DOM element node.
- */
-function xmlNodeValue(domNode) {
-    
-    if (domNode.nodeType === 1) {
-        return xmlInnerText(domNode);
-    }
-    return domNode.nodeValue;
-}
-
-/** Walks through the descendants of the domNode and invokes a callback for each node.
- * @param domNode - DOM node whose descendants are going to be traversed.
- * @param {Boolean} recursive
- * - True if the traversal should include all the descenants of the DOM node.
- * - False if the traversal should be scoped only to the direct children of the DOM node.
- * @returns {String} Namespace URI of node.
- */
-function xmlTraverse(domNode, recursive, onChildCallback) {
-
-    var subtrees = [];
-    var child = domNode.firstChild;
-    var proceed = true;
-    while (child && proceed) {
-        proceed = onChildCallback(child);
-        if (proceed) {
-            if (recursive && child.firstChild) {
-                subtrees.push(child.firstChild);
-            }
-            child = child.nextSibling || subtrees.shift();
-        }
-    }
-}
-
-/** Returns the next sibling DOM element of the specified DOM node.
- * @param domNode - DOM node from which the next sibling is going to be retrieved.
- * @param {String} [namespaceURI] - 
- * @param {String} [localName] - 
- * @return The node's next sibling DOM element, null if there is none.</returns>
- */
-function xmlSiblingElement(domNode, namespaceURI, localName) {
-
-    var sibling = domNode.nextSibling;
-    while (sibling) {
-        if (sibling.nodeType === 1) {
-            var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI;
-            var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName;
-
-            if (isExpectedNamespace && isExpectedNodeName) {
-                return sibling;
-            }
-        }
-        sibling = sibling.nextSibling;
-    }
-    return null;
-}
-
-/** Creates a new empty DOM document node.
- * @return New DOM document node.</returns>
- *
- * This function will first try to create a native DOM document using
- * the browsers createDocument function.  If the browser doesn't
- * support this but supports ActiveXObject, then an attempt to create
- * an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt
- * for creating an MXSML 3.0 DOM will be made.  If this last attemp fails or
- * the browser doesn't support ActiveXObject then an exception will be thrown.
- */
-function xmlDom() {
-    var implementation = window.document.implementation;
-    return (implementation && implementation.createDocument) ?
-       implementation.createDocument(null, null, null) :
-       msXmlDom();
-}
-
-/** Appends a collection of child nodes or string values to a parent DOM node.
- * @param parent - DOM node to which the children will be appended.
- * @param {Array} children - Array containing DOM nodes or string values that will be appended to the parent.
- * @return The parent with the appended children or string values.</returns>
- *  If a value in the children collection is a string, then a new DOM text node is going to be created
- *  for it and then appended to the parent.
- */
-function xmlAppendChildren(parent, children) {
-    if (!isArray(children)) {
-        return xmlAppendChild(parent, children);
-    }
-
-    var i, len;
-    for (i = 0, len = children.length; i < len; i++) {
-        children[i] && xmlAppendChild(parent, children[i]);
-    }
-    return parent;
-}
-
-/** Appends a child node or a string value to a parent DOM node.
- * @param parent - DOM node to which the child will be appended.
- * @param child - Child DOM node or string value to append to the parent.
- * @return The parent with the appended child or string value.</returns>
- * If child is a string value, then a new DOM text node is going to be created
- * for it and then appended to the parent.
- */
-function xmlAppendChild(parent, child) {
-
-    djsassert(parent !== child, "xmlAppendChild() - parent and child are one and the same!");
-    if (child) {
-        if (typeof child === "string") {
-            return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child));
-        }
-        if (child.nodeType === 2) {
-            parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child);
-        } else {
-            parent.appendChild(child);
-        }
-    }
-    return parent;
-}
-
-/** Creates a new DOM attribute node.
- * @param dom - DOM document used to create the attribute.
- * @param {String} prefix - Namespace prefix.
- * @param {String} namespaceURI - Namespace URI.
- * @return DOM attribute node for the namespace declaration.
- */
-function xmlNewAttribute(dom, namespaceURI, qualifiedName, value) {
-
-    var attribute =
-        dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
-        dom.createNode(2, qualifiedName, namespaceURI || undefined);
-
-    attribute.value = value || "";
-    return attribute;
-}
-
-/** Creates a new DOM element node.
- * @param dom - DOM document used to create the DOM element.
- * @param {String} namespaceURI - Namespace URI of the new DOM element.
- * @param {String} qualifiedName - Qualified name in the form of "prefix:name" of the new DOM element.
- * @param {Array} [children] Collection of child DOM nodes or string values that are going to be appended to the new DOM element.
- * @return New DOM element.</returns>
- * If a value in the children collection is a string, then a new DOM text node is going to be created
- * for it and then appended to the new DOM element.
- */
-function xmlNewElement(dom, nampespaceURI, qualifiedName, children) {
-    var element =
-        dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) ||
-        dom.createNode(1, qualifiedName, nampespaceURI || undefined);
-
-    return xmlAppendChildren(element, children || []);
-}
-
-/** Creates a namespace declaration attribute.
- * @param dom - DOM document used to create the attribute.
- * @param {String} namespaceURI - Namespace URI.
- * @param {String} prefix - Namespace prefix.
- * @return DOM attribute node for the namespace declaration.</returns>
- */
-function xmlNewNSDeclaration(dom, namespaceURI, prefix) {
-    return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI);
-}
-
-/** Creates a new DOM document fragment node for the specified xml text.
- * @param dom - DOM document from which the fragment node is going to be created.
- * @param {String} text XML text to be represented by the XmlFragment.
- * @return New DOM document fragment object.
- */
-function xmlNewFragment(dom, text) {
-
-    var value = "<c>" + text + "</c>";
-    var tempDom = xmlParse(value);
-    var tempRoot = tempDom.documentElement;
-    var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot;
-    var fragment = dom.createDocumentFragment();
-
-    var importedChild = imported.firstChild;
-    while (importedChild) {
-        fragment.appendChild(importedChild);
-        importedChild = importedChild.nextSibling;
-    }
-    return fragment;
-}
-
-/** Creates new DOM text node.
- * @param dom - DOM document used to create the text node.
- * @param {String} text - Text value for the DOM text node.
- * @return DOM text node.</returns>
- */ 
-function xmlNewText(dom, text) {
-    return dom.createTextNode(text);
-}
-
-/** Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.
- * @param dom - DOM document used to create the new node.
- * @param root - DOM element node used as root of the subtree on which the new nodes are going to be created.
- * @param {String} namespaceURI - Namespace URI of the new DOM element or attribute.
- * @param {String} namespacePrefix - Prefix used to qualify the name of the new DOM element or attribute.
- * @param {String} Path - Path string describing the location of the new DOM element or attribute from the root element.
- * @return DOM element or attribute node for the last segment of the path.</returns>
-
- * This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix
- * for each segment that doesn't have a matching element under root.
- * The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node
- * will be created.
- */
-function xmlNewNodeByPath(dom, root, namespaceURI, prefix, path) {
-    var name = "";
-    var parts = path.split("/");
-    var xmlFindNode = xmlFirstChildElement;
-    var xmlNewNode = xmlNewElement;
-    var xmlNode = root;
-
-    var i, len;
-    for (i = 0, len = parts.length; i < len; i++) {
-        name = parts[i];
-        if (name.charAt(0) === "@") {
-            name = name.substring(1);
-            xmlFindNode = xmlAttributeNode;
-            xmlNewNode = xmlNewAttribute;
-        }
-
-        var childNode = xmlFindNode(xmlNode, namespaceURI, name);
-        if (!childNode) {
-            childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name));
-            xmlAppendChild(xmlNode, childNode);
-        }
-        xmlNode = childNode;
-    }
-    return xmlNode;
-}
-
-/** Returns the text representation of the document to which the specified node belongs.
- * @param root - Wrapped element in the document to serialize.
- * @returns {String} Serialized document.
-*/
-function xmlSerialize(domNode) {
-    var xmlSerializer = window.XMLSerializer;
-    if (xmlSerializer) {
-        var serializer = new xmlSerializer();
-        return serializer.serializeToString(domNode);
-    }
-
-    if (domNode.xml) {
-        return domNode.xml;
-    }
-
-    throw { message: "XML serialization unsupported" };
-}
-
-/** Returns the XML representation of the all the descendants of the node.
- * @param domNode - Node to serialize.</param>
- * @returns {String} The XML representation of all the descendants of the node.
- */
-function xmlSerializeDescendants(domNode) {
-    var children = domNode.childNodes;
-    var i, len = children.length;
-    if (len === 0) {
-        return "";
-    }
-
-    // Some implementations of the XMLSerializer don't deal very well with fragments that
-    // don't have a DOMElement as their first child. The work around is to wrap all the
-    // nodes in a dummy root node named "c", serialize it and then just extract the text between
-    // the <c> and the </c> substrings.
-
-    var dom = domNode.ownerDocument;
-    var fragment = dom.createDocumentFragment();
-    var fragmentRoot = dom.createElement("c");
-
-    fragment.appendChild(fragmentRoot);
-    // Move the children to the fragment tree.
-    for (i = 0; i < len; i++) {
-        fragmentRoot.appendChild(children[i]);
-    }
-
-    var xml = xmlSerialize(fragment);
-    xml = xml.substr(3, xml.length - 7);
-
-    // Move the children back to the original dom tree.
-    for (i = 0; i < len; i++) {
-        domNode.appendChild(fragmentRoot.childNodes[i]);
-    }
-
-    return xml;
-}
-
-/** Returns the XML representation of the node and all its descendants.
- * @param domNode - Node to serialize
- * @returns {String} The XML representation of the node and all its descendants.
- */
-function xmlSerializeNode(domNode) {
-
-    var xml = domNode.xml;
-    if (xml !== undefined) {
-        return xml;
-    }
-
-    if (window.XMLSerializer) {
-        var serializer = new window.XMLSerializer();
-        return serializer.serializeToString(domNode);
-    }
-
-    throw { message: "XML serialization unsupported" };
-}
-
-exports.http = http;
-exports.w3org = w3org;
-exports.xmlNS = xmlNS;
-exports.xmlnsNS = xmlnsNS;
-
-exports.hasLeadingOrTrailingWhitespace = hasLeadingOrTrailingWhitespace;
-exports.isXmlNSDeclaration = isXmlNSDeclaration;
-exports.xmlAppendChild = xmlAppendChild;
-exports.xmlAppendChildren = xmlAppendChildren;
-exports.xmlAttributeNode = xmlAttributeNode;
-exports.xmlAttributes = xmlAttributes;
-exports.xmlAttributeValue = xmlAttributeValue;
-exports.xmlBaseURI = xmlBaseURI;
-exports.xmlChildElements = xmlChildElements;
-exports.xmlFindElementByPath = xmlFindElementByPath;
-exports.xmlFindNodeByPath = xmlFindNodeByPath;
-exports.xmlFirstChildElement = xmlFirstChildElement;
-exports.xmlFirstDescendantElement = xmlFirstDescendantElement;
-exports.xmlInnerText = xmlInnerText;
-exports.xmlLocalName = xmlLocalName;
-exports.xmlNamespaceURI = xmlNamespaceURI;
-exports.xmlNodeValue = xmlNodeValue;
-exports.xmlDom = xmlDom;
-exports.xmlNewAttribute = xmlNewAttribute;
-exports.xmlNewElement = xmlNewElement;
-exports.xmlNewFragment = xmlNewFragment;
-exports.xmlNewNodeByPath = xmlNewNodeByPath;
-exports.xmlNewNSDeclaration = xmlNewNSDeclaration;
-exports.xmlNewText = xmlNewText;
-exports.xmlParse = xmlParse;
-exports.xmlQualifiedName = xmlQualifiedName;
-exports.xmlSerialize = xmlSerialize;
-exports.xmlSerializeDescendants = xmlSerializeDescendants;
-exports.xmlSiblingElement = xmlSiblingElement;

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata.js b/datajs/src/lib/odata.js
deleted file mode 100644
index 0249aa3..0000000
--- a/datajs/src/lib/odata.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- /** @module odata */
-
-// Imports
-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');
-var odataJson     = exports.json      = require('./odata/json.js');
-                    exports.batch     = require('./odata/batch.js');
-                    
-
-
-var utils = require('./datajs/utils.js');
-var assigned = utils.assigned;
-
-var defined = utils.defined;
-var throwErrorCallback = utils.throwErrorCallback;
-
-var invokeRequest = odataUtils.invokeRequest;
-var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
-var prepareRequest = odataUtils.prepareRequest;
-var metadataParser = odataMetadata.metadataParser;
-
-// CONTENT START
-
-var handlers = [odataJson.jsonHandler, odataHandler.textHandler];
-
-/** Dispatches an operation to handlers.
- * @param {String} handlerMethod - Name of handler method to invoke.
- * @param {Object} requestOrResponse - request/response argument for delegated call.
- * @param {Object} context - context argument for delegated call.
- */
-function dispatchHandler(handlerMethod, requestOrResponse, context) {
-
-    var i, len;
-    for (i = 0, len = handlers.length; i < len && !handlers[i][handlerMethod](requestOrResponse, context); i++) {
-    }
-
-    if (i === len) {
-        throw { message: "no handler for data" };
-    }
-}
-
-/** Default success handler for OData.
- * @param data - Data to process.
- */
-exports.defaultSuccess = function (data) {
-
-    window.alert(window.JSON.stringify(data));
-};
-
-exports.defaultError = throwErrorCallback;
-
-exports.defaultHandler = {
-
-        /** Reads the body of the specified response by delegating to JSON handlers.
-        * @param response - Response object.
-        * @param context - Operation context.
-        */
-        read: function (response, context) {
-
-            if (response && assigned(response.body) && response.headers["Content-Type"]) {
-                dispatchHandler("read", response, context);
-            }
-        },
-
-        /** Write the body of the specified request by delegating to JSON handlers.
-        * @param request - Reques tobject.
-        * @param context - Operation context.
-        */
-        write: function (request, context) {
-
-            dispatchHandler("write", request, context);
-        },
-
-        maxDataServiceVersion: MAX_DATA_SERVICE_VERSION,
-        accept: "application/json;q=0.9, */*;q=0.1"
-    };
-
-exports.defaultMetadata = []; //TODO check why is the defaultMetadata an Array? and not an Object.
-
-/** Reads data from the specified URL.
- * @param urlOrRequest - URL to read data from.
- * @param {Function} [success] - 
- * @param {Function} [error] - 
- * @param {Object} [handler] - 
- * @param {Object} [httpClient] - 
- * @param {Object} [metadata] - 
- */
-exports.read = function (urlOrRequest, success, error, handler, httpClient, metadata) {
-
-    var request;
-    if (urlOrRequest instanceof String || typeof urlOrRequest === "string") {
-        request = { requestUri: urlOrRequest };
-    } else {
-        request = urlOrRequest;
-    }
-
-    return exports.request(request, success, error, handler, httpClient, metadata);
-};
-
-/** Sends a request containing OData payload to a server.
- * @param {Object} request - Object that represents the request to be sent.
- * @param {Function} [success] - 
- * @param {Function} [error] - 
- * @param {Object} [handler] - 
- * @param {Object} [httpClient] - 
- * @param {Object} [metadata] - 
- */
-exports.request = function (request, success, error, handler, httpClient, metadata) {
-
-    success = success || exports.defaultSuccess;
-    error = error || exports.defaultError;
-    handler = handler || exports.defaultHandler;
-    httpClient = httpClient || odataNet.defaultHttpClient;
-    metadata = metadata || exports.defaultMetadata;
-
-    // Augment the request with additional defaults.
-    request.recognizeDates = utils.defined(request.recognizeDates, odataJson.jsonHandler.recognizeDates);
-    request.callbackParameterName = utils.defined(request.callbackParameterName, odataNet.defaultHttpClient.callbackParameterName);
-    request.formatQueryString = utils.defined(request.formatQueryString, odataNet.defaultHttpClient.formatQueryString);
-    request.enableJsonpCallback = utils.defined(request.enableJsonpCallback, odataNet.defaultHttpClient.enableJsonpCallback);
-
-    // Create the base context for read/write operations, also specifying complete settings.
-    var context = {
-        metadata: metadata,
-        recognizeDates: request.recognizeDates,
-        callbackParameterName: request.callbackParameterName,
-        formatQueryString: request.formatQueryString,
-        enableJsonpCallback: request.enableJsonpCallback
-    };
-
-    try {
-        odataUtils.prepareRequest(request, handler, context);
-        return odataUtils.invokeRequest(request, success, error, handler, httpClient, context);
-    } catch (err) {
-        // errors in success handler for sync requests are catched here and result in error handler calls. 
-        // So here we fix this and throw that error further.
-        if (err.bIsSuccessHandlerError) {
-            throw err;
-        } else {
-            error(err);
-        }
-    }
-
-};
-
-/** Parses the csdl metadata to DataJS metatdata format. This method can be used when the metadata is retrieved using something other than DataJS
- * @param {string} csdlMetadata - A string that represents the entire csdl metadata.
- * @returns {Object} An object that has the representation of the metadata in Datajs format.
- */
-exports.parseMetadata = function (csdlMetadataDocument) {
-
-    return metadataParser(null, csdlMetadataDocument);
-};
-
-// Configure the batch handler to use the default handler for the batch parts.
-exports.batch.batchHandler.partHandler = exports.defaultHandler;
-exports.metadataHandler =  odataMetadata.metadataHandler;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/batch.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/batch.js b/datajs/src/lib/odata/batch.js
deleted file mode 100644
index 5b006ff..0000000
--- a/datajs/src/lib/odata/batch.js
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module odata/batch */
-
-var utils    = require('./../datajs.js').utils;
-var odataUtils    = require('./utils.js');
-var odataHandler = require('./handler.js');
-
-var extend = utils.extend;
-var isArray = utils.isArray;
-var trimString = utils.trimString;
-
-var contentType = odataHandler.contentType;
-var handler = odataHandler.handler;
-var isBatch = odataUtils.isBatch;
-var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
-var normalizeHeaders = odataUtils.normalizeHeaders;
-//TODO var payloadTypeOf = odata.payloadTypeOf;
-var prepareRequest = odataUtils.prepareRequest;
-
-
-
-
-
-// Imports
-
-
-
-// CONTENT START
-var batchMediaType = "multipart/mixed";
-var responseStatusRegex = /^HTTP\/1\.\d (\d{3}) (.*)$/i;
-var responseHeaderRegex = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/;
-
-/* Calculates a random 16 bit number and returns it in hexadecimal format.
- * @returns {String} A 16-bit number in hex format.
- */
-function hex16() {
-
-    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substr(1);
-}
-
-/* Creates a string that can be used as a multipart request boundary.
- * @param {String} [prefix] - 
- * @returns {String} Boundary string of the format: <prefix><hex16>-<hex16>-<hex16>
- */
-function createBoundary(prefix) {
-
-    return prefix + hex16() + "-" + hex16() + "-" + hex16();
-}
-
-/* Gets the handler for data serialization of individual requests / responses in a batch.
- * @param context - Context used for data serialization.
- * @returns Handler object
- */
-function partHandler(context) {
-
-    return context.handler.partHandler;
-}
-
-/* Gets the current boundary used for parsing the body of a multipart response.
- * @param context - Context used for parsing a multipart response.
- * @returns {String} Boundary string.
- */
-function currentBoundary(context) {
-    var boundaries = context.boundaries;
-    return boundaries[boundaries.length - 1];
-}
-
-/** Parses a batch response.
- * @param handler - This handler.
- * @param {String} text - Batch text.
- * @param {Object} context - Object with parsing context.
- * @return An object representation of the batch.
- */
-function batchParser(handler, text, context) {
-
-    var boundary = context.contentType.properties["boundary"];
-    return { __batchResponses: readBatch(text, { boundaries: [boundary], handlerContext: context }) };
-}
-
-/** Serializes a batch object representation into text.
- * @param handler - This handler.
- * @param {Object} data - Representation of a batch.
- * @param {Object} context - Object with parsing context.
- * @return An text representation of the batch object; undefined if not applicable.#
- */
-function batchSerializer(handler, data, context) {
-
-    var cType = context.contentType = context.contentType || contentType(batchMediaType);
-    if (cType.mediaType === batchMediaType) {
-        return writeBatch(data, context);
-    }
-}
-
-/* Parses a multipart/mixed response body from from the position defined by the context.
- * @param {String}  text - Body of the multipart/mixed response.
- * @param context - Context used for parsing.
- * @return Array of objects representing the individual responses.
- */
-function readBatch(text, context) {
-    var delimiter = "--" + currentBoundary(context);
-
-    // Move beyond the delimiter and read the complete batch
-    readTo(text, context, delimiter);
-
-    // Ignore the incoming line
-    readLine(text, context);
-
-    // Read the batch parts
-    var responses = [];
-    var partEnd;
-
-    while (partEnd !== "--" && context.position < text.length) {
-        var partHeaders = readHeaders(text, context);
-        var partContentType = contentType(partHeaders["Content-Type"]);
-
-        var changeResponses;
-        if (partContentType && partContentType.mediaType === batchMediaType) {
-            context.boundaries.push(partContentType.properties.boundary);
-            try {
-                changeResponses = readBatch(text, context);
-            } catch (e) {
-                e.response = readResponse(text, context, delimiter);
-                changeResponses = [e];
-            }
-            responses.push({ __changeResponses: changeResponses });
-            context.boundaries.pop();
-            readTo(text, context, "--" + currentBoundary(context));
-        } else {
-            if (!partContentType || partContentType.mediaType !== "application/http") {
-                throw { message: "invalid MIME part type " };
-            }
-            // Skip empty line
-            readLine(text, context);
-            // Read the response
-            var response = readResponse(text, context, delimiter);
-            try {
-                if (response.statusCode >= 200 && response.statusCode <= 299) {
-                    partHandler(context.handlerContext).read(response, context.handlerContext);
-                } else {
-                    // Keep track of failed responses and continue processing the batch.
-                    response = { message: "HTTP request failed", response: response };
-                }
-            } catch (e) {
-                response = e;
-            }
-
-            responses.push(response);
-        }
-
-        partEnd = text.substr(context.position, 2);
-
-        // Ignore the incoming line.
-        readLine(text, context);
-    }
-    return responses;
-}
-
-/* Parses the http headers in the text from the position defined by the context.
-* @param {String} text - Text containing an http response's headers</param>
-* @param context - Context used for parsing.
-* @returns Object containing the headers as key value pairs.
-* This function doesn't support split headers and it will stop reading when it hits two consecutive line breaks.
-*/
-function readHeaders(text, context) {
-    var headers = {};
-    var parts;
-    var line;
-    var pos;
-
-    do {
-        pos = context.position;
-        line = readLine(text, context);
-        parts = responseHeaderRegex.exec(line);
-        if (parts !== null) {
-            headers[parts[1]] = parts[2];
-        } else {
-            // Whatever was found is not a header, so reset the context position.
-            context.position = pos;
-        }
-    } while (line && parts);
-
-    normalizeHeaders(headers);
-
-    return headers;
-}
-
-/* Parses an HTTP response.
- * @param {String} text -Text representing the http response.
- * @param context optional - Context used for parsing.
- * @param {String} delimiter -String used as delimiter of the multipart response parts.
- * @return Object representing the http response.
- */
-function readResponse(text, context, delimiter) {
-    // Read the status line.
-    var pos = context.position;
-    var match = responseStatusRegex.exec(readLine(text, context));
-
-    var statusCode;
-    var statusText;
-    var headers;
-
-    if (match) {
-        statusCode = match[1];
-        statusText = match[2];
-        headers = readHeaders(text, context);
-        readLine(text, context);
-    } else {
-        context.position = pos;
-    }
-
-    return {
-        statusCode: statusCode,
-        statusText: statusText,
-        headers: headers,
-        body: readTo(text, context, "\r\n" + delimiter)
-    };
-}
-
-/** Returns a substring from the position defined by the context up to the next line break (CRLF).
- * @param {String} text - Input string.
- * @param context - Context used for reading the input string.
- * @returns {String} Substring to the first ocurrence of a line break or null if none can be found. 
- */
-function readLine(text, context) {
-
-    return readTo(text, context, "\r\n");
-}
-
-/** Returns a substring from the position given by the context up to value defined by the str parameter and increments the position in the context.
- * @param {String} text - Input string.</param>
- * @param context - Context used for reading the input string.</param>
- * @param {String} [str] - Substring to read up to.
- * @returns {String} Substring to the first ocurrence of str or the end of the input string if str is not specified. Null if the marker is not found.
- */
-function readTo(text, context, str) {
-    var start = context.position || 0;
-    var end = text.length;
-    if (str) {
-        end = text.indexOf(str, start);
-        if (end === -1) {
-            return null;
-        }
-        context.position = end + str.length;
-    } else {
-        context.position = end;
-    }
-
-    return text.substring(start, end);
-}
-
-/** Serializes a batch request object to a string.
- * @param data - Batch request object in payload representation format
- * @param context - Context used for the serialization
- * @returns {String} String representing the batch request
- */
-function writeBatch(data, context) {
-    if (!isBatch(data)) {
-        throw { message: "Data is not a batch object." };
-    }
-
-    var batchBoundary = createBoundary("batch_");
-    var batchParts = data.__batchRequests;
-    var batch = "";
-    var i, len;
-    for (i = 0, len = batchParts.length; i < len; i++) {
-        batch += writeBatchPartDelimiter(batchBoundary, false) +
-                 writeBatchPart(batchParts[i], context);
-    }
-    batch += writeBatchPartDelimiter(batchBoundary, true);
-
-    // Register the boundary with the request content type.
-    var contentTypeProperties = context.contentType.properties;
-    contentTypeProperties.boundary = batchBoundary;
-
-    return batch;
-}
-
-/** Creates the delimiter that indicates that start or end of an individual request.
- * @param {String} boundary Boundary string used to indicate the start of the request</param>
- * @param {Boolean} close - Flag indicating that a close delimiter string should be generated
- * @returns {String} Delimiter string
- */
-function writeBatchPartDelimiter(boundary, close) {
-    var result = "\r\n--" + boundary;
-    if (close) {
-        result += "--";
-    }
-
-    return result + "\r\n";
-}
-
-/** Serializes a part of a batch request to a string. A part can be either a GET request or
- * a change set grouping several CUD (create, update, delete) requests.
- * @param part - Request or change set object in payload representation format</param>
- * @param context - Object containing context information used for the serialization</param>
- * @param {boolean} [nested] - 
- * @returns {String} String representing the serialized part
- * A change set is an array of request objects and they cannot be nested inside other change sets.
- */
-function writeBatchPart(part, context, nested) {
-    
-
-    var changeSet = part.__changeRequests;
-    var result;
-    if (isArray(changeSet)) {
-        if (nested) {
-            throw { message: "Not Supported: change set nested in other change set" };
-        }
-
-        var changeSetBoundary = createBoundary("changeset_");
-        result = "Content-Type: " + batchMediaType + "; boundary=" + changeSetBoundary + "\r\n";
-        var i, len;
-        for (i = 0, len = changeSet.length; i < len; i++) {
-            result += writeBatchPartDelimiter(changeSetBoundary, false) +
-                 writeBatchPart(changeSet[i], context, true);
-        }
-
-        result += writeBatchPartDelimiter(changeSetBoundary, true);
-    } else {
-        result = "Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\n";
-        var partContext = extend({}, context);
-        partContext.handler = handler;
-        partContext.request = part;
-        partContext.contentType = null;
-
-        prepareRequest(part, partHandler(context), partContext);
-        result += writeRequest(part);
-    }
-
-    return result;
-}
-
-/* Serializes a request object to a string.
- * @param request - Request object to serialize</param>
- * @returns {String} String representing the serialized request
- */
-function writeRequest(request) {
-    var result = (request.method ? request.method : "GET") + " " + request.requestUri + " HTTP/1.1\r\n";
-    for (var name in request.headers) {
-        if (request.headers[name]) {
-            result = result + name + ": " + request.headers[name] + "\r\n";
-        }
-    }
-
-    result += "\r\n";
-
-    if (request.body) {
-        result += request.body;
-    }
-
-    return result;
-}
-
-
-
-/** batchHandler (see {@link module:odata/batch~batchParser}) */
-exports.batchHandler = handler(batchParser, batchSerializer, batchMediaType, MAX_DATA_SERVICE_VERSION);
-exports.batchSerializer = batchSerializer;
-exports.writeRequest = writeRequest;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/src/lib/odata/handler.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/handler.js b/datajs/src/lib/odata/handler.js
deleted file mode 100644
index 3e85a1e..0000000
--- a/datajs/src/lib/odata/handler.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/** @module odata/handler */
-
-
-var utils    = require('./../datajs.js').utils;
-var oDataUtils    = require('./utils.js');
-
-// Imports.
-var assigned = utils.assigned;
-var extend = utils.extend;
-var trimString = utils.trimString;
-var maxVersion = oDataUtils.maxVersion;
-var MAX_DATA_SERVICE_VERSION = "4.0";
-
-/** Parses a string into an object with media type and properties.
- * @param {String} str - String with media type to parse.
- * @return null if the string is empty; an object with 'mediaType' and a 'properties' dictionary otherwise.
- */
-function contentType(str) {
-
-    if (!str) {
-        return null;
-    }
-
-    var contentTypeParts = str.split(";");
-    var properties = {};
-
-    var i, len;
-    for (i = 1, len = contentTypeParts.length; i < len; i++) {
-        var contentTypeParams = contentTypeParts[i].split("=");
-        properties[trimString(contentTypeParams[0])] = contentTypeParams[1];
-    }
-
-    return { mediaType: trimString(contentTypeParts[0]), properties: properties };
-}
-
-/** Serializes an object with media type and properties dictionary into a string.
- * @param contentType - Object with media type and properties dictionary to serialize.
- * @return String representation of the media type object; undefined if contentType is null or undefined.</returns>
- */
-function contentTypeToString(contentType) {
-    if (!contentType) {
-        return undefined;
-    }
-
-    var result = contentType.mediaType;
-    var property;
-    for (property in contentType.properties) {
-        result += ";" + property + "=" + contentType.properties[property];
-    }
-    return result;
-}
-
-/** Creates an object that is going to be used as the context for the handler's parser and serializer.
- * @param contentType - Object with media type and properties dictionary.
- * @param {String} dataServiceVersion - String indicating the version of the protocol to use.
- * @param context - Operation context.
- * @param handler - Handler object that is processing a resquest or response.
- * @return Context object.</returns>
- */
-function createReadWriteContext(contentType, dataServiceVersion, context, handler) {
-
-    var rwContext = {};
-    extend(rwContext, context);
-    extend(rwContext, {
-        contentType: contentType,
-        dataServiceVersion: dataServiceVersion,
-        handler: handler
-    });
-
-    return rwContext;
-}
-
-/** Sets a request header's value. If the header has already a value other than undefined, null or empty string, then this method does nothing.
- * @param request - Request object on which the header will be set.
- * @param {String} name - Header name.
- * @param {String} value - Header value.
- */
-function fixRequestHeader(request, name, value) {
-    if (!request) {
-        return;
-    }
-
-    var headers = request.headers;
-    if (!headers[name]) {
-        headers[name] = value;
-    }
-}
-
-/** Sets the DataServiceVersion header of the request if its value is not yet defined or of a lower version.
- * @param request - Request object on which the header will be set.
- * @param {String} version - Version value.
- *  If the request has already a version value higher than the one supplied the this function does nothing.
- */
-function fixDataServiceVersionHeader(request, version) {   
-
-    if (request) {
-        var headers = request.headers;
-        var dsv = headers["OData-Version"];
-        headers["OData-Version"] = dsv ? maxVersion(dsv, version) : version;
-    }
-}
-
-/** Gets the value of a request or response header.
- * @param requestOrResponse - Object representing a request or a response.
- * @param {String} name - Name of the header to retrieve.
- * @returns {String} String value of the header; undefined if the header cannot be found.
- */
-function getRequestOrResponseHeader(requestOrResponse, name) {
-
-    var headers = requestOrResponse.headers;
-    return (headers && headers[name]) || undefined;
-}
-
-/** Gets the value of the Content-Type header from a request or response.
- * @param requestOrResponse - Object representing a request or a response.
- * @returns {Object} Object with 'mediaType' and a 'properties' dictionary; null in case that the header is not found or doesn't have a value.
- */
-function getContentType(requestOrResponse) {
-
-    return contentType(getRequestOrResponseHeader(requestOrResponse, "Content-Type"));
-}
-
-var versionRE = /^\s?(\d+\.\d+);?.*$/;
-/** Gets the value of the DataServiceVersion header from a request or response.
- * @param requestOrResponse - Object representing a request or a response.
- * @returns {String} Data service version; undefined if the header cannot be found.
- */
-function getDataServiceVersion(requestOrResponse) {
-
-    var value = getRequestOrResponseHeader(requestOrResponse, "OData-Version");
-    if (value) {
-        var matches = versionRE.exec(value);
-        if (matches && matches.length) {
-            return matches[1];
-        }
-    }
-
-    // Fall through and return undefined.
-}
-
-/** Checks that a handler can process a particular mime type.
- * @param handler - Handler object that is processing a resquest or response.
- * @param cType - Object with 'mediaType' and a 'properties' dictionary.
- * @returns {Boolean} True if the handler can process the mime type; false otherwise.
- *
- * The following check isn't as strict because if cType.mediaType = application/; it will match an accept value of "application/xml";
- * however in practice we don't not expect to see such "suffixed" mimeTypes for the handlers.
- */
-function handlerAccepts(handler, cType) {
-    return handler.accept.indexOf(cType.mediaType) >= 0;
-}
-
-/** Invokes the parser associated with a handler for reading the payload of a HTTP response.
- * @param handler - Handler object that is processing the response.
- * @param {Function} parseCallback - Parser function that will process the response payload.
- * @param response - HTTP response whose payload is going to be processed.
- * @param context - Object used as the context for processing the response.
- * @returns {Boolean} True if the handler processed the response payload and the response.data property was set; false otherwise.
- */
-function handlerRead(handler, parseCallback, response, context) {
-
-    if (!response || !response.headers) {
-        return false;
-    }
-
-    var cType = getContentType(response);
-    var version = getDataServiceVersion(response) || "";
-    var body = response.body;
-
-    if (!assigned(body)) {
-        return false;
-    }
-
-    if (handlerAccepts(handler, cType)) {
-        var readContext = createReadWriteContext(cType, version, context, handler);
-        readContext.response = response;
-        response.data = parseCallback(handler, body, readContext);
-        return response.data !== undefined;
-    }
-
-    return false;
-}
-
-/** Invokes the serializer associated with a handler for generating the payload of a HTTP request.
- * @param handler - Handler object that is processing the request.
- * @param {Function} serializeCallback - Serializer function that will generate the request payload.
- * @param response - HTTP request whose payload is going to be generated.
- * @param context - Object used as the context for serializing the request.
- * @returns {Boolean} True if the handler serialized the request payload and the request.body property was set; false otherwise.
- */
-function handlerWrite(handler, serializeCallback, request, context) {
-    if (!request || !request.headers) {
-        return false;
-    }
-
-    var cType = getContentType(request);
-    var version = getDataServiceVersion(request);
-
-    if (!cType || handlerAccepts(handler, cType)) {
-        var writeContext = createReadWriteContext(cType, version, context, handler);
-        writeContext.request = request;
-
-        request.body = serializeCallback(handler, request.data, writeContext);
-
-        if (request.body !== undefined) {
-            fixDataServiceVersionHeader(request, writeContext.dataServiceVersion || "4.0");
-
-            fixRequestHeader(request, "Content-Type", contentTypeToString(writeContext.contentType));
-            fixRequestHeader(request, "OData-MaxVersion", handler.maxDataServiceVersion);
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/** Creates a handler object for processing HTTP requests and responses.
- * @param {Function} parseCallback - Parser function that will process the response payload.
- * @param {Function} serializeCallback - Serializer function that will generate the request payload.
- * @param {String} accept - String containing a comma separated list of the mime types that this handler can work with.
- * @param {String} maxDataServiceVersion - String indicating the highest version of the protocol that this handler can work with.
- * @returns {Object} Handler object.
- */
-function handler(parseCallback, serializeCallback, accept, maxDataServiceVersion) {
-
-    return {
-        accept: accept,
-        maxDataServiceVersion: maxDataServiceVersion,
-
-        read: function (response, context) {
-            return handlerRead(this, parseCallback, response, context);
-        },
-
-        write: function (request, context) {
-            return handlerWrite(this, serializeCallback, request, context);
-        }
-    };
-}
-
-function textParse(handler, body /*, context */) {
-    return body;
-}
-
-function textSerialize(handler, data /*, context */) {
-    if (assigned(data)) {
-        return data.toString();
-    } else {
-        return undefined;
-    }
-}
-
-
-
-
-exports.textHandler = handler(textParse, textSerialize, "text/plain", MAX_DATA_SERVICE_VERSION);
-
-exports.contentType = contentType;
-exports.contentTypeToString = contentTypeToString;
-exports.handler = handler;
-exports.createReadWriteContext = createReadWriteContext;
-exports.fixRequestHeader = fixRequestHeader;
-exports.getRequestOrResponseHeader = getRequestOrResponseHeader;
-exports.getContentType = getContentType;
-exports.getDataServiceVersion = getDataServiceVersion;
-exports.MAX_DATA_SERVICE_VERSION = MAX_DATA_SERVICE_VERSION;
\ No newline at end of file


[34/51] [partial] rename folder /datajs into /odatajs. no file modification.

Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/EpmDataService.svc b/datajs/tests/endpoints/EpmDataService.svc
deleted file mode 100644
index 316c9ae..0000000
--- a/datajs/tests/endpoints/EpmDataService.svc
+++ /dev/null
@@ -1,336 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.EpmDataService" %>
-
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel.Web;
-
-    /// <summary>
-    /// A data service that uses EPM
-    /// </summary>
-    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class EpmDataService : DataService<EpmDataSource>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-            config.UseVerboseErrors = true;
-
-        }
-        
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-    }
-
-    public class EpmDataSource : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<MappedEntry> MappedEntries
-        {
-            get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
-        }
-
-        public IQueryable<ReplicatedEntry> ReplicatedEntries
-        {
-            get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
-        }
-
-        public IQueryable<BaseEntry> HierarchicalEntries
-        {
-            get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            MappedEntry[] mappedEntries = new MappedEntry[]
-            {
-                new MappedEntry
-                {
-                    ID = 0,
-                    UnmappedField = "Unmapped0",
-                    Author = new Author
-                    {
-                        Email = "AuthorEmail0",
-                        Name = "AuthorName0",
-                        Uri = "http://www.example.com/AuthorUri",
-                        Contributor = new Contributor
-                        {
-                            Email = "ContributorEmail0",
-                            Name = "ContributorName0",
-                            Uri = "http://www.example.com/ContributorUri",
-                        },
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = "Rights0",
-                    Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
-                    Title = "Title<b>0</b>",
-                    Updated = "2000-01-01T00:00:00-08:00",
-                    CustomElement = "CustomElement0",
-                    CustomAttribute = "CustomAttribute0",
-                    NestedElement1 = "NestedElement1_0",
-                    NestedElement2 = "NestedElement2_0",
-                    CommonAttribute1 = "CommonAttribute1_0",
-                    CommonAttribute2 = "CommonAttribute2_0",
-                    Location = new Location
-                    {
-                        Lat = 3.14f,
-                        Long = 2.72f
-                    }
-                },
-                
-                new MappedEntry
-                {
-                    ID = 1,
-                    UnmappedField = null,
-                    Author = new Author
-                    {
-                        Email = null,
-                        Name = string.Empty,
-                        Uri = "http://www.example.com/AuthorUri1",
-                        Contributor = new Contributor
-                        {
-                            Email = null,
-                            Name = string.Empty,
-                            Uri = "http://www.example.com/ContributorUri1",
-                        },
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = null,
-                    Summary = "",
-                    Title = "Title<i>1</i>",
-                    Updated = "2111-01-01T00:00:00-08:00",
-                    CustomElement = null,
-                    NestedElement1 = string.Empty,
-                    NestedElement2 = "NestedElement2_1",
-                    CustomAttribute = null,
-                    CommonAttribute1 = string.Empty,
-                    CommonAttribute2 = "CommonAttribute2_1",
-                    Location = new Location
-                    {
-                        Lat = float.MaxValue,
-                        Long = float.MinValue
-                    }
-                },
-                
-                new MappedEntry
-                {
-                    ID = 2,
-                    UnmappedField = "Unmapped2",
-                    Author = new Author
-                    {
-                        Email = "AuthorEmail2",
-                        Name = "AuthorName2",
-                        Uri = "http://www.example.com/AuthorUri2",
-                        Contributor = null
-                    },
-                    Published = "2000-01-01T00:00:00-08:00",
-                    Rights = "Rights2",
-                    Summary = "Summary2",
-                    Title = "Title2",
-                    Updated = "2000-01-01T00:00:00-08:00",
-                    CustomElement = "CustomElement2",
-                    CustomAttribute = "CustomAttribute2",
-                    NestedElement1 = "NestedElement1_2",
-                    NestedElement2 = "NestedElement2_2",
-                    CommonAttribute1 = "CommonAttribute1_2",
-                    CommonAttribute2 = "CommonAttribute2_2",
-                    Location = null
-                },
-            };
-            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
-
-            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
-            {
-                ID = item.ID,
-                UnmappedField = item.UnmappedField,
-                Author = item.Author == null ? null : new Author2
-                {
-                    Email = item.Author.Email,
-                    Name = item.Author.Name,
-                    Uri = item.Author.Uri,
-                    Contributor = item.Author.Contributor == null ? null : new Contributor2
-                    {
-                        Name = item.Author.Contributor.Name,
-                        Email = item.Author.Contributor.Email,
-                        Uri = item.Author.Contributor.Uri
-                    },
-                },
-                Published = item.Published,
-                Rights = item.Rights,
-                Summary = item.Summary,
-                Title = item.Title,
-                Updated = item.Updated,
-                CustomElement = item.CustomElement,
-                CustomAttribute = item.CustomAttribute,
-                NestedElement1 = item.NestedElement1,
-                NestedElement2 = item.NestedElement2,
-                CommonAttribute1 = item.CommonAttribute1,
-                CommonAttribute2 = item.CommonAttribute2,
-                Location = item.Location == null ? null : new Location2
-                {
-                    Lat = item.Location.Lat,
-                    Long = item.Location.Long
-                }
-            }));
-
-            BaseEntry[] hierarchicalEntries = new BaseEntry[]
-            {
-                new BaseEntry
-                {
-                    ID = 0,
-                    MappedField = "MappedField0",
-                    MappedInDerivedField = "MappedInDerivedField0",
-                    UnmappedField = "UnmappedField0"
-                },
-                new DerivedEntry
-                {
-                    ID = 1,
-                    MappedField = "MappedField1",
-                    MappedInDerivedField = "MappedInDerivedField1",
-                    UnmappedField = "UnmappedField1",
-                    MappedConcreteField = "MappedConcreteField1",
-                    UnmappedConcreteField = "UnmappedConcreteField1"
-                },
-            };
-            Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Author
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-        public Contributor Contributor { get; set; }
-    }
-
-    public class Contributor
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-    }
-    
-    public class Location
-    {
-        public float Lat { get; set; }
-        public float Long { get; set; }
-    }
-
-    public class Author2
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-        public Contributor2 Contributor { get; set; }
-    }
-
-    public class Contributor2
-    {
-        public string Email { get; set; }
-        public string Name { get; set; }
-        public string Uri { get; set; }
-    }
-
-    public class Location2
-    {
-        public float Lat { get; set; }
-        public float Long { get; set; }
-    }
-    
-    public class MappedEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public Author Author { get; set; }
-        public string Published { get; set; }
-        public string Rights { get; set; }
-        public string Summary { get; set; }
-        public string Title { get; set; }
-        public string Updated { get; set; }
-        public string CustomElement { get; set; }
-        public string CustomAttribute { get; set; }
-        public string NestedElement1 { get; set; }
-        public string NestedElement2 { get; set; }
-        public string CommonAttribute1 { get; set; }
-        public string CommonAttribute2 { get; set; }
-        public Location Location { get; set; }
-    }
-
-    public class ReplicatedEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public Author2 Author { get; set; }
-        public string Published { get; set; }
-        public string Rights { get; set; }
-        public string Summary { get; set; }
-        public string Title { get; set; }
-        public string Updated { get; set; }
-        public string CustomElement { get; set; }
-        public string CustomAttribute { get; set; }
-        public string NestedElement1 { get; set; }
-        public string NestedElement2 { get; set; }
-        public string CommonAttribute1 { get; set; }
-        public string CommonAttribute2 { get; set; }
-        public Location2 Location { get; set; }
-    }
-    
-    public class BaseEntry
-    {
-        public int ID { get; set; }
-        public string UnmappedField { get; set; }
-        public string MappedInDerivedField { get; set; }
-        public string MappedField { get; set; }
-    }
-    
-    public class DerivedEntry : BaseEntry
-    {
-        public string UnmappedConcreteField { get; set; }
-        public string MappedConcreteField { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/ErrorDataService.svc b/datajs/tests/endpoints/ErrorDataService.svc
deleted file mode 100644
index 052a2df..0000000
--- a/datajs/tests/endpoints/ErrorDataService.svc
+++ /dev/null
@@ -1,78 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.ErrorDataService" %>
-
-
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-
-    /// <summary>
-    /// A data service that contains in-stream errors
-    /// </summary>
-    public class ErrorDataService : DataService<ErrorDataSource>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
-        }
-    }
-
-    public class ErrorDataSource
-    {
-        public IQueryable<ErrorType> Entities
-        {
-            get
-            {
-                ErrorType[] entities = new ErrorType[]
-                {
-                    new ErrorType(() => 0),
-                    new ErrorType(() => { throw new ApplicationException(); })
-                };
-
-                return entities.AsQueryable();
-            }
-        }
-    }
-    
-    public class ErrorType
-    {
-        Func<int> generateID;
-        
-        public ErrorType(Func<int> generateID)
-        {
-            this.generateID = generateID;
-        }
-        
-        public int ID
-        {
-            get { return this.generateID(); }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/FoodStoreDataServiceV4.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/FoodStoreDataServiceV4.svc b/datajs/tests/endpoints/FoodStoreDataServiceV4.svc
deleted file mode 100644
index ac1cfe7..0000000
--- a/datajs/tests/endpoints/FoodStoreDataServiceV4.svc
+++ /dev/null
@@ -1,590 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.V4.FoodStoreDataService" %>
-
-namespace DataJS.Tests.V4
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using Microsoft.OData.Service.Providers;
-    using System.Linq;
-    using System.ServiceModel.Web;
-    using System.Web;
-    using System.IO;
-    using Microsoft.Spatial;
-    
-    /// <summary>
-    /// Provides a service similar to FoodStoreDataService, but uses V4 and WCF Data Services 6.0.0-beta1
-    /// features.
-    /// </summary>
-    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class FoodStoreDataService : DataService<FoodContainer>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.UseVerboseErrors = true;
-            // Set Foods page size to 5 for cache testing
-            config.SetEntitySetPageSize("Foods", 5);
-            // Make the Categories set paged to have a paged feed
-            config.SetEntitySetPageSize("Categories", 1);
-        }
-        
-        [WebInvoke]
-        public string ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-            return "Data Reset";
-        }
-
-        [WebGet]
-        public IQueryable<string> FoodsAvailable()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Name);
-        }
-
-        [WebGet]
-        public IQueryable<Package> PackagingTypes()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
-        }
-
-        [WebGet]
-        public string UserNameAndPassword()
-        {
-            var request = WebOperationContext.Current.IncomingRequest;
-            string authorization = request.Headers["Authorization"];
-            if (String.IsNullOrEmpty(authorization))
-            {
-                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
-                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
-            }
-
-            return authorization;
-        }
-    }
-
-    public class FoodContainer : ReflectionDataContext, IUpdatable, IDataServiceStreamProvider2
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Category> Categories
-        {
-            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
-        }
-        
-        public IQueryable<Food> Foods
-        {
-            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            var builder = SpatialImplementation.CurrentImplementation.CreateBuilder();
-            builder.GeometryPipeline.SetCoordinateSystem(CoordinateSystem.DefaultGeography);
-            builder.GeometryPipeline.BeginGeometry(SpatialType.Collection);
-            builder.GeometryPipeline.BeginFigure(new GeometryPosition(5.0, 5.0));
-            builder.GeometryPipeline.EndFigure();
-            builder.GeometryPipeline.EndGeometry();
-            
-            int i = 0;
-            Category[] categories = new Category[]
-            {
-                new Category { CategoryID = i++, Name = "Baking Supplies" },
-                new Category { CategoryID = i++, Name = "Condiments" },
-                new Category { CategoryID = i++, Name = "Empty Category" }
-            };
-            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
-            
-            i = 0;
-            Food[] foods = new Food[]
-            {            
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "flour",
-                    UnitPrice = .19999,
-                    ServingSize = 1,
-                    MeasurementUnit = "Cup",
-                    ProteinGrams = 3,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 20,
-                    CaloriesPerServing = 140,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
-                    ItemGUID = new Guid("27272727272727272727272727272727"),
-                    Weight = 10f,
-                    AvailableUnits = 1,
-                    
-                    Packaging = new Package(){
-                        Type = null, 
-                        Color = String.Empty, 
-                        NumberPerPackage = int.MaxValue, 
-                        RequiresRefridgeration = false, 
-                        PackageDimensions = new Dimensions()
-                        {
-                            Length = Decimal.MaxValue, 
-                            Height = Int16.MaxValue, 
-                            Width = Int64.MaxValue, 
-                            Volume = double.MaxValue,   
-                        },
-                        ShipDate = new DateTime(2000, 12, 29)
-                    },
-                    
-                    CookedSize = new CookedDimensions()
-                    {
-                        Height = 1,
-                        Length = 2,
-                        Width = 3,
-                        Volume = 1 * 2 * 3
-                    },
-                    
-                    Category = categories[0],
-                    
-                    AlternativeNames = new List<string>() {"ground cereal", "ground grain"},
-                    
-                    Providers = new List<Provider> {
-                        new Provider() { 
-                             Name= "Flour Provider", 
-                             Aliases = new List<string>() {"fp1", "flour provider1"},
-                             Details = new ProviderDetails() {
-                                 Telephone= "555-555-555",
-                                 PreferredCode = 1001
-                             }
-                        },
-                        new Provider() { 
-                             Name= "Ground Grains", 
-                             Aliases = new List<string>()
-                        }
-                    },
-                    
-                    SpatialData = (GeometryCollection)builder.ConstructedGeometry 
-                },
-                
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "sugar",
-                    UnitPrice = .2,
-                    ServingSize = 1,
-                    MeasurementUnit = "tsp",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 4,
-                    CaloriesPerServing = 16,
-                    IsAvailable = false,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
-                    Weight = 0.1f,
-                    AvailableUnits = 0,
-
-                    Packaging = new Package(){
-                        Type = " ",
-                        Color = "BLUE",
-                        NumberPerPackage = int.MinValue,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = Decimal.MinValue,
-                            Height = Int16.MinValue,
-                            Width = Int64.MinValue,
-                            Volume = double.MinValue,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = categories[1],
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "1 Chicken Egg",
-                    UnitPrice = 0.55,
-                    MeasurementUnit = null,
-                    ServingSize = 1,
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 1,
-                    CaloriesPerServing = 70,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("00000000000000000000000000000000"),
-                    Weight = 0,
-                    AvailableUnits = -128,
-                    
-                    Packaging = new Package(){
-                        Type = "18     - Carton",
-                        Color = " brown ",
-                        NumberPerPackage = 0,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = null,
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = null,
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "Brown Sugar",
-                    UnitPrice = 1.6,
-                    ServingSize = 1,
-                    MeasurementUnit = "TSP.",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 5, 
-                    CaloriesPerServing = 16,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 4.5f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Cobb Salad",
-                    UnitPrice = 1.99,
-                    ServingSize = -1,
-                    MeasurementUnit = "cups",
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 3, 
-                    CaloriesPerServing = 5,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 5.674f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                    Instructions = "1.) Open 2.) Eat",
-                    NumberOfIngredients = 4,
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Lasagna",
-                    UnitPrice = 0,
-                    ServingSize = 8,
-                    MeasurementUnit = " servings",
-                    ProteinGrams = 100,
-                    FatGrams = 4,
-                    CarbohydrateGrams = 27, 
-                    CaloriesPerServing = 389,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(1904, 2, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 0,
-                    AvailableUnits = 4,
-                    Packaging = new Package(){
-                        Type = "box",
-                        Color = " 1 ",
-                        NumberPerPackage = 1,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = 3,
-                            Height = 1,
-                            Width = 5,
-                            Volume = 1.5,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    Category = categories[0],
-                    Instructions = "Bake in oven",
-                    NumberOfIngredients = 15,
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Chocolate"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Pizza"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Avocados"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Quinoa"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Oatmeal"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Peanut Butter"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Banana"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Yam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Clam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Spam"
-                }
-            };
-            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
-
-            categories[0].Foods.Add(foods[0]);
-            categories[1].Foods.Add(foods[2]);
-            categories[1].Foods.Add(foods[3]);
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-
-        public Stream GetReadStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            return new MemoryStream();
-        }
-
-        public Uri GetReadStreamUri(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            if (streamProperty.Name == "Icon")
-            {
-                return null;
-            }
-            return new Uri(operationContext.AbsoluteServiceUri, streamProperty.Name);
-        }
-
-        public string GetStreamContentType(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            if (streamProperty.Name == "Icon")
-            {
-                return "image/gif";
-            }
-            return "image/png";
-        }
-
-        public string GetStreamETag(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext)
-        {
-            return "W/\"123456789\"";
-        }
-
-        public Stream GetWriteStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            return new MemoryStream();
-        }
-
-        public void DeleteStream(object entity, DataServiceOperationContext operationContext)
-        {
-            // do nothing.
-        }
-
-        public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
-        {
-            throw new NotImplementedException();
-        }
-
-        public int StreamBufferSize
-        {
-            get { return 1024; }
-        }
-    }
-
-    /// <summary>
-    /// The Category class is a simple class with V1-compatible feed customizations.
-    /// </summary>
-    public class Category
-    {
-        public Category()
-        {
-            this.Foods = new List<Food>();
-        }
-        
-        public int CategoryID { get; set; }
-        public string Name { get; set; }
-        public List<Food> Foods { get; set; }
-    }
-    
-    /// <summary>
-    /// The Food class has a mixture of V1-compatible and incompatible feed
-    /// customizations (thus it's V2), and custom mappings.
-    /// </summary>
-    public class Food
-    {
-        private List<string> alternativeNames = new List<string>();
-        private List<Provider> providers = new List<Provider>();
-        
-        // Primitive types
-        public int FoodID { get; set; }
-        public string Name { get; set; }
-        public double UnitPrice { get; set; }
-        public Decimal ServingSize { get; set; }
-        public string MeasurementUnit { get; set; }
-        public Byte ProteinGrams { get; set; }
-        public Int16 FatGrams { get; set; }
-        public Int32 CarbohydrateGrams { get; set; }
-        public Int64 CaloriesPerServing { get; set; }
-        public Boolean IsAvailable { get; set; }
-        public DateTime ExpirationDate { get; set; }
-        public Guid ItemGUID { get; set; }
-        public Single Weight { get; set; }
-        public sbyte AvailableUnits { get; set; }
-
-        // Complex types
-        public Package Packaging { get; set; }
-        public CookedDimensions CookedSize { get; set; }
-
-        // Navigation properties
-        public Category Category { get; set; }
-
-        // Collection properties
-        public List<string> AlternativeNames
-        {
-            get { return alternativeNames; }
-            set { alternativeNames = value; }
-        }
-
-        public List<Provider> Providers
-        {
-            get { return providers; }
-            set { providers = value; }
-        }
-
-        public GeometryCollection SpatialData
-        {
-            get;
-            set;
-        }
-        
-    }
-
-    public class Provider
-    {
-        public string Name { get; set; }
-        public List<string> Aliases { get; set; }
-        public ProviderDetails Details { get; set; }
-    }
-
-    public class ProviderDetails
-    {
-        public string Telephone { get; set; }
-        public int PreferredCode { get; set; }
-    }
-    
-    public class Package
-    {
-        public string Type { get; set; }
-        public string Color { get; set; }
-        public int NumberPerPackage { get; set; }
-        public Boolean RequiresRefridgeration { get; set; }
-        public DateTime ShipDate { get; set; }
-        public Dimensions PackageDimensions { get; set; }
-    }
-
-    public class Dimensions
-    {
-        public Decimal Length { get; set; }
-        public Int16 Height { get; set; }
-        public Int64 Width { get; set; }
-        public double Volume { get; set; }
-    }
-
-    public class CookedDimensions
-    {
-        public Decimal Length { get; set; }
-        public Int16 Height { get; set; }
-        public Int64 Width { get; set; }
-        public double Volume { get; set; }
-    }
-
-    public class PreparedFood : Food
-    {
-        public string Instructions { get; set; }
-        public float NumberOfIngredients { get; set; }
-    }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/LargeCollectionService.svc
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/LargeCollectionService.svc b/datajs/tests/endpoints/LargeCollectionService.svc
deleted file mode 100644
index bfbd3ef..0000000
--- a/datajs/tests/endpoints/LargeCollectionService.svc
+++ /dev/null
@@ -1,113 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-
-<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.LargeCollectionService" %>
-
-namespace DataJS.Tests
-{
-    using System;
-    using System.Collections.Generic;
-    using Microsoft.OData.Service;
-    using System.Linq;
-    using System.ServiceModel;
-    using System.ServiceModel.Web;
-    using System.Web;
-
-    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class LargeCollectionService : DataService<LargeCollection>
-    {
-        // This method is called only once to initialize service-wide policies.
-        public static void InitializeService(DataServiceConfiguration config)
-        {
-            config.SetEntitySetAccessRule("*", EntitySetRights.All);
-            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
-            config.UseVerboseErrors = true;
-        }
-
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-    }
-
-    public class LargeCollection : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Customer> Customers
-        {
-            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
-        }
-
-        public IQueryable<Supplier> Suppliers
-        {
-            get { return this.GetResourceSetEntities<Supplier>("Suppliers").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-
-            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
-            foreach (int i in Enumerable.Range(1, 2 * 1024 * 1024))
-            {
-                customers.Add(new Customer()
-                {
-                    ID = i,
-                    Name = "Customer " + i
-                });
-            }
-
-            IList<Supplier> suppliers = this.GetResourceSetEntities<Supplier>("Suppliers");
-            foreach (int i in Enumerable.Range(1, 5000))
-            {
-                suppliers.Add(new Supplier()
-                {
-                    ID = i,
-                    Name = "Supplier " + i
-                });
-            }
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Customer
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-
-    public class Supplier
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/endpoints/web.config
----------------------------------------------------------------------
diff --git a/datajs/tests/endpoints/web.config b/datajs/tests/endpoints/web.config
deleted file mode 100644
index 116a567..0000000
--- a/datajs/tests/endpoints/web.config
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version='1.0'?>
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-<configuration>
-  <system.web>
-    <compilation debug='true'>
-      <assemblies>
-        <add assembly='System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
-        <add assembly='System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/>
-        <add assembly='System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/>
-        <add assembly="Microsoft.OData.Core, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-        <add assembly="Microsoft.OData.Client, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
-      </assemblies>
-    </compilation>
-  </system.web>
-  <system.codedom>
-    <compilers>
-      <compiler language='c#;cs;csharp' extension='.cs' type='Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'>
-        <providerOption name='CompilerVersion' value='v4.0' />
-      </compiler>
-    </compilers>
-  </system.codedom>
-</configuration>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/node-test-setup.js
----------------------------------------------------------------------
diff --git a/datajs/tests/node-test-setup.js b/datajs/tests/node-test-setup.js
deleted file mode 100644
index 50fcac2..0000000
--- a/datajs/tests/node-test-setup.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-//Creates the global objects
-
-//tools
-djstest = require("./common/djstest.js");
-MockHttpClient = require("./common/MockHttpClient.js").init({});
-
-//lib
-datajs = require('./../src/lib/datajs.js');
-OData = require('./../src/lib/odata.js');
-
-
-

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/datajs/tests/odata-batch-functional-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-batch-functional-tests.html b/datajs/tests/odata-batch-functional-tests.html
deleted file mode 100644
index 4f79204..0000000
--- a/datajs/tests/odata-batch-functional-tests.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- -->
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-    <title>batch tests</title>
-    <meta http-equiv="cache-control" content="no-cache" />
-    <meta http-equiv="pragma" content="no-cache" />
-    <meta http-equiv="expires" content="-1" />
-    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
-    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
-    <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="common/ODataReadOracle.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/odatajs-4.0.0-beta-01.js"></script>  
-    <script type="text/javascript" src="common/common.js"></script> 
-    <script type="text/javascript" src="common/djstest.js"></script>
-    <script type="text/javascript" src="odata-batch-functional-tests.js"></script>
-</head>
-<body>
-    <h1 id="qunit-header">batch 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/d5ec5557/datajs/tests/odata-batch-functional-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-batch-functional-tests.js b/datajs/tests/odata-batch-functional-tests.js
deleted file mode 100644
index 328bb66..0000000
--- a/datajs/tests/odata-batch-functional-tests.js
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-(function (window, undefined) {
-    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
-
-    var unexpectedErrorHandler = function (err) {
-        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
-        djstest.done();
-    };
-
-    var determineExpected = function (batchRequests) {
-        var expected = 0;
-        $.each(batchRequests, function (_, batchRequest) {
-            // 2 assertions per request: response code and data
-            if (batchRequest.__changeRequests) {
-                expected += batchRequest.__changeRequests.length * 2;
-            } else {
-                expected += 2;
-            }
-        });
-
-        // 2 more assertions than the number of requests in batch: response code and batch response length
-        return expected + 2;
-    };
-
-    var verifyBatchRequest = function (serviceRoot, batchRequests, elementTypes, done) {
-        odatajs.oData.request({ requestUri: serviceRoot + "/$batch", method: "POST", data: { __batchRequests: batchRequests} },
-            function (data, response) {
-                djstest.assertAreEqual(response.statusCode, httpStatusCode.accepted, "Verify response code");
-                djstest.assertAreEqual(data.__batchResponses.length, batchRequests.length, "Verify batch response count");
-                verifyBatchResponses(batchRequests, elementTypes, serviceRoot, data.__batchResponses, done);
-            },
-            unexpectedErrorHandler, OData.batch.batchHandler);
-    };
-
-    var verifyBatchResponses = function (batchRequests, elementTypes, serviceRoot, batchResponses, done) {
-        forEachAsync(batchRequests, function (index, batchRequest, doneOne) {
-            if (batchRequest.requestUri) {
-                var readFeedOrEntry = elementTypes[index] == "feed" ? ODataReadOracle.readFeed : ODataReadOracle.readEntry;
-                djstest.assertAreEqual(batchResponses[index].statusCode, httpStatusCode.ok, "Verify response code for: GET " + batchRequest.requestUri);
-                readFeedOrEntry(serviceRoot + "/" + batchRequest.requestUri, function (expectedData) {
-                    djstest.assertAreEqualDeep(batchResponses[index].data, expectedData, "Verify data for: GET " + batchRequest.requestUri);
-                    doneOne();
-                }, batchRequests[index].headers.Accept);
-            }
-            else if (batchRequest.__changeRequests) {
-                verifyChangeResponses(batchRequest.__changeRequests, batchResponses[index].__changeResponses, function () { doneOne(); });
-            }
-        }, done);
-    }
-
-    var verifyChangeResponses = function (changeRequests, changeResponses, done) {
-        forEachAsync(changeRequests, function (index, changeRequest, doneOne) {
-            var httpOperation = changeRequest.method + " " + changeRequest.requestUri;
-            var changeResponse = changeResponses[index];
-
-            if (changeRequest.method == "POST") {
-                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.created, "Verify response code for: " + httpOperation);
-                ODataReadOracle.readEntry(changeResponse.headers["Location"], function (expectedData) {
-                    djstest.assertAreEqualDeep(changeResponse.data, expectedData, "Verify response data for: " + httpOperation);
-                    doneOne();
-                }, changeRequest.headers.Accept);
-            }
-            else if (changeRequest.method == "PUT") {
-                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
-                djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
-                doneOne();
-            }
-            else if (changeRequest.method == "DELETE") {
-                djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
-                djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
-                doneOne();
-            }
-        }, done);
-    }
-
-    var forEachAsync = function (array, callback, done) {
-        var count = 0;
-        var doneOne = function () {
-            count++;
-            if (count == array.length) {
-                done();
-            }
-        }
-
-        $.each(array, function (index, element) { callback(index, element, doneOne); });
-    };
-
-    var cloneHeadersWithContentId = function (mimeHeaders, count) {
-        var headers = djstest.clone(mimeHeaders);
-        headers["Content-ID"] = count;
-        return headers;
-    };
-
-    var service = "./endpoints/FoodStoreDataServiceV4.svc";
-    var batchUri = service + "/$batch";
-
-    var httpStatusCode = {
-        ok: 200,
-        created: 201,
-        accepted: 202,
-        noContent: 204
-    };
-
-    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
-
-    module("Functional", {
-        setup: function () {
-            djstest.wait(function (done) {
-                $.post(service + "/ResetData", done);
-            });
-        }
-    });
-
-    $.each(mimeTypes, function (_, mimeType) {
-        var acceptHeaders = mimeType ? { Accept: mimeType} : undefined;
-        var mimeHeaders = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
-
-        djstest.addTest(function multipleRetrieves(acceptHeaders) {
-            var uriSegments = ["Foods(0)", "Foods?$filter=FoodID eq 1", "Foods?$top=2"];
-            var elementTypes = ["entry", "feed", "feed"];
-
-            var batchRequests = $.map(uriSegments, function (uriSegment) {
-                return { requestUri: uriSegment, method: "GET", headers: acceptHeaders }
-            });
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Multiple retrieves: mimeType = " + mimeType, acceptHeaders);
-
-        djstest.addTest(function multipleChangesets(params) {
-            var batchRequests = [
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
-                                { CategoryID: 42, Name: "New Category" }
-                            }
-                        ]
-                    },
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
-                                { CategoryID: 1, Name: "Updated Category" }
-                            },
-                            { requestUri: "Categories(0)", method: "DELETE", headers: cloneHeadersWithContentId(params.mimeHeaders, 3) }
-                        ]
-                    }
-                ];
-            var elementTypes = [null, null];
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Multiple changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
-
-        djstest.addTest(function multipleRetrievesAndChangesets(params) {
-            // Header needs to be cloned because it is mutable; this means that after processing one request in the batch
-            // the header object will be modified
-            var batchRequests = [
-                    { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
-                    { requestUri: "Foods?$filter=FoodID eq 1", method: "GET", headers: djstest.clone(params.acceptHeaders) },
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
-                                { CategoryID: 42, Name: "New Category" }
-                            }
-                        ]
-                    },
-                    { requestUri: "Foods?$top=2", method: "GET", headers: djstest.clone(params.acceptHeaders) },
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
-                                { CategoryID: 1, Name: "Updated Category" }
-                            },
-                            { requestUri: "Categories(0)", method: "DELETE", headers: cloneHeadersWithContentId(params.mimeHeaders, 3) }
-                        ]
-                    }
-                ];
-            var elementTypes = ["entry", "feed", null, "feed", null];
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Multiple retrieves and changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
-
-        djstest.addTest(function singleRetrieve(acceptHeaders) {
-            var batchRequests = [{ requestUri: "Foods(2)", method: "GET", headers: acceptHeaders}];
-            var elementTypes = ["entry"];
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Single retrieve: mimeType = " + mimeType, acceptHeaders);
-
-        djstest.addTest(function singleChangeset(params) {
-            var batchRequests = [
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
-                                { CategoryID: 42, Name: "New Category" }
-                            },
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
-                                { CategoryID: 1, Name: "Updated Category" }
-                            }
-                        ]
-                    }
-                ];
-            var elementTypes = [null];
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Single changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
-
-        djstest.addTest(function singleRetrieveAndChangeset(params) {
-            var batchRequests = [
-                    { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
-                    {
-                        __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data:
-                                { CategoryID: 42, Name: "New Category" }
-                            },
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data:
-                                { CategoryID: 1, Name: "Updated Category" }
-                            }
-                        ]
-                    }
-                ];
-            var elementTypes = ["entry", null];
-
-            djstest.assertsExpected(determineExpected(batchRequests));
-            verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
-        }, "Single retrieve and changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
-
-        djstest.addTest(function retrieveInsideChangeset(params) {
-
-            var batchRequests = [
-                    { requestUri: "Foods(0)", method: "GET" },
-                    { __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 1), data: { CategoryID: 42, Name: "New Category"} },
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 2), data: { CategoryID: 1, Name: "Updated Category"} }
-                        ]
-                    },
-                    { requestUri: "Foods(1)", method: "GET" },
-                    { __changeRequests: [
-                            { requestUri: "Categories", method: "POST", headers: cloneHeadersWithContentId(params.mimeHeaders, 3), data: { CategoryID: 42, Name: "New Category"} },
-                            { requestUri: "Categories(1)", method: "PUT", headers: cloneHeadersWithContentId(params.mimeHeaders, 4), data: { CategoryID: 1, Name: "Updated Category"} },
-                            { requestUri: "Foods", method: "GET" }
-                        ]
-                    }
-                ];
-
-            odatajs.oData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
-            function (data, response) {
-                var batchResponses = data.__batchResponses;
-                var error = batchResponses[3].__changeResponses[0];
-                djstest.assert(error.response.body.indexOf("An error occurred while processing this request.") > -1, "Response contains expected message");
-                // Verify that the responses prior to the error are the expected ones.
-                batchRequests.splice(3, 1);
-                batchResponses.splice(3, 1);
-                verifyBatchResponses(batchRequests, ["entry", null], service, batchResponses, function () { djstest.done(); });
-            }, unexpectedErrorHandler, OData.batch.batchHandler);
-        }, "Retrieve inside changeset: mimeType = " + mimeType, {mimeHeaders: mimeHeaders });
-    });
-
-    /*On Odata V4 spec, the POST/PUT/Delete operations are allowed outside of changesets.*/
-    djstest.addTest(function updateOutsideChangeset() {
-        var batchRequests = [{ requestUri: "Categories", method: "POST", data: { CategoryID: 42, Name: "New Category"}}];
-
-        djstest.assertsExpected(1);
-        odatajs.oData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
-            function (data, response) {
-                djstest.assert(response.body.indexOf("An error occurred while processing this request.") == -1, "Verify that there is no error occurred.");
-                djstest.done();
-            }, unexpectedErrorHandler, OData.batch.batchHandler
-        );
-    }, "Update outside changeset");
-})(this);
\ No newline at end of file