text:
(function (window, undefined) {

    var datajs = window.datajs || {};
    var odata = window.OData || {};

    // AMD support
    if (typeof define === 'function' && define.amd) {
        define('datajs', datajs);
        define('OData', odata);
    } else {
        window.datajs = datajs;
        window.OData = odata;
    }

    var activeXObject = function (progId) {
        /// Creates a new ActiveXObject from the given progId.
        /// <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) {
        /// Checks whether the specified value is different from null and undefined.
        /// <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) {
        /// Checks whether the specified item is in the array.
        /// <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) {
        /// Given two values, picks the first one that is not undefined.
        /// <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) {
        /// Delays the invocation of the specified function until execution unwinds.
        /// <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) {
        /// Extends the target with the specified values.
        /// <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) {
        /// Returns the first item in the array that makes the callback function true.
        /// <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) {
        /// Checks whether the specified value is an array object.
        /// <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) {
        /// Checks whether the specified value is a Date object.
        /// <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) {
        /// Tests whether a value is an object.
        /// <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) {
        /// Parses a value in base 10.
        /// <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) {
        /// Renames a property in an object.
        /// <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) {
        /// Default error handler.
        /// <param name="error" type="Object">Error to handle.</param>
        throw error;
    };

    var trimString = function (str) {
        /// Removes leading and trailing whitespaces from a string.
        /// <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) {
        /// Returns a default value in place of undefined.
        /// <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) {
        /// Gets information about the components of the specified URI.
        /// <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) {
        /// Builds a URI string from its components.
        /// <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) {
        /// Normalizes the casing of a URI.
        /// <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) {
        /// Normalizes a possibly relative URI with a base URI.
        /// <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) {
        /// Merges the path of a relative URI and a base URI.
        /// <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) {
        /// Removes the special folders . and .. from a URI's path.
        /// <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;
    };

    // 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) {
        /// Checks whether the specified string has leading or trailing spaces.
        /// <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) {
        /// Determines whether the specified text is empty or whitespace.
        /// <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) {
        /// Determines whether the specified element has xml:space='preserve' applied.
        /// <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) {
        /// Determines whether the attribute is a XML namespace declaration.
        /// <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) {
        /// Safely set as property in an object by invoking obj.setProperty.
        /// <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 () {
        /// Creates an configures new MSXML 3.0 ActiveX object.
        /// <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 () {
        /// Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.
        /// <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) {
        /// Parses an XML string using the MSXML DOM.
        /// <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) {
        /// Throws a new exception containing XML parsing error information.
        /// <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) {
        /// Returns an XML DOM document from the specified text.
        /// <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) {
        /// Builds a XML qualified name string in the form of "prefix:name".
        /// <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) {
        /// Appends a text node into the specified DOM element node.
        /// <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) {
        /// Iterates through the XML element's attributes and invokes the callback function for each one.
        /// <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) {
        /// Returns the value of a DOM element's attribute.
        /// <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) {
        /// Gets an attribute node from a DOM element.
        /// <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) {
        /// Gets the value of the xml:base attribute on the specified element.
        /// <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) {
        /// Iterates through the XML element's child DOM elements and invokes the callback function for each one.
        /// <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) {
        /// Gets the descendant element under root that corresponds to the specified path and namespace URI.
        /// <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) {
        /// Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.
        /// <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) {
        /// Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.
        /// <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) {
        /// Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
        /// <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) {
        /// Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.
        /// <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) {
        /// Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.
        /// <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   1. The space between  and  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) {
        /// Returns the localName of a XML node.
        /// <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) {
        /// Returns the namespace URI of a XML node.
        /// <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) {
        /// Returns the value or the inner text of a XML node.
        /// <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) {
        /// Walks through the descendants of the domNode and invokes a callback for each node.
        /// <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) {
        /// Returns the next sibling DOM element of the specified DOM node.
        /// <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 () {
        /// Creates a new empty DOM document node.
        /// <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) {
        /// Appends a collection of child nodes or string values to a parent DOM node.
        /// <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) {
        /// Appends a child node or a string value to a parent DOM node.
        /// <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;
    };

    // ##### BEGIN: MODIFIED BY SAP
    // polyfill for document.createAttributeNS which was removed from Chrome 34
    // but will be added back in, see:
    // http://datajs.codeplex.com/workitem/1272
    // https://code.google.com/p/chromium/issues/detail?id=347506
    // https://codereview.chromium.org/243333003
    var _createAttributeNS = function(namespaceURI, qualifiedName) {
        var dummy = document.createElement('dummy');
        dummy.setAttributeNS(namespaceURI, qualifiedName, '');
        var attr = dummy.attributes[0];
        dummy.removeAttributeNode(attr);
        return attr;
    };
    // ##### END: MODIFIED BY SAP

    var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) {
        /// Creates a new DOM attribute node.
        /// <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>

        // ##### BEGIN: MODIFIED BY SAP
        // added usage of _createAttributeNS as fallback (see function above)
        var attribute =
            dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) ||
            "createNode" in dom && dom.createNode(2, qualifiedName, namespaceURI || undefined) ||
            _createAttributeNS(namespaceURI, qualifiedName);
        // ##### END: MODIFIED BY SAP

        attribute.value = value || "";
        return attribute;
    };

    var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) {
        /// Creates a new DOM element node.
        /// <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) {
        /// Creates a namespace declaration attribute.
        /// <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) {
        /// Creates a new DOM document fragment node for the specified xml text.
        /// <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) {
        /// Creates new DOM text node.
        /// <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) {
        /// Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.
        /// <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) {
        ///
        /// Returns the text representation of the document to which the specified node belongs.
        ///
        /// <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) {
        /// Returns the XML representation of the all the descendants of the node.
        /// <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) {
        /// Returns the XML representation of the node and all its descendants.
        /// <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) {
        /// Creates a new function to forward a call.
        /// <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 () {
        /// Initializes a new DjsDeferred object.
        /// <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 */) {
            /// Adds success and error callbacks for this deferred object.
            /// <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 */) {
            /// Invokes success callbacks for this deferred object.
            /// <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 */) {
            /// Invokes error callbacks for this deferred object.
            /// <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 () {
            /// Returns a version of this object that has only the read-only methods available.
            /// <returns>An object with only the promise object.</returns>

            var result = {};
            result.then = forwardCall(this, "then", result);
            return result;
        }
    };

    var createDeferred = function () {
        /// Creates a deferred object.
        /// <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) {
        /// 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 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) {
        /// Invokes a function once per schema in metadata.
        /// <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) {
        /// Formats a millisecond and a nanosecond value into a single string.
        /// <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;
    };

    // ##### BEGIN: MODIFIED BY SAP
    var formatDateTimeOffsetJSON = function (value) {
    	return "\/Date("+value.getTime()+")\/";
    };
    // ##### END: MODIFIED BY SAP

    var formatDateTimeOffset = function (value) {
        /// Formats a DateTime or DateTimeOffset value a string.
        /// <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.getMinutes() + (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) {
        /// Converts a duration to a string in xsd:duration format.
        /// <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) {
        /// Formats the specified value to the given width.
        /// <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) {
        /// Gets the canonical timezone representation.
        /// <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) {
        /// Gets the type of a collection type name.
        /// <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) {
        /// Sends a request containing OData payload to a server.
        /// <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;
            }
            // ##### BEGIN: MODIFIED BY SAP
            // 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;
			}
			// ##### END: MODIFIED BY SAP
        }, error);
    };

    var isBatch = function (value) {
        /// Tests whether a value is a batch object in the library's internal representation.
        /// <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) {
        /// Tests whether a value is a collection value in the library's internal representation.
        /// <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) {
        /// Checks whether the specified type name is a collection type.
        /// <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) {
        /// Tests whether a value is a complex type value in the library's internal representation.
        /// <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) {
        /// Checks whether a Date object is DateTimeOffset value
        /// <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) {
        /// Tests whether a value is a deferred navigation property in the library's internal representation.
        /// <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) {
        /// Tests whether a value is an entry object in the library's internal representation.
        /// <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) {
        /// Tests whether a value is a feed value in the library's internal representation.
        /// <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) {
        /// Checks whether the specified type name is a geography EDM type.
        /// <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) {
        /// Checks whether the specified type name is a geometry EDM type.
        /// <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) {
        /// Tests whether a value is a named stream value in the library's internal representation.
        /// <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) {
        /// Tests whether a value is a primitive type value in the library's internal representation.
        /// <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) {
        /// Checks whether the specified type name is a primitive EDM type.
        /// <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) {
        /// Gets the kind of a navigation property value.
        /// <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) {
        /// Looks up a property by name.
        /// <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) {
        /// Looks up a type object by name.
        /// <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) {
        /// Looks up a entity set by name.
        /// <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) {
        /// Looks up a complex type object by name.
        /// <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) {
        /// Looks up an entity type object by name.
        /// <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) {
        /// Looks up an
        /// <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) {
        /// Looks up an entity container object by name.
        /// <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) {
        /// Looks up a function import by name.
        /// <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) {
        /// Looks up the target entity type for a navigation property.
        /// <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];
                        }
                    }
                }
            });

            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 removeNamespace = function (ns, fullName) {
        /// Given an expected namespace prefix, removes it from a full name.
        /// <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) {
        /// Looks up a schema object by name.
        /// <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) {
        /// Compares to version strings and returns the higher one.
        /// <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) {
        /// Normalizes headers so they can be found with consistent casing.
        /// <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) {
        /// Parses a string into a boolean value.
        /// <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)

	// ##### BEGIN: MODIFIED BY SAP
    var parseDateTimeRE = /^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d+))?(.*)$/;
	// ##### END: MODIFIED BY SAP

    var parseDateTimeMaybeOffset = function (value, withOffset, nullOnError) {
        /// Parses a string into a DateTime value.
        /// <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]);
    	// ##### BEGIN: MODIFIED BY SAP
        var seconds = parseInt10(parts[6]) || 0;
    	// ##### END: MODIFIED BY SAP
        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) {
        /// Parses a string into a DateTime value.
        /// <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) {
        /// Parses a string into a DateTimeOffset value.
        /// <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) {
        /// Parses a string in xsd:duration format.
        /// <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) {
        /// Parses a timezone description in (+|-)nn:nn format.
        /// <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) {
        /// Prepares a request object so that it can be sent through the network.
        /// <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";
        }

        // ##### BEGIN: MODIFIED BY SAP
        if (request.async === undefined) {
        	request.async = true;
        }
        // ##### END: MODIFIED BY SAP
    };

    var traverseInternal = function (item, owner, callback) {
        /// Traverses a tree of objects invoking callback for every value.
        /// <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) {
        /// Traverses a tree of objects invoking callback for every value.
        /// <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) {
        ///
        /// Checks whether the specified request can be satisfied with a JSONP request.
        ///
        /// <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) {
        /// Creates an IFRAME tag for loading the JSONP script
        /// <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, "&").replace(/"/g, """).replace(/\</g, "<");
        var html = "


text:
Location: `/application/config.py`.

---

Mocha uses class-based configuration, and the config will be loaded upon startup.

    class BaseConfig(object):
        """
        Base Configuration.
        """

        APPLICATION_NAME = "Mocha"

        APPLICATION_URL = ""

        APPLICATION_VERSION = "0.0.1"

        GOOGLE_ANALYTICS_ID = ""

        ADMIN_EMAIL = None

        CONTACT_EMAIL = None

        PAGINATION_PER_PAGE = 20

        ...

    class Dev(BaseConfig):
        """
        Config for development environment
        """
        SERVER_NAME = None
        DEBUG = True
        SECRET_KEY = "PLEASE CHANGE ME"

    class Prod(BaseConfig):
        """
        Config for Production environment
        """
        SERVER_NAME = "abc.com"
        DEBUG = False
        SECRET_KEY = "My Prod Secret"
        COMPRESS_HTML = True

It is recommended to have a base class, `BaseConfig`, and your environment classes `Dev`, `Prod` which are subclasses
of the `BaseConfig`, this way they can share some common config.

The environment classes will be loaded on Mocha startup. By default, and in development, Mocha will attempt to load
 the `Dev` if one isn't provided.

To switch to a different config, you have to set the environment variable

    env=prod mocha :serve

or to set the application along with the environment

    app=main:prod mocha :serve

The code above will load the `Prod` config.

One main advantage of having your config like that, is that you have the ability of using different config for different
environment, could be for testing, prod, dev, etc.

---

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace line\logger;

/**
 * Show logs on console .
 * @class ConsoleAppender
 * @link  http://linephp.com
 * @author Alivop[alivop.liu@gmail.com]
 * @since 1.0
 * @package line\logger
 */
class ConsoleAppender extends LineLogger
{
    protected function rewriteDebug($message)
    {
        echo $message;
    }

    protected function rewriteInfo($message)
    {
        echo $message;
    }

    protected function rewriteWarn($message)
    {
        echo $message;
    }

    protected function rewriteError($message)
    {
        echo $message;
    }

    protected function rewrite($message){
        echo $message;
    }

    protected function deal($message)
    {
        return "[LineLog]".$message.'
';
    }

}


text:
require 'delegate'

require 'hopper/message'
require 'hay/task/resolvers'

module Baler
  class Message
    class Decoder
      class MsgPack < DelegateClass(Hopper::Message)
        def initialize(message)
          @message = message
          super
        end

        def payload
          @payload ||= ::MessagePack.unpack(@message.message.payload)
        end
        Hay::Task::Resolvers.register(self, Hay::Task::Resolver::Task)
      end
    end
  end
end