add end-to-end test for V3 & V4 running side by side.
diff --git a/datajs/JSLib.csproj b/datajs/JSLib.csproj
index eb682b6..c2c3906 100644
--- a/datajs/JSLib.csproj
+++ b/datajs/JSLib.csproj
@@ -71,6 +71,7 @@
     <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" />
@@ -161,7 +162,6 @@
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml.Linq" />
   </ItemGroup>
-  <ItemGroup />
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
   <ProjectExtensions>
diff --git a/datajs/tests/e2etest/Test.html b/datajs/tests/e2etest/Test.html
new file mode 100644
index 0000000..265c1da
--- /dev/null
+++ b/datajs/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>
diff --git a/datajs/tests/e2etest/chh.js b/datajs/tests/e2etest/chh.js
deleted file mode 100644
index 1ad5912..0000000
--- a/datajs/tests/e2etest/chh.js
+++ /dev/null
@@ -1,8373 +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 e(t, n, r) {
-    function s(o, u) {
-        if (!n[o]) {
-            if (!t[o]) {
-                var a = typeof require == "function" && require;
-                if (!u && a) return a(o, !0);
-                if (i) return i(o, !0);
-                throw new Error("Cannot find module '" + o + "'")
-            }
-            var f = n[o] = {
-                exports: {}
-            };
-            t[o][0].call(f.exports, function(e) {
-                var n = t[o][1][e];
-                return s(n ? n : e)
-            }, f, f.exports, e, t, n, r)
-        }
-        return n[o].exports
-    }
-    var i = typeof require == "function" && require;
-    for (var o = 0; o < r.length; o++) s(r[o]);
-    return s
-})({
-    1: [
-        function(require, module, exports) {
-
-
-            if (window.odatajs === undefined) {
-                window.odatajs = {};
-            }
-
-            window.odatajs = require('./lib/datajs.js');
-            window.odatajs.oData = require('./lib/odata.js');
-
-            window.odatajs.store = require('./lib/store.js');
-            window.odatajs.cache = require('./lib/cache.js');
-
-            /*
-            function extend(target) {
-                var sources = [].slice.call(arguments, 1);
-                sources.forEach(function (source) {
-                    for (var prop in source) {
-                        target[prop] = source[prop];
-                    }
-                });
-                return target;
-            }*/
-
-
-
-        }, {
-            "./lib/cache.js": 2,
-            "./lib/datajs.js": 4,
-            "./lib/odata.js": 8,
-            "./lib/store.js": 15
-        }
-    ],
-    2: [
-        function(require, module, exports) {
-
-
-            /** @module cache */
-
-            var utils = require('./datajs.js').utils;
-
-
-            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 deferred = require('./datajs/deferred.js');
-
-            var createDeferred = deferred.createDeferred;
-            var DjsDeferred = deferred.DjsDeferred;
-            var ODataCacheSource = require('./cache/source').ODataCacheSource;
-
-            var getJsonValueArraryLength = utils.getJsonValueArraryLength;
-            var sliceJsonValueArray = utils.sliceJsonValueArray;
-            var concatJsonValueArray = utils.concatJsonValueArray;
-            var storeReq = require('./datajs.js').store;
-
-
-            /** Appending a page appendPage */
-            var appendPage = function(operation, page) {
-                /// <summary>Appends a page's data to the operation data.</summary>
-                /// <param name="operation" type="Object">Operation with (i)ndex, (c)ount and (d)ata.</param>
-                /// <param name="page" type="Object">Page with (i)ndex, (c)ount and (d)ata.</param>
-
-                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));
-            };
-
-            var intersectRanges = function(x, y) {
-                /// <summary>Returns the {(i)ndex, (c)ount} range for the intersection of x and y.</summary>
-                /// <param name="x" type="Object">Range with (i)ndex and (c)ount members.</param>
-                /// <param name="y" type="Object">Range with (i)ndex and (c)ount members.</param>
-                /// <returns type="Object">The intersection (i)ndex and (c)ount; undefined if there is no intersection.</returns>
-
-                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;
-            };
-
-            var checkZeroGreater = function(val, name) {
-                /// <summary>Checks whether val is a defined number with value zero or greater.</summary>
-                /// <param name="val" type="Number">Value to check.</param>
-                /// <param name="name" type="String">Parameter name to use in exception.</param>
-
-                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."
-                    };
-                }
-            };
-
-            var checkUndefinedGreaterThanZero = function(val, name) {
-                /// <summary>Checks whether val is undefined or a number with value greater than zero.</summary>
-                /// <param name="val" type="Number">Value to check.</param>
-                /// <param name="name" type="String">Parameter name to use in exception.</param>
-
-                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."
-                        };
-                    }
-                }
-            };
-
-            var checkUndefinedOrNumber = function(val, name) {
-                /// <summary>Checks whether val is undefined or a number</summary>
-                /// <param name="val" type="Number">Value to check.</param>
-                /// <param name="name" type="String">Parameter name to use in exception.</param>
-                if (val !== undefined && (typeof val !== "number" || isNaN(val) || !isFinite(val))) {
-                    throw {
-                        message: "'" + name + "' must be a number."
-                    };
-                }
-            };
-
-            var removeFromArray = function(arr, item) {
-                /// <summary>Performs a linear search on the specified array and removes the first instance of 'item'.</summary>
-                /// <param name="arr" type="Array">Array to search.</param>
-                /// <param name="item">Item being sought.</param>
-                /// <returns type="Boolean">Whether the item was removed.</returns>
-
-                var i, len;
-                for (i = 0, len = arr.length; i < len; i++) {
-                    if (arr[i] === item) {
-                        arr.splice(i, 1);
-                        return true;
-                    }
-                }
-
-                return false;
-            };
-
-            var estimateSize = function(obj) {
-                /// <summary>Estimates the size of an object in bytes.</summary>
-                /// <param name="obj" type="Object">Object to determine the size of.</param>
-                /// <returns type="Integer">Estimated size of the object in bytes.</returns>
-                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 snapToPageBoundaries = function(lowIndex, highIndex, pageSize) {
-                /// <summary>Snaps low and high indices into page sizes and returns a range.</summary>
-                /// <param name="lowIndex" type="Number">Low index to snap to a lower value.</param>
-                /// <param name="highIndex" type="Number">High index to snap to a higher value.</param>
-                /// <param name="pageSize" type="Number">Page size to snap to.</param>
-                /// <returns type="Object">A range with (i)ndex and (c)ount of elements.</returns>
-
-                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.
-
-            // DataCache state constants
-
-            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";
-
-            var DataCacheOperation = function(stateMachine, promise, isCancelable, index, count, data, pending) {
-                /// <summary>Creates a new operation object.</summary>
-                /// <param name="stateMachine" type="Function">State machine that describes the specific behavior of the operation.</param>
-                /// <param name="promise" type ="DjsDeferred">Promise for requested values.</param>
-                /// <param name="isCancelable" type ="Boolean">Whether this operation can be canceled or not.</param>
-                /// <param name="index" type="Number">Index of first item requested.</param>
-                /// <param name="count" type="Number">Count of items requested.</param>
-                /// <param name="data" type="Array">Array with the items requested by the operation.</param>
-                /// <param name="pending" type="Number">Total number of pending prefetch records.</param>
-                /// <returns type="DataCacheOperation">A new data cache operation instance.</returns>
-
-                /// <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;
-
-                that.cancel = function() {
-                    /// <summary>Transitions this operation to the cancel state and sets the canceled flag to true.</summary>
-                    /// <remarks>The function is a no-op if the operation is non-cancelable.</summary>
-
-                    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);
-                    }
-                };
-
-                that.complete = function() {
-                    /// <summary>Transitions this operation to the end state.</summary>
-
-                    djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.complete() - operation is in the end state", that);
-                    transition(OPERATION_STATE_END, stateData);
-                };
-
-                that.error = function(err) {
-                    /// <summary>Transitions this operation to the error state.</summary>
-                    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);
-                    }
-                };
-
-                that.run = function(state) {
-                    /// <summary>Executes the operation's current state in the context of a new cache state.</summary>
-                    /// <param name="state" type="Object">New cache state.</param>
-
-                    cacheState = state;
-                    that.transition(that.s, stateData);
-                };
-
-                that.wait = function(data) {
-                    /// <summary>Transitions this operation to the wait state.</summary>
-
-                    djsassert(that.s !== OPERATION_STATE_END, "DataCacheOperation.wait() - operation is in the end state", that);
-                    transition(OPERATION_STATE_WAIT, data);
-                };
-
-                var operationStateMachine = function(opTargetState, cacheState, data) {
-                    /// <summary>State machine that describes all operations common behavior.</summary>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-
-                    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;
-                    }
-                };
-
-                var transition = function(state, data) {
-                    /// <summary>Transitions this operation to a new state.</summary>
-                    /// <param name="state" type="Object">State to transition the operation to.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-
-                    that.s = state;
-                    stateData = data;
-                    operationStateMachine(state, cacheState, data);
-                };
-
-                that.transition = transition;
-
-                return that;
-            };
-
-            DataCacheOperation.prototype.fireResolved = function() {
-                /// <summary>Fires a resolved notification as necessary.</summary>
-
-                // Fire the resolve just once.
-                var p = this.p;
-                if (p) {
-                    this.p = null;
-                    p.resolve(this.d);
-                }
-            };
-
-            DataCacheOperation.prototype.fireRejected = function(reason) {
-                /// <summary>Fires a rejected notification as necessary.</summary>
-
-                // Fire the rejection just once.
-                var p = this.p;
-                if (p) {
-                    this.p = null;
-                    p.reject(reason);
-                }
-            };
-
-            DataCacheOperation.prototype.fireCanceled = function() {
-                /// <summary>Fires a canceled notification as necessary.</summary>
-
-                this.fireRejected({
-                    canceled: true,
-                    message: "Operation canceled"
-                });
-            };
-
-
-            var DataCache = function(options) {
-                /// <summary>Creates a data cache for a collection that is efficiently loaded on-demand.</summary>
-                /// <param name="options">
-                /// Options for the data cache, including name, source, pageSize,
-                /// prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
-                /// </param>
-                /// <returns type="DataCache">A new data cache instance.</returns>
-
-                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 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;
-
-                that.count = function() {
-                    /// <summary>Counts the number of items in the collection.</summary>
-                    /// <returns type="Object">A promise with the number of items.</returns>
-
-                    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(), {
-                        cancel: function() {
-                            /// <summary>Aborts the count operation.</summary>
-                            if (request) {
-                                canceled = true;
-                                request.abort();
-                                request = null;
-                            }
-                        }
-                    });
-                };
-
-                that.clear = function() {
-                    /// <summary>Cancels all running operations and clears all local data associated with this cache.</summary>
-                    /// <remarks>
-                    /// 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.
-                    /// </remarks>
-                    /// <returns type="Object">A promise that has no value and can't be canceled.</returns>
-
-                    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;
-                };
-
-                that.filterForward = function(index, count, predicate) {
-                    /// <summary>Filters the cache data based a predicate.</summary>
-                    /// <param name="index" type="Number">The index of the item to start filtering forward from.</param>
-                    /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-                    /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-                    /// <remarks>
-                    /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-                    /// </remarks>
-                    /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-                    return filter(index, count, predicate, false);
-                };
-
-                that.filterBack = function(index, count, predicate) {
-                    /// <summary>Filters the cache data based a predicate.</summary>
-                    /// <param name="index" type="Number">The index of the item to start filtering backward from.</param>
-                    /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-                    /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-                    /// <remarks>
-                    /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-                    /// </remarks>
-                    /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-                    return filter(index, count, predicate, true);
-                };
-
-                that.readRange = function(index, count) {
-                    /// <summary>Reads a range of adjacent records.</summary>
-                    /// <param name="index" type="Number">Zero-based index of record range to read.</param>
-                    /// <param name="count" type="Number">Number of records in the range.</param>
-                    /// <remarks>
-                    /// 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.
-                    /// </remarks>
-                    /// <returns type="DjsDeferred">
-                    /// A promise for an array of records; less records may be returned if the
-                    /// end of the collection is found.
-                    /// </returns>
-
-                    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() {
-                            /// <summary>Aborts the readRange operation.</summary>
-                            op.cancel();
-                        }
-                    });
-                };
-
-                that.ToObservable = that.toObservable = function() {
-                    /// <summary>Creates an Observable object that enumerates all the cache contents.</summary>
-                    /// <returns>A new Observable object that enumerates all the cache contents.</returns>
-                    if (!window.Rx || !window.Rx.Observable) {
-                        throw {
-                            message: "Rx library not available - include rx.js"
-                        };
-                    }
-
-                    if (cacheFailure) {
-                        throw cacheFailure;
-                    }
-
-                    return window.Rx.Observable.CreateWithDisposable(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;
-                            }
-                        };
-                    });
-                };
-
-                var cacheFailureCallback = function(message) {
-                    /// <summary>Creates a function that handles a callback by setting the cache into failure mode.</summary>
-                    /// <param name="message" type="String">Message text.</param>
-                    /// <returns type="Function">Function to use as error callback.</returns>
-                    /// <remarks>
-                    /// This function will specifically handle problems with critical store resources
-                    /// during cache initialization.
-                    /// </remarks>
-
-                    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;
-                    };
-                };
-
-                var changeState = function(newState) {
-                    /// <summary>Updates the cache's state and signals all pending operations of the change.</summary>
-                    /// <param name="newState" type="Object">New cache state.</param>
-                    /// <remarks>This method is a no-op if the cache's current state and the new state are the same.</remarks>
-
-                    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);
-                        }
-                    }
-                };
-
-                var clearStore = function() {
-                    /// <summary>Removes all the data stored in the cache.</summary>
-                    /// <returns type="DjsDeferred">A promise with no value.</returns>
-                    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;
-                };
-
-                var dequeueOperation = function(operation) {
-                    /// <summary>Removes an operation from the caches queues and changes the cache state to idle.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation to dequeue.</param>
-                    /// <remarks>This method is used as a handler for the operation's oncomplete event.</remarks>
-
-                    var removed = removeFromArray(clearOperations, operation);
-                    if (!removed) {
-                        removed = removeFromArray(readOperations, operation);
-                        if (!removed) {
-                            removeFromArray(prefetchOperations, operation);
-                        }
-                    }
-
-                    pendingOperations--;
-                    changeState(CACHE_STATE_IDLE);
-                };
-
-                var fetchPage = function(start) {
-                    /// <summary>Requests data from the cache source.</summary>
-                    /// <param name="start" type="Number">Zero-based index of items to request.</param>
-                    /// <returns type="DjsDeferred">A promise for a page object with (i)ndex, (c)ount, (d)ata.</returns>
-
-                    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;
-                            }
-                        }
-                    });
-                };
-
-                var filter = function(index, count, predicate, backwards) {
-                    /// <summary>Filters the cache data based a predicate.</summary>
-                    /// <param name="index" type="Number">The index of the item to start filtering from.</param>
-                    /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-                    /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-                    /// <param name="backwards" type="Boolean">True if the filtering should move backward from the specified index, falsey otherwise.</param>
-                    /// <remarks>
-                    /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-                    /// </remarks>
-                    /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-                    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(), {
-                        cancel: function() {
-                            /// <summary>Aborts the filter operation</summary>
-                            if (pendingReadRange) {
-                                pendingReadRange.cancel();
-                            }
-                            canceled = true;
-                        }
-                    });
-                };
-
-                var fireOnIdle = function() {
-                    /// <summary>Fires an onidle event if any functions are assigned.</summary>
-
-                    if (that.onidle && pendingOperations === 0) {
-                        that.onidle();
-                    }
-                };
-
-                var prefetch = function(start) {
-                    /// <summary>Creates and starts a new prefetch operation.</summary>
-                    /// <param name="start" type="Number">Zero-based index of the items to prefetch.</param>
-                    /// <remarks>
-                    /// 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).
-                    /// <remarks>
-
-                    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);
-                    }
-                };
-
-                var queueAndStart = function(op, queue) {
-                    /// <summary>Queues an operation and runs it.</summary>
-                    /// <param name="op" type="DataCacheOperation">Operation to queue.</param>
-                    /// <param name="queue" type="Array">Array that will store the operation.</param>
-
-                    op.oncomplete = dequeueOperation;
-                    queue.push(op);
-                    pendingOperations++;
-                    op.run(state);
-                };
-
-                var readPage = function(key) {
-                    /// <summary>Requests a page from the cache local store.</summary>
-                    /// <param name="key" type="Number">Zero-based index of the reuqested page.</param>
-                    /// <returns type="DjsDeferred">A promise for a found flag and page object with (i)ndex, (c)ount, (d)ata, and (t)icks.</returns>
-
-                    djsassert(state !== CACHE_STATE_DESTROY, "DataCache.readPage() - cache is on the destroy state");
-
-                    var canceled = false;
-                    var deferred = extend(new DjsDeferred(), {
-                        cancel: function() {
-                            /// <summary>Aborts the readPage operation.</summary>
-                            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;
-                };
-
-                var savePage = function(key, page) {
-                    /// <summary>Saves a page to the cache local store.</summary>
-                    /// <param name="key" type="Number">Zero-based index of the requested page.</param>
-                    /// <param name="page" type="Object">Object with (i)ndex, (c)ount, (d)ata, and (t)icks.</param>
-                    /// <returns type="DjsDeferred">A promise with no value.</returns>
-
-                    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(), {
-                        cancel: function() {
-                            /// <summary>Aborts the readPage operation.</summary>
-                            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;
-                };
-
-                var saveSettings = function(success, error) {
-                    /// <summary>Saves the cache's current settings to the local store.</summary>
-                    /// <param name="success" type="Function">Success callback.</param>
-                    /// <param name="error" type="Function">Errror callback.</param>
-
-                    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);
-                };
-
-                var storeFailureCallback = function(deferred /*, message*/ ) {
-                    /// <summary>Creates a function that handles a store error.</summary>
-                    /// <param name="deferred" type="DjsDeferred">Deferred object to resolve.</param>
-                    /// <param name="message" type="String">Message text.</param>
-                    /// <returns type="Function">Function to use as error callback.</returns>
-                    /// <remarks>
-                    /// This function will specifically handle problems when interacting with the store.
-                    /// </remarks>
-
-                    return function( /*error*/ ) {
-                        // var console = window.console;
-                        // if (console && console.log) {
-                        //    console.log(message);
-                        //    console.dir(error);
-                        // }
-                        deferred.resolve(false);
-                    };
-                };
-
-                var updateSettings = function(page, pageBytes) {
-                    /// <summary>Updates the cache's settings based on a page object.</summary>
-                    /// <param name="page" type="Object">Object with (i)ndex, (c)ount, (d)ata.</param>
-                    /// <param name="pageBytes" type="Number">Size of the page in bytes.</param>
-
-                    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;
-                    }
-                };
-
-                var cancelStateMachine = function(operation, opTargetState, cacheState, data) {
-                    /// <summary>State machine describing the behavior for cancelling a read or prefetch operation.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-                    /// <remarks>
-                    /// This state machine contains behavior common to read and prefetch operations.
-                    /// </remarks>
-
-                    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;
-                };
-
-                var destroyStateMachine = function(operation, opTargetState, cacheState) {
-                    /// <summary>State machine describing the behavior of a clear operation.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <remarks>
-                    /// Clear operations have the highest priority and can't be interrupted by other operations; however,
-                    /// they will preempt any other operation currently executing.
-                    /// </remarks>
-
-                    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;
-                };
-
-                var prefetchStateMachine = function(operation, opTargetState, cacheState, data) {
-                    /// <summary>State machine describing the behavior of a prefetch operation.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-                    /// <remarks>
-                    /// 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.
-                    /// </remarks>
-
-                    // 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;
-                };
-
-                var readStateMachine = function(operation, opTargetState, cacheState, data) {
-                    /// <summary>State machine describing the behavior of a read operation.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-                    /// <remarks>
-                    /// 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.
-                    /// </remarks>
-
-                    // 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;
-                };
-
-                var readSaveStateMachine = function(operation, opTargetState, cacheState, data, isPrefetch) {
-                    /// <summary>State machine describing the behavior for reading and saving data into the cache.</summary>
-                    /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-                    /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-                    /// <param name="cacheState" type="Object">Current cache state.</param>
-                    /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-                    /// <param name="isPrefetch" type="Boolean">Flag indicating whether a read (false) or prefetch (true) operation is running.
-                    /// <remarks>
-                    /// This state machine contains behavior common to read and prefetch operations.
-                    /// </remarks>
-
-                    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;
-            };
-
-            exports.createDataCache = function(options) {
-                /// <summary>Creates a data cache for a collection that is efficiently loaded on-demand.</summary>
-                /// <param name="options">
-                /// Options for the data cache, including name, source, pageSize,
-                /// prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
-                /// </param>
-                /// <returns type="DataCache">A new data cache instance.</returns>
-                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);
-            };
-
-            exports.estimateSize = estimateSize;
-
-
-        }, {
-            "./cache/source": 3,
-            "./datajs.js": 4,
-            "./datajs/deferred.js": 5
-        }
-    ],
-    3: [
-        function(require, module, exports) {
-            /*
-             * 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 utils = require("./../datajs.js").utils;
-            var odataRequest = require("./../odata.js");
-
-            var parseInt10 = utils.parseInt10;
-            var normalizeURICase = utils.normalizeURICase;
-
-            var appendQueryOption = function(uri, queryOption) {
-                /// <summary>Appends the specified escaped query option to the specified URI.</summary>
-                /// <param name="uri" type="String">URI to append option to.</param>
-                /// <param name="queryOption" type="String">Escaped query option to append.</param>
-                var separator = (uri.indexOf("?") >= 0) ? "&" : "?";
-                return uri + separator + queryOption;
-            };
-
-            var appendSegment = function(uri, segment) {
-                /// <summary>Appends the specified segment to the given URI.</summary>
-                /// <param name="uri" type="String">URI to append a segment to.</param>
-                /// <param name="segment" type="String">Segment to append.</param>
-                /// <returns type="String">The original URI with a new segment appended.</returns>
-
-                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;
-            };
-
-            var buildODataRequest = function(uri, options) {
-                /// <summary>Builds a request object to GET the specified URI.</summary>
-                /// <param name="uri" type="String">URI for request.</param>
-                /// <param name="options" type="Object">Additional options.</param>
-
-                return {
-                    method: "GET",
-                    requestUri: uri,
-                    user: options.user,
-                    password: options.password,
-                    enableJsonpCallback: options.enableJsonpCallback,
-                    callbackParameterName: options.callbackParameterName,
-                    formatQueryString: options.formatQueryString
-                };
-            };
-
-            var findQueryOptionStart = function(uri, name) {
-                /// <summary>Finds the index where the value of a query option starts.</summary>
-                /// <param name="uri" type="String">URI to search in.</param>
-                /// <param name="name" type="String">Name to look for.</param>
-                /// <returns type="Number">The index where the query option starts.</returns>
-
-                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;
-            };
-
-            var queryForData = function(uri, options, success, error) {
-                /// <summary>Gets data from an OData service.</summary>
-                /// <param name="uri" type="String">URI to the OData service.</param>
-                /// <param name="options" type="Object">Object with additional well-known request options.</param>
-                /// <param name="success" type="Function">Success callback.</param>
-                /// <param name="error" type="Function">Error callback.</param>
-                /// <returns type="Object">Object with an abort method.</returns>
-
-                var request = queryForDataInternal(uri, options, {}, success, error);
-                return request;
-            };
-
-            var queryForDataInternal = function(uri, options, data, success, error) {
-                /// <summary>Gets data from an OData service taking into consideration server side paging.</summary>
-                /// <param name="uri" type="String">URI to the OData service.</param>
-                /// <param name="options" type="Object">Object with additional well-known request options.</param>
-                /// <param name="data" type="Array">Array that stores the data provided by the OData service.</param>
-                /// <param name="success" type="Function">Success callback.</param>
-                /// <param name="error" type="Function">Error callback.</param>
-                /// <returns type="Object">Object with an abort method.</returns>
-
-                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();
-                    }
-                };
-            };
-
-            var ODataCacheSource = function(options) {
-                /// <summary>Creates a data cache source object for requesting data from an OData service.</summary>
-                /// <param name="options">Options for the cache data source.</param>
-                /// <returns type="ODataCacheSource">A new data cache source instance.</returns>
-
-                var that = this;
-                var uri = options.source;
-
-                that.identifier = normalizeURICase(encodeURI(decodeURI(uri)));
-                that.options = options;
-
-                that.count = function(success, error) {
-                    /// <summary>Gets the number of items in the collection.</summary>
-                    /// <param name="success" type="Function">Success callback with the item count.</param>
-                    /// <param name="error" type="Function">Error callback.</param>
-                    /// <returns type="Object">Request object with an abort method./<param>
-
-                    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);
-                };
-
-                that.read = function(index, count, success, error) {
-                    /// <summary>Gets a number of consecutive items from the collection.</summary>
-                    /// <param name="index" type="Number">Zero-based index of the items to retrieve.</param>
-                    /// <param name="count" type="Number">Number of items to retrieve.</param>
-                    /// <param name="success" type="Function">Success callback with the requested items.</param>
-                    /// <param name="error" type="Function">Error callback.</param>
-                    /// <returns type="Object">Request object with an abort method./<param>
-
-                    var queryOptions = "$skip=" + index + "&$top=" + count;
-                    return queryForData(appendQueryOption(uri, queryOptions), that.options, success, error);
-                };
-
-                return that;
-            };
-
-            exports.ODataCacheSource = ODataCacheSource;
-
-        }, {
-            "./../datajs.js": 4,
-            "./../odata.js": 8
-        }
-    ],
-    4: [
-        function(require, module, exports) {
-
-
-
-            //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');
-
-
-        }, {
-            "./datajs/deferred.js": 5,
-            "./datajs/utils.js": 6,
-            "./datajs/xml.js": 7
-        }
-    ],
-    5: [
-        function(require, module, exports) {
-            /*
-             * 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 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();
-                }
-            };
-
-            exports.createDeferred = createDeferred;
-            exports.DjsDeferred = DjsDeferred;
-
-
-        }, {}
-    ],
-    6: [
-        function(require, module, exports) {
-
-
-            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);
-            };
-
-            // DATAJS INTERNAL START
-            var djsassert = function(condition, message, data) {
-                /// <summary>Throws an exception in case that a condition evaluates to false.</summary>
-                /// <param name="condition" type="Boolean">Condition to evaluate.</param>
-                /// <param name="message" type="String">Message explaining the assertion.</param>
-                /// <param name="data" type="Object">Additional data to be included in the exception.</param>
-
-                if (!condition) {
-                    throw {
-                        message: "Assert fired: " + message,
-                        data: data
-                    };
-                };
-            };
-            // DATAJS INTERNAL END
-
-            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;
-            };
-
-            var endsWith = function(input, search) {
-                return input.indexOf(search, input.length - search.length) !== -1;
-            };
-
-            var startsWith = function(input, search) {
-                return input.indexOf(search) == 0;
-            };
-
-            var getFormatKind = function(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.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;
-
-        }, {}
-    ],
-    7: [
-        function(require, module, exports) {
-            /*
-             * 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 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";
-
-            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>
-
-                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;
-            };
-
-            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"
-                };
-            };
-
-            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;
-
-        }, {
-            "./utils.js": 6
-        }
-    ],
-    8: [
-        function(require, module, exports) {
-
-
-            // 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');
-
-            exports.metadataHandler = odataMetadata.metadataHandler;
-
-            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];
-
-            var dispatchHandler = function(handlerMethod, requestOrResponse, context) {
-                /// <summary>Dispatches an operation to handlers.</summary>
-                /// <param name="handlerMethod" type="String">Name of handler method to invoke.</param>
-                /// <param name="requestOrResponse" type="Object">request/response argument for delegated call.</param>
-                /// <param name="context" type="Object">context argument for delegated call.</param>
-
-                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"
-                    };
-                }
-            };
-
-            exports.defaultSuccess = function(data) {
-                /// <summary>Default success handler for OData.</summary>
-                /// <param name="data">Data to process.</param>
-
-                window.alert(window.JSON.stringify(data));
-            };
-
-            exports.defaultError = throwErrorCallback;
-
-            exports.defaultHandler = {
-                read: function(response, context) {
-                    /// <summary>Reads the body of the specified response by delegating to JSON handlers.</summary>
-                    /// <param name="response">Response object.</param>
-                    /// <param name="context">Operation context.</param>
-
-                    if (response && assigned(response.body) && response.headers["Content-Type"]) {
-                        dispatchHandler("read", response, context);
-                    }
-                },
-
-                write: function(request, context) {
-                    /// <summary>Write the body of the specified request by delegating to JSON handlers.</summary>
-                    /// <param name="request">Reques tobject.</param>
-                    /// <param name="context">Operation context.</param>
-
-                    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.
-
-            exports.read = function(urlOrRequest, success, error, handler, httpClient, metadata) {
-                /// <summary>Reads data from the specified URL.</summary>
-                /// <param name="urlOrRequest">URL to read data from.</param>
-                /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
-                /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
-                /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
-                /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
-                /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>
-
-                var request;
-                if (urlOrRequest instanceof String || typeof urlOrRequest === "string") {
-                    request = {
-                        requestUri: urlOrRequest
-                    };
-                } else {
-                    request = urlOrRequest;
-                }
-
-                return exports.request(request, success, error, handler, httpClient, metadata);
-            };
-
-            exports.request = function(request, success, error, handler, httpClient, metadata) {
-                /// <summary>Sends a request containing OData payload to a server.</summary>
-                /// <param name="request" type="Object">Object that represents the request to be sent.</param>
-                /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
-                /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
-                /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
-                /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
-                /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>
-
-                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);
-                    }
-                }
-
-            };
-
-            exports.parseMetadata = function(csdlMetadataDocument) {
-                /// <summary>Parses the csdl metadata to DataJS metatdata format. This method can be used when the metadata is retrieved using something other than DataJS</summary>
-                /// <param name="csdlMetadata" type="string">A string that represents the entire csdl metadata.</param>
-                /// <returns type="Object">An object that has the representation of the metadata in Datajs format.</returns>
-
-                return metadataParser(null, csdlMetadataDocument);
-            };
-
-            // Configure the batch handler to use the default handler for the batch parts.
-            exports.batch.batchHandler.partHandler = exports.defaultHandler;
-
-        }, {
-            "./datajs/utils.js": 6,
-            "./odata/batch.js": 9,
-            "./odata/handler.js": 10,
-            "./odata/json.js": 11,
-            "./odata/metadata.js": 12,
-            "./odata/net.js": 13,
-            "./odata/utils.js": 14
-        }
-    ],
-    9: [
-        function(require, module, exports) {
-            /*
-             * 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.
-             */
-
-            /* {
-                oldname:'odata-batch.js',
-                updated:'20140514 12:59'
-            }*/
-
-            var utils = require('./../datajs.js').utils;
-            var odataUtils = require('./utils.js');
-            var odataHandler = require('./handler.js');
-
-            // Imports
-
-            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;
-
-            // CONTENT START
-            var batchMediaType = "multipart/mixed";
-            var responseStatusRegex = /^HTTP\/1\.\d (\d{3}) (.*)$/i;
-            var responseHeaderRegex = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/;
-
-            var hex16 = function() {
-                /// <summary>
-                /// Calculates a random 16 bit number and returns it in hexadecimal format.
-                /// </summary>
-                /// <returns type="String">A 16-bit number in hex format.</returns>
-
-                return Math.floor((1 + Math.random()) * 0x10000).toString(16).substr(1);
-            };
-
-            var createBoundary = function(prefix) {
-                /// <summary>
-                /// Creates a string that can be used as a multipart request boundary.
-                /// </summary>
-                /// <param name="prefix" type="String" optional="true">String to use as the start of the boundary string</param>
-                /// <returns type="String">Boundary string of the format: <prefix><hex16>-<hex16>-<hex16></returns>
-
-                return prefix + hex16() + "-" + hex16() + "-" + hex16();
-            };
-
-            var partHandler = function(context) {
-                /// <summary>
-                /// Gets the handler for data serialization of individual requests / responses in a batch.
-                /// </summary>
-                /// <param name="context">Context used for data serialization.</param>
-                /// <returns>Handler object.</returns>
-
-                return context.handler.partHandler;
-            };
-
-            var currentBoundary = function(context) {
-                /// <summary>
-                /// Gets the current boundary used for parsing the body of a multipart response.
-                /// </summary>
-                /// <param name="context">Context used for parsing a multipart response.</param>
-                /// <returns type="String">Boundary string.</returns>
-
-                var boundaries = context.boundaries;
-                return boundaries[boundaries.length - 1];
-            };
-
-            var batchParser = function(handler, text, context) {
-                /// <summary>Parses a batch response.</summary>
-                /// <param name="handler">This handler.</param>
-                /// <param name="text" type="String">Batch text.</param>
-                /// <param name="context" type="Object">Object with parsing context.</param>
-                /// <returns>An object representation of the batch.</returns>
-
-                var boundary = context.contentType.properties["boundary"];
-                return {
-                    __batchResponses: readBatch(text, {
-                        boundaries: [boundary],
-                        handlerContext: context
-                    })
-                };
-            };
-
-            var batchSerializer = function(handler, data, context) {
-                /// <summary>Serializes a batch object representation into text.</summary>
-                /// <param name="handler">This handler.</param>
-                /// <param name="data" type="Object">Representation of a batch.</param>
-                /// <param name="context" type="Object">Object with parsing context.</param>
-                /// <returns>An text representation of the batch object; undefined if not applicable.</returns>
-
-                var cType = context.contentType = context.contentType || contentType(batchMediaType);
-                if (cType.mediaType === batchMediaType) {
-                    return writeBatch(data, context);
-                }
-            };
-
-            var readBatch = function(text, context) {
-                /// <summary>
-                /// Parses a multipart/mixed response body from from the position defined by the context.
-                /// </summary>
-                /// <param name="text" type="String" optional="false">Body of the multipart/mixed response.</param>
-                /// <param name="context">Context used for parsing.</param>
-                /// <returns>Array of objects representing the individual responses.</returns>
-
-                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;
-            };
-
-            var readHeaders = function(text, context) {
-                /// <summary>
-                /// Parses the http headers in the text from the position defined by the context.
-                /// </summary>
-                /// <param name="text" type="String" optional="false">Text containing an http response's headers</param>
-                /// <param name="context">Context used for parsing.</param>
-                /// <returns>Object containing the headers as key value pairs.</returns>
-                /// <remarks>
-                /// This function doesn't support split headers and it will stop reading when it hits two consecutive line breaks.
-                /// </remarks>
-
-                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;
-            };
-
-            var readResponse = function(text, context, delimiter) {
-                /// <summary>
-                /// Parses an HTTP response.
-                /// </summary>
-                /// <param name="text" type="String" optional="false">Text representing the http response.</param>
-                /// <param name="context" optional="false">Context used for parsing.</param>
-                /// <param name="delimiter" type="String" optional="false">String used as delimiter of the multipart response parts.</param>
-                /// <returns>Object representing the http response.</returns>
-
-                // 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)
-                };
-            };
-
-            var readLine = function(text, context) {
-                /// <summary>
-                /// Returns a substring from the position defined by the context up to the next line break (CRLF).
-                /// </summary>
-                /// <param name="text" type="String" optional="false">Input string.</param>
-                /// <param name="context" optional="false">Context used for reading the input string.</param>
-                /// <returns type="String">Substring to the first ocurrence of a line break or null if none can be found. </returns>
-
-                return readTo(text, context, "\r\n");
-            };
-
-            var readTo = function(text, context, str) {
-                /// <summary>
-                /// 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.
-                /// </summary>
-                /// <param name="text" type="String" optional="false">Input string.</param>
-                /// <param name="context" type="Object" optional="false">Context used for reading the input string.</param>
-                /// <param name="str" type="String" optional="true">Substring to read up to.</param>
-                /// <returns type="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.</returns>
-
-                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);
-            };
-
-            var writeBatch = function(data, context) {
-                /// <summary>
-                /// Serializes a batch request object to a string.
-                /// </summary>
-                /// <param name="data" optional="false">Batch request object in payload representation format</param>
-                /// <param name="context" optional="false">Context used for the serialization</param>
-                /// <returns type="String">String representing the batch request</returns>
-
-                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;
-            };
-
-            var writeBatchPartDelimiter = function(boundary, close) {
-                /// <summary>
-                /// Creates the delimiter that indicates that start or end of an individual request.
-                /// </summary>
-                /// <param name="boundary" type="String" optional="false">Boundary string used to indicate the start of the request</param>
-                /// <param name="close" type="Boolean">Flag indicating that a close delimiter string should be generated</param>
-                /// <returns type="String">Delimiter string</returns>
-
-                var result = "\r\n--" + boundary;
-                if (close) {
-                    result += "--";
-                }
-
-                return result + "\r\n";
-            };
-
-            var writeBatchPart = function(part, context, nested) {
-                /// <summary>
-                /// 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.
-                /// </summary>
-                /// <param name="part" optional="false">Request or change set object in payload representation format</param>
-                /// <param name="context" optional="false">Object containing context information used for the serialization</param>
-                /// <param name="nested" type="boolean" optional="true">Flag indicating that the part is nested inside a change set</param>
-                /// <returns type="String">String representing the serialized part</returns>
-                /// <remarks>
-                /// A change set is an array of request objects and they cannot be nested inside other change sets.
-                /// </remarks>
-
-                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;
-            };
-
-            var writeRequest = function(request) {
-                /// <summary>
-                /// Serializes a request object to a string.
-                /// </summary>
-                /// <param name="request" optional="false">Request object to serialize</param>
-                /// <returns type="String">String representing the serialized request</returns>
-
-                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;
-            };
-
-            exports.batchHandler = handler(batchParser, batchSerializer, batchMediaType, MAX_DATA_SERVICE_VERSION);
-
-            // DATAJS INTERNAL START
-            exports.batchSerializer = batchSerializer;
-            exports.writeRequest = writeRequest;
-            // DATAJS INTERNAL END
-
-        }, {
-            "./../datajs.js": 4,
-            "./handler.js": 10,
-            "./utils.js": 14
-        }
-    ],
-    10: [
-        function(require, module, exports) {
-
-
-            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";
-
-            var contentType = function(str) {
-                /// <summary>Parses a string into an object with media type and properties.</summary>
-                /// <param name="str" type="String">String with media type to parse.</param>
-                /// <returns>null if the string is empty; an object with 'mediaType' and a 'properties' dictionary otherwise.</returns>
-
-                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
-                };
-            };
-
-            var contentTypeToString = function(contentType) {
-                /// <summary>Serializes an object with media type and properties dictionary into a string.</summary>
-                /// <param name="contentType">Object with media type and properties dictionary to serialize.</param>
-                /// <returns>String representation of the media type object; undefined if contentType is null or undefined.</returns>
-
-                if (!contentType) {
-                    return undefined;
-                }
-
-                var result = contentType.mediaType;
-                var property;
-                for (property in contentType.properties) {
-                    result += ";" + property + "=" + contentType.properties[property];
-                }
-                return result;
-            };
-
-            var createReadWriteContext = function(contentType, dataServiceVersion, context, handler) {
-                /// <summary>Creates an object that is going to be used as the context for the handler's parser and serializer.</summary>
-                /// <param name="contentType">Object with media type and properties dictionary.</param>
-                /// <param name="dataServiceVersion" type="String">String indicating the version of the protocol to use.</param>
-                /// <param name="context">Operation context.</param>
-                /// <param name="handler">Handler object that is processing a resquest or response.</param>
-                /// <returns>Context object.</returns>
-
-                var rwContext = {};
-                extend(rwContext, context);
-                extend(rwContext, {
-                    contentType: contentType,
-                    dataServiceVersion: dataServiceVersion,
-                    handler: handler
-                });
-
-                return rwContext;
-            };
-
-            var fixRequestHeader = function(request, name, value) {
-                /// <summary>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.</summary>
-                /// <param name="request">Request object on which the header will be set.</param>
-                /// <param name="name" type="String">Header name.</param>
-                /// <param name="value" type="String">Header value.</param>
-                if (!request) {
-                    return;
-                }
-
-                var headers = request.headers;
-                if (!headers[name]) {
-                    headers[name] = value;
-                }
-            };
-
-            var fixDataServiceVersionHeader = function(request, version) {
-                /// <summary>Sets the DataServiceVersion header of the request if its value is not yet defined or of a lower version.</summary>
-                /// <param name="request">Request object on which the header will be set.</param>
-                /// <param name="version" type="String">Version value.</param>
-                /// <remarks>
-                /// If the request has already a version value higher than the one supplied the this function does nothing.
-                /// </remarks>
-
-                if (request) {
-                    var headers = request.headers;
-                    var dsv = headers["OData-Version"];
-                    headers["OData-Version"] = dsv ? maxVersion(dsv, version) : version;
-                }
-            };
-
-            var getRequestOrResponseHeader = function(requestOrResponse, name) {
-                /// <summary>Gets the value of a request or response header.</summary>
-                /// <param name="requestOrResponse">Object representing a request or a response.</param>
-                /// <param name="name" type="String">Name of the header to retrieve.</param>
-                /// <returns type="String">String value of the header; undefined if the header cannot be found.</returns>
-
-                var headers = requestOrResponse.headers;
-                return (headers && headers[name]) || undefined;
-            };
-
-            var getContentType = function(requestOrResponse) {
-                /// <summary>Gets the value of the Content-Type header from a request or response.</summary>
-                /// <param name="requestOrResponse">Object representing a request or a response.</param>
-                /// <returns type="Object">Object with 'mediaType' and a 'properties' dictionary; null in case that the header is not found or doesn't have a value.</returns>
-
-                return contentType(getRequestOrResponseHeader(requestOrResponse, "Content-Type"));
-            };
-
-            var versionRE = /^\s?(\d+\.\d+);?.*$/;
-            var getDataServiceVersion = function(requestOrResponse) {
-                /// <summary>Gets the value of the DataServiceVersion header from a request or response.</summary>
-                /// <param name="requestOrResponse">Object representing a request or a response.</param>
-                /// <returns type="String">Data service version; undefined if the header cannot be found.</returns>
-
-                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.
-            };
-
-            var handlerAccepts = function(handler, cType) {
-                /// <summary>Checks that a handler can process a particular mime type.</summary>
-                /// <param name="handler">Handler object that is processing a resquest or response.</param>
-                /// <param name="cType">Object with 'mediaType' and a 'properties' dictionary.</param>
-                /// <returns type="Boolean">True if the handler can process the mime type; false otherwise.</returns>
-
-                // 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.
-                return handler.accept.indexOf(cType.mediaType) >= 0;
-            };
-
-            var handlerRead = function(handler, parseCallback, response, context) {
-                /// <summary>Invokes the parser associated with a handler for reading the payload of a HTTP response.</summary>
-                /// <param name="handler">Handler object that is processing the response.</param>
-                /// <param name="parseCallback" type="Function">Parser function that will process the response payload.</param>
-                /// <param name="response">HTTP response whose payload is going to be processed.</param>
-                /// <param name="context">Object used as the context for processing the response.</param>
-                /// <returns type="Boolean">True if the handler processed the response payload and the response.data property was set; false otherwise.</returns>
-
-                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;
-            };
-
-            var handlerWrite = function(handler, serializeCallback, request, context) {
-                /// <summary>Invokes the serializer associated with a handler for generating the payload of a HTTP request.</summary>
-                /// <param name="handler">Handler object that is processing the request.</param>
-                /// <param name="serializeCallback" type="Function">Serializer function that will generate the request payload.</param>
-                /// <param name="response">HTTP request whose payload is going to be generated.</param>
-                /// <param name="context">Object used as the context for serializing the request.</param>
-                /// <returns type="Boolean">True if the handler serialized the request payload and the request.body property was set; false otherwise.</returns>
-                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;
-            };
-
-            var handler = function(parseCallback, serializeCallback, accept, maxDataServiceVersion) {
-                /// <summary>Creates a handler object for processing HTTP requests and responses.</summary>
-                /// <param name="parseCallback" type="Function">Parser function that will process the response payload.</param>
-                /// <param name="serializeCallback" type="Function">Serializer function that will generate the request payload.</param>
-                /// <param name="accept" type="String">String containing a comma separated list of the mime types that this handler can work with.</param>
-                /// <param name="maxDataServiceVersion" type="String">String indicating the highest version of the protocol that this handler can work with.</param>
-                /// <returns type="Object">Handler object.</returns>
-
-                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);
-                    }
-                };
-            };
-
-            var textParse = function(handler, body /*, context */ ) {
-                return body;
-            };
-
-            var textSerialize = function(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;
-
-        }, {
-            "./../datajs.js": 4,
-            "./utils.js": 14
-        }
-    ],
-    11: [
-        function(require, module, exports) {
-
-
-            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 parseDuration = oDataUtils.parseDuration;
-            //var parseTimezone = oDataUtils.parseTimezone;
-            //var payloadTypeOf = oDataUtils.payloadTypeOf;
-            //var traverse = oDataUtils.traverse;
-
-            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+)?\)\/$/;
-
-            var minutesToOffset = function(minutes) {
-                /// <summary>Formats the given minutes into (+/-)hh:mm format.</summary>
-                /// <param name="minutes" type="Number">Number of minutes to format.</param>
-                /// <returns type="String">The minutes in (+/-)hh:mm format.</returns>
-
-                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);
-            };
-
-            var parseJsonDateString = function(value) {
-                /// <summary>Parses the JSON Date representation into a Date object.</summary>
-                /// <param name="value" type="String">String value.</param>
-                /// <returns type="Date">A Date object if the value matches one; falsy otherwise.</returns>
-
-                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.
-
-            var jsonParser = function(handler, text, context) {
-                /// <summary>Parses a JSON OData payload.</summary>
-                /// <param name="handler">This handler.</param>
-                /// <param name="text">Payload text (this parser also handles pre-parsed objects).</param>
-                /// <param name="context" type="Object">Object with parsing context.</param>
-                /// <returns>An object representation of the OData payload.</returns>
-
-                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;
-                }
-            };
-
-
-            var addType = function(data, name, value) {
-                var fullName = name + '@odata.type';
-
-                if (data[fullName] === undefined) {
-                    data[fullName] = value;
-                }
-            };
-
-            var addTypeNoEdm = function(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;
-                    }
-
-                }
-            };
-
-            var addTypeColNoEdm = function(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 + ')';
-                    }
-                }
-            };
-
-
-            var readPayloadFull = function(data, model, recognizeDates) {
-                /// <summary>Adds typeinformation for String, Boolean and numerical EDM-types. 
-                /// The type is determined from the odata-json-format-v4.0.doc specification
-                ///</summary>
-                /// <param name="data">Date which will be extendet</param>
-                /// <param name="recognizeDates" type="Boolean">
-                ///     True if strings formatted as datetime values should be treated as datetime values. False otherwise.
-                /// </param>
-                /// <returns>An object representation of the OData payload.</returns>
-
-                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;
-                                        var type = data[key + '@odata.type'];
-                                        if (type && (isGeographyEdmType(type) || isGeometryEdmType(type))) {
-                                            // is gemometry type
-                                        } else {
-                                            readPayloadFull(data[key], model, recognizeDates);
-                                        }
-                                    }
-                                } else {
-                                    var 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;
-            };
-
-            var jsonSerializer = function(handler, data, context) {
-                /// <summary>Serializes the data by returning its string representation.</summary>
-                /// <param name="handler">This handler.</param>
-                /// <param name="data">Data to serialize.</param>
-                /// <param name="context" type="Object">Object with serialization context.</param>
-                /// <returns type="String">The string representation of data.</returns>
-
-                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;
-            };
-
-            var formatJsonRequestPayload = function(data) {
-                if (!data) {
-                    return data;
-                }
-
-                if (isPrimitive(data)) {
-                    return data;
-                }
-
-                if (isArray(data)) {
-                    var newArrayData = [];
-                    var i, len;
-                    for (i = 0, len = data.length; i < len; i++) {
-                        newArrayData[i] = formatJsonRequestPayload(data[i]);
-                    }
-
-                    return newArrayData;
-                }
-
-                var newdata = {};
-                for (var property in data) {
-                    if (isJsonSerializableProperty(property)) {
-                        newdata[property] = formatJsonRequestPayload(data[property]);
-                    }
-                }
-
-                return newdata;
-            };
-            var jsonReplacer = function(_, value) {
-                /// <summary>JSON replacer function for converting a value to its JSON representation.</summary>
-                /// <param value type="Object">Value to convert.</param>
-                /// <returns type="String">JSON representation of the input value.</returns>
-                /// <remarks>
-                ///   This method is used during JSON serialization and invoked only by the JSON.stringify function.
-                ///   It should never be called directly.
-                /// </remarks>
-
-                if (value && value.__edmType === "Edm.Time") {
-                    return formatDuration(value);
-                } else {
-                    return value;
-                }
-            };
-
-
-            var jsonMakePayloadInfo = function(kind, type) {
-                /// <summary>Creates an object containing information for the json payload.</summary>
-                /// <param name="kind" type="String">JSON payload kind, one of the PAYLOADTYPE_XXX constant values.</param>
-                /// <param name="typeName" type="String">Type name of the JSON payload.</param>
-                /// <returns type="Object">Object with kind and type fields.</returns>
-
-                /// <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
-                };
-            };
-
-            /// <summary>Creates an object containing information for the context</summary>
-            /// ...
-            /// <returns type="Object">Object with type information
-            /// attribute detectedPayloadKind(optional): see constants starting with PAYLOADTYPE_
-            /// attribute deltaKind(optional): deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
-            /// attribute typeName(optional): name of the type
-            /// attribute type(optional): object containing type information for entity- and complex-types ( null if a typeName is a primitive)
-            ///  </returns>
-            var parseContextUriFragment = function(fragments, model) {
-                var ret = {};
-
-                if (fragments.indexOf('/') === -1) {
-                    if (fragments.length === 0) {
-                        // Capter 10.1
-                        ret.detectedPayloadKind = PAYLOADTYPE_SVCDOC;
-                        return ret;
-                    } else if (fragments === 'Edm.Null') {
-                        // Capter 10.15
-                        ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
-                        ret.isNullProperty = true;
-                        return ret;
-                    } else if (fragments === 'Collection($ref)') {
-                        // Capter 10.11
-                        ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINKS;
-                        return ret;
-                    } else if (fragments === '$ref') {
-                        // Capter 10.12
-                        ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINK;
-                        return ret;
-                    } else {
-                        //TODO check for navigation resource
-                    }
-                }
-
-                ret.type = undefined;
-                ret.typeName = undefined;
-
-                var fragmentParts = fragments.split("/");
-                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;
-            };
-
-            var createPayloadInfo = function(data, model) {
-                /// <summary>Infers the information describing the JSON payload from its metadata annotation, structure, and data model.</summary>
-                /// <param name="data" type="Object">Json response payload object.</param>
-                /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-                /// <remarks>
-                ///     If the arguments passed to the function don't convey enough information about the payload to determine without doubt that the payload is a feed then it
-                ///     will try to use the payload object structure instead.  If the payload looks like a feed (has value property that is an array or non-primitive values) then
-                ///     the function will report its kind as PAYLOADTYPE_FEED unless the inferFeedAsComplexType flag is set to true. This flag comes from the user request
-                ///     and allows the user to control how the library behaves with an ambigous JSON payload.
-                /// </remarks>
-                /// <returns type="Object">
-                ///     Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
-                /// </returns>
-
-                var metadataUri = data[contextUrlAnnotation];
-                if (!metadataUri || typeof metadataUri !== "string") {
-                    return null;
-                }
-
-                var fragmentStart = metadataUri.lastIndexOf("#");
-                if (fragmentStart === -1) {
-                    return jsonMakePayloadInfo(PAYLOADTYPE_SVCDOC);
-                }
-
-                var fragment = metadataUri.substring(fragmentStart + 1);
-                return parseContextUriFragment(fragment, model);
-            };
-
-            var readPayloadMinimal = function(data, model, recognizeDates) {
-                /// <summary>Processe a JSON response payload with metadata-minimal</summary>
-                /// <param name="data" type="Object">Json response payload object</param>
-                /// <param name="model" type="Object">Object describing an OData conceptual schema</param>
-                /// <param name="recognizeDates" type="Boolean">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-                /// <returns type="Object">Object in the library's representation.</returns>
-
-                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;
-            };
-
-            var jsonGetEntryKey = function(data, entityModel) {
-                /// <summary>Gets the key of an entry.</summary>
-                /// <param name="data" type="Object">JSON entry.</param>
-                /// <paraFrom   Subject Received    Size    Categories  
-                /// <returns type="string">Entry instance key.</returns>
-
-                var entityInstanceKey;
-                var entityKeys = entityModel.key[0].propertyRef;
-                var type;
-                entityInstanceKey = "(";
-                if (entityKeys.length == 1) {
-                    type = lookupProperty(entityModel.property, entityKeys[0].name).type;
-                    entityInstanceKey += formatLiteral(data[entityKeys[0].name], type);
-                } else {
-                    var first = true;
-                    for (var i = 0; i < entityKeys.length; i++) {
-                        if (!first) {
-                            entityInstanceKey += ",";
-                        } else {
-                            first = false;
-                        }
-                        type = lookupProperty(entityModel.property, entityKeys[i].name).type;
-                        entityInstanceKey += entityKeys[i].name + "=" + formatLiteral(data[entityKeys[i].name], type);
-                    }
-                }
-                entityInstanceKey += ")";
-                return entityInstanceKey;
-            };
-
-            var readPayloadMinimalProperty = function(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;
-            };
-
-            var readPayloadMinimalCollection = function(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;
-            };
-            var readPayloadMinimalFeed = function(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;
-            };
-
-            var readPayloadMinimalEntry = function(data, model, entryInfo, baseURI, recognizeDates) {
-                return readPayloadMinimalObject(data, entryInfo, baseURI, model, recognizeDates);
-            };
-
-            var formatLiteral = function(value, type) {
-                /// <summary>Formats a value according to Uri literal format</summary>
-                /// <param name="value">Value to be formatted.</param>
-                /// <param name="type">Edm type of the value</param>
-                /// <returns type="string">Value after formatting</returns>
-
-                value = "" + formatRowLiteral(value, type);
-                value = encodeURIComponent(value.replace("'", "''"));
-                switch ((type)) {
-                    case "Edm.Binary":
-                        return "X'" + value + "'";
-                    case "Edm.DateTime":
-                        return "datetime" + "'" + value + "'";
-                    case "Edm.DateTimeOffset":
-                        return "datetimeoffset" + "'" + value + "'";
-                    case "Edm.Decimal":
-                        return value + "M";
-                    case "Edm.Guid":
-                        return "guid" + "'" + value + "'";
-                    case "Edm.Int64":
-                        return value + "L";
-                    case "Edm.Float":
-                        return value + "f";
-                    case "Edm.Double":
-                        return value + "D";
-                    case "Edm.Geography":
-                        return "geography" + "'" + value + "'";
-                    case "Edm.Geometry":
-                        return "geometry" + "'" + value + "'";
-                    case "Edm.Time":
-                        return "time" + "'" + value + "'";
-                    case "Edm.String":
-                        return "'" + value + "'";
-                    default:
-                        return value;
-                }
-            };
-
-            var formatRowLiteral = function(value, type) {
-                switch (type) {
-                    case "Edm.Binary":
-                        return convertByteArrayToHexString(value);
-                    default:
-                        return value;
-                }
-            };
-
-            var convertDates = function(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);
-                }
-            };
-
-            var convertDatesNoEdm = function(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);
-                }
-            };
-
-            var checkProperties = function(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);
-                            }
-                        }
-                    }
-                }
-            };
-
-            var readPayloadMinimalComplexObject = function(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);
-            };
-
-            var readPayloadMinimalObject = function(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"];
-
-            var isJsonSerializableProperty = function(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;
-            };
-
-            var jsonIsPrimitiveType = function(typeName) {
-                /// <summary>Determines whether a type name is a primitive type in a JSON payload.</summary>
-                /// <param name="typeName" type="String">Type name to test.</param>
-                /// <returns type="Boolean">True if the type name an EDM primitive type or an OData spatial type; false otherwise.</returns>
-
-                return isPrimitiveEdmType(typeName) || isGeographyEdmType(typeName) || isGeometryEdmType(typeName);
-            };
-
-
-            var jsonHandler = oDataHandler.handler(jsonParser, jsonSerializer, jsonMediaType, MAX_DATA_SERVICE_VERSION);
-            jsonHandler.recognizeDates = false;
-
-            exports.jsonHandler = jsonHandler;
-            exports.jsonParser = jsonParser;
-            exports.jsonSerializer = jsonSerializer;
-            exports.parseJsonDateString = parseJsonDateString;
-
-        }, {
-            "./../datajs.js": 4,
-            "./handler.js": 10,
-            "./utils.js": 14
-        }
-    ],
-    12: [
-        function(require, module, exports) {
-
-
-            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";
-
-            var schemaElement = function(attributes, elements, text, ns) {
-                /// <summary>Creates an object that describes an element in an schema.</summary>
-                /// <param name="attributes" type="Array">List containing the names of the attributes allowed for this element.</param>
-                /// <param name="elements" type="Array">List containing the names of the child elements allowed for this element.</param>
-                /// <param name="text" type="Boolean">Flag indicating if the element's text value is of interest or not.</param>
-                /// <param name="ns" type="String">Namespace to which the element belongs to.</param>
-                /// <remarks>
-                ///    If a child element name ends with * then it is understood by the schema that that child element can appear 0 or more times.
-                /// </remarks>
-                /// <returns type="Object">Object with attributes, elements, text, and ns fields.</returns>
-
-                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"]
-                    )
-                }
-            };
-
-
-            var scriptCase = function(text) {
-                /// <summary>Converts a Pascal-case identifier into a camel-case identifier.</summary>
-                /// <param name="text" type="String">Text to convert.</param>
-                /// <returns type="String">Converted text.</returns>
-                /// <remarks>If the text starts with multiple uppercase characters, it is left as-is.</remarks>
-
-                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();
-            };
-
-            var getChildSchema = function(parentSchema, candidateName) {
-                /// <summary>Gets the schema node for the specified element.</summary>
-                /// <param name="parentSchema" type="Object">Schema of the parent XML node of 'element'.</param>
-                /// <param name="candidateName">XML element name to consider.</param>
-                /// <returns type="Object">The schema that describes the specified element; null if not found.</returns>
-
-                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;
-            };
-
-            var isEdmNamespace = function(nsURI) {
-                /// <summary>Checks whether the specifies namespace URI is one of the known CSDL namespace URIs.</summary>
-                /// <param name="nsURI" type="String">Namespace URI to check.</param>
-                /// <returns type="Boolean">true if nsURI is a known CSDL namespace; false otherwise.</returns>
-
-                return nsURI === edmNs1;
-            };
-
-            var parseConceptualModelElement = function(element) {
-                /// <summary>Parses a CSDL document.</summary>
-                /// <param name="element">DOM element to parse.</param>
-                /// <returns type="Object">An object describing the parsed element.</returns>
-
-                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;
-            };
-
-            var metadataParser = function(handler, text) {
-                /// <summary>Parses a metadata document.</summary>
-                /// <param name="handler">This handler.</param>
-                /// <param name="text" type="String">Metadata text.</param>
-                /// <returns>An object representation of the conceptual model.</returns>
-
-                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;
-
-        }, {
-            "./../datajs.js": 4,
-            "./handler.js": 10
-        }
-    ],
-    13: [
-        function(require, module, exports) {
-
-
-            var utils = require('./../datajs.js').utils;
-            // Imports.
-
-            var defined = utils.defined;
-            var delay = utils.delay;
-
-            var ticks = 0;
-
-            var canUseJSONP = function(request) {
-                /// <summary>
-                /// Checks whether the specified request can be satisfied with a JSONP request.
-                /// </summary>
-                /// <param name="request">Request object to check.</param>
-                /// <returns type="Boolean">true if the request can be satisfied; false otherwise.</returns>
-
-                // 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.
-                if (request.method && request.method !== "GET") {
-                    return false;
-                }
-
-                return true;
-            };
-
-            var createIFrame = function(url) {
-                /// <summary>Creates an IFRAME tag for loading the JSONP script</summary>
-                /// <param name="url" type="String">The source URL of the script</param>
-                /// <returns type="HTMLElement">The IFRAME tag</returns>
-                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;
-            };
-
-            var createXmlHttpRequest = function() {
-                /// <summary>Creates a XmlHttpRequest object.</summary>
-                /// <returns type="XmlHttpRequest">XmlHttpRequest object.</returns>
-                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;
-            };
-
-            var isAbsoluteUrl = function(url) {
-                /// <summary>Checks whether the specified URL is an absolute URL.</summary>
-                /// <param name="url" type="String">URL to check.</param>
-                /// <returns type="Boolean">true if the url is an absolute URL; false otherwise.</returns>
-
-                return url.indexOf("http://") === 0 ||
-                    url.indexOf("https://") === 0 ||
-                    url.indexOf("file://") === 0;
-            };
-
-            var isLocalUrl = function(url) {
-                /// <summary>Checks whether the specified URL is local to the current context.</summary>
-                /// <param name="url" type="String">URL to check.</param>
-                /// <returns type="Boolean">true if the url is a local URL; false otherwise.</returns>
-
-                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);
-            };
-
-            var removeCallback = function(name, tick) {
-                /// <summary>Removes a callback used for a JSONP request.</summary>
-                /// <param name="name" type="String">Function name to remove.</param>
-                /// <param name="tick" type="Number">Tick count used on the callback.</param>
-                try {
-                    delete window[name];
-                } catch (err) {
-                    window[name] = undefined;
-                    if (tick === ticks - 1) {
-                        ticks -= 1;
-                    }
-                }
-            };
-
-            var removeIFrame = function(iframe) {
-                /// <summary>Removes an iframe.</summary>
-                /// <param name="iframe" type="Object">The iframe to remove.</param>
-                /// <returns type="Object">Null value to be assigned to iframe reference.</returns>
-                if (iframe) {
-                    writeHtmlToIFrame(iframe, "");
-                    iframe.parentNode.removeChild(iframe);
-                }
-
-                return null;
-            };
-
-            var readResponseHeaders = function(xhr, headers) {
-                /// <summary>Reads response headers into array.</summary>
-                /// <param name="xhr" type="XMLHttpRequest">HTTP request with response available.</param>
-                /// <param name="headers" type="Array">Target array to fill with name/value pairs.</param>
-
-                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];
-                    }
-                }
-            };
-
-            var writeHtmlToIFrame = function(iframe, html) {
-                /// <summary>Writes HTML to an IFRAME document.</summary>
-                /// <param name="iframe" type="HTMLElement">The IFRAME element to write to.</param>
-                /// <param name="html" type="String">The HTML to write.</param>
-                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,
-
-                request: function(request, success, error) {
-                    /// <summary>Performs a network request.</summary>
-                    /// <param name="request" type="Object">Request description.</request>
-                    /// <param name="success" type="Function">Success callback with the response object.</param>
-                    /// <param name="error" type="Function">Error callback with an error object.</param>
-                    /// <returns type="Object">Object with an 'abort' method for the operation.</returns>
-
-                    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;
-
-
-        }, {
-            "./../datajs.js": 4
-        }
-    ],
-    14: [
-        function(require, module, exports) {
-            /*
-             * 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
-            ];
-
-            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 formatDateTimeOffsetJSON = function(value) {
-                return "\/Date(" + value.getTime() + ")\/";
-            };
-
-            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;
-                    }
-                    // 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);
-            };
-
-            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>
-
-                //check with edm
-                var ret = contains(geographyEdmTypes, typeName) ||
-                    (typeName.indexOf('.') === -1 && contains(geographyTypes, typeName));
-                return ret;
-
-            };
-
-            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>
-
-                var ret = contains(geometryEdmTypes, typeName) ||
-                    (typeName.indexOf('.') === -1 && contains(geometryTypes, typeName));
-                return ret;
-            };
-
-            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 lookupSingleton = function(singletons, name) {
-                /// <summary>Looks up a entity set by name.</summary>
-                /// <param name="properties" type="Array" mayBeNull="true">Array of entity set objects as per EDM metadata.</param>
-                /// <param name="name" type="String">Name to look for.</param>
-                /// <returns type="Object">The entity set object; null if not found.</returns>
-
-                return find(singletons, function(singleton) {
-                    return singleton.name === name;
-                });
-            };
-
-            var lookupComplexType = function(name, metadata) {
-                /// <summary>Looks up a complex type object by name.</summary>
-                /// <param name="name" type="String">Name, possibly null or empty.</param>
-                /// <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) {
-                    if (isObject(schema.entityContainer)) {
-                        return schema.entityContainer;
-                    }
-                });
-            };
-
-            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 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;
-            };
-
-            var removeNamespace = function(ns, fullName) {
-                /// <summary>Given an expected namespace prefix, removes it from a full name.</summary>
-                /// <param name="ns" type="String">Expected namespace.</param>
-                /// <param name="fullName" type="String">Full name in 'ns'.'name' form.</param>
-                /// <returns type="String">The local name, null if it isn't found in the expected namespace.</returns>
-
-                if (fullName.indexOf(ns) === 0 && fullName.charAt(ns.length) === ".") {
-                    return fullName.substr(ns.length + 1);
-                }
-
-                return null;
-            };
-
-            var lookupInSchema = function(name, schema, kind) {
-                /// <summary>Looks up a schema object by name.</summary>
-                /// <param name="name" type="String">Name (assigned).</param>
-                /// <param name="schema">Schema object as per EDM metadata.</param>
-                /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
-                /// <returns>An entity type description if the name is found; null otherwise.</returns>
-
-                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;
-            };
-
-            var maxVersion = function(left, right) {
-                /// <summary>Compares to version strings and returns the higher one.</summary>
-                /// <param name="left" type="String">Version string in the form "major.minor.rev"</param>
-                /// <param name="right" type="String">Version string in the form "major.minor.rev"</param>
-                /// <returns type="String">The higher version string.</returns>
-
-                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"
-            };
-
-            var normalizeHeaders = function(headers) {
-                /// <summary>Normalizes headers so they can be found with consistent casing.</summary>
-                /// <param name="headers" type="Object">Dictionary of name/value pairs.</param>
-
-                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;
-                    }
-                }
-            };
-
-            var parseBool = function(propertyValue) {
-                /// <summary>Parses a string into a boolean value.</summary>
-                /// <param name="propertyValue">Value to parse.</param>
-                /// <returns type="Boolean">true if the property value is 'true'; false otherwise.</returns>
-
-                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+))?(.*)$/;
-
-            var parseDateTimeMaybeOffset = function(value, withOffset, nullOnError) {
-                /// <summary>Parses a string into a DateTime value.</summary>
-                /// <param name="value" type="String">Value to parse.</param>
-                /// <param name="withOffset" type="Boolean">Whether offset is expected.</param>
-                /// <returns type="Date">The parsed value.</returns>
-
-                // 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;
-            };
-
-            var parseDate = function(propertyValue, nullOnError) {
-                /// <summary>Parses a string into a Date object.</summary>
-                /// <param name="propertyValue" type="String">Value to parse.</param>
-                /// <returns type="Date">The parsed with year, month, day set, time values are set to 0</returns>
-                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+))?)?$/;
-
-            var parseTimeOfDay = function(propertyValue, nullOnError) {
-                var parts = parseTimeOfDayRE.exec(propertyValue);
-
-
-                return {
-                    'h': parseInt10(parts[1]),
-                    'm': parseInt10(parts[2]),
-                    's': parseInt10(parts[4]),
-                    'ms': parseInt10(parts[6]),
-                };
-            };
-
-            var parseDateTimeOffset = function(propertyValue, nullOnError) {
-                /// <summary>Parses a string into a DateTimeOffset value.</summary>
-                /// <param name="propertyValue" type="String">Value to parse.</param>
-                /// <returns type="Date">The parsed value.</returns>
-                /// <remarks>
-                /// 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.
-                /// </remarks>
-
-                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)?)?/;
-
-            var isEdmDurationValue = function(value) {
-                parseTimeRE.test(value);
-            };
-
-            var parseDuration = function(duration) {
-                /// <summary>Parses a string in xsd:duration format.</summary>
-                /// <param name="duration" type="String">Duration value.</param>
-                /// <remarks>
-                /// This method will throw an exception if the input string has a year or a month component.
-                /// </remarks>
-                /// <returns type="Object">Object representing the time</returns>
-
-                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;
-            };
-
-            var parseTimezone = function(timezone) {
-                /// <summary>Parses a timezone description in (+|-)nn:nn format.</summary>
-                /// <param name="timezone" type="String">Timezone offset.</param>
-                /// <returns type="Object">
-                /// An object with a (d)irection property of 1 for + and -1 for -,
-                /// offset (h)ours and offset (m)inutes.
-                /// </returns>
-
-                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
-                };
-            };
-
-            var prepareRequest = function(request, handler, context) {
-                /// <summary>Prepares a request object so that it can be sent through the network.</summary>
-                /// <param name="request">Object that represents the request to be sent.</param>
-                /// <param name="handler">Handler for data serialization</param>
-                /// <param name="context">Context used for preparing the request</param>
-
-                // 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;
-                }
-
-            };
-
-            var traverseInternal = function(item, owner, callback) {
-                /// <summary>Traverses a tree of objects invoking callback for every value.</summary>
-                /// <param name="item" type="Object">Object or array to traverse.</param>
-                /// <param name="callback" type="Function">
-                /// Callback function with key and value, similar to JSON.parse reviver.
-                /// </param>
-                /// <returns type="Object">The object with traversed properties.</returns>
-                /// <remarks>Unlike the JSON reviver, this won't delete null members.</remarks>
-
-                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;
-            };
-
-            var traverse = function(item, callback) {
-                /// <summary>Traverses a tree of objects invoking callback for every value.</summary>
-                /// <param name="item" type="Object">Object or array to traverse.</param>
-                /// <param name="callback" type="Function">
-                /// Callback function with key and value, similar to JSON.parse reviver.
-                /// </param>
-                /// <returns type="Object">The traversed object.</returns>
-                /// <remarks>Unlike the JSON reviver, this won't delete null members.</remarks>
-
-                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;
-
-
-        }, {
-            "./../datajs.js": 4
-        }
-    ],
-    15: [
-        function(require, module, exports) {
-            /*
-             * 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.
-             */
-
-            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
-            };
-
-            exports.defaultStoreMechanism = "best";
-
-            exports.createStore = function(name, mechanism) {
-                /// <summary>Creates a new store object.</summary>
-                /// <param name="name" type="String">Store name.</param>
-                /// <param name="mechanism" type="String" optional="true">A specific mechanism to use (defaults to best, can be "best", "dom", "indexeddb", "webdb").</param>
-                /// <returns type="Object">Store object.</returns>
-
-                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;
-
-
-
-        }, {
-            "./store/dom.js": 16,
-            "./store/indexeddb.js": 17,
-            "./store/memory.js": 18
-        }
-    ],
-    16: [
-        function(require, module, exports) {
-            /*
-             * 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 utils = require('./../datajs.js').utils;
-
-            // Imports.
-            var throwErrorCallback = utils.throwErrorCallback;
-            var delay = utils.delay;
-
-            var localStorage = null;
-
-            var domStoreDateToJSON = function() {
-                /// <summary>Converts a Date object into an object representation friendly to JSON serialization.</summary>
-                /// <returns type="Object">Object that represents the Date.</returns>
-                /// <remarks>
-                ///   This method is used to override the Date.toJSON method and is called only by
-                ///   JSON.stringify.  It should never be called directly.
-                /// </remarks>
-
-                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;
-            };
-
-            var domStoreJSONToDate = function(_, value) {
-                /// <summary>JSON reviver function for converting an object representing a Date in a JSON stream to a Date object</summary>
-                /// <param value="Object">Object to convert.</param>
-                /// <returns type="Date">Date object.</returns>
-                /// <remarks>
-                ///   This method is used during JSON parsing and invoked only by the reviver function.
-                ///   It should never be called directly.
-                /// </remarks>
-
-                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;
-            };
-
-            var qualifyDomStoreKey = function(store, key) {
-                /// <summary>Qualifies the key with the name of the store.</summary>
-                /// <param name="store" type="Object">Store object whose name will be used for qualifying the key.</param>
-                /// <param name="key" type="String">Key string.</param>
-                /// <returns type="String">Fully qualified key string.</returns>
-
-                return store.name + "#!#" + key;
-            };
-
-            var unqualifyDomStoreKey = function(store, key) {
-                /// <summary>Gets the key part of a fully qualified key string.</summary>
-                /// <param name="store" type="Object">Store object whose name will be used for qualifying the key.</param>
-                /// <param name="key" type="String">Fully qualified key string.</param>
-                /// <returns type="String">Key part string</returns>
-
-                return key.replace(store.name + "#!#", "");
-            };
-
-            var DomStore = function(name) {
-                /// <summary>Constructor for store objects that use DOM storage as the underlying mechanism.</summary>
-                /// <param name="name" type="String">Store name.</param>
-                this.name = name;
-            };
-
-            DomStore.create = function(name) {
-                /// <summary>Creates a store object that uses DOM Storage as its underlying mechanism.</summary>
-                /// <param name="name" type="String">Store name.</param>
-                /// <returns type="Object">Store object.</returns>
-
-                if (DomStore.isSupported()) {
-                    localStorage = localStorage || window.localStorage;
-                    return new DomStore(name);
-                }
-
-                throw {
-                    message: "Web Storage not supported by the browser"
-                };
-            };
-
-            DomStore.isSupported = function() {
-                /// <summary>Checks whether the underlying mechanism for this kind of store objects is supported by the browser.</summary>
-                /// <returns type="Boolean">True if the mechanism is supported by the browser; otherwise false.</summary>
-                return !!window.localStorage;
-            };
-
-            DomStore.prototype.add = function(key, value, success, error) {
-                /// <summary>Adds a new value identified by a key to the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="value">Value that is going to be added to the store.</param>
-                /// <param name="success" type="Function" optional="no">Callback for a successful add operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                /// <remarks>
-                ///    This method errors out if the store already contains the specified key.
-                /// </remarks>
-
-                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);
-            };
-
-            DomStore.prototype.addOrUpdate = function(key, value, success, error) {
-                /// <summary>Adds or updates a value identified by a key to the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="value">Value that is going to be added or updated to the store.</param>
-                /// <param name="success" type="Function" optional="no">Callback for a successful add or update operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                /// <remarks>
-                ///   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.
-                /// </remarks>
-
-                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;
-                    }
-                }
-            };
-
-            DomStore.prototype.clear = function(success, error) {
-                /// <summary>Removes all the data associated with this store object.</summary>
-                /// <param name="success" type="Function" optional="no">Callback for a successful clear operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                /// <remarks>
-                ///    In case of an error, this method will not restore any keys that might have been deleted at that point.
-                /// </remarks>
-
-                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);
-                }
-            };
-
-            DomStore.prototype.close = function() {
-                /// <summary>This function does nothing in DomStore as it does not have a connection model</summary>
-            };
-
-            DomStore.prototype.contains = function(key, success, error) {
-                /// <summary>Checks whether a key exists in the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="success" type="Function" optional="no">Callback indicating whether the store contains the key or not.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                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;
-
-            DomStore.prototype.getAllKeys = function(success, error) {
-                /// <summary>Gets all the keys that exist in the store.</summary>
-                /// <param name="success" type="Function" optional="no">Callback for a successful get operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-
-                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);
-                }
-            };
-
-            /// <summary>Identifies the underlying mechanism used by the store.</summary>
-            DomStore.prototype.mechanism = "dom";
-
-            DomStore.prototype.read = function(key, success, error) {
-                /// <summary>Reads the value associated to a key in the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="success" type="Function" optional="no">Callback for a successful reads operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                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);
-                    }
-                }
-            };
-
-            DomStore.prototype.remove = function(key, success, error) {
-                /// <summary>Removes a key and its value from the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="success" type="Function" optional="no">Callback for a successful remove operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                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);
-                    }
-                }
-            };
-
-            DomStore.prototype.update = function(key, value, success, error) {
-                /// <summary>Updates the value associated to a key in the store.</summary>
-                /// <param name="key" type="String">Key string.</param>
-                /// <param name="value">New value.</param>
-                /// <param name="success" type="Function" optional="no">Callback for a successful update operation.</param>
-                /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                /// <remarks>
-                ///    This method errors out if the specified key is not found in the store.
-                /// </remarks>
-
-                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;
-
-        }, {
-            "./../datajs.js": 4
-        }
-    ],
-    17: [
-        function(require, module, exports) {
-            /*
-             * 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 utils = require('./../datajs.js').utils;
-
-
-            // Imports.
-            var throwErrorCallback = utils.throwErrorCallback;
-            var delay = utils.delay;
-
-            var indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
-            var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
-            var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
-
-            var IDBT_READ_ONLY = IDBTransaction.READ_ONLY || "readonly";
-            var IDBT_READ_WRITE = IDBTransaction.READ_WRITE || "readwrite";
-
-            var getError = function(error, defaultError) {
-                /// <summary>Returns either a specific error handler or the default error handler</summary>
-                /// <param name="error" type="Function">The specific error handler</param>
-                /// <param name="defaultError" type="Function">The default error handler</param>
-                /// <returns type="Function">The error callback</returns>
-
-                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
-                    });
-                };
-            };
-
-            var openStoreDb = function(store, success, error) {
-                /// <summary>Opens the store object's indexed db database.</summary>
-                /// <param name="store" type="IndexedDBStore">The store object</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-
-                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);
-                };
-            };
-
-            var openTransaction = function(store, mode, success, error) {
-                /// <summary>Opens a new transaction to the store</summary>
-                /// <param name="store" type="IndexedDBStore">The store object</param>
-                /// <param name="mode" type="Short">The read/write mode of the transaction (constants from IDBTransaction)</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-
-                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);
-            };
-
-            var IndexedDBStore = function(name) {
-                /// <summary>Creates a new IndexedDBStore.</summary>
-                /// <param name="name" type="String">The name of the store.</param>
-                /// <returns type="Object">The new IndexedDBStore.</returns>
-                this.name = name;
-            };
-
-            IndexedDBStore.create = function(name) {
-                /// <summary>Creates a new IndexedDBStore.</summary>
-                /// <param name="name" type="String">The name of the store.</param>
-                /// <returns type="Object">The new IndexedDBStore.</returns>
-                if (IndexedDBStore.isSupported()) {
-                    return new IndexedDBStore(name);
-                }
-
-                throw {
-                    message: "IndexedDB is not supported on this browser"
-                };
-            };
-
-            IndexedDBStore.isSupported = function() {
-                /// <summary>Returns whether IndexedDB is supported.</summary>
-                /// <returns type="Boolean">True if IndexedDB is supported, false otherwise.</returns>
-                return !!indexedDB;
-            };
-
-            IndexedDBStore.prototype.add = function(key, value, success, error) {
-                /// <summary>Adds a key/value pair to the store</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="value" type="Object">The value</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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);
-            };
-
-            IndexedDBStore.prototype.addOrUpdate = function(key, value, success, error) {
-                /// <summary>Adds or updates a key/value pair in the store</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="value" type="Object">The value</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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);
-            };
-
-            IndexedDBStore.prototype.clear = function(success, error) {
-                /// <summary>Clears the store</summary>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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);
-            };
-
-            IndexedDBStore.prototype.close = function() {
-                /// <summary>Closes the connection to the database</summary>
-                if (this.db) {
-                    this.db.close();
-                    this.db = null;
-                }
-            };
-
-            IndexedDBStore.prototype.contains = function(key, success, error) {
-                /// <summary>Returns whether the store contains a key</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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;
-
-            IndexedDBStore.prototype.getAllKeys = function(success, error) {
-                /// <summary>Gets all the keys from the store</summary>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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);
-            };
-
-            /// <summary>Identifies the underlying mechanism used by the store.</summary>
-            IndexedDBStore.prototype.mechanism = "indexeddb";
-
-            IndexedDBStore.prototype.read = function(key, success, error) {
-                /// <summary>Reads the value for the specified key</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                /// <remarks>If the key does not exist, the success handler will be called with value = undefined</remarks>
-                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);
-            };
-
-            IndexedDBStore.prototype.remove = function(key, success, error) {
-                /// <summary>Removes the specified key from the store</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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);
-            };
-
-            IndexedDBStore.prototype.update = function(key, value, success, error) {
-                /// <summary>Updates a key/value pair in the store</summary>
-                /// <param name="key" type="String">The key</param>
-                /// <param name="value" type="Object">The value</param>
-                /// <param name="success" type="Function">The success callback</param>
-                /// <param name="error" type="Function">The error callback</param>
-                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;
-
-        }, {
-            "./../datajs.js": 4
-        }
-    ],
-    18: [
-        function(require, module, exports) {
-
-
-            var utils = require('./../datajs.js').utils;
-
-
-            // Imports.
-            var throwErrorCallback = utils.throwErrorCallback;
-            var delay = utils.delay;
-
-            var MemoryStore = function(name) {
-                /// <summary>Constructor for store objects that use a sorted array as the underlying mechanism.</summary>
-                /// <param name="name" type="String">Store name.</param>
-
-                var holes = [];
-                var items = [];
-                var keys = {};
-
-                this.name = name;
-
-                var getErrorCallback = function(error) {
-                    return error || this.defaultError;
-                };
-
-                var validateKeyInput = function(key, error) {
-                    /// <summary>Validates that the specified key is not undefined, not null, and not an array</summary>
-                    /// <param name="key">Key value.</param>
-                    /// <param name="error" type="Function">Error callback.</param>
-                    /// <returns type="Boolean">True if the key is valid. False if the key is invalid and the error callback has been queued for execution.</returns>
-
-                    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.add = function(key, value, success, error) {
-                    /// <summary>Adds a new value identified by a key to the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="value">Value that is going to be added to the store.</param>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful add operation.</param>
-                    /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                    /// <remarks>
-                    ///    This method errors out if the store already contains the specified key.
-                    /// </remarks>
-
-                    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.addOrUpdate = function(key, value, success, error) {
-                    /// <summary>Adds or updates a value identified by a key to the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="value">Value that is going to be added or updated to the store.</param>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful add or update operation.</param>
-                    /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                    /// <remarks>
-                    ///   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.
-                    /// </remarks>
-
-                    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);
-                    }
-                };
-
-                this.clear = function(success) {
-                    /// <summary>Removes all the data associated with this store object.</summary>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful clear operation.</param>
-
-                    items = [];
-                    keys = {};
-                    holes = [];
-
-                    delay(success);
-                };
-
-                this.contains = function(key, success) {
-                    /// <summary>Checks whether a key exists in the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="success" type="Function" optional="no">Callback indicating whether the store contains the key or not.</param>
-
-                    var contained = keys.hasOwnProperty(key);
-                    delay(success, contained);
-                };
-
-                this.getAllKeys = function(success) {
-                    /// <summary>Gets all the keys that exist in the store.</summary>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful get operation.</param>
-
-                    var results = [];
-                    for (var name in keys) {
-                        results.push(name);
-                    }
-                    delay(success, results);
-                };
-
-                this.read = function(key, success, error) {
-                    /// <summary>Reads the value associated to a key in the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful reads operation.</param>
-                    /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                    error = getErrorCallback(error);
-
-                    if (validateKeyInput(key, error)) {
-                        var index = keys[key];
-                        delay(success, key, items[index]);
-                    }
-                };
-
-                this.remove = function(key, success, error) {
-                    /// <summary>Removes a key and its value from the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful remove operation.</param>
-                    /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                    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);
-                    }
-                };
-
-                this.update = function(key, value, success, error) {
-                    /// <summary>Updates the value associated to a key in the store.</summary>
-                    /// <param name="key" type="String">Key string.</param>
-                    /// <param name="value">New value.</param>
-                    /// <param name="success" type="Function" optional="no">Callback for a successful update operation.</param>
-                    /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-                    /// <remarks>
-                    ///    This method errors out if the specified key is not found in the store.
-                    /// </remarks>
-
-                    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
-                            });
-                        }
-                    }
-                };
-            };
-
-            MemoryStore.create = function(name) {
-                /// <summary>Creates a store object that uses memory storage as its underlying mechanism.</summary>
-                /// <param name="name" type="String">Store name.</param>
-                /// <returns type="Object">Store object.</returns>
-                return new MemoryStore(name);
-            };
-
-            MemoryStore.isSupported = function() {
-                /// <summary>Checks whether the underlying mechanism for this kind of store objects is supported by the browser.</summary>
-                /// <returns type="Boolean">True if the mechanism is supported by the browser; otherwise false.</returns>
-                return true;
-            };
-
-            MemoryStore.prototype.close = function() {
-                /// <summary>This function does nothing in MemoryStore as it does not have a connection model.</summary>
-            };
-
-            MemoryStore.prototype.defaultError = throwErrorCallback;
-
-            /// <summary>Identifies the underlying mechanism used by the store.</summary>
-            MemoryStore.prototype.mechanism = "memory";
-
-            module.exports = MemoryStore;
-
-        }, {
-            "./../datajs.js": 4
-        }
-    ]
-}, {}, [1]);
\ No newline at end of file
diff --git a/datajs/tests/e2etest/datajs-1.1.2.js b/datajs/tests/e2etest/datajs-1.1.2.js
deleted file mode 100644
index 5040efc..0000000
--- a/datajs/tests/e2etest/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 = schema.entityContainer;
-            for (var i = 0; i < containers.length; i++) {
-                var entitySets = containers[i].entitySet;
-                if (entitySets) {
-                    for (var j = 0; j < entitySets.length; j++) {
-                        if (entitySets[j].name == entitySetName) {
-                            return { entitySet: entitySets[j], containerName: containers[i].name, functionImport: containers[i].functionImport };
-                        }
-                    }
-                }
-            }
-            return null;
-        });
-
-        return info;
-    };
-
-    var removeNamespace = function (ns, fullName) {
-        /// <summary>Given an expected namespace prefix, removes it from a full name.</summary>
-        /// <param name="ns" type="String">Expected namespace.</param>
-        /// <param name="fullName" type="String">Full name in 'ns'.'name' form.</param>
-        /// <returns type="String">The local name, null if it isn't found in the expected namespace.</returns>
-
-        if (fullName.indexOf(ns) === 0 && fullName.charAt(ns.length) === ".") {
-            return fullName.substr(ns.length + 1);
-        }
-
-        return null;
-    };
-
-    var lookupInSchema = function (name, schema, kind) {
-        /// <summary>Looks up a schema object by name.</summary>
-        /// <param name="name" type="String">Name (assigned).</param>
-        /// <param name="schema">Schema object as per EDM metadata.</param>
-        /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param>
-        /// <returns>An entity type description if the name is found; null otherwise.</returns>
-
-        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;
-    };
-
-    var maxVersion = function (left, right) {
-        /// <summary>Compares to version strings and returns the higher one.</summary>
-        /// <param name="left" type="String">Version string in the form "major.minor.rev"</param>
-        /// <param name="right" type="String">Version string in the form "major.minor.rev"</param>
-        /// <returns type="String">The higher version string.</returns>
-
-        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 = {
-        "accept": "Accept",
-        "content-type": "Content-Type",
-        "dataserviceversion": "DataServiceVersion",
-        "maxdataserviceversion": "MaxDataServiceVersion"
-    };
-
-    var normalizeHeaders = function (headers) {
-        /// <summary>Normalizes headers so they can be found with consistent casing.</summary>
-        /// <param name="headers" type="Object">Dictionary of name/value pairs.</param>
-
-        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;
-            }
-        }
-    };
-
-    var parseBool = function (propertyValue) {
-        /// <summary>Parses a string into a boolean value.</summary>
-        /// <param name="propertyValue">Value to parse.</param>
-        /// <returns type="Boolean">true if the property value is 'true'; false otherwise.</returns>
-
-        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+))?(.*)$/;
-
-    var parseDateTimeMaybeOffset = function (value, withOffset, nullOnError) {
-        /// <summary>Parses a string into a DateTime value.</summary>
-        /// <param name="value" type="String">Value to parse.</param>
-        /// <param name="withOffset" type="Boolean">Whether offset is expected.</param>
-        /// <returns type="Date">The parsed value.</returns>
-
-        // 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;
-    };
-
-    var parseDateTime = function (propertyValue, nullOnError) {
-        /// <summary>Parses a string into a DateTime value.</summary>
-        /// <param name="propertyValue" type="String">Value to parse.</param>
-        /// <returns type="Date">The parsed value.</returns>
-
-        return parseDateTimeMaybeOffset(propertyValue, false, nullOnError);
-    };
-
-    var parseDateTimeOffset = function (propertyValue, nullOnError) {
-        /// <summary>Parses a string into a DateTimeOffset value.</summary>
-        /// <param name="propertyValue" type="String">Value to parse.</param>
-        /// <returns type="Date">The parsed value.</returns>
-        /// <remarks>
-        /// 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.
-        /// </remarks>
-
-        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)?)?/;
-
-    var isEdmDurationValue = function(value) {
-        parseTimeRE.test(value);
-    };
-
-    var parseDuration = function (duration) {
-        /// <summary>Parses a string in xsd:duration format.</summary>
-        /// <param name="duration" type="String">Duration value.</param>
-        /// <remarks>
-        /// This method will throw an exception if the input string has a year or a month component.
-        /// </remarks>
-        /// <returns type="Object">Object representing the time</returns>
-
-        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;
-    };
-
-    var parseTimezone = function (timezone) {
-        /// <summary>Parses a timezone description in (+|-)nn:nn format.</summary>
-        /// <param name="timezone" type="String">Timezone offset.</param>
-        /// <returns type="Object">
-        /// An object with a (d)irection property of 1 for + and -1 for -,
-        /// offset (h)ours and offset (m)inutes.
-        /// </returns>
-
-        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 };
-    };
-
-    var prepareRequest = function (request, handler, context) {
-        /// <summary>Prepares a request object so that it can be sent through the network.</summary>
-        /// <param name="request">Object that represents the request to be sent.</param>
-        /// <param name="handler">Handler for data serialization</param>
-        /// <param name="context">Context used for preparing the request</param>
-
-        // 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.MaxDataServiceVersion)) {
-            request.headers.MaxDataServiceVersion = handler.maxDataServiceVersion || "1.0";
-        }
-    };
-
-    var traverseInternal = function (item, owner, callback) {
-        /// <summary>Traverses a tree of objects invoking callback for every value.</summary>
-        /// <param name="item" type="Object">Object or array to traverse.</param>
-        /// <param name="callback" type="Function">
-        /// Callback function with key and value, similar to JSON.parse reviver.
-        /// </param>
-        /// <returns type="Object">The object with traversed properties.</returns>
-        /// <remarks>Unlike the JSON reviver, this won't delete null members.</remarks>
-
-        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;
-    };
-
-    var traverse = function (item, callback) {
-        /// <summary>Traverses a tree of objects invoking callback for every value.</summary>
-        /// <param name="item" type="Object">Object or array to traverse.</param>
-        /// <param name="callback" type="Function">
-        /// Callback function with key and value, similar to JSON.parse reviver.
-        /// </param>
-        /// <returns type="Object">The traversed object.</returns>
-        /// <remarks>Unlike the JSON reviver, this won't delete null members.</remarks>
-
-        return callback("", traverseInternal(item, "", callback));
-    };
-
-
-    var ticks = 0;
-
-    var canUseJSONP = function (request) {
-        /// <summary>
-        /// Checks whether the specified request can be satisfied with a JSONP request.
-        /// </summary>
-        /// <param name="request">Request object to check.</param>
-        /// <returns type="Boolean">true if the request can be satisfied; false otherwise.</returns>
-
-        // 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.
-        if (request.method && request.method !== "GET") {
-            return false;
-        }
-
-        return true;
-    };
-
-    var createIFrame = function (url) {
-        /// <summary>Creates an IFRAME tag for loading the JSONP script</summary>
-        /// <param name="url" type="String">The source URL of the script</param>
-        /// <returns type="HTMLElement">The IFRAME tag</returns>
-        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;
-    };
-
-    var createXmlHttpRequest = function () {
-        /// <summary>Creates a XmlHttpRequest object.</summary>
-        /// <returns type="XmlHttpRequest">XmlHttpRequest object.</returns>
-        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;
-    };
-
-    var isAbsoluteUrl = function (url) {
-        /// <summary>Checks whether the specified URL is an absolute URL.</summary>
-        /// <param name="url" type="String">URL to check.</param>
-        /// <returns type="Boolean">true if the url is an absolute URL; false otherwise.</returns>
-
-        return url.indexOf("http://") === 0 ||
-            url.indexOf("https://") === 0 ||
-            url.indexOf("file://") === 0;
-    };
-
-    var isLocalUrl = function (url) {
-        /// <summary>Checks whether the specified URL is local to the current context.</summary>
-        /// <param name="url" type="String">URL to check.</param>
-        /// <returns type="Boolean">true if the url is a local URL; false otherwise.</returns>
-
-        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);
-    };
-
-    var removeCallback = function (name, tick) {
-        /// <summary>Removes a callback used for a JSONP request.</summary>
-        /// <param name="name" type="String">Function name to remove.</param>
-        /// <param name="tick" type="Number">Tick count used on the callback.</param>
-        try {
-            delete window[name];
-        } catch (err) {
-            window[name] = undefined;
-            if (tick === ticks - 1) {
-                ticks -= 1;
-            }
-        }
-    };
-
-    var removeIFrame = function (iframe) {
-        /// <summary>Removes an iframe.</summary>
-        /// <param name="iframe" type="Object">The iframe to remove.</param>
-        /// <returns type="Object">Null value to be assigned to iframe reference.</returns>
-        if (iframe) {
-            writeHtmlToIFrame(iframe, "");
-            iframe.parentNode.removeChild(iframe);
-        }
-
-        return null;
-    };
-
-    var readResponseHeaders = function (xhr, headers) {
-        /// <summary>Reads response headers into array.</summary>
-        /// <param name="xhr" type="XMLHttpRequest">HTTP request with response available.</param>
-        /// <param name="headers" type="Array">Target array to fill with name/value pairs.</param>
-
-        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];
-            }
-        }
-    };
-
-    var writeHtmlToIFrame = function (iframe, html) {
-        /// <summary>Writes HTML to an IFRAME document.</summary>
-        /// <param name="iframe" type="HTMLElement">The IFRAME element to write to.</param>
-        /// <param name="html" type="String">The HTML to write.</param>
-        var frameDocument = (iframe.contentWindow) ? iframe.contentWindow.document : iframe.contentDocument.document;
-        frameDocument.open();
-        frameDocument.write(html);
-        frameDocument.close();
-    };
-
-    odata.defaultHttpClient = {
-        callbackParameterName: "$callback",
-
-        formatQueryString: "$format=json",
-
-        enableJsonpCallback: false,
-
-        request: function (request, success, error) {
-            /// <summary>Performs a network request.</summary>
-            /// <param name="request" type="Object">Request description.</request>
-            /// <param name="success" type="Function">Success callback with the response object.</param>
-            /// <param name="error" type="Function">Error callback with an error object.</param>
-            /// <returns type="Object">Object with an 'abort' method for the operation.</returns>
-
-            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;
-                        // Adding dataServiceVersion in case of json light ( data.d doesn't exist )
-                        if (data.d === undefined) {
-                            headers = { "Content-Type": "application/json;odata=minimalmetadata", dataServiceVersion: "3.0" };
-                        } else {
-                            headers = { "Content-Type": "application/json" };
-                        }
-                        // 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 (this.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;
-        }
-    };
-
-
-
-    var MAX_DATA_SERVICE_VERSION = "3.0";
-
-    var contentType = function (str) {
-        /// <summary>Parses a string into an object with media type and properties.</summary>
-        /// <param name="str" type="String">String with media type to parse.</param>
-        /// <returns>null if the string is empty; an object with 'mediaType' and a 'properties' dictionary otherwise.</returns>
-
-        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 };
-    };
-
-    var contentTypeToString = function (contentType) {
-        /// <summary>Serializes an object with media type and properties dictionary into a string.</summary>
-        /// <param name="contentType">Object with media type and properties dictionary to serialize.</param>
-        /// <returns>String representation of the media type object; undefined if contentType is null or undefined.</returns>
-
-        if (!contentType) {
-            return undefined;
-        }
-
-        var result = contentType.mediaType;
-        var property;
-        for (property in contentType.properties) {
-            result += ";" + property + "=" + contentType.properties[property];
-        }
-        return result;
-    };
-
-    var createReadWriteContext = function (contentType, dataServiceVersion, context, handler) {
-        /// <summary>Creates an object that is going to be used as the context for the handler's parser and serializer.</summary>
-        /// <param name="contentType">Object with media type and properties dictionary.</param>
-        /// <param name="dataServiceVersion" type="String">String indicating the version of the protocol to use.</param>
-        /// <param name="context">Operation context.</param>
-        /// <param name="handler">Handler object that is processing a resquest or response.</param>
-        /// <returns>Context object.</returns>
-
-        var rwContext = {};
-        extend(rwContext, context);
-        extend(rwContext, {
-            contentType: contentType,
-            dataServiceVersion: dataServiceVersion,
-            handler: handler
-        });
-
-        return rwContext;
-    };
-
-    var fixRequestHeader = function (request, name, value) {
-        /// <summary>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.</summary>
-        /// <param name="request">Request object on which the header will be set.</param>
-        /// <param name="name" type="String">Header name.</param>
-        /// <param name="value" type="String">Header value.</param>
-        if (!request) {
-            return;
-        }
-
-        var headers = request.headers;
-        if (!headers[name]) {
-            headers[name] = value;
-        }
-    };
-
-    var fixDataServiceVersionHeader = function (request, version) {
-        /// <summary>Sets the DataServiceVersion header of the request if its value is not yet defined or of a lower version.</summary>
-        /// <param name="request">Request object on which the header will be set.</param>
-        /// <param name="version" type="String">Version value.</param>
-        /// <remarks>
-        /// If the request has already a version value higher than the one supplied the this function does nothing.
-        /// </remarks>
-
-        if (request) {
-            var headers = request.headers;
-            var dsv = headers["DataServiceVersion"];
-            headers["DataServiceVersion"] = dsv ? maxVersion(dsv, version) : version;
-        }
-    };
-
-    var getRequestOrResponseHeader = function (requestOrResponse, name) {
-        /// <summary>Gets the value of a request or response header.</summary>
-        /// <param name="requestOrResponse">Object representing a request or a response.</param>
-        /// <param name="name" type="String">Name of the header to retrieve.</param>
-        /// <returns type="String">String value of the header; undefined if the header cannot be found.</returns>
-
-        var headers = requestOrResponse.headers;
-        return (headers && headers[name]) || undefined;
-    };
-
-    var getContentType = function (requestOrResponse) {
-        /// <summary>Gets the value of the Content-Type header from a request or response.</summary>
-        /// <param name="requestOrResponse">Object representing a request or a response.</param>
-        /// <returns type="Object">Object with 'mediaType' and a 'properties' dictionary; null in case that the header is not found or doesn't have a value.</returns>
-
-        return contentType(getRequestOrResponseHeader(requestOrResponse, "Content-Type"));
-    };
-
-    var versionRE = /^\s?(\d+\.\d+);?.*$/;
-    var getDataServiceVersion = function (requestOrResponse) {
-        /// <summary>Gets the value of the DataServiceVersion header from a request or response.</summary>
-        /// <param name="requestOrResponse">Object representing a request or a response.</param>
-        /// <returns type="String">Data service version; undefined if the header cannot be found.</returns>
-
-        var value = getRequestOrResponseHeader(requestOrResponse, "DataServiceVersion");
-        if (value) {
-            var matches = versionRE.exec(value);
-            if (matches && matches.length) {
-                return matches[1];
-            }
-        }
-
-        // Fall through and return undefined.
-    };
-
-    var handlerAccepts = function (handler, cType) {
-        /// <summary>Checks that a handler can process a particular mime type.</summary>
-        /// <param name="handler">Handler object that is processing a resquest or response.</param>
-        /// <param name="cType">Object with 'mediaType' and a 'properties' dictionary.</param>
-        /// <returns type="Boolean">True if the handler can process the mime type; false otherwise.</returns>
-
-        // 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.
-        return handler.accept.indexOf(cType.mediaType) >= 0;
-    };
-
-    var handlerRead = function (handler, parseCallback, response, context) {
-        /// <summary>Invokes the parser associated with a handler for reading the payload of a HTTP response.</summary>
-        /// <param name="handler">Handler object that is processing the response.</param>
-        /// <param name="parseCallback" type="Function">Parser function that will process the response payload.</param>
-        /// <param name="response">HTTP response whose payload is going to be processed.</param>
-        /// <param name="context">Object used as the context for processing the response.</param>
-        /// <returns type="Boolean">True if the handler processed the response payload and the response.data property was set; false otherwise.</returns>
-
-        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;
-    };
-
-    var handlerWrite = function (handler, serializeCallback, request, context) {
-        /// <summary>Invokes the serializer associated with a handler for generating the payload of a HTTP request.</summary>
-        /// <param name="handler">Handler object that is processing the request.</param>
-        /// <param name="serializeCallback" type="Function">Serializer function that will generate the request payload.</param>
-        /// <param name="response">HTTP request whose payload is going to be generated.</param>
-        /// <param name="context">Object used as the context for serializing the request.</param>
-        /// <returns type="Boolean">True if the handler serialized the request payload and the request.body property was set; false otherwise.</returns>
-        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 || "1.0");
-
-                fixRequestHeader(request, "Content-Type", contentTypeToString(writeContext.contentType));
-                fixRequestHeader(request, "MaxDataServiceVersion", handler.maxDataServiceVersion);
-                return true;
-            }
-        }
-
-        return false;
-    };
-
-    var handler = function (parseCallback, serializeCallback, accept, maxDataServiceVersion) {
-        /// <summary>Creates a handler object for processing HTTP requests and responses.</summary>
-        /// <param name="parseCallback" type="Function">Parser function that will process the response payload.</param>
-        /// <param name="serializeCallback" type="Function">Serializer function that will generate the request payload.</param>
-        /// <param name="accept" type="String">String containing a comma separated list of the mime types that this handler can work with.</param>
-        /// <param name="maxDataServiceVersion" type="String">String indicating the highest version of the protocol that this handler can work with.</param>
-        /// <returns type="Object">Handler object.</returns>
-
-        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);
-            }
-        };
-    };
-
-    var textParse = function (handler, body /*, context */) {
-        return body;
-    };
-
-    var textSerialize = function (handler, data /*, context */) {
-        if (assigned(data)) {
-            return data.toString();
-        } else {
-            return undefined;
-        }
-    };
-
-    odata.textHandler = handler(textParse, textSerialize, "text/plain", MAX_DATA_SERVICE_VERSION);
-
-
-    var gmlOpenGis = http + "www.opengis.net";           // http://www.opengis.net
-    var gmlXmlNs = gmlOpenGis + "/gml";                 // http://www.opengis.net/gml
-    var gmlSrsPrefix = gmlOpenGis + "/def/crs/EPSG/0/"; // http://www.opengis.net/def/crs/EPSG/0/
-
-    var gmlPrefix = "gml";
-
-    var gmlCreateGeoJSONOBject = function (type, member, data) {
-        /// <summary>Creates a GeoJSON object with the specified type, member and value.</summary>
-        /// <param name="type" type="String">GeoJSON object type.</param>
-        /// <param name="member" type="String">Name for the data member in the GeoJSON object.</param>
-        /// <param name="data">Data to be contained by the GeoJSON object.</param>
-        /// <returns type="Object">GeoJSON object.</returns>
-
-        var result = { type: type };
-        result[member] = data;
-        return result;
-    };
-
-    var gmlSwapLatLong = function (coordinates) {
-        /// <summary>Swaps the longitude and latitude in the coordinates array.</summary>
-        /// <param name="coordinates" type="Array">Array of doubles descrbing a set of coordinates.</param>
-        /// <returns type="Array">Array of doubles with the latitude and longitude components swapped.</returns>
-
-        if (isArray(coordinates) && coordinates.length >= 2) {
-            var tmp = coordinates[0];
-            coordinates[0] = coordinates[1];
-            coordinates[1] = tmp;
-        }
-        return coordinates;
-    };
-
-    var gmlReadODataMultiItem = function (domElement, type, member, members, valueReader, isGeography) {
-        /// <summary>
-        ///    Reads a GML DOM element that represents a composite structure like a multi-point or a
-        ///    multi-geometry returnig its GeoJSON representation.
-        /// </summary>
-        /// <param name="domElement">GML DOM element.</param>
-        /// <param name="type" type="String">GeoJSON object type.</param>
-        /// <param name="member" type="String">Name for the child element representing a single item in the composite structure.</param>
-        /// <param name="members" type="String">Name for the child element representing a collection of items in the composite structure.</param>
-        /// <param name="valueReader" type="Function">Callback function invoked to get the coordinates of each item in the comoposite structure.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">GeoJSON object.</returns>
-
-        var coordinates = gmlReadODataMultiItemValue(domElement, member, members, valueReader, isGeography);
-        return gmlCreateGeoJSONOBject(type, "coordinates", coordinates);
-    };
-
-    var gmlReadODataMultiItemValue = function (domElement, member, members, valueReader, isGeography) {
-        /// <summary>
-        ///    Reads the value of a GML DOM element that represents a composite structure like a multi-point or a
-        ///    multi-geometry returnig its items.
-        /// </summary>
-        /// <param name="domElement">GML DOM element.</param>
-        /// <param name="type" type="String">GeoJSON object type.</param>
-        /// <param name="member" type="String">Name for the child element representing a single item in the composite structure.</param>
-        /// <param name="members" type="String">Name for the child element representing a collection of items in the composite structure.</param>
-        /// <param name="valueReader" type="Function">Callback function invoked to get the transformed value of each item in the comoposite structure.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array containing the transformed value of each item in the multi-item.</returns>
-
-        var items = [];
-
-        xmlChildElements(domElement, function (child) {
-            if (xmlNamespaceURI(child) !== gmlXmlNs) {
-                return;
-            }
-
-            var localName = xmlLocalName(child);
-
-            if (localName === member) {
-                var valueElement = xmlFirstChildElement(child, gmlXmlNs);
-                if (valueElement) {
-                    var value = valueReader(valueElement, isGeography);
-                    if (value) {
-                        items.push(value);
-                    }
-                }
-                return;
-            }
-
-            if (localName === members) {
-                xmlChildElements(child, function (valueElement) {
-                    if (xmlNamespaceURI(valueElement) !== gmlXmlNs) {
-                        return;
-                    }
-
-                    var value = valueReader(valueElement, isGeography);
-                    if (value) {
-                        items.push(value);
-                    }
-                });
-            }
-        });
-        return items;
-    };
-
-    var gmlReadODataCollection = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a multi-geometry returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">MultiGeometry object in GeoJSON format.</returns>
-
-        var geometries = gmlReadODataMultiItemValue(domElement, "geometryMember", "geometryMembers", gmlReadODataSpatialValue, isGeography);
-        return gmlCreateGeoJSONOBject(GEOJSON_GEOMETRYCOLLECTION, "geometries", geometries);
-    };
-
-    var gmlReadODataLineString = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a line string returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">LineString object in GeoJSON format.</returns>
-
-        return gmlCreateGeoJSONOBject(GEOJSON_LINESTRING, "coordinates", gmlReadODataLineValue(domElement, isGeography));
-    };
-
-    var gmlReadODataMultiLineString = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a multi-line string returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">MultiLineString object in GeoJSON format.</returns>
-
-        return gmlReadODataMultiItem(domElement, GEOJSON_MULTILINESTRING, "curveMember", "curveMembers", gmlReadODataLineValue, isGeography);
-    };
-
-    var gmlReadODataMultiPoint = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a multi-point returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">MultiPoint object in GeoJSON format.</returns>
-
-        return gmlReadODataMultiItem(domElement, GEOJSON_MULTIPOINT, "pointMember", "pointMembers", gmlReadODataPointValue, isGeography);
-    };
-
-    var gmlReadODataMultiPolygon = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a multi-polygon returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">MultiPolygon object in GeoJSON format.</returns>
-
-        return gmlReadODataMultiItem(domElement, GEOJSON_MULTIPOLYGON, "surfaceMember", "surfaceMembers", gmlReadODataPolygonValue, isGeography);
-    };
-
-    var gmlReadODataPoint = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a point returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">Point object in GeoJSON format.</returns>
-
-        return gmlCreateGeoJSONOBject(GEOJSON_POINT, "coordinates", gmlReadODataPointValue(domElement, isGeography));
-    };
-
-    var gmlReadODataPolygon = function (domElement, isGeography) {
-        /// <summary>Reads a GML DOM element representing a polygon returning its GeoJSON representation.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Object">Polygon object in GeoJSON format.</returns>
-
-        return gmlCreateGeoJSONOBject(GEOJSON_POLYGON, "coordinates", gmlReadODataPolygonValue(domElement, isGeography));
-    };
-
-    var gmlReadODataLineValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element representing a line returning its set of coordinates.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array containing an array of doubles for each coordinate of the line.</returns>
-
-        var coordinates = [];
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-
-            if (nsURI !== gmlXmlNs) {
-                return;
-            }
-
-            var localName = xmlLocalName(child);
-
-            if (localName === "posList") {
-                coordinates = gmlReadODataPosListValue(child, isGeography);
-                return;
-            }
-            if (localName === "pointProperty") {
-                coordinates.push(gmlReadODataPointWrapperValue(child, isGeography));
-                return;
-            }
-            if (localName === "pos") {
-                coordinates.push(gmlReadODataPosValue(child, isGeography));
-                return;
-            }
-        });
-
-        return coordinates;
-    };
-
-    var gmlReadODataPointValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element representing a point returning its coordinates.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array of doubles containing the point coordinates.</returns>
-
-        var pos = xmlFirstChildElement(domElement, gmlXmlNs, "pos");
-        return pos ? gmlReadODataPosValue(pos, isGeography) : [];
-    };
-
-    var gmlReadODataPointWrapperValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element wrapping an element representing a point returning its coordinates.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array of doubles containing the point coordinates.</returns>
-
-        var point = xmlFirstChildElement(domElement, gmlXmlNs, "Point");
-        return point ? gmlReadODataPointValue(point, isGeography) : [];
-    };
-
-    var gmlReadODataPolygonValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element representing a polygon returning its set of coordinates.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array containing an array of array of doubles for each ring of the polygon.</returns>
-
-        var coordinates = [];
-        var exteriorFound = false;
-        xmlChildElements(domElement, function (child) {
-            if (xmlNamespaceURI(child) !== gmlXmlNs) {
-                return;
-            }
-
-            // Only the exterior and the interior rings are interesting
-            var localName = xmlLocalName(child);
-            if (localName === "exterior") {
-                exteriorFound = true;
-                coordinates.unshift(gmlReadODataPolygonRingValue(child, isGeography));
-                return;
-            }
-            if (localName === "interior") {
-                coordinates.push(gmlReadODataPolygonRingValue(child, isGeography));
-                return;
-            }
-        });
-
-        if (!exteriorFound && coordinates.length > 0) {
-            // Push an empty exterior ring.
-            coordinates.unshift([[]]);
-        }
-
-        return coordinates;
-    };
-
-    var gmlReadODataPolygonRingValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element representing a linear ring in a GML Polygon element.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array containing an array of doubles for each coordinate of the linear ring.</returns>
-
-        var value = [];
-        xmlChildElements(domElement, function (child) {
-            if (xmlNamespaceURI(child) !== gmlXmlNs || xmlLocalName(child) !== "LinearRing") {
-                return;
-            }
-            value = gmlReadODataLineValue(child, isGeography);
-        });
-        return value;
-    };
-
-    var gmlReadODataPosListValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element representing a list of positions retruning its set of coordinates.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        ///
-        ///    The positions described by the list are assumed to be 2D, so 
-        ///    an exception will be thrown if the list has an odd number elements.
-        /// </remarks>
-        /// <returns type="Array">Array containing an array of doubles for each coordinate in the list.</returns>
-
-        var coordinates = gmlReadODataPosValue(domElement, false);
-        var len = coordinates.length;
-
-        if (len % 2 !== 0) {
-            throw { message: "GML posList element has an uneven number of numeric values" };
-        }
-
-        var value = [];
-        for (var i = 0; i < len; i += 2) {
-            var pos = coordinates.slice(i, i + 2);
-            value.push(isGeography ? gmlSwapLatLong(pos) : pos);
-        }
-        return value;
-    };
-
-    var gmlReadODataPosValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML element describing a position or a set of coordinates in an OData spatial property value.</summary>
-        /// <param name="property">DOM element for the GML element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns type="Array">Array of doubles containing the coordinates.</returns>
-
-        var value = [];
-        var delims = " \t\r\n";
-        var text = xmlInnerText(domElement);
-
-        if (text) {
-            var len = text.length;
-            var start = 0;
-            var end = 0;
-
-            while (end <= len) {
-                if (delims.indexOf(text.charAt(end)) !== -1) {
-                    var coord = text.substring(start, end);
-                    if (coord) {
-                        value.push(parseFloat(coord));
-                    }
-                    start = end + 1;
-                }
-                end++;
-            }
-        }
-
-        return isGeography ? gmlSwapLatLong(value) : value;
-    };
-
-    var gmlReadODataSpatialValue = function (domElement, isGeography) {
-        /// <summary>Reads the value of a GML DOM element a spatial value in an OData XML document.</summary>
-        /// <param name="domElement">DOM element.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each position coordinates in the resulting GeoJSON object.
-        /// </remarks>
-        /// <returns type="Array">Array containing an array of doubles for each coordinate of the polygon.</returns>
-
-        var localName = xmlLocalName(domElement);
-        var reader;
-
-        switch (localName) {
-            case "Point":
-                reader = gmlReadODataPoint;
-                break;
-            case "Polygon":
-                reader = gmlReadODataPolygon;
-                break;
-            case "LineString":
-                reader = gmlReadODataLineString;
-                break;
-            case "MultiPoint":
-                reader = gmlReadODataMultiPoint;
-                break;
-            case "MultiCurve":
-                reader = gmlReadODataMultiLineString;
-                break;
-            case "MultiSurface":
-                reader = gmlReadODataMultiPolygon;
-                break;
-            case "MultiGeometry":
-                reader = gmlReadODataCollection;
-                break;
-            default:
-                throw { message: "Unsupported element: " + localName, element: domElement };
-        }
-
-        var value = reader(domElement, isGeography);
-        // Read the CRS
-        // WCF Data Services qualifies the srsName attribute withing the GML namespace; however
-        // other end points might no do this as per the standard.
-
-        var srsName = xmlAttributeValue(domElement, "srsName", gmlXmlNs) ||
-                      xmlAttributeValue(domElement, "srsName");
-
-        if (srsName) {
-            if (srsName.indexOf(gmlSrsPrefix) !== 0) {
-                throw { message: "Unsupported srs name: " + srsName, element: domElement };
-            }
-
-            var crsId = srsName.substring(gmlSrsPrefix.length);
-            if (crsId) {
-                value.crs = {
-                    type: "name",
-                    properties: {
-                        name: "EPSG:" + crsId
-                    }
-                };
-            }
-        }
-        return value;
-    };
-
-    var gmlNewODataSpatialValue = function (dom, value, type, isGeography) {
-        /// <summary>Creates a new GML DOM element for the value of an OData spatial property or GeoJSON object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">Spatial property value in GeoJSON format.</param>
-        /// <param name="type" type="String">String indicating the GeoJSON type of the value to serialize.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the spatial value. </returns>
-
-        var gmlWriter;
-
-        switch (type) {
-            case GEOJSON_POINT:
-                gmlWriter = gmlNewODataPoint;
-                break;
-            case GEOJSON_LINESTRING:
-                gmlWriter = gmlNewODataLineString;
-                break;
-            case GEOJSON_POLYGON:
-                gmlWriter = gmlNewODataPolygon;
-                break;
-            case GEOJSON_MULTIPOINT:
-                gmlWriter = gmlNewODataMultiPoint;
-                break;
-            case GEOJSON_MULTILINESTRING:
-                gmlWriter = gmlNewODataMultiLineString;
-                break;
-            case GEOJSON_MULTIPOLYGON:
-                gmlWriter = gmlNewODataMultiPolygon;
-                break;
-            case GEOJSON_GEOMETRYCOLLECTION:
-                gmlWriter = gmlNewODataGeometryCollection;
-                break;
-            default:
-                return null;
-        }
-
-        var gml = gmlWriter(dom, value, isGeography);
-
-        // Set the srsName attribute if applicable.
-        var crs = value.crs;
-        if (crs) {
-            if (crs.type === "name") {
-                var properties = crs.properties;
-                var name = properties && properties.name;
-                if (name && name.indexOf("ESPG:") === 0 && name.length > 5) {
-                    var crsId = name.substring(5);
-                    var srsName = xmlNewAttribute(dom, null, "srsName", gmlPrefix + crsId);
-                    xmlAppendChild(gml, srsName);
-                }
-            }
-        }
-
-        return gml;
-    };
-
-    var gmlNewODataElement = function (dom, name, children) {
-        /// <summary>Creates a new DOM element in the GML namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the GML element to create.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <returns>New DOM element in the GML namespace.</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 as a child of the new DOM Element.
-        /// </remarks>
-
-        return xmlNewElement(dom, gmlXmlNs, xmlQualifiedName(gmlPrefix, name), children);
-    };
-
-    var gmlNewODataPosElement = function (dom, coordinates, isGeography) {
-        /// <summary>Creates a new GML pos DOM element.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="coordinates" type="Array">Array of doubles describing the coordinates of the pos element.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the coordinates use a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first coordinate is the Longitude and
-        ///    will be serialized as the second component of the <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New pos DOM element in the GML namespace.</returns>
-
-        var posValue = isArray(coordinates) ? coordinates : [];
-
-        // If using a geographic reference system, then the first coordinate is the longitude and it has to
-        // swapped with the latitude.
-        posValue = isGeography ? gmlSwapLatLong(posValue) : posValue;
-
-        return gmlNewODataElement(dom, "pos", posValue.join(" "));
-    };
-
-    var gmlNewODataLineElement = function (dom, name, coordinates, isGeography) {
-        /// <summary>Creates a new GML DOM element representing a line.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Name of the element to create.</param>
-        /// <param name="coordinates" type="Array">Array of array of doubles describing the coordinates of the line element.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the coordinates use a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace.</returns>
-
-        var element = gmlNewODataElement(dom, name);
-        if (isArray(coordinates)) {
-            var i, len;
-            for (i = 0, len = coordinates.length; i < len; i++) {
-                xmlAppendChild(element, gmlNewODataPosElement(dom, coordinates[i], isGeography));
-            }
-
-            if (len === 0) {
-                xmlAppendChild(element, gmlNewODataElement(dom, "posList"));
-            }
-        }
-        return element;
-    };
-
-    var gmlNewODataPointElement = function (dom, coordinates, isGeography) {
-        /// <summary>Creates a new GML Point DOM element.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON Point object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON Point.</returns>
-
-        return gmlNewODataElement(dom, "Point", gmlNewODataPosElement(dom, coordinates, isGeography));
-    };
-
-    var gmlNewODataLineStringElement = function (dom, coordinates, isGeography) {
-        /// <summary>Creates a new GML LineString DOM element.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="coordinates" type="Array">Array of array of doubles describing the coordinates of the line element.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON LineString.</returns>
-
-        return gmlNewODataLineElement(dom, "LineString", coordinates, isGeography);
-    };
-
-    var gmlNewODataPolygonRingElement = function (dom, name, coordinates, isGeography) {
-        /// <summary>Creates a new GML DOM element representing a polygon ring.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Name of the element to create.</param>
-        /// <param name="coordinates" type="Array">Array of array of doubles describing the coordinates of the polygon ring.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the coordinates use a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace.</returns>
-
-        var ringElement = gmlNewODataElement(dom, name);
-        if (isArray(coordinates) && coordinates.length > 0) {
-            var linearRing = gmlNewODataLineElement(dom, "LinearRing", coordinates, isGeography);
-            xmlAppendChild(ringElement, linearRing);
-        }
-        return ringElement;
-    };
-
-    var gmlNewODataPolygonElement = function (dom, coordinates, isGeography) {
-        /// <summary>Creates a new GML Polygon DOM element for a GeoJSON Polygon object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="coordinates" type="Array">Array of array of array of doubles describing the coordinates of the polygon.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace.</returns>
-
-        var len = coordinates && coordinates.length;
-        var element = gmlNewODataElement(dom, "Polygon");
-
-        if (isArray(coordinates) && len > 0) {
-            xmlAppendChild(element, gmlNewODataPolygonRingElement(dom, "exterior", coordinates[0], isGeography));
-
-            var i;
-            for (i = 1; i < len; i++) {
-                xmlAppendChild(element, gmlNewODataPolygonRingElement(dom, "interior", coordinates[i], isGeography));
-            }
-        }
-        return element;
-    };
-
-    var gmlNewODataPoint = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML Point DOM element for a GeoJSON Point object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON Point object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON Point.</returns>
-
-        return gmlNewODataPointElement(dom, value.coordinates, isGeography);
-    };
-
-    var gmlNewODataLineString = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML LineString DOM element for a GeoJSON LineString object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON LineString object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON LineString.</returns>
-
-        return gmlNewODataLineStringElement(dom, value.coordinates, isGeography);
-    };
-
-    var gmlNewODataPolygon = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML Polygon DOM element for a GeoJSON Polygon object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON Polygon object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON Polygon.</returns>
-
-        return gmlNewODataPolygonElement(dom, value.coordinates, isGeography);
-    };
-
-    var gmlNewODataMultiItem = function (dom, name, members, items, itemWriter, isGeography) {
-        /// <summary>Creates a new GML DOM element for a composite structure like a multi-point or a multi-geometry.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Name of the element to create.</param>
-        /// <param name="items" type="Array">Array of items in the composite structure.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the multi-item uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each of the items is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace.</returns>
-
-        var len = items && items.length;
-        var element = gmlNewODataElement(dom, name);
-
-        if (isArray(items) && len > 0) {
-            var membersElement = gmlNewODataElement(dom, members);
-            var i;
-            for (i = 0; i < len; i++) {
-                xmlAppendChild(membersElement, itemWriter(dom, items[i], isGeography));
-            }
-            xmlAppendChild(element, membersElement);
-        }
-        return element;
-    };
-
-    var gmlNewODataMultiPoint = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML MultiPoint DOM element for a GeoJSON MultiPoint object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON MultiPoint object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON MultiPoint.</returns>
-
-        return gmlNewODataMultiItem(dom, "MultiPoint", "pointMembers", value.coordinates, gmlNewODataPointElement, isGeography);
-    };
-
-    var gmlNewODataMultiLineString = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML MultiCurve DOM element for a GeoJSON MultiLineString object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON MultiLineString object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON MultiLineString.</returns>
-
-        return gmlNewODataMultiItem(dom, "MultiCurve", "curveMembers", value.coordinates, gmlNewODataLineStringElement, isGeography);
-    };
-
-    var gmlNewODataMultiPolygon = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML MultiSurface DOM element for a GeoJSON MultiPolygon object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON MultiPolygon object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON MultiPolygon.</returns>
-
-        return gmlNewODataMultiItem(dom, "MultiSurface", "surfaceMembers", value.coordinates, gmlNewODataPolygonElement, isGeography);
-    };
-
-    var gmlNewODataGeometryCollectionItem = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML element for an item in a geometry collection object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="item" type="Object">GeoJSON object in the geometry collection.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace.</returns>
-
-        return gmlNewODataSpatialValue(dom, value, value.type, isGeography);
-    };
-
-    var gmlNewODataGeometryCollection = function (dom, value, isGeography) {
-        /// <summary>Creates a new GML MultiGeometry DOM element for a GeoJSON GeometryCollection object.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="value" type="Object">GeoJSON GeometryCollection object.</param>
-        /// <param name="isGeography" type="Boolean">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in the GeoJSON value is the Longitude and
-        ///    will be serialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the GeoJSON GeometryCollection.</returns>
-
-        return gmlNewODataMultiItem(dom, "MultiGeometry", "geometryMembers", value.geometries, gmlNewODataGeometryCollectionItem, isGeography);
-    };
-
-
-
-    var xmlMediaType = "application/xml";
-
-    var ado = http + "schemas.microsoft.com/ado/";      // http://schemas.microsoft.com/ado/
-    var adoDs = ado + "2007/08/dataservices";           // http://schemas.microsoft.com/ado/2007/08/dataservices
-
-    var edmxNs = ado + "2007/06/edmx";                  // http://schemas.microsoft.com/ado/2007/06/edmx
-    var edmNs1 = ado + "2006/04/edm";                   // http://schemas.microsoft.com/ado/2006/04/edm
-    var edmNs1_1 = ado + "2007/05/edm";                 // http://schemas.microsoft.com/ado/2007/05/edm
-    var edmNs1_2 = ado + "2008/01/edm";                 // http://schemas.microsoft.com/ado/2008/01/edm
-
-    // There are two valid namespaces for Edm 2.0
-    var edmNs2a = ado + "2008/09/edm";                  // http://schemas.microsoft.com/ado/2008/09/edm
-    var edmNs2b = ado + "2009/08/edm";                  // http://schemas.microsoft.com/ado/2009/08/edm
-
-    var edmNs3 = ado + "2009/11/edm";                   // http://schemas.microsoft.com/ado/2009/11/edm
-
-    var odataXmlNs = adoDs;                             // http://schemas.microsoft.com/ado/2007/08/dataservices
-    var odataMetaXmlNs = adoDs + "/metadata";           // http://schemas.microsoft.com/ado/2007/08/dataservices/metadata
-    var odataRelatedPrefix = adoDs + "/related/";       // http://schemas.microsoft.com/ado/2007/08/dataservices/related
-    var odataScheme = adoDs + "/scheme";                // http://schemas.microsoft.com/ado/2007/08/dataservices/scheme
-
-    var odataPrefix = "d";
-    var odataMetaPrefix = "m";
-
-    var createAttributeExtension = function (domNode, useNamespaceURI) {
-        /// <summary>Creates an extension object for the specified attribute.</summary>
-        /// <param name="domNode">DOM node for the attribute.</param>
-        /// <param name="useNamespaceURI" type="Boolean">Flag indicating if the namespaceURI property should be added to the extension object instead of the namespace property.</param>
-        /// <remarks>
-        ///    The useNamespaceURI flag is used to prevent a breaking change from older versions of datajs in which extension
-        ///    objects created for Atom extension attributes have the namespaceURI property instead of the namespace one.
-        ///    
-        ///    This flag and the namespaceURI property should be deprecated in future major versions of the library.
-        /// </remarks>
-        /// <returns type="Object">The new extension object.</returns>
-
-        var extension = { name: xmlLocalName(domNode), value: domNode.value };
-        extension[useNamespaceURI ? "namespaceURI" : "namespace"] = xmlNamespaceURI(domNode);
-
-        return extension;
-    };
-
-    var createElementExtension = function (domNode, useNamespaceURI) {
-        /// <summary>Creates an extension object for the specified element.</summary>
-        /// <param name="domNode">DOM node for the element.</param>
-        /// <param name="useNamespaceURI" type="Boolean">Flag indicating if the namespaceURI property should be added to the extension object instead of the namespace property.</param>
-        /// <remarks>
-        ///    The useNamespaceURI flag is used to prevent a breaking change from older versions of datajs in which extension
-        ///    objects created for Atom extension attributes have the namespaceURI property instead of the namespace one.
-        ///    
-        ///    This flag and the namespaceURI property should be deprecated in future major versions of the library.
-        /// </remarks>
-        /// <returns type="Object">The new extension object.</returns>
-
-
-        var attributeExtensions = [];
-        var childrenExtensions = [];
-
-        var i, len;
-        var attributes = domNode.attributes;
-        for (i = 0, len = attributes.length; i < len; i++) {
-            var attr = attributes[i];
-            if (xmlNamespaceURI(attr) !== xmlnsNS) {
-                attributeExtensions.push(createAttributeExtension(attr, useNamespaceURI));
-            }
-        }
-
-        var child = domNode.firstChild;
-        while (child != null) {
-            if (child.nodeType === 1) {
-                childrenExtensions.push(createElementExtension(child, useNamespaceURI));
-            }
-            child = child.nextSibling;
-        }
-
-        var extension = {
-            name: xmlLocalName(domNode),
-            value: xmlInnerText(domNode),
-            attributes: attributeExtensions,
-            children: childrenExtensions
-        };
-
-        extension[useNamespaceURI ? "namespaceURI" : "namespace"] = xmlNamespaceURI(domNode);
-        return extension;
-    };
-
-    var isCollectionItemElement = function (domElement) {
-        /// <summary>Checks whether the domElement is a collection item.</summary>
-        /// <param name="domElement">DOM element possibliy represnting a collection item.</param>
-        /// <returns type="Boolean">True if the domeElement belongs to the OData metadata namespace and its local name is "element"; false otherwise.</returns>
-
-        return xmlNamespaceURI(domElement) === odataXmlNs && xmlLocalName(domElement) === "element";
-    };
-
-    var makePropertyMetadata = function (type, extensions) {
-        /// <summary>Creates an object containing property metadata.</summary>
-        /// <param type="String" name="type">Property type name.</param>
-        /// <param type="Array" name="extensions">Array of attribute extension objects.</param>
-        /// <returns type="Object">Property metadata object cotaining type and extensions fields.</returns>
-
-        return { type: type, extensions: extensions };
-    };
-
-    var odataInferTypeFromPropertyXmlDom = function (domElement) {
-        /// <summary>Infers type of a property based on its xml DOM tree.</summary>
-        /// <param name="domElement">DOM element for the property.</param>
-        /// <returns type="String">Inferred type name; null if the type cannot be determined.</returns>
-
-        if (xmlFirstChildElement(domElement, gmlXmlNs)) {
-            return EDM_GEOMETRY;
-        }
-
-        var firstChild = xmlFirstChildElement(domElement, odataXmlNs);
-        if (!firstChild) {
-            return EDM_STRING;
-        }
-
-        if (isCollectionItemElement(firstChild)) {
-            var sibling = xmlSiblingElement(firstChild, odataXmlNs);
-            if (sibling && isCollectionItemElement(sibling)) {
-                // More than one <element> tag have been found, it can be safely assumed that this is a collection property.
-                return "Collection()";
-            }
-        }
-
-        return null;
-    };
-
-    var xmlReadODataPropertyAttributes = function (domElement) {
-        /// <summary>Reads the attributes of a property DOM element in an OData XML document.</summary>
-        /// <param name="domElement">DOM element for the property.</param>
-        /// <returns type="Object">Object containing the property type, if it is null, and its attribute extensions.</returns>
-
-        var type = null;
-        var isNull = false;
-        var extensions = [];
-
-        xmlAttributes(domElement, function (attribute) {
-            var nsURI = xmlNamespaceURI(attribute);
-            var localName = xmlLocalName(attribute);
-            var value = xmlNodeValue(attribute);
-
-            if (nsURI === odataMetaXmlNs) {
-                if (localName === "null") {
-                    isNull = (value.toLowerCase() === "true");
-                    return;
-                }
-
-                if (localName === "type") {
-                    type = value;
-                    return;
-                }
-            }
-
-            if (nsURI !== xmlNS && nsURI !== xmlnsNS) {
-                extensions.push(createAttributeExtension(attribute, true));
-                return;
-            }
-        });
-
-        return { type: (!type && isNull ? EDM_STRING : type), isNull: isNull, extensions: extensions };
-    };
-
-    var xmlReadODataProperty = function (domElement) {
-        /// <summary>Reads a property DOM element in an OData XML document.</summary>
-        /// <param name="domElement">DOM element for the property.</param>
-        /// <returns type="Object">Object with name, value, and metadata for the property.</returns>
-
-        if (xmlNamespaceURI(domElement) !== odataXmlNs) {
-            // domElement is not a proprety element because it is not in the odata xml namespace.
-            return null;
-        }
-
-        var propertyName = xmlLocalName(domElement);
-        var propertyAttributes = xmlReadODataPropertyAttributes(domElement);
-
-        var propertyIsNull = propertyAttributes.isNull;
-        var propertyType = propertyAttributes.type;
-
-        var propertyMetadata = makePropertyMetadata(propertyType, propertyAttributes.extensions);
-        var propertyValue = propertyIsNull ? null : xmlReadODataPropertyValue(domElement, propertyType, propertyMetadata);
-
-        return { name: propertyName, value: propertyValue, metadata: propertyMetadata };
-    };
-
-    var xmlReadODataPropertyValue = function (domElement, propertyType, propertyMetadata) {
-        /// <summary>Reads the value of a property in an OData XML document.</summary>
-        /// <param name="domElement">DOM element for the property.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object">Object that will store metadata about the property.</param>
-        /// <returns>Property value.</returns>
-
-        if (!propertyType) {
-            propertyType = odataInferTypeFromPropertyXmlDom(domElement);
-            propertyMetadata.type = propertyType;
-        }
-
-        var isGeograhpyType = isGeographyEdmType(propertyType);
-        if (isGeograhpyType || isGeometryEdmType(propertyType)) {
-            return xmlReadODataSpatialPropertyValue(domElement, propertyType, isGeograhpyType);
-        }
-
-        if (isPrimitiveEdmType(propertyType)) {
-            return xmlReadODataEdmPropertyValue(domElement, propertyType);
-        }
-
-        if (isCollectionType(propertyType)) {
-            return xmlReadODataCollectionPropertyValue(domElement, propertyType, propertyMetadata);
-        }
-
-        return xmlReadODataComplexPropertyValue(domElement, propertyType, propertyMetadata);
-    };
-
-    var xmlReadODataSpatialPropertyValue = function (domElement, propertyType, isGeography) {
-        /// <summary>Reads the value of an spatial property in an OData XML document.</summary>
-        /// <param name="property">DOM element for the spatial property.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="isGeography" type="Boolean" Optional="True">Flag indicating if the value uses a geographic reference system or not.<param>
-        /// <remarks>
-        ///    When using a geographic reference system, the first component of all the coordinates in each <pos> element in the GML DOM tree is the Latitude and
-        ///    will be deserialized as the second component of each <pos> element in the GML DOM tree.
-        /// </remarks>
-        /// <returns>Spatial property value in GeoJSON format.</returns>
-
-        var gmlRoot = xmlFirstChildElement(domElement, gmlXmlNs);
-
-        var value = gmlReadODataSpatialValue(gmlRoot, isGeography);
-        value.__metadata = { type: propertyType };
-        return value;
-    };
-
-    var xmlReadODataEdmPropertyValue = function (domNode, propertyType) {
-        /// <summary>Reads the value of an EDM property in an OData XML document.</summary>
-        /// <param name="donNode">DOM node for the EDM property.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <returns>EDM property value.</returns>
-
-        var propertyValue = xmlNodeValue(domNode) || "";
-
-        switch (propertyType) {
-            case EDM_BOOLEAN:
-                return parseBool(propertyValue);
-            case EDM_BINARY:
-            case EDM_DECIMAL:
-            case EDM_GUID:
-            case EDM_INT64:
-            case EDM_STRING:
-                return propertyValue;
-            case EDM_BYTE:
-            case EDM_INT16:
-            case EDM_INT32:
-            case EDM_SBYTE:
-                return parseInt10(propertyValue);
-            case EDM_DOUBLE:
-            case EDM_SINGLE:
-                return parseFloat(propertyValue);
-            case EDM_TIME:
-                return parseDuration(propertyValue);
-            case EDM_DATETIME:
-                return parseDateTime(propertyValue);
-            case EDM_DATETIMEOFFSET:
-                return parseDateTimeOffset(propertyValue);
-        }
-
-        return propertyValue;
-    };
-
-    var xmlReadODataComplexPropertyValue = function(domElement, propertyType, propertyMetadata) {
-        /// <summary>Reads the value of a complex type property in an OData XML document.</summary>
-        /// <param name="property">DOM element for the complex type property.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object">Object that will store metadata about the property.</param>
-        /// <returns type="Object">Complex type property value.</returns>
-
-        var propertyValue = { __metadata: { type: propertyType } };
-        xmlChildElements(domElement, function(child) {
-            var childProperty = xmlReadODataProperty(child);
-            var childPropertyName = childProperty.name;
-
-            propertyMetadata.properties = propertyMetadata.properties || {};
-            propertyMetadata.properties[childPropertyName] = childProperty.metadata;
-            propertyValue[childPropertyName] = childProperty.value;
-        });
-
-        return propertyValue;
-    };
-
-    var xmlReadODataCollectionPropertyValue = function (domElement, propertyType, propertyMetadata) {
-        /// <summary>Reads the value of a collection property in an OData XML document.</summary>
-        /// <param name="property">DOM element for the collection property.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object">Object that will store metadata about the property.</param>
-        /// <returns type="Object">Collection property value.</returns>
-
-        var items = [];
-        var itemsMetadata = propertyMetadata.elements = [];
-        var collectionType = getCollectionType(propertyType);
-
-        xmlChildElements(domElement, function (child) {
-            if (isCollectionItemElement(child)) {
-                var itemAttributes = xmlReadODataPropertyAttributes(child);
-                var itemExtensions = itemAttributes.extensions;
-                var itemType = itemAttributes.type || collectionType;
-                var itemMetadata = makePropertyMetadata(itemType, itemExtensions);
-
-                var item = xmlReadODataPropertyValue(child, itemType, itemMetadata);
-
-                items.push(item);
-                itemsMetadata.push(itemMetadata);
-            }
-        });
-
-        return { __metadata: { type: propertyType === "Collection()" ? null : propertyType }, results: items };
-    };
-
-    var readODataXmlDocument = function (xmlRoot, baseURI) {
-        /// <summary>Reads an OData link(s) producing an object model in return.</summary>
-        /// <param name="xmlRoot">Top-level element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the XML payload.</param>
-        /// <returns type="Object">The object model representing the specified element.</returns>
-
-        if (xmlNamespaceURI(xmlRoot) === odataXmlNs) {
-            baseURI = xmlBaseURI(xmlRoot, baseURI);
-            var localName = xmlLocalName(xmlRoot);
-
-            if (localName === "links") {
-                return readLinks(xmlRoot, baseURI);
-            }
-            if (localName === "uri") {
-                return readUri(xmlRoot, baseURI);
-            }
-        }
-        return undefined;
-    };
-
-    var readLinks = function (linksElement, baseURI) {
-        /// <summary>Deserializes an OData XML links element.</summary>
-        /// <param name="linksElement">XML links element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the XML payload.</param>
-        /// <returns type="Object">A new object representing the links collection.</returns>
-
-        var uris = [];
-
-        xmlChildElements(linksElement, function (child) {
-            if (xmlLocalName(child) === "uri" && xmlNamespaceURI(child) === odataXmlNs) {
-                uris.push(readUri(child, baseURI));
-            }
-        });
-
-        return { results: uris };
-    };
-
-    var readUri = function (uriElement, baseURI) {
-        /// <summary>Deserializes an OData XML uri element.</summary>
-        /// <param name="uriElement">XML uri element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the XML payload.</param>
-        /// <returns type="Object">A new object representing the uri.</returns>
-
-        var uri = xmlInnerText(uriElement) || "";
-        return { uri: normalizeURI(uri, baseURI) };
-    };
-
-    var xmlODataInferSpatialValueGeoJsonType = function (value, edmType) {
-        /// <summary>Infers the GeoJSON type from the spatial property value and the edm type name.</summary>
-        /// <param name="value" type="Object">Spatial property value in GeoJSON format.</param>
-        /// <param name="edmType" type="String" mayBeNull="true" optional="true">Spatial property edm type.<param>
-        /// <remarks>
-        ///   If the edmType parameter is null, undefined, "Edm.Geometry" or "Edm.Geography", then the function returns
-        ///   the GeoJSON type indicated by the value's type property.
-        ///
-        ///   If the edmType parameter is specified or is not one of the base spatial types, then it is used to
-        ///   determine the GeoJSON type and the value's type property is ignored.
-        /// </remarks>
-        /// <returns>New DOM element in the GML namespace for the spatial value. </returns>
-
-        if (edmType === EDM_GEOMETRY || edmType === EDM_GEOGRAPHY) {
-            return value && value.type;
-        }
-
-        if (edmType === EDM_GEOMETRY_POINT || edmType === EDM_GEOGRAPHY_POINT) {
-            return GEOJSON_POINT;
-        }
-
-        if (edmType === EDM_GEOMETRY_LINESTRING || edmType === EDM_GEOGRAPHY_LINESTRING) {
-            return GEOJSON_LINESTRING;
-        }
-
-        if (edmType === EDM_GEOMETRY_POLYGON || edmType === EDM_GEOGRAPHY_POLYGON) {
-            return GEOJSON_POLYGON;
-        }
-
-        if (edmType === EDM_GEOMETRY_COLLECTION || edmType === EDM_GEOGRAPHY_COLLECTION) {
-            return GEOJSON_GEOMETRYCOLLECTION;
-        }
-
-        if (edmType === EDM_GEOMETRY_MULTIPOLYGON || edmType === EDM_GEOGRAPHY_MULTIPOLYGON) {
-            return GEOJSON_MULTIPOLYGON;
-        }
-
-        if (edmType === EDM_GEOMETRY_MULTILINESTRING || edmType === EDM_GEOGRAPHY_MULTILINESTRING) {
-            return GEOJSON_MULTILINESTRING;
-        }
-
-        if (edmType === EDM_GEOMETRY_MULTIPOINT || edmType === EDM_GEOGRAPHY_MULTIPOINT) {
-            return GEOJSON_MULTIPOINT;
-        }
-
-        return null;
-    };
-
-    var xmlNewODataMetaElement = function (dom, name, children) {
-        /// <summary>Creates a new DOM element in the OData metadata namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the OData metadata element to create.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <returns>New DOM element in the OData metadata namespace.</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 as a child of the new DOM Element.
-        /// </remarks>
-
-        return xmlNewElement(dom, odataMetaXmlNs, xmlQualifiedName(odataMetaPrefix, name), children);
-    };
-
-    var xmlNewODataMetaAttribute = function (dom, name, value) {
-        /// <summary>Creates a new DOM attribute in the odata namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the OData attribute to create.</param>
-        /// <param name="value">Attribute value.</param>
-        /// <returns>New DOM attribute in the odata namespace.</returns>
-
-        return xmlNewAttribute(dom, odataMetaXmlNs, xmlQualifiedName(odataMetaPrefix, name), value);
-    };
-
-    var xmlNewODataElement = function (dom, name, children) {
-        /// <summary>Creates a new DOM element in the OData namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the OData element to create.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <returns>New DOM element in the OData namespace.</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 as a child of the new DOM Element.
-        /// </remarks>
-
-        return xmlNewElement(dom, odataXmlNs, xmlQualifiedName(odataPrefix, name), children);
-    };
-
-    var xmlNewODataPrimitiveValue = function (value, typeName) {
-        /// <summary>Returns the string representation of primitive value for an OData XML document.</summary>
-        /// <param name="value">Primivite value to format.</param>
-        /// <param name="typeName" type="String" optional="true">Type name of the primitive value.</param>
-        /// <returns type="String">Formatted primitive value.</returns>
-
-        if (typeName === EDM_DATETIME || typeName === EDM_DATETIMEOFFSET || isDate(value)) {
-            return formatDateTimeOffset(value);
-        }
-        if (typeName === EDM_TIME) {
-            return formatDuration(value);
-        }
-        return value.toString();
-    };
-
-    var xmlNewODataElementInfo = function (domElement, dataServiceVersion) {
-        /// <summary>Creates an object that represents a new DOM element for an OData XML document and the data service version it requires.</summary>
-        /// <param name="domElement">New DOM element for an OData XML document.</param>
-        /// <param name="dataServiceVersion" type="String">Required data service version by the new DOM element.</param>
-        /// <returns type="Object">Object containing new DOM element and its required data service version.</returns>
-
-        return { element: domElement, dsv: dataServiceVersion };
-    };
-
-    var xmlNewODataProperty = function (dom, name, typeName, children) {
-        /// <summary>Creates a new DOM element for an entry property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <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 as a child of the new DOM Element.
-        /// </remarks>
-        /// <returns>New DOM element in the OData namespace for the entry property.</returns>
-
-        var typeAttribute = typeName ? xmlNewODataMetaAttribute(dom, "type", typeName) : null;
-        var property = xmlNewODataElement(dom, name, typeAttribute);
-        return xmlAppendChildren(property, children);
-    };
-
-    var xmlNewODataEdmProperty = function (dom, name, value, typeName) {
-        /// <summary>Creates a new DOM element for an EDM property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="value">Property value.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the OData namespace for the EDM property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var propertyValue = xmlNewODataPrimitiveValue(value, typeName);
-        var property = xmlNewODataProperty(dom, name, typeName, propertyValue);
-        return xmlNewODataElementInfo(property, /*dataServiceVersion*/"1.0");
-    };
-
-    var xmlNewODataNullProperty = function (dom, name, typeName, model) {
-        /// <summary>Creates a new DOM element for a null property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <remarks>
-        ///     If no typeName is specified, then it will be assumed that this is a primitive type property.
-        /// </remarks>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the OData namespace for the null property and the 
-        ///     required data service version for this property.
-        /// </returns>
-
-        var nullAttribute = xmlNewODataMetaAttribute(dom, "null", "true");
-        var property = xmlNewODataProperty(dom, name, typeName, nullAttribute);
-        var dataServiceVersion = lookupComplexType(typeName, model) ? "2.0" : "1.0";
-
-        return xmlNewODataElementInfo(property, dataServiceVersion);
-    };
-
-    var xmlNewODataCollectionProperty = function (dom, name, value, typeName, collectionMetadata, collectionModel, model) {
-        /// <summary>Creates a new DOM element for a collection property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="value">Property value either as an array or an object representing a collection in the library's internal representation.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <param name="collectionMetadata" type="Object" optional="true">Object containing metadata about the collection property.</param>
-        /// <param name="collectionModel" type="Object" optional="true">Object describing the collection property in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the OData namespace for the collection property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var itemTypeName = getCollectionType(typeName);
-        var items = isArray(value) ? value : value.results;
-        var itemMetadata = typeName ? { type: itemTypeName} : {};
-        itemMetadata.properties = collectionMetadata.properties;
-
-        var xmlProperty = xmlNewODataProperty(dom, name, itemTypeName ? typeName : null);
-
-        var i, len;
-        for (i = 0, len = items.length; i < len; i++) {
-            var itemValue = items[i];
-            var item = xmlNewODataDataElement(dom, "element", itemValue, itemMetadata, collectionModel, model);
-
-            xmlAppendChild(xmlProperty, item.element);
-        }
-        return xmlNewODataElementInfo(xmlProperty, /*dataServiceVersion*/"3.0");
-    };
-
-    var xmlNewODataComplexProperty = function (dom, name, value, typeName, propertyMetadata, propertyModel, model) {
-        /// <summary>Creates a new DOM element for a complex type property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="value">Property value as an object in the library's internal representation.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object" optional="true">Object containing metadata about the complex type property.</param>
-        /// <param name="propertyModel" type="Object" optional="true">Object describing the complex type property in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the OData namespace for the complex type property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var xmlProperty = xmlNewODataProperty(dom, name, typeName);
-        var complexTypePropertiesMetadata = propertyMetadata.properties || {};
-        var complexTypeModel = lookupComplexType(typeName, model) || {};
-
-        var dataServiceVersion = "1.0";
-
-        for (var key in value) {
-            if (key !== "__metadata") {
-                var memberValue = value[key];
-                var memberModel = lookupProperty(complexTypeModel.property, key);
-                var memberMetadata = complexTypePropertiesMetadata[key] || {};
-                var member = xmlNewODataDataElement(dom, key, memberValue, memberMetadata, memberModel, model);
-
-                dataServiceVersion = maxVersion(dataServiceVersion, member.dsv);
-                xmlAppendChild(xmlProperty, member.element);
-            }
-        }
-        return xmlNewODataElementInfo(xmlProperty, dataServiceVersion);
-    };
-
-    var xmlNewODataSpatialProperty = function (dom, name, value, typeName, isGeography) {
-        /// <summary>Creates a new DOM element for an EDM spatial property in an OData XML document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="value" type="Object">GeoJSON object containing the property value.</param>
-        /// <param name="typeName" type="String" optional="true">Property type name.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the OData namespace for the EDM property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var geoJsonType = xmlODataInferSpatialValueGeoJsonType(value, typeName);
-
-        var gmlRoot = gmlNewODataSpatialValue(dom, value, geoJsonType, isGeography);
-        var xmlProperty = xmlNewODataProperty(dom, name, typeName, gmlRoot);
-
-        return xmlNewODataElementInfo(xmlProperty, "3.0");
-    };
-
-    var xmlNewODataDataElement = function (dom, name, value, dataItemMetadata, dataItemModel, model) {
-        /// <summary>Creates a new DOM element for a data item in an entry, complex property, or collection property.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Data item name.</param>
-        /// <param name="value" optional="true" mayBeNull="true">Value of the data item, if any.</param>
-        /// <param name="dataItemMetadata" type="Object" optional="true">Object containing metadata about the data item.</param>
-        /// <param name="dataItemModel" type="Object" optional="true">Object describing the data item in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the appropriate namespace for the data item and the
-        ///     required data service version for it.
-        /// </returns>
-
-        var typeName = dataItemTypeName(value, dataItemMetadata, dataItemModel);
-        if (isPrimitive(value)) {
-            return xmlNewODataEdmProperty(dom, name, value, typeName || EDM_STRING);
-        }
-
-        var isGeography = isGeographyEdmType(typeName);
-        if (isGeography || isGeometryEdmType(typeName)) {
-            return xmlNewODataSpatialProperty(dom, name, value, typeName, isGeography);
-        }
-
-        if (isCollection(value, typeName)) {
-            return xmlNewODataCollectionProperty(dom, name, value, typeName, dataItemMetadata, dataItemModel, model);
-        }
-
-        if (isNamedStream(value)) {
-            return null;
-        }
-
-        // This may be a navigation property.
-        var navPropKind = navigationPropertyKind(value, dataItemModel);
-        if (navPropKind !== null) {
-            return null;
-        }
-
-        if (value === null) {
-            return xmlNewODataNullProperty(dom, name, typeName);
-        }
-
-        return xmlNewODataComplexProperty(dom, name, value, typeName, dataItemMetadata, dataItemModel, model);
-    };
-
-    var odataNewLinkDocument = function (data) {
-        /// <summary>Writes the specified data into an OData XML document.</summary>
-        /// <param name="data">Data to write.</param>
-        /// <returns>The root of the DOM tree built.</returns>
-
-        if (data && isObject(data)) {
-            var dom = xmlDom();
-            return xmlAppendChild(dom, xmlNewODataElement(dom, "uri", data.uri));
-        }
-        // Allow for undefined to be returned.
-    };
-
-    var xmlParser = function (handler, text) {
-        /// <summary>Parses an OData XML document.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text" type="String">Document text.</param>
-        /// <returns>An object representation of the document; undefined if not applicable.</returns>
-
-        if (text) {
-            var doc = xmlParse(text);
-            var root = xmlFirstChildElement(doc);
-            if (root) {
-                return readODataXmlDocument(root);
-            }
-        }
-
-        // Allow for undefined to be returned.
-    };
-
-    var xmlSerializer = function (handler, data, context) {
-        /// <summary>Serializes an OData XML object into a document.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="data" type="Object">Representation of feed or entry.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>A text representation of the data object; undefined if not applicable.</returns>
-
-        var cType = context.contentType = context.contentType || contentType(xmlMediaType);
-        if (cType && cType.mediaType === xmlMediaType) {
-            return xmlSerialize(odataNewLinkDocument(data));
-        }
-        return undefined;
-    };
-
-    odata.xmlHandler = handler(xmlParser, xmlSerializer, xmlMediaType, MAX_DATA_SERVICE_VERSION);
-
-
-
-    var atomPrefix = "a";
-
-    var atomXmlNs = w3org + "2005/Atom";                    // http://www.w3.org/2005/Atom
-    var appXmlNs = w3org + "2007/app";                      // http://www.w3.org/2007/app
-
-    var odataEditMediaPrefix = adoDs + "/edit-media/";        // http://schemas.microsoft.com/ado/2007/08/dataservices/edit-media
-    var odataMediaResourcePrefix = adoDs + "/mediaresource/"; // http://schemas.microsoft.com/ado/2007/08/dataservices/mediaresource
-    var odataRelatedLinksPrefix = adoDs + "/relatedlinks/";   // http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks
-
-    var atomAcceptTypes = ["application/atom+xml", "application/atomsvc+xml", "application/xml"];
-    var atomMediaType = atomAcceptTypes[0];
-
-    // These are the namespaces that are not considered ATOM extension namespaces.
-    var nonExtensionNamepaces = [atomXmlNs, appXmlNs, xmlNS, xmlnsNS];
-
-    // These are entity property mapping paths that have well-known paths.
-    var knownCustomizationPaths = {
-        SyndicationAuthorEmail: "author/email",
-        SyndicationAuthorName: "author/name",
-        SyndicationAuthorUri: "author/uri",
-        SyndicationContributorEmail: "contributor/email",
-        SyndicationContributorName: "contributor/name",
-        SyndicationContributorUri: "contributor/uri",
-        SyndicationPublished: "published",
-        SyndicationRights: "rights",
-        SyndicationSummary: "summary",
-        SyndicationTitle: "title",
-        SyndicationUpdated: "updated"
-    };
-
-    var expandedFeedCustomizationPath = function (path) {
-        /// <summary>Returns an expanded customization path if it's well-known.</summary>
-        /// <param name="path" type="String">Path to expand.</param>
-        /// <returns type="String">Expanded path or just 'path' otherwise.</returns>
-
-        return knownCustomizationPaths[path] || path;
-    };
-
-    var isExtensionNs = function (nsURI) {
-        /// <summary>Checks whether the specified namespace is an extension namespace to ATOM.</summary>
-        /// <param type="String" name="nsURI">Namespace to check.</param>
-        /// <returns type="Boolean">true if nsURI is an extension namespace to ATOM; false otherwise.</returns>
-
-        return !(contains(nonExtensionNamepaces, nsURI));
-    };
-
-    var atomFeedCustomization = function (customizationModel, entityType, model, propertyName, suffix) {
-        /// <summary>Creates an object describing a feed customization that was delcared in an OData conceptual schema.</summary>
-        /// <param name="customizationModel" type="Object">Object describing the customization delcared in the conceptual schema.</param>
-        /// <param name="entityType" type="Object">Object describing the entity type that owns the customization in an OData conceputal schema.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="propertyName" type="String" optional="true">Name of the property to which this customization applies.</param>
-        /// <param name="suffix" type="String" optional="true">Suffix to feed customization properties in the conceptual schema.</param>
-        /// <returns type="Object">Object that describes an applicable feed customization.</returns>
-
-        suffix = suffix || "";
-        var targetPath = customizationModel["FC_TargetPath" + suffix];
-        if (!targetPath) {
-            return null;
-        }
-
-        var sourcePath = customizationModel["FC_SourcePath" + suffix];
-        var targetXmlPath = expandedFeedCustomizationPath(targetPath);
-
-        var propertyPath = propertyName ? propertyName + (sourcePath ? "/" + sourcePath : "") : sourcePath;
-        var propertyType = propertyPath && lookupPropertyType(model, entityType, propertyPath);
-        var nsURI = customizationModel["FC_NsUri" + suffix] || null;
-        var nsPrefix = customizationModel["FC_NsPrefix" + suffix] || null;
-        var keepinContent = customizationModel["FC_KeepInContent" + suffix] || "";
-
-        if (targetPath !== targetXmlPath) {
-            nsURI = atomXmlNs;
-            nsPrefix = atomPrefix;
-        }
-
-        return {
-            contentKind: customizationModel["FC_ContentKind" + suffix],
-            keepInContent: keepinContent.toLowerCase() === "true",
-            nsPrefix: nsPrefix,
-            nsURI: nsURI,
-            propertyPath: propertyPath,
-            propertyType: propertyType,
-            entryPath: targetXmlPath
-        };
-    };
-
-    var atomApplyAllFeedCustomizations = function (entityType, model, callback) {
-        /// <summary>Gets all the feed customizations that have to be applied to an entry as per the enity type declared in an OData conceptual schema.</summary>
-        /// <param name="entityType" type="Object">Object describing an entity type in a conceptual schema.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="callback" type="Function">Callback function to be invoked for each feed customization that needs to be applied.</param>
-
-        var customizations = [];
-        while (entityType) {
-            var sourcePath = entityType.FC_SourcePath;
-            var customization = atomFeedCustomization(entityType, entityType, model);
-            if (customization) {
-                callback(customization);
-            }
-
-            var properties = entityType.property || [];
-            var i, len;
-            for (i = 0, len = properties.length; i < len; i++) {
-                var property = properties[i];
-                var suffixCounter = 0;
-                var suffix = "";
-
-                while (customization = atomFeedCustomization(property, entityType, model, property.name, suffix)) {
-                    callback(customization);
-                    suffixCounter++;
-                    suffix = "_" + suffixCounter;
-                }
-            }
-            entityType = lookupEntityType(entityType.baseType, model);
-        }
-        return customizations;
-    };
-
-    var atomReadExtensionAttributes = function (domElement) {
-        /// <summary>Reads ATOM extension attributes (any attribute not in the Atom namespace) from a DOM element.</summary>
-        /// <param name="domElement">DOM element with zero or more extension attributes.</param>
-        /// <returns type="Array">An array of extension attribute representations.</returns>
-
-        var extensions = [];
-        xmlAttributes(domElement, function (attribute) {
-            var nsURI = xmlNamespaceURI(attribute);
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-        return extensions;
-    };
-
-    var atomReadExtensionElement = function (domElement) {
-        /// <summary>Reads an ATOM extension element (an element not in the ATOM namespaces).</summary>
-        /// <param name="domElement">DOM element not part of the atom namespace.</param>
-        /// <returns type="Object">Object representing the extension element.</returns>
-
-        return createElementExtension(domElement, /*addNamespaceURI*/true);
-    };
-
-    var atomReadDocument = function (domElement, baseURI, model) {
-        /// <summary>Reads an ATOM entry, feed or service document, producing an object model in return.</summary>
-        /// <param name="domElement">Top-level ATOM DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM document.</param>
-        /// <param name="model" type="Object">Object that describes the conceptual schema.</param>
-        /// <returns type="Object">The object model representing the specified element, undefined if the top-level element is not part of the ATOM specification.</returns>
-
-        var nsURI = xmlNamespaceURI(domElement);
-        var localName = xmlLocalName(domElement);
-
-        // Handle service documents.
-        if (nsURI === appXmlNs && localName === "service") {
-            return atomReadServiceDocument(domElement, baseURI);
-        }
-
-        // Handle feed and entry elements.
-        if (nsURI === atomXmlNs) {
-            if (localName === "feed") {
-                return atomReadFeed(domElement, baseURI, model);
-            }
-            if (localName === "entry") {
-                return atomReadEntry(domElement, baseURI, model);
-            }
-        }
-
-        // Allow undefined to be returned.
-    };
-
-    var atomReadAdvertisedActionOrFunction = function (domElement, baseURI) {
-        /// <summary>Reads the DOM element for an action or a function in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or function target url.</param>
-        /// <returns type="Object">Object with title, target, and metadata fields.</returns>
-
-        var extensions = [];
-        var result = { extensions: extensions };
-        xmlAttributes(domElement, function (attribute) {
-            var localName = xmlLocalName(attribute);
-            var nsURI = xmlNamespaceURI(attribute);
-            var value = xmlNodeValue(attribute);
-
-            if (nsURI === null) {
-                if (localName === "title" || localName === "metadata") {
-                    result[localName] = value;
-                    return;
-                }
-                if (localName === "target") {
-                    result.target = normalizeURI(value, xmlBaseURI(domElement, baseURI));
-                    return;
-                }
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-        return result;
-    };
-
-    var atomReadAdvertisedAction = function (domElement, baseURI, parentMetadata) {
-        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
-        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
-
-        var actions = parentMetadata.actions = parentMetadata.actions || [];
-        actions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
-    };
-
-    var atomReadAdvertisedFunction = function (domElement, baseURI, parentMetadata) {
-        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
-        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
-
-        var functions = parentMetadata.functions = parentMetadata.functions || [];
-        functions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
-    };
-
-    var atomReadFeed = function (domElement, baseURI, model) {
-        /// <summary>Reads a DOM element for an ATOM feed, producing an object model in return.</summary>
-        /// <param name="domElement">ATOM feed DOM element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM feed.</param>
-        /// <param name="model">Metadata that describes the conceptual schema.</param>
-        /// <returns type="Object">A new object representing the feed.</returns>
-
-        var extensions = atomReadExtensionAttributes(domElement);
-        var feedMetadata = { feed_extensions: extensions };
-        var results = [];
-
-        var feed = { __metadata: feedMetadata, results: results };
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === odataMetaXmlNs) {
-                if (localName === "count") {
-                    feed.__count = parseInt(xmlInnerText(child), 10);
-                    return;
-                }
-                if (localName === "action") {
-                    atomReadAdvertisedAction(child, baseURI, feedMetadata);
-                    return;
-                }
-                if (localName === "function") {
-                    atomReadAdvertisedFunction(child, baseURI, feedMetadata);
-                    return;
-                }
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createElementExtension(child));
-                return;
-            }
-
-            // The element should belong to the ATOM namespace.
-
-            if (localName === "entry") {
-                results.push(atomReadEntry(child, baseURI, model));
-                return;
-            }
-            if (localName === "link") {
-                atomReadFeedLink(child, feed, baseURI);
-                return;
-            }
-            if (localName === "id") {
-                feedMetadata.uri = normalizeURI(xmlInnerText(child), baseURI);
-                feedMetadata.uri_extensions = atomReadExtensionAttributes(child);
-                return;
-            }
-            if (localName === "title") {
-                feedMetadata.title = xmlInnerText(child) || "";
-                feedMetadata.title_extensions = atomReadExtensionAttributes(child);
-                return;
-            }
-        });
-
-        return feed;
-    };
-
-    var atomReadFeedLink = function (domElement, feed, baseURI) {
-        /// <summary>Reads an ATOM link DOM element for a feed.</summary>
-        /// <param name="domElement">ATOM link DOM element.</param>
-        /// <param name="feed">Feed object to be annotated with the link data.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var link = atomReadLink(domElement, baseURI);
-        var href = link.href;
-        var rel = link.rel;
-        var extensions = link.extensions;
-        var metadata = feed.__metadata;
-
-        if (rel === "next") {
-            feed.__next = href;
-            metadata.next_extensions = extensions;
-            return;
-        }
-        if (rel === "self") {
-            metadata.self = href;
-            metadata.self_extensions = extensions;
-            return;
-        }
-    };
-
-    var atomReadLink = function (domElement, baseURI) {
-        /// <summary>Reads an ATOM link DOM element.</summary>
-        /// <param name="linkElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the link href.</param>
-        /// <returns type="Object">A link element representation.</returns>
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        var extensions = [];
-        var link = { extensions: extensions, baseURI: baseURI };
-
-        xmlAttributes(domElement, function (attribute) {
-            var nsURI = xmlNamespaceURI(attribute);
-            var localName = xmlLocalName(attribute);
-            var value = attribute.value;
-
-            if (localName === "href") {
-                link.href = normalizeURI(value, baseURI);
-                return;
-            }
-            if (localName === "type" || localName === "rel") {
-                link[localName] = value;
-                return;
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-
-        if (!link.href) {
-            throw { error: "href attribute missing on link element", element: domElement };
-        }
-
-        return link;
-    };
-
-    var atomGetObjectValueByPath = function (path, item) {
-        /// <summary>Gets a slashed path value from the specified item.</summary>
-        /// <param name="path" type="String">Property path to read ('/'-separated).</param>
-        /// <param name="item" type="Object">Object to get value from.</param>
-        /// <returns>The property value, possibly undefined if any path segment is missing.</returns>
-
-        // Fast path.
-        if (path.indexOf('/') === -1) {
-            return item[path];
-        } else {
-            var parts = path.split('/');
-            var i, len;
-            for (i = 0, len = parts.length; i < len; i++) {
-                // Avoid traversing a null object.
-                if (item === null) {
-                    return undefined;
-                }
-
-                item = item[parts[i]];
-                if (item === undefined) {
-                    return item;
-                }
-            }
-
-            return item;
-        }
-    };
-
-    var atomSetEntryValueByPath = function (path, target, value, propertyType) {
-        /// <summary>Sets a slashed path value on the specified target.</summary>
-        /// <param name="path" type="String">Property path to set ('/'-separated).</param>
-        /// <param name="target" type="Object">Object to set value on.</param>
-        /// <param name="value">Value to set.</param>
-        /// <param name="propertyType" type="String" optional="true">Property type to set in metadata.</param>
-
-        var propertyName;
-        if (path.indexOf('/') === -1) {
-            target[path] = value;
-            propertyName = path;
-        } else {
-            var parts = path.split('/');
-            var i, len;
-            for (i = 0, len = (parts.length - 1); i < len; i++) {
-                // We construct each step of the way if the property is missing;
-                // if it's already initialized to null, we stop further processing.
-                var next = target[parts[i]];
-                if (next === undefined) {
-                    next = {};
-                    target[parts[i]] = next;
-                } else if (next === null) {
-                    return;
-                }
-                target = next;
-            }
-            propertyName = parts[i];
-            target[propertyName] = value;
-        }
-
-        if (propertyType) {
-            var metadata = target.__metadata = target.__metadata || {};
-            var properties = metadata.properties = metadata.properties || {};
-            var property = properties[propertyName] = properties[propertyName] || {};
-            property.type = propertyType;
-        }
-    };
-
-    var atomApplyCustomizationToEntryObject = function (customization, domElement, entry) {
-        /// <summary>Applies a specific feed customization item to an object.</summary>
-        /// <param name="customization">Object with customization description.</param>
-        /// <param name="sourcePath">Property path to set ('source' in the description).</param>
-        /// <param name="entryElement">XML element for the entry that corresponds to the object being read.</param>
-        /// <param name="entryObject">Object being read.</param>
-        /// <param name="propertyType" type="String">Name of property type to set.</param>
-        /// <param name="suffix" type="String">Suffix to feed customization properties.</param>
-
-        var propertyPath = customization.propertyPath;
-        // If keepInConent equals true or the property value is null we do nothing as this overrides any other customization.
-        if (customization.keepInContent || atomGetObjectValueByPath(propertyPath, entry) === null) {
-            return;
-        }
-
-        var xmlNode = xmlFindNodeByPath(domElement, customization.nsURI, customization.entryPath);
-
-        // If the XML tree does not contain the necessary elements to read the value,
-        // then it shouldn't be considered null, but rather ignored at all. This prevents
-        // the customization from generating the object path down to the property.
-        if (!xmlNode) {
-            return;
-        }
-
-        var propertyType = customization.propertyType;
-        var propertyValue;
-
-        if (customization.contentKind === "xhtml") {
-            // Treat per XHTML in http://tools.ietf.org/html/rfc4287#section-3.1.1, including the DIV
-            // in the content.
-            propertyValue = xmlSerializeDescendants(xmlNode);
-        } else {
-            propertyValue = xmlReadODataEdmPropertyValue(xmlNode, propertyType || "Edm.String");
-        }
-        // Set the value on the entry.
-        atomSetEntryValueByPath(propertyPath, entry, propertyValue, propertyType);
-    };
-
-    var lookupPropertyType = function (metadata, owningType, path) {
-        /// <summary>Looks up the type of a property given its path in an entity type.</summary>
-        /// <param name="metadata">Metadata in which to search for base and complex types.</param>
-        /// <param name="owningType">Type to which property belongs.</param>
-        /// <param name="path" type="String" mayBeNull="false">Property path to look at.</param>
-        /// <returns type="String">The name of the property type; possibly null.</returns>
-
-        var parts = path.split("/");
-        var i, len;
-        while (owningType) {
-            // Keep track of the type being traversed, necessary for complex types.
-            var traversedType = owningType;
-
-            for (i = 0, len = parts.length; i < len; i++) {
-                // Traverse down the structure as necessary.
-                var properties = traversedType.property;
-                if (!properties) {
-                    break;
-                }
-
-                // Find the property by scanning the property list (might be worth pre-processing).
-                var propertyFound = lookupProperty(properties, parts[i]);
-                if (!propertyFound) {
-                    break;
-                }
-
-                var propertyType = propertyFound.type;
-
-                // We could in theory still be missing types, but that would
-                // be caused by a malformed path.
-                if (!propertyType || isPrimitiveEdmType(propertyType)) {
-                    return propertyType || null;
-                }
-
-                traversedType = lookupComplexType(propertyType, metadata);
-                if (!traversedType) {
-                    return null;
-                }
-            }
-
-            // Traverse up the inheritance chain.
-            owningType = lookupEntityType(owningType.baseType, metadata);
-        }
-
-        return null;
-    };
-
-    var atomReadEntry = function (domElement, baseURI, model) {
-        /// <summary>Reads a DOM element for an ATOM entry, producing an object model in return.</summary>
-        /// <param name="domElement">ATOM entry DOM element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM entry.</param>
-        /// <param name="model">Metadata that describes the conceptual schema.</param>
-        /// <returns type="Object">A new object representing the entry.</returns>
-
-        var entryMetadata = {};
-        var entry = { __metadata: entryMetadata };
-
-        var etag = xmlAttributeValue(domElement, "etag", odataMetaXmlNs);
-        if (etag) {
-            entryMetadata.etag = etag;
-        }
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "id") {
-                    atomReadEntryId(child, entryMetadata, baseURI);
-                    return;
-                }
-                if (localName === "category") {
-                    atomReadEntryType(child, entryMetadata);
-                    return;
-                }
-                if (localName === "content") {
-                    atomReadEntryContent(child, entry, entryMetadata, baseURI);
-                    return;
-                }
-                if (localName === "link") {
-                    atomReadEntryLink(child, entry, entryMetadata, baseURI, model);
-                    return;
-                }
-                return;
-            }
-
-            if (nsURI === odataMetaXmlNs) {
-                if (localName === "properties") {
-                    atomReadEntryStructuralObject(child, entry, entryMetadata);
-                    return;
-                }
-                if (localName === "action") {
-                    atomReadAdvertisedAction(child, baseURI, entryMetadata);
-                    return;
-                }
-                if (localName === "function") {
-                    atomReadAdvertisedFunction(child, baseURI, entryMetadata);
-                    return;
-                }
-            }
-        });
-
-        // Apply feed customizations if applicable
-        var entityType = lookupEntityType(entryMetadata.type, model);
-        atomApplyAllFeedCustomizations(entityType, model, function (customization) {
-            atomApplyCustomizationToEntryObject(customization, domElement, entry);
-        });
-
-        return entry;
-    };
-
-    var atomReadEntryId = function (domElement, entryMetadata, baseURI) {
-        /// <summary>Reads an ATOM entry id DOM element.</summary>
-        /// <param name="domElement">ATOM id DOM element.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the id information.</param>
-
-        entryMetadata.uri = normalizeURI(xmlInnerText(domElement), xmlBaseURI(domElement, baseURI));
-        entryMetadata.uri_extensions = atomReadExtensionAttributes(domElement);
-    };
-
-    var atomReadEntryType = function (domElement, entryMetadata) {
-        /// <summary>Reads type information from an ATOM category DOM element.</summary>
-        /// <param name="domElement">ATOM category DOM element.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the type information.</param>
-
-        if (xmlAttributeValue(domElement, "scheme") === odataScheme) {
-            if (entryMetadata.type) {
-                throw { message: "Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry", element: domElement };
-            }
-
-            var typeExtensions = [];
-            xmlAttributes(domElement, function (attribute) {
-                var nsURI = xmlNamespaceURI(attribute);
-                var localName = xmlLocalName(attribute);
-
-                if (!nsURI) {
-                    if (localName !== "scheme" && localName !== "term") {
-                        typeExtensions.push(createAttributeExtension(attribute, true));
-                    }
-                    return;
-                }
-
-                if (isExtensionNs(nsURI)) {
-                    typeExtensions.push(createAttributeExtension(attribute, true));
-                }
-            });
-
-            entryMetadata.type = xmlAttributeValue(domElement, "term");
-            entryMetadata.type_extensions = typeExtensions;
-        }
-    };
-
-    var atomReadEntryContent = function (domElement, entry, entryMetadata, baseURI) {
-        /// <summary>Reads an ATOM content DOM element.</summary>
-        /// <param name="domElement">ATOM content DOM element.</param>
-        /// <param name="entry">Entry object to update with information.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the content information.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the Atom entry content.</param>
-
-        var src = xmlAttributeValue(domElement, "src");
-        var type = xmlAttributeValue(domElement, "type");
-
-        if (src) {
-            if (!type) {
-                throw {
-                    message: "Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",
-                    element: domElement
-                };
-            }
-
-            entryMetadata.media_src = normalizeURI(src, xmlBaseURI(domElement, baseURI));
-            entryMetadata.content_type = type;
-        }
-
-        xmlChildElements(domElement, function (child) {
-            if (src) {
-                throw { message: "Invalid AtomPub document: content element must not have child elements if the src attribute is specified", element: domElement };
-            }
-
-            if (xmlNamespaceURI(child) === odataMetaXmlNs && xmlLocalName(child) === "properties") {
-                atomReadEntryStructuralObject(child, entry, entryMetadata);
-            }
-        });
-    };
-
-    var atomReadEntryLink = function (domElement, entry, entryMetadata, baseURI, model) {
-        /// <summary>Reads a link element on an entry.</summary>
-        /// <param name="atomEntryLink">'link' element on the entry.</param>
-        /// <param name="entry" type="Object">Entry object to update with the link data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the link metadata.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the link href.</param>
-        /// <param name="model" type="Object">Metadata that describes the conceptual schema.</param>
-
-        var link = atomReadLink(domElement, baseURI);
-
-        var rel = link.rel;
-        var href = link.href;
-        var extensions = link.extensions;
-
-        if (rel === "self") {
-            entryMetadata.self = href;
-            entryMetadata.self_link_extensions = extensions;
-            return;
-        }
-
-        if (rel === "edit") {
-            entryMetadata.edit = href;
-            entryMetadata.edit_link_extensions = extensions;
-            return;
-        }
-
-        if (rel === "edit-media") {
-            entryMetadata.edit_media = link.href;
-            entryMetadata.edit_media_extensions = extensions;
-            atomReadLinkMediaEtag(link, entryMetadata);
-            return;
-        }
-
-        // This might be a named stream edit link
-        if (rel.indexOf(odataEditMediaPrefix) === 0) {
-            atomReadNamedStreamEditLink(link, entry, entryMetadata);
-            return;
-        }
-
-        // This might be a named stram media resource (read) link
-        if (rel.indexOf(odataMediaResourcePrefix) === 0) {
-            atomReadNamedStreamSelfLink(link, entry, entryMetadata);
-            return;
-        }
-
-        // This might be a navigation property
-        if (rel.indexOf(odataRelatedPrefix) === 0) {
-            atomReadNavPropLink(domElement, link, entry, entryMetadata, model);
-            return;
-        }
-
-        if (rel.indexOf(odataRelatedLinksPrefix) === 0) {
-            atomReadNavPropRelatedLink(link, entryMetadata);
-            return;
-        }
-    };
-
-    var atomReadNavPropRelatedLink = function (link, entryMetadata) {
-        /// <summary>Reads a link represnting the links related to a navigation property in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entryMetadata" type="Object">Entry metadata object to update with the related links information.</param>
-
-        var propertyName = link.rel.substring(odataRelatedLinksPrefix.length);
-
-        // Set the extra property information on the entry object metadata.
-        entryMetadata.properties = entryMetadata.properties || {};
-        var propertyMetadata = entryMetadata.properties[propertyName] = entryMetadata.properties[propertyName] || {};
-
-        propertyMetadata.associationuri = link.href;
-        propertyMetadata.associationuri_extensions = link.extensions;
-    };
-
-    var atomReadNavPropLink = function (domElement, link, entry, entryMetadata, model) {
-        /// <summary>Reads a link representing a navigation property in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element for a navigation property in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the navigation property.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the navigation property metadata.</param>
-        /// <param name="model" type="Object">Metadata that describes the conceptual schema.</param>
-
-        // Get any inline data.
-        var inlineData;
-        var inlineElement = xmlFirstChildElement(domElement, odataMetaXmlNs, "inline");
-        if (inlineElement) {
-            var inlineDocRoot = xmlFirstChildElement(inlineElement);
-            var inlineBaseURI = xmlBaseURI(inlineElement, link.baseURI);
-            inlineData = inlineDocRoot ? atomReadDocument(inlineDocRoot, inlineBaseURI, model) : null;
-        } else {
-            // If the link has no inline content, we consider it deferred.
-            inlineData = { __deferred: { uri: link.href} };
-        }
-
-        var propertyName = link.rel.substring(odataRelatedPrefix.length);
-
-        // Set the property value on the entry object.
-        entry[propertyName] = inlineData;
-
-        // Set the extra property information on the entry object metadata.
-        entryMetadata.properties = entryMetadata.properties || {};
-        var propertyMetadata = entryMetadata.properties[propertyName] = entryMetadata.properties[propertyName] || {};
-
-        propertyMetadata.extensions = link.extensions;
-    };
-
-    var atomReadNamedStreamEditLink = function (link, entry, entryMetadata) {
-        /// <summary>Reads a link representing the edit-media url of a named stream in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the named stream data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the named stream metadata.</param>
-
-        var propertyName = link.rel.substring(odataEditMediaPrefix.length);
-
-        var namedStreamMediaResource = atomGetEntryNamedStreamMediaResource(propertyName, entry, entryMetadata);
-        var mediaResource = namedStreamMediaResource.value;
-        var mediaResourceMetadata = namedStreamMediaResource.metadata;
-
-        var editMedia = link.href;
-
-        mediaResource.edit_media = editMedia;
-        mediaResource.content_type = link.type;
-        mediaResourceMetadata.edit_media_extensions = link.extensions;
-
-        // If there is only the edit link, make it the media self link as well.
-        mediaResource.media_src = mediaResource.media_src || editMedia;
-        mediaResourceMetadata.media_src_extensions = mediaResourceMetadata.media_src_extensions || [];
-
-        atomReadLinkMediaEtag(link, mediaResource);
-    };
-
-    var atomReadNamedStreamSelfLink = function (link, entry, entryMetadata) {
-        /// <summary>Reads a link representing the self url of a named stream in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the named stream data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the named stream metadata.</param>
-
-        var propertyName = link.rel.substring(odataMediaResourcePrefix.length);
-
-        var namedStreamMediaResource = atomGetEntryNamedStreamMediaResource(propertyName, entry, entryMetadata);
-        var mediaResource = namedStreamMediaResource.value;
-        var mediaResourceMetadata = namedStreamMediaResource.metadata;
-
-        mediaResource.media_src = link.href;
-        mediaResourceMetadata.media_src_extensions = link.extensions;
-        mediaResource.content_type = link.type;
-    };
-
-    var atomGetEntryNamedStreamMediaResource = function (name, entry, entryMetadata) {
-        /// <summary>Gets the media resource object and metadata object for a named stream in an entry object.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object from which the media resource object will be obtained.</param>
-        /// <param name="entryMetadata" type="Object">Entry metadata object from which the media resource metadata object will be obtained.</param>
-        /// <remarks>
-        ///    If the entry doest' have a media resource for the named stream indicated by the name argument, then this function will create a new
-        ///    one along with its metadata object.
-        /// <remarks>
-        /// <returns type="Object"> Object containing the value and metadata of the named stream's media resource. <returns>
-
-        entryMetadata.properties = entryMetadata.properties || {};
-
-        var mediaResourceMetadata = entryMetadata.properties[name];
-        var mediaResource = entry[name] && entry[name].__mediaresource;
-
-        if (!mediaResource) {
-            mediaResource = {};
-            entry[name] = { __mediaresource: mediaResource };
-            entryMetadata.properties[name] = mediaResourceMetadata = {};
-        }
-        return { value: mediaResource, metadata: mediaResourceMetadata };
-    };
-
-    var atomReadLinkMediaEtag = function (link, mediaResource) {
-        /// <summary>Gets the media etag from the link extensions and updates the media resource object with it.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="mediaResource" type="Object">Object containing media information for an OData Atom entry.</param>
-        /// <remarks>
-        ///    The function will remove the extension object for the etag if it finds it in the link extensions and will set
-        ///    its value under the media_etag property of the mediaResource object.
-        /// <remarks>
-        /// <returns type="Object"> Object containing the value and metadata of the named stream's media resource. <returns>
-
-        var extensions = link.extensions;
-        var i, len;
-        for (i = 0, len = extensions.length; i < len; i++) {
-            if (extensions[i].namespaceURI === odataMetaXmlNs && extensions[i].name === "etag") {
-                mediaResource.media_etag = extensions[i].value;
-                extensions.splice(i, 1);
-                return;
-            }
-        }
-    };
-
-    var atomReadEntryStructuralObject = function (domElement, parent, parentMetadata) {
-        /// <summary>Reads an atom entry's property as a structural object and sets its value in the parent and the metadata in the parentMetadata objects.</summary>
-        /// <param name="propertiesElement">XML element for the 'properties' node.</param>
-        /// <param name="parent">
-        ///     Object that will contain the property value. It can be either an antom entry or
-        ///     an atom complex property object.
-        /// </param>
-        /// <param name="parentMetadata">Object that will contain the property metadata. It can be either an atom entry metadata or a complex property metadata object</param>
-
-        xmlChildElements(domElement, function (child) {
-            var property = xmlReadODataProperty(child);
-            if (property) {
-                var propertyName = property.name;
-                var propertiesMetadata = parentMetadata.properties = parentMetadata.properties || {};
-                propertiesMetadata[propertyName] = property.metadata;
-                parent[propertyName] = property.value;
-            }
-        });
-    };
-
-    var atomReadServiceDocument = function (domElement, baseURI) {
-        /// <summary>Reads an AtomPub service document</summary>
-        /// <param name="atomServiceDoc">DOM element for the root of an AtomPub service document</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document.</param>
-        /// <returns type="Object">An object that contains the properties of the service document</returns>
-
-        var workspaces = [];
-        var extensions = [];
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-        // Find all the workspace elements.
-        xmlChildElements(domElement, function (child) {
-            if (xmlNamespaceURI(child) === appXmlNs && xmlLocalName(child) === "workspace") {
-                workspaces.push(atomReadServiceDocumentWorkspace(child, baseURI));
-                return;
-            }
-            extensions.push(createElementExtension(child));
-        });
-
-        // AtomPub (RFC 5023 Section 8.3.1) says a service document MUST contain one or
-        // more workspaces. Throw if we don't find any.
-        if (workspaces.length === 0) {
-            throw { message: "Invalid AtomPub service document: No workspace element found.", element: domElement };
-        }
-
-        return { workspaces: workspaces, extensions: extensions };
-    };
-
-    var atomReadServiceDocumentWorkspace = function (domElement, baseURI) {
-        /// <summary>Reads a single workspace element from an AtomPub service document</summary>
-        /// <param name="domElement">DOM element that represents a workspace of an AtomPub service document</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document workspace.</param>
-        /// <returns type="Object">An object that contains the properties of the workspace</returns>
-
-        var collections = [];
-        var extensions = [];
-        var title; // = undefined;
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "title") {
-                    if (title !== undefined) {
-                        throw { message: "Invalid AtomPub service document: workspace has more than one child title element", element: child };
-                    }
-
-                    title = xmlInnerText(child);
-                    return;
-                }
-            }
-
-            if (nsURI === appXmlNs) {
-                if (localName === "collection") {
-                    collections.push(atomReadServiceDocumentCollection(child, baseURI));
-                }
-                return;
-            }
-            extensions.push(atomReadExtensionElement(child));
-        });
-
-        return { title: title || "", collections: collections, extensions: extensions };
-    };
-
-    var atomReadServiceDocumentCollection = function (domElement, baseURI) {
-        /// <summary>Reads a service document collection element into an object.</summary>
-        /// <param name="domElement">DOM element that represents a collection of an AtomPub service document.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document collection.</param>
-        /// <returns type="Object">An object that contains the properties of the collection.</returns>
-
-
-        var href = xmlAttributeValue(domElement, "href");
-
-        if (!href) {
-            throw { message: "Invalid AtomPub service document: collection has no href attribute", element: domElement };
-        }
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-        href = normalizeURI(href, xmlBaseURI(domElement, baseURI));
-        var extensions = [];
-        var title; // = undefined;
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "title") {
-                    if (title !== undefined) {
-                        throw { message: "Invalid AtomPub service document: collection has more than one child title element", element: child };
-                    }
-                    title = xmlInnerText(child);
-                }
-                return;
-            }
-
-            if (nsURI !== appXmlNs) {
-                extensions.push(atomReadExtensionElement(domElement));
-            }
-        });
-
-        // AtomPub (RFC 5023 Section 8.3.3) says the collection element MUST contain
-        // a title element. It's likely to be problematic if the service doc doesn't
-        // have one so here we throw.
-        if (!title) {
-            throw { message: "Invalid AtomPub service document: collection has no title element", element: domElement };
-        }
-
-        return { title: title, href: href, extensions: extensions };
-    };
-
-    var atomNewElement = function (dom, name, children) {
-        /// <summary>Creates a new DOM element in the Atom namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the Atom element to create.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <returns>New DOM element in the Atom namespace.</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 as a child of the new DOM Element.
-        /// </remarks>
-
-        return xmlNewElement(dom, atomXmlNs, xmlQualifiedName(atomPrefix, name), children);
-    };
-
-    var atomNewAttribute = function (dom, name, value) {
-        /// <summary>Creates a new DOM attribute for an Atom element in the default namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the OData attribute to create.</param>
-        /// <param name="value">Attribute value.</param>
-        /// <returns>New DOM attribute in the default namespace.</returns>
-
-        return xmlNewAttribute(dom, null, name, value);
-    };
-
-    var atomCanRemoveProperty = function (propertyElement) {
-        /// <summary>Checks whether the property represented by domElement can be removed from the atom document DOM tree.</summary>
-        /// <param name="propertyElement">DOM element for the property to test.</param>
-        /// <remarks>
-        ///     The property can only be removed if it doens't have any children and only has namespace or type declaration attributes.
-        /// </remarks>
-        /// <returns type="Boolean">True is the property can be removed; false otherwise.</returns>
-
-        if (propertyElement.childNodes.length > 0) {
-            return false;
-        }
-
-        var isEmpty = true;
-        var attributes = propertyElement.attributes;
-        var i, len;
-        for (i = 0, len = attributes.length; i < len && isEmpty; i++) {
-            var attribute = attributes[i];
-
-            isEmpty = isEmpty && isXmlNSDeclaration(attribute) ||
-                 (xmlNamespaceURI(attribute) == odataMetaXmlNs && xmlLocalName(attribute) === "type");
-        }
-        return isEmpty;
-    };
-
-    var atomNewODataNavigationProperty = function (dom, name, kind, value, model) {
-        /// <summary>Creates a new Atom link DOM element for a navigation property in an OData Atom document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="kind" type="String">Navigation property kind. Expected values are "deferred", "entry", or "feed".</param>
-        /// <param name="value" optional="true" mayBeNull="true">Value of the navigation property, if any.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new Atom link DOM element for the navigation property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var linkType = null;
-        var linkContent = null;
-        var linkContentBodyData = null;
-        var href = "";
-
-        if (kind !== "deferred") {
-            linkType = atomNewAttribute(dom, "type", "application/atom+xml;type=" + kind);
-            linkContent = xmlNewODataMetaElement(dom, "inline");
-
-            if (value) {
-                href = value.__metadata && value.__metadata.uri || "";
-                linkContentBodyData =
-                    atomNewODataFeed(dom, value, model) ||
-                    atomNewODataEntry(dom, value, model);
-                xmlAppendChild(linkContent, linkContentBodyData.element);
-            }
-        } else {
-            href = value.__deferred.uri;
-        }
-
-        var navProp = atomNewElement(dom, "link", [
-            atomNewAttribute(dom, "href", href),
-            atomNewAttribute(dom, "rel", normalizeURI(name, odataRelatedPrefix)),
-            linkType,
-            linkContent
-        ]);
-
-        return xmlNewODataElementInfo(navProp, linkContentBodyData ? linkContentBodyData.dsv : "1.0");
-    };
-
-    var atomNewODataEntryDataItem = function (dom, name, value, dataItemMetadata, dataItemModel, model) {
-        /// <summary>Creates a new DOM element for a data item in an entry, complex property, or collection property.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Data item name.</param>
-        /// <param name="value" optional="true" mayBeNull="true">Value of the data item, if any.</param>
-        /// <param name="dataItemMetadata" type="Object" optional="true">Object containing metadata about the data item.</param>
-        /// <param name="dataItemModel" type="Object" optional="true">Object describing the data item in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the appropriate namespace for the data item and the
-        ///     required data service version for it.
-        /// </returns>
-
-        if (isNamedStream(value)) {
-            return null;
-        }
-
-        var dataElement = xmlNewODataDataElement(dom, name, value, dataItemMetadata, dataItemModel, model);
-        if (!dataElement) {
-            // This may be a navigation property.
-            var navPropKind = navigationPropertyKind(value, dataItemModel);
-
-            dataElement = atomNewODataNavigationProperty(dom, name, navPropKind, value, model);
-        }
-        return dataElement;
-    };
-
-    var atomEntryCustomization = function (dom, entry, entryProperties, customization) {
-        /// <summary>Applies a feed customization by transforming an Atom entry DOM element as needed.</summary>
-        /// <param name="dom">DOM document used for creating any new DOM nodes required by the customization.</param>
-        /// <param name="entry">DOM element for the Atom entry to which the customization is going to be applied.</param>
-        /// <param name="entryProperties">DOM element containing the properties of the Atom entry.</param>
-        /// <param name="customization" type="Object">Object describing an applicable feed customization.</param>
-        /// <remarks>
-        ///     Look into the atomfeedCustomization function for a description of the customization object.
-        /// </remarks>
-        /// <returns type="String">Data service version required by the applied customization</returns>
-
-        var atomProperty = xmlFindElementByPath(entryProperties, odataXmlNs, customization.propertyPath);
-        var atomPropertyNullAttribute = atomProperty && xmlAttributeNode(atomProperty, "null", odataMetaXmlNs);
-        var atomPropertyValue;
-        var dataServiceVersion = "1.0";
-
-        if (atomPropertyNullAttribute && atomPropertyNullAttribute.value === "true") {
-            return dataServiceVersion;
-        }
-
-        if (atomProperty) {
-            atomPropertyValue = xmlInnerText(atomProperty) || "";
-            if (!customization.keepInContent) {
-                dataServiceVersion = "2.0";
-                var parent = atomProperty.parentNode;
-                var candidate = parent;
-
-                parent.removeChild(atomProperty);
-                while (candidate !== entryProperties && atomCanRemoveProperty(candidate)) {
-                    parent = candidate.parentNode;
-                    parent.removeChild(candidate);
-                    candidate = parent;
-                }
-            }
-        }
-
-        var targetNode = xmlNewNodeByPath(dom, entry,
-            customization.nsURI, customization.nsPrefix, customization.entryPath);
-
-        if (targetNode.nodeType === 2) {
-            targetNode.value = atomPropertyValue;
-            return dataServiceVersion;
-        }
-
-        var contentKind = customization.contentKind;
-        xmlAppendChildren(targetNode, [
-                contentKind && xmlNewAttribute(dom, null, "type", contentKind),
-                contentKind === "xhtml" ? xmlNewFragment(dom, atomPropertyValue) : atomPropertyValue
-        ]);
-
-        return dataServiceVersion;
-    };
-
-    var atomNewODataEntry = function (dom, data, model) {
-        /// <summary>Creates a new DOM element for an Atom entry.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="data" type="Object">Entry object in the library's internal representation.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element for the Atom entry and the required data service version for it.
-        /// </returns>
-
-        var payloadMetadata = data.__metadata || {};
-        var propertiesMetadata = payloadMetadata.properties || {};
-
-        var etag = payloadMetadata.etag;
-        var uri = payloadMetadata.uri;
-        var typeName = payloadMetadata.type;
-        var entityType = lookupEntityType(typeName, model);
-
-        var properties = xmlNewODataMetaElement(dom, "properties");
-        var entry = atomNewElement(dom, "entry", [
-            atomNewElement(dom, "author",
-                atomNewElement(dom, "name")
-            ),
-            etag && xmlNewODataMetaAttribute(dom, "etag", etag),
-            uri && atomNewElement(dom, "id", uri),
-            typeName && atomNewElement(dom, "category", [
-                atomNewAttribute(dom, "term", typeName),
-                atomNewAttribute(dom, "scheme", odataScheme)
-            ]),
-        // TODO: MLE support goes here.
-            atomNewElement(dom, "content", [
-                atomNewAttribute(dom, "type", "application/xml"),
-                properties
-            ])
-        ]);
-
-        var dataServiceVersion = "1.0";
-        for (var name in data) {
-            if (name !== "__metadata") {
-                var entryDataItemMetadata = propertiesMetadata[name] || {};
-                var entryDataItemModel = entityType && (
-                    lookupProperty(entityType.property, name) ||
-                    lookupProperty(entityType.navigationProperty, name));
-
-                var entryDataItem = atomNewODataEntryDataItem(dom, name, data[name], entryDataItemMetadata, entryDataItemModel, model);
-                if (entryDataItem) {
-                    var entryElement = entryDataItem.element;
-                    var entryElementParent = (xmlNamespaceURI(entryElement) === atomXmlNs) ? entry : properties;
-
-                    xmlAppendChild(entryElementParent, entryElement);
-                    dataServiceVersion = maxVersion(dataServiceVersion, entryDataItem.dsv);
-                }
-            }
-        }
-
-        atomApplyAllFeedCustomizations(entityType, model, function (customization) {
-            var customizationDsv = atomEntryCustomization(dom, entry, properties, customization);
-            dataServiceVersion = maxVersion(dataServiceVersion, customizationDsv);
-        });
-
-        return xmlNewODataElementInfo(entry, dataServiceVersion);
-    };
-
-    var atomNewODataFeed = function (dom, data, model) {
-        /// <summary>Creates a new DOM element for an Atom feed.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="data" type="Object">Feed object in the library's internal representation.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element for the Atom feed and the required data service version for it.
-        /// </returns>
-
-        var entries = isArray(data) ? data : data.results;
-
-        if (!entries) {
-            return null;
-        }
-
-        var dataServiceVersion = "1.0";
-        var atomFeed = atomNewElement(dom, "feed");
-
-        var i, len;
-        for (i = 0, len = entries.length; i < len; i++) {
-            var atomEntryData = atomNewODataEntry(dom, entries[i], model);
-            xmlAppendChild(atomFeed, atomEntryData.element);
-            dataServiceVersion = maxVersion(dataServiceVersion, atomEntryData.dsv);
-        }
-        return xmlNewODataElementInfo(atomFeed, dataServiceVersion);
-    };
-
-    var atomNewODataDocument = function (data, model) {
-        /// <summary>Creates a new OData Atom document.</summary>
-        /// <param name="data" type="Object">Feed or entry object in the libary's internal representaion.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM document for the Atom document and the required data service version for it.
-        /// </returns>
-
-        if (data) {
-            var atomRootWriter = isFeed(data) && atomNewODataFeed ||
-                isObject(data) && atomNewODataEntry;
-
-            if (atomRootWriter) {
-                var dom = xmlDom();
-                var atomRootData = atomRootWriter(dom, data, model);
-
-                if (atomRootData) {
-                    var atomRootElement = atomRootData.element;
-                    xmlAppendChildren(atomRootElement, [
-                        xmlNewNSDeclaration(dom, odataMetaXmlNs, odataMetaPrefix),
-                        xmlNewNSDeclaration(dom, odataXmlNs, odataPrefix)
-                    ]);
-                    return xmlNewODataElementInfo(xmlAppendChild(dom, atomRootElement), atomRootData.dsv);
-                }
-            }
-        }
-        return null;
-    };
-
-    var atomParser = function (handler, text, context) {
-        /// <summary>Parses an ATOM document (feed, entry or service document).</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text" type="String">Document text.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An object representation of the document; undefined if not applicable.</returns>
-
-        if (text) {
-            var atomDoc = xmlParse(text);
-            var atomRoot = xmlFirstChildElement(atomDoc);
-            if (atomRoot) {
-                return atomReadDocument(atomRoot, null, context.metadata);
-            }
-        }
-    };
-
-    var atomSerializer = function (handler, data, context) {
-        /// <summary>Serializes an ATOM object into a document (feed or entry).</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="data" type="Object">Representation of feed or entry.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An text representation of the data object; undefined if not applicable.</returns>
-
-        var cType = context.contentType = context.contentType || contentType(atomMediaType);
-        if (cType && cType.mediaType === atomMediaType) {
-            var atomDoc = atomNewODataDocument(data, context.metadata);
-            if (atomDoc) {
-                context.dataServiceVersion = maxVersion(context.dataServiceVersion || "1.0", atomDoc.dsv);
-                return xmlSerialize(atomDoc.element);
-            }
-        }
-        // Allow undefined to be returned.
-    };
-
-    odata.atomHandler = handler(atomParser, atomSerializer, atomAcceptTypes.join(","), MAX_DATA_SERVICE_VERSION);
-
-
-
-    var schemaElement = function (attributes, elements, text, ns) {
-        /// <summary>Creates an object that describes an element in an schema.</summary>
-        /// <param name="attributes" type="Array">List containing the names of the attributes allowed for this element.</param>
-        /// <param name="elements" type="Array">List containing the names of the child elements allowed for this element.</param>
-        /// <param name="text" type="Boolean">Flag indicating if the element's text value is of interest or not.</param>
-        /// <param name="ns" type="String">Namespace to which the element belongs to.</param>
-        /// <remarks>
-        ///    If a child element name ends with * then it is understood by the schema that that child element can appear 0 or more times.
-        /// </remarks>
-        /// <returns type="Object">Object with attributes, elements, text, and ns fields.</returns>
-
-        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://msdn.microsoft.com/en-us/library/bb399292.aspx for a CSDL reference.
-    var schema = {
-        elements: {
-            Annotations: schemaElement(
-            /*attributes*/["Target", "Qualifier"],
-            /*elements*/["TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            Association: schemaElement(
-            /*attributes*/["Name"],
-            /*elements*/["End*", "ReferentialConstraint", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            AssociationSet: schemaElement(
-            /*attributes*/["Name", "Association"],
-            /*elements*/["End*", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            Binary: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Bool: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Collection: schemaElement(
-            /*attributes*/null,
-            /*elements*/["String*", "Int*", "Float*", "Decimal*", "Bool*", "DateTime*", "DateTimeOffset*", "Guid*", "Binary*", "Time*", "Collection*", "Record*"]
-            ),
-            CollectionType: schemaElement(
-            /*attributes*/["ElementType", "Nullable", "DefaultValue", "MaxLength", "FixedLength", "Precision", "Scale", "Unicode", "Collation", "SRID"],
-            /*elements*/["CollectionType", "ReferenceType", "RowType", "TypeRef"]
-            ),
-            ComplexType: schemaElement(
-            /*attributes*/["Name", "BaseType", "Abstract"],
-            /*elements*/["Property*", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            DateTime: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            DateTimeOffset: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Decimal: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            DefiningExpression: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Dependent: schemaElement(
-            /*attributes*/["Role"],
-            /*elements*/["PropertyRef*"]
-            ),
-            Documentation: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            End: schemaElement(
-            /*attributes*/["Type", "Role", "Multiplicity", "EntitySet"],
-            /*elements*/["OnDelete"]
-            ),
-            EntityContainer: schemaElement(
-            /*attributes*/["Name", "Extends"],
-            /*elements*/["EntitySet*", "AssociationSet*", "FunctionImport*", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            EntitySet: schemaElement(
-            /*attributes*/["Name", "EntityType"],
-            /*elements*/["TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            EntityType: schemaElement(
-            /*attributes*/["Name", "BaseType", "Abstract", "OpenType"],
-            /*elements*/["Key", "Property*", "NavigationProperty*", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            EnumType: schemaElement(
-            /*attributes*/["Name", "UnderlyingType", "IsFlags"],
-            /*elements*/["Member*"]
-            ),
-            Float: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Function: schemaElement(
-            /*attributes*/["Name", "ReturnType"],
-            /*elements*/["Parameter*", "DefiningExpression", "ReturnType", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            FunctionImport: schemaElement(
-            /*attributes*/["Name", "ReturnType", "EntitySet", "IsSideEffecting", "IsComposable", "IsBindable", "EntitySetPath"],
-            /*elements*/["Parameter*", "ReturnType", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            Guid: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Int: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Key: schemaElement(
-            /*attributes*/null,
-            /*elements*/["PropertyRef*"]
-            ),
-            LabeledElement: schemaElement(
-            /*attributes*/["Name"],
-            /*elements*/["Path", "String", "Int", "Float", "Decimal", "Bool", "DateTime", "DateTimeOffset", "Guid", "Binary", "Time", "Collection", "Record", "LabeledElement", "Null"]
-            ),
-            Member: schemaElement(
-            /*attributes*/["Name", "Value"]
-            ),
-            NavigationProperty: schemaElement(
-            /*attributes*/["Name", "Relationship", "ToRole", "FromRole", "ContainsTarget"],
-            /*elements*/["TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            Null: schemaElement(
-            /*attributes*/null,
-            /*elements*/null
-            ),
-            OnDelete: schemaElement(
-            /*attributes*/["Action"]
-            ),
-            Path: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Parameter: schemaElement(
-            /*attributes*/["Name", "Type", "Mode", "Nullable", "DefaultValue", "MaxLength", "FixedLength", "Precision", "Scale", "Unicode", "Collation", "ConcurrencyMode", "SRID"],
-            /*elements*/["CollectionType", "ReferenceType", "RowType", "TypeRef", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            Principal: schemaElement(
-            /*attributes*/["Role"],
-            /*elements*/["PropertyRef*"]
-            ),
-            Property: schemaElement(
-            /*attributes*/["Name", "Type", "Nullable", "DefaultValue", "MaxLength", "FixedLength", "Precision", "Scale", "Unicode", "Collation", "ConcurrencyMode", "CollectionKind", "SRID"],
-            /*elements*/["CollectionType", "ReferenceType", "RowType", "TypeAnnotation*", "ValueAnnotation*"]
-            ),
-            PropertyRef: schemaElement(
-            /*attributes*/["Name"]
-            ),
-            PropertyValue: schemaElement(
-            /*attributes*/["Property", "Path", "String", "Int", "Float", "Decimal", "Bool", "DateTime", "DateTimeOffset", "Guid", "Binary", "Time"],
-            /*Elements*/["Path", "String", "Int", "Float", "Decimal", "Bool", "DateTime", "DateTimeOffset", "Guid", "Binary", "Time", "Collection", "Record", "LabeledElement", "Null"]
-            ),
-            ReferenceType: schemaElement(
-            /*attributes*/["Type"]
-            ),
-            ReferentialConstraint: schemaElement(
-            /*attributes*/null,
-            /*elements*/["Principal", "Dependent"]
-            ),
-            ReturnType: schemaElement(
-            /*attributes*/["ReturnType", "Type", "EntitySet"],
-            /*elements*/["CollectionType", "ReferenceType", "RowType"]
-            ),
-            RowType: schemaElement(
-            /*elements*/["Property*"]
-            ),
-            String: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            Schema: schemaElement(
-            /*attributes*/["Namespace", "Alias"],
-            /*elements*/["Using*", "EntityContainer*", "EntityType*", "Association*", "ComplexType*", "Function*", "ValueTerm*", "Annotations*"]
-            ),
-            Time: schemaElement(
-            /*attributes*/null,
-            /*elements*/null,
-            /*text*/true
-            ),
-            TypeAnnotation: schemaElement(
-            /*attributes*/["Term", "Qualifier"],
-            /*elements*/["PropertyValue*"]
-            ),
-            TypeRef: schemaElement(
-            /*attributes*/["Type", "Nullable", "DefaultValue", "MaxLength", "FixedLength", "Precision", "Scale", "Unicode", "Collation", "SRID"]
-            ),
-            Using: schemaElement(
-            /*attributes*/["Namespace", "Alias"]
-            ),
-            ValueAnnotation: schemaElement(
-            /*attributes*/["Term", "Qualifier", "Path", "String", "Int", "Float", "Decimal", "Bool", "DateTime", "DateTimeOffset", "Guid", "Binary", "Time"],
-            /*Elements*/["Path", "String", "Int", "Float", "Decimal", "Bool", "DateTime", "DateTimeOffset", "Guid", "Binary", "Time", "Collection", "Record", "LabeledElement", "Null"]
-            ),
-            ValueTerm: schemaElement(
-            /*attributes*/["Name", "Type"],
-            /*elements*/["TypeAnnotation*", "ValueAnnotation*"]
-            ),
-
-            // See http://msdn.microsoft.com/en-us/library/dd541238(v=prot.10) for an EDMX reference.
-            Edmx: schemaElement(
-            /*attributes*/["Version"],
-            /*elements*/["DataServices", "Reference*", "AnnotationsReference*"],
-            /*text*/false,
-            /*ns*/edmxNs
-            ),
-            DataServices: schemaElement(
-            /*attributes*/null,
-            /*elements*/["Schema*"],
-            /*text*/false,
-            /*ns*/edmxNs
-            )
-        }
-    };
-
-    // See http://msdn.microsoft.com/en-us/library/ee373839.aspx for a feed customization reference.
-    var customizationAttributes = ["m:FC_ContentKind", "m:FC_KeepInContent", "m:FC_NsPrefix", "m:FC_NsUri", "m:FC_SourcePath", "m:FC_TargetPath"];
-    schema.elements.Property.attributes = schema.elements.Property.attributes.concat(customizationAttributes);
-    schema.elements.EntityType.attributes = schema.elements.EntityType.attributes.concat(customizationAttributes);
-
-    // See http://msdn.microsoft.com/en-us/library/dd541284(PROT.10).aspx for an EDMX reference.
-    schema.elements.Edmx = { attributes: ["Version"], elements: ["DataServices"], ns: edmxNs };
-    schema.elements.DataServices = { elements: ["Schema*"], ns: edmxNs };
-
-    // See http://msdn.microsoft.com/en-us/library/dd541233(v=PROT.10) for Conceptual Schema Definition Language Document for Data Services.
-    schema.elements.EntityContainer.attributes.push("m:IsDefaultEntityContainer");
-    schema.elements.Property.attributes.push("m:MimeType");
-    schema.elements.FunctionImport.attributes.push("m:HttpMethod");
-    schema.elements.FunctionImport.attributes.push("m:IsAlwaysBindable");
-    schema.elements.EntityType.attributes.push("m:HasStream");
-    schema.elements.DataServices.attributes = ["m:DataServiceVersion", "m:MaxDataServiceVersion"];
-
-    var scriptCase = function (text) {
-        /// <summary>Converts a Pascal-case identifier into a camel-case identifier.</summary>
-        /// <param name="text" type="String">Text to convert.</param>
-        /// <returns type="String">Converted text.</returns>
-        /// <remarks>If the text starts with multiple uppercase characters, it is left as-is.</remarks>
-
-        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();
-    };
-
-    var getChildSchema = function (parentSchema, candidateName) {
-        /// <summary>Gets the schema node for the specified element.</summary>
-        /// <param name="parentSchema" type="Object">Schema of the parent XML node of 'element'.</param>
-        /// <param name="candidateName">XML element name to consider.</param>
-        /// <returns type="Object">The schema that describes the specified element; null if not found.</returns>
-
-        if (candidateName === "Documentation") {
-            return { isArray: true, propertyName: "documentation" };
-        }
-
-        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;
-    };
-
-    // This regular expression is used to detect a feed customization element
-    // after we've normalized it into the 'm' prefix. It starts with m:FC_,
-    // followed by other characters, and ends with _ and a number.
-    // The captures are 0 - whole string, 1 - name as it appears in internal table.
-    var isFeedCustomizationNameRE = /^(m:FC_.*)_[0-9]+$/;
-
-    var isEdmNamespace = function (nsURI) {
-        /// <summary>Checks whether the specifies namespace URI is one of the known CSDL namespace URIs.</summary>
-        /// <param name="nsURI" type="String">Namespace URI to check.</param>
-        /// <returns type="Boolean">true if nsURI is a known CSDL namespace; false otherwise.</returns>
-
-        return nsURI === edmNs1 ||
-               nsURI === edmNs1_1 ||
-               nsURI === edmNs1_2 ||
-               nsURI === edmNs2a ||
-               nsURI === edmNs2b ||
-               nsURI === edmNs3;
-    };
-
-    var parseConceptualModelElement = function (element) {
-        /// <summary>Parses a CSDL document.</summary>
-        /// <param name="element">DOM element to parse.</param>
-        /// <returns type="Object">An object describing the parsed element.</returns>
-
-        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 extensions = [];
-        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;
-
-                // Feed customizations for complex types have additional
-                // attributes with a suffixed counter starting at '1', so
-                // take that into account when doing the lookup.
-                var match = isFeedCustomizationNameRE.exec(schemaName);
-                if (match) {
-                    schemaName = match[1];
-                }
-
-                if (contains(attributes, schemaName)) {
-                    handled = true;
-                    item[scriptCase(localName)] = value;
-                }
-            }
-
-            if (!handled) {
-                extensions.push(createAttributeExtension(attribute));
-            }
-        });
-
-        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);
-                }
-            } else {
-                extensions.push(createElementExtension(child));
-            }
-        });
-
-        if (elementSchema.text) {
-            item.text = xmlInnerText(element);
-        }
-
-        if (extensions.length) {
-            item.extensions = extensions;
-        }
-
-        return item;
-    };
-
-    var metadataParser = function (handler, text) {
-        /// <summary>Parses a metadata document.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text" type="String">Metadata text.</param>
-        /// <returns>An object representation of the conceptual model.</returns>
-
-        var doc = xmlParse(text);
-        var root = xmlFirstChildElement(doc);
-        return parseConceptualModelElement(root) || undefined;
-    };
-
-    odata.metadataHandler = handler(metadataParser, null, xmlMediaType, MAX_DATA_SERVICE_VERSION);
-
-
-
-    var PAYLOADTYPE_OBJECT = "o";
-    var PAYLOADTYPE_FEED = "f";
-    var PAYLOADTYPE_PRIMITIVE = "p";
-    var PAYLOADTYPE_COLLECTION = "c";
-    var PAYLOADTYPE_SVCDOC = "s";
-    var PAYLOADTYPE_LINKS = "l";
-
-    var odataNs = "odata";
-    var odataAnnotationPrefix = odataNs + ".";
-
-    var bindAnnotation = "@" + odataAnnotationPrefix + "bind";
-    var metadataAnnotation = odataAnnotationPrefix + "metadata";
-    var navUrlAnnotation = odataAnnotationPrefix + "navigationLinkUrl";
-    var typeAnnotation = odataAnnotationPrefix + "type";
-
-    var jsonLightNameMap = {
-        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"
-    };
-
-    var jsonLightAnnotations = {
-        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"
-    };
-
-    var jsonLightAnnotationInfo = function (annotation) {
-        /// <summary>Gets the name and target of an annotation in a JSON light payload.</summary>
-        /// <param name="annotation" type="String">JSON light payload annotation.</param>
-        /// <returns type="Object">Object containing the annotation name and the target property name.</param>
-
-        if (annotation.indexOf(".") > 0) {
-            var targetEnd = annotation.indexOf("@");
-            var target = targetEnd > -1 ? annotation.substring(0, targetEnd) : null;
-            var name = annotation.substring(targetEnd + 1);
-
-            return {
-                target: target,
-                name: name,
-                isOData: name.indexOf(odataAnnotationPrefix) === 0
-            };
-        }
-        return null;
-    };
-
-    var jsonLightDataItemType = function (name, value, container, dataItemModel, model) {
-        /// <summary>Gets the type name of a JSON light data item that belongs to a feed, an entry, a complex type property, or a collection property.</summary>
-        /// <param name="name" type="String">Name of the data item for which the type name is going to be retrieved.</param>
-        /// <param name="value">Value of the data item.</param>
-        /// <param name="container" type="Object">JSON light object that owns the data item.</param>
-        /// <param name="dataItemModel" type="Object" optional="true">Object describing the data item in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <remarks>
-        ///    This function will first try to get the type name from the data item's value itself if it is a JSON light object; otherwise
-        ///    it will try to get it from the odata.type annotation applied to the data item in the container. Then, it will fallback to the data item model.
-        ///    If all attempts fail, it will return null.
-        /// </remarks>
-        /// <returns type="String">Data item type name; null if the type name cannot be found.</returns>
-
-        return (isComplex(value) && value[typeAnnotation]) ||
-            (container && container[name + "@" + typeAnnotation]) ||
-            (dataItemModel && dataItemModel.type) ||
-            (lookupNavigationPropertyType(dataItemModel, model)) ||
-            null;
-    };
-
-    var jsonLightDataItemModel = function (name, containerModel) {
-        /// <summary>Gets an object describing a data item in an OData conceptual schema.</summary>
-        /// <param name="name" type="String">Name of the data item for which the model is going to be retrieved.</param>
-        /// <param name="containerModel" type="Object">Object describing the owner of the data item in an OData conceptual schema.</param>
-        /// <returns type="Object">Object describing the data item; null if it cannot be found.</returns>
-
-        if (containerModel) {
-            return lookupProperty(containerModel.property, name) ||
-                lookupProperty(containerModel.navigationProperty, name);
-        }
-        return null;
-    };
-
-    var jsonLightIsEntry = function (data) {
-        /// <summary>Determines whether data represents a JSON light entry object.</summary>
-        /// <param name="data" type="Object">JSON light object to test.</param>
-        /// <returns type="Boolean">True if the data is JSON light entry object; false otherwise.</returns>
-
-        return isComplex(data) && ((odataAnnotationPrefix + "id") in data);
-    };
-
-    var jsonLightIsNavigationProperty = function (name, data, dataItemModel) {
-        /// <summary>Determines whether a data item in a JSON light object is a navigation property.</summary>
-        /// <param name="name" type="String">Name of the data item to test.</param>
-        /// <param name="data" type="Object">JSON light object that owns the data item.</param>
-        /// <param name="dataItemModel" type="Object">Object describing the data item in an OData conceptual schema.</param>
-        /// <returns type="Boolean">True if the data item is a navigation property; false otherwise.</returns>
-
-        if (!!data[name + "@" + navUrlAnnotation] || (dataItemModel && dataItemModel.relationship)) {
-            return true;
-        }
-
-        // Sniff the property value.
-        var value = isArray(data[name]) ? data[name][0] : data[name];
-        return jsonLightIsEntry(value);
-    };
-
-    var jsonLightIsPrimitiveType = function (typeName) {
-        /// <summary>Determines whether a type name is a primitive type in a JSON light payload.</summary>
-        /// <param name="typeName" type="String">Type name to test.</param>
-        /// <returns type="Boolean">True if the type name an EDM primitive type or an OData spatial type; false otherwise.</returns>
-
-        return isPrimitiveEdmType(typeName) || isGeographyEdmType(typeName) || isGeometryEdmType(typeName);
-    };
-
-    var jsonLightReadDataAnnotations = function (data, obj, baseURI, dataModel, model) {
-        /// <summary>Converts annotations found in a JSON light payload object to either properties or metadata.</summary>
-        /// <param name="data" type="Object">JSON light payload object containing the annotations to convert.</param>
-        /// <param name="obj" type="Object">Object that will store the converted annotations.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="dataModel" type="Object">Object describing the JSON light payload in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns>JSON light payload object with its annotations converted to either properties or metadata.</param>
-
-        for (var name in data) {
-            if (name.indexOf(".") > 0 && name.charAt(0) !== "#") {
-                var annotationInfo = jsonLightAnnotationInfo(name);
-                if (annotationInfo) {
-                    var annotationName = annotationInfo.name;
-                    var target = annotationInfo.target;
-                    var targetModel = null;
-                    var targetType = null;
-
-                    if (target) {
-                        targetModel = jsonLightDataItemModel(target, dataModel);
-                        targetType = jsonLightDataItemType(target, data[target], data, targetModel, model);
-                    }
-
-                    if (annotationInfo.isOData) {
-                        jsonLightApplyPayloadODataAnnotation(annotationName, target, targetType, data[name], data, obj, baseURI);
-                    } else {
-                        obj[name] = data[name];
-                    }
-                }
-            }
-        }
-        return obj;
-    };
-
-    var jsonLightApplyPayloadODataAnnotation = function (name, target, targetType, value, data, obj, baseURI) {
-        /// <summary>
-        ///   Processes a JSON Light payload OData annotation producing either a property, payload metadata, or property metadata on its owner object.
-        /// </summary>
-        /// <param name="name" type="String">Annotation name.</param>
-        /// <param name="target" type="String">Name of the property that is being targeted by the annotation.</param>
-        /// <param name="targetType" type="String">Type name of the target property.</param>
-        /// <param name="data" type="Object">JSON light object containing the annotation.</param>
-        /// <param name="obj" type="Object">Object that will hold properties produced by the annotation.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var annotation = name.substring(odataAnnotationPrefix.length);
-
-        switch (annotation) {
-            case "navigationLinkUrl":
-                jsonLightApplyNavigationUrlAnnotation(annotation, target, targetType, value, data, obj, baseURI);
-                return;
-            case "nextLink":
-            case "count":
-                jsonLightApplyFeedAnnotation(annotation, target, value, obj, baseURI);
-                return;
-            case "mediaReadLink":
-            case "mediaEditLink":
-            case "mediaContentType":
-            case "mediaETag":
-                jsonLightApplyMediaAnnotation(annotation, target, targetType, value, obj, baseURI);
-                return;
-            default:
-                jsonLightApplyMetadataAnnotation(annotation, target, value, obj, baseURI);
-                return;
-        }
-    };
-
-    var jsonLightApplyMetadataAnnotation = function (name, target, value, obj, baseURI) {
-        /// <summary>
-        ///    Converts a JSON light annotation that applies to entry metadata only (i.e. odata.editLink or odata.readLink) and its value
-        ///    into their library's internal representation and saves it back to data.
-        /// </summary>
-        /// <param name="name" type="String">Annotation name.</param>
-        /// <param name="target" type="String">Name of the property on which the annotation should be applied.</param>
-        /// <param name="value" type="Object">Annotation value.</param>
-        /// <param name="obj" type="Object">Object that will hold properties produced by the annotation.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var metadata = obj.__metadata = obj.__metadata || {};
-        var mappedName = jsonLightNameMap[name] || name;
-
-        if (name === "editLink") {
-            metadata.uri = normalizeURI(value, baseURI);
-            metadata[mappedName] = metadata.uri;
-            return;
-        }
-
-        if (name === "readLink" || name === "associationLinkUrl") {
-            value = normalizeURI(value, baseURI);
-        }
-
-        if (target) {
-            var propertiesMetadata = metadata.properties = metadata.properties || {};
-            var propertyMetadata = propertiesMetadata[target] = propertiesMetadata[target] || {};
-
-            if (name === "type") {
-                propertyMetadata[mappedName] = propertyMetadata[mappedName] || value;
-                return;
-            }
-            propertyMetadata[mappedName] = value;
-            return;
-        }
-        metadata[mappedName] = value;
-    };
-
-    var jsonLightApplyFeedAnnotation = function (name, target, value, obj, baseURI) {
-        /// <summary>
-        ///    Converts a JSON light annotation that applies to feeds only (i.e. odata.count or odata.nextlink) and its value
-        ///    into their library's internal representation and saves it back to data.
-        /// </summary>
-        /// <param name="name" type="String">Annotation name.</param>
-        /// <param name="target" type="String">Name of the property on which the annotation should be applied.</param>
-        /// <param name="value" type="Object">Annotation value.</param>
-        /// <param name="obj" type="Object">Object that will hold properties produced by the annotation.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var mappedName = jsonLightNameMap[name];
-        var feed = target ? obj[target] : obj;
-        feed[mappedName] = (name === "nextLink") ? normalizeURI(value, baseURI) : value;
-    };
-
-    var jsonLightApplyMediaAnnotation = function (name, target, targetType, value, obj, baseURI) {
-        /// <summary>
-        ///    Converts a JSON light media annotation in and its value into their library's internal representation
-        ///    and saves it back to data or metadata.
-        /// </summary>
-        /// <param name="name" type="String">Annotation name.</param>
-        /// <param name="target" type="String">Name of the property on which the annotation should be applied.</param>
-        /// <param name="targetType" type="String">Type name of the target property.</param>
-        /// <param name="value" type="Object">Annotation value.</param>
-        /// <param name="obj" type="Object">Object that will hold properties produced by the annotation.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var metadata = obj.__metadata = obj.__metadata || {};
-        var mappedName = jsonLightNameMap[name];
-
-        if (name === "mediaReadLink" || name === "mediaEditLink") {
-            value = normalizeURI(value, baseURI);
-        }
-
-        if (target) {
-            var propertiesMetadata = metadata.properties = metadata.properties || {};
-            var propertyMetadata = propertiesMetadata[target] = propertiesMetadata[target] || {};
-            propertyMetadata.type = propertyMetadata.type || targetType;
-
-            obj.__metadata = metadata;
-            obj[target] = obj[target] || { __mediaresource: {} };
-            obj[target].__mediaresource[mappedName] = value;
-            return;
-        }
-
-        metadata[mappedName] = value;
-    };
-
-    var jsonLightApplyNavigationUrlAnnotation = function (name, target, targetType, value, data, obj, baseURI) {
-        /// <summary>
-        ///    Converts a JSON light navigation property annotation and its value into their library's internal representation
-        ///    and saves it back to data o metadata.
-        /// </summary>
-        /// <param name="name" type="String">Annotation name.</param>
-        /// <param name="target" type="String">Name of the property on which the annotation should be applied.</param>
-        /// <param name="targetType" type="String">Type name of the target property.</param>
-        /// <param name="value" type="Object">Annotation value.</param>
-        /// <param name="data" type="Object">JSON light object containing the annotation.</param>
-        /// <param name="obj" type="Object">Object that will hold properties produced by the annotation.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var metadata = obj.__metadata = obj.__metadata || {};
-        var propertiesMetadata = metadata.properties = metadata.properties || {};
-        var propertyMetadata = propertiesMetadata[target] = propertiesMetadata[target] || {};
-        var uri = normalizeURI(value, baseURI);
-
-        if (data.hasOwnProperty(target)) {
-            // The navigation property is inlined in the payload,
-            // so the navigation link url should be pushed to the object's
-            // property metadata instead.
-            propertyMetadata.navigationLinkUrl = uri;
-            return;
-        }
-        obj[target] = { __deferred: { uri: uri} };
-        propertyMetadata.type = propertyMetadata.type || targetType;
-    };
-
-
-    var jsonLightReadDataItemValue = function (value, typeName, dataItemMetadata, baseURI, dataItemModel, model, recognizeDates) {
-        /// <summary>Converts the value of a data item in a JSON light object to its library representation.</summary>
-        /// <param name="value">Data item value to convert.</param>
-        /// <param name="typeName" type="String">Type name of the data item.</param>
-        /// <param name="dataItemMetadata" type="Object">Object containing metadata about the data item.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="dataItemModel" type="Object" optional="true">Object describing the data item in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns>Data item value in its library representation.</param>
-
-        if (typeof value === "string") {
-            return jsonLightReadStringPropertyValue(value, typeName, recognizeDates);
-        }
-
-        if (!jsonLightIsPrimitiveType(typeName)) {
-            if (isArray(value)) {
-                return jsonLightReadCollectionPropertyValue(value, typeName, dataItemMetadata, baseURI, model, recognizeDates);
-            }
-
-            if (isComplex(value)) {
-                return jsonLightReadComplexPropertyValue(value, typeName, dataItemMetadata, baseURI, model, recognizeDates);
-            }
-        }
-        return value;
-    };
-
-    var jsonLightReadStringPropertyValue = function (value, propertyType, recognizeDates) {
-        /// <summary>Convertes the value of a string property in a JSON light object to its library representation.</summary>
-        /// <param name="value" type="String">String value to convert.</param>
-        /// <param name="propertyType" type="String">Type name of the property.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns>String property value in its library representation.</returns>
-
-        switch (propertyType) {
-            case EDM_TIME:
-                return parseDuration(value);
-            case EDM_DATETIME:
-                return parseDateTime(value, /*nullOnError*/false);
-            case EDM_DATETIMEOFFSET:
-                return parseDateTimeOffset(value, /*nullOnError*/false);
-        }
-
-        if (recognizeDates) {
-            return parseDateTime(value, /*nullOnError*/true) ||
-                   parseDateTimeOffset(value, /*nullOnError*/true) ||
-                   value;
-        }
-        return value;
-    };
-
-    var jsonLightReadCollectionPropertyValue = function (value, propertyType, propertyMetadata, baseURI, model, recognizeDates) {
-        /// <summary>Converts the value of a collection property in a JSON light object into its library representation.</summary>
-        /// <param name="value" type="Array">Collection property value to convert.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object">Object containing metadata about the collection property.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Collection property value in its library representation.</returns>
-
-        var collectionType = getCollectionType(propertyType);
-        var itemsMetadata = [];
-        var items = [];
-
-        var i, len;
-        for (i = 0, len = value.length; i < len; i++) {
-            var itemType = jsonLightDataItemType(null, value[i]) || collectionType;
-            var itemMetadata = { type: itemType };
-            var item = jsonLightReadDataItemValue(value[i], itemType, itemMetadata, baseURI, null, model, recognizeDates);
-
-            if (!jsonLightIsPrimitiveType(itemType) && !isPrimitive(value[i])) {
-                itemsMetadata.push(itemMetadata);
-            }
-            items.push(item);
-        }
-
-        if (itemsMetadata.length > 0) {
-            propertyMetadata.elements = itemsMetadata;
-        }
-
-        return { __metadata: { type: propertyType }, results: items };
-    };
-
-    var jsonLightReadComplexPropertyValue = function (value, propertyType, propertyMetadata, baseURI, model, recognizeDates) {
-        /// <summary>Converts the value of a comples property in a JSON light object into its library representation.</summary>
-        /// <param name="value" type="Object">Complex property value to convert.</param>
-        /// <param name="propertyType" type="String">Property type name.</param>
-        /// <param name="propertyMetadata" type="Object">Object containing metadata about the complx type property.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Complex property value in its library representation.</returns>
-
-        var complexValue = jsonLightReadObject(value, { type: propertyType }, baseURI, model, recognizeDates);
-        var complexMetadata = complexValue.__metadata;
-        var complexPropertiesMetadata = complexMetadata.properties;
-
-        if (complexPropertiesMetadata) {
-            propertyMetadata.properties = complexPropertiesMetadata;
-            delete complexMetadata.properties;
-        }
-        return complexValue;
-    };
-
-    var jsonLightReadNavigationPropertyValue = function (value, propertyInfo, baseURI, model, recognizeDates) {
-        /// <summary>Converts the value of a navigation property in a JSON light object into its library representation.</summary>
-        /// <param name="value">Navigation property property value to convert.</param>
-        /// <param name="propertyInfo" type="String">Information about the property whether it's an entry, feed or complex type.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Collection property value in its library representation.</returns>
-
-        if (isArray(value)) {
-            return jsonLightReadFeed(value, propertyInfo, baseURI, model, recognizeDates);
-        }
-
-        if (isComplex(value)) {
-            return jsonLightReadObject(value, propertyInfo, baseURI, model, recognizeDates);
-        }
-        return null;
-    };
-
-    var jsonLightReadObject = function (data, objectInfo, baseURI, model, recognizeDates) {
-        /// <summary>Converts a JSON light entry or complex type object into its library representation.</summary>
-        /// <param name="data" type="Object">JSON light entry or complex type object to convert.</param>
-        /// <param name="objectInfo" type="Object">Information about the entry or complex.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Entry or complex type object.</param>
-
-        objectInfo = objectInfo || {};
-        var actualType = data[typeAnnotation] || objectInfo.type || null;
-        var dataModel = lookupEntityType(actualType, model);
-        var isEntry = true;
-        if (!dataModel) {
-            isEntry = false;
-            dataModel = lookupComplexType(actualType, model);
-        }
-
-        var metadata = { type: actualType };
-        var obj = { __metadata: metadata };
-        var propertiesMetadata = {};
-        var baseTypeModel;
-        if (isEntry && dataModel && objectInfo.entitySet && objectInfo.contentTypeOdata == "minimalmetadata") {
-            var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
-            baseTypeModel = null; // check if the key model is in a parent type.
-            if (!dataModel.key) {
-                baseTypeModel = dataModel;
-            }
-            while (!!baseTypeModel && !baseTypeModel.key && baseTypeModel.baseType) {
-                baseTypeModel = lookupEntityType(baseTypeModel.baseType, model);
-            }
-
-            if (dataModel.key || (!!baseTypeModel && baseTypeModel.key)) {
-                var entryKey;
-                if (dataModel.key) {
-                    entryKey = jsonLightGetEntryKey(data, dataModel);
-                } else {
-                    entryKey = jsonLightGetEntryKey(data, baseTypeModel);
-                }
-                if (entryKey) {
-                    var entryInfo = {
-                        key: entryKey,
-                        entitySet: objectInfo.entitySet,
-                        functionImport: objectInfo.functionImport,
-                        containerName: objectInfo.containerName
-                    };
-                    jsonLightComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
-                }
-            }
-        }
-
-        for (var name in data) {
-            if (name.indexOf("#") === 0) {
-                // This is an advertised function or action.
-                jsonLightReadAdvertisedFunctionOrAction(name.substring(1), data[name], obj, baseURI, model);
-            } else {
-                // Is name NOT an annotation?
-                if (name.indexOf(".") === -1) {
-                    if (!metadata.properties) {
-                        metadata.properties = propertiesMetadata;
-                    }
-
-                    var propertyValue = data[name];
-                    var propertyModel = propertyModel = jsonLightDataItemModel(name, dataModel);
-                    baseTypeModel = dataModel;
-                    while (!!dataModel && propertyModel === null && baseTypeModel.baseType) {
-                        baseTypeModel = lookupEntityType(baseTypeModel.baseType, model);
-                        propertyModel = propertyModel = jsonLightDataItemModel(name, baseTypeModel);
-                    }
-                    var isNavigationProperty = jsonLightIsNavigationProperty(name, data, propertyModel);
-                    var propertyType = jsonLightDataItemType(name, propertyValue, data, propertyModel, model);
-                    var propertyMetadata = propertiesMetadata[name] = propertiesMetadata[name] || { type: propertyType };
-                    if (isNavigationProperty) {
-                        var propertyInfo = {};
-                        if (objectInfo.entitySet !== undefined) {
-                            var navigationPropertyEntitySetName = lookupNavigationPropertyEntitySet(propertyModel, objectInfo.entitySet.name, model);
-                            propertyInfo = getEntitySetInfo(navigationPropertyEntitySetName, model);
-                        }
-                        propertyInfo.contentTypeOdata = objectInfo.contentTypeOdata;
-                        propertyInfo.kind = objectInfo.kind;
-                        propertyInfo.type = propertyType;
-                        obj[name] = jsonLightReadNavigationPropertyValue(propertyValue, propertyInfo, baseURI, model, recognizeDates);
-                    } else {
-                        obj[name] = jsonLightReadDataItemValue(propertyValue, propertyType, propertyMetadata, baseURI, propertyModel, model, recognizeDates);
-                    }
-                }
-            }
-        }
-
-        return jsonLightReadDataAnnotations(data, obj, baseURI, dataModel, model);
-    };
-
-    var jsonLightReadAdvertisedFunctionOrAction = function (name, value, obj, baseURI, model) {
-        /// <summary>Converts a JSON light advertised action or function object into its library representation.</summary>
-        /// <param name="name" type="String">Advertised action or function name.</param>
-        /// <param name="value">Advertised action or function value.</param>
-        /// <param name="obj" type="Object">Object that will the converted value of the advertised action or function.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action's or function's relative URIs.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <remarks>
-        ///     Actions and functions have the same representation in json light, so to disambiguate them the function uses
-        ///     the model object.  If available, the function will look for the functionImport object that describes the
-        ///     the action or the function.  If for whatever reason the functionImport can't be retrieved from the model (like
-        ///     there is no model available or there is no functionImport within the model), then the value is going to be treated
-        ///     as an advertised action and stored under obj.__metadata.actions.
-        /// </remarks>
-
-        if (!name || !isArray(value) && !isComplex(value)) {
-            return;
-        }
-
-        var isFunction = false;
-        var nsEnd = name.lastIndexOf(".");
-        var simpleName = name.substring(nsEnd + 1);
-        var containerName = (nsEnd > -1) ? name.substring(0, nsEnd) : "";
-
-        var container = (simpleName === name || containerName.indexOf(".") === -1) ?
-            lookupDefaultEntityContainer(model) :
-            lookupEntityContainer(containerName, model);
-
-        if (container) {
-            var functionImport = lookupFunctionImport(container.functionImport, simpleName);
-            if (functionImport && !!functionImport.isSideEffecting) {
-                isFunction = !parseBool(functionImport.isSideEffecting);
-            }
-        }
-
-        var metadata = obj.__metadata;
-        var targetName = isFunction ? "functions" : "actions";
-        var metadataURI = normalizeURI(name, baseURI);
-        var items = (isArray(value)) ? value : [value];
-
-        var i, len;
-        for (i = 0, len = items.length; i < len; i++) {
-            var item = items[i];
-            if (item) {
-                var targetCollection = metadata[targetName] = metadata[targetName] || [];
-                var actionOrFunction = { metadata: metadataURI, title: item.title, target: normalizeURI(item.target, baseURI) };
-                targetCollection.push(actionOrFunction);
-            }
-        }
-    };
-
-    var jsonLightReadFeed = function (data, feedInfo, baseURI, model, recognizeDates) {
-        /// <summary>Converts a JSON light feed or top level collection property object into its library representation.</summary>
-        /// <param name="data" type="Object">JSON light feed object to convert.</param>
-        /// <param name="typeName" type="String">Type name of the feed or collection items.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Feed or top level collection object.</param>
-
-        var items = isArray(data) ? data : data.value;
-        var entries = [];
-        var i, len, entry;
-        for (i = 0, len = items.length; i < len; i++) {
-            entry = jsonLightReadObject(items[i], feedInfo, baseURI, model, recognizeDates);
-            entries.push(entry);
-        }
-
-        var feed = { results: entries };
-
-        if (isComplex(data)) {
-            for (var name in data) {
-                if (name.indexOf("#") === 0) {
-                    // This is an advertised function or action.
-                    feed.__metadata = feed.__metadata || {};
-                    jsonLightReadAdvertisedFunctionOrAction(name.substring(1), data[name], feed, baseURI, model);
-                }
-            }
-            feed = jsonLightReadDataAnnotations(data, feed, baseURI);
-        }
-        return feed;
-    };
-
-    var jsonLightGetEntryKey = function (data, entityModel) {
-        /// <summary>Gets the key of an entry.</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="entityModel" type="String">Object describing the entry Model</param>
-        /// <returns type="string">Entry instance key.</returns>
-
-        var entityInstanceKey;
-        var entityKeys = entityModel.key.propertyRef;
-        var type;
-        entityInstanceKey = "(";
-        if (entityKeys.length == 1) {
-            type = lookupProperty(entityModel.property, entityKeys[0].name).type;
-            entityInstanceKey += formatLiteral(data[entityKeys[0].name], type);
-        } else {
-            var first = true;
-            for (var i = 0; i < entityKeys.length; i++) {
-                if (!first) {
-                    entityInstanceKey += ",";
-                } else {
-                    first = false;
-                }
-                type = lookupProperty(entityModel.property, entityKeys[i].name).type;
-                entityInstanceKey += entityKeys[i].name + "=" + formatLiteral(data[entityKeys[i].name], type);
-            }
-        }
-        entityInstanceKey += ")";
-        return entityInstanceKey;
-    };
-
-
-    var jsonLightComputeUrisIfMissing = function (data, entryInfo, actualType, serviceURI, entityModel, baseTypeModel) {
-        /// <summary>Compute the URI according to OData conventions if it doesn't exist</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="entryInfo" type="Object">Information about the entry includes type, key, entitySet and entityContainerName.</param>
-        /// <param name="actualType" type="String">Type of the entry</param>
-        /// <param name="serviceURI" type="String">Base URI the service.</param>
-        /// <param name="entityModel" type="Object">Object describing an OData conceptual schema of the entry.</param>
-        /// <param name="baseTypeModel" type="Object" optional="true">Object escribing an OData conceptual schema of the baseType if it exists.</param>
-
-        var lastIdSegment = data[jsonLightAnnotations.id] || data[jsonLightAnnotations.read] || data[jsonLightAnnotations.edit] || entryInfo.entitySet.name + entryInfo.key;
-        data[jsonLightAnnotations.id] = serviceURI + lastIdSegment;
-        if (!data[jsonLightAnnotations.edit]) {
-            data[jsonLightAnnotations.edit] = entryInfo.entitySet.name + entryInfo.key;
-            if (entryInfo.entitySet.entityType != actualType) {
-                data[jsonLightAnnotations.edit] += "/" + actualType;
-            }
-        }
-        data[jsonLightAnnotations.read] = data[jsonLightAnnotations.read] || data[jsonLightAnnotations.edit];
-        if (!data[jsonLightAnnotations.etag]) {
-            var etag = jsonLightComputeETag(data, entityModel, baseTypeModel);
-            if (!!etag) {
-                data[jsonLightAnnotations.etag] = etag;
-            }
-        }
-
-        jsonLightComputeStreamLinks(data, entityModel, baseTypeModel);
-        jsonLightComputeNavigationAndAssociationProperties(data, entityModel, baseTypeModel);
-        jsonLightComputeFunctionImports(data, entryInfo);
-    };
-
-    var jsonLightComputeETag = function (data, entityModel, baseTypeModel) {
-        /// <summary>Computes the etag of an entry</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="entryInfo" type="Object">Object describing the entry model.</param>
-        /// <param name="baseTypeModel" type="Object"  optional="true">Object describing an OData conceptual schema of the baseType if it exists.</param>
-        /// <returns type="string">Etag value</returns>
-        var etag = "";
-        var propertyModel;
-        for (var i = 0; entityModel.property && i < entityModel.property.length; i++) {
-            propertyModel = entityModel.property[i];
-            etag = jsonLightAppendValueToEtag(data, etag, propertyModel);
-
-        }
-        if (baseTypeModel) {
-            for (i = 0; baseTypeModel.property && i < baseTypeModel.property.length; i++) {
-                propertyModel = baseTypeModel.property[i];
-                etag = jsonLightAppendValueToEtag(data, etag, propertyModel);
-            }
-        }
-        if (etag.length > 0) {
-            return etag + "\"";
-        }
-        return null;
-    };
-
-    var jsonLightAppendValueToEtag = function (data, etag, propertyModel) {
-        /// <summary>Adds a propery value to the etag after formatting.</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="etag" type="Object">value of the etag.</param>
-        /// <param name="propertyModel" type="Object">Object describing an OData conceptual schema of the property.</param>
-        /// <returns type="string">Etag value</returns>
-
-        if (propertyModel.concurrencyMode == "Fixed") {
-            if (etag.length > 0) {
-                etag += ",";
-            } else {
-                etag += "W/\"";
-            }
-            if (data[propertyModel.name] !== null) {
-                etag += formatLiteral(data[propertyModel.name], propertyModel.type);
-            } else {
-                etag += "null";
-            }
-        }
-        return etag;
-    };
-
-    var jsonLightComputeNavigationAndAssociationProperties = function (data, entityModel, baseTypeModel) {
-        /// <summary>Adds navigation links to the entry metadata</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="entityModel" type="Object">Object describing the entry model.</param>
-        /// <param name="baseTypeModel" type="Object"  optional="true">Object describing an OData conceptual schema of the baseType if it exists.</param>
-
-        var navigationLinkAnnotation = "@odata.navigationLinkUrl";
-        var associationLinkAnnotation = "@odata.associationLinkUrl";
-        var navigationPropertyName, navigationPropertyAnnotation, associationPropertyAnnotation;
-        for (var i = 0; entityModel.navigationProperty && i < entityModel.navigationProperty.length; i++) {
-            navigationPropertyName = entityModel.navigationProperty[i].name;
-            navigationPropertyAnnotation = navigationPropertyName + navigationLinkAnnotation;
-            if (data[navigationPropertyAnnotation] === undefined) {
-                data[navigationPropertyAnnotation] = data[jsonLightAnnotations.edit] + "/" + encodeURIComponent(navigationPropertyName);
-            }
-            associationPropertyAnnotation = navigationPropertyName + associationLinkAnnotation;
-            if (data[associationPropertyAnnotation] === undefined) {
-                data[associationPropertyAnnotation] = data[jsonLightAnnotations.edit] + "/$links/" + encodeURIComponent(navigationPropertyName);
-            }
-        }
-
-        if (baseTypeModel && baseTypeModel.navigationProperty) {
-            for (i = 0; i < baseTypeModel.navigationProperty.length; i++) {
-                navigationPropertyName = baseTypeModel.navigationProperty[i].name;
-                navigationPropertyAnnotation = navigationPropertyName + navigationLinkAnnotation;
-                if (data[navigationPropertyAnnotation] === undefined) {
-                    data[navigationPropertyAnnotation] = data[jsonLightAnnotations.edit] + "/" + encodeURIComponent(navigationPropertyName);
-                }
-                associationPropertyAnnotation = navigationPropertyName + associationLinkAnnotation;
-                if (data[associationPropertyAnnotation] === undefined) {
-                    data[associationPropertyAnnotation] = data[jsonLightAnnotations.edit] + "/$links/" + encodeURIComponent(navigationPropertyName);
-                }
-            }
-        }
-    };
-
-    var formatLiteral = function (value, type) {
-        /// <summary>Formats a value according to Uri literal format</summary>
-        /// <param name="value">Value to be formatted.</param>
-        /// <param name="type">Edm type of the value</param>
-        /// <returns type="string">Value after formatting</returns>
-
-        value = "" + formatRowLiteral(value, type);
-        value = encodeURIComponent(value.replace("'", "''"));
-        switch ((type)) {
-            case "Edm.Binary":
-                return "X'" + value + "'";
-            case "Edm.DateTime":
-                return "datetime" + "'" + value + "'";
-            case "Edm.DateTimeOffset":
-                return "datetimeoffset" + "'" + value + "'";
-            case "Edm.Decimal":
-                return value + "M";
-            case "Edm.Guid":
-                return "guid" + "'" + value + "'";
-            case "Edm.Int64":
-                return value + "L";
-            case "Edm.Float":
-                return value + "f";
-            case "Edm.Double":
-                return value + "D";
-            case "Edm.Geography":
-                return "geography" + "'" + value + "'";
-            case "Edm.Geometry":
-                return "geometry" + "'" + value + "'";
-            case "Edm.Time":
-                return "time" + "'" + value + "'";
-            case "Edm.String":
-                return "'" + value + "'";
-            default:
-                return value;
-        }
-    };
-
-
-    var formatRowLiteral = function (value, type) {
-        switch (type) {
-            case "Edm.Binary":
-                return convertByteArrayToHexString(value);
-            default:
-                return value;
-        }
-    };
-
-    var jsonLightComputeFunctionImports = function (data, entryInfo) {
-        /// <summary>Adds functions and actions links to the entry metadata</summary>
-        /// <param name="entry" type="Object">JSON light entry.</param>
-        /// <param name="entityInfo" type="Object">Object describing the entry</param>
-
-        var functionImport = entryInfo.functionImport || [];
-        for (var i = 0; i < functionImport.length; i++) {
-            if (functionImport[i].isBindable && functionImport[i].parameter[0] && functionImport[i].parameter[0].type == entryInfo.entitySet.entityType) {
-                var functionImportAnnotation = "#" + entryInfo.containerName + "." + functionImport[i].name;
-                if (data[functionImportAnnotation] == undefined) {
-                    data[functionImportAnnotation] = {
-                        title: functionImport[i].name,
-                        target: data[jsonLightAnnotations.edit] + "/" + functionImport[i].name
-                    };
-                }
-            }
-        }
-    };
-
-    var jsonLightComputeStreamLinks = function (data, entityModel, baseTypeModel) {
-        /// <summary>Adds stream links to the entry metadata</summary>
-        /// <param name="data" type="Object">JSON light entry.</param>
-        /// <param name="entityModel" type="Object">Object describing the entry model.</param>
-        /// <param name="baseTypeModel" type="Object"  optional="true">Object describing an OData conceptual schema of the baseType if it exists.</param>
-
-        if (entityModel.hasStream || (baseTypeModel && baseTypeModel.hasStream)) {
-            data[jsonLightAnnotations.mediaEdit] = data[jsonLightAnnotations.mediaEdit] || data[jsonLightAnnotations.mediaEdit] + "/$value";
-            data[jsonLightAnnotations.mediaRead] = data[jsonLightAnnotations.mediaRead] || data[jsonLightAnnotations.mediaEdit];
-        }
-    };
-
-    var jsonLightReadTopPrimitiveProperty = function (data, typeName, baseURI, recognizeDates) {
-        /// <summary>Converts a JSON light top level primitive property object into its library representation.</summary>
-        /// <param name="data" type="Object">JSON light feed object to convert.</param>
-        /// <param name="typeName" type="String">Type name of the primitive property.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Top level primitive property object.</param>
-
-        var metadata = { type: typeName };
-        var value = jsonLightReadDataItemValue(data.value, typeName, metadata, baseURI, null, null, recognizeDates);
-        return jsonLightReadDataAnnotations(data, { __metadata: metadata, value: value }, baseURI);
-    };
-
-    var jsonLightReadTopCollectionProperty = function (data, typeName, baseURI, model, recognizeDates) {
-        /// <summary>Converts a JSON light top level collection property object into its library representation.</summary>
-        /// <param name="data" type="Object">JSON light feed object to convert.</param>
-        /// <param name="typeName" type="String">Type name of the collection property.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <returns type="Object">Top level collection property object.</param>
-
-        var propertyMetadata = {};
-        var value = jsonLightReadCollectionPropertyValue(data.value, typeName, propertyMetadata, baseURI, model, recognizeDates);
-        extend(value.__metadata, propertyMetadata);
-        return jsonLightReadDataAnnotations(data, value, baseURI);
-    };
-
-    var jsonLightReadLinksDocument = function (data, baseURI) {
-        /// <summary>Converts a JSON light links collection object to its library representation.</summary>
-        /// <param name="data" type="Object">JSON light link object to convert.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <returns type="Object">Links collection object.</param>
-
-        var items = data.value;
-        if (!isArray(items)) {
-            return jsonLightReadLink(data, baseURI);
-        }
-
-        var results = [];
-        var i, len;
-        for (i = 0, len = items.length; i < len; i++) {
-            results.push(jsonLightReadLink(items[i], baseURI));
-        }
-
-        var links = { results: results };
-        return jsonLightReadDataAnnotations(data, links, baseURI);
-    };
-
-    var jsonLightReadLink = function (data, baseURI) {
-        /// <summary>Converts a JSON light link object to its library representation.</summary>
-        /// <param name="data" type="Object">JSON light link object to convert.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <returns type="Object">Link object.</param>
-
-        var link = { uri: normalizeURI(data.url, baseURI) };
-
-        link = jsonLightReadDataAnnotations(data, link, baseURI);
-        var metadata = link.__metadata || {};
-        var metadataProperties = metadata.properties || {};
-
-        jsonLightRemoveTypePropertyMetadata(metadataProperties.url);
-        renameProperty(metadataProperties, "url", "uri");
-
-        return link;
-    };
-
-    var jsonLightRemoveTypePropertyMetadata = function (propertyMetadata) {
-        /// <summary>Removes the type property from a property metadata object.</summary>
-        /// <param name="propertyMetadata" type="Object">Property metadata object.</param>
-
-        if (propertyMetadata) {
-            delete propertyMetadata.type;
-        }
-    };
-
-    var jsonLightReadSvcDocument = function (data, baseURI) {
-        /// <summary>Converts a JSON light service document object to its library representation.</summary>
-        /// <param name="data" type="Object">JSON light service document object to convert.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-        /// <returns type="Object">Link object.</param>
-
-        var items = data.value;
-        var collections = [];
-        var workspace = jsonLightReadDataAnnotations(data, { collections: collections }, baseURI);
-
-        var metadata = workspace.__metadata || {};
-        var metadataProperties = metadata.properties || {};
-
-        jsonLightRemoveTypePropertyMetadata(metadataProperties.value);
-        renameProperty(metadataProperties, "value", "collections");
-
-        var i, len;
-        for (i = 0, len = items.length; i < len; i++) {
-            var item = items[i];
-            var collection = { title: item.name, href: normalizeURI(item.url, baseURI) };
-
-            collection = jsonLightReadDataAnnotations(item, collection, baseURI);
-            metadata = collection.__metadata || {};
-            metadataProperties = metadata.properties || {};
-
-            jsonLightRemoveTypePropertyMetadata(metadataProperties.name);
-            jsonLightRemoveTypePropertyMetadata(metadataProperties.url);
-
-            renameProperty(metadataProperties, "name", "title");
-            renameProperty(metadataProperties, "url", "href");
-
-            collections.push(collection);
-        }
-
-        return { workspaces: [workspace] };
-    };
-
-    var jsonLightMakePayloadInfo = function (kind, type) {
-        /// <summary>Creates an object containing information for the json light payload.</summary>
-        /// <param name="kind" type="String">JSON light payload kind, one of the PAYLOADTYPE_XXX constant values.</param>
-        /// <param name="typeName" type="String">Type name of the JSON light payload.</param>
-        /// <returns type="Object">Object with kind and type fields.</returns>
-
-        /// <field name="kind" type="String">Kind of the JSON light payload. One of the PAYLOADTYPE_XXX constant values.</field>
-        /// <field name="type" type="String">Data type of the JSON light payload.</field>
-
-        return { kind: kind, type: type || null };
-    };
-
-    var jsonLightPayloadInfo = function (data, model, inferFeedAsComplexType) {
-        /// <summary>Infers the information describing the JSON light payload from its metadata annotation, structure, and data model.</summary>
-        /// <param name="data" type="Object">Json light response payload object.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="inferFeedAsComplexType" type="Boolean">True if a JSON light payload that looks like a feed should be treated as a complex type property instead.</param>
-        /// <remarks>
-        ///     If the arguments passed to the function don't convey enough information about the payload to determine without doubt that the payload is a feed then it
-        ///     will try to use the payload object structure instead.  If the payload looks like a feed (has value property that is an array or non-primitive values) then
-        ///     the function will report its kind as PAYLOADTYPE_FEED unless the inferFeedAsComplexType flag is set to true. This flag comes from the user request
-        ///     and allows the user to control how the library behaves with an ambigous JSON light payload.
-        /// </remarks>
-        /// <returns type="Object">
-        ///     Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
-        /// </returns>
-
-        var metadataUri = data[metadataAnnotation];
-        if (!metadataUri || typeof metadataUri !== "string") {
-            return null;
-        }
-
-        var fragmentStart = metadataUri.lastIndexOf("#");
-        if (fragmentStart === -1) {
-            return jsonLightMakePayloadInfo(PAYLOADTYPE_SVCDOC);
-        }
-
-        var elementStart = metadataUri.indexOf("@Element", fragmentStart);
-        var fragmentEnd = elementStart - 1;
-
-        if (fragmentEnd < 0) {
-            fragmentEnd = metadataUri.indexOf("?", fragmentStart);
-            if (fragmentEnd === -1) {
-                fragmentEnd = metadataUri.length;
-            }
-        }
-
-        var fragment = metadataUri.substring(fragmentStart + 1, fragmentEnd);
-        if (fragment.indexOf("/$links/") > 0) {
-            return jsonLightMakePayloadInfo(PAYLOADTYPE_LINKS);
-        }
-
-        var fragmentParts = fragment.split("/");
-        if (fragmentParts.length >= 0) {
-            var qualifiedName = fragmentParts[0];
-            var typeCast = fragmentParts[1];
-
-            if (jsonLightIsPrimitiveType(qualifiedName)) {
-                return jsonLightMakePayloadInfo(PAYLOADTYPE_PRIMITIVE, qualifiedName);
-            }
-
-            if (isCollectionType(qualifiedName)) {
-                return jsonLightMakePayloadInfo(PAYLOADTYPE_COLLECTION, qualifiedName);
-            }
-
-            var entityType = typeCast;
-            var entitySet, functionImport, containerName;
-            if (!typeCast) {
-                var nsEnd = qualifiedName.lastIndexOf(".");
-                var simpleName = qualifiedName.substring(nsEnd + 1);
-                var container = (simpleName === qualifiedName) ?
-                    lookupDefaultEntityContainer(model) :
-                    lookupEntityContainer(qualifiedName.substring(0, nsEnd), model);
-
-                if (container) {
-                    entitySet = lookupEntitySet(container.entitySet, simpleName);
-                    functionImport = container.functionImport;
-                    containerName = container.name;
-                    entityType = !!entitySet ? entitySet.entityType : null;
-                }
-            }
-
-            var info;
-            if (elementStart > 0) {
-                info = jsonLightMakePayloadInfo(PAYLOADTYPE_OBJECT, entityType);
-                info.entitySet = entitySet;
-                info.functionImport = functionImport;
-                info.containerName = containerName;
-                return info;
-            }
-
-            if (entityType) {
-                info = jsonLightMakePayloadInfo(PAYLOADTYPE_FEED, entityType);
-                info.entitySet = entitySet;
-                info.functionImport = functionImport;
-                info.containerName = containerName;
-                return info;
-            }
-
-            if (isArray(data.value) && !lookupComplexType(qualifiedName, model)) {
-                var item = data.value[0];
-                if (!isPrimitive(item)) {
-                    if (jsonLightIsEntry(item) || !inferFeedAsComplexType) {
-                        return jsonLightMakePayloadInfo(PAYLOADTYPE_FEED, null);
-                    }
-                }
-            }
-
-            return jsonLightMakePayloadInfo(PAYLOADTYPE_OBJECT, qualifiedName);
-        }
-
-        return null;
-    };
-
-    var jsonLightReadPayload = function (data, model, recognizeDates, inferFeedAsComplexType, contentTypeOdata) {
-        /// <summary>Converts a JSON light response payload object into its library's internal representation.</summary>
-        /// <param name="data" type="Object">Json light response payload object.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-        /// <param name="inferFeedAsComplexType" type="Boolean">True if a JSON light payload that looks like a feed should be reported as a complex type property instead.</param>
-        /// <param name="contentTypeOdata" type="string">Includes the type of json ( minimalmetadata, fullmetadata .. etc )</param>
-        /// <returns type="Object">Object in the library's representation.</returns>
-
-        if (!isComplex(data)) {
-            return data;
-        }
-
-        contentTypeOdata = contentTypeOdata || "minimalmetadata";
-        var baseURI = data[metadataAnnotation];
-        var payloadInfo = jsonLightPayloadInfo(data, model, inferFeedAsComplexType);
-        if (assigned(payloadInfo)) {
-            payloadInfo.contentTypeOdata = contentTypeOdata;
-        }
-        var typeName = null;
-        if (payloadInfo) {
-            delete data[metadataAnnotation];
-
-            typeName = payloadInfo.type;
-            switch (payloadInfo.kind) {
-                case PAYLOADTYPE_FEED:
-                    return jsonLightReadFeed(data, payloadInfo, baseURI, model, recognizeDates);
-                case PAYLOADTYPE_COLLECTION:
-                    return jsonLightReadTopCollectionProperty(data, typeName, baseURI, model, recognizeDates);
-                case PAYLOADTYPE_PRIMITIVE:
-                    return jsonLightReadTopPrimitiveProperty(data, typeName, baseURI, recognizeDates);
-                case PAYLOADTYPE_SVCDOC:
-                    return jsonLightReadSvcDocument(data, baseURI);
-                case PAYLOADTYPE_LINKS:
-                    return jsonLightReadLinksDocument(data, baseURI);
-            }
-        }
-        return jsonLightReadObject(data, payloadInfo, baseURI, model, recognizeDates);
-    };
-
-    var jsonLightSerializableMetadata = ["type", "etag", "media_src", "edit_media", "content_type", "media_etag"];
-
-    var formatJsonLight = function (obj, context) {
-        /// <summary>Converts an object in the library's internal representation to its json light representation.</summary>
-        /// <param name="obj" type="Object">Object the library's internal representation.</param>
-        /// <param name="context" type="Object">Object with the serialization context.</param>
-        /// <returns type="Object">Object in its json light representation.</returns>
-
-        // Regular expression used to test that the uri is for a $links document.
-        var linksUriRE = /\/\$links\//;
-        var data = {};
-        var metadata = obj.__metadata;
-
-        var islinks = context && linksUriRE.test(context.request.requestUri);
-        formatJsonLightData(obj, (metadata && metadata.properties), data, islinks);
-        return data;
-    };
-
-    var formatJsonLightMetadata = function (metadata, data) {
-        /// <summary>Formats an object's metadata into the appropriate json light annotations and saves them to data.</summary>
-        /// <param name="obj" type="Object">Object whose metadata is going to be formatted as annotations.</param>
-        /// <param name="data" type="Object">Object on which the annotations are going to be stored.</param>
-
-        if (metadata) {
-            var i, len;
-            for (i = 0, len = jsonLightSerializableMetadata.length; i < len; i++) {
-                // There is only a subset of metadata values that are interesting during update requests.
-                var name = jsonLightSerializableMetadata[i];
-                var qName = odataAnnotationPrefix + (jsonLightNameMap[name] || name);
-                formatJsonLightAnnotation(qName, null, metadata[name], data);
-            }
-        }
-    };
-
-    var formatJsonLightData = function (obj, pMetadata, data, isLinks) {
-        /// <summary>Formats an object's data into the appropriate json light values and saves them to data.</summary>
-        /// <param name="obj" type="Object">Object whose data is going to be formatted.</param>
-        /// <param name="pMetadata" type="Object">Object that contains metadata for the properties that are being formatted.</param>
-        /// <param name="data" type="Object">Object on which the formatted values are going to be stored.</param>
-        /// <param name="isLinks" type="Boolean">True if a links document is being formatted.  False otherwise.</param>
-
-        for (var key in obj) {
-            var value = obj[key];
-            if (key === "__metadata") {
-                // key is the object metadata.
-                formatJsonLightMetadata(value, data);
-            } else if (key.indexOf(".") === -1) {
-                // key is an regular property or array element.
-                if (isLinks && key === "uri") {
-                    formatJsonLightEntityLink(value, data);
-                } else {
-                    formatJsonLightProperty(key, value, pMetadata, data, isLinks);
-                }
-            } else {
-                data[key] = value;
-            }
-        }
-    };
-
-    var formatJsonLightProperty = function (name, value, pMetadata, data) {
-        /// <summary>Formats an object's value identified by name to its json light representation and saves it to data.</summary>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="value">Property value.</param>
-        /// <param name="pMetadata" type="Object">Object that contains metadata for the property that is being formatted.</param>
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        // Get property type from property metadata
-        var propertyMetadata = pMetadata && pMetadata[name] || { properties: undefined, type: undefined };
-        var typeName = dataItemTypeName(value, propertyMetadata);
-
-        if (isPrimitive(value) || !value) {
-            // It is a primitive value then.
-            formatJsonLightAnnotation(typeAnnotation, name, typeName, data);
-            data[name] = value;
-            return;
-        }
-
-        if (isFeed(value, typeName) || isEntry(value)) {
-            formatJsonLightInlineProperty(name, value, data);
-            return;
-        }
-
-        if (!typeName && isDeferred(value)) {
-            // It is really a deferred property.
-            formatJsonLightDeferredProperty(name, value, data);
-            return;
-        }
-
-        if (isCollection(value, typeName)) {
-            // The thing is a collection, format it as one.
-            if (getCollectionType(typeName)) {
-                formatJsonLightAnnotation(typeAnnotation, name, typeName, data);
-            }
-            formatJsonLightCollectionProperty(name, value, data);
-            return;
-        }
-
-
-        // Format the complex property value in a new object in data[name].
-        data[name] = {};
-        formatJsonLightAnnotation(typeAnnotation, null, typeName, data[name]);
-        formatJsonLightData(value, propertyMetadata.properties, data[name]);
-    };
-
-    var formatJsonLightEntityLink = function (value, data) {
-        /// <summary>Formats an entity link in a $links document and saves it into data.</summary>
-        /// <param name="value" type="String">Entity link value.</summary>
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-        data.url = value;
-    };
-
-    var formatJsonLightDeferredProperty = function (name, value, data) {
-        /// <summary>Formats the object value's identified by name as an odata.navigalinkurl annotation and saves it to data.</summary>
-        /// <param name="name" type="String">Name of the deferred property to be formatted.</param>
-        /// <param name="value" type="Object">Deferred property value to be formatted.</param>
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        formatJsonLightAnnotation(navUrlAnnotation, name, value.__deferred.uri, data);
-    };
-
-    var formatJsonLightCollectionProperty = function (name, value, data) {
-        /// <summary>Formats a collection property in obj identified by name as a json light collection property and saves it to data.</summary>
-        /// <param name="name" type="String">Name of the collection property to be formatted.</param>
-        /// <param name="value" type="Object">Collection property value to be formatted.</param>
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        data[name] = [];
-        var items = isArray(value) ? value : value.results;
-        formatJsonLightData(items, null, data[name]);
-    };
-
-    var formatJsonLightInlineProperty = function (name, value, data) {
-        /// <summary>Formats an inline feed or entry property in obj identified by name as a json light value and saves it to data.</summary>
-        /// <param name="name" type="String">Name of the inline feed or entry property to be formatted.</param>
-        /// <param name="value" type="Object or Array">Value of the inline feed or entry property.</param>
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        if (isFeed(value)) {
-            data[name] = [];
-            // Format each of the inline feed entries
-            var entries = isArray(value) ? value : value.results;
-            var i, len;
-            for (i = 0, len = entries.length; i < len; i++) {
-                formatJsonLightInlineEntry(name, entries[i], true, data);
-            }
-            return;
-        }
-        formatJsonLightInlineEntry(name, value, false, data);
-    };
-
-    var formatJsonLightInlineEntry = function (name, value, inFeed, data) {
-        /// <summary>Formats an inline entry value in the property identified by name as a json light value and saves it to data.</summary>
-        /// <param name="name" type="String">Name of the inline feed or entry property that owns the entry formatted.</param>
-        /// <param name="value" type="Object">Inline entry value to be formatted.</param>
-        /// <param name="inFeed" type="Boolean">True if the entry is in an inline feed; false otherwise.
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        // This might be a bind instead of a deep insert.
-        var uri = value.__metadata && value.__metadata.uri;
-        if (uri) {
-            formatJsonLightBinding(name, uri, inFeed, data);
-            return;
-        }
-
-        var entry = formatJsonLight(value);
-        if (inFeed) {
-            data[name].push(entry);
-            return;
-        }
-        data[name] = entry;
-    };
-
-    var formatJsonLightBinding = function (name, uri, inFeed, data) {
-        /// <summary>Formats an entry binding in the inline property in obj identified by name as an odata.bind annotation and saves it to data.</summary>
-        /// <param name="name" type="String">Name of the inline property that has the binding to be formated.</param>
-        /// <param name="uri" type="String">Uri to the bound entry.</param>
-        /// <param name="inFeed" type="Boolean">True if the binding is in an inline feed; false otherwise.
-        /// <param name="data" type="Object">Object on which the formatted value is going to be stored.</param>
-
-        var bindingName = name + bindAnnotation;
-        if (inFeed) {
-            // The binding is inside an inline feed, so merge it with whatever other bindings already exist in data.
-            data[bindingName] = data[bindingName] || [];
-            data[bindingName].push(uri);
-            return;
-        }
-        // The binding is on an inline entry; it can be safely overwritten.
-        data[bindingName] = uri;
-    };
-
-    var formatJsonLightAnnotation = function (qName, target, value, data) {
-        /// <summary>Formats a value as a json light annotation and stores it in data</summary>
-        /// <param name="qName" type="String">Qualified name of the annotation.</param>
-        /// <param name="target" type="String">Name of the property that the metadata value targets.</param>
-        /// <param name="value">Annotation value.</param>
-        /// <param name="data" type="Object">Object on which the annotation is going to be stored.</param>
-
-        if (value !== undefined) {
-            if(target) {
-                data[target + "@" + qName] = value;
-            }
-            else {
-                data[qName] = value;
-            }
-        }
-    };
-
-
-
-    var jsonMediaType = "application/json";
-    var jsonContentType = contentType(jsonMediaType);
-
-    var jsonReadAdvertisedActionsOrFunctions = function (value) {
-        /// <summary>Reads and object containing action or function metadata and maps them into a single array of objects.</summary>
-        /// <param name="value" type="Object">Object containing action or function metadata.</param>
-        /// <returns type="Array">Array of objects containing metadata for the actions or functions specified in value.</returns>
-
-        var result = [];
-        for (var name in value) {
-            var i, len;
-            for (i = 0, len = value[name].length; i < len; i++) {
-                result.push(extend({ metadata: name }, value[name][i]));
-            }
-        }
-        return result;
-    };
-
-    var jsonApplyMetadata = function (value, metadata, dateParser, recognizeDates) {
-        /// <summary>Applies metadata coming from both the payload and the metadata object to the value.</summary>
-        /// <param name="value" type="Object">Data on which the metada is going to be applied.</param>
-        /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param>
-        /// <param name="dateParser" type="function">Function used for parsing datetime values.</param>
-        /// <param name="recognizeDates" type="Boolean">
-        ///     True if strings formatted as datetime values should be treated as datetime values. False otherwise.
-        /// </param>
-        /// <returns type="Object">Transformed data.</returns>
-
-        if (value && typeof value === "object") {
-            var dataTypeName;
-            var valueMetadata = value.__metadata;
-
-            if (valueMetadata) {
-                if (valueMetadata.actions) {
-                    valueMetadata.actions = jsonReadAdvertisedActionsOrFunctions(valueMetadata.actions);
-                }
-                if (valueMetadata.functions) {
-                    valueMetadata.functions = jsonReadAdvertisedActionsOrFunctions(valueMetadata.functions);
-                }
-                dataTypeName = valueMetadata && valueMetadata.type;
-            }
-
-            var dataType = lookupEntityType(dataTypeName, metadata) || lookupComplexType(dataTypeName, metadata);
-            var propertyValue;
-            if (dataType) {
-                var properties = dataType.property;
-                if (properties) {
-                    var i, len;
-                    for (i = 0, len = properties.length; i < len; i++) {
-                        var property = properties[i];
-                        var propertyName = property.name;
-                        propertyValue = value[propertyName];
-
-                        if (property.type === "Edm.DateTime" || property.type === "Edm.DateTimeOffset") {
-                            if (propertyValue) {
-                                propertyValue = dateParser(propertyValue);
-                                if (!propertyValue) {
-                                    throw { message: "Invalid date/time value" };
-                                }
-                                value[propertyName] = propertyValue;
-                            }
-                        } else if (property.type === "Edm.Time") {
-                            value[propertyName] = parseDuration(propertyValue);
-                        }
-                    }
-                }
-            } else if (recognizeDates) {
-                for (var name in value) {
-                    propertyValue = value[name];
-                    if (typeof propertyValue === "string") {
-                        value[name] = dateParser(propertyValue) || propertyValue;
-                    }
-                }
-            }
-        }
-        return value;
-    };
-
-    var isJsonLight = function (contentType) {
-        /// <summary>Tests where the content type indicates a json light payload.</summary>
-        /// <param name="contentType">Object with media type and properties dictionary.</param>
-        /// <returns type="Boolean">True is the content type indicates a json light payload. False otherwise.</returns>
-
-        if (contentType) {
-            var odata = contentType.properties.odata;
-            return odata === "nometadata" || odata === "minimalmetadata" || odata === "fullmetadata";
-        }
-        return false;
-    };
-
-    var normalizeServiceDocument = function (data, baseURI) {
-        /// <summary>Normalizes a JSON service document to look like an ATOM service document.</summary>
-        /// <param name="data" type="Object">Object representation of service documents as deserialized.</param>
-        /// <param name="baseURI" type="String">Base URI to resolve relative URIs.</param>
-        /// <returns type="Object">An object representation of the service document.</returns>
-        var workspace = { collections: [] };
-
-        var i, len;
-        for (i = 0, len = data.EntitySets.length; i < len; i++) {
-            var title = data.EntitySets[i];
-            var collection = {
-                title: title,
-                href: normalizeURI(title, baseURI)
-            };
-
-            workspace.collections.push(collection);
-        }
-
-        return { workspaces: [workspace] };
-    };
-
-    // 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+)?\)\/$/;
-
-    var minutesToOffset = function (minutes) {
-        /// <summary>Formats the given minutes into (+/-)hh:mm format.</summary>
-        /// <param name="minutes" type="Number">Number of minutes to format.</param>
-        /// <returns type="String">The minutes in (+/-)hh:mm format.</returns>
-
-        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);
-    };
-
-    var parseJsonDateString = function (value) {
-        /// <summary>Parses the JSON Date representation into a Date object.</summary>
-        /// <param name="value" type="String">String value.</param>
-        /// <returns type="Date">A Date object if the value matches one; falsy otherwise.</returns>
-
-        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.
-
-    var jsonParser = function (handler, text, context) {
-        /// <summary>Parses a JSON OData payload.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text">Payload text (this parser also handles pre-parsed objects).</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An object representation of the OData payload.</returns>
-
-        var recognizeDates = defined(context.recognizeDates, handler.recognizeDates);
-        var inferJsonLightFeedAsObject = defined(context.inferJsonLightFeedAsObject, handler.inferJsonLightFeedAsObject);
-        var model = context.metadata;
-        var dataServiceVersion = context.dataServiceVersion;
-        var dateParser = parseJsonDateString;
-        var json = (typeof text === "string") ? window.JSON.parse(text) : text;
-
-        if ((maxVersion("3.0", dataServiceVersion) === dataServiceVersion)) {
-            if (isJsonLight(context.contentType)) {
-                return jsonLightReadPayload(json, model, recognizeDates, inferJsonLightFeedAsObject, context.contentType.properties.odata);
-            }
-            dateParser = parseDateTime;
-        }
-
-        json = traverse(json.d, function (key, value) {
-            return jsonApplyMetadata(value, model, dateParser, recognizeDates);
-        });
-
-        json = jsonUpdateDataFromVersion(json, context.dataServiceVersion);
-        return jsonNormalizeData(json, context.response.requestUri);
-    };
-
-    var jsonToString = function (data) {
-        /// <summary>Converts the data into a JSON string.</summary>
-        /// <param name="data">Data to serialize.</param>
-        /// <returns type="String">The JSON string representation of data.</returns>
-
-        var result; // = undefined;
-        // Save the current date.toJSON function
-        var dateToJSON = Date.prototype.toJSON;
-        try {
-            // Set our own date.toJSON function
-            Date.prototype.toJSON = function () {
-                return formatDateTimeOffset(this);
-            };
-            result = window.JSON.stringify(data, jsonReplacer);
-        } finally {
-            // Restore the original toJSON function
-            Date.prototype.toJSON = dateToJSON;
-        }
-        return result;
-    };
-
-    var jsonSerializer = function (handler, data, context) {
-        /// <summary>Serializes the data by returning its string representation.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="data">Data to serialize.</param>
-        /// <param name="context" type="Object">Object with serialization context.</param>
-        /// <returns type="String">The string representation of data.</returns>
-
-        var dataServiceVersion = context.dataServiceVersion || "1.0";
-        var useJsonLight = defined(context.useJsonLight, handler.useJsonLight);
-        var cType = context.contentType = context.contentType || jsonContentType;
-
-        if (cType && cType.mediaType === jsonContentType.mediaType) {
-            var json = data;
-            if (useJsonLight || isJsonLight(cType)) {
-                context.dataServiceVersion = maxVersion(dataServiceVersion, "3.0");
-                json = formatJsonLight(data, context);
-                return jsonToString(json);
-            }
-            if (maxVersion("3.0", dataServiceVersion) === dataServiceVersion) {
-                cType.properties.odata = "verbose";
-                context.contentType = cType;
-            }
-            return jsonToString(json);
-        }
-        return undefined;
-    };
-
-    var jsonReplacer = function (_, value) {
-        /// <summary>JSON replacer function for converting a value to its JSON representation.</summary>
-        /// <param value type="Object">Value to convert.</param>
-        /// <returns type="String">JSON representation of the input value.</returns>
-        /// <remarks>
-        ///   This method is used during JSON serialization and invoked only by the JSON.stringify function.
-        ///   It should never be called directly.
-        /// </remarks>
-
-        if (value && value.__edmType === "Edm.Time") {
-            return formatDuration(value);
-        } else {
-            return value;
-        }
-    };
-
-    var jsonNormalizeData = function (data, baseURI) {
-        /// <summary>
-        /// Normalizes the specified data into an intermediate representation.
-        /// like the latest supported version.
-        /// </summary>
-        /// <param name="data" optional="false">Data to update.</param>
-        /// <param name="baseURI" optional="false">URI to use as the base for normalizing references.</param>
-
-        var isSvcDoc = isComplex(data) && !data.__metadata && isArray(data.EntitySets);
-        return isSvcDoc ? normalizeServiceDocument(data, baseURI) : data;
-    };
-
-    var jsonUpdateDataFromVersion = function (data, dataVersion) {
-        /// <summary>
-        /// Updates the specified data in the specified version to look
-        /// like the latest supported version.
-        /// </summary>
-        /// <param name="data" optional="false">Data to update.</param>
-        /// <param name="dataVersion" optional="true" type="String">Version the data is in (possibly unknown).</param>
-
-        // Strip the trailing comma if there.
-        if (dataVersion && dataVersion.lastIndexOf(";") === dataVersion.length - 1) {
-            dataVersion = dataVersion.substr(0, dataVersion.length - 1);
-        }
-
-        if (!dataVersion || dataVersion === "1.0") {
-            if (isArray(data)) {
-                data = { results: data };
-            }
-        }
-
-        return data;
-    };
-
-    var jsonHandler = handler(jsonParser, jsonSerializer, jsonMediaType, MAX_DATA_SERVICE_VERSION);
-    jsonHandler.recognizeDates = false;
-    jsonHandler.useJsonLight = false;
-    jsonHandler.inferJsonLightFeedAsObject = false;
-
-    odata.jsonHandler = jsonHandler;
-
-
-
-
-    var batchMediaType = "multipart/mixed";
-    var responseStatusRegex = /^HTTP\/1\.\d (\d{3}) (.*)$/i;
-    var responseHeaderRegex = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/;
-
-    var hex16 = function () {
-        /// <summary>
-        /// Calculates a random 16 bit number and returns it in hexadecimal format.
-        /// </summary>
-        /// <returns type="String">A 16-bit number in hex format.</returns>
-
-        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substr(1);
-    };
-
-    var createBoundary = function (prefix) {
-        /// <summary>
-        /// Creates a string that can be used as a multipart request boundary.
-        /// </summary>
-        /// <param name="prefix" type="String" optional="true">String to use as the start of the boundary string</param>
-        /// <returns type="String">Boundary string of the format: <prefix><hex16>-<hex16>-<hex16></returns>
-
-        return prefix + hex16() + "-" + hex16() + "-" + hex16();
-    };
-
-    var partHandler = function (context) {
-        /// <summary>
-        /// Gets the handler for data serialization of individual requests / responses in a batch.
-        /// </summary>
-        /// <param name="context">Context used for data serialization.</param>
-        /// <returns>Handler object.</returns>
-
-        return context.handler.partHandler;
-    };
-
-    var currentBoundary = function (context) {
-        /// <summary>
-        /// Gets the current boundary used for parsing the body of a multipart response.
-        /// </summary>
-        /// <param name="context">Context used for parsing a multipart response.</param>
-        /// <returns type="String">Boundary string.</returns>
-
-        var boundaries = context.boundaries;
-        return boundaries[boundaries.length - 1];
-    };
-
-    var batchParser = function (handler, text, context) {
-        /// <summary>Parses a batch response.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text" type="String">Batch text.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An object representation of the batch.</returns>
-
-        var boundary = context.contentType.properties["boundary"];
-        return { __batchResponses: readBatch(text, { boundaries: [boundary], handlerContext: context }) };
-    };
-
-    var batchSerializer = function (handler, data, context) {
-        /// <summary>Serializes a batch object representation into text.</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="data" type="Object">Representation of a batch.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An text representation of the batch object; undefined if not applicable.</returns>
-
-        var cType = context.contentType = context.contentType || contentType(batchMediaType);
-        if (cType.mediaType === batchMediaType) {
-            return writeBatch(data, context);
-        }
-    };
-
-    var readBatch = function (text, context) {
-        /// <summary>
-        /// Parses a multipart/mixed response body from from the position defined by the context.
-        /// </summary>
-        /// <param name="text" type="String" optional="false">Body of the multipart/mixed response.</param>
-        /// <param name="context">Context used for parsing.</param>
-        /// <returns>Array of objects representing the individual responses.</returns>
-
-        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;
-    };
-
-    var readHeaders = function (text, context) {
-        /// <summary>
-        /// Parses the http headers in the text from the position defined by the context.
-        /// </summary>
-        /// <param name="text" type="String" optional="false">Text containing an http response's headers</param>
-        /// <param name="context">Context used for parsing.</param>
-        /// <returns>Object containing the headers as key value pairs.</returns>
-        /// <remarks>
-        /// This function doesn't support split headers and it will stop reading when it hits two consecutive line breaks.
-        /// </remarks>
-
-        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;
-    };
-
-    var readResponse = function (text, context, delimiter) {
-        /// <summary>
-        /// Parses an HTTP response.
-        /// </summary>
-        /// <param name="text" type="String" optional="false">Text representing the http response.</param>
-        /// <param name="context" optional="false">Context used for parsing.</param>
-        /// <param name="delimiter" type="String" optional="false">String used as delimiter of the multipart response parts.</param>
-        /// <returns>Object representing the http response.</returns>
-
-        // 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)
-        };
-    };
-
-    var readLine = function (text, context) {
-        /// <summary>
-        /// Returns a substring from the position defined by the context up to the next line break (CRLF).
-        /// </summary>
-        /// <param name="text" type="String" optional="false">Input string.</param>
-        /// <param name="context" optional="false">Context used for reading the input string.</param>
-        /// <returns type="String">Substring to the first ocurrence of a line break or null if none can be found. </returns>
-
-        return readTo(text, context, "\r\n");
-    };
-
-    var readTo = function (text, context, str) {
-        /// <summary>
-        /// 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.
-        /// </summary>
-        /// <param name="text" type="String" optional="false">Input string.</param>
-        /// <param name="context" type="Object" optional="false">Context used for reading the input string.</param>
-        /// <param name="str" type="String" optional="true">Substring to read up to.</param>
-        /// <returns type="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.</returns>
-
-        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);
-    };
-
-    var writeBatch = function (data, context) {
-        /// <summary>
-        /// Serializes a batch request object to a string.
-        /// </summary>
-        /// <param name="data" optional="false">Batch request object in payload representation format</param>
-        /// <param name="context" optional="false">Context used for the serialization</param>
-        /// <returns type="String">String representing the batch request</returns>
-
-        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;
-    };
-
-    var writeBatchPartDelimiter = function (boundary, close) {
-        /// <summary>
-        /// Creates the delimiter that indicates that start or end of an individual request.
-        /// </summary>
-        /// <param name="boundary" type="String" optional="false">Boundary string used to indicate the start of the request</param>
-        /// <param name="close" type="Boolean">Flag indicating that a close delimiter string should be generated</param>
-        /// <returns type="String">Delimiter string</returns>
-
-        var result = "\r\n--" + boundary;
-        if (close) {
-            result += "--";
-        }
-
-        return result + "\r\n";
-    };
-
-    var writeBatchPart = function (part, context, nested) {
-        /// <summary>
-        /// 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.
-        /// </summary>
-        /// <param name="part" optional="false">Request or change set object in payload representation format</param>
-        /// <param name="context" optional="false">Object containing context information used for the serialization</param>
-        /// <param name="nested" type="boolean" optional="true">Flag indicating that the part is nested inside a change set</param>
-        /// <returns type="String">String representing the serialized part</returns>
-        /// <remarks>
-        /// A change set is an array of request objects and they cannot be nested inside other change sets.
-        /// </remarks>
-
-        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;
-    };
-
-    var writeRequest = function (request) {
-        /// <summary>
-        /// Serializes a request object to a string.
-        /// </summary>
-        /// <param name="request" optional="false">Request object to serialize</param>
-        /// <returns type="String">String representing the serialized request</returns>
-
-        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;
-    };
-
-    odata.batchHandler = handler(batchParser, batchSerializer, batchMediaType, MAX_DATA_SERVICE_VERSION);
-
-
-
-    var handlers = [odata.jsonHandler, odata.atomHandler, odata.xmlHandler, odata.textHandler];
-
-    var dispatchHandler = function (handlerMethod, requestOrResponse, context) {
-        /// <summary>Dispatches an operation to handlers.</summary>
-        /// <param name="handlerMethod" type="String">Name of handler method to invoke.</param>
-        /// <param name="requestOrResponse" type="Object">request/response argument for delegated call.</param>
-        /// <param name="context" type="Object">context argument for delegated call.</param>
-
-        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" };
-        }
-    };
-
-    odata.defaultSuccess = function (data) {
-        /// <summary>Default success handler for OData.</summary>
-        /// <param name="data">Data to process.</param>
-
-        window.alert(window.JSON.stringify(data));
-    };
-
-    odata.defaultError = throwErrorCallback;
-
-    odata.defaultHandler = {
-        read: function (response, context) {
-            /// <summary>Reads the body of the specified response by delegating to JSON and ATOM handlers.</summary>
-            /// <param name="response">Response object.</param>
-            /// <param name="context">Operation context.</param>
-
-            if (response && assigned(response.body) && response.headers["Content-Type"]) {
-                dispatchHandler("read", response, context);
-            }
-        },
-
-        write: function (request, context) {
-            /// <summary>Write the body of the specified request by delegating to JSON and ATOM handlers.</summary>
-            /// <param name="request">Reques tobject.</param>
-            /// <param name="context">Operation context.</param>
-
-            dispatchHandler("write", request, context);
-        },
-
-        maxDataServiceVersion: MAX_DATA_SERVICE_VERSION,
-        accept: "application/atomsvc+xml;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1"
-    };
-
-    odata.defaultMetadata = [];
-
-    odata.read = function (urlOrRequest, success, error, handler, httpClient, metadata) {
-        /// <summary>Reads data from the specified URL.</summary>
-        /// <param name="urlOrRequest">URL to read data from.</param>
-        /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
-        /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
-        /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
-        /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
-        /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>
-
-        var request;
-        if (urlOrRequest instanceof String || typeof urlOrRequest === "string") {
-            request = { requestUri: urlOrRequest };
-        } else {
-            request = urlOrRequest;
-        }
-
-        return odata.request(request, success, error, handler, httpClient, metadata);
-    };
-
-    odata.request = function (request, success, error, handler, httpClient, metadata) {
-        /// <summary>Sends a request containing OData payload to a server.</summary>
-        /// <param name="request" type="Object">Object that represents the request to be sent.</param>
-        /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
-        /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
-        /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
-        /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
-        /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>
-
-        success = success || odata.defaultSuccess;
-        error = error || odata.defaultError;
-        handler = handler || odata.defaultHandler;
-        httpClient = httpClient || odata.defaultHttpClient;
-        metadata = metadata || odata.defaultMetadata;
-
-        // Augment the request with additional defaults.
-        request.recognizeDates = defined(request.recognizeDates, odata.jsonHandler.recognizeDates);
-        request.callbackParameterName = defined(request.callbackParameterName, odata.defaultHttpClient.callbackParameterName);
-        request.formatQueryString = defined(request.formatQueryString, odata.defaultHttpClient.formatQueryString);
-        request.enableJsonpCallback = defined(request.enableJsonpCallback, odata.defaultHttpClient.enableJsonpCallback);
-        request.useJsonLight = defined(request.useJsonLight, odata.jsonHandler.enableJsonpCallback);
-        request.inferJsonLightFeedAsObject = defined(request.inferJsonLightFeedAsObject, odata.jsonHandler.inferJsonLightFeedAsObject);
-
-        // 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,
-            useJsonLight: request.useJsonLight,
-            inferJsonLightFeedAsObject: request.inferJsonLightFeedAsObject
-        };
-
-        try {
-            prepareRequest(request, handler, context);
-            return invokeRequest(request, success, error, handler, httpClient, context);
-        } catch (err) {
-            error(err);
-        }
-    };
-
-    odata.parseMetadata = function (csdlMetadataDocument) {
-        /// <summary>Parses the csdl metadata to DataJS metatdata format. This method can be used when the metadata is retrieved using something other than DataJS</summary>
-        /// <param name="atomMetadata" type="string">A string that represents the entire csdl metadata.</param>
-        /// <returns type="Object">An object that has the representation of the metadata in Datajs format.</returns>
-
-        return metadataParser(null, csdlMetadataDocument);
-    };
-
-    // Configure the batch handler to use the default handler for the batch parts.
-    odata.batchHandler.partHandler = odata.defaultHandler;
-
-
-
-    var localStorage = null;
-
-    var domStoreDateToJSON = function () {
-        /// <summary>Converts a Date object into an object representation friendly to JSON serialization.</summary>
-        /// <returns type="Object">Object that represents the Date.</returns>
-        /// <remarks>
-        ///   This method is used to override the Date.toJSON method and is called only by
-        ///   JSON.stringify.  It should never be called directly.
-        /// </remarks>
-
-        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;
-    };
-
-    var domStoreJSONToDate = function (_, value) {
-        /// <summary>JSON reviver function for converting an object representing a Date in a JSON stream to a Date object</summary>
-        /// <param value="Object">Object to convert.</param>
-        /// <returns type="Date">Date object.</returns>
-        /// <remarks>
-        ///   This method is used during JSON parsing and invoked only by the reviver function.
-        ///   It should never be called directly.
-        /// </remarks>
-
-        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;
-    };
-
-    var qualifyDomStoreKey = function (store, key) {
-        /// <summary>Qualifies the key with the name of the store.</summary>
-        /// <param name="store" type="Object">Store object whose name will be used for qualifying the key.</param>
-        /// <param name="key" type="String">Key string.</param>
-        /// <returns type="String">Fully qualified key string.</returns>
-
-        return store.name + "#!#" + key;
-    };
-
-    var unqualifyDomStoreKey = function (store, key) {
-        /// <summary>Gets the key part of a fully qualified key string.</summary>
-        /// <param name="store" type="Object">Store object whose name will be used for qualifying the key.</param>
-        /// <param name="key" type="String">Fully qualified key string.</param>
-        /// <returns type="String">Key part string</returns>
-
-        return key.replace(store.name + "#!#", "");
-    };
-
-    var DomStore = function (name) {
-        /// <summary>Constructor for store objects that use DOM storage as the underlying mechanism.</summary>
-        /// <param name="name" type="String">Store name.</param>
-        this.name = name;
-    };
-
-    DomStore.create = function (name) {
-        /// <summary>Creates a store object that uses DOM Storage as its underlying mechanism.</summary>
-        /// <param name="name" type="String">Store name.</param>
-        /// <returns type="Object">Store object.</returns>
-
-        if (DomStore.isSupported()) {
-            localStorage = localStorage || window.localStorage;
-            return new DomStore(name);
-        }
-
-        throw { message: "Web Storage not supported by the browser" };
-    };
-
-    DomStore.isSupported = function () {
-        /// <summary>Checks whether the underlying mechanism for this kind of store objects is supported by the browser.</summary>
-        /// <returns type="Boolean">True if the mechanism is supported by the browser; otherwise false.</summary>
-        return !!window.localStorage;
-    };
-
-    DomStore.prototype.add = function (key, value, success, error) {
-        /// <summary>Adds a new value identified by a key to the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="value">Value that is going to be added to the store.</param>
-        /// <param name="success" type="Function" optional="no">Callback for a successful add operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        /// <remarks>
-        ///    This method errors out if the store already contains the specified key.
-        /// </remarks>
-
-        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);
-    };
-
-    DomStore.prototype.addOrUpdate = function (key, value, success, error) {
-        /// <summary>Adds or updates a value identified by a key to the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="value">Value that is going to be added or updated to the store.</param>
-        /// <param name="success" type="Function" optional="no">Callback for a successful add or update operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        /// <remarks>
-        ///   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.
-        /// </remarks>
-
-        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;
-            }
-        }
-    };
-
-    DomStore.prototype.clear = function (success, error) {
-        /// <summary>Removes all the data associated with this store object.</summary>
-        /// <param name="success" type="Function" optional="no">Callback for a successful clear operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        /// <remarks>
-        ///    In case of an error, this method will not restore any keys that might have been deleted at that point.
-        /// </remarks>
-
-        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);
-        }
-    };
-
-    DomStore.prototype.close = function () {
-        /// <summary>This function does nothing in DomStore as it does not have a connection model</summary>
-    };
-
-    DomStore.prototype.contains = function (key, success, error) {
-        /// <summary>Checks whether a key exists in the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="success" type="Function" optional="no">Callback indicating whether the store contains the key or not.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        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;
-
-    DomStore.prototype.getAllKeys = function (success, error) {
-        /// <summary>Gets all the keys that exist in the store.</summary>
-        /// <param name="success" type="Function" optional="no">Callback for a successful get operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-
-        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);
-        }
-    };
-
-    /// <summary>Identifies the underlying mechanism used by the store.</summary>
-    DomStore.prototype.mechanism = "dom";
-
-    DomStore.prototype.read = function (key, success, error) {
-        /// <summary>Reads the value associated to a key in the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="success" type="Function" optional="no">Callback for a successful reads operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        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);
-            }
-        }
-    };
-
-    DomStore.prototype.remove = function (key, success, error) {
-        /// <summary>Removes a key and its value from the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="success" type="Function" optional="no">Callback for a successful remove operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        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);
-            }
-        }
-    };
-
-    DomStore.prototype.update = function (key, value, success, error) {
-        /// <summary>Updates the value associated to a key in the store.</summary>
-        /// <param name="key" type="String">Key string.</param>
-        /// <param name="value">New value.</param>
-        /// <param name="success" type="Function" optional="no">Callback for a successful update operation.</param>
-        /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-        /// <remarks>
-        ///    This method errors out if the specified key is not found in the store.
-        /// </remarks>
-
-        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);
-    };
-
-
-
-    var indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
-    var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
-    var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
-
-    var IDBT_READ_ONLY = IDBTransaction.READ_ONLY || "readonly";
-    var IDBT_READ_WRITE = IDBTransaction.READ_WRITE || "readwrite";
-
-    var getError = function (error, defaultError) {
-        /// <summary>Returns either a specific error handler or the default error handler</summary>
-        /// <param name="error" type="Function">The specific error handler</param>
-        /// <param name="defaultError" type="Function">The default error handler</param>
-        /// <returns type="Function">The error callback</returns>
-
-        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 });
-        };
-    };
-
-    var openStoreDb = function (store, success, error) {
-        /// <summary>Opens the store object's indexed db database.</summary>
-        /// <param name="store" type="IndexedDBStore">The store object</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-
-        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);
-        };
-    };
-
-    var openTransaction = function (store, mode, success, error) {
-        /// <summary>Opens a new transaction to the store</summary>
-        /// <param name="store" type="IndexedDBStore">The store object</param>
-        /// <param name="mode" type="Short">The read/write mode of the transaction (constants from IDBTransaction)</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-
-        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);
-    };
-
-    var IndexedDBStore = function (name) {
-        /// <summary>Creates a new IndexedDBStore.</summary>
-        /// <param name="name" type="String">The name of the store.</param>
-        /// <returns type="Object">The new IndexedDBStore.</returns>
-        this.name = name;
-    };
-
-    IndexedDBStore.create = function (name) {
-        /// <summary>Creates a new IndexedDBStore.</summary>
-        /// <param name="name" type="String">The name of the store.</param>
-        /// <returns type="Object">The new IndexedDBStore.</returns>
-        if (IndexedDBStore.isSupported()) {
-            return new IndexedDBStore(name);
-        }
-
-        throw { message: "IndexedDB is not supported on this browser" };
-    };
-
-    IndexedDBStore.isSupported = function () {
-        /// <summary>Returns whether IndexedDB is supported.</summary>
-        /// <returns type="Boolean">True if IndexedDB is supported, false otherwise.</returns>
-        return !!indexedDB;
-    };
-
-    IndexedDBStore.prototype.add = function (key, value, success, error) {
-        /// <summary>Adds a key/value pair to the store</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="value" type="Object">The value</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-    IndexedDBStore.prototype.addOrUpdate = function (key, value, success, error) {
-        /// <summary>Adds or updates a key/value pair in the store</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="value" type="Object">The value</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-    IndexedDBStore.prototype.clear = function (success, error) {
-        /// <summary>Clears the store</summary>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-    IndexedDBStore.prototype.close = function () {
-        /// <summary>Closes the connection to the database</summary>
-        if (this.db) {
-            this.db.close();
-            this.db = null;
-        }
-    };
-
-    IndexedDBStore.prototype.contains = function (key, success, error) {
-        /// <summary>Returns whether the store contains a key</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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;
-
-    IndexedDBStore.prototype.getAllKeys = function (success, error) {
-        /// <summary>Gets all the keys from the store</summary>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-    /// <summary>Identifies the underlying mechanism used by the store.</summary>
-    IndexedDBStore.prototype.mechanism = "indexeddb";
-
-    IndexedDBStore.prototype.read = function (key, success, error) {
-        /// <summary>Reads the value for the specified key</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        /// <remarks>If the key does not exist, the success handler will be called with value = undefined</remarks>
-        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);
-    };
-
-    IndexedDBStore.prototype.remove = function (key, success, error) {
-        /// <summary>Removes the specified key from the store</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-    IndexedDBStore.prototype.update = function (key, value, success, error) {
-        /// <summary>Updates a key/value pair in the store</summary>
-        /// <param name="key" type="String">The key</param>
-        /// <param name="value" type="Object">The value</param>
-        /// <param name="success" type="Function">The success callback</param>
-        /// <param name="error" type="Function">The error callback</param>
-        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);
-    };
-
-
-
-    var MemoryStore = function (name) {
-        /// <summary>Constructor for store objects that use a sorted array as the underlying mechanism.</summary>
-        /// <param name="name" type="String">Store name.</param>
-
-        var holes = [];
-        var items = [];
-        var keys = {};
-
-        this.name = name;
-
-        var getErrorCallback = function (error) {
-            return error || this.defaultError;
-        };
-
-        var validateKeyInput = function (key, error) {
-            /// <summary>Validates that the specified key is not undefined, not null, and not an array</summary>
-            /// <param name="key">Key value.</param>
-            /// <param name="error" type="Function">Error callback.</param>
-            /// <returns type="Boolean">True if the key is valid. False if the key is invalid and the error callback has been queued for execution.</returns>
-
-            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.add = function (key, value, success, error) {
-            /// <summary>Adds a new value identified by a key to the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="value">Value that is going to be added to the store.</param>
-            /// <param name="success" type="Function" optional="no">Callback for a successful add operation.</param>
-            /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-            /// <remarks>
-            ///    This method errors out if the store already contains the specified key.
-            /// </remarks>
-
-            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.addOrUpdate = function (key, value, success, error) {
-            /// <summary>Adds or updates a value identified by a key to the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="value">Value that is going to be added or updated to the store.</param>
-            /// <param name="success" type="Function" optional="no">Callback for a successful add or update operation.</param>
-            /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-            /// <remarks>
-            ///   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.
-            /// </remarks>
-
-            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);
-            }
-        };
-
-        this.clear = function (success) {
-            /// <summary>Removes all the data associated with this store object.</summary>
-            /// <param name="success" type="Function" optional="no">Callback for a successful clear operation.</param>
-
-            items = [];
-            keys = {};
-            holes = [];
-
-            delay(success);
-        };
-
-        this.contains = function (key, success) {
-            /// <summary>Checks whether a key exists in the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="success" type="Function" optional="no">Callback indicating whether the store contains the key or not.</param>
-
-            var contained = keys.hasOwnProperty(key);
-            delay(success, contained);
-        };
-
-        this.getAllKeys = function (success) {
-            /// <summary>Gets all the keys that exist in the store.</summary>
-            /// <param name="success" type="Function" optional="no">Callback for a successful get operation.</param>
-
-            var results = [];
-            for (var name in keys) {
-                results.push(name);
-            }
-            delay(success, results);
-        };
-
-        this.read = function (key, success, error) {
-            /// <summary>Reads the value associated to a key in the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="success" type="Function" optional="no">Callback for a successful reads operation.</param>
-            /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-            error = getErrorCallback(error);
-
-            if (validateKeyInput(key, error)) {
-                var index = keys[key];
-                delay(success, key, items[index]);
-            }
-        };
-
-        this.remove = function (key, success, error) {
-            /// <summary>Removes a key and its value from the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="success" type="Function" optional="no">Callback for a successful remove operation.</param>
-            /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-            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);
-            }
-        };
-
-        this.update = function (key, value, success, error) {
-            /// <summary>Updates the value associated to a key in the store.</summary>
-            /// <param name="key" type="String">Key string.</param>
-            /// <param name="value">New value.</param>
-            /// <param name="success" type="Function" optional="no">Callback for a successful update operation.</param>
-            /// <param name="error" type="Function" optional="yes">Callback for handling errors. If not specified then store.defaultError is invoked.</param>
-            /// <remarks>
-            ///    This method errors out if the specified key is not found in the store.
-            /// </remarks>
-
-            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 });
-                }
-            }
-        };
-    };
-
-    MemoryStore.create = function (name) {
-        /// <summary>Creates a store object that uses memory storage as its underlying mechanism.</summary>
-        /// <param name="name" type="String">Store name.</param>
-        /// <returns type="Object">Store object.</returns>
-        return new MemoryStore(name);
-    };
-
-    MemoryStore.isSupported = function () {
-        /// <summary>Checks whether the underlying mechanism for this kind of store objects is supported by the browser.</summary>
-        /// <returns type="Boolean">True if the mechanism is supported by the browser; otherwise false.</returns>
-        return true;
-    };
-
-    MemoryStore.prototype.close = function () {
-        /// <summary>This function does nothing in MemoryStore as it does not have a connection model.</summary>
-    };
-
-    MemoryStore.prototype.defaultError = throwErrorCallback;
-
-    /// <summary>Identifies the underlying mechanism used by the store.</summary>
-    MemoryStore.prototype.mechanism = "memory";
-
-
-
-    var mechanisms = {
-        indexeddb: IndexedDBStore,
-        dom: DomStore,
-        memory: MemoryStore
-    };
-
-    odatajs.defaultStoreMechanism = "best";
-
-    odatajs.createStore = function (name, mechanism) {
-        /// <summary>Creates a new store object.</summary>
-        /// <param name="name" type="String">Store name.</param>
-        /// <param name="mechanism" type="String" optional="true">A specific mechanism to use (defaults to best, can be "best", "dom", "indexeddb", "webdb").</param>
-        /// <returns type="Object">Store object.</returns>
-
-        if (!mechanism) {
-            mechanism = odatajs.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 };
-    };
-
-
-
-
-    var appendQueryOption = function (uri, queryOption) {
-        /// <summary>Appends the specified escaped query option to the specified URI.</summary>
-        /// <param name="uri" type="String">URI to append option to.</param>
-        /// <param name="queryOption" type="String">Escaped query option to append.</param>
-        var separator = (uri.indexOf("?") >= 0) ? "&" : "?";
-        return uri + separator + queryOption;
-    };
-
-    var appendSegment = function (uri, segment) {
-        /// <summary>Appends the specified segment to the given URI.</summary>
-        /// <param name="uri" type="String">URI to append a segment to.</param>
-        /// <param name="segment" type="String">Segment to append.</param>
-        /// <returns type="String">The original URI with a new segment appended.</returns>
-
-        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;
-    };
-
-    var buildODataRequest = function (uri, options) {
-        /// <summary>Builds a request object to GET the specified URI.</summary>
-        /// <param name="uri" type="String">URI for request.</param>
-        /// <param name="options" type="Object">Additional options.</param>
-
-        return {
-            method: "GET",
-            requestUri: uri,
-            user: options.user,
-            password: options.password,
-            enableJsonpCallback: options.enableJsonpCallback,
-            callbackParameterName: options.callbackParameterName,
-            formatQueryString: options.formatQueryString
-        };
-    };
-
-    var findQueryOptionStart = function (uri, name) {
-        /// <summary>Finds the index where the value of a query option starts.</summary>
-        /// <param name="uri" type="String">URI to search in.</param>
-        /// <param name="name" type="String">Name to look for.</param>
-        /// <returns type="Number">The index where the query option starts.</returns>
-
-        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;
-    };
-
-    var queryForData = function (uri, options, success, error) {
-        /// <summary>Gets data from an OData service.</summary>
-        /// <param name="uri" type="String">URI to the OData service.</param>
-        /// <param name="options" type="Object">Object with additional well-known request options.</param>
-        /// <param name="success" type="Function">Success callback.</param>
-        /// <param name="error" type="Function">Error callback.</param>
-        /// <returns type="Object">Object with an abort method.</returns>
-
-        var request = queryForDataInternal(uri, options, [], success, error);
-        return request;
-    };
-
-    var queryForDataInternal = function (uri, options, data, success, error) {
-        /// <summary>Gets data from an OData service taking into consideration server side paging.</summary>
-        /// <param name="uri" type="String">URI to the OData service.</param>
-        /// <param name="options" type="Object">Object with additional well-known request options.</param>
-        /// <param name="data" type="Array">Array that stores the data provided by the OData service.</param>
-        /// <param name="success" type="Function">Success callback.</param>
-        /// <param name="error" type="Function">Error callback.</param>
-        /// <returns type="Object">Object with an abort method.</returns>
-
-        var request = buildODataRequest(uri, options);
-        var currentRequest = odata.request(request, function (newData) {
-            var next = newData.__next;
-            var results = newData.results;
-
-            data = data.concat(results);
-
-            if (next) {
-                currentRequest = queryForDataInternal(next, options, data, success, error);
-            } else {
-                success(data);
-            }
-        }, error, undefined, options.httpClient, options.metadata);
-
-        return {
-            abort: function () {
-                currentRequest.abort();
-            }
-        };
-    };
-
-    var ODataCacheSource = function (options) {
-        /// <summary>Creates a data cache source object for requesting data from an OData service.</summary>
-        /// <param name="options">Options for the cache data source.</param>
-        /// <returns type="ODataCacheSource">A new data cache source instance.</returns>
-
-        var that = this;
-        var uri = options.source;
-        
-        that.identifier = normalizeURICase(encodeURI(decodeURI(uri)));
-        that.options = options;
-
-        that.count = function (success, error) {
-            /// <summary>Gets the number of items in the collection.</summary>
-            /// <param name="success" type="Function">Success callback with the item count.</param>
-            /// <param name="error" type="Function">Error callback.</param>
-            /// <returns type="Object">Request object with an abort method./<param>
-
-            var options = that.options;
-            return odata.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);
-        };
-
-        that.read = function (index, count, success, error) {
-            /// <summary>Gets a number of consecutive items from the collection.</summary>
-            /// <param name="index" type="Number">Zero-based index of the items to retrieve.</param>
-            /// <param name="count" type="Number">Number of items to retrieve.</param>
-            /// <param name="success" type="Function">Success callback with the requested items.</param>
-            /// <param name="error" type="Function">Error callback.</param>
-            /// <returns type="Object">Request object with an abort method./<param>
-
-            var queryOptions = "$skip=" + index + "&$top=" + count;
-            return queryForData(appendQueryOption(uri, queryOptions), that.options, success, error);
-        };
-
-        return that;
-    };
-
-
-
-    var appendPage = function (operation, page) {
-        /// <summary>Appends a page's data to the operation data.</summary>
-        /// <param name="operation" type="Object">Operation with (i)ndex, (c)ount and (d)ata.</param>
-        /// <param name="page" type="Object">Page with (i)ndex, (c)ount and (d)ata.</param>
-
-        var intersection = intersectRanges(operation, page);
-        if (intersection) {
-            var start = intersection.i - page.i;
-            var end = start + (operation.c - operation.d.length);
-            operation.d = operation.d.concat(page.d.slice(start, end));
-        }
-    };
-
-    var intersectRanges = function (x, y) {
-        /// <summary>Returns the {(i)ndex, (c)ount} range for the intersection of x and y.</summary>
-        /// <param name="x" type="Object">Range with (i)ndex and (c)ount members.</param>
-        /// <param name="y" type="Object">Range with (i)ndex and (c)ount members.</param>
-        /// <returns type="Object">The intersection (i)ndex and (c)ount; undefined if there is no intersection.</returns>
-
-        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;
-    };
-
-    var checkZeroGreater = function (val, name) {
-        /// <summary>Checks whether val is a defined number with value zero or greater.</summary>
-        /// <param name="val" type="Number">Value to check.</param>
-        /// <param name="name" type="String">Parameter name to use in exception.</param>
-
-        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." };
-        }
-    };
-
-    var checkUndefinedGreaterThanZero = function (val, name) {
-        /// <summary>Checks whether val is undefined or a number with value greater than zero.</summary>
-        /// <param name="val" type="Number">Value to check.</param>
-        /// <param name="name" type="String">Parameter name to use in exception.</param>
-
-        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." };
-            }
-        }
-    };
-
-    var checkUndefinedOrNumber = function (val, name) {
-        /// <summary>Checks whether val is undefined or a number</summary>
-        /// <param name="val" type="Number">Value to check.</param>
-        /// <param name="name" type="String">Parameter name to use in exception.</param>
-        if (val !== undefined && (typeof val !== "number" || isNaN(val) || !isFinite(val))) {
-            throw { message: "'" + name + "' must be a number." };
-        }
-    };
-
-    var removeFromArray = function (arr, item) {
-        /// <summary>Performs a linear search on the specified array and removes the first instance of 'item'.</summary>
-        /// <param name="arr" type="Array">Array to search.</param>
-        /// <param name="item">Item being sought.</param>
-        /// <returns type="Boolean">Whether the item was removed.</returns>
-
-        var i, len;
-        for (i = 0, len = arr.length; i < len; i++) {
-            if (arr[i] === item) {
-                arr.splice(i, 1);
-                return true;
-            }
-        }
-
-        return false;
-    };
-
-    var estimateSize = function (obj) {
-        /// <summary>Estimates the size of an object in bytes.</summary>
-        /// <param name="obj" type="Object">Object to determine the size of.</param>
-        /// <returns type="Integer">Estimated size of the object in bytes.</returns>
-        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 snapToPageBoundaries = function (lowIndex, highIndex, pageSize) {
-        /// <summary>Snaps low and high indices into page sizes and returns a range.</summary>
-        /// <param name="lowIndex" type="Number">Low index to snap to a lower value.</param>
-        /// <param name="highIndex" type="Number">High index to snap to a higher value.</param>
-        /// <param name="pageSize" type="Number">Page size to snap to.</param>
-        /// <returns type="Object">A range with (i)ndex and (c)ount of elements.</returns>
-
-        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.
-
-    // DataCache state constants
-
-    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";
-
-    var DataCacheOperation = function (stateMachine, promise, isCancelable, index, count, data, pending) {
-        /// <summary>Creates a new operation object.</summary>
-        /// <param name="stateMachine" type="Function">State machine that describes the specific behavior of the operation.</param>
-        /// <param name="promise" type ="DjsDeferred">Promise for requested values.</param>
-        /// <param name="isCancelable" type ="Boolean">Whether this operation can be canceled or not.</param>
-        /// <param name="index" type="Number">Index of first item requested.</param>
-        /// <param name="count" type="Number">Count of items requested.</param>
-        /// <param name="data" type="Array">Array with the items requested by the operation.</param>
-        /// <param name="pending" type="Number">Total number of pending prefetch records.</param>
-        /// <returns type="DataCacheOperation">A new data cache operation instance.</returns>
-
-        /// <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;
-
-        that.cancel = function () {
-            /// <summary>Transitions this operation to the cancel state and sets the canceled flag to true.</summary>
-            /// <remarks>The function is a no-op if the operation is non-cancelable.</summary>
-
-            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);
-            }
-        };
-
-        that.complete = function () {
-            /// <summary>Transitions this operation to the end state.</summary>
-
-            transition(OPERATION_STATE_END, stateData);
-        };
-
-        that.error = function (err) {
-            /// <summary>Transitions this operation to the error state.</summary>
-            if (!that.canceled) {
-                transition(OPERATION_STATE_ERROR, err);
-            }
-        };
-
-        that.run = function (state) {
-            /// <summary>Executes the operation's current state in the context of a new cache state.</summary>
-            /// <param name="state" type="Object">New cache state.</param>
-
-            cacheState = state;
-            that.transition(that.s, stateData);
-        };
-
-        that.wait = function (data) {
-            /// <summary>Transitions this operation to the wait state.</summary>
-
-            transition(OPERATION_STATE_WAIT, data);
-        };
-
-        var operationStateMachine = function (opTargetState, cacheState, data) {
-            /// <summary>State machine that describes all operations common behavior.</summary>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-
-            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.
-                        stateMachine(that, opTargetState, cacheState, data);
-                    break;
-            }
-        };
-
-        var transition = function (state, data) {
-            /// <summary>Transitions this operation to a new state.</summary>
-            /// <param name="state" type="Object">State to transition the operation to.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-
-            that.s = state;
-            stateData = data;
-            operationStateMachine(state, cacheState, data);
-        };
-
-        that.transition = transition;
-
-        return that;
-    };
-
-    DataCacheOperation.prototype.fireResolved = function () {
-        /// <summary>Fires a resolved notification as necessary.</summary>
-
-        // Fire the resolve just once.
-        var p = this.p;
-        if (p) {
-            this.p = null;
-            p.resolve(this.d);
-        }
-    };
-
-    DataCacheOperation.prototype.fireRejected = function (reason) {
-        /// <summary>Fires a rejected notification as necessary.</summary>
-
-        // Fire the rejection just once.
-        var p = this.p;
-        if (p) {
-            this.p = null;
-            p.reject(reason);
-        }
-    };
-
-    DataCacheOperation.prototype.fireCanceled = function () {
-        /// <summary>Fires a canceled notification as necessary.</summary>
-
-        this.fireRejected({ canceled: true, message: "Operation canceled" });
-    };
-
-
-    var DataCache = function (options) {
-        /// <summary>Creates a data cache for a collection that is efficiently loaded on-demand.</summary>
-        /// <param name="options">
-        /// Options for the data cache, including name, source, pageSize,
-        /// prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
-        /// </param>
-        /// <returns type="DataCache">A new data cache instance.</returns>
-
-        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 ODataCacheSource(options);
-        }
-        source.options = options;
-
-        // Create a cache local store.
-        var store = odatajs.createStore(options.name, options.mechanism);
-
-        var that = this;
-
-        that.onidle = options.idle;
-        that.stats = stats;
-
-        that.count = function () {
-            /// <summary>Counts the number of items in the collection.</summary>
-            /// <returns type="Object">A promise with the number of items.</returns>
-
-            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(), {
-                cancel: function () {
-                    /// <summary>Aborts the count operation.</summary>
-                    if (request) {
-                        canceled = true;
-                        request.abort();
-                        request = null;
-                    }
-                }
-            });
-        };
-
-        that.clear = function () {
-            /// <summary>Cancels all running operations and clears all local data associated with this cache.</summary>
-            /// <remarks>
-            /// 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.
-            /// </remarks>
-            /// <returns type="Object">A promise that has no value and can't be canceled.</returns>
-
-            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;
-        };
-
-        that.filterForward = function (index, count, predicate) {
-            /// <summary>Filters the cache data based a predicate.</summary>
-            /// <param name="index" type="Number">The index of the item to start filtering forward from.</param>
-            /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-            /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-            /// <remarks>
-            /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-            /// </remarks>
-            /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-            return filter(index, count, predicate, false);
-        };
-
-        that.filterBack = function (index, count, predicate) {
-            /// <summary>Filters the cache data based a predicate.</summary>
-            /// <param name="index" type="Number">The index of the item to start filtering backward from.</param>
-            /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-            /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-            /// <remarks>
-            /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-            /// </remarks>
-            /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-            return filter(index, count, predicate, true);
-        };
-
-        that.readRange = function (index, count) {
-            /// <summary>Reads a range of adjacent records.</summary>
-            /// <param name="index" type="Number">Zero-based index of record range to read.</param>
-            /// <param name="count" type="Number">Number of records in the range.</param>
-            /// <remarks>
-            /// 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.
-            /// </remarks>
-            /// <returns type="DjsDeferred">
-            /// A promise for an array of records; less records may be returned if the
-            /// end of the collection is found.
-            /// </returns>
-
-            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 () {
-                    /// <summary>Aborts the readRange operation.</summary>
-                    op.cancel();
-                }
-            });
-        };
-
-        that.ToObservable = that.toObservable = function () {
-            /// <summary>Creates an Observable object that enumerates all the cache contents.</summary>
-            /// <returns>A new Observable object that enumerates all the cache contents.</returns>
-            if (!window.Rx || !window.Rx.Observable) {
-                throw { message: "Rx library not available - include rx.js" };
-            }
-
-            if (cacheFailure) {
-                throw cacheFailure;
-            }
-
-            return window.Rx.Observable.CreateWithDisposable(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.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[i]);
-                        }
-
-                        if (data.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; } };
-            });
-        };
-
-        var cacheFailureCallback = function (message) {
-            /// <summary>Creates a function that handles a callback by setting the cache into failure mode.</summary>
-            /// <param name="message" type="String">Message text.</param>
-            /// <returns type="Function">Function to use as error callback.</returns>
-            /// <remarks>
-            /// This function will specifically handle problems with critical store resources
-            /// during cache initialization.
-            /// </remarks>
-
-            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.
-                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;
-            };
-        };
-
-        var changeState = function (newState) {
-            /// <summary>Updates the cache's state and signals all pending operations of the change.</summary>
-            /// <param name="newState" type="Object">New cache state.</param>
-            /// <remarks>This method is a no-op if the cache's current state and the new state are the same.</remarks>
-
-            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);
-                }
-            }
-        };
-
-        var clearStore = function () {
-            /// <summary>Removes all the data stored in the cache.</summary>
-            /// <returns type="DjsDeferred">A promise with no value.</returns>
-
-            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;
-        };
-
-        var dequeueOperation = function (operation) {
-            /// <summary>Removes an operation from the caches queues and changes the cache state to idle.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation to dequeue.</param>
-            /// <remarks>This method is used as a handler for the operation's oncomplete event.</remarks>
-
-            var removed = removeFromArray(clearOperations, operation);
-            if (!removed) {
-                removed = removeFromArray(readOperations, operation);
-                if (!removed) {
-                    removeFromArray(prefetchOperations, operation);
-                }
-            }
-
-            pendingOperations--;
-            changeState(CACHE_STATE_IDLE);
-        };
-
-        var fetchPage = function (start) {
-            /// <summary>Requests data from the cache source.</summary>
-            /// <param name="start" type="Number">Zero-based index of items to request.</param>
-            /// <returns type="DjsDeferred">A promise for a page object with (i)ndex, (c)ount, (d)ata.</returns>
-
-
-            var deferred = new DjsDeferred();
-            var canceled = false;
-
-            var request = source.read(start, pageSize, function (data) {
-                var page = { i: start, c: data.length, d: data };
-                deferred.resolve(page);
-            }, function (err) {
-                deferred.reject(err);
-            });
-
-            return extend(deferred, {
-                cancel: function () {
-                    if (request) {
-                        request.abort();
-                        canceled = true;
-                        request = null;
-                    }
-                }
-            });
-        };
-
-        var filter = function (index, count, predicate, backwards) {
-            /// <summary>Filters the cache data based a predicate.</summary>
-            /// <param name="index" type="Number">The index of the item to start filtering from.</param>
-            /// <param name="count" type="Number">Maximum number of items to include in the result.</param>
-            /// <param name="predicate" type="Function">Callback function returning a boolean that determines whether an item should be included in the result or not.</param>
-            /// <param name="backwards" type="Boolean">True if the filtering should move backward from the specified index, falsey otherwise.</param>
-            /// <remarks>
-            /// Specifying a negative count value will yield all the items in the cache that satisfy the predicate.
-            /// </remarks>
-            /// <returns type="DjsDeferred">A promise for an array of results.</returns>
-            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 arr = [];
-            var canceled = false;
-            var pendingReadRange = null;
-
-            var readMore = function (readIndex, readCount) {
-                if (!canceled) {
-                    if (count >= 0 && arr.length >= count) {
-                        deferred.resolve(arr);
-                    } else {
-                        pendingReadRange = that.readRange(readIndex, readCount).then(function (data) {
-                            for (var i = 0, length = data.length; i < length && (count < 0 || arr.length < count); i++) {
-                                var dataIndex = backwards ? length - i - 1 : i;
-                                var item = data[dataIndex];
-                                if (predicate(item)) {
-                                    var element = {
-                                        index: readIndex + dataIndex,
-                                        item: item
-                                    };
-
-                                    backwards ? arr.unshift(element) : arr.push(element);
-                                }
-                            }
-
-                            // Have we reached the end of the collection?
-                            if ((!backwards && data.length < readCount) || (backwards && readIndex <= 0)) {
-                                deferred.resolve(arr);
-                            } 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(), {
-                cancel: function () {
-                    /// <summary>Aborts the filter operation</summary>
-                    if (pendingReadRange) {
-                        pendingReadRange.cancel();
-                    }
-                    canceled = true;
-                }
-            });
-        };
-
-        var fireOnIdle = function () {
-            /// <summary>Fires an onidle event if any functions are assigned.</summary>
-
-            if (that.onidle && pendingOperations === 0) {
-                that.onidle();
-            }
-        };
-
-        var prefetch = function (start) {
-            /// <summary>Creates and starts a new prefetch operation.</summary>
-            /// <param name="start" type="Number">Zero-based index of the items to prefetch.</param>
-            /// <remarks>
-            /// 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).
-            /// <remarks>
-
-            if (allDataLocal || prefetchSize === 0 || overflowed) {
-                return;
-            }
-
-
-            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);
-            }
-        };
-
-        var queueAndStart = function (op, queue) {
-            /// <summary>Queues an operation and runs it.</summary>
-            /// <param name="op" type="DataCacheOperation">Operation to queue.</param>
-            /// <param name="queue" type="Array">Array that will store the operation.</param>
-
-            op.oncomplete = dequeueOperation;
-            queue.push(op);
-            pendingOperations++;
-            op.run(state);
-        };
-
-        var readPage = function (key) {
-            /// <summary>Requests a page from the cache local store.</summary>
-            /// <param name="key" type="Number">Zero-based index of the reuqested page.</param>
-            /// <returns type="DjsDeferred">A promise for a found flag and page object with (i)ndex, (c)ount, (d)ata, and (t)icks.</returns>
-
-
-            var canceled = false;
-            var deferred = extend(new DjsDeferred(), {
-                cancel: function () {
-                    /// <summary>Aborts the readPage operation.</summary>
-                    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;
-        };
-
-        var savePage = function (key, page) {
-            /// <summary>Saves a page to the cache local store.</summary>
-            /// <param name="key" type="Number">Zero-based index of the requested page.</param>
-            /// <param name="page" type="Object">Object with (i)ndex, (c)ount, (d)ata, and (t)icks.</param>
-            /// <returns type="DjsDeferred">A promise with no value.</returns>
-
-
-            var canceled = false;
-
-            var deferred = extend(new DjsDeferred(), {
-                cancel: function () {
-                    /// <summary>Aborts the readPage operation.</summary>
-                    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;
-        };
-
-        var saveSettings = function (success, error) {
-            /// <summary>Saves the cache's current settings to the local store.</summary>
-            /// <param name="success" type="Function">Success callback.</param>
-            /// <param name="error" type="Function">Errror callback.</param>
-
-            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);
-        };
-
-        var storeFailureCallback = function (deferred/*, message*/) {
-            /// <summary>Creates a function that handles a store error.</summary>
-            /// <param name="deferred" type="DjsDeferred">Deferred object to resolve.</param>
-            /// <param name="message" type="String">Message text.</param>
-            /// <returns type="Function">Function to use as error callback.</returns>
-            /// <remarks>
-            /// This function will specifically handle problems when interacting with the store.
-            /// </remarks>
-
-            return function (/*error*/) {
-                // var console = window.console;
-                // if (console && console.log) {
-                //    console.log(message);
-                //    console.dir(error);
-                // }
-                deferred.resolve(false);
-            };
-        };
-
-        var updateSettings = function (page, pageBytes) {
-            /// <summary>Updates the cache's settings based on a page object.</summary>
-            /// <param name="page" type="Object">Object with (i)ndex, (c)ount, (d)ata.</param>
-            /// <param name="pageBytes" type="Number">Size of the page in bytes.</param>
-
-            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;
-            }
-        };
-
-        var cancelStateMachine = function (operation, opTargetState, cacheState, data) {
-            /// <summary>State machine describing the behavior for cancelling a read or prefetch operation.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-            /// <remarks>
-            /// This state machine contains behavior common to read and prefetch operations.
-            /// </remarks>
-
-            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;
-        };
-
-        var destroyStateMachine = function (operation, opTargetState, cacheState) {
-            /// <summary>State machine describing the behavior of a clear operation.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <remarks>
-            /// Clear operations have the highest priority and can't be interrupted by other operations; however,
-            /// they will preempt any other operation currently executing.
-            /// </remarks>
-
-            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;
-        };
-
-        var prefetchStateMachine = function (operation, opTargetState, cacheState, data) {
-            /// <summary>State machine describing the behavior of a prefetch operation.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-            /// <remarks>
-            /// 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.
-            /// </remarks>
-
-            // 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;
-        };
-
-        var readStateMachine = function (operation, opTargetState, cacheState, data) {
-            /// <summary>State machine describing the behavior of a read operation.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-            /// <remarks>
-            /// 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.
-            /// </remarks>
-
-            // 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.
-                        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 = operation.d.length;
-                        // 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;
-        };
-
-        var readSaveStateMachine = function (operation, opTargetState, cacheState, data, isPrefetch) {
-            /// <summary>State machine describing the behavior for reading and saving data into the cache.</summary>
-            /// <param name="operation" type="DataCacheOperation">Operation being run.</param>
-            /// <param name="opTargetState" type="Object">Operation state to transition to.</param>
-            /// <param name="cacheState" type="Object">Current cache state.</param>
-            /// <param name="data" type="Object" optional="true">Additional data passed to the state.</param>
-            /// <param name="isPrefetch" type="Boolean">Flag indicating whether a read (false) or prefetch (true) operation is running.
-            /// <remarks>
-            /// This state machine contains behavior common to read and prefetch operations.
-            /// </remarks>
-
-            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;
-    };
-
-    odatajs.createDataCache = function (options) {
-        /// <summary>Creates a data cache for a collection that is efficiently loaded on-demand.</summary>
-        /// <param name="options">
-        /// Options for the data cache, including name, source, pageSize,
-        /// prefetchSize, cacheSize, storage mechanism, and initial prefetch and local-data handler.
-        /// </param>
-        /// <returns type="DataCache">A new data cache instance.</returns>
-        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);
-    };
-
-
-
-})(this);
\ No newline at end of file