From 6b8479b10183342a5825d1f4d64f1ddd97bb22f4 Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:14:45 -0400 Subject: [PATCH 01/84] Update package.json --- packages/angular/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index bfe7742..9ed5915 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-angular", - "version": "5.0.0", + "version": "5.0.1", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with Angular.", "main": "lib/progress.data.angular.js", "files": [ From 331c10cc6732e1ccc88fad3072a016842d6f32dc Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:15:09 -0400 Subject: [PATCH 02/84] Update package.json --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 6dce5a9..9c2ee1b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-core", - "version": "5.0.0", + "version": "5.0.1", "description": "JSDO Core Module", "main": "lib/progress.core.js", "files": [ From e93a8995577492a2b1c2d0d37b4a0310bb4f835b Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:15:34 -0400 Subject: [PATCH 03/84] Update package.json --- packages/nativescript/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nativescript/package.json b/packages/nativescript/package.json index 7cf6e45..6b4dbcc 100644 --- a/packages/nativescript/package.json +++ b/packages/nativescript/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-nativescript", - "version": "5.0.0", + "version": "5.0.1", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with NativeScript", "main": "lib/progress.data.ns.js", "files": [ From 837170a7d2b662e53177169ac42b953548032957 Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:16:06 -0400 Subject: [PATCH 04/84] Update package.json --- packages/ng-datasource/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 14ab974..deb0891 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-nsds", - "version": "5.0.0", + "version": "5.0.1", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with NativeScript", "main": "lib/progress.data.ng.ds.js", "files": [ From 57db75f70cabdd062b9ed8469d28ec324ea48952 Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:16:27 -0400 Subject: [PATCH 05/84] Update package.json --- packages/node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/package.json b/packages/node/package.json index 0eecaa3..56db64d 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-node", - "version": "5.0.0", + "version": "5.0.1", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular and Node.js. This will provide a seamless integration between OpenEdge (Progress Data Object) with Node.js.", "main": "lib/progress.data.node.js", "files": [ From ad9388342f5bedd80b821aa768d4e2b70f913778 Mon Sep 17 00:00:00 2001 From: Anil Date: Tue, 15 May 2018 17:17:37 -0400 Subject: [PATCH 06/84] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 315c3e5..fe7f2d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo", - "version": "5.0.0", + "version": "5.0.1", "description": "The JSDO is a JavaScript implementation of the CDO Specification published by Progress Software Corporation.\r The JSDO is a free and open-source full-featured implementation that can be used in web, mobile web and hybrid mobile apps.", "main": "lib/progress.all.min.js", "files": [ From a88d6706638d063e5a463fdc6bbdbcd2c48c86f8 Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 17 May 2018 23:33:18 -0400 Subject: [PATCH 07/84] Update guidelines to contribute --- contributing.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contributing.md b/contributing.md index 4b015f3..377c3a9 100644 --- a/contributing.md +++ b/contributing.md @@ -32,8 +32,9 @@ If you want to implement a new feature yourself, consider submitting it to the < Contribute to the Code Base === -Before you submit a Pull Request, consider the following guidelines. -* Read and sign the JSDO Contributor License Agreement. +Before you submit a Pull Request, consider the following guidelines: +* By submitting a pull request, you represent that you have the right to license your contribution to Progress and the community, and agree by submitting the patch that your contributions are licensed under the progress/JSDO license. +Notwithstanding the above, we reserve the right to ask you to sign a Contributor License Agreement (CLA) for larger changes. * Search GitHub for an open or closed Pull Request that relates to your submission. * Clone the repository. ```bash From f004ce9ceac8726d05ac4ad5b4e31a01f1fc4e00 Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 17 May 2018 23:38:34 -0400 Subject: [PATCH 08/84] Update guidelines to contribute --- .github/PULL_REQUEST_TEMPLATE.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1104512..f11fcf2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,12 +3,10 @@ ## PR Checklist -- [ ] See our contributing guidelines: https://github.com/progress/JSDO/blob/master/contributing.md#contribute-to-the-code-base. -- [ ] You have signed the [CLA](https://www.progress.com/jsdo/cla). +- [ ] Read our contributing guidelines: https://github.com/progress/JSDO/blob/master/contributing.md#contribute-to-the-code-base. [Describe the impact of the changes here. Please include issue # if applicable.] - From 4fef2cc6363bfea07a755483456ed43b67757b4d Mon Sep 17 00:00:00 2001 From: "SOFTPAK\\David" Date: Wed, 23 May 2018 14:22:25 +0200 Subject: [PATCH 09/84] fixed add method. Parameter could be empty and return type is JSRecord --- typings/progress.all.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 1f228f8..6dfc26f 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -308,7 +308,7 @@ export module progress { * @param {object} - New Record Object * @returns {object} progress.data.JSRecord class */ - add(object: any): boolean; + add(object?: any): JSRecord; /** * Updates JSDO memory with one or more record objects read from an array, single-table, or multi-table resource that are passed in an object parameter, @@ -462,7 +462,7 @@ export module progress { * @param {object} - New Record Object * @returns {object} progress.data.JSRecord class */ - add(object: any): boolean; + add(object?: any): JSRecord; /** * Updates JSDO memory with one or more record objects read from an array, single-table, or multi-table resource that are passed in an object parameter, @@ -1115,7 +1115,7 @@ export module progress { interface IJSTableRef { acceptChanges(): boolean; - add(object: any): boolean; + add(object?: any): JSRecord; addRecords(mergeObject: any, addMode: number, keyFields?: any): void; find(code: Function): JSRecord; findById(id: string): JSRecord; From cb19b1357df6ea3226abc53e6876268da989d1d3 Mon Sep 17 00:00:00 2001 From: "SOFTPAK\\David" Date: Wed, 23 May 2018 14:23:47 +0200 Subject: [PATCH 10/84] added missing typings for transpiling with NoImplicitAny --- typings/progress.all.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 6dfc26f..0fc610d 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -206,7 +206,7 @@ export module progress { * properties in the current JSDO, where name and value define a single property as defined for the setProperty( ) method. * @returns {null} */ - setProperties(propsObject): void + setProperties(propsObject: any): void /** * Sets the value of the specified JSDO user-defined property. @@ -225,7 +225,7 @@ export module progress { * Returns the value of the specified JSDO user-defined property. * @param name - The name of a user-defined property to query from the JSDO. */ - getProperty(name): any + getProperty(name: string): any /** * Returns an array of errors from the most recent invocation of Create, Read, Update, Delete, or Submit operations (CRUD or Submit) From 42e8d5c1860d131a4fe00fca6798ca96da62a987 Mon Sep 17 00:00:00 2001 From: joshualan Date: Mon, 4 Jun 2018 16:44:24 -0400 Subject: [PATCH 11/84] Adding support for CI and its dependencies --- .eslintrc.json | 5 +- .gitignore | 3 + build/index.html | 500 ++ build/progress.jsdo.js | 15014 +++++++++++++++++++++++++++++++++++++++ index.html | 500 ++ package.json | 16 +- test/smoke.js | 49 + 7 files changed, 16083 insertions(+), 4 deletions(-) create mode 100644 build/index.html create mode 100644 build/progress.jsdo.js create mode 100644 index.html create mode 100644 test/smoke.js diff --git a/.eslintrc.json b/.eslintrc.json index 21e0614..b2c4a71 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,8 +7,9 @@ "env": { "browser": true, "es6": true, - "node": true - }, + "node": true, + "mocha": true + }, "rules": { "indent": 1, "no-console": 0, diff --git a/.gitignore b/.gitignore index b00f58d..bc032af 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ .vscode tmp tslint.json +node_modules/ +scratch1/ +scratch2/ \ No newline at end of file diff --git a/build/index.html b/build/index.html new file mode 100644 index 0000000..f160653 --- /dev/null +++ b/build/index.html @@ -0,0 +1,500 @@ + + + + Mocha + + + + +
+
+
    +
  • show failures only
  • +
+
    +
  • passes: 1
  • +
  • pending: 0
  • +
  • failures: 0
  • +
  • duration: 1.3s
  • +
+
+
  • Smoke Tests

    • Ping Test

      • should have a successful connection to the backend38ms

        session.ping().then((object) => {
        +    // If we have successfully logged into the backend, the result
        +    // of our ping() should be true
        +    expect(object.result).to.be.true;
        +}).then(done, done);
+
+ + + diff --git a/build/progress.jsdo.js b/build/progress.jsdo.js new file mode 100644 index 0000000..c1ac383 --- /dev/null +++ b/build/progress.jsdo.js @@ -0,0 +1,15014 @@ +/*eslint no-global-assign: ["error", {"exceptions": ["localStorage"]}]*/ +/*global XMLHttpRequest:true, require, console, localStorage:true, sessionStorage:true, $:true, Promise, setTimeout */ +/* +progress.util.js Version: 5.0.0 + +Copyright (c) 2014-2018 Progress Software Corporation and/or its subsidiaries or affiliates. + +Contains support objects used by the jsdo and/or session object + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ +/*global progress:true, btoa:true*/ +/*jslint nomen: true*/ + +(function () { + // Pre-release code to detect enviroment and load required modules for Node.js and NativeScript + // Requirements: + // - XMLHttpRequest + // - localStorage + // - sessionStorage + // - Promise object (Promises with the same interface as jQuery Promises) + + // Notes: + // Required packages should be installed before loading progress-jsdo. + // Node.js: + // - xmlhttprequest + // - node-localstorage + // NativeScript: + // - nativescript-localstorage + // - base-64 + + var isNativeScript = false, + isNodeJS = false; + + var pkg_xmlhttprequest = "xmlhttprequest", + pkg_nodeLocalstorage = "node-localstorage", + pkg_nativescriptLocalstorage = "nativescript-localstorage", + pkg_fileSystemAccess = "file-system/file-system-access" + ; + + // If XMLHttpRequest is undefined, enviroment would appear to be Node.js + // load xmlhttprequest module + // Web browser and NativeScript clients have a built-in XMLHttpRequest object + if (typeof XMLHttpRequest === "undefined") { + isNodeJS = true; + try { + XMLHttpRequest = require("" + pkg_xmlhttprequest).XMLHttpRequest; + // xhrc = require("xmlhttprequest-cookie"); + // XMLHttpRequest = xhrc.XMLHttpRequest; + } catch(e) { + console.error("Error: JSDO library requires XMLHttpRequest object in Node.js.\n" + + "Please install xmlhttprequest package."); + } + } + + // Detect if the environment is NativeScript + if (!isNodeJS + && (typeof localStorage === "undefined" + || typeof sessionStorage === "undefined")) { + try { + require("" + pkg_fileSystemAccess); + isNativeScript = true; + } catch(exception1) { + isNativeScript = false; + } + } + + // If localStorage or sessionStorage is not defined, + // we need to load the corresponding support module + + // If environment is NativeScript, load required modules + if (isNativeScript) { + try { + // load module nativescript-localstorage + if (typeof sessionStorage === "undefined") { + sessionStorage = require("" + pkg_nativescriptLocalstorage); + } + if (typeof localStorage === "undefined") { + localStorage = require("" + pkg_nativescriptLocalstorage); + } + } catch(exception2) { + console.error("Error: JSDO library requires localStorage and sessionStorage objects in NativeScript.\n" + + "Please install nativescript-localstorage package."); + } + + // load module base-64 + try { + if (typeof btoa === "undefined") { + btoa = require("base-64").encode; + } + } catch(exception3) { + console.error("Error: JSDO library requires btoa() function in NativeScript.\n" + + "Please install base-64 package."); + } + } + + // If environment is NodeJS, load module node-localstorage + if (isNodeJS) { + var LocalStorage; + if (typeof localStorage === "undefined") { + try { + var module = require("" + pkg_nodeLocalstorage); + LocalStorage = module.LocalStorage; + localStorage = new LocalStorage('./scratch1'); + } catch(e) { + console.error("Error: JSDO library requires localStorage and sessionStorage objects in Node.js.\n" + + "Please install node-localstorage package."); + } + } + + if (typeof sessionStorage === "undefined" + && typeof LocalStorage !== "undefined") { + sessionStorage = new LocalStorage('./scratch2'); + } + + // load module base-64 + try { + if (typeof btoa === "undefined") { + btoa = require("base-64").encode; + } + } catch(exception3) { + console.error("Error: JSDO library requires btoa() function in Node.js.\n" + + "Please install base-64 package."); + } + } +}()); + +(function () { + + /* Define these if not defined yet - they may already be defined if + * progress.js was included first */ + if (typeof progress === "undefined") { + progress = {}; + } + + if (typeof progress.data === "undefined") { + progress.data = {}; + } + + progress.util = {}; + + var STRING_OBJECT_TYPE = "String", + DATE_OBJECT_TYPE = "Date", + CHARACTER_ABL_TYPE = "CHARACTER"; + + /** + * Deferred class to provide access to ES6 and JQuery Promises. + * + * @class + */ + progress.util.Deferred = /** @class */ (function () { + function Deferred() { + this._deferred = {}; + } + + /** + * Returns a Promise object. + */ + Deferred.prototype.promise = function () { + var that = this; + + if (progress.util.Deferred.useJQueryPromises) { + if (typeof($) !== 'undefined' && typeof($.Deferred) === 'function') { + this._deferred._jQuerydeferred = $.Deferred(); + this._promise = this._deferred._jQuerydeferred.promise(); + } else { + throw new Error("JQuery Promises not found in environment."); + } + } else { + this._promise = new Promise(function (resolve, reject) { + that._deferred.resolve = resolve; + that._deferred.reject = reject; + }); + } + + if (this._resolveArguments || this._rejectArguments) { + setTimeout(function () { + if (that._resolveArguments) { + that.resolve.apply(that, that._resolveArguments); + } else if (that._rejectArguments) { + that.reject.apply(that, that._rejectArguments); + } + }, 500); + } + + // return null; + return this._promise; + + }; + + /** + * Calls the underlying resolve() method. + */ + Deferred.prototype.resolve = function (arg1, arg2, arg3) { + if (this._promise) { + if (this._deferred._jQuerydeferred) { + this._deferred._jQuerydeferred.resolve.apply(this, arguments); + } else { + var object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); + this._deferred.resolve(object); + } + } else { + this._resolveArguments = arguments; + } + }; + + /** + * Calls the underlying reject() method. + */ + Deferred.prototype.reject = function (arg1, arg2, arg3) { + if (this._promise) { + if (this._deferred._jQuerydeferred) { + this._deferred._jQuerydeferred.reject.apply(this, arguments); + } else { + var object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); + this._deferred.reject(object); + } + } else { + this._rejectArguments = arguments; + } + }; + + /** + * @property {boolean} useJQueryPromises - Tells the Deferred object to use jQuery Promises. + */ + Deferred.useJQueryPromises = false; + + /** + * Returns a deferred object based on a collection. + */ + Deferred.when = function (deferreds) { + if (progress.util.Deferred.useJQueryPromises) { + return $.when.apply($, deferreds); + } else { + return Promise.all(deferreds); + } + } + + /** + * Returns an object with the parameters to resolve()/reject(). + */ + Deferred.getParamObject1 = function (arg1, arg2, arg3) { + var object = {}, + objectName; + + try { + if ((typeof(arg1) === "undefined") || (arg1 === null)) { + object.result = arg2; + object.info = arg3; + } else { + objectName = arg1.constructor.name.toLowerCase(); + if (!objectName) { + objectName = typeof(arg1); + } + + // Map some object name to use a particular property name + switch (objectName) { + case "authenticationprovider": + objectName = "provider" + break; + case "number": + objectName = "result" + break; + default: + break; + } + object[objectName] = arg1; + if (objectName === "jsdo") { + object.success = arg2; + if (arg3 && arg3.xhr) { + object.request = arg3; + } else { + object.info = arg3; + } + } else { + if (objectName === "result") { + object.info = arg2; + if (arg3) { + object.info2 = arg3; + } + } else { + object.result = arg2; + object.info = arg3; + } + } + } + } catch(e) { + console.log("Error: Undetermined argument in getParamObject() call."); + } + + return object; + } + + /** + * Returns an object with the parameters to resolve()/reject() based on the Promise type. + */ + Deferred.getParamObject = function (arg1, arg2, arg3) { + var object = {}; + + if (progress.util.Deferred.useJQueryPromises) { + object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); + } else { + if (typeof(arg1) === "undefined") { + object.result = arg2; + object.info = arg3; + arg1 = object; + } + return arg1; + } + + return object; + }; + + return Deferred; + }()); + + /** + * Utility class that allows subscribing and unsubscribing from named events. + * + * @returns {progress.util.Observable} + */ + progress.util.Observable = function () { + /* + * Example format of the events object. Some event delegates may only + * have a function setup, others may optionally have scope, and possibly an operation filter + * + * var events = { + * afterfill : [{ + * scope : {}, // this is optional + * fn : function () {}, + * operation : 'getCustomers' // this is optional + * }, ...] + * + * } + * + * + * + */ + + /* + * remove the given function from the array of observers + */ + function _filterObservers(observers, fn, scope, operation) { + return observers.filter(function (el) { + if (el.fn !== fn || el.scope !== scope || el.operation !== operation) { + return el; + } + }, this); + } + + /* + * validate the arguments passed to the subscribe function + */ + this.validateSubscribe = function (args, evt, listenerData) { + + if (args.length >= 2 && (typeof args[0] === 'string') && (typeof args[1] === 'string')) { + listenerData.operation = args[1]; + listenerData.fn = args[2]; + listenerData.scope = args[3]; + + } else if (args.length >= 2 && (typeof args[0] === 'string') && (typeof args[1] === 'function')) { + listenerData.operation = undefined; + listenerData.scope = args[2]; + listenerData.fn = args[1]; + } else { + throw new Error(); + } + + }; + + + /* + * bind the specified function so it receives callbacks when the + * specified event name is called. Event name is not case sensitive. + * An optional scope can be provided so that the function is executed + * in the given scope. If no scope is given, then the function will be + * called without scope. + * + * If the same function is registered for the same event a second time with + * the same scope the original subscription is removed and replaced with the new function + * to be called in the new scope. + * + * This method has two signatures. + * + * Signature 1: + * @param evt The name of the event to bind a handler to. String. Not case sensitive. + * @param fn The function callback for the event . Function. + * @param scope The scope the function is to be run in. Object. Optional. + * + * Signature 2: + * + * @param evt The name of the event to bind a handler to. String. Not case sensitive + * @param operation The name of the operation to bind to. String. Case sensitive. + * @param fn The function callback for the event . Function. + * @param scope The scope the function is to be run in. Object. Optional. + + */ + this.subscribe = function (evt, operation, fn, scope) { + var listenerData, + observers; + + if (!evt) { + throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "subscribe")); + } + + if (typeof evt !== 'string') { + throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), + "subscribe", progress.data._getMsgText("jsdoMSG039"))); + } + + this._events = this._events || {}; + evt = evt.toLowerCase(); + listenerData = {fn: undefined, scope: undefined, operation: undefined}; + + try { + this.validateSubscribe(arguments, evt, listenerData); + } catch (e) { + throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), + "subscribe", e.message)); + } + + observers = this._events[evt] || []; + + // make sure we don't add duplicates + observers = _filterObservers(observers, listenerData.fn, + listenerData.scope, listenerData.operation); + observers.push(listenerData); + this._events[evt] = observers; + + return this; + }; + + /* + * remove the specified function so it no longer receives events from + * the given name. event name is not case sensitive. + * + * This method has two signaturues. + * Signature 1: + * @param evt Required. The name of the event for which to unbind the given function. String. + * @param fn Required. The function to remove from the named event. Function. + * @param scope Optional. The function scope in which to remove the listener. Object. + * + * Signature 2: + * + * @param evt Required. The name of the event for which to unbind the given function. + String. Not case sensitive + * @param operation Required. The name of the operation to receive events. String. Case Sensitive + * @param fn Required. The function to remove from the named event. Function. + * @param scope Optional. The function scope in which to remove the listener. Object. + * + */ + this.unsubscribe = function (evt, operation, fn, scope) { + var listenerData, + observers; + + if (!evt) { + throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "unsubscribe")); + } + + if (typeof evt !== 'string') { + throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), + "unsubscribe", progress.data._getMsgText("jsdoMSG037"))); + } + + this._events = this._events || {}; + evt = evt.toLowerCase(); + listenerData = {fn: undefined, scope: undefined, operation: undefined}; + try { + this.validateSubscribe(arguments, evt, listenerData); + } catch (e) { + // throw new Error("Invalid signature for unsubscribe. " + e.message); + throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), + "unsubscribe", e.message)); + } + + observers = this._events[evt] || []; + if (observers.length > 0) { + this._events[evt] = _filterObservers(observers, listenerData.fn, + listenerData.scope, listenerData.operation); + } + + return this; + }; + + /* + * trigger an event of the given name, and pass the specified data to + * the subscribers of the event. Event name is not case sensitive. + * A variable numbers of arguments can be passed as arguments to the event handler. + * + * This method has two signatures + * Signature 1: + * @param evt The name of the event to fire. String. Not case sensitive. + * @param operation The name of the operation. String. Case sensitive + * @param args Optional. A variable number of arguments to pass to the event handlers. + * + * Signature 2: + * @param evt The name of the event to fire. String. Not case sensitive + * @param args Optional. A variable number of arguments to pass to the event handlers. + */ + this.trigger = function (evt, operation, args) { + var observers, + op; + + if (!evt) { + throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "trigger")); + } + + this._events = this._events || {}; + evt = evt.toLowerCase(); + observers = this._events[evt] || []; + if (observers.length > 0) { + args = Array.prototype.slice.call(arguments); + + if ((arguments.length >= 2) + && (typeof evt === 'string') + && (typeof operation === 'string')) { + // in alt format the second argument is the event name, + // and the first is the operation name + op = operation; + args = args.length > 2 ? args.slice(2) : []; + } else if (arguments.length >= 1 && (typeof evt === 'string')) { + op = undefined; + args = args.length > 1 ? args.slice(1) : []; + } else { + throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), "trigger")); + } + + observers.forEach(function (el) { + if (el.operation === op) { + el.fn.apply(el.scope, args); + } + }); + + } + + return this; + }; + + // unbind all listeners from the given event. If the + // evt is undefined, then all listeners for all events are unbound + // evnt name is not case sensitive + // @param evt Optional. The name of the event to unbind. If not passed, then all events are unbound + this.unsubscribeAll = function (evt, operation) { + var observers; + + if (evt) { + this._events = this._events || {}; + if (typeof evt === 'string') { + evt = evt.toLowerCase(); + observers = this._events[evt] || []; + + observers.forEach(function (el) { + if (el.operation) { + this.unsubscribe(evt, el.operation, el.fn, el.scope); + } else { + this.unsubscribe(evt, el.fn, el.scope); + } + }, this); + } + } else { + this._events = {}; + } + + return this; + }; + }; + + + /** + * Utility class that saves/reads data to localStorage + * + * @returns {progress.data.LocalStorage} + */ + progress.data.LocalStorage = function LocalStorage() { + + /*global localStorage */ + if (typeof localStorage === "undefined") { + // "progress.data.LocalStorage: No support for localStorage." + throw new Error(progress.data._getMsgText("jsdoMSG126", "progress.data.LocalStorage", "localStorage")); + } + + + // "Methods" + + this.saveToLocalStorage = function (name, dataObj) { + localStorage.setItem(name, JSON.stringify(dataObj)); + }; + + this.readFromLocalStorage = function (name) { + + var jsonStr = localStorage.getItem(name), + dataObj = null; + + if (jsonStr !== null) { + try { + dataObj = JSON.parse(jsonStr); + } catch (e) { + dataObj = null; + } + } + return dataObj; + }; + + this.clearLocalStorage = function (name) { + localStorage.removeItem(name); + }; + + }; // End of LocalStorage + + + ///////////////////////////////////////////////////////////////////////////////////////// + // Utility Functions + + /* + * Converts the specified filter object to an OpenEdge ABL Where String. + * + * @param tableRef - handle to the table in jsdo, where string is applied to. + * @param filter - the filter object to convert. + * + * @returns - translated OE where string. + */ + progress.util._convertToABLWhereString = function (tableRef, filter) { + var result = [], + logic = filter.logic || "and", + idx, + length, + field, + fieldInfo, + type, + format, + operator, + value, + ablType, + //filters = (filter.filters) ? filter.filters : [filter], + filters = filter.filters || [filter], + + whereOperators = { + eq: "=", + neq: "<>", + gt: ">", + gte: ">=", + lt: "<", + lte: "<=", + contains : "INDEX", + doesnotcontain: "INDEX", + endswith: "R-INDEX", + startswith: "BEGINS", + isnull: "ISNULL", + isnotnull: "ISNOTNULL", + isempty: "ISEMPTY", + isnotempty: "ISNOTEMPTY" + }; + + for (idx = 0, length = filters.length; idx < length; idx += 1) { + filter = filters[idx]; + field = filter.field; + value = filter.value; + + if (filter.filters) { + filter = progress.util._convertToABLWhereString(tableRef, filter); + } else { + // Use original field name instead of serialized name + if (field && tableRef._name) { + fieldInfo = tableRef._jsdo[tableRef._name]._fields[field.toLowerCase()]; + if (fieldInfo && fieldInfo.origName) { + field = fieldInfo.origName; + } + } + + operator = whereOperators[filter.operator]; + + if (operator === undefined) { + throw new Error("The operator " + filter.operator + " is not valid."); + } + + switch (filter.operator) { + case "isnull": + case "isnotnull": + case "isempty": + case "isnotempty": + value = undefined; + break; + } + + if (operator && value !== undefined) { + type = progress.util._getObjectType(value); + + // We need to build a template format string for the where string. + // We'll first add positional info for the value + if (type === STRING_OBJECT_TYPE) { + format = "'{1}'"; + value = value.replace(/'/g, "~'"); + } else if (type === DATE_OBJECT_TYPE) { + ablType = tableRef._getABLType(field); + if (ablType === "DATE") { + format = "DATE({1:MM, dd, yyyy})"; + } else if (ablType === "DATETIME-TZ") { + // zzz here means to translate timezone offset into minutes + format = "DATETIME-TZ({1:MM, dd, yyyy, hh, mm, ss, fff, zzz})"; + } else { + format = "DATETIME({1:MM, dd, yyyy, hh, mm, ss, fff})"; + } + } else { + format = "{1}"; + } + + // Most where strings are in the format: field operator value. Ex. custnum < 100 + // An exception to this is INDEX() and R-INDEX() which have format: operator field value + // Ex. R-INDEX(name, "LTD") + if (operator === "INDEX" || operator === "R-INDEX") { + if (type !== STRING_OBJECT_TYPE) { + throw new Error("Error parsing filter object. The operator " + filter.operator + + " requires a string value"); + } + if (filter.operator === "doesnotcontain") { + format = "{0}(" + "{2}, " + format + ") = 0"; + } else if (filter.operator === "contains") { + format = "{0}(" + "{2}, " + format + ") > 0"; + } else { // else filter.operator = "endswith" + format = "{2} MATCHES '*{1}'"; + } + } else { + format = "{2} {0} " + format; + } + + filter = progress.util._format(format, operator, value, field); + } else if (operator && value === undefined) { + if (filter.operator === "isempty" || filter.operator === "isnotempty") { + ablType = tableRef._getABLType(field); + if (ablType !== CHARACTER_ABL_TYPE) { + throw new Error("Error parsing filter object. The operator " + filter.operator + + " requires a CHARACTER field"); + } + if (filter.operator === "isempty") { + format = "{2} = ''"; + } else if (filter.operator === "isnotempty") { + format = "{2} <> ''"; + } + } else { + if (filter.operator === "isnull") { + format = "{2} = ?"; + } else if (filter.operator === "isnotnull") { + format = "{2} <> ?"; + } else { + format = "{2} {0} ?"; + } + } + + // format, operator {0}, value {1}, field {2} + filter = progress.util._format(format, operator, value, field); + } + } + + result.push(filter); + } + + filter = result.join(" " + logic + " "); + + if (result.length > 1) { + filter = "(" + filter + ")"; + } + + return filter; + }; + + + /* + * Converts the specified filter object to an SQL Query String. + * + * @param tableName - tableName of table in jsdo, where clause is applied to. + * @param filter - the filter object to convert. + * + * @returns - translated SQL where clause. + */ + progress.util._convertToSQLQueryString = function (tableRef, filter, addSelect) { + var result = [], + logic = filter.logic || "and", + idx, + length, + field, + type, + format, + operator, + value, + fieldFormat, + filters = filter.filters || [filter], + filterStr, + usingLike = true, + + whereOperators = { + eq: "=", + neq: "!=", + gt: ">", + gte: ">=", + lt: "<", + lte: "<=", + contains : "LIKE", + doesnotcontain: "NOT LIKE", + endswith: "LIKE", + startswith: "LIKE", + isnull: "ISNULL", + isnotnull: "ISNOTNULL", + isempty: "ISEMPTY", + isnotempty: "ISNOTEMPTY" + }; + + if (typeof addSelect === "undefined") { + addSelect = false; + } + + for (idx = 0, length = filters.length; idx < length; idx += 1) { + filter = filters[idx]; + field = filter.field; + value = filter.value; + + if (filter.filters) { + filterStr = progress.util._convertToSQLQueryString(tableRef, filter, false); + } else { + operator = whereOperators[filter.operator]; + + if (operator === undefined) { + throw new Error("The operator " + filter.operator + " is not valid."); + } + + switch (filter.operator) { + case "isnull": + case "isnotnull": + case "isempty": + case "isnotempty": + value = undefined; + break; + } + + if (operator && value !== undefined) { + type = progress.util._getObjectType(value); + + if (operator === "LIKE" || operator === "NOT LIKE") { + if (type !== STRING_OBJECT_TYPE) { + throw new Error("Error parsing filter object. The operator " + filter.operator + + " requires a string value"); + } + } + + if (type === STRING_OBJECT_TYPE) { + format = "'{1}'"; + value = value.replace(/'/g, "''"); + } else if (type === DATE_OBJECT_TYPE) { + fieldFormat = tableRef._getFormat(field); + if (fieldFormat === "date") { + format = "'{1:yyyy-MM-dd}'"; + } else if (fieldFormat === "date-time") { + format = "{1:#ISO(iso)}"; + } else if (fieldFormat === "time") { + format = "'{1:FFF}'"; + } + } else { + format = "{1}"; + } + + // We need to build a template format string for the where string. + // We'll first add positional info for the value, which is represented by {1} + if (filter.operator === "startswith") { + format = "'{1}%'"; + } else if (filter.operator === "endswith") { + format = "'%{1}'"; + } else if (filter.operator === "contains" || filter.operator === "doesnotcontain") { + format = "'%{1}%'"; + } else { + usingLike = false; + } + + if (usingLike) { + value = value.replace(/%/g, '\\%'); + value = value.replace(/_/g, '\\_'); + } + + format = "{2} {0} " + format; + filterStr = progress.util._format(format, operator, value, field); + } else if (operator && value === undefined) { + if (filter.operator === "isempty" || filter.operator === "isnotempty") { + type = tableRef._fields[field.toLowerCase()].type; + if (type !== STRING_OBJECT_TYPE.toLowerCase()) { + throw new Error("Error parsing filter object. The operator " + filter.operator + + " requires a string field"); + } + if (filter.operator === "isempty") { + format = "{2} = ''"; + } else if (filter.operator === "isnotempty") { + format = "{2} != ''"; + } + } else { + if (filter.operator === "isnull") { + format = "{2} IS NULL"; + } else if (filter.operator === "isnotnull") { + format = "{2} IS NOT NULL"; + } else { + format = "{2} {0} NULL"; + } + } + + // format, operator {0}, value {1}, field {2} + filterStr = progress.util._format(format, operator, value, field); + } + } + + result.push(filterStr); + } + + filterStr = result.join(" " + logic + " "); + + if (result.length > 1) { + filterStr = "(" + filterStr + ")"; + } + + if (addSelect === true) { + filterStr = "SELECT * FROM " + tableRef._name + " WHERE " + filterStr; + } + + return filterStr; + }; + + + /* + * Returns the object type; Example "String", "Date" + * Constants for object type values are defined above. + * + * @param value - the object whose type is returned + */ + progress.util._getObjectType = function (value) { + // Returns [object xxx]. Removing [object ] + return Object.prototype.toString.call(value).slice(8, -1); + }; + + + /* + * Substitutes in a variable number of arguments into specified format string (with place-holders) + * + * @param fmt - the format string with place-holders, eg. "{0} text {1}". + * + * @returns - formatted string. + */ + progress.util._format = function (fmt) { + /*jslint regexp: true*/ + var values = arguments, + formatRegExp = /\{(\d+)(:[^\}]+)?\}/g; + /*jslint regexp: false*/ + + return fmt.replace(formatRegExp, function (match, index, placeholderFormat) { + var value = values[parseInt(index, 10) + 1]; + + return progress.util._toString(value, placeholderFormat ? placeholderFormat.substring(1) : ""); + }); + + }; + + /* + * Converts the specified value param to a string. + * + * @param value - object to convert + * @param fmt - optional format string with place-holders, eg. "MM dd yyyy". + * + * @returns - converted string. + */ + progress.util._toString = function (value, fmt) { + var str; + + if (fmt) { + if (progress.util._getObjectType(value) === "Date") { + return progress.util._formatDate(value, fmt); + } + } + + if (typeof value === "number") { + str = value.toString(); + } else { + str = (value !== undefined ? value : ""); + } + + return str; + }; + + /* + * Accepts string representing number and optionally pads it with "0"'s to conform to + * specified number of digits. + * + * @param number - string representing number to pad. + * @param digit - number of digits desired for padded string. If not specified, default is 2. + * + * @returns - padded string representing number. + */ + progress.util._pad = function (number, digits) { + var zeros = ["", "0", "00", "000", "0000"], + end; + + number = String(number); + digits = digits || 2; + end = digits - number.length; + + if (end) { + return zeros[digits].substring(0, end) + number; + } + return number; + }; + + /* + * Converts the specified date param to a string. + * + * @param date - date object to convert + * @param fmt - format string with place-holders, eg. "MM dd yyyy". + * + * @returns - converted string. + */ + progress.util._formatDate = function (date, format) { + /*jslint regexp: true*/ + var dateFormatRegExp = + /dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g; + /*jslint regexp: false*/ + + return format.replace(dateFormatRegExp, function (match) { + var minutes, + result, + sign; + + if (match === "dd") { + result = progress.util._pad(date.getDate()); + } else if (match === "MM") { + result = progress.util._pad(date.getMonth() + 1); + } else if (match === "yyyy") { + result = progress.util._pad(date.getFullYear(), 4); + } else if (match === "hh") { + result = progress.util._pad(date.getHours()); + } else if (match === "mm") { + result = progress.util._pad(date.getMinutes()); + } else if (match === "ss") { + result = progress.util._pad(date.getSeconds()); + } else if (match === "fff") { + result = progress.util._pad(date.getMilliseconds(), 3); + } else if (match === "FFF") { + result = String(date.getTime()); + } else if (match === "zzz") { + // timezone is returned in minutes + minutes = date.getTimezoneOffset(); + sign = minutes < 0; + result = (sign ? "+" : "-") + minutes; + } else if (match === "iso") { + result = date.toISOString(); + } + + return result !== undefined ? result : match.slice(1, match.length - 1); + }); + }; + + /* + * Processes settings in a jsdoSettings object. + * This method is used by project templates. + */ + progress.util.jsdoSettingsProcessor = function jsdoSettingsProcessor(jsdoSettings) { + if (typeof jsdoSettings === 'object') { + if (jsdoSettings.authenticationModel === undefined || jsdoSettings.authenticationModel === "") { + jsdoSettings.authenticationModel = "ANONYMOUS"; + } + } + }; + +}()); + +/* +progress.js Version: 5.0.0 + +Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ + +/*global $, progress:true*/ +(function () { + + // "use strict"; + + var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS = 20, + PROGRESS_JSDO_OP_STRING = ["none", "create", "read", "update", "delete", "submit"], + PROGRESS_JSDO_ROW_STATE_STRING = ["", "created", "", "modified", "deleted"]; + + /* define these if not defined yet - they may already be defined if + progress.session.js was included first */ + if (typeof progress === 'undefined') { + progress = {}; + } + if (typeof progress.data === 'undefined') { + progress.data = {}; + } + + progress.data._nextid = 0; + progress.data._uidprefix = "" + ( Date.now ? Date.now() : (new Date().getTime())); + + /* 15 - 9 */ + var UID_MAX_VALUE = 999999999999999; + + progress.data._getNextId = function () { + var uid = ++progress.data._nextid; + if (uid >= UID_MAX_VALUE) { + progress.data._nextid = uid = 1; + progress.data._uidprefix = "" + ( Date.now ? Date.now() : (new Date().getTime())); + } + + return progress.data._uidprefix + "-" + uid; + }; + + + var msg = {}; + msg.msgs = {}; + // msg numbers 0 - 99 are related to use of the API (methods and properties we expose to developers) + // 100 - 109 relate to network errors + // 110 - 998 are for miscellaneous errors + + msg.msgs.jsdoMSG000 = "JSDO, Internal Error: {1}"; + msg.msgs.jsdoMSG001 = "JSDO: JSDO has multiple tables. Please use {1} at the table reference level."; + msg.msgs.jsdoMSG002 = "JSDO: Working record for '{1}' is undefined."; + msg.msgs.jsdoMSG003 = "JSDO: {1} function requires a function as a parameter."; + msg.msgs.jsdoMSG004 = "JSDO: Unable to find resource '{1}' in the catalog."; + msg.msgs.jsdoMSG005 = "JSDO: Data for table '{1}' was not specified in addRecords() call."; + msg.msgs.jsdoMSG006 = "JSDO: Data for JSDO was not specified in addRecords() call."; + msg.msgs.jsdoMSG007 = "JSDO: Test function in {1} must return a boolean."; + msg.msgs.jsdoMSG008 = "JSDO: Invalid keyFields parameter in addRecords() call."; + msg.msgs.jsdoMSG009 = "JSDO: KeyField '{1}' in addRecords() call was not found in the schema."; + msg.msgs.jsdoMSG010 = "JSDO: Field '{1}' in relationship was not found in the schema."; + msg.msgs.jsdoMSG011 = "UIHelper: JSDO has multiple tables. " + + "Please use {1} at the table reference level."; + msg.msgs.jsdoMSG012 = "UIHelper: Invalid {2} parameter in {1} call."; + msg.msgs.jsdoMSG020 = "JSDO: tableName parameter must be a string in addRecords() call."; + msg.msgs.jsdoMSG021 = "JSDO: addMode parameter must be specified in addRecords() call."; + msg.msgs.jsdoMSG022 = "JSDO: Invalid addMode specified in addRecords() call."; + msg.msgs.jsdoMSG023 = "JSDO: Duplicate found in addRecords() call using APPEND mode."; + msg.msgs.jsdoMSG024 = "{1}: Unexpected signature in call to {2} function."; + msg.msgs.jsdoMSG025 = "{1}: Invalid parameters in call to {2} function."; + msg.msgs.jsdoMSG026 = "JSDO: saveChanges requires a " + + "CREATE, UPDATE, DELETE or SUBMIT operation to be defined."; + msg.msgs.jsdoMSG030 = "JSDO: Invalid {1}, expected {2}."; + msg.msgs.jsdoMSG031 = "JSDO: Specified sort field name '{1}' was not found in the schema."; + msg.msgs.jsdoMSG032 = "JSDO: Before-image data already exists for record in addRecords() call."; + msg.msgs.jsdoMSG033 = "{1}: Invalid signature for {2}. {3}"; + msg.msgs.jsdoMSG034 = "JSDO: In '{1}' function, JSON data is missing _id"; + msg.msgs.jsdoMSG035 = "JSDO: In '{1}' function, before-image JSON data is missing prods:clientId"; + msg.msgs.jsdoMSG036 = "JSDO: '{1}' can only be called for a dataset"; + msg.msgs.jsdoMSG037 = "{1}: Event name must be provided for {2}."; + msg.msgs.jsdoMSG038 = "Too few arguments. There must be at least {1}."; + msg.msgs.jsdoMSG039 = "The name of the event is not a string."; + msg.msgs.jsdoMSG040 = "The event listener is not a function."; + msg.msgs.jsdoMSG041 = "The event listener scope is not an object."; + msg.msgs.jsdoMSG042 = "'{1}' is not a defined event for this object."; + msg.msgs.jsdoMSG043 = "{1}: A session object was requested to check the status of a Mobile " + + "Service named '{2}', but it has not loaded the definition of that service."; + msg.msgs.jsdoMSG044 = "JSDO: In '{1}' function, {2} is missing {3} property."; + msg.msgs.jsdoMSG045 = "JSDO: {1} function: {2} is missing {3} property."; + msg.msgs.jsdoMSG046 = "JSDO: {1} operation is not defined."; + msg.msgs.jsdoMSG047 = "{1} timeout expired."; + msg.msgs.jsdoMSG048 = "{1}: {2} method has argument '{3}' that is missing property '{4}'."; + msg.msgs.jsdoMSG049 = "{1}: Unexpected error calling {2}: {3}"; + msg.msgs.jsdoMSG050 = "No token returned from server"; + msg.msgs.jsdoMSG051 = "{1} The login method was not executed because the AuthenticationProvider is already logged in."; + msg.msgs.jsdoMSG052 = "{1}: The login method was not executed because no credentials were supplied."; + msg.msgs.jsdoMSG053 = "{1}: {2} was not executed because the AuthenticationProvider is not logged in."; + msg.msgs.jsdoMSG054 = "{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token."; + msg.msgs.jsdoMSG055 = "{1}: Token refresh was not executed because the authentication model is not sso."; + msg.msgs.jsdoMSG056 = "{1}: Already logged in."; + msg.msgs.jsdoMSG057 = "{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead."; + msg.msgs.jsdoMSG058 = "{1}: Cannot pass username and password to addCatalog when authenticationModel " + + "is sso. Pass an AuthenticationProvider instead."; + msg.msgs.jsdoMSG059 = "{1}: Error in constructor. The authenticationModels of the " + + "AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible."; + msg.msgs.jsdoMSG060 = "AuthenticationProvider: AuthenticationProvider is no longer logged in. " + + "Tried to refresh SSO token but failed due to authentication error at token server."; + msg.msgs.jsdoMSG061 = "{1}: Attempted to set {2} property to an invalid value."; + msg.msgs.jsdoMSG062 = "{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in."; + + // 100 - 109 relate to network errors + msg.msgs.jsdoMSG100 = "JSDO: Unexpected HTTP response. Too many records."; + msg.msgs.jsdoMSG101 = "Network error while executing HTTP request."; + + // 110 - 499 are for miscellaneous errors + msg.msgs.jsdoMSG110 = "Catalog error: idProperty not specified for resource '{1}'. " + + "idProperty is required {2}."; + msg.msgs.jsdoMSG111 = "Catalog error: Schema '{1}' was not found in catalog."; + msg.msgs.jsdoMSG112 = "Catalog error: Output parameter '{1}' was not found for operation '{2}'."; + msg.msgs.jsdoMSG113 = "Catalog error: Found xType '{1}' for output parameter '{2}' " + + "for operation '{3}' but xType DATASET, TABLE or ARRAY was expected."; + msg.msgs.jsdoMSG114 = "JSDO: idProperty '{1}' is missing from '{2}' record."; + msg.msgs.jsdoMSG115 = "JSDO: Invalid option specified in {1}() call."; + msg.msgs.jsdoMSG116 = "JSDO: {1} parameter must be a string in {2} call."; + msg.msgs.jsdoMSG117 = "JSDO: Schema from storage area '{1}' does not match JSDO schema"; + msg.msgs.jsdoMSG118 = "JSDO: Plugin '{1}' was not found."; + msg.msgs.jsdoMSG119 = "JSDO: A mappingType is expected when 'capabilities' is set." + + " Please specify a plugin (ex: JFP)."; + msg.msgs.jsdoMSG120 = "JSDO: Parameter '{2}' requires capability '{1}' in the catalog."; + msg.msgs.jsdoMSG121 = "{1}: Argument {2} must be of type {3} in {4} call."; + msg.msgs.jsdoMSG122 = "{1}: Incorrect number of arguments in {2} call. There should be {3}."; + msg.msgs.jsdoMSG123 = "{1}: A server response included an invalid '{2}' header."; + msg.msgs.jsdoMSG124 = "JSDO: autoApplyChanges is not supported for saveChanges(true) " + + "with a temp-table. Use jsdo.autoApplyChanges = false."; + msg.msgs.jsdoMSG125 = "{1}: The AuthenticationProvider is not managing valid credentials."; + msg.msgs.jsdoMSG126 = "{1}: No support for {2}."; + msg.msgs.jsdoMSG127 = "JSDO: acceptRowChanges() cannot be called for record with _rejected === true."; + + // 500 - 998 are for generic errors + msg.msgs.jsdoMSG500 = "{1}: '{2}' objects must contain a '{3}' property."; + msg.msgs.jsdoMSG501 = "{1}: '{2}' in '{3}' function cannot be an empty string."; + msg.msgs.jsdoMSG502 = "{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for " + + "its '{4}' property."; + msg.msgs.jsdoMSG503 = "{1}: '{2}' must be of type '{3}'."; + msg.msgs.jsdoMSG504 = "{1}: {2} has an invalid value for the '{3}' property."; + msg.msgs.jsdoMSG505 = "{1}: '{2}' objects must have a '{3}' method."; + // use message below if invalid parameter value is an object + msg.msgs.jsdoMSG506 = "{1}: Invalid argument for the {2} parameter in {3} call."; + // use message below if invalid parameter value is a primitive + msg.msgs.jsdoMSG507 = "{1}: '{2}' is an invalid value for the {3} parameter in {4} call."; + msg.msgs.jsdoMSG508 = "JSDOSession: If a JSDOSession object is using the SSO authentication model, " + + "the options object passed to its constructor must include an authProvider property."; + msg.msgs.jsdoMSG509 = "progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, " + + "authenticationURI and authProviderAuthenticationModel are required parameters."; + msg.msgs.jsdoMSG510 = "{1}: This session has been invalidated and cannot be used."; + msg.msgs.jsdoMSG511 = "JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or " + + "connect() has been successfully called."; + msg.msgs.jsdoMSG512 = "JSDOSession: Error while loading multiple catalogs."; + + msg.msgs.jsdoMSG998 = "JSDO: JSON object in addRecords() must be DataSet or Temp-Table data."; + + msg.getMsgText = function (n, args) { + var text = msg.msgs[n], + i; + if (!text) { + throw new Error("Message text was not found by getMsgText()"); + } + for (i = 1; i < arguments.length; i += 1) { + text = text.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]); + } + + return text; + }; + + progress.data._getMsgText = msg.getMsgText; + + progress.data.PluginManager = {}; + progress.data.PluginManager._plugins = {}; + + progress.data.PluginManager.addPlugin = function(name, plugin) { + if (progress.data.PluginManager._plugins[name] === undefined) { + progress.data.PluginManager._plugins[name] = plugin; + } + else { + throw new Error("A plugin named '" + name + "' is already registered."); + } + }; + + progress.data.PluginManager.getPlugin = function (name) { + return progress.data.PluginManager._plugins[name]; + }; + + progress.data.JSIndexEntry = function JSIndexEntry(index) { + this.index = index; + }; + + progress.data.JSTableRef = function JSTableRef(jsdo, tableName) { + this._jsdo = jsdo; + this._name = tableName; + this._schema = null; + this._primaryKeys = null; + this._fields = null; + this._processed = {}; + this._visited = false; + + // record is used to represent the current record for a table reference + this.record = null; + + // Data structure + this._data = []; + this._index = {}; + this._tmpIndex = {}; + this._hasEmptyBlocks = false; + + // Arrays to keep track of changes + this._beforeImage = {}; + this._added = []; + this._changed = {}; + this._deleted = []; + this._lastErrors = []; + this._convertForServer; + + this._createIndex = function () { + var i, block, id, idProperty; + this._index = {}; + this._tmpIndex = {}; + this._hasEmptyBlocks = false; + for (i = 0; i < this._data.length; i += 1) { + block = this._data[i]; + if (!block) { + this._hasEmptyBlocks = true; + continue; + } + id = this._data[i]._id; + if (!id) { + idProperty = this._jsdo._resource.idProperty; + if (typeof(idProperty) == "string") { + id = this._data[i][idProperty]; + if (id === undefined) { + throw new Error(msg.getMsgText("jsdoMSG114", idProperty, this._name)); + } + id += ""; + } + else { + id = progress.data._getNextId(); + } + id += ""; // ID Property + this._data[i]._id = id; + } + this._index[id] = new progress.data.JSIndexEntry(i); + } + this._needCompaction = false; + }; + + this._compact = function () { + var newDataArray = [], i, block; + + for (i = 0; i < this._data.length; i += 1) { + block = this._data[i]; + if (block) { + newDataArray.push(block); + } + } + this._data = newDataArray; + this._createIndex(); + }; + + this._loadBeforeImageData = function (jsonObject, beforeImageJsonIndex, keyFields) { + var prodsBeforeData = jsonObject[this._jsdo._dataSetName]["prods:before"], + tmpIndex = {}, + record, + record2, + recordId, + key, + tmpKeyIndex, + id, + jsrecord, + tmpDataIndex, + tmpDeletedIndex, + i, + j; + + if (prodsBeforeData && prodsBeforeData[this._name]) { + + if ((Object.keys(this._beforeImage).length !== 0) && keyFields && (keyFields.length !== 0)) { + tmpKeyIndex = {}; + for (id in this._beforeImage) { + jsrecord = this._findById(id, false); + + if (jsrecord) { + key = this._getKey(jsrecord.data, keyFields); + tmpKeyIndex[key] = jsrecord.data; + } + } + } + + for (i = 0; i < prodsBeforeData[this._name].length; i++) { + record = prodsBeforeData[this._name][i]; + tmpIndex[record["prods:id"]] = record; + + if (record["prods:rowState"] == "deleted") { + key = undefined; + + if (keyFields && (keyFields.length !== 0)) { + key = this._getKey(record, keyFields); + } + + if (tmpKeyIndex) { + if (tmpKeyIndex[key] !== undefined) { + throw new Error(msg.getMsgText("jsdoMSG032")); + } + } + + if ((tmpDataIndex === undefined) && keyFields && (keyFields.length !== 0)) { + tmpDataIndex = {}; + tmpDeletedIndex = {}; + + for (var j = 0; j < this._data.length; j++) { + record2 = this._data[j]; + if (!record2) continue; + + var key2 = this._getKey(record2, keyFields); + tmpDataIndex[key2] = record2; + } + + // We also want to check if _deleted record already exists + for (j = 0; j < this._deleted.length; j++) { + record2 = this._deleted[j].data; + if (!record2) continue; + + var key2 = this._getKey(record2, keyFields); + tmpDeletedIndex[key2] = record2; + } + } + + // First check to see if this deleted record is already in _deleted array + if (key !== undefined) { + record2 = tmpDeletedIndex[key]; + if (record2 !== undefined) { + // If record is already in _deleted array, then nothing more to do here + continue; + } + } + + if (key !== undefined) { + record2 = tmpDataIndex[key]; + if (record2 !== undefined) { + var jsrecord = this._findById(record2._id, false); + if (jsrecord) jsrecord._remove(false); + record._id = record2._id; + } + } + + if (record._id === undefined) + record._id = progress.data._getNextId(); + var copy = {}; + this._jsdo._copyRecord( + this._tableRef, record, copy); + this._jsdo._deleteProdsProperties(copy); + this._beforeImage[record._id] = copy; + var jsrecord = new progress.data.JSRecord(this, copy); + this._deleted.push(jsrecord); + } + } + } + + // Process data using jsonObject instead of _data + // First check if there is after-data for table. Can be called with just before-image data + var tableObject = jsonObject[this._jsdo._dataSetName][this._name]; + if (tableObject) { + for (i = 0; i < jsonObject[this._jsdo._dataSetName][this._name].length; i++) { + record = jsonObject[this._jsdo._dataSetName][this._name][i]; + recordId = undefined; + if (beforeImageJsonIndex && record["prods:id"]) { + recordId = beforeImageJsonIndex[record["prods:id"]]; + } + switch (record["prods:rowState"]) { + case "created": + if (recordId === undefined) { + recordId = record._id; + } + + // If recordId and record._id are undefined, the record was not processed + if (recordId !== undefined) { + this._beforeImage[recordId] = null; + this._added.push(recordId); + } + break; + case "modified": + var beforeRecord = tmpIndex[record["prods:id"]]; + if (beforeRecord === undefined) { + beforeRecord = {}; + } + + if (recordId === undefined) { + recordId = record._id; + } + // If recordId and record._id are undefined, the record was not processed + if (recordId !== undefined) { + beforeRecord._id = record._id; + + var copy = {}; + this._jsdo._copyRecord( + this._tableRef, beforeRecord, copy); + this._jsdo._deleteProdsProperties(copy); + + this._beforeImage[recordId] = copy; + this._changed[recordId] = record; + + this._beforeImage[beforeRecord._id] = copy; + this._changed[beforeRecord._id] = record; + } + break; + case undefined: + break; // rowState is only specified for records that have changed + default: + throw new Error(msg.getMsgText("jsdoMSG030", + "rowState value in before-image data", "'created' or 'modified'")); + } + } + } + + // Process prods:errors + var prodsErrors = jsonObject[this._jsdo._dataSetName]["prods:errors"]; + if (prodsErrors) { + for (i = 0; i < prodsErrors[this._name].length; i++) { + var item = prodsErrors[this._name][i]; + var recordId = beforeImageJsonIndex[item["prods:id"]]; + var jsrecord = this._findById(recordId, false); + if (jsrecord) { + jsrecord.data._errorString = item["prods:error"]; + } + } + } + + tmpIndex = null; + }; + + /* + * Clears all data (including any pending changes) in buffer + */ + this._clearData = function () { + this._setRecord(null); + + // Data structure + this._data = []; + this._index = {}; + this._tmpIndex = {}; + this._createIndex(); + + // Arrays to keep track of changes + this._beforeImage = {}; + this._added = []; + this._changed = {}; + this._deleted = []; + }; + + this.hasData = function () { + var data; + + // Check if we should return this table with its nested child table's data as nested + if (this._jsdo._nestChildren) { + data = this._getDataWithNestedChildren(this._data); + } + else { + data = this._getRelatedData(); + } + + if (this._hasEmptyBlocks) { + for (var i = 0; i < data.length; i++) { + var block = data[i]; + if (!block) { + return true; + } + } + } + + return data.length !== 0; + }; + + // Public method that returns data. Before returning data, + // a compaction is performed (removal of null record entries) + this.getData = function (params) { + if (this._needCompaction || this._hasEmptyBlocks) { + this._compact(); + } + + return this._getData(params); + } + + // Private method that returns data. It optimizes compaction (removal of null record entries) + this._getData = function (params) { + var i, + data, + numEmptyBlocks, + newDataArray, + block, + field; + + if (this._needCompaction) { + this._compact(); + } + + if (params && params.filter) { + throw new Error("Not implemented in current version"); + } + // Check if we should return this table with its nested child table's data as nested + else if (this._jsdo._nestChildren) { + data = this._getDataWithNestedChildren(this._data); + } + else { + data = this._getRelatedData(); + } + + if (this._hasEmptyBlocks) { + numEmptyBlocks = 0; + newDataArray = []; + for (i = 0; i < data.length; i += 1) { + block = data[i]; + if (block) { + newDataArray.push(block); + } + else { + numEmptyBlocks++; + } + } + if ((numEmptyBlocks * 100 / this._data.length) >= PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS) + this._needCompaction = true; + + data = newDataArray; + } + else { + // Creates a copy of the data if sort and top are specified + // so that the sorting does not happen in the JSDO memory but + // in a copy of the records + if (params && (params.sort || params.top)) { + newDataArray = []; + for (i = 0; i < data.length; i += 1) { + newDataArray.push(data[i]); + } + data = newDataArray; + } + } + + if (params && (params.sort || params.top)) { + if (params.sort) { + // Converts sort option from Kendo UI to sort option used by the JSDO + var sortFields = []; + for (i = 0; i < params.sort.length; i += 1) { + field = params.sort[i].field; + if (params.sort[i].dir == "desc") { + field += ":DESC"; + } + sortFields.push(field); + } + + // Obtain sortObject from sort options to get compare functions + var sortObject = this._processSortFields(sortFields); + if (sortObject.sortFields && sortObject.sortFields.length > 0) { + sortObject.tableRef = this; + data.sort(this._getCompareFn(sortObject)); + } + } + + if (params.top) { + if (typeof(params.skip) == "undefined") { + params.skip = 0; + } + + data = data.splice(params.skip, params.top); + } + } + + return data; + }; + + this._recToDataObject = function (record, includeChildren) { + var array = [record]; + var dataObject = array; + + if (typeof(includeChildren) == 'undefined') { + includeChildren = false; + } + if (this._jsdo._dataSetName) { + dataObject = {}; + dataObject[this._jsdo._dataSetName] = {}; + dataObject[this._jsdo._dataSetName][this._name] = array; + if (includeChildren && this._children.length > 0) { + var jsrecord = this._findById(record._id, false); + if (jsrecord) { + for (var i = 0; i < this._children.length; i++) { + var tableName = this._children[i]; + dataObject[this._jsdo._dataSetName][tableName] = + this._jsdo._buffers[tableName]._getRelatedData(jsrecord); + } + } + } + } + else { + if (this._jsdo._dataProperty) { + dataObject = {}; + dataObject[this._jsdo._dataProperty] = array; + } + } + return dataObject; + }; + + this._recFromDataObject = function (dataObject) { + var data = {}; + if (dataObject) { + if (this._jsdo._dataSetName) { + if (dataObject[this._jsdo._dataSetName]) + data = dataObject[this._jsdo._dataSetName][this._name]; + } + else { + if (this._jsdo._dataProperty) { + if (dataObject[this._jsdo._dataProperty]) + data = dataObject[this._jsdo._dataProperty]; + } + else if (dataObject.data) { + data = dataObject.data; + } + else { + data = dataObject; + } + } + } + + return data instanceof Array ? data[0] : data; + }; + + // Property: schema + this.getSchema = function () { + return this._schema; + }; + this.setSchema = function (schema) { + this._schema = schema; + }; + + // Private method that returns the ABL data type for the specified field + this._getABLType = function (fieldName) { + var i, schema; + + schema = this.getSchema(); + + for (i = 0; i < schema.length; i++) { + if (schema[i].name == fieldName) { + return schema[i].ablType; + } + } + + return undefined; + }; + + // Private method that returns format property (from catalog) for the specified field + this._getFormat = function (fieldName) { + var i, schema; + + schema = this.getSchema(); + + for (i = 0; i < schema.length; i++) { + if (schema[i].name == fieldName) { + return schema[i].format; + } + } + + return undefined; + }; + + + + this.add = function (values) { + return this._add(values, true, true); + }; + + // Alias for add() method + this.create = this.add; + + this._add = function (values, trackChanges, setWorkingRecord) { + if (typeof(trackChanges) == 'undefined') { + trackChanges = true; + } + if (typeof(setWorkingRecord) == 'undefined') { + setWorkingRecord = true; + } + var record = {}, + i, + j, + value, + prefixElement, + name; + + if (typeof values === "undefined") { + values = {}; + } + + // Assign values from the schema + var schema = this.getSchema(); + for (i = 0; i < schema.length; i++) { + var fieldName = schema[i].name; + if (schema[i].type == "array") { + record[fieldName] = []; + if (schema[i].maxItems) { + for (j = 0; j < schema[i].maxItems; j++) { + record[fieldName][j] = this._jsdo._getDefaultValue(schema[i]); + } + } + + // Assign array values from object parameter + value = values[fieldName]; + if (typeof value != "undefined") { + record[fieldName] = value; + delete values[fieldName]; + } + // Assign values from individual fields from flattened arrays + prefixElement = this._jsdo._getArrayField(fieldName); + if (!record[fieldName]) { + record[fieldName] = []; + } + for (j = 0; j < schema[i].maxItems; j += 1) { + name = prefixElement.name + (j+1); + value = values[name]; + if (typeof value != "undefined") { + if (!this._fields[name.toLowerCase()]) { + // Skip element if a field with the same name exists + // Remove property from object for element since it is not part of the actual schema + delete values[prefixElement.name + (j+1)]; + if (typeof value == 'string' && schema[i].items.type != 'string') { + value = this._jsdo._convertType(value, + schema[i].items.type, + null); + } + record[fieldName][j] = value; + } + } + } + } + else { + record[fieldName] = this._jsdo._getDefaultValue(schema[i]); + } + } + + // Assign values based on a relationship + if (this._jsdo.useRelationships && this._relationship && this._parent) { + if (this._jsdo._buffers[this._parent].record) { + for (j = 0; j < this._relationship.length; j++) { + record[this._relationship[j].childFieldName] = + this._jsdo._buffers[this._parent].record.data[this._relationship[j].parentFieldName]; + } + } + else + throw new Error(msg.getMsgText("jsdoMSG002", this._parent)); + } + // Assign values from object parameter + for (var v in values) { + record[v] = values[v]; + } + + // Specify _id field - do not use schema default + var id; + var idProperty; + if ((idProperty = this._jsdo._resource.idProperty) !== undefined) { + id = record[idProperty]; + } + if (!id) { + id = progress.data._getNextId(); + } + else { + id += ""; + } + id += ""; // ID Property + record._id = id; + + if (this.autoSort + && this._sortRecords + && (this._sortFn !== undefined || this._sortObject.sortFields !== undefined)) { + if (this._needsAutoSorting) { + this._data.push(record); + this._sort(); + } + else { + // Find position of new record in _data and use splice + for (i = 0; i < this._data.length; i++) { + if (this._data[i] === null) continue; // Skip null elements + var ret = this._sortFn ? + this._sortFn(record, this._data[i]) : + this._compareFields(record, this._data[i]); + if (ret == -1) break; + } + this._data.splice(i, 0, record); + } + this._createIndex(); + } + else { + this._data.push(record); + this._index[record._id] = new progress.data.JSIndexEntry(this._data.length - 1); + } + + var jsrecord = new progress.data.JSRecord(this, record); + + // Set record property ignoring relationships + if (setWorkingRecord) + this._setRecord(jsrecord, true); + + if (trackChanges) { + // Save before image + this._beforeImage[record._id] = null; + // End - Save before image + this._added.push(record._id); + } + return jsrecord; + }; + + /* + * Returns records related to the specified jsrecord. + * If jsrecord is not specified the parent working record is used. + */ + this._getRelatedData = function (jsrecord) { + var data = []; + + if (this._data.length === 0) return data; + + if (typeof(jsrecord) == 'undefined') { + if (this._jsdo.useRelationships && this._relationship && this._parent) { + jsrecord = this._jsdo._buffers[this._parent].record; + if (!jsrecord) + throw new Error(msg.getMsgText("jsdoMSG002", this._parent)); + } + } + if (jsrecord) { + // Filter records using relationship + for (var i = 0; i < this._data.length; i++) { + var block = this._data[i]; + if (!block) continue; + + var match = false; + for (var j = 0; j < this._relationship.length; j++) { + match = (jsrecord.data[this._relationship[j].parentFieldName] == + this._data[i][this._relationship[j].childFieldName]); + if (!match) break; + } + if (match) + data.push(this._data[i]); + } + } + else + data = this._data; + + return data; + }; + + + // This method is called on a parent table that has child tables + // where the relationship is specified as NESTED. + // It returns a json array that contains the parent rows. + // If a parent row is involved in nested relationship, + // then references to the child rows are added + // to the parent row in a child table array (providing the nested format) + // We are using the internal jsdo _data arrays, + // and adding a child table array to each parent row that has children. + // Once the caller is done with the nested data, they can call jsdo._unnestData() + // which removes these child table references + this._getDataWithNestedChildren = function (data) { + + // Walk through all the rows and determine if any of its child tables + // should be associated (nested) with the current record + for (var i = 0; i < data.length; i++) { + var parentRecord = data[i]; + + // Now walk thru the parent's children to find any nested children + if (this._children && this._children.length > 0) { + for (var j = 0; j < this._children.length; j++) { + var childBuf = this._jsdo._buffers[this._children[j]]; + + if (childBuf._isNested) { + // If child is nested, then we should walk child records to find matches + for (var k = 0; k < childBuf._data.length; k++) { + var childRecord = childBuf._data[k]; + if (!childRecord) continue; + + var match = false; + for (var m = 0; m < childBuf._relationship.length; m++) { + match = (parentRecord[childBuf._relationship[m].parentFieldName] == + childRecord[childBuf._relationship[m].childFieldName]); + if (!match) break; + } + if (match) { + // Make sure that this parentRecord has an array for its child rows + if (!parentRecord[childBuf._name]) { + parentRecord[childBuf._name] = []; + } + parentRecord[childBuf._name].push(childRecord); + } + + + } // end for; finished adding all child rows for parentRecord + + // The child table may have its own nested children so call recursively + // Use child row array in current parentRecord + if (childBuf._hasNestedChild()) { + childBuf._getDataWithNestedChildren(parentRecord[childBuf._name]); + } + + + } // end if (childBuf._isNested) + } + } + + + } + return data; + + }; + + this._findFirst = function () { + if (this._jsdo.useRelationships && this._relationship && this._parent) { + if (this._jsdo._buffers[this._parent].record) { + // Filter records using relationship + for (var i = 0; i < this._data.length; i++) { + var block = this._data[i]; + if (!block) continue; + + var match = false; + var parentFieldName, childFieldName; + for (var j = 0; j < this._relationship.length; j++) { + parentFieldName = this._relationship[j].parentFieldName; + childFieldName = this._relationship[j].childFieldName; + match = (this._jsdo._buffers[this._parent].record.data[parentFieldName] == + this._data[i][childFieldName]); + if (!match) break; + } + if (match) { + return new progress.data.JSRecord(this, this._data[i]); + } + } + } + } + else { + for (var i = 0; i < this._data.length; i++) { + var block = this._data[i]; + if (!block) continue; + + return new progress.data.JSRecord(this, this._data[i]); + } + } + + + return undefined; + }; + + this._setRecord = function (jsrecord, ignoreRelationships) { + if (jsrecord) { + this.record = jsrecord; + } + else { + this.record = undefined; + } + + // Set child records only if useRelationships is true + if (this._jsdo.useRelationships) { + ignoreRelationships = ((typeof(ignoreRelationships) == 'boolean') && ignoreRelationships); + + if (this._children && this._children.length > 0) { + for (var i = 0; i < this._children.length; i++) { + var childTable = this._jsdo._buffers[this._children[i]]; + if (!ignoreRelationships && this.record && childTable._relationship) { + childTable._setRecord(childTable._findFirst()); + } + else { + childTable._setRecord(undefined, ignoreRelationships); + } + } + } + } + + if (this._jsdo._defaultTableRef) { + this._jsdo.record = this.record; + } + }; + + this.assign = function (values) { + if (this.record) { + return this.record.assign(values); + } + else + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + }; + + // Alias for assign() method + this.update = this.assign; + + this.remove = function () { + if (this.record) { + return this.record._remove(true); + } + else + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + }; + + this._remove = function (bTrackChanges) { + if (this.record) { + return this.record._remove(bTrackChanges); + } + else + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + }; + + this.getId = function () { + if (this.record) { + return this.record.data._id; + } + else + return 0; + }; + + // getErrors() - JSTableRef + this.getErrors = function () { + return this._lastErrors; + }; + + this.getErrorString = function () { + if (this.record) { + return this.record.data._errorString; + } + else + return 0; + }; + + this.findById = function (id) { + return this._findById(id, true); + }; + + this._findById = function (id, setWorkingRecord) { + if (typeof(setWorkingRecord) == 'undefined') { + setWorkingRecord = true; + } + if (id && this._index[id]) { + var record = this._data[this._index[id].index]; + this.record = record ? (new progress.data.JSRecord(this, record)) : null; + if (setWorkingRecord) + this._setRecord(this.record); + return this.record; + } + + if (setWorkingRecord) + this._setRecord(null); + return null; + }; + + /* + * Finds a record in the JSDO memory using the specified function to determine the record. + */ + this.find = function (fn) { + if (typeof(fn) != 'function') { + throw new Error(msg.getMsgText("jsdoMSG003", "find()")); + } + var data = this._getRelatedData(); + + for (var i = 0; i < data.length; i++) { + var block = data[i]; + if (!block) { + continue; + } + this._setRecord(new progress.data.JSRecord(this, data[i])); + var result = fn(this.record); + if (typeof(result) != 'boolean') { + throw new Error(msg.getMsgText("jsdoMSG007", "find()")); + } + if (result) { + return this.record; + } + } + + this._setRecord(null); + return null; + }; + + /* + * Loops through the records + */ + this.foreach = function (fn) { + if (typeof(fn) != 'function') { + throw new Error(msg.getMsgText("jsdoMSG003", "foreach()")); + } + var numEmptyBlocks = 0; + if (this._needCompaction) + this._compact(); + + var data = this._getRelatedData(); + + this._inforeach = true; + for (var i = 0; i < data.length; i++) { + var block = data[i]; + if (!block) { + numEmptyBlocks++; + continue; + } + + this._setRecord(new progress.data.JSRecord(this, data[i])); + var result = fn(this.record); + if ((typeof(result) != 'undefined') && !result) + break; + } + + this._inforeach = false; + + if ((numEmptyBlocks * 100 / this._data.length) >= PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS) + this._needCompaction = true; + }; + + this._equalRecord = function (rec1, rec2, keyFields) { + var field; + var match = true; + for (var i = 0; i < keyFields.length; i++) { + var fieldName = keyFields[i]; + var value1 = rec1[fieldName]; + var value2 = rec2[fieldName]; + + if (!jsdo[tableName].caseSensitive) { + field = jsdo[tableName]._fields[fieldName.toLowerCase()]; + if (field && field.type == "string") { + if (value1 !== undefined && value1 !== null) + value1 = value1.toUpperCase(); + if (value2 !== undefined && value2 !== null) + value2 = value2.toUpperCase(); + } + } + + match = (value1 == value2); + if (!match) return false; + } + return true; + }; + + // Private method to merge changes using merge modes: APPEND, EMPTY, MERGE and REPLACE + this._getKey = function (record, keyFields) { + var keyObject = {}; + for (var i = 0; i < keyFields.length; i++) { + var fieldName = keyFields[i]; + var value = record[fieldName]; + + if (!jsdo[tableName].caseSensitive) { + var field = jsdo[tableName]._fields[fieldName.toLowerCase()]; + if (field && field.type == "string") { + if (value !== undefined && value !== null) + value = value.toUpperCase(); + } + } + keyObject[fieldName] = value; + } + return JSON.stringify(keyObject); + }; + + this._getCompareFn = function (sortObject) { + if (typeof sortObject == 'function') { + return function (rec1, rec2) { + if (rec1 === null) return 1; + if (rec2 === null) return -1; + + var jsrec1 = new progress.data.JSRecord(this, rec1); + var jsrec2 = new progress.data.JSRecord(this, rec2); + return sortObject(jsrec1, jsrec2); + }; + } + else return function (rec1, rec2) { + var tableRef = sortObject.tableRef; + var sortFields = sortObject.sortFields; + if (!(sortFields instanceof Array)) return 0; + var sortAscending = sortObject.sortAscending; + + if (rec1 === null) return 1; + if (rec2 === null) return -1; + + var field; + for (var i = 0; i < sortFields.length; i++) { + var fieldName = sortFields[i]; + var value1 = rec1[fieldName]; + var value2 = rec2[fieldName]; + + if (!tableRef.caseSensitive) { + field = tableRef._fields[fieldName.toLowerCase()]; + if (field && field.type == "string") { + if (value1 !== undefined && value1 !== null) + value1 = value1.toUpperCase(); + if (value2 !== undefined && value2 !== null) + value2 = value2.toUpperCase(); + } + } + if (value1 > value2 || (value1 === undefined || value1 === null)) + return sortAscending[i] ? 1 : -1; + else if (value1 < value2 || (value2 === undefined && value2 === null)) + return sortAscending[i] ? -1 : 1; + } + return 0; + }; + }; + + this._sortObject = {}; + this._sortObject.tableRef = this; + this._sortObject.sortFields = undefined; + this._sortObject.sortAscending = undefined; + this._compareFields = this._getCompareFn(this._sortObject); + + // _sortRecords - Tells the table reference whether to sort on add, assign and addRecords + this._sortRecords = true; + // Tells the table reference whether an autoSort is required on an add or assign + this._needsAutoSorting = false; + this._sortFn = undefined; + if ((typeof Object.defineProperty) == 'function') { + this._autoSort = true; + Object.defineProperty( + this, + "autoSort", + { + get: function () { + return this._autoSort; + }, + set: function (value) { + if (value) { + this._autoSort = true; + if (this._sortFn || this._sortObject.sortFields) { + this._sort(); + this._createIndex(); + } + } + else + this._autoSort = false; + }, + enumerable: true, + writeable: true + }); + this._caseSensitive = false; + Object.defineProperty( + this, + "caseSensitive", + { + get: function () { + return this._caseSensitive; + }, + set: function (value) { + if (value) { + this._caseSensitive = true; + } + else + this._caseSensitive = false; + if (this.autoSort && + (this._sortObject.sortFields && !this._sortFn)) { + this._sort(); + this._createIndex(); + } + }, + enumerable: true, + writeable: true + }); + } + else { + this.autoSort = true; + this.caseSensitive = false; // caseSensitive is false by default + } + + this._processSortFields = function (sortFields) { + var sortObject = {}; + if (sortFields instanceof Array) { + sortObject.sortFields = sortFields; + sortObject.sortAscending = []; + sortObject.fields = {}; + for (var i = 0; i < sortObject.sortFields.length; i++) { + var idx; + var fieldName; + var field; + + if (typeof (sortObject.sortFields[i]) != 'string') { + throw new Error(msg.getMsgText("jsdoMSG030", "sort field name", "string element")); + } + if ((idx = sortObject.sortFields[i].indexOf(':')) != -1) { + fieldName = sortObject.sortFields[i].substring(0, idx); + var sortOrder = sortObject.sortFields[i].substring(idx + 1); + switch (sortOrder.toUpperCase()) { + case 'ASCENDING': + case 'ASC': + sortObject.sortAscending[i] = true; + break; + case 'DESCENDING': + case 'DESC': + sortObject.sortAscending[i] = false; + break; + default: + throw new Error(msg.getMsgText("jsdoMSG030", + "sort order '" + sortObject.sortFields[i].substring(idx + 1) + "'", + "ASCENDING or DESCENDING")); + } + } + else { + fieldName = sortObject.sortFields[i]; + sortObject.sortAscending[i] = true; + } + if (fieldName != "_id" && this._fields) { + field = this._fields[fieldName.toLowerCase()]; + if (field) { + if (field.type == "array") + throw new Error(msg.getMsgText("jsdoMSG030", "data type found in sort", + "scalar field")); + fieldName = field.name; + } + else + throw new Error(msg.getMsgText("jsdoMSG031", fieldName)); + } + sortObject.sortFields[i] = fieldName; + sortObject.fields[fieldName] = fieldName; + } + } + else { + sortObject.sortFields = undefined; + sortObject.sortAscending = undefined; + sortObject.fields = undefined; + } + return sortObject; + }; + + this.setSortFields = function (sortFields) { + if (sortFields === undefined || sortFields === null) { + this._sortObject.sortFields = undefined; + this._sortObject.sortAscending = undefined; + } + else if (sortFields instanceof Array) { + var sortObject = this._processSortFields(sortFields); + this._sortObject.sortFields = sortObject.sortFields; + this._sortObject.sortAscending = sortObject.sortAscending; + this._sortObject.fields = sortObject.fields; + + if (this.autoSort) { + this._sort(); + this._createIndex(); + } + } + else + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "setSortFields()")); + }; + + this.setSortFn = function (fn) { + // Check that fn parameter is a function + // Valid values are a function, undefined, or null + // Documentation mentions null as a way to clear the sort function + if (fn && typeof (fn) != 'function') { + throw new Error(msg.getMsgText("jsdoMSG030", "parameter in setSortFn()", + "function parameter")); + } + this._sortFn = fn ? this._getCompareFn(fn) : undefined; + if (this.autoSort) { + this._sort(); + this._createIndex(); + } + }; + + this.sort = function (arg1) { + if (arg1 === undefined || arg1 === null) { + throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "sort()")); + } + if (arguments.length !== 1 || + (!(arg1 instanceof Array) && typeof(arg1) != 'function')) { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "sort()")); + } + + if (arg1 instanceof Array) { + var sortObject = this._processSortFields(arg1); + if (sortObject.sortFields && sortObject.sortFields.length > 0) + this._sort(sortObject); + } + else { + this._sort(arg1); + } + this._createIndex(); + }; + + this._sort = function (arg1) { + if (arguments.length === 0 && + (!this.autoSort || (this._sortFn === undefined && this._sortObject.sortFields === undefined))) + return; + + if (arguments.length === 0) { + if (this._sortFn) { + // Sort using function + this._data.sort(this._sortFn); + } + else { + // Sort using sort fields + this._data.sort(this._compareFields); + } + this._needsAutoSorting = false; + } + else { + if (typeof(arg1) == 'function') { + // Sort using function + this._data.sort(this._getCompareFn(arg1)); + } + else { + // Sort using sort fields + arg1.tableRef = this; + this._data.sort(this._getCompareFn(arg1)); + } + if (this.autoSort) + this._needsAutoSorting = true; + } + }; + + /* + * Reads a JSON object into the JSDO memory for the specified table reference. + */ + this.addRecords = function (jsonObject, addMode, keyFields, trackChanges, isInvoke) { + this._jsdo._addRecords(this._name, jsonObject, addMode, keyFields, trackChanges, isInvoke); + }; + + /* + * Accepts changes for the specified table reference. + */ + this.acceptChanges = function () { + var tableRef = this; + + // First, let's remove any "prods:" properties from created and updated records. + // Don't have to worry about deleted records, since they're going away. + for (var id in tableRef._beforeImage) { + // Create + if (tableRef._beforeImage[id] === null) { + var jsrecord = tableRef._findById(id, false); + if (jsrecord !== null) { + tableRef._jsdo._deleteProdsProperties(jsrecord.data, true); + } + + } + // Update + else if (this._changed[id] !== undefined) { + var jsrecord = this._findById(id, false); + if (jsrecord !== null) { + tableRef._jsdo._deleteProdsProperties(jsrecord.data, true); + } + } + } + + tableRef._processed = {}; + tableRef._added = []; + tableRef._changed = {}; + tableRef._deleted = []; + tableRef._beforeImage = {}; + }; + + /* + * Rejects changes for the specified table reference. + */ + this.rejectChanges = function () { + // Reject changes + for (var id in this._beforeImage) { + if (this._beforeImage[id] === null) { + // Undo create + this._jsdo._undoCreate(this, id); + } + else if (this._changed[id] !== undefined) { + // Undo update + this._jsdo._undoUpdate(this, id, true); + } + else { + // Undo delete + this._jsdo._undoDelete(this, id, true); + } + } + + var tableRef = this; + tableRef._processed = {}; + tableRef._added = []; + tableRef._changed = {}; + tableRef._deleted = []; + }; + + this.hasChanges = function () { + return (Object.keys(this._beforeImage).length !== 0); + }; + + this.getChanges = function () { + var result = []; + for (var id in this._beforeImage) { + var item = {rowState: "", record: null}; + // Create + if (this._beforeImage[id] === null) { + item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE]; + item.record = this._findById(id, false); + } + // Update + else if (this._changed[id] !== undefined) { + item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE]; + item.record = this._findById(id, false); + } + // Delete + else { + item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE]; + item.record = new progress.data.JSRecord(this, this._beforeImage[id]); + } + result.push(item); + } + return result; + }; + + /* + * Private method to clear out _errorString for the specified table reference. + * If a row change was rejected, _errorString was set. + * If saveChanges() is called to retry the row change, _errorString needs to be reset. + * This could occur if the autoApplyChanges property is false. + */ + this._clearErrorStrings = function () { + var record = null; + + for (var id in this._beforeImage) { + // Create has id only in _beforeImage entry + if (this._beforeImage[id] === null) { + record = this._findById(id, false); + if (record) { + delete record.data._errorString; + } + } + else { + // Get Updated entry + record = this._findById(id, false); + if (record) { + delete record.data._errorString; + } + else { + // Deleted entry only in beforeImage table + delete this._beforeImage[id]._errorString; + } + } + } + }; + + /* + * Private method to apply changes for the specified table reference. + * If _errorString has been set for a row, row change is rejected. + * If it has not been set, acceptRowChanges() is called. + */ + this._applyChanges = function () { + var i; + + for (var id in this._beforeImage) { + // Create + if (this._beforeImage[id] === null) { + var jsrecord = this._findById(id, false); + + // Check _tmpIndex for temporary _id + if (jsrecord === null + && this._jsdo._resource.idProperty !== undefined) { + if (this._tmpIndex[id]) { + var record = this._data[this._tmpIndex[id].index]; + jsrecord = record ? (new progress.data.JSRecord(this, record)) : null; + delete this._tmpIndex[id]; + } + } + + if (jsrecord !== null) { + if (jsrecord.data._rejected + || (jsrecord.data._errorString !== undefined)) { + this._jsdo._undoCreate(this, id); + } + else { + jsrecord.acceptRowChanges(); + } + } + else { + // Record not present in JSDO memory + // Delete after Create + var found = false; + for (var i = 0; i < this._deleted.length; i++) { + found = (this._deleted[i].data._id == id); + if (found) break; + } + if (!found) { + throw new Error(msg.getMsgText("jsdoMSG000", + "Created record appears to be deleted without a delete operation.")); + } + } + } + // Update + else if (this._changed[id] !== undefined) { + var jsrecord = this._findById(id, false); + if (jsrecord !== null) { + // Record found in JSDO memory + if (jsrecord.data._rejected + || (jsrecord.data._errorString !== undefined)) { + this._jsdo._undoUpdate(this, id); + } + else { + jsrecord.acceptRowChanges(); + } + } + else { + // Record not present in JSDO memory + // Delete after Update + if (this._beforeImage[id]._rejected + || (this._beforeImage[id]._errorString !== undefined)) { + this._jsdo._undoDelete(this, id); + } + else { + var found = false; + for (i = 0; i < this._deleted.length; i++) { + found = (this._deleted[i].data._id == id); + if (found) break; + } + if (!found) { + throw new Error(msg.getMsgText("jsdoMSG000", + "Updated record appears to be deleted without a delete operation.")); + } + } + } + } + // Delete + else { + if (this._beforeImage[id]._rejected + || (this._beforeImage[id]._errorString !== undefined)) { + this._jsdo._undoDelete(this, id); + } + } + } + + var tableRef = this; + tableRef._processed = {}; + tableRef._added = []; + tableRef._changed = {}; + tableRef._deleted = []; + tableRef._beforeImage = {}; + }; + + + /* + * Accepts row changes for the working record at the table reference level. + */ + this.acceptRowChanges = function () { + if (this.record) + return this.record.acceptRowChanges(); + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + }; + + /* + * Rejects row changes for the working record at the table reference level. + */ + this.rejectRowChanges = function () { + if (this.record) + return this.record.rejectRowChanges(); + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + }; + + + /* This method returns true + * if this table has any child tables and at least one of those tables is nested. + * Else if returns false. + */ + this._hasNestedChild = function () { + var hasNestedChild = false; + var childBufObj; + + // If table has children, see if any relationship is NESTED + if (this._children.length > 0) { + for (var i = 0; i < this._children.length; i++) { + childBufObj = this._jsdo._buffers[this._children[i]]; + + if (childBufObj._isNested) { + hasNestedChild = true; + break; + } + } + } + + return hasNestedChild; + }; + }; + + /* + * Returns a JSRecord for the specified JSDO. + * @param jsdo the JSDO + * @param record the values of the record + */ + progress.data.JSRecord = function JSRecord(tableRef, record) { + this._tableRef = tableRef; + this.data = record; + + this.getId = function () { + return this.data._id ? this.data._id : null; + }; + + this.getErrorString = function () { + return this.data._errorString; + }; + + /* + * Saves a copy of the current record to the before image. + */ + this._saveBeforeImageUpdate = function () { + // Save before image + if (this._tableRef._beforeImage[this.data._id] === undefined) { + // this.data._index = index; + var copy = {}; + this._tableRef._jsdo._copyRecord( + this._tableRef, this.data, copy); + this._tableRef._beforeImage[this.data._id] = copy; + } + + if (this._tableRef._changed[this.data._id] === undefined) { + this._tableRef._changed[this.data._id] = this.data; + } + // End - Save before image + }; + + /* + * + */ + this._sortRecord = function (fields) { + var index = this._tableRef._index[this.data._id].index; + var record = this._tableRef._data[index]; + + if (this._tableRef.autoSort + && this._tableRef._sortRecords + && (this._tableRef._sortFn !== undefined + || this._tableRef._sortObject.sortFields !== undefined)) { + + if (this._tableRef._sortObject.fields) { + if (typeof fields == 'string') { + if (this._tableRef._sortObject.fields[fields] === undefined) + return; // Only sort records if the the specified field is in the sort fields + } + else if (fields instanceof Array) { + var found = false; + for (var i = 0; i < fields.length; i++) { + if (this._tableRef._sortObject.fields[fields[i]] !== undefined) { + found = true; + break; + } + } + if (!found) + return; // Only sort records if the the specified fields are in the sort fields + } + } + + if (this._tableRef._needsAutoSorting) { + this._tableRef._sort(); + this._tableRef._createIndex(); + } + else { + // Find position of new record in _data and use splice + for (var i = 0; i < this._tableRef._data.length; i++) { + if (this._tableRef._data[i] === null) continue; // Skip null elements + if (i == index) continue; // Skip changed record + var ret = this._tableRef._sortFn ? + this._tableRef._sortFn(record, this._tableRef._data[i]) : + this._tableRef._compareFields(record, this._tableRef._data[i]); + if (ret == -1) break; + } + + if (i > index) { + i--; + } + if (i != index) { + this._tableRef._data.splice(index, 1); + this._tableRef._data.splice(i, 0, record); + this._tableRef._createIndex(); + } + } + } + }; + + /* + * Assigns the specified values. + * @param record parameter with the record values + */ + this.assign = function (record) { + if (record === undefined) + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "assign() or update()")); + + this._saveBeforeImageUpdate(); + + var fieldName, + i, + j, + value, + schema = this._tableRef.getSchema(), + prefixElement, + name; + + if (record) { + for (i = 0; i < schema.length; i += 1) { + fieldName = schema[i].name; + value = record[fieldName]; + if (typeof value != "undefined") { + if (typeof value == 'string' && schema[i].type != 'string') { + value = this._tableRef._jsdo._convertType(value, + schema[i].type, + schema[i].items ? schema[i].items.type : null); + } + this.data[fieldName] = value; + } + if (schema[i].type === "array") { + // Assign values from individual fields from flattened arrays + prefixElement = this._tableRef._jsdo._getArrayField(fieldName); + if (!this.data[fieldName]) { + this.data[fieldName] = []; + } + for (j = 0; j < schema[i].maxItems; j += 1) { + name = prefixElement.name + (j+1); + value = record[name]; + if (typeof value != "undefined") { + // Skip element if a field with the same name exists + if (!this._tableRef._fields[name.toLowerCase()]) { + if (typeof value == 'string' && schema[i].items.type != 'string') { + value = this._tableRef._jsdo._convertType(value, + schema[i].items.type, + null); + } + this.data[fieldName][j] = value; + } + } + } + } + } + + this._sortRecord(); + } + return true; + }; + + // Alias for assign() method + this.update = this.assign; + + /* + * Removes the JSRecord. + */ + this.remove = function () { + return this._remove(true); + }; + + this._remove = function (bTrackChanges) { + if (typeof(bTrackChanges) == 'undefined') { + bTrackChanges = true; + } + + var index = this._tableRef._index[this.data._id].index; + var jsrecord = this._tableRef._findById(this.data._id, false); + + if (bTrackChanges) { + // Save before image + var record = this._tableRef._beforeImage[this.data._id]; + if (record === undefined) { + // Record does not exist in the before image + this.data._index = index; + this._tableRef._beforeImage[this.data._id] = this.data; + } + else { + // Record exists in the before image + if (record) { + // Record is not null - a null entry in the before image indicates + // corresponds to an add + // Save the index of the record + // so that an undo would restore the record in the same position in _data + record._index = index; + } + } + // End - Save before image + this._tableRef._deleted.push(jsrecord); + } + + // Set entry to null instead of removing entry - index requires positions to be persistent + this._tableRef._data[index] = null; + this._tableRef._hasEmptyBlocks = true; + delete this._tableRef._index[this.data._id]; + + // Set record property + this._tableRef._setRecord(null); + + return true; + }; + + /* + * Accepts row changes for the specified record. + */ + this.acceptRowChanges = function () { + var id = this.data._id; + if (this._tableRef._beforeImage[id] !== undefined) { + if (this.data._rejected) { + throw new Error(msg.getMsgText("jsdoMSG127")); + } + if (this._tableRef._beforeImage[id] === null) { + // Accept create + // Remove element from _added + for (var i = 0; i < this._tableRef._added.length; i++) { + if (this._tableRef._added[i] == id) { + this._tableRef._added.splice(i, 1); + break; + } + } + this._tableRef._jsdo._deleteProdsProperties(this.data, true); + } + else if (this._tableRef._changed[id] !== undefined) { + // Accept update + delete this._tableRef._changed[id]; + this._tableRef._jsdo._deleteProdsProperties(this.data, true); + } + else { + // Accept delete + // Remove element from _deleted + for (var i = 0; i < this._tableRef._deleted.length; i++) { + if (this._tableRef._deleted[i].data._id == id) { + this._tableRef._deleted.splice(i, 1); + break; + } + } + } + delete tableRef._beforeImage[id]; + } + }; + + /* + * Rejects row changes for the specified record. + */ + this.rejectRowChanges = function () { + var id = this.data._id; + if (this._tableRef._beforeImage[id] !== undefined) { + if (this._tableRef._beforeImage[id] === null) { + // Undo create + this._tableRef._jsdo._undoCreate(this._tableRef, id); + // Remove element from _added + for (var i = 0; i < this._tableRef._added.length; i++) { + if (this._tableRef._added[i] == id) { + this._tableRef._added.splice(i, 1); + break; + } + } + } + else if (this._tableRef._changed[id] !== undefined) { + // Undo update + this._tableRef._jsdo._undoUpdate(this._tableRef, id, true); + delete this._tableRef._changed[id]; + } + else { + // Undo delete + this._tableRef._jsdo._undoDelete(this._tableRef, id, true); + // Remove element from _deleted + for (var i = 0; i < this._tableRef._deleted.length; i++) { + if (this._tableRef._deleted[i].data._id == id) { + this._tableRef._deleted.splice(i, 1); + break; + } + } + } + delete tableRef._beforeImage[id]; + } + }; + + }; + + /* + * Returns a JSDO for the specified resource. + * @param resNameOrParmObj: the resource name or an object that contains the initial values for the JSDO + * (if this is an object, it should include the name property with the resource name + * @param serviceName : name of service (ignored if 1st param is an object containing the initial values) + */ + progress.data.JSDO = function JSDO(resNameOrParmObj, serviceName) { + var _super = {}; + + if (typeof progress.data.Session == 'undefined') { + throw new Error('ERROR: You must include progress.session.js'); + } + + _super.subscribe = this.subscribe; + + // Override for Observable.subscribe + this.subscribe = function(evt) { + var args = Array.prototype.slice.call(arguments); + if (typeof evt === "string") { + // Aliases for events + switch(evt.toLowerCase()) { + case "beforeread": + args[0] = "beforefill"; + break; + case "afterread": + args[0] = "afterfill"; + break; + } + } + _super.subscribe.apply(this, args); + }; + + this._defineProperty = function (tableName, fieldName) { + Object.defineProperty( + this._buffers[tableName], + fieldName, + { + get: function fnGet() { + var name, + index, + element, + fieldInfo; + if (this.record) { + index = fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR); + if (index > 0 && !this._fields[fieldName.toLowerCase()]) { + // Skip element if a field with the same name exists + // Check if field is a flattened array field by quickly checking for the separator + // Extract name and index element + name = fieldName.substring(0, index); + element = fieldName.substring(index + progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length); + fieldInfo = this._fields[name.toLowerCase()]; + if (!isNaN(element) && fieldInfo && (fieldInfo.type === "array")) { + return this.record.data[name][element - 1]; + } + } + return this.record.data[fieldName]; + } + else + return null; + }, + set: function (value) { + var name = fieldName, + index, + element, + fieldInfo; + if (this.record) { + this.record._saveBeforeImageUpdate(); + + try { + index = fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR); + if (index > 0 && !this._fields[fieldName.toLowerCase()]) { + // Skip element if a field with the same name exists + name = fieldName.substring(0, index); + element = fieldName.substring(index + progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length); + fieldInfo = this._fields[name.toLowerCase()]; + if (!isNaN(element) && fieldInfo && (fieldInfo.type === "array")) { + this.record.data[name][element - 1] = value; + return; + } + } + this.record.data[fieldName] = value; + } + finally { + this.record._sortRecord(name); + } + } + }, + enumerable: true, + writeable: true + }); + }; + + Object.defineProperty( + this, + 'hasSubmitOperation', + { + get: function () { + return this._hasSubmitOperation; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'hasCUDOperations', + { + get: function () { + return this._hasCUDOperations; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'defaultTableRef', + { + get: function () { + return this._defaultTableRef; + }, + enumerable: true + } + ); + + // Initial values + this._buffers = {}; // Object of table references + this._numBuffers = 0; + this._defaultTableRef = null; + + this._async = true; + this._dataProperty = null; + this._dataSetName = null; + this.operations = []; + this.useRelationships = true; + + this._session = null; + this._needCompaction = false; + + this._hasCUDOperations = false; + this._hasSubmitOperation = false; + this._useSubmit = false; // For saving saveChanges(useSubmit) param + + this.autoApplyChanges = true; // default should be true to support 11.2 behavior + this._lastErrors = []; + this._localStorage = null; + this._convertForServer; + this._fillMergeMode; + var autoFill = false; + + // Initialize JSDO using init values + if (!arguments[0]) { + throw new Error("JSDO: Parameters are required in constructor."); + } + + if (typeof(arguments[0]) == "string") { + this.name = arguments[0]; + // if ( arguments[1] && (typeof(arguments[1]) == "string") ) + // localServiceName = serviceName; + } + else if (typeof(arguments[0]) == "object") { + var args = arguments[0]; + for (var v in args) { + switch (v) { + case 'autoFill': + autoFill = args[v]; + break; + case 'events': + this._events = {}; + for (var eventName in args[v]) { + this._events[eventName.toLowerCase()] = args[v][eventName]; + } + break; + case 'dataProperty': + this._dataProperty = args[v]; + break; + default: + this[v] = args[v]; + } + } + } + /* error out if caller didn't pass the resource name */ + if ((!this.name) /*|| !(this._session)*/) { + // make this error message more specific? + throw new Error("JSDO: JSDO constructor is missing the value for 'name'"); + } + + /* perform some basic validation on the event object for the proper structure if provided */ + if (this._events) { + if ((typeof this._events) !== 'object') { + throw new Error("JSDO: JSDO constructor event object is not defined as an object"); + } + + /* make sure all the event handlers are sane */ + for (var prop in this._events) { + var evt = this._events[prop]; + if (!(evt instanceof Array)) { + throw new Error('JSDO: JSDO constructor event object for ' + prop + ' must be an array'); + } + evt.forEach(function (el) { + if ((typeof el) !== 'object') { + throw new Error("JSDO: JSDO constuctor event object for " + + prop + " is not defined as an object"); + } + /* listener must have at least fn property defined as a function */ + if ((typeof el.fn) !== 'function') { + throw new Error("JSDO: JSDO event listener for " + prop + " is not a function."); + } + /* scope is optional, but must be an object if provided */ + if (el.scope && (typeof el.scope) !== 'object') { + throw new Error("JSDO: JSDO event listener scope for " + prop + " is not an object."); + } + }); + } + } + + if (this.name) { + // Read resource definition from the Catalog - save reference to JSDO + // Enhance this to deal with multiple services loaded and the same resource + // name is used by more than one service (use the local serviceName var) + this._resource = progress.data.ServicesManager.getResource(this.name); + if (this._resource) { + if (!this.url) + this.url = this._resource.url; + if (!this._dataSetName && this._resource._dataSetName) { + // Catalog defines a DataSet + this._dataSetName = this._resource._dataSetName; + + // Define TableRef property in the JSDO + if (this._resource.dataProperty) { + var buffer = this[this._resource.dataProperty] + = new progress.data.JSTableRef(this, this._resource.dataProperty); + this._buffers[this._resource.dataProperty] = buffer; + } + else { + for (var tableName in this._resource.fields) { + var buffer = this[tableName] + = new progress.data.JSTableRef(this, tableName); + this._buffers[tableName] = buffer; + } + } + } + if (!this._dataProperty && this._resource.dataProperty) + this._dataProperty = this._resource.dataProperty; + + if (!this._dataSetName) { + var tableName = this._dataProperty ? this._dataProperty : ""; + this._buffers[tableName] = new progress.data.JSTableRef(this, tableName); + if (tableName) + this[tableName] = this._buffers[tableName]; + } + + // Set idProperty from table reference level at the resource level + var properties, + tableName; + if (this._dataSetName + && this._resource.schema + && this._resource.schema.properties[this._dataSetName]) { + properties = this._resource.schema.properties[this._dataSetName].properties; + if (Object.keys(properties).length === 1) { + tableName = Object.keys(properties)[0]; + if (properties[tableName].idProperty) { + this._resource.idProperty = properties[tableName].idProperty; + } + } + } + + // Add functions for operations to JSDO object + for (var fnName in this._resource.fn) { + this[fnName] = this._resource.fn[fnName]["function"]; + } + // Check if CUD operations have been defined + this._hasCUDOperations = + this._resource.generic["create"] !== undefined + || this._resource.generic["update"] !== undefined + || this._resource.generic["delete"] !== undefined; + this._hasSubmitOperation = this._resource.generic["submit"] !== undefined; + + /* get a session object, using name of the service to look it up in the list of + * sessions maintained by the ServicesManager + */ + if (!this._session) { + var myservice = progress.data.ServicesManager.getService(this._resource.service.name); + this._session = myservice._session; + this._session._pushJSDOs(this); + } + } + else { + throw new Error(msg.getMsgText("jsdoMSG004", this.name)); + } + } + else { + this._buffers[""] = new progress.data.JSTableRef(this, ""); + } + + if (!this._session) { + throw new Error("JSDO: Unable to get user session for resource '" + this.name + "'"); + } + + // Calculate _numBuffers and _defaultTableRef + for (var buf in this._buffers) { + this._buffers[buf]._parent = null; + this._buffers[buf]._children = []; + // The _relationship object is only specified for the child buffer. + // Currently it is limited to only a single relationship. ie. It does not support the + // where the child buffer is involved in more than one data-relation + this._buffers[buf]._relationship = null; + this._buffers[buf]._isNested = false; + if (!this._defaultTableRef) + this._defaultTableRef = this._buffers[buf]; + this._numBuffers++; + } + if (this._numBuffers != 1) + this._defaultTableRef = null; + else { + // record is used to represent the current record for a table reference + // data corresponds to the values (JSON object) of the data + this.record = null; + } + + // Define caseSensitive property at the JSDO level + if ((typeof Object.defineProperty) == 'function') { + this._caseSensitive = false; // caseSensitive is false by default + Object.defineProperty( + this, + "caseSensitive", + { + get: function () { + return this._caseSensitive; + }, + set: function (value) { + this._caseSensitive = value ? true : false; + + for (var buf in this._buffers) { + this._buffers[buf].caseSensitive = this._caseSensitive; + } + }, + enumerable: true, + writeable: true + }); + this._autoSort = true; // autoSort is true by default + Object.defineProperty( + this, + "autoSort", + { + get: function () { + return this._autoSort; + }, + set: function (value) { + this._autoSort = value ? true : false; + + for (var buf in this._buffers) { + this._buffers[buf].autoSort = this._autoSort; + } + }, + enumerable: true, + writeable: true + }); + } + + // Define _properties property at the JSDO level + this._properties = {}; + if ((typeof Object.defineProperty) == 'function') { + Object.defineProperty( this, + "this._properties", + { + get: function () { + return this._properties; + }, + enumerable: false + } + ); + + } + + + // Set schema for TableRef + if (this._resource && this._resource.fields) { + for (var buf in this._buffers) { + this._buffers[buf]._schema = this._resource.fields[buf]; + this._buffers[buf]._primaryKeys = this._resource.primaryKeys[buf]; + + // Create _fields object used to validate fields as case-insensitive. + this._buffers[buf]._fields = {}; + var fields = this._buffers[buf]._schema; + for (var i = 0; i < fields.length; i++) { + this._buffers[buf]._fields[fields[i].name.toLowerCase()] = fields[i]; + if (typeof(fields[i].origName) !== "undefined") { + if ((typeof(fields[i].origName) !== "string") + || (fields[i].origName.trim() === "")) { + throw new Error(msg.getMsgText("jsdoMSG504", + "JSDO", "Field '" + fields[i].name + "' in resource '" + this._resource.name + "'", "origName")); + } + } + } + + if (this._buffers[buf]._schema && (typeof Object.defineProperty) == 'function') { + // Add fields as properties of the TableRef object + for (var i = 0; i < this._buffers[buf]._schema.length; i++) { + var fieldName = this._buffers[buf]._schema[i].name, + fieldInfo = this._buffers[buf]._schema[i]; + if (typeof(this._buffers[buf][fieldName]) == 'undefined') { + this._defineProperty(buf, fieldName); + } + if (fieldInfo.type === "array") { + for (var j = 0; j < fieldInfo.maxItems; j += 1) { + var name = fieldName + progress.data.JSDO.ARRAY_INDEX_SEPARATOR + (j + 1); + // Skip element if a field with the same name exists + // Only create property if the name is not being used + if (!this._buffers[buf]._fields[name.toLowerCase()]) { + this._defineProperty(buf, name); + } + } + } + } + } + } + // Set schema for when dataProperty is used but not specified via the catalog + if (this._defaultTableRef + && !this._defaultTableRef._schema + && this._resource.fields[""]) { + this._defaultTableRef._schema = this._resource.fields[""]; + } + } + else { + if (this._defaultTableRef) + this._defaultTableRef._schema = []; + } + + // Set isNested property + if (this._numBuffers > 1) { + for (var buf in this._buffers) { + var fields = []; + var found = false; + for (var i = 0; i < this._buffers[buf]._schema.length; i++) { + var field = this._buffers[buf]._schema[i]; + + if (field.items + && field.type == "array" && field.items.$ref) { + if (this._buffers[field.name]) { + found = true; + this._buffers[field.name]._isNested = true; + } + } + else + fields.push(field); + } + // Replace list of fields - removing nested datasets from schema + if (found) + this._buffers[buf]._schema = fields; + } + } + + // Process relationships + if (this._resource && this._resource.relations) { + for (var i = 0; i < this._resource.relations.length; i++) { + var relationship = this._resource.relations[i]; + + // Set relationship information ignoring self-referencing (recursive) relationships + if (relationship.childName + && relationship.parentName + && (relationship.childName !== relationship.parentName)) { + // Set casing of fields in relationFields to be the same as in the schema + if (relationship.relationFields instanceof Array) { + for (var j = 0; j < relationship.relationFields.length; j++) { + var fieldName; + var field; + if (this._buffers[relationship.parentName]._fields) { + fieldName = relationship.relationFields[j].parentFieldName; + field=this._buffers[relationship.parentName]._fields[fieldName.toLowerCase()]; + if (field) { + relationship.relationFields[j].parentFieldName = field.name; + } + else + throw new Error(msg.getMsgText("jsdoMSG010", fieldName)); + } + if (this._buffers[relationship.childName]._fields) { + fieldName = relationship.relationFields[j].childFieldName; + field=this._buffers[relationship.childName]._fields[fieldName.toLowerCase()]; + if (field) { + relationship.relationFields[j].childFieldName = field.name; + } + else + throw new Error(msg.getMsgText("jsdoMSG010", fieldName)); + } + } + } + this._buffers[relationship.childName]._parent = relationship.parentName; + this._buffers[relationship.childName]._relationship = relationship.relationFields; + this._buffers[relationship.parentName]._children.push(relationship.childName); + } + } + } + + + this._getDefaultValue = function (field) { + var defaultValue, + t, m, d, + isDate = false; + + if ((field.type === "string") + && field.format + && (field.format.indexOf("date") !== -1) + && (field["default"])) { + isDate = true; + } else if ((field.type === "array") + && field.ablType + && (field.ablType.indexOf("DATE") != -1) + && (field["default"])) { + isDate = true; + } else { + defaultValue = field["default"]; + } + + if (isDate) { + switch (field["default"].toUpperCase()) { + case "NOW": + defaultValue = new Date().toISOString(); + break; + case "TODAY": + t = new Date(); + m = String((t.getMonth() + 1)); + if (m.length === 1) { + m = '0' + m; + } + d = String((t.getDate())); + if (d.length === 1) { + d = '0' + d; + } + defaultValue = t.getFullYear() + '-' + m + '-' + d; + break; + default: + defaultValue = field["default"]; + } + } + + return defaultValue; + }; + + // Method to calculate the element information of an array given the name, index, and value + // Parameters: + // arrayFieldName The name o the field + // index Optional parameter - if index is null/undefined the name of the element is the prefix + // value Optional parameter + this._getArrayField = function (arrayFieldName, index, value) { + var element = {}; + // ABL arrays are 1-based + element.name = arrayFieldName + progress.data.JSDO.ARRAY_INDEX_SEPARATOR + ((index >= 0) ? (index + 1) : ""); + element.value = value ? value[index] : undefined; + return element; + }; + + this.isDataSet = function () { + return this._dataSetName ? true : false; + }; + + /* handler for invoke operation complete */ + this._invokeComplete = function (jsdo, success, request) { + // only fire on async requests + if (request.async && request.fnName) { + jsdo.trigger('afterInvoke', request.fnName, jsdo, success, request); + } + + if (request.deferred) { + if (success) { + request.deferred.resolve(jsdo, success, request); + } + else { + request.deferred.reject(jsdo, success, request); + } + } + }; + + /* handler for invoke operation success */ + this._invokeSuccess = function (/* jsdo, success, request */) { + // do nothing + }; + + /* handler for invoke operation error */ + this._invokeError = function (/* jsdo, success, request */) { + // do nothing + }; + + /* + * Performs an HTTP request using the specified parameters. This is + * used to perform remote calls for the JSDO for operations defined. + * + */ + this._httpRequest = function (xhr, method, url, reqBody, request) { + + function afterOpenRequest() { + var input = null; + if (reqBody) { + xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); + input = JSON.stringify(reqBody); + } + + try { + xhr.send(input); + } catch (e) { + request.success = false; + request.exception = e; + // let Session check for online/offline + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + } + } + + // if xhr wasn't passed we'll create our own since this is an invoke operation + // if xhr is passed, then it is probably a CRUD operation which is setup with XHR + // in call to session + if (!xhr) { + xhr = new XMLHttpRequest(); + + // only setup the callback handlers if we're responsible for creating the + // xhr call which happens on invoke operations...which is the normal case + // the CRUD operations setup their own callbacks and they have their own + // event handlers so we don't use them here. + xhr.onCompleteFn = this._invokeComplete; + xhr.onSuccessFn = this._invokeSuccess; + xhr.onErrorFn = this._invokeError; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + + // for invokes we always fire the invoke when doing async + if (request.async && request.fnName) { + this.trigger('beforeInvoke', request.fnName, this, request); + } + + // For Invoke operations, wrap reqBody in a request object + // This is not required for CRUD operations since the whole + // reqBody is mapped to the parameter + if (reqBody) { + if (this._resource && this._resource.service) { + var useRequest = this._resource.service.useRequest; + if (this._resource.service.settings + && this._resource.service.settings.useRequest !== undefined) { + useRequest = this._resource.service.settings.useRequest; + } + if (useRequest) { + reqBody = {request: reqBody}; + } + } + } + } + + xhr.request = request; + xhr.jsdo = this; + request.jsdo = this; + request.xhr = xhr; + + this._session._openRequest(xhr, method, url, request.async, afterOpenRequest); + + return request; // Note: for the async case, this does not give us exactly the same behavior + // as when afterOpenRequest is called synchronously, because this returns + // request before its xhr has had its open() called + }; + + + // This method currently is just used by the JSDOReadService. + // It returns data in its non-nested (default) format + this._getDataObject = function () { + var dataObject = {}; + if (this._dataSetName) { + dataObject[this._dataSetName] = {}; + + var oldUseRelationships = this.useRelationships; + // Turn off useRelationships so that getData() returns all the records + try { + this.useRelationships = false; + for (var buf in this._buffers) { + dataObject[this._dataSetName][buf] = this._buffers[buf].getData(); + } + } + finally { + // Restore useRelationships + this.useRelationships = oldUseRelationships; + } + } + else { + if (this._dataProperty) { + dataObject[this._dataProperty] = this.getData(); + } + else + return this.getData(); // Array + } + return dataObject; + }; + + + // This method currently is just used by the JSDOReadService. + // Now that the JSDO Services support nested data, we want to return data nested for those + // relationships that are marked nested. + // + // This method returns a data object containing the nested data. + // If a parent row is involved in nested relationship, + // then references to its child rows are added to the parent row in a child table array + // (providing the nested format). + // We are using the internal jsdo _data arrays, + // and adding a child table array to each parent row that has children. + // Once the caller is done with the nested data, + // they can call jsdo._unnestData() which removes these child table references + // + this._getDataObjectAsNested = function () { + var dataObject = {}; + if (this._dataSetName) { + dataObject[this._dataSetName] = {}; + + try { + // First walk thru all buffers. We need to determine if any of the buffers are + // involved in a nested relationship. If so, we want to return the child's + // data in nested format. + for (var buf in this._buffers) { + var bufObj = this._buffers[buf]; + + + // If this is a child table, and its involved in a nested relationship, + // then just skip. + // This table's data will be nested within each parent row when we + // process the parent table. + if (bufObj._isNested) continue; + + this._nestChildren = false; // default to false + + // If table has children, see if any relationship is NESTED + if (bufObj._children.length > 0) { + for (var i = 0; i < bufObj._children.length; i++) { + var childBufObj = this._buffers[bufObj._children[i]]; + + if (childBufObj._isNested) { + this._nestChildren = true; + break; + } + } + } + + dataObject[this._dataSetName][buf] = this._buffers[buf].getData(); + } + } + catch (e) { + throw new Error(msg.getMsgText("jsdoMSG000", e.message)); + } + finally { + // Set back to default avlue + this._nestChildren = false; + } + } + else { + if (this._dataProperty) { + dataObject[this._dataProperty] = this.getData(); + } + else + return this.getData(); // Array + } + return dataObject; + }; + + + // This method is used in conjunction with _getDataObjectAsNested() in the JSDOReadService. + // _getDataObjectAsNested() adds arrays of child row references to their parent rows. + // Once the JSDOReadService has done its data mapping, we need to remove the references since + // internally the JSDO stores its data in unnested format. + this._unnestData = function () { + + if (this._dataSetName) { + var parentRecord; + var bufObj; + var childBufObj; + + // First walk thru all buffers. We need to determine if any of the buffers are parent + // buffers involved in a nested relationship. If so, then we'll look for any child row arrays + // to delete + for (var buf in this._buffers) { + bufObj = this._buffers[buf]; + + // If we know this table has at least one nested child table, we'll walk thru + // all its rows to determine if the rows have any child row arrays. + // It's more efficient to just walk thru the parent row list once, so we'll + // check for all child row arrays here + + if (bufObj._hasNestedChild()) { + // Now must walk thru the parent rows and delete any child row arrays + for (var i = 0; i < bufObj._data.length; i++) { + parentRecord = bufObj._data[i]; + + for (var j = 0; j < bufObj._children.length; j++) { + childBufObj = this._buffers[bufObj._children[j]]; + + if (parentRecord[childBufObj._name]) { + delete parentRecord[childBufObj._name]; + } + } + + } + } + } // end for + } + }; + + + this._recToDataObject = function (record, includeChildren) { + if (this._defaultTableRef) + return this._defaultTableRef._recToDataObject(record, includeChildren); + throw new Error(msg.getMsgText("jsdoMSG001", "_recToDataObject()")); + }; + + this._recFromDataObject = function (dataObject) { + if (this._defaultTableRef) + return this._defaultTableRef._recFromDataObject(dataObject); + throw new Error(msg.getMsgText("jsdoMSG001", "_recFromDataObject()")); + }; + + this.add = function (obj) { + if (this._defaultTableRef) + return this._defaultTableRef.add(obj); + throw new Error(msg.getMsgText("jsdoMSG001", "add() or create()")); + }; + + // Alias for add() method + this.create = this.add; + + this.hasData = function () { + for (var buf in this._buffers) { + if (this._buffers[this._buffers[buf]._name].hasData()) + return true; + } + return false; + }; + + this.getData = function (params) { + if (this._defaultTableRef) + return this._defaultTableRef.getData(params); + throw new Error(msg.getMsgText("jsdoMSG001", "getData()")); + }; + + this.getSchema = function () { + if (this._defaultTableRef) + return this._defaultTableRef.getSchema(); + throw new Error(msg.getMsgText("jsdoMSG001", "getSchema()")); + }; + + this.findById = function (id) { + if (this._defaultTableRef) + return this._defaultTableRef.findById(id); + throw new Error(msg.getMsgText("jsdoMSG001", "findById()")); + }; + + this._convertType = function (value, type, itemType) { + if ((typeof value != 'string') || (type === null)) return value; + var result = value; + try { + if (type == 'array') { + var result = []; + + value = value.slice(1, value.length - 1); + var elements = value.split(','); + var convertItem = (itemType && (itemType != 'string')); + for (var i = 0; i < elements.length; i++) { + result[i] = convertItem ? this._convertType(elements[i], itemType, null) : elements[i]; + } + } + else if (type == 'integer') { + result = parseInt(value); + } + else if (type == 'number') { + result = parseFloat(value); + } + else { + result = value; + } + } + catch (e) { + throw new Error(msg.getMsgText("jsdoMSG000", + "Error converting string to native type: " + e.message)); + } + return result; + }; + + this.assign = function (values) { + if (this._defaultTableRef) { + return this._defaultTableRef.assign(values); + } + else + throw new Error(msg.getMsgText("jsdoMSG001", "assign() or update()")); + }; + + // Alias for assign() method + this.update = this.assign; + + this.remove = function () { + if (this._defaultTableRef) { + return this._defaultTableRef.remove(); + } + else + throw new Error(msg.getMsgText("jsdoMSG001", "remove()")); + }; + + this.getId = function () { + if (this._defaultTableRef) + return this._defaultTableRef.getId(); + throw new Error(msg.getMsgText("jsdoMSG001", "getId()")); + }; + + // getErrors() - JSDO + this.getErrors = function () { + if (this._defaultTableRef) + return this._defaultTableRef.getErrors(); + throw new Error(msg.getMsgText("jsdoMSG001", "getErrors()")); + }; + + this.getErrorString = function () { + if (this._defaultTableRef) + return this._defaultTableRef.getErrorString(); + throw new Error(msg.getMsgText("jsdoMSG001", "getErrorString()")); + }; + + /* + * Finds a record in the JSDO memory using the specified function to determine the record. + */ + this.find = function (fn) { + if (this._defaultTableRef) + return this._defaultTableRef.find(fn); + throw new Error(msg.getMsgText("jsdoMSG001", "find()")); + }; + + this.foreach = function (fn) { + if (this._defaultTableRef) + return this._defaultTableRef.foreach(fn); + throw new Error(msg.getMsgText("jsdoMSG001", "foreach()")); + }; + + this.setSortFields = function (sortFields) { + if (this._defaultTableRef) + return this._defaultTableRef.setSortFields(sortFields); + throw new Error(msg.getMsgText("jsdoMSG001", "setSortFields()")); + }; + + this.setSortFn = function (fn) { + if (this._defaultTableRef) + return this._defaultTableRef.setSortFn(fn); + throw new Error(msg.getMsgText("jsdoMSG001", "setSortFn()")); + }; + + this.sort = function (arg1) { + if (this._defaultTableRef) + return this._defaultTableRef.sort(arg1); + throw new Error(msg.getMsgText("jsdoMSG001", "sort()")); + }; + + this._clearErrors = function (clearErrorString) { + /* Default to false */ + if (typeof(clearErrorString) == 'undefined') { + clearErrorString = false; + } + + this._lastErrors = []; + for (var buf in this._buffers) { + this._buffers[buf]._lastErrors = []; + + // Clears out errorString for any rejected row change + if (clearErrorString) { + this._buffers[buf]._clearErrorStrings() + } + } + }; + + /** + * setAllRecordsRejected + * + * Sets _allRecordsRejected flag to indicate whether all records have been rejected + * in a saveChanges() call. + * If changes are specified as an array, the changes are used to calculate the flag. + * + * @param {*} param - Array with changes or boolean with value + */ + this._setAllRecordsRejected = function (param) { + var changes, + hasErrors, + hasRejected, + hasCommittedRecords, + i; + + // Note: This function is a single one-stop convenient function to set + // _allRecordsRejected and _someRecordsRejected. + // This logic can be optimized by setting the flags while processing the response. + if (param instanceof Object) { + if (param instanceof Array) { + changes = param; + hasErrors = false; + + this._allRecordsRejected = false; + this._someRecordsRejected = false; + + for (var buf in this._buffers) { + if (this._buffers[buf]._lastErrors.length > 0) { + hasErrors = true; + } + } + if (hasErrors) { + this._allRecordsRejected = true; + this._someRecordsRejected = true; + + for (i = 0; i < changes.length; i += 1) { + if (changes[i].record && !changes[i].record.data._rejected) { + this._allRecordsRejected = false; + return; + } + } + } else if (changes.length > 0) { + this._allRecordsRejected = true; + this._someRecordsRejected = false; + hasCommittedRecords = false; + + for (i = 0; i < changes.length; i += 1) { + if (changes[i].record) { + if (changes[i].record.data._rejected) { + this._someRecordsRejected = true; + } else { + hasCommittedRecords = true; + } + } + } + if (hasCommittedRecords && !this._someRecordsRejected) { + this._allRecordsRejected = false; + } + } + } else { + if (param.operations instanceof Array) { + if (param.operations.length > 0 + && !param.operations[0].success) { + // First operation failed + this._allRecordsRejected = true; + this._someRecordsRejected = true; + + for (i = 0; i < param.operations.length; i += 1) { + if (param.operations[i].success) { + this._allRecordsRejected = false; + return; + } + } + } else { + // Not all operations were rejected + this._allRecordsRejected = false; + this._someRecordsRejected = false; + + for (i = 0; i < param.operations.length; i += 1) { + if (!param.operations[i].success) { + this._someRecordsRejected = true; + return; + } + } + } + } + } + } else { + // Possible values: true, false, undefined + this._allRecordsRejected = param; + this._someRecordsRejected = param; + } + }; + + /* + * Loads data from the HTTP resource. + */ + this.fill = function () { + var objParam, + promise, + properties, + mapping; + + try { + // Clear errors before sending request + this._clearErrors(); + + // Reset _allRecordsRejected + this._setAllRecordsRejected(undefined); + + // Process parameters + if (arguments.length !== 0) { + // Call to fill() has parameters + if (typeof(arguments[0]) == 'function') { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "fill() or read()")); + } + + properties = this.getMethodProperties("read"); + + // Get plugin if mappingType is not undefined, null, or "" + if (properties && properties.mappingType) { + mapping = progress.data.PluginManager.getPlugin(properties.mappingType); + if (!mapping) { + throw new Error(msg.getMsgText("jsdoMSG118", properties.mappingType)); + } + } + + // fill( string); + var filter; + if (arguments[0] === null || arguments[0] === undefined) { + filter = ""; + } + else if (typeof(arguments[0]) == "string") { + filter = arguments[0]; + objParam = {filter: filter}; + } + else if (typeof(arguments[0]) == "object") { + // options + // ablFilter, id, top, skip, sort + + if (arguments[0].mergeMode){ + this._fillMergeMode = arguments[0].mergeMode + switch(arguments[0].mergeMode) { + case progress.data.JSDO.MODE_APPEND: + case progress.data.JSDO.MODE_EMPTY: + case progress.data.JSDO.MODE_MERGE: + case progress.data.JSDO.MODE_REPLACE: + break; + default: + throw new Error(msg.getMsgText("jsdoMSG022")); + } + + } + + // Use plugin if mappingType is not undefined, null, or "" + if (mapping) { + if (typeof(mapping.requestMapping) === "function") { + objParam = mapping.requestMapping(this, arguments[0], { operation: "read" }); + } + else { + objParam = arguments[0]; + } + } + else { + if (properties.capabilities) { + throw new Error(msg.getMsgText("jsdoMSG119")); + } + objParam = arguments[0]; + } + } + else { + throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "fill() or read()")); + } + } + else { + // fill(); + objParam = null; + } + + var xhr = new XMLHttpRequest(); + var request = { + xhr: xhr, + jsdo: this, + objParam: objParam + }; + + xhr.request = request; + xhr.jsdo = this; + + xhr.onSuccessFn = this._fillSuccess; + xhr.onErrorFn = this._fillError; + xhr.onCompleteFn = this._fillComplete; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + + this.trigger("beforeFill", this, request); + + if (this._resource) { + if (typeof(this._resource.generic.read) == "function") { + xhr.objParam = objParam; + this._resource.generic.read.call(this, xhr, this._async); + if (xhr.request.deferred) { + promise = xhr.request.deferred.promise(); + } + } + else { + throw new Error("JSDO: READ operation is not defined."); + } + } + else { + // Old approach to call READ + this._session._openRequest(xhr, 'GET', this.url, this._async); + try { + xhr.send(null); + } + catch (e) { + request.exception = e; + // get the Client Context ID (AppServer ID) + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + } + } + + // This is the scenario where the read.call did not reach server. i.e., + // some problem in between making successful call to server and we are + // completing the fill() operation with necessary cleanup operations + if (request.success == false && request.exception) { + + if ((typeof xhr.onErrorFn) == 'function') { + xhr.onErrorFn(xhr.jsdo, request.success, request); + } + + // get the Client Context ID (AppServer ID) + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + + if ((typeof xhr.onCompleteFn) == 'function') { + xhr.onCompleteFn(xhr.jsdo, request.success, request); + } + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + var deferred; + if (!(xhr && xhr.deferred)) { + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + } + deferred.reject(this, false, { + errorObject: error + }); + } + } + return promise; + }; + + // Alias for fill() method + this.read = this.fill; + + /* + * Clears all data (including any pending changes) for each buffer in JSDO + */ + this._clearData = function () { + for (var buf in this._buffers) { + this._buffers[buf]._clearData(); + } + }; + + /* + * Executes a CRUD operation using the built-in API. + */ + this._execGenericOperation = function (operation, objParam, request, + onCompleteFn, onSuccessFn, onErrorFn) { + + var xhr = new XMLHttpRequest(); + request.xhr = xhr; + request.jsdo = this; + request.objParam = objParam; + request.operation = operation; + xhr.jsdo = this; + xhr.onCompleteFn = onCompleteFn; + xhr.onSuccessFn = onSuccessFn; + xhr.onErrorFn = onErrorFn; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + xhr.request = request; + + this._convertRequestData(objParam); + + var operationStr; + switch (operation) { + case progress.data.JSDO._OP_READ: + case progress.data.JSDO._OP_CREATE: + case progress.data.JSDO._OP_UPDATE: + case progress.data.JSDO._OP_DELETE: + case progress.data.JSDO._OP_SUBMIT: + operationStr = PROGRESS_JSDO_OP_STRING[operation]; + break; + default: + throw new Error("JSDO: Unexpected operation " + operation + " in HTTP request."); + } + + if (this._resource) { + if (typeof(this._resource.generic[operationStr]) == "function") { + xhr.objParam = objParam; + this._resource.generic[operationStr](xhr, this._async); + } + else { + // "JSDO: {1} operation is not defined." + throw new Error(msg.getMsgText("jsdoMSG046", operationStr.toUpperCase() )); + } + } + }; + + // Determines if any fields need a conversion when data sent to backend + this._initConvertForServer = function () { + var i, buf, schema; + + // If set, we're good. Field lists for conversion have already been created + if (this._convertForServer !== undefined) { + return; + } + + this._convertForServer = false; + for (buf in this._buffers) { + schema = this._buffers[buf].getSchema(); + this._buffers[buf]._convertFieldsForServer = []; + this._buffers[buf]._convertForServer = false; + + // Check if any fields need conversion + for (i = 0; i < schema.length; i++) { + if (schema[i].ablType && this._ablTypeNeedsConversion(schema[i].ablType)) { + this._buffers[buf]._convertFieldsForServer.push({name: schema[i].name, + ablType: schema[i].ablType}); + } + } + if (this._buffers[buf]._convertFieldsForServer.length > 0) { + this._convertForServer = true; + this._buffers[buf]._convertForServer = true; + } + } + }; + + this._convertRequestData = function (objParam) { + var buf, + beforeData; + + if (this._convertForServer === false) { + return; + } + + // We know at least one table has a field to convert + for (buf in this._buffers) { + if (this._buffers[buf]._convertForServer) { + if (objParam[this._dataSetName]) { + // First convert after-table + if (objParam[this._dataSetName][buf]) { + this._convertTableData(this._buffers[buf], objParam[this._dataSetName][buf]); + } + + // Now let's convert before-image data + beforeData = objParam[this._dataSetName]["prods:before"]; + if (beforeData && beforeData[buf]) { + this._convertTableData(this._buffers[buf], beforeData[buf]); + } + } + // This is for case where saveChanges(false) is called with no before-image data + else if (objParam[buf]) { + this._convertTableData(this._buffers[buf], objParam[buf]); + } + } + } + }; + + this._convertTableData = function (tableRef, tableData) { + var i; + + for (i = 0; i < tableData.length; i++) { + this._convertRowData(tableRef, tableData[i]); + } + }; + + this._convertRowData = function (tableRef, record) { + var i, + field; + + for (i = 0; i < tableRef._convertFieldsForServer.length; i += 1) { + field = tableRef._convertFieldsForServer[i]; + record[field.name] = this._convertField(record[field.name], field.ablType); + } + }; + + this._convertField = function (value, ablType) { + var result; + + if (value === undefined || value === null) { + return value; + } + + if (value instanceof Array) { + var resultArray = []; + for (var i = 0; i < value.length; i++) { + resultArray[i] = this._convertField(value[i], ablType); + } + return resultArray; + } + + try { + switch (ablType.toUpperCase()) { + case "DATE": + case "DATETIME": + if (typeof value === 'string') { + result = value; + } + else if (value instanceof Date) { + result = this._convertDate(value, ablType.toUpperCase()); + } + else { + throw new Error("Unexpected value for " + ablType.toUpperCase() + "."); + } + break; + default: + result = value; + break; + } + } + catch (e) { + throw new Error(msg.getMsgText("jsdoMSG000", + "Error in _convertField for value: " + value + ". " + e.message)); + } + + return result; + }; + + // Convert Date object to string for DATE and DATETIME ablTypes + // Not necessary to do for DATETIME-TZ since JSON.stringify() will do correct conversion + this._convertDate = function (value, ablType) { + var result = value; + + // DATE format should be in ISO 8601 format yyyy-mm-dd + // DATETIME format should be in ISO 8601 format yyyy-mm-ddThh:mm:ss.sss + if (ablType === "DATE" || ablType === "DATETIME") { + result = progress.util._pad(value.getFullYear(), 4) + '-' + + progress.util._pad(value.getMonth() + 1) + '-' + + progress.util._pad(value.getDate()); + + if (ablType === "DATETIME") { + result = result + "T" + + progress.util._pad(value.getHours()) + ":" + + progress.util._pad(value.getMinutes()) + ":" + + progress.util._pad(value.getSeconds()) + "." + + progress.util._pad(value.getMilliseconds(), 3); + } + } + + return result; + }; + + + this._ablTypeNeedsConversion = function (ablType) { + + var needsConversion = false; + + switch (ablType.toUpperCase()) { + case "DATE": + case "DATETIME": + needsConversion = true; + break; + } + + return needsConversion; + }; + + + + this._undefWorkingRecord = function () { + // Set record property + for (var buf in this._buffers) { + this._buffers[buf]._setRecord(null); + } + }; + + /* + * Saves changes in the JSDO. Save any outstanding changes for CREATES, UPDATE, and DELETEs + */ + this.saveChanges = function (useSubmit) { + var deferred, + promise, + request; + + try { + if (useSubmit === undefined) { + useSubmit = false; + } + else if (typeof(useSubmit) != 'boolean') { + throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "saveChanges()")); + } + + // _fireCUDTriggersForSubmit() needs to know how saveChanges() was called + this._useSubmit = useSubmit; + + // confirm the availability of the operations required for executing this saveChanges call + // (_checkThatJSDOHasRequiredOperations() throws an error if there's a missing operation, + // which this method deliberately allows to bubble up to the caller) + this._checkThatJSDOHasRequiredOperations(); + + // Don't allow Submit with just a temp-table if autoApplyChanges is true + if ( !this._dataSetName && this._useSubmit && this.autoApplyChanges) { + /* error message: "autoApplyChanges is not supported for submit with a temp-table */ + /* Use jsdo.autoApplyChanges = false." */ + throw new Error(msg.getMsgText("jsdoMSG124")); + } + + // Check if any data being sent to server needs to first be converted + this._initConvertForServer(); + + // Clear errors before sending request + this._clearErrors(true); + + // Reset _allRecordsRejected + this._setAllRecordsRejected(undefined); + + request = { + jsdo: this + }; + + this.trigger("beforeSaveChanges", this, request); + + if (useSubmit) { + /* Pass in request object. + * Need to use same request object so before and after saveChanges events + * are in sync in JSDO Submit Service. */ + promise = this._syncDataSetForSubmit(request); + } + else if (this._dataSetName) { + promise = this._syncDataSetForCUD(); + } + else { + promise = this._syncSingleTable(); + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + deferred.reject(this, false, { + errorObject: error + }); + } + } + return promise; + }; + + /* + * _checkThatJSDOHasRequiredOperations + + This method is intended to be used by the saveChanges() method to determine whether + the JSDO's resource definition includes the operations necessary for executing the + types of changes that are pending in the JSDO. It checks for Submit if saveChanges + was called with useSubmit set to true, otherwise it checks whatever CUD operations are + pending. + The JSDO's internal _useSubmit property must be set correctly before this method + is called + */ + this._checkThatJSDOHasRequiredOperations = function( ) { + var checkedDelete = false, + checkedCreate = false, + checkedUpdate = false, + buf, + tableRef; + + if (!this._hasCUDOperations && !this._hasSubmitOperation) { + throw new Error(msg.getMsgText("jsdoMSG026")); + } + + // Validate the use of Submit + if (this._useSubmit) { + if (!this._hasSubmitOperation) { + // "JSDO: {1} operation is not defined."; + throw new Error(msg.getMsgText("jsdoMSG046", "SUBMIT")); + } + else { + return; + } + } + + if (!this._resource) { + // Need the _resource property to do the validation. If not present, just return + // and let execution run as normal (presumably there will be an error) + return; + } + + // Find the pending operations and make sure they are defined + for (buf in this._buffers) { + + tableRef = this._buffers[buf]; + + if (!checkedDelete && tableRef._deleted.length > 0) { + this._confirmOperationExists( progress.data.JSDO._OP_DELETE ); + checkedDelete = true; + } + + if (!checkedCreate && tableRef._added.length > 0) { + this._confirmOperationExists( progress.data.JSDO._OP_CREATE ); + checkedCreate = true; + } + + if (!checkedUpdate && Object.keys(tableRef._changed).length > 0) { + this._confirmOperationExists( progress.data.JSDO._OP_UPDATE ); + checkedUpdate = true; + } + + if ( checkedDelete && checkedCreate && checkedUpdate ) { + break; + } + } + + }; + + // Determines whether a given operation is defined by the JSDO's resource + // throws an error if it's not defined + this._confirmOperationExists = function(operation) { + var operationStr = PROGRESS_JSDO_OP_STRING[operation]; + if (typeof(this._resource.generic[operationStr]) !== "function") { + // "JSDO: {1} operation is not defined." + throw new Error(msg.getMsgText("jsdoMSG046", operationStr.toUpperCase() )); + } + }; + + this.invoke = function (name, object) { + var deferred, promise; + + try { + var request = this[name](object); + if (request.deferred) { + deferred = request.deferred; + promise = request.deferred.promise(); + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + if (!deferred) { + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + } + deferred.reject(this, false, { + errorObject: error + }); + } + } + return promise; + }; + + /* + * Synchronizes changes for a TableRef + * + * @param operation HTTP operation to be performed + * @param tableRef Handle to the TableRef + * @param batch Optional. batch information associated with the sync operation. + * If not specified a new one will be created. Used for saving datasets. + */ + this._syncTableRef = function (operation, tableRef, batch) { + var rowData, + requestData, + jsonObject, + dataSetObject; + + if (tableRef._visited) return; + tableRef._visited = true; + + //ensure batch object is sane + if (!batch) { + batch = { + operations: [] + }; + } else if (!batch.operations) { + batch.operations = []; + } + + // Before children + // Create parent records before children + switch (operation) { + case progress.data.JSDO._OP_CREATE: + for (var i = 0; i < tableRef._added.length; i++) { + var id = tableRef._added[i]; + var jsrecord = tableRef._findById(id, false); + + if (!jsrecord) continue; + if (tableRef._processed[id]) continue; + tableRef._processed[id] = jsrecord.data; + + rowData = {}; + jsonObject = {}; + + // Make copy of row data, in case we need to convert data for backend.. + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + + if (this.isDataSet()) { + jsonObject[this._dataSetName] = {}; + dataSetObject = jsonObject[this._dataSetName]; + if (this._useBeforeImage("create")) { + dataSetObject["prods:hasChanges"] = true; + dataSetObject[tableRef._name] = []; + + // Dont need to send prods:id for create, + // no before table or error table to match + // Dont need to send prods:clientId - since only sending one record + rowData["prods:rowState"] = "created"; + rowData["prods:clientId"] = jsrecord.data._id; + + delete rowData["_id"]; + + dataSetObject[tableRef._name].push(rowData); + } + else { + dataSetObject[tableRef._name] = []; + dataSetObject[tableRef._name].push(rowData); + } + } + else { + jsonObject = rowData; + } + + + var request = { + operation: operation, + batch: batch, + jsrecord: jsrecord, + jsdo: this + }; + batch.operations.push(request); + + jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); + this.trigger("beforeCreate", this, jsrecord, request); + + this._execGenericOperation( + progress.data.JSDO._OP_CREATE, jsonObject, request, this._createComplete, + this._createSuccess, this._createError); + } + break; + case progress.data.JSDO._OP_UPDATE: + for (var id in tableRef._changed) { + var jsrecord = tableRef._findById(id, false); + + if (!jsrecord) continue; + if (tableRef._processed[id]) continue; + tableRef._processed[id] = jsrecord.data; + + rowData = {}; + jsonObject = {}; + requestData = {}; + + // Make copy of row data, in case we need to convert data for backend.. + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + + var useBeforeImageFormat = false; + if (this.isDataSet()) { + if (this._useBeforeImage("update")) { + useBeforeImageFormat = true; + jsonObject[this._dataSetName] = {}; + dataSetObject = jsonObject[this._dataSetName]; + dataSetObject["prods:hasChanges"] = true; + dataSetObject[tableRef._name] = []; + + // Dont need to send prods:clientId - since only sending one record + rowData["prods:id"] = jsrecord.data._id; + rowData["prods:rowState"] = "modified"; + rowData["prods:clientId"] = jsrecord.data._id; + delete rowData["_id"]; + + dataSetObject[tableRef._name].push(rowData); + + // Now create before-table data + dataSetObject["prods:before"] = {}; + var beforeObject = dataSetObject["prods:before"]; + beforeObject[tableRef._name] = []; + + var beforeRowData = {}; + // Dont need to send prods:clientId - since only sending one record + beforeRowData["prods:id"] = jsrecord.data._id; + + tableRef._jsdo._copyRecord(tableRef, + tableRef._beforeImage[jsrecord.data._id], beforeRowData); + delete beforeRowData["_id"]; + + beforeObject[tableRef._name].push(beforeRowData); + } + } + + if (!useBeforeImageFormat) { + if (this._resource.service + && this._resource.service.settings + && this._resource.service.settings.sendOnlyChanges) { + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData, + tableRef._beforeImage[jsrecord.data._id]); + + if (this._resource.idProperty) { + requestData[this._resource.idProperty] = + jsrecord.data[this._resource.idProperty]; + } + else { + throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, + " for sendOnlyChanges property")); + } + } + else + requestData = rowData; + + if (this.isDataSet()) { + jsonObject[this._dataSetName] = {}; + dataSetObject = jsonObject[this._dataSetName]; + dataSetObject[tableRef._name] = []; + dataSetObject[tableRef._name].push(requestData); + } + else { + jsonObject = rowData; + } + } + + var request = { + jsrecord: jsrecord, + operation: operation, + batch: batch, + jsdo: this + }; + batch.operations.push(request); + + jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); + this.trigger("beforeUpdate", this, jsrecord, request); + + this._execGenericOperation( + progress.data.JSDO._OP_UPDATE, jsonObject, request, this._updateComplete, + this._updateSuccess, this._updateError); + } + break; + } + + // Call _syncTableRef on child tables + for (var i = 0; i < tableRef._children.length; i++) { + var childTableName = tableRef._children[i]; + this._syncTableRef( + operation, this._buffers[childTableName], batch); + } + + // After children + // Delete parent records after children + + if (operation == progress.data.JSDO._OP_DELETE) { + for (var i = 0; i < tableRef._deleted.length; i++) { + var id = tableRef._deleted[i]._id; + var jsrecord = tableRef._deleted[i]; + + if (!jsrecord) continue; + tableRef._processed[id] = jsrecord.data; + + rowData = {}; + jsonObject = {}; + requestData = {}; + + // Make copy of row data, in case we need to convert data for backend.. + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + + var useBeforeImageFormat = false; + if (this.isDataSet()) { + if (this._useBeforeImage("delete")) { + useBeforeImageFormat = true; + jsonObject[this._dataSetName] = {}; + dataSetObject = jsonObject[this._dataSetName]; + dataSetObject["prods:hasChanges"] = true; + + // There is no after tables for deletes, so just create before-table data + dataSetObject["prods:before"] = {}; + var beforeObject = dataSetObject["prods:before"]; + beforeObject[tableRef._name] = []; + + var beforeRowData = {}; + + // Dont need to send prods:id for delete, no after table or error table to match + // Dont need to send prods:clientId - since only sending one record + beforeRowData["prods:rowState"] = "deleted"; + beforeRowData["prods:clientId"] = jsrecord.data._id; + + tableRef._jsdo._copyRecord(tableRef, + tableRef._beforeImage[rowData._id], beforeRowData); + beforeObject[tableRef._name].push(beforeRowData); + } + } + + if (!useBeforeImageFormat) { + if (this._resource.service + && this._resource.service.settings + && this._resource.service.settings.sendOnlyChanges) { + if (this._resource.idProperty) { + requestData[this._resource.idProperty] = + jsrecord.data[this._resource.idProperty]; + } + else { + throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, + " for sendOnlyChanges property")); + } + } + else { + requestData = rowData; + } + + if (this.isDataSet()) { + jsonObject[this._dataSetName] = {}; + dataSetObject = jsonObject[this._dataSetName]; + dataSetObject[tableRef._name] = []; + dataSetObject[tableRef._name].push(requestData); + } + else { + jsonObject = rowData; + } + } + + var request = { + batch: batch, + jsrecord: jsrecord, + operation: operation, + jsdo: this + }; + + batch.operations.push(request); + + jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); + this.trigger("beforeDelete", this, jsrecord, request); + + this._execGenericOperation( + progress.data.JSDO._OP_DELETE, jsonObject, request, this._deleteComplete, + this._deleteSuccess, this._deleteError); + } + } + }; + + /* + * Returns true if the specified operation type was specified in the catalog as useBeforeImage, + * else it returns false. + */ + this._useBeforeImage = function (opType) { + + for (var idx = 0; idx < this._resource.operations.length; idx++) { + if (this._resource.operations[idx].type == opType) { + return this._resource.operations[idx].useBeforeImage; + } + } + + return false; + }; + + + /* + * Synchronizes changes for a DataSet. This is called when we send over one row at at time + * to Create, Update and Delete methods. + * It handles row with or without before-image data. + */ + this._syncDataSetForCUD = function () { + var batch = { + operations: [] + }, + deferred, + promise; + + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + batch.deferred = deferred; + + // Process buffers + // Synchronize deletes + for (var buf in this._buffers) { + this._buffers[buf]._visited = false; + } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._syncTableRef( + progress.data.JSDO._OP_DELETE, tableRef, batch); + } + + // Synchronize adds + for (var buf in this._buffers) { + this._buffers[buf]._visited = false; + } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._syncTableRef( + progress.data.JSDO._OP_CREATE, tableRef, batch); + } + + // Synchronize updates + for (var buf in this._buffers) { + this._buffers[buf]._visited = false; + } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._syncTableRef( + progress.data.JSDO._OP_UPDATE, tableRef, batch); + } + + if (this.autoApplyChanges) { + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + tableRef._processed = {}; + tableRef._added = []; + tableRef._changed = {}; + tableRef._deleted = []; + } + } + + // OE00229270 If _async is false, this ensures that afterSaveChanges() is called just once + // We now do this after all operations have been processed + // Alternatively, scenario where the saveChanges() is invoked without + // performing any operations. In that scenario we have to process this. + if (!this._async || (batch.operations && batch.operations.length === 0)) { + if (this._isBatchComplete(batch)) { + var success = this._isBatchSuccess(batch); + var request = { + batch: batch, + success: success + }; + this._undefWorkingRecord(); + + // Save error messages + this._lastErrors = []; + if (!success && batch.operations) { + this._updateLastErrors(this, batch, null); + } + this._setAllRecordsRejected(batch); + + this._fireAfterSaveChanges(success, request); + } + } + // end OE00229270 + + return promise; + }; + + + /* + * Synchronizes changes for a single table + */ + this._syncSingleTable = function () { + var deferred, promise; + if (!this._defaultTableRef) return; + var tableRef = this._defaultTableRef; + + var batch = { + operations: [] + }; + + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + batch.deferred = deferred; + + var fireAfterSaveChanges = false; + + // Skip delete for records that were added + // mark them as processed + var addedRecords = {}; + for (var i = 0; i < tableRef._added.length; i++) { + var id = tableRef._added[i]; + addedRecords[id] = id; + } + for (var i = 0; i < tableRef._deleted.length; i++) { + var jsrecord = tableRef._deleted[i]; + if (!jsrecord) continue; + + var id = jsrecord.data._id; + if (addedRecords[id]) { + // Set request object + // Properties async, fnName, objParam, and response + // are not set when the HTTP request is suppressed + var request = { + success: true, + xhr: undefined, + operation: progress.data.JSDO._OP_DELETE, + batch: batch, + jsrecord: jsrecord, + jsdo: this + }; + batch.operations.push(request); + tableRef._processed[id] = jsrecord.data; + + var jsdo = request.jsdo; + try { + request.jsrecord._tableRef.trigger("afterDelete", jsdo, request.jsrecord, + request.success, request); + jsdo.trigger("afterDelete", jsdo, request.jsrecord, request.success, request); + } finally { + request.complete = true; + } + + fireAfterSaveChanges = true; + } + } + addedRecords = null; + + // Synchronize deletes + for (var i = 0; i < tableRef._deleted.length; i++) { + var jsrecord = tableRef._deleted[i]; + if (!jsrecord) continue; + + var id = jsrecord.data._id; + if (tableRef._processed[id]) continue; + + tableRef._processed[id] = jsrecord.data; + fireAfterSaveChanges = false; + + var xhr = new XMLHttpRequest(); + xhr.jsdo = this; + + var request = { + xhr: xhr, + operation: progress.data.JSDO._OP_DELETE, + batch: batch, + jsrecord: jsrecord, + jsdo: this + }; + batch.operations.push(request); + xhr.onCompleteFn = this._deleteComplete; + xhr.onSuccessFn = this._deleteSuccess; + xhr.onErrorFn = this._deleteError; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + xhr.request = request; + + jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); + this.trigger("beforeDelete", this, jsrecord, request); + + var requestData = {}; + if (this._resource.service + && this._resource.service.settings + && this._resource.service.settings.sendOnlyChanges) { + if (this._resource.idProperty) { + requestData[this._resource.idProperty] = jsrecord.data[this._resource.idProperty]; + } + else { + throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, + " for sendOnlyChanges property")); + } + } + else { + // We must copy record in case _convertRowData() needs to make conversion + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData); + } + + if (tableRef._convertForServer) { + this._convertRowData(tableRef, requestData); + } + + if (this._resource) { + if (typeof(this._resource.generic["delete"]) == "function") { + xhr.objParam = requestData; + this._resource.generic["delete"].call(this, xhr, this._async); + } + else { + throw new Error("JSDO: DELETE operation is not defined."); + } + } + else { + this._session._openRequest(xhr, 'DELETE', this.url + '/' + id, true); + try { + xhr.send(null); + } catch (e) { + request.success = false; + request.exception = e; + // let Session check for online/offline + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + } + + } + } + + // Synchronize adds + for (var i = 0; i < tableRef._added.length; i++) { + var id = tableRef._added[i]; + var jsrecord = tableRef._findById(id, false); + var requestData = {}; + + if (!jsrecord) continue; + if (tableRef._processed[id]) continue; + tableRef._processed[id] = jsrecord.data; + fireAfterSaveChanges = false; + + var xhr = new XMLHttpRequest(); + xhr.jsdo = this; + var request = { + xhr: xhr, + jsrecord: jsrecord, + batch: batch, + operation: progress.data.JSDO._OP_CREATE, + jsdo: this + }; + batch.operations.push(request); + xhr.onCompleteFn = this._createComplete; + xhr.onSuccessFn = this._createSuccess; + xhr.onErrorFn = this._createError; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + xhr.request = request; + + jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); + this.trigger("beforeCreate", this, jsrecord, request); + + if (this._resource) { + if (typeof(this._resource.generic.create) == "function") { + this._copyRecord(tableRef, jsrecord.data, requestData); + if (this._resource.idProperty !== undefined && jsrecord.data._id !== undefined) { + // Remove _id when idProperty is set + delete requestData._id; + } + + if (tableRef._convertForServer) { + this._convertRowData(tableRef, requestData); + } + + xhr.objParam = requestData; + + this._resource.generic.create.call(this, xhr, this._async); + } + else { + throw new Error("JSDO: CREATE operation is not defined."); + } + + } + else { + this._session._openRequest(xhr, 'POST', this.url, true); + xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); + this._copyRecord(tableRef, jsrecord.data, requestData); + + if (tableRef._convertForServer) { + this._convertRowData(tableRef, requestData); + } + var input = JSON.stringify(requestData); + + try { + xhr.send(input); + } catch (e) { + request.success = false; + request.exception = e; + // let Session check for online/offline + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + } + + } + } + + // Synchronize updates + for (var id in tableRef._changed) { + var jsrecord = tableRef._findById(id, false); + + if (!jsrecord) continue; + if (tableRef._processed[id]) continue; + tableRef._processed[id] = jsrecord.data; + fireAfterSaveChanges = false; + + var xhr = new XMLHttpRequest(); + var request = { + xhr: xhr, + jsrecord: jsrecord, + operation: progress.data.JSDO._OP_UPDATE, + batch: batch, + jsdo: this + }; + xhr.request = request; + xhr.jsdo = this; + batch.operations.push(request); + xhr.onCompleteFn = this._updateComplete; + xhr.onSuccessFn = this._updateSuccess; + xhr.onErrorFn = this._updateError; + xhr.onreadystatechange = this.onReadyStateChangeGeneric; + + jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); + this.trigger("beforeUpdate", this, jsrecord, request); + + var requestData = {}; + if (this._resource.service + && this._resource.service.settings + && this._resource.service.settings.sendOnlyChanges) { + + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData, + tableRef._beforeImage[jsrecord.data._id]); + + if (this._resource.idProperty) { + requestData[this._resource.idProperty] = jsrecord.data[this._resource.idProperty]; + } + else { + throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, + " for sendOnlyChanges property")); + } + } + else { + // We must copy record in case _convertRowData() needs to make conversion + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData); + } + + if (tableRef._convertForServer) { + this._convertRowData(tableRef, requestData); + } + + if (this._resource) { + if (typeof(this._resource.generic.update) == "function") { + xhr.objParam = requestData; + this._resource.generic.update.call(this, xhr, this._async); + } + else { + throw new Error("JSDO: UPDATE operation is not defined."); + } + } + else { + this._session._openRequest(xhr, 'PUT', this.url + '/' + id, this._async); + xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); + + var input = JSON.stringify(requestData); + + try { + xhr.send(input); + } catch (e) { + request.success = false; + request.exception = e; + // let Session check for online/offline + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + } + } + } + + if (this.autoApplyChanges) { + // Arrays to keep track of changes + tableRef._added = []; + tableRef._changed = {}; + tableRef._deleted = []; + tableRef._processed = {}; + } + + // OE00229270 If _async is false, fire afterSaveChanges() after all operations are processed + if (!this._async) + fireAfterSaveChanges = true; + + if (fireAfterSaveChanges) { + var jsdo = this; + var request = { + batch: batch, + success: true + }; + + // Save error messages + jsdo._lastErrors = []; + if (batch.operations) { + jsdo._updateLastErrors(jsdo, batch, null); + } + + jsdo._undefWorkingRecord(); + jsdo._fireAfterSaveChanges(request.success, request); + } + + return promise; + }; + + /************************************************************************ + * + * Synchronizes changes for a DataSet or a temp-table, sending over the entire change-set + * to saveChanges() on server + * If sync'ing a DataSet, sends over before-image and after-image data. + */ + this._syncDataSetForSubmit = function (request) { + var deferred, + promise, + jsonObject, + completeFn = this._saveChangesComplete, + successFn = this._saveChangesSuccess, + errorFn = this._saveChangesError; + + deferred = new progress.util.Deferred(); + promise = deferred.promise(); + request.deferred = deferred; + + request.jsrecords = []; + + // First thing to do is to create jsonObject with before and after image data for all + // records in change-set (creates, updates and deletes) + if ( this._dataSetName ) { + jsonObject = this._createChangeSet(this._dataSetName, false, request); + } + else { + // just a temp-table. Need to create it somewhat differently from DS + // (no before and after image data) + jsonObject = this._createTTChangeSet(this._defaultTableRef, request); + successFn = this._saveChangesSuccessTT; // will process success response differently from DS + } + + this._execGenericOperation(progress.data.JSDO._OP_SUBMIT, jsonObject, request, + completeFn, successFn, errorFn); + + return promise; + }; + + /************************************************************************ + * + * Private method that creates a jsonObject with before and after image data for all + * records in change-set (creates, updates and deletes) + * + * Params: dataSetName is required. + * alwaysCreateTable is required. If true, always create table array (even if no data/changes) + * request is optional + */ + this._createChangeSet = function (dataSetName, alwaysCreateTable, request) { + var changeSetJsonObject = {}; + + changeSetJsonObject[dataSetName] = {}; + var dataSetJsonObject = changeSetJsonObject[dataSetName]; + + var hasChanges = dataSetJsonObject["prods:hasChanges"] = this._hasChanges(); + if (hasChanges) { + if ((alwaysCreateTable === true)) { + for (var buf in this._buffers) { + dataSetJsonObject[this._buffers[buf]._name] = []; + } + } + + // First do deletes + //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._addDeletesToChangeSet(tableRef, dataSetJsonObject, request); + } + + // Adds + //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._addCreatesToChangeSet(tableRef, dataSetJsonObject, request); + } + + // Updates + //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._addChangesToChangeSet(tableRef, dataSetJsonObject, request); + } + + // Clear _processed map + for (var buf in this._buffers) { + this._buffers[buf]._processed = {}; + } + } + + // Check if change set is empty + // A saveChanges() with a delete of new record would result in an empty change set + // An empty DataSet is sent to the server to ensure that AfterSaveChanges fires + var keys = Object.keys(changeSetJsonObject[dataSetName]); + if (keys.length == 1 && keys[0] == "prods:hasChanges") { + for (var buf in this._buffers) { + dataSetJsonObject[this._buffers[buf]._name] = []; + } + dataSetJsonObject["prods:hasChanges"] = false; + } + + return changeSetJsonObject; + }; + + /************************************************************************ + * + * Private method that creates a jsonObject for the created and changed records + * in a temp-table. There is no before-image information. This is used in the + * case of a Submit operation when the JSDO is just for a temp-table + * + * Params: dataSetName is required. + * alwaysCreateTable is required. If true, always create table array (even if no data/changes) + * request is optional + */ + this._createTTChangeSet = function (tableRef, request) { + var changeSetJsonObject = {}, + hasChanges, + tempTableJsonObject, + i, + id, + jsrecord; + + changeSetJsonObject[tableRef._name] = []; + tempTableJsonObject = changeSetJsonObject[tableRef._name]; + + hasChanges = this._hasChanges(); + if (hasChanges) { + + // (note that we do not send deleted rows on submit for a temp-table) + + // Adds + for (i = 0; i < tableRef._added.length; i++) { + id = tableRef._added[i]; + jsrecord = tableRef._findById(id, false); + if (jsrecord) { + if ( !tableRef._processed[jsrecord.data._id] ) { + this._addRowToTTChangeSet(tableRef, jsrecord, tempTableJsonObject, + request, "beforeCreate"); + } + } + } + + // changed rows + for (id in tableRef._changed) { + if (tableRef._changed.hasOwnProperty(id)) { + jsrecord = tableRef._findById(id, false); + if (jsrecord) { + if ( !tableRef._processed[jsrecord.data._id] ) { + this._addRowToTTChangeSet(tableRef, jsrecord, tempTableJsonObject, + request, "beforeUpdate"); + } + } + } + } + + // Clear _processed map + tableRef._processed = {}; + } + + return changeSetJsonObject; + }; + + this._addRowToTTChangeSet = function (tableRef, jsrecord, tempTableJsonObject, request, event) { + var rowData = {}; + + tableRef._processed[jsrecord.data._id] = jsrecord.data; + + // Store jsrecord in request object so we can access it when saveChanges completes, + // in order to run afterCreate events + if (typeof(request) != 'undefined') { + request.jsrecords.push(jsrecord); + + // Need to call beforeCreate trigger when saveChanges(true) is called + jsrecord._tableRef.trigger(event, this, jsrecord, request); + this.trigger(event, this, jsrecord, request); + } + + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + delete rowData["_id"]; + + tempTableJsonObject.push(rowData); + }; + + /************************************************************************ + * + * Private method that creates a jsonObject with data and also before image data + * for all records in change-set (creates, updates and deletes) + * + * Params: dataSetName is required. + * It returns jsonObject that can be used as input to addRecords() + */ + this._createDataAndChangeSet = function (dataSetName) { + var jsonObject = {}; + + jsonObject[dataSetName] = {}; + var dataSetJsonObject = jsonObject[dataSetName]; + + /* We always want to create tables (even if there's no data) so we can compare schemas + * of data in local storage to JSDO's schema */ + for (var buf in this._buffers) + dataSetJsonObject[this._buffers[buf]._name] = []; + + if (this._hasChanges()) { + dataSetJsonObject["prods:hasChanges"] = true; + } + + // Add data from each table. This will also add bi data for any created or updated rows + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._addRecordsToObject(tableRef, dataSetJsonObject); + } + + // Now do deletes + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + this._addDeletesToChangeSet(tableRef, dataSetJsonObject); + } + + // Clear _processed map + for (var buf in this._buffers) { + this._buffers[buf]._processed = {}; + } + return jsonObject; + }; + + // This method adds all record for specified table into dataSetJsonObject. + // If record has bi data, it adds that as well + this._addRecordsToObject = function (tableRef, dataSetJsonObject) { + + if (tableRef._data.length > 0 && !dataSetJsonObject[tableRef._name]) + dataSetJsonObject[tableRef._name] = []; + + for (var i = 0; i < tableRef._data.length; i++) { + var record = tableRef._data[i]; + if (!record) continue; + + // Check if record has bi data, can only determine if it's created or changed since + // deleted rows are not in after data + if (this._doesRecordHaveCreateBIData(tableRef, record._id) === true) { + var jsrecord = tableRef._findById(record._id, false); + if (!jsrecord) continue; + if (tableRef._processed[jsrecord.data._id]) continue; + this._addCreatedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject); + } + if (this._doesRecordHaveUpdateBIData(tableRef, record._id) === true) { + var jsrecord = tableRef._findById(record._id, false); + if (!jsrecord) continue; + if (tableRef._processed[jsrecord.data._id]) continue; + this._addChangedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject); + } + else { + if (tableRef._processed[record._id]) continue; + tableRef._processed[record._id] = record; + + var rowData = {}; + + tableRef._jsdo._copyRecord(tableRef, record, rowData); + delete rowData["_id"]; + + dataSetJsonObject[tableRef._name].push(rowData); + } + } + }; + + + // Check if specified after record has bi data for newly created record. + // Returns True if after record has corresponding bi data, else false + this._doesRecordHaveCreateBIData = function (tableRef, id) { + for (var i = 0; i < tableRef._added.length; i++) { + if (tableRef._added[i] === id) + return true; + } + + return false; + }; + + // Check if specified after record has bi data for updated record. + // Returns True if after record has corresponding bi data, else false + this._doesRecordHaveUpdateBIData = function (tableRef, id) { + for (var changedId in tableRef._changed) { + if (changedId === id) + return true; + } + + return false; + }; + + + // If a create, remove or update exists, method returns true, else returns false + this._hasChanges = function () { + var hasChanges = false; + + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + + var hasUpdates = false; + for (var id in tableRef._changed) { + hasUpdates = true; + break; + } + + if (tableRef._deleted.length > 0 || tableRef._added.length > 0 || hasUpdates) { + hasChanges = true; + break; + } + } + + return hasChanges; + }; + + // This method is used when saveChanges() is called, and also when storing data to local storage. + // The request param should be defined for saveChanges(), + // but not needed when storing data to local storage + this._addDeletesToChangeSet = function (tableRef, dataSetJsonObject, request) { + // There is no after table for deletes, so just create before-table data + for (var i = 0; i < tableRef._deleted.length; i++) { + var jsrecord = tableRef._deleted[i]; + + if (!jsrecord) continue; + + if (jsrecord.data + && jsrecord.data._id !== undefined + && tableRef._beforeImage[jsrecord.data._id] === null) { + // Deleted record is for a new record - do not send deleted record to server + continue; + } + + this._addDeletedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); + } + }; + + this._addDeletedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { + tableRef._processed[jsrecord.data._id] = jsrecord.data; + + // Store jsrecord in request object so we can access it when saveChanges completes, + // in order to run afterDelete events + jsrecord.data["prods:rowState"] = "deleted"; + + if (typeof(request) != 'undefined') { + request.jsrecords.push(jsrecord); + + // Need to call beforeDelete trigger if saveChanges(true) is called + jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); + this.trigger("beforeDelete", this, jsrecord, request); + } + + var beforeRowData = {}; + // AppServer will roundtrip this back to jsdo client + beforeRowData["prods:clientId"] = jsrecord.data._id; + beforeRowData["prods:rowState"] = "deleted"; + + var beforeTableJsonObject = this._getTableInBeforeJsonObject(dataSetJsonObject, tableRef._name); + tableRef._jsdo._copyRecord(tableRef, tableRef._beforeImage[jsrecord.data._id], beforeRowData); + delete beforeRowData["_id"]; + + beforeTableJsonObject.push(beforeRowData); + }; + + // This method is used when saveChanges() is called, and also when storing data to local storage. + // The request param should be defined for saveChanges(), + // but not needed when storing data to local storage + this._addCreatesToChangeSet = function (tableRef, dataSetJsonObject, request) { + // There is no before table for creates, so just create after-table data + for (var i = 0; i < tableRef._added.length; i++) { + var id = tableRef._added[i]; + var jsrecord = tableRef._findById(id, false); + if (!jsrecord) continue; + if (tableRef._processed[jsrecord.data._id]) continue; + + this._addCreatedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); + } + }; + + this._addCreatedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { + tableRef._processed[jsrecord.data._id] = jsrecord.data; + + if (!dataSetJsonObject[tableRef._name]) { + dataSetJsonObject[tableRef._name] = []; + } + + // Store jsrecord in request object so we can access it when saveChanges completes, + // in order to run afterCreate events + jsrecord.data["prods:rowState"] = "created"; + + if (typeof(request) != 'undefined') { + request.jsrecords.push(jsrecord); + + // Need to call beforeCreate trigger when saveChanges(true) is called + jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); + this.trigger("beforeCreate", this, jsrecord, request); + } + + var rowData = {}; + // AppServer will roundtrip this back to jsdo client + rowData["prods:clientId"] = jsrecord.data._id; + rowData["prods:rowState"] = "created"; + + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + delete rowData["_id"]; + + dataSetJsonObject[tableRef._name].push(rowData); + }; + + // This method is used when saveChanges() is called, and also when storing data to local storage. + // The request param should be defined for saveChanges(), + // but not needed when storing data to local storage + this._addChangesToChangeSet = function (tableRef, dataSetJsonObject, request) { + // For Changes, there is both before and after table data + for (var id in tableRef._changed) { + var jsrecord = tableRef._findById(id, false); + if (!jsrecord) continue; + if (tableRef._processed[jsrecord.data._id]) continue; + + this._addChangedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); + } + }; + + this._addChangedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { + tableRef._processed[jsrecord.data._id] = jsrecord.data; + + if (!dataSetJsonObject[tableRef._name]) { + dataSetJsonObject[tableRef._name] = []; + } + + // Store jsrecord in request object so we can access it when saveChanges completes, in order + // to run afterUpdate events + jsrecord.data["prods:rowState"] = "modified"; + + if (typeof(request) != 'undefined') { + request.jsrecords.push(jsrecord); + + // Need to call beforeUpdate trigger when saveChanges(true) is called + jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); + this.trigger("beforeUpdate", this, jsrecord, request); + } + + var rowData = {}; + // Required by AppServer in before-image data. Matches before row + rowData["prods:id"] = jsrecord.data._id; + // AppServer will roundtrip this back to jsdo client + rowData["prods:clientId"] = jsrecord.data._id; + rowData["prods:rowState"] = "modified"; + + tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); + delete rowData["_id"]; + + dataSetJsonObject[tableRef._name].push(rowData); + + // Now add before-image data + var beforeTableJsonObject = this._getTableInBeforeJsonObject(dataSetJsonObject, tableRef._name); + var beforeRowData = {}; + // Required by AppServer in before-image data. Matches after row + beforeRowData["prods:id"] = jsrecord.data._id; + + tableRef._jsdo._copyRecord(tableRef, tableRef._beforeImage[jsrecord.data._id], beforeRowData); + //delete beforeRowData["_id"]; + + beforeTableJsonObject.push(beforeRowData); + }; + + + // Private method to get table's json object from the specified dataset json object. + // If it hasn't been created yet, this method creates it. + this._getTableInBeforeJsonObject = function (dataSetJsonObject, tableName) { + if (!dataSetJsonObject["prods:before"]) { + dataSetJsonObject["prods:before"] = {}; + } + var beforeObject = dataSetJsonObject["prods:before"]; + + if (!beforeObject[tableName]) { + beforeObject[tableName] = []; + } + + return beforeObject[tableName]; + }; + + + /********************************************************************* + * + * Reads a JSON object into the JSDO memory. + */ + this.addRecords = function (jsonObject, addMode, keyFields, trackChanges, isInvoke) { + if (this.isDataSet()) { + if (jsonObject instanceof Array) { + if (!this._defaultTableRef) { + throw new Error(msg.getMsgText("jsdoMSG998")); + } + } + else { + if (jsonObject === undefined || jsonObject === null) { + jsonObject = {}; + } + + if (jsonObject[this._dataSetName]) { + jsonObject = jsonObject[this._dataSetName]; + } + } + + // Allow empty object in addRecords with MODE_EMPTY + if (addMode != progress.data.JSDO.MODE_EMPTY) { + if (Object.keys(jsonObject).length === 0) + throw new Error(msg.getMsgText("jsdoMSG006")); + } + + var oldUseRelationships = this.useRelationships; + // Turn off useRelationships since addRecords() does not use the working record + this.useRelationships = false; + try { + for (var buf in this._buffers) { + // Read data for tables in JSON object + if (jsonObject[this._buffers[buf]._name]) + this._addRecords(this._buffers[buf]._name, jsonObject, addMode, + keyFields, trackChanges, isInvoke); + else if (addMode == progress.data.JSDO.MODE_EMPTY) { + this._buffers[this._buffers[buf]._name]._clearData(); + } + } + } finally { + // Restore useRelationships + this.useRelationships = oldUseRelationships; + } + } + else if (this._defaultTableRef) { + this._addRecords(this._defaultTableRef._name, jsonObject, addMode, keyFields, + trackChanges, isInvoke); + } + }; + + /* + * Copies the fields of the source record to the target record. + * Preserves the _id of the target record. + */ + this._copyRecord = function (tableRef, source, target, onlyChangesRecord) { + for (var field in source) { + + if (onlyChangesRecord !== undefined) { + if (source[field] == onlyChangesRecord[field]) + continue; + } + + // Fix for PSC00277769 + if (source[field] === undefined || source[field] === null) { + target[field] = source[field]; + } + else if (source[field] instanceof Date) { + target[field] = source[field]; + } + else if (typeof source[field] === 'object') { + var newObject = source[field] instanceof Array ? [] : {}; + this._copyRecord(tableRef, source[field], newObject); + target[field] = newObject; + } + else + target[field] = source[field]; + } + }; + + /* + * Deletes the "prods:" properties when no longer needed, + * typically when doing acceptChanges, rejectChanges, or _applyChanges. + * These properties are used to transfer before-image info between client JSDO and AppServer. + * + * Also, it optionally clears out the errorString field depending upon value of clearErrorString. + * To be consistent with the handling of + * the ABL's Buffer ERROR-STRING attribute, + * the errorString field should be cleared out when doing acceptChanges() or rejectChanges(). + */ + this._deleteProdsProperties = function (record, clearErrorString, deleteRowState) { + + /* Default to false */ + if (typeof(clearErrorString) == 'undefined') { + clearErrorString = false; + } + + /* Default to true */ + if (typeof(deleteRowState) == 'undefined') { + deleteRowState = true; + } + + if (record) { + delete record["prods:id"]; + delete record["prods:hasErrors"]; + delete record["prods:clientId"]; + delete record["prods:rejected"]; + delete record._rejected; + + if (deleteRowState) { + delete record["prods:rowState"]; + } + + if (clearErrorString) { + delete record._errorString; + } + } + }; + + this._addRecords = function (tableName, jsonObject, addMode, keyFields, trackChanges, isInvoke) { + var beforeImageJsonObject = null; + var beforeImageJsonIndex = null; + + if (jsonObject && (this._dataSetName !== undefined)) { + if (jsonObject[this._dataSetName] && + jsonObject[this._dataSetName]["prods:hasChanges"]) { + beforeImageJsonObject = jsonObject; + beforeImageJsonIndex = {}; + } + else if (jsonObject["prods:hasChanges"]) { + beforeImageJsonObject = {}; + beforeImageJsonObject[this._dataSetName] = jsonObject; + beforeImageJsonIndex = {}; + } + } + + if (typeof(tableName) != 'string') + throw new Error(msg.getMsgText("jsdoMSG020")); + if (!addMode) + throw new Error(msg.getMsgText("jsdoMSG021")); + + switch (addMode) { + case progress.data.JSDO.MODE_APPEND: + case progress.data.JSDO.MODE_EMPTY: + case progress.data.JSDO.MODE_MERGE: + case progress.data.JSDO.MODE_REPLACE: + break; + default: + throw new Error(msg.getMsgText("jsdoMSG022")); + } + + if (!keyFields) + keyFields = []; + else { + if (!(keyFields instanceof Array) && (typeof(keyFields) == 'object')) { + if (keyFields[tableName]) { + keyFields = keyFields[tableName]; + } + else { + keyFields = []; + } + } + } + + if (!(keyFields instanceof Array)) { + throw new Error(msg.getMsgText("jsdoMSG008")); + } + + // Check that the specified field names are in the schema + if (this._buffers[tableName]._fields) { + for (var i = 0; i < keyFields.length; i++) { + var field = this._buffers[tableName]._fields[keyFields[i].toLowerCase()]; + if (field === undefined) { + throw new Error(msg.getMsgText("jsdoMSG009", keyFields[i])); + } + else { + keyFields[i] = field.name; + } + } + } + + trackChanges = trackChanges ? true : false; + + if (tableName) { + if (!(jsonObject instanceof Array)) { + var data = null; + + if (jsonObject === undefined || jsonObject === null) { + jsonObject = {}; + } + + if (this.isDataSet()) { + if (jsonObject[this._dataSetName]) + data = jsonObject[this._dataSetName][tableName]; + else if (jsonObject[tableName]) + data = jsonObject[tableName]; + } else { + if (this._dataProperty) + data = jsonObject[this._dataProperty]; + else if (jsonObject.data) + data = jsonObject.data; + } + + + if (data instanceof Array) { + // saveJsonObject = jsonObject; + jsonObject = data; + } + else if ((addMode == progress.data.JSDO.MODE_EMPTY) + && (typeof (jsonObject) == 'object') + && (Object.keys(jsonObject).length === 0)) { + jsonObject = []; // Allow empty object in addRecords with + // MODE_EMPTY + } + // Allow empty object when called by restoreChangesOnlyForTable() + // where there are only deletes - in bi data + else if ((addMode == progress.data.JSDO.MODE_REPLACE) + && (typeof (jsonObject) == 'object') + && (beforeImageJsonObject)) { + jsonObject = []; + } + } + + if (!(jsonObject instanceof Array)) { + throw new Error(msg.getMsgText("jsdoMSG005", tableName)); + } + + var dataHasBeenProcessed = false; + try { + this._buffers[tableName]._sortRecords = false; + if (keyFields.length === 0 || addMode == progress.data.JSDO.MODE_EMPTY) { + // Quick merge + if (addMode == progress.data.JSDO.MODE_EMPTY) { + this._buffers[tableName]._clearData(); + } + // APPEND, MERGE, REPLACE + for (var i = 0; i < jsonObject.length; i++) { + var jsrecord = this._buffers[tableName]._add(jsonObject[i], trackChanges, false); + jsonObject[i]._id = jsrecord.data._id; + if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { + beforeImageJsonIndex[jsonObject[i]["prods:id"]] = jsrecord.data._id; + } + if (beforeImageJsonObject) { + this._deleteProdsProperties(jsrecord.data); + } + } + } + else { + // Build temporary index + var tmpIndex; + + if (this._buffers[tableName]._data.length * jsonObject.length >= 10) { + tmpIndex = {}; + + for (var i = 0; i < this._buffers[tableName]._data.length; i++) { + var record = this._buffers[tableName]._data[i]; + if (!record) continue; + + var key = this._buffers[tableName]._getKey(record, keyFields); + tmpIndex[key] = record; + } + + } + else + tmpIndex = null; // Do not use an index + var checkBeforeImage = + (Object.keys(this._buffers[tableName]._beforeImage).length !== 0); + for (var i = 0; i < jsonObject.length; i++) { + var match = false; + var record = null; + + // Check for duplicates + if (tmpIndex) { + var key = this._buffers[tableName]._getKey(jsonObject[i], keyFields); + record = tmpIndex[key]; + match = (record !== undefined); + } + else { + for (var j = 0; j < this._buffers[tableName]._data.length; j++) { + record = this._buffers[tableName]._data[j]; + if (!record) continue; + match = + (this._buffers[tableName]._equalRecord(jsonObject[i], record, keyFields)); + if (match) { + // Duplicate found + break; + } + } + } + + if (match) { + if (isInvoke + && (this._resource.idProperty !== undefined) + && (jsonObject[i]._id === undefined)) { + // Add _id to jsonObject + jsonObject[i]._id = record._id; + } + + // If beforeRecord is null, there is entry in _beforeImage for a create. + // If beforeRecord is undefined, there is no entry + var beforeRecord = this._buffers[tableName]._beforeImage[record._id]; + if (checkBeforeImage + && (jsonObject[i]["prods:id"] !== undefined) + && (typeof beforeRecord !== 'undefined')) { + // Only throw exception if the existing bi data + // is not the same as the new bi data + var isAfterSame = this._sameData(jsonObject[i], record); + var isBeforeSame = true; + + // For creates, beforeRecord will be null + if (beforeRecord) { + var beforeObject = this._getBeforeRecordFromObject(jsonObject[i], + beforeImageJsonObject, tableName); + if (beforeObject) + isBeforeSame = this._sameData(beforeObject, beforeRecord); + } + + if (!isAfterSame || !isBeforeSame) + throw new Error(msg.getMsgText("jsdoMSG032")); + } + + switch (addMode) { + case progress.data.JSDO.MODE_APPEND: + throw new Error(msg.getMsgText("jsdoMSG023")); + case progress.data.JSDO.MODE_MERGE: + /* Ignore duplicate */ + if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { + beforeImageJsonIndex[jsonObject[i]["prods:id"]] = record._id; + } + break; + case progress.data.JSDO.MODE_REPLACE: + if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { + beforeImageJsonIndex[jsonObject[i]["prods:id"]] = record._id; + } + + if (jsonObject[i]._id === undefined) + jsonObject[i]._id = record._id; + this._copyRecord( + this._buffers[tableName], + jsonObject[i], record); + this._deleteProdsProperties(record); + break; + default: + break; + } + } + else { + // Add record + var jsrecord = + this._buffers[tableName]._add(jsonObject[i], trackChanges, false); + jsonObject[i]._id = jsrecord.data._id; + if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { + beforeImageJsonIndex[jsonObject[i]["prods:id"]] = jsrecord.data._id; + } + if (beforeImageJsonObject) { + this._deleteProdsProperties(jsrecord.data); + } + if (tmpIndex) { + var key = this._buffers[tableName]._getKey(jsrecord.data, keyFields); + tmpIndex[key] = jsrecord.data; + } + } + + } + tmpIndex = null; + } + dataHasBeenProcessed = true; + } + finally { + this._buffers[tableName]._sortRecords = true; + this._buffers[tableName]._sort(); + this._buffers[tableName]._createIndex(); + + if (dataHasBeenProcessed && beforeImageJsonObject) { + this._buffers[tableName]._loadBeforeImageData(beforeImageJsonObject, + beforeImageJsonIndex, keyFields); + } + } + } + }; + + // This method returns corresponding bi record of the afterRecord from specified jsonObject + this._getBeforeRecordFromObject = function (afterRecord, jsonObject, tablename) { + var beforeData = jsonObject[this._dataSetName]["prods:before"]; + var id = afterRecord["prods:id"]; + var beforeRecord; + + if (!beforeData) return beforeRecord; + + // First check to see if the before data is the same + for (var i = 0; i < beforeData[tablename].length; i++) { + var record = beforeData[tablename][i]; + if (record["prods:id"] && id == record["prods:id"]) { + beforeRecord = record; + break; + } + } + + return beforeRecord; + }; + + this._sameData = function (record1, record2) { + var value1, value2; + for (var fieldName in record1) { + if (fieldName.substring(0, 5) != "prods" && fieldName != "_id") { + value1 = record1[fieldName]; + value2 = record2[fieldName]; + + if (value1 > value2 || value1 === null) + return false; + else if (value1 < value2 || value2 === null) + return false; + } + } + + return true; + }; + + + // private method to merge changes after a read operation + this._mergeRead = function (jsonObject, xhr) { + if (this.isDataSet()) { + if (this._dataProperty) { + var datasetBuffer = this._buffers[this._dataProperty]; + datasetBuffer._data = jsonObject[this._dataSetName][this._dataProperty]; + if (datasetBuffer.autoSort) { + datasetBuffer._sort(); + } + datasetBuffer._createIndex(); + } + else { + // Load data from JSON object into _data + for (var buf in this._buffers) { + var data; + if (jsonObject[this._dataSetName]) + data = jsonObject[this._dataSetName][buf]; + else + data = null; + data = data ? data : []; + + // We want to merge records based on the mergeMode that is coming to fill() operation. + // i.e., a mergeMode can be APPEND, MERGE, REPLACE or EMPTY. Excluding EMPTY because this is already + // taken care in the _fillSuccess + + if (this._fillMergeMode) { + + // Check for the availability of the buffer (temp-table). If we don't find any, then we want to assign an + // empty array such that we proceed with addRecords() operation with an empty dataset + if (this.isDataSet() && jsonObject[this._dataSetName] && !jsonObject[this._dataSetName][this._buffers[buf]._name]) { + jsonObject[this._dataSetName][this._buffers[buf]._name] = []; + } + + switch (this._fillMergeMode) { + case progress.data.JSDO.MODE_APPEND: + this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_APPEND); + break; + case progress.data.JSDO.MODE_MERGE: + this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_MERGE, this._buffers[buf]._primaryKeys); + break; + case progress.data.JSDO.MODE_REPLACE: + this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_REPLACE, this._buffers[buf]._primaryKeys); + break; + default: + throw new Error(msg.getMsgText("jsdoMSG022")); + } + + } else { + this._buffers[buf]._data = data; + } + + if (this._buffers[buf].autoSort) { + this._buffers[buf]._sort(); + } + this._buffers[buf]._createIndex(); + if (jsonObject[this._dataSetName] + && jsonObject[this._dataSetName]["prods:hasChanges"]) { + this._buffers[buf]._loadBeforeImageData(jsonObject); + } + } + + // Reset the fillMergeMode back to default such that it will not affect upcoming fill() operations + this._fillMergeMode = undefined; + + // Load nested data into _data + if (this._numBuffers > 1) { + for (var buf in this._buffers) { + if (this._buffers[buf]._isNested + && this._buffers[buf]._parent + && this._buffers[this._buffers[buf]._parent]) { + var srcData = this._buffers[this._buffers[buf]._parent]._data; + var data = []; + for (var i = 0; i < srcData.length; i++) { + if (srcData[i][buf] !== undefined) { + for (var j = 0; j < srcData[i][buf].length; j++) { + data.push(srcData[i][buf][j]); + } + delete srcData[i][buf]; + } + } + this._buffers[buf]._data = data; + if (this._buffers[buf].autoSort) { + this._buffers[buf]._sort(); + } + this._buffers[buf]._createIndex(); + } + } + } + } + } + else { + if (jsonObject instanceof Array) { + this._defaultTableRef._data = jsonObject; + } + else { + if (this._dataProperty) + this._defaultTableRef._data = jsonObject[this._dataProperty]; + else if (jsonObject.data) + this._defaultTableRef._data = jsonObject.data; + else { + this._defaultTableRef._data = []; + this._defaultTableRef._data[0] = jsonObject; + } + } + } + + for (var buf in this._buffers) { + if (this._buffers[buf].autoSort) { + this._buffers[buf]._sort(); + } + this._buffers[buf]._createIndex(); + } + }; + + /** + * Replace existing record data and index entry with new record data. + */ + this._mergeUpdateRecord = function (tableRef, recordId, record) { + var index = tableRef._index[recordId].index; + record._id = recordId; + + if (!tableRef._data[index]) { + tableRef._data[index] = {}; + } + this._copyRecord(this._tableRef, record, tableRef._data[index]); + record = tableRef._data[index]; + + if (tableRef._jsdo._resource.idProperty !== undefined) { + var id = tableRef._data[index][tableRef._jsdo._resource.idProperty]; + if (id !== undefined) { + id += ""; // ID Property + + // Delete index entry for recordId (_id) + delete tableRef._index[recordId]; + + if (tableRef._beforeImage[recordId] === null) { + // Save old recordId (_id) to _tmpIndex + tableRef._tmpIndex[recordId] = new progress.data.JSIndexEntry(index); + } + + // Create index entry with new id + tableRef._index[id] = new progress.data.JSIndexEntry(index); + record._id = id; + } + } + + return record; + }; + + + /** + *update existing record data with specified error string + */ + this._setErrorString = function (tableRef, recordId, errorString, setInBeforeTable) { + + if (setInBeforeTable) { + // Ensure that object exists, it's null for deleted rows + if (tableRef._beforeImage[recordId]) { + tableRef._beforeImage[recordId]._errorString = errorString; + } + } + else { + var index = tableRef._index[recordId].index; + tableRef._data[index]._errorString = errorString; + } + }; + + /* + * Returns the array with the data from the specified dataObject. + */ + this._arrayFromDataObject = function (dataObject, tableRef) { + var data; + + if (dataObject === undefined) return undefined; + if (this._dataSetName) { + if (dataObject[this._dataSetName]) + data = dataObject[this._dataSetName][tableRef._name]; + } + else { + // check if data returned as array + if (dataObject instanceof Array) { + data = dataObject; + } else { + // or if data property is set + if (this._dataProperty) { + data = dataObject[this._dataProperty]; + } else if (dataObject.data) { + // or just try with 'data' as the data property name + data = dataObject.data; + } + } + } + + return data; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method to merge changes after a create or update operation. + // This method is called to merge changes when server's Create or Update methods were called. + // + // It returns true if it found error for row in before-image data (prods:hasErrors = true) + // It returns false if there is no before-image data or prods:hasErrors property is absent + this._mergeUpdateForCUD = function (jsonObject, xhr) { + var hasError = false, + errorString; + + // Update dataset with changes from server + if (this._dataSetName) { + var dataSetJsonObject = jsonObject[this._dataSetName]; + + // only updates the specified record + var tableRef = xhr.request.jsrecord._tableRef; + var tableJsonObject = this._arrayFromDataObject(jsonObject, tableRef); + + if (tableJsonObject instanceof Array) { + if (tableJsonObject.length > 1) { + xhr.request.success = false; + throw new Error(msg.getMsgText("jsdoMSG100")); + } + + for (var i = 0; i < tableJsonObject.length; i++) { + var recordId = xhr.request.jsrecord.getId(); + + if (!recordId) { + throw new Error(msg.getMsgText("jsdoMSG034", "_mergeUpdateForCUD()")); + } + + // Determine if error string (get prods_id before _mergeUpdateRecord() is called, + // since it removes all prods properties) + errorString = undefined; + + if (tableJsonObject[i]["prods:hasErrors"]) { + var prods_id = tableJsonObject[i]["prods:id"]; + errorString = + this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); + hasError = true; + } + + var record = this._mergeUpdateRecord(tableRef, recordId, tableJsonObject[i]); + if (errorString) + this._setErrorString(tableRef, recordId, errorString, false); + + // Set _rejected property + if (tableJsonObject[i]["prods:rejected"] + || errorString) { + record._rejected = true; + if (errorString === "REJECTED") { + delete record._errorString; + } + } + + xhr.request.jsrecord = new progress.data.JSRecord(tableRef, record); + } + } + } else { + // update single record with changes from server + var tableRef = this._defaultTableRef; + var data = this._arrayFromDataObject(jsonObject); + + if (data instanceof Array) { + if (data.length > 1) { + xhr.request.success = false; + throw new Error(msg.getMsgText("jsdoMSG100")); + } + + for (var i = 0; i < data.length; i++) { + var recordId = xhr.request.jsrecord.getId(); + + if (!recordId) { + throw new Error(msg.getMsgText("jsdoMSG034", "_mergeUpdateForCUD()")); + } + + var record = this._mergeUpdateRecord(tableRef, recordId, data[i]); + xhr.request.jsrecord = new progress.data.JSRecord(tableRef, record); + } + } + } + + return hasError; + }; + + + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method to determine if deleted row (from delete operation) returned from AppServer + // was returned with an error in the before-image data. + // + // It returns true if it found an error for row in before-image data (prods:hasErrors = true) + // It returns false if there is no before-image data or prods:hasErrors property is absent + + this._checkForDeleteError = function (dataSetJsonObject, xhr) { + var hasError = false; + var tableRef = xhr.request.jsrecord._tableRef; + + var beforeJsonObject = dataSetJsonObject["prods:before"]; + + // No merge is necessary for deletes, but we need to see + // if there are any errors on deletes records. + // delete records are not in after table, only in before table + if (beforeJsonObject) { + var beforeTableJsonObject = beforeJsonObject[tableRef._name]; + + if (beforeTableJsonObject.length > 1) { + xhr.request.success = false; + throw new Error(msg.getMsgText("jsdoMSG100")); + } + // clientId is same as _id + var recordId = beforeTableJsonObject[0]["prods:clientId"]; + if (!recordId) { + throw new Error(msg.getMsgText("jsdoMSG035", "_checkForDeleteError()")); + } + + // Determine if row was returned with error string + if (beforeTableJsonObject[0]["prods:hasErrors"]) { + var prods_id = beforeTableJsonObject[0]["prods:id"]; + var errorString = + this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); + this._setErrorString(tableRef, recordId, errorString, true); + hasError = true; + } + } + + return hasError; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method to merge changes after a call to saveChanges. + // This method is called when saveChanges(useSubmit) was called with useSubmit=true. + // This can process/merge one or more created, deleted or updated records. + // In order for a jsonObject to have before-image data, it must be associated with a dataset. + // + // It only merges changes in the after table. But we need to look at before-image table to see + // if there were any errors passed back for the deletes + // + this._mergeUpdateForSubmit = function (jsonObject, xhr) { + var errorString; + + //if (!this._dataSetName || !jsonObject[this._dataSetName]["prods:hasChanges"]) + if (!this._dataSetName) { + // "_mergeUpdateForSubmit() can only be called for a dataset" + throw new Error(msg.getMsgText("jsdoMSG036", "_mergeUpdateForSubmit()")); + } + + // response is sent back with extra dataset object wrapper + var dataSetJsonObject = jsonObject[this._dataSetName]; + if (dataSetJsonObject[this._dataSetName]) + dataSetJsonObject = dataSetJsonObject[this._dataSetName]; + + var beforeJsonObject = dataSetJsonObject["prods:before"]; + + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + + var tableJsonObject = dataSetJsonObject[tableRef._name]; + if (tableJsonObject instanceof Array) { + for (var i = 0; i < tableJsonObject.length; i++) { + + var recordId = tableJsonObject[i]["prods:clientId"]; + if (!recordId) { + throw new Error(msg.getMsgText("jsdoMSG035", "_mergeUpdateForSubmit()")); + } + + // Determine if error string (get prods_id before _mergeUpdateRecord() is called, + // since it removes all prods properties) + errorString = undefined; + + if (tableJsonObject[i]["prods:hasErrors"]) { + var prods_id = tableJsonObject[i]["prods:id"]; + errorString = + this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); + } + var record = this._mergeUpdateRecord(tableRef, recordId, tableJsonObject[i]); + if (errorString) { + this._setErrorString(tableRef, recordId, errorString, false); + } + + // Set _rejected property so it can be checked in applyChanges() + if (tableJsonObject[i]["prods:rejected"] + || errorString) { + record._rejected = true; + if (errorString === "REJECTED") { + delete record._errorString; + } + } + + // Now need to update jsrecords. + // We use this data when we fire create, update and delete events. + // Updating so that it contains latest data (data sent back from server) + var jsrecords = xhr.request.jsrecords; + for (var idx = 0; idx < jsrecords.length; idx++) { + if (jsrecords[idx].data["_id"] == recordId) { + jsrecords[idx].data = record; + break; + } + } + } + } + } + + // No merge is necessary for deletes, + // but we need to see if there are any errors on deletes records. + // delete records are not in after table, only in before table + if (beforeJsonObject) { + for (var buf in this._buffers) { + var tableRef = this._buffers[buf]; + var beforeTableJsonObject = beforeJsonObject[tableRef._name]; + var errorString; + + if (beforeTableJsonObject instanceof Array) { + for (var i = 0; i < beforeTableJsonObject.length; i++) { + + if (beforeTableJsonObject[i]["prods:rowState"] == "deleted") { + var recordId = beforeTableJsonObject[i]["prods:clientId"]; + if (!recordId) { + throw new Error(msg.getMsgText("jsdoMSG035", "_mergeUpdateForSubmit()")); + } + + errorString = undefined; + // If row was returned with error string, just copy that over to jsdo record + if (beforeTableJsonObject[i]["prods:hasErrors"]) { + var prods_id = beforeTableJsonObject[i]["prods:id"]; + + errorString = this._getErrorStringFromJsonObject(dataSetJsonObject, + tableRef, prods_id); + this._setErrorString(tableRef, recordId, errorString, true); + } + + // Set _rejected property so it can be checked in applyChanges() + if ((beforeTableJsonObject[i]["prods:rejected"] + || errorString) + && tableRef._beforeImage[recordId]) { + tableRef._beforeImage[recordId]._rejected = true; + if (errorString === "REJECTED") { + delete tableRef._beforeImage[recordId]._errorString; + } + } + } + } + } + } + } + }; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method that fires afterCreate, afterUpdate and afterDelete (CUD) triggers after + // saveChanges(true) is called. We must fire create, update and delete triggers + // for each record that was sent to backend submit operation + this._fireCUDTriggersForSubmit = function (request) { + // Before firing triggers, delete prods properties (except rowState) so they don't appear in data + for (var idx = 0; idx < request.jsrecords.length; idx++) { + this._deleteProdsProperties(request.jsrecords[idx].data, false, false); + } + + for (var idx = 0; idx < request.jsrecords.length; idx++) { + var jsrecord = request.jsrecords[idx]; + switch (jsrecord.data["prods:rowState"]) { + case "created": + jsrecord._tableRef.trigger("afterCreate", this, jsrecord, request.success, request); + this.trigger("afterCreate", this, jsrecord, request.success, request); + break; + case "modified": + jsrecord._tableRef.trigger("afterUpdate", this, jsrecord, request.success, request); + this.trigger("afterUpdate", this, jsrecord, request.success, request); + break; + case "deleted": + jsrecord._tableRef.trigger("afterDelete", this, jsrecord, request.success, request); + this.trigger("afterDelete", this, jsrecord, request.success, request); + break; + } + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////////// + // + // Private method to return error for specified row + // from jsonObject's prods:errors object (before-data) sent over from AppServer + // + this._getErrorStringFromJsonObject = function (dataSetJsonObject, tableRef, prods_id) { + var tableJsonObject; + var errorsJsonObject = dataSetJsonObject["prods:errors"]; + + if (errorsJsonObject) { + tableJsonObject = errorsJsonObject[tableRef._name]; + } + + if (tableJsonObject instanceof Array) { + for (var i = 0; i < tableJsonObject.length; i++) { + + var id = tableJsonObject[i]["prods:id"]; + if (id === prods_id) { + var errorString = tableJsonObject[i]["prods:error"]; + return errorString === null ? + "Server returned unspecified error. Please check log files." : errorString; + } + } + } + + return undefined; + }; + + this._fillSuccess = function (jsdo, success, request) { + var xhr = request.xhr, + properties, + mapping; + + // Need to check if responseMapping was specified; developer can specify + // plug-in to manipulate response + properties = jsdo.getMethodProperties("read"); + + if (properties && properties.mappingType) { + mapping = progress.data.PluginManager.getPlugin(properties.mappingType); + if (!mapping) { + throw new Error(progress.data._getMsgText("jsdoMSG118", properties.mappingType)); + } + + if (typeof (mapping.responseMapping) === "function") { + request.response = mapping.responseMapping(jsdo, request.response, { operation: "read" }); + } + } + + // Here check for the mergeMode flag of fill() operation and performing accordingly. + // When the mergeMode is EMPTY or if the fillMergeMode is NOT set then only we will be performing clearData operation + if(!request.jsdo._fillMergeMode || request.jsdo._fillMergeMode === progress.data.JSDO.MODE_EMPTY) { + jsdo._clearData(); + } + jsdo._mergeRead(request.response, xhr); + + // Set working record + for (var buf in jsdo._buffers) { + if (!jsdo._buffers[buf]._parent || !jsdo.useRelationships) { + jsdo._buffers[buf]._setRecord(jsdo._buffers[buf]._findFirst()); + } + } + }; + + this._fillComplete = function (jsdo, success, request) { + jsdo.trigger("afterFill", jsdo, request.success, request); + if (request.deferred) { + if (success) { + request.deferred.resolve(jsdo, success, request); + } + else { + request.deferred.reject(jsdo, success, request); + } + } + }; + + this._fillError = function (jsdo, success, request) { + jsdo._clearData(); + jsdo._updateLastErrors(jsdo, null, null, request); + }; + + this._undoCreate = function (tableRef, id) { + // Undo operation + // Remove record from JSDO memory + var entry = tableRef._index[id]; + if (entry !== undefined) { + var index = entry.index; + tableRef._data[index] = null; + } + tableRef._hasEmptyBlocks = true; + delete tableRef._index[id]; + delete tableRef._beforeImage[id]; + // End - Undo operation + }; + + this._undoUpdate = function (tableRef, id, deleteProdsProps) { + /* Default to false */ + if (typeof(deleteProdsProps) == 'undefined') { + deleteProdsProps = false; + } + + // Undo operation + // Restore from before image + var record = tableRef._beforeImage[id]; + + // Before image points to an existing record + if (record) { + var index = tableRef._index[id].index; + tableRef._jsdo._copyRecord(tableRef, record, tableRef._data[index]); + if (deleteProdsProps) + tableRef._jsdo._deleteProdsProperties(tableRef._data[index], true); + } + delete tableRef._beforeImage[id]; + // End - Restore before image + }; + + this._undoDelete = function (tableRef, id, deleteProdsProps) { + /* Default to false */ + if (typeof(deleteProdsProps) == 'undefined') { + deleteProdsProps = false; + } + + // Restore from before image + var record = tableRef._beforeImage[id]; + + // Before image points to an existing record + if (record) { + var index = record._index; + delete record._index; + if (deleteProdsProps) + tableRef._jsdo._deleteProdsProperties(record, true); + + if ((index !== undefined) && (tableRef._data[index] === null)) { + tableRef._data[index] = record; + } + else { + tableRef._data.push(record); + index = tableRef._data.length - 1; + } + tableRef._index[id] = new progress.data.JSIndexEntry(index); + } + delete tableRef._beforeImage[id]; + // End - Restore before image + }; + + this._deleteComplete = function (jsdo, success, request) { + var xhr = request.xhr; + var jsrecord = request.jsrecord; + + try { + // Before firing trigger, delete prods properties so they don't appear in data + jsdo._deleteProdsProperties(jsrecord.data, false); + + jsrecord._tableRef.trigger("afterDelete", jsdo, jsrecord, request.success, request); + jsdo.trigger("afterDelete", jsdo, jsrecord, request.success, request); + + } finally { + request.complete = true; + jsdo._checkSaveComplete(xhr); + } + }; + + this._deleteSuccess = function (jsdo, success, request) { + var xhr = request.xhr; + var jsonObject = request.response; + var beforeJsonObject = null; + var dataSetJsonObject = null; + var data; + + //Even though this is _deleteSuccess, if before-image data is returned, the call of + // delete operation could return a success, but we have to check if error was returned + // in before-image data + var hasError = false; + if (jsdo._useBeforeImage("delete")) { + dataSetJsonObject = jsonObject[jsdo._dataSetName]; + beforeJsonObject = dataSetJsonObject["prods:before"]; + + if (beforeJsonObject) { + data = beforeJsonObject[request.jsrecord._tableRef._name]; + } + } + else { + data = jsdo._arrayFromDataObject(jsonObject, request.jsrecord._tableRef); + } + + if (data instanceof Array) { + if (data.length > 1) { + request.success = false; + throw new Error(msg.getMsgText("jsdoMSG100")); + } + } + + if (beforeJsonObject) { + hasError = jsdo._checkForDeleteError(dataSetJsonObject, xhr); + } + + if (hasError) + request.success = false; + + if (jsdo.autoApplyChanges) { + if (!hasError) { + // Clear before image + delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; + // End - Clear before image + } + else { + jsdo._deleteError(jsdo, success, request); + } + } + }; + + this._deleteError = function (jsdo, success, request) { + if (jsdo.autoApplyChanges) { + jsdo._undoDelete(request.jsrecord._tableRef, request.jsrecord.data._id); + } + }; + + this._createComplete = function (jsdo, success, request) { + var xhr = request.xhr; + var jsrecord = request.jsrecord; + + try { + // Before firing trigger, delete prods properties so they don't appear in data + jsdo._deleteProdsProperties(jsrecord.data, false); + + jsrecord._tableRef.trigger("afterCreate", jsdo, jsrecord, request.success, request); + jsdo.trigger("afterCreate", jsdo, jsrecord, request.success, request); + } finally { + request.complete = true; + jsdo._checkSaveComplete(xhr); + } + }; + + this._createSuccess = function (jsdo, success, request) { + var xhr = request.xhr; + var record = request.response; + var hasError = jsdo._mergeUpdateForCUD(record, xhr); + + if (hasError) + request.success = false; + + if (jsdo.autoApplyChanges) { + if (!hasError) { + // Clear before image + delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; + // End - Clear before image + } + else { + jsdo._createError(jsdo, success, request); + } + } + }; + + this._createError = function (jsdo, success, request) { + if (jsdo.autoApplyChanges) { + jsdo._undoCreate(request.jsrecord._tableRef, request.jsrecord.data._id); + } + }; + + + this._updateComplete = function (jsdo, success, request) { + var xhr = request.xhr; + var jsrecord = request.jsrecord; + try { + // Before firing trigger, delete prods properties so they don't appear in data + jsdo._deleteProdsProperties(jsrecord.data, false); + + jsrecord._tableRef.trigger("afterUpdate", jsdo, jsrecord, request.success, request); + jsdo.trigger("afterUpdate", jsdo, jsrecord, request.success, request); + } finally { + request.complete = true; + jsdo._checkSaveComplete(xhr); + } + }; + + this._updateSuccess = function (jsdo, success, request) { + var xhr = request.xhr; + var hasError = jsdo._mergeUpdateForCUD(request.response, xhr); + + if (hasError) { + request.success = false; + } + + if (jsdo.autoApplyChanges) { + if (!hasError) { + request.success = true; + // Clear before image + delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; + // End - Clear before image + } + else { + jsdo._updateError(jsdo, success, request); + } + } + }; + + this._updateError = function (jsdo, success, request) { + + if (jsdo.autoApplyChanges) { + request.success = false; + jsdo._undoUpdate(request.jsrecord._tableRef, request.jsrecord.data._id); + } + }; + + + this._saveChangesSuccess = function (jsdo, success, request) { + var records = request.response; + jsdo._mergeUpdateForSubmit(records, request.xhr); + + // Ensure that that the _lastErrors variable has been cleared + jsdo._clearErrors(); + var changes = jsdo.getChanges(); + jsdo._updateLastErrors(jsdo, null, changes); + + jsdo._setAllRecordsRejected(changes); + + if (jsdo.autoApplyChanges) { + jsdo._applyChanges(); + } + }; + + + this._saveChangesError = function (jsdo, success, request) { + jsdo._setAllRecordsRejected(true); + if (jsdo.autoApplyChanges) { + jsdo.rejectChanges(); + } + jsdo._updateLastErrors(jsdo, null, null, request); + }; + + /* _saveChangesSuccessTT + internal function called after a Submit of a temp-table (not DataSet) returns success + This method does not attempt to do any merging of records into the JSDO memory. The + absence of _id for the records means that the only way we could possibly do a "merge" + would be to delete the changed rceords in the JSDO memory and then add the records + that were returned form the data service, but that would invalidate the _id's that + the Kendo datasource depends on. The application programmmer must do the merging in + the afterSaveChanges handler + + *** Submit(temp-table) is not supported. This method will be removed in a future version. *** + */ + this._saveChangesSuccessTT = function (jsdo, success, request) { + var changes; + + // Ensure that that the _lastErrors variable has been cleared + jsdo._clearErrors(); + changes = jsdo.getChanges(); + jsdo._updateLastErrors(jsdo, null, changes); + jsdo._setAllRecordsRejected(false); + }; + + this._saveChangesComplete = function (jsdo, success, request) { + // Success with errors + if ((request.xhr.status >= 200 && request.xhr.status < 300) + && (jsdo._lastErrors.length > 0 || jsdo._someRecordsRejected)) { + request.success = false; + } + + // If saveChanges(true) was called, then we must fire create, update and delete triggers + // for each record that was sent to submit operation + if (jsdo._useSubmit === true) { + jsdo._fireCUDTriggersForSubmit(request); + } + + jsdo._undefWorkingRecord(); + jsdo._fireAfterSaveChanges(request.success, request); + + }; + + this._fireAfterSaveChanges = function (success, request) { + this.trigger("afterSaveChanges", this, success, request); + + if (request.jsrecords) { + if (request.deferred) { + if (success) { + request.deferred.resolve(this, success, request); + } + else { + request.deferred.reject(this, success, request); + } + } + } + else if (request.batch && request.batch.deferred) { + if (success) { + request.batch.deferred.resolve(this, success, request); + } + else { + request.batch.deferred.reject(this, success, request); + } + } + + // Clear error string when autoApplyChanges is true + var clearErrorString = this.autoApplyChanges; + + // This will be set if submit operation was performed + if (request.jsrecords) { + for (var idx = 0; idx < request.jsrecords.length; idx++) { + var jsrecord = request.jsrecords[idx]; + if (clearErrorString) { + delete jsrecord.data._errorString; + } + delete jsrecord.data["prods:rowState"]; + } + } + else if (request.batch && request.batch.operations) { + for (var idx = 0; idx < request.batch.operations.length; idx++) { + var jsrecord = request.batch.operations[idx].jsrecord; + if (clearErrorString) { + delete jsrecord.data._errorString; + } + } + } + }; + + /* + * Returns errors in response associated with the HTTP request.records related to the specified jsrecord. + */ + this._getErrorsFromRequest = function(request) { + var errors = [], // Array of objects with properties: type, id, error, errorNum, responseText + errorArray = [], + errorObject, + retValString, + j, + i; + + if (request && !request.success) { + if (request.xhr.status >= 400 && request.xhr.status < 600) { + try { + var responseObject = JSON.parse(request.xhr.responseText); + + // responseText could be an array, an object or just text. + // If it is an array, each object would have properties _errors and optional _retVal. + // If it is not an array, the object would have properties _errors and optional _retVal. + // If it is text, the content could also be an HTML page, this error is handle using "HTTP Status". + if (responseObject instanceof Array) { + errorArray = responseObject; + } else if (responseObject instanceof Object) { + errorArray.push(responseObject); + } + for (i = 0; i < errorArray.length; i += 1) { + errorObject = errorArray[i]; + if (errorObject._retVal) { + errors.push({ + type: progress.data.JSDO.RETVAL, + error: errorObject._retVal + }); + retValString = errorObject._retVal; + } else { + retValString = null; + } + if (errorObject._errors instanceof Array) { + for (j = 0; j < errorObject._errors.length; j += 1) { + if ((errorObject._errors[j]._errorNum === 0) + && (errorObject._errors[j]._errorMsg === retValString)) { + // Suppress additional error msg if it is same as return value + continue; + } + errors.push({ + type: progress.data.JSDO.APP_ERROR, + error: errorObject._errors[j]._errorMsg, + errorNum: errorObject._errors[j]._errorNum + }); + } + } + } + } + catch (e) { + // Ignore exceptions + } + } + if (request.exception) { + errors.push({ + type: progress.data.JSDO.ERROR, + error: request.exception + }); + } + if (errors.length === 0 + && request.xhr + && (request.xhr.status >= 400 && request.xhr.status < 600)) { + errors.push({ + type: progress.data.JSDO.ERROR, + error: "Error: HTTP Status " + request.xhr.status + " " + request.xhr.statusText, + responseText: request.xhr.responseText + }); + } + } + return errors; + }; + + this._updateLastErrors = function (jsdo, batch, changes, request) { + var errors, + errorText, + responseObject, + i, + j, + buf; + + if (batch) { + if (batch.operations === undefined) return; + for (i = 0; i < batch.operations.length; i++) { + request = batch.operations[i]; + if (!request.success && request.xhr) { + if (request.xhr.status >= 200 && request.xhr.status < 300) { + // Add error string to jsdo._lastErrors + jsdo._lastErrors.push({errorString: request.jsrecord.data._errorString}); + // Add error object to jsdo.._lastErrors + jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({ + type: progress.data.JSDO.DATA_ERROR, + id: request.jsrecord.data._id, + error: request.jsrecord.data._errorString}); + } + else { + errors = this._getErrorsFromRequest(request); + errorText = ""; + for (j = 0; j < errors.length; j += 1) { + if (errors.length > 1 && errors[j].error.indexOf("(7243)") != -1) { + // If there are more error messages + // supress error "The Server application has returned an error. (7243)" + continue; + } + // Add error to table reference + if (request.jsrecord + && (errors[j].type === progress.data.JSDO.APP_ERROR + || errors[j].type === progress.data.JSDO.RETVAL)) { + errors[j].id = request.jsrecord.data._id; + request.jsrecord._tableRef._lastErrors.push(errors[j]); + } + if (errorText.length === 0) { + errorText = errors[j].error; + } + else { + errorText += "\n" + errors[j].error; + } + } + // Add error string to jsdo._lastErrors + jsdo._lastErrors.push({errorString: errorText}); + } + } + } + } + else if (changes instanceof Array) { + for (i = 0; i < changes.length; i++) { + if (changes[i].record && changes[i].record.data._errorString !== undefined) { + jsdo._lastErrors.push({errorString: changes[i].record.data._errorString}); + jsdo._buffers[changes[i].record._tableRef._name]._lastErrors.push({ + type: progress.data.JSDO.DATA_ERROR, + id: changes[i].record.data._id, + error: changes[i].record.data._errorString}); + } + } + } + else if (request + && !request.success + && request.xhr + && ((request.xhr.status >= 400 && request.xhr.status < 600) || request.xhr.status === 0)) { + errors = this._getErrorsFromRequest(request); + errorText = ""; + for (j = 0; j < errors.length; j += 1) { + if (errors.length > 1 && errors[j].error.indexOf("(7243)") != -1) { + // If there are more error messages + // supress error "The Server application has returned an error. (7243)" + continue; + } + // Add error to all table references + for (buf in this._buffers) { + this._buffers[buf]._lastErrors.push(errors[j]); + } + if (errorText.length === 0) { + errorText = errors[j].error; + } + else { + errorText += "\n" + errors[j].error; + } + } + jsdo._lastErrors.push({errorString: errorText}); + } + }; + + // Check if all the xhr operations associated with the batch for which + // this xhr object is related have completed (not necessarily to success). + // If all XHR operations have completed this fires 'afterSaveChanges' event + this._checkSaveComplete = function (xhr) { + if (xhr.request) { + var jsdo = xhr.request.jsdo; + var batch = xhr.request.batch; + // OE00229270 Should only do afterSaveChanges if _async + if (jsdo && batch && jsdo._async) { + if (jsdo._isBatchComplete(batch)) { + var success = jsdo._isBatchSuccess(batch); + var request = { + batch: batch, + success: success + }; + jsdo._undefWorkingRecord(); + + // Save error messages + jsdo._lastErrors = []; + if (!success && batch.operations) { + jsdo._updateLastErrors(jsdo, batch, null); + } + this._setAllRecordsRejected(batch); + + jsdo._fireAfterSaveChanges(success, request); + } + } + } + }; + + + /* + * determine if a batch of XHR requests has completed in which all requests are successful + */ + this._isBatchSuccess = function (batch) { + if (batch.operations) { + for (var i = 0; i < batch.operations.length; i++) { + if (!batch.operations[i].success) { + return false; + } + } + } + return true; + }; + + /* + * determine if all XHR requests from the batch of saves have completed (not necessarily to success) + */ + this._isBatchComplete = function (batch) { + if (batch.operations) { + for (var i = 0; i < batch.operations.length; i++) { + var request = batch.operations[i]; + // we have to check against the 'complete' flag because xhr.readyState + // might be set async by the browser + // while we're still in the middle of processing some other requests's response + if (!request.complete) { + return false; + } + } + } + return true; + }; + + this._mergeInvoke = function (jsonObject, xhr) { + var operation, i; + + if (xhr.request.fnName !== undefined + && xhr.jsdo._resource.fn[xhr.request.fnName] !== undefined) { + operation = xhr.jsdo._resource.fn[xhr.request.fnName].operation; + } + else + operation = null; + if (operation === undefined) { + // Operation data is only required for invoke operations with mergeMode: true + operation = null; + for (i = 0; i < xhr.jsdo._resource.operations.length; i++) { + if (xhr.jsdo._resource.operations[i].name == xhr.request.fnName) { + operation = xhr.jsdo._resource.operations[i]; + break; + } + } + xhr.jsdo._resource.fn[xhr.request.fnName].operation = operation; + } + if (operation !== null && operation.mergeMode) { + try { + var mergeMode = progress.data.JSDO["MODE_" + operation.mergeMode.toUpperCase()]; + if (mergeMode === null) { + throw new Error(msg.getMsgText("jsdoMSG030", "mergeMode property", + "EMPTY, APPEND, MERGE or REPLACE")); + } + if (xhr.jsdo._resource.idProperty === undefined) { + throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, + " by mergeMode property in invoke operation")); + } + var dataParameterName; + if (xhr.jsdo.isDataSet()) { + dataParameterName = xhr.jsdo._resource._dataSetName; + } + else if (xhr.jsdo._resource.dataProperty !== undefined) { + dataParameterName = xhr.jsdo._resource.dataProperty; + } + else if (xhr.jsdo._resource._tempTableName !== undefined) { + dataParameterName = xhr.jsdo._resource._tempTableName; + } + else { + throw new Error(msg.getMsgText("jsdoMSG111", "")); + } + + var found = false; + for (i = 0; i < operation.params.length; i++) { + if (operation.params[i].name == dataParameterName) { + if (operation.params[i].type.indexOf('RESPONSE_BODY') != -1) { + if ((operation.params[i].xType !== undefined) + && (operation.params[i].xType != 'DATASET') + && (operation.params[i].xType != 'TABLE') + && (operation.params[i].xType != 'ARRAY')) { + throw new Error(msg.getMsgText("jsdoMSG113", operation.params[i].xType, + dataParameterName, xhr.request.fnName)); + } + found = true; + break; + } + } + } + + if (!found) { + throw new Error(msg.getMsgText("jsdoMSG112", dataParameterName, xhr.request.fnName)); + } + xhr.jsdo.addRecords(xhr.request.response[dataParameterName], + mergeMode, [xhr.jsdo._resource.idProperty], false, true); + } + catch (e) { + xhr.request.success = false; + xhr.request.exception = e; + } + } + }; + + this.onReadyStateChangeGeneric = function () { + var xhr = this; + if (xhr.readyState == 4) { + var request = xhr.request; + + /* try to parse response even if request is considered "failed" due to http status */ + try { + request.response = JSON.parse(xhr.responseText); + // in some cases the object back from appserver has a "response" property which represents + // the real content of the JSON...happens when multiple output parameters are returned. + // this of course assumes no one names their root object "response". + if (request.response && request.response.response) { + request.response = request.response.response; + } + } catch (e) { + request.response = undefined; + } + + try { + if ((xhr.status >= 200 && xhr.status < 300) + || (xhr.status === 0 && xhr.responseText !== "")) { + + request.success = true; + // get the Client Context ID (AppServer ID) + xhr.jsdo._session._saveClientContextId(xhr); + if ((typeof xhr.onSuccessFn) == 'function') { + var operation; + if (xhr.request.fnName !== undefined + && xhr.jsdo._resource.fn[xhr.request.fnName] !== undefined) { + operation = xhr.jsdo._resource.fn[xhr.request.fnName].operation; + } + else + operation = null; + if ((operation === undefined) || (operation !== null && operation.mergeMode)) + xhr.jsdo._mergeInvoke(request.response, xhr); + if (request.success) + xhr.onSuccessFn(xhr.jsdo, request.success, request); + else if ((typeof xhr.onErrorFn) == 'function') + xhr.onErrorFn(xhr.jsdo, request.success, request); + } + + } else { + request.success = false; + if (xhr.status === 0) { + request.exception = new Error(msg.getMsgText("jsdoMSG101")); + } + if ((typeof xhr.onErrorFn) == 'function') { + xhr.onErrorFn(xhr.jsdo, request.success, request); + } + } + } catch (e) { + request.success = false; + request.exception = e; + if ((typeof xhr.onErrorFn) == 'function') { + xhr.onErrorFn(xhr.jsdo, request.success, request); + } + } + // get the Client Context ID (AppServer ID) + xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); + + if ((typeof xhr.onCompleteFn) == 'function') { + xhr.onCompleteFn(xhr.jsdo, request.success, request); + } + + } + }; + + /* + * Accepts changes for all table references in the JSDO. + */ + this.acceptChanges = function () { + for (var buf in this._buffers) { + this._buffers[this._buffers[buf]._name].acceptChanges(); + } + }; + + /* + * Rejects changes for the table references in the JSDO. + */ + this.rejectChanges = function () { + for (var buf in this._buffers) { + this._buffers[this._buffers[buf]._name].rejectChanges(); + } + }; + + /* + * Returns an array with changes for all table references in the JSDO. + */ + this.getChanges = function () { + var result = []; + for (var buf in this._buffers) { + var changes = this._buffers[this._buffers[buf]._name].getChanges(); + result = result.concat(changes); + } + return result; + }; + + this.hasChanges = function () { + for (var buf in this._buffers) { + if (this._buffers[this._buffers[buf]._name].hasChanges()) + return true; + } + return false; + }; + + /* + * Private method to apply changes for all table references in the JSDO. + * If _errorString has been set for a row, rejectRowChanges() is called. + * If it has not been set, acceptRowChanges() is called. + */ + this._applyChanges = function () { + for (var buf in this._buffers) { + this._buffers[this._buffers[buf]._name]._applyChanges(); + } + }; + + /* + * Accepts row changes for the working record using the JSDO reference. + */ + this.acceptRowChanges = function () { + if (this._defaultTableRef) + return this._defaultTableRef.acceptRowChanges(); + throw new Error(msg.getMsgText("jsdoMSG001", "acceptRowChanges()")); + }; + + /* + * Reject row changes for the working record using the JSDO reference. + */ + this.rejectRowChanges = function () { + if (this._defaultTableRef) + return this._defaultTableRef.rejectRowChanges(); + throw new Error(msg.getMsgText("jsdoMSG001", "rejectRowChanges()")); + }; + + /* + * Sets complete set of properties for the jsdo. All existing properties are replaced with new set + */ + this.setProperties = function( propertiesObject ) { + var prop; + + if (arguments.length < 1) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'setProperties', 1)); + } + if (arguments.length > 1) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'setProperties', 1)); + } + if ( typeof propertiesObject == "object" ) { + /* Copy properties of the propertiesObject argument into _properties. + * Note that if object passed in has a prototype, this code copies them too) + */ + this._properties = {}; + + for (prop in propertiesObject) { + if( propertiesObject.hasOwnProperty(prop) ) { + if (typeof propertiesObject[prop] !== "function" ) { + this._properties[prop] = propertiesObject[prop]; + } + } + } + } + else if ( (propertiesObject === undefined) || (propertiesObject === null) ) { + this._properties = {}; + } + else { + // {1}: Parameter {1} must be of type {3} in {4} call. + throw new Error(progress.data._getMsgText("jsdoMSG121", 'JSDO', 1, 'Object', + 'setProperties')); + } + }; + + /* + * Set or remove an individual property in the property set maintained by the jsdo. + * This operates only on the property identified by propertyName; + * all other existing properties remain as they are. + * If the propertyName is not part of the context, this call adds it. + * If it exists, it is updated, unless - + * If propertyValue is undefined, this call removes the property + */ + this.setProperty = function( propertyName, propertyValue) { + if (arguments.length < 2) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', + 'setProperty', 2)); + } + if (arguments.length !== 2) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", "JSDO", + "setProperty", 2)); + } + if (typeof propertyName !== "string") { + // {1}: Parameter {1} must be of type {3} in {4} call. + throw new Error(progress.data._getMsgText("jsdoMSG121", 'JSDO', 1, 'string', + 'setProperty')); + } + + if ( propertyValue === undefined ) { + delete this._properties[propertyName]; // OK if it doesn't exist -- no error + } + else { + this._properties[propertyName] = propertyValue; + } + }; + + /* + * Gets the set of jsdo properties. Returns an object containing all the properties + */ + this.getProperties = function( ) { + if (arguments.length > 0) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperties', 0)); + } + return this._properties; + }; + + /* Gets the value of an individual property in the jsdo property set + */ + this.getProperty = function( propertyName) { + if (arguments.length < 1) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperty', 1)); + } + if (arguments.length > 1) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperty', 1)); + } + return this._properties[propertyName]; + + }; + + /////////////////////////////////////////////////////////////////////////// + // + // The following methods provide support for Object Pesistence + + /* + * Saves JSDO memory (and optionally pending changes) to local storage. + * + * saveLocal() + * saveLocal(name) + * saveLocal(dataMode) + * saveLocal(name, dataMode) + * + */ + this.saveLocal = function saveLocal(arg1, arg2) { + var name; + var dataMode; + + if (arguments.length > 2) { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); + } + + if (typeof(arg1) == 'string' || arg1 === null || arg1 === undefined) { + name = arg1; + dataMode = arg2; + } + else { + name = null; + dataMode = arg1; + } + + if (name === undefined || name === null || name === "") { + name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; + } + if (typeof(dataMode) == 'undefined') { + dataMode = progress.data.JSDO.ALL_DATA; + } + else { + switch (dataMode) { + case progress.data.JSDO.ALL_DATA: + case progress.data.JSDO.CHANGES_ONLY: + break; + default: + throw new Error(msg.getMsgText("jsdoMSG115", arguments.callee.name)); + } + } + + if (this._localStorage === null) { + // Must first instantiate _localStorage object + this._localStorage = new progress.data.LocalStorage(); + } + + var dataObj = this._prepareDataObjectForLocalStorage(dataMode); + this._localStorage.saveToLocalStorage(name, dataObj); + }; + + /* + * Reads localStorage (based upon name) into JSDO memory + * (localStorage may or may not have pending changes). + * readLocal() + * readLocal(name) + * + */ + this.readLocal = function readLocal(name) { + if (arguments.length > 1) { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); + } + if (name === undefined || name === null || name === "") { + name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; + } + else if (typeof(name) != 'string') { + throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); + } + + if (this._localStorage === null) { + this._localStorage = new progress.data.LocalStorage(); + } + + var object = this._localStorage.readFromLocalStorage(name); + + // If storage area does not exist (i.e. object = null) then don't update JSDO local memory + if (object) { + if (this._hasMatchingSchema(object) === false) + throw new Error(msg.getMsgText("jsdoMSG117", name)); + + // For readLocal(), JSDO should first be emptied of data, so using MODE_EMPTY + this._restoreFromLocalStorage(object, progress.data.JSDO.MODE_EMPTY); + } + + return object !== null; + }; + + /* + * Reads localStorage (based upon name) into JSDO memory + * (localStorage may or may not have pending changes). + * addLocalRecords(addMode) + * addLocalRecords(addMode, keyFields) + * addLocalRecords(name, addMode) + * addLocalRecords(name, addMode, keyFields) + */ + this.addLocalRecords = function addLocalRecords(arg1, arg2, arg3) { + var name; + var addMode; + var keyFields; + + if (arguments.length < 1) { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); + } + + if (typeof(arg1) == 'string') { + name = arg1; + addMode = arg2; + keyFields = arg3; + } + else { + name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; + addMode = arg1; + keyFields = arg2; + } + + if (typeof(name) == 'undefined' || name === null || name === "") { + name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; + } + else if (typeof(name) != 'string') { + throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); + } + + if (addMode != progress.data.JSDO.MODE_REPLACE) { + throw new Error(msg.getMsgText("jsdoMSG115", arguments.callee.name)); + } + + if (this._localStorage === null) { + this._localStorage = new progress.data.LocalStorage(); + } + + var object = this._localStorage.readFromLocalStorage(name); + + // If storage area does not exist (i.e. object = null) then don't update JSDO local memory + if (object) { + if (this._hasMatchingSchema(object) === false) + throw new Error(msg.getMsgText("jsdoMSG117", name)); + + try { + this._restoreFromLocalStorage(object, addMode, keyFields); + } + catch (e) { + var text = e.message; + throw new Error(text.replace(new RegExp('addRecords', 'g'), 'addLocalRecords')); + } + } + + return object !== null; + }; + + + /* + * This method returns True if each buffer in the jsdo contains a primary key. + */ + this._containsPrimaryKeys = function _containsPrimaryKeys() { + + for (var buf in this._buffers) { + if (this._buffers[buf]._primaryKeys === null) + return false; + } + + return true; + }; + + /* + * Compares JSDO's dataset/table names with those in specified storage object. + * Returns true if they match (or if storageObject is null or empty), else false. + */ + this._hasMatchingSchema = function _hasMatchingSchema(storageObject) { + var isValid = true; + + if (storageObject === null || (Object.keys(storageObject).length === 0)) + return true; + + + if (this._dataSetName) { + if (storageObject[this._dataSetName]) { + for (var buf in this._buffers) + if (storageObject[this._dataSetName][buf] === undefined) { + isValid = false; + break; + } + } + else + isValid = false; // dataset should be in storage area + } + else if (this._dataProperty) { + // If array, we had to wrap in "fake" dataset, so unwrap it + storageObject = storageObject["_localStorage"]; + if (storageObject === undefined || storageObject[this._dataProperty] === undefined) + isValid = false; + } + else { + // If temp-table, we had to wrap in "fake" dataset, so unwrap it + storageObject = storageObject["_localStorage"]; + if (storageObject === undefined || storageObject[this._defaultTableRef._name] === undefined) + isValid = false; + } + + return isValid; + }; + + + /* + * Clears the data saved to local storage. + * + * deleteLocal() + * deleteLocal(name) + */ + this.deleteLocal = function deleteLocal(name) { + if (arguments.length > 1) { + throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); + } + if (name === undefined || name === null || name === "") { + name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; + } + else if (typeof(name) != 'string') { + throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); + } + + if (this._localStorage === null) { + this._localStorage = new progress.data.LocalStorage(); + } + this._localStorage.clearLocalStorage(name); + }; + + + // This method is used by saveLocal() to return a jsonObject with current JSDO data based upon option. + // + // In order to take advantage of existing code (createChangeSet() and addRecords()) and particularly + // to use the processing of before-data in addRecords(), for tables and arrays, we create a dummy + // dataset name: _localStorage. + this._prepareDataObjectForLocalStorage = function (option) { + + var storageObject = {}; + + // DataSets + if (this._dataSetName) { + switch (option) { + case progress.data.JSDO.ALL_DATA: + storageObject = this._createDataAndChangeSet(this._dataSetName); + break; + + case progress.data.JSDO.CHANGES_ONLY: + storageObject = this._createChangeSet(this._dataSetName, true); + break; + } + } + // Arrays + else if (this._dataProperty) { + switch (option) { + case progress.data.JSDO.ALL_DATA: + storageObject = this._createDataAndChangeSet("_localStorage"); + break; + + case progress.data.JSDO.CHANGES_ONLY: + storageObject = this._createChangeSet("_localStorage", true); + break; + } + } + // Temp Tables + else { + switch (option) { + case progress.data.JSDO.ALL_DATA: + storageObject = this._createDataAndChangeSet("_localStorage"); + break; + + case progress.data.JSDO.CHANGES_ONLY: + storageObject = this._createChangeSet("_localStorage", true); + break; + } + } + + return storageObject; + }; + + + // Restore the data retrieved from local storage to the JSDO based upon the specified addMode + this._restoreFromLocalStorage = function (storageObject, addMode, keyFields) { + + if (storageObject && (Object.keys(storageObject).length > 0)) { + if (this._dataSetName) { + // Walk thru all tables to retrieve data + for (var buf in this._buffers) + this._restoreDataForTable(this._buffers[buf], storageObject, addMode, keyFields); + } + // Either temp-table or array + else + this._restoreDataForTable(this._defaultTableRef, storageObject, addMode, keyFields); + } + else if (addMode === progress.data.JSDO.MODE_EMPTY) + this._clearData(); + }; + + + this._restoreDataForTable = function (tableRef, jsonObject, addMode, keyFields) { + + // If primaryKeys not found, check if the idProperty is there + keyFields = keyFields !== undefined ? keyFields : tableRef._primaryKeys; + if (keyFields === undefined && this._resource.idProperty) { + keyFields = []; + keyFields[0] = this._resource.idProperty; + } + + if (this._dataSetName) { + var oldUseRelationships = this.useRelationships; + // Turn off useRelationships since addRecords() does not use the working record + this.useRelationships = false; + + try { + tableRef.addRecords(jsonObject, addMode, keyFields); + } finally { + // Restore useRelationships + this.useRelationships = oldUseRelationships; + } + } + // else it's either an array (this._dataProperty) or a temp-table + else { + // Creating dummy dataset name: "_localStorage" for tables and arrays + this._dataSetName = "_localStorage"; + tableRef.addRecords(jsonObject, addMode, keyFields); + this._dataSetName = null; + } + }; + + this.getMethodProperties = function(operation, name) { + var idx; + + if (this._resource._operations) { + if (this._resource._operations[operation]) { + return this._resource._operations[operation]; + } + } + else { + this._resource._operations = {}; + } + for (var idx = 0; idx < this._resource.operations.length; idx++) { + if (this._resource.operations[idx].type == operation) { + return (this._resource._operations[operation] = this._resource.operations[idx]); + } + } + }; + + /////////////////////////////////////////////////////////////////////////// + + // Load data + if (autoFill) + this.fill(); + + }; // End of JSDO + + // Constants for progress.data.JSDO + if ((typeof Object.defineProperty) == 'function') { + Object.defineProperty(progress.data.JSDO, 'MODE_APPEND', { + value: 1, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'MODE_EMPTY', { + value: 2, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'MODE_MERGE', { + value: 3, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'MODE_REPLACE', { + value: 4, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'ERROR', { + value: -1, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'APP_ERROR', { + value: -2, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'RETVAL', { + value: -3, + enumerable: true + }); + Object.defineProperty(progress.data.JSDO, 'DATA_ERROR', { + value: -4, + enumerable: true + }); + } else { + progress.data.JSDO.MODE_APPEND = 1; + progress.data.JSDO.MODE_EMPTY = 2; + progress.data.JSDO.MODE_MERGE = 3; + progress.data.JSDO.MODE_REPLACE = 4; + } + + /* CRUD */ + progress.data.JSDO._OP_CREATE = 1; + progress.data.JSDO._OP_READ = 2; + progress.data.JSDO._OP_UPDATE = 3; + progress.data.JSDO._OP_DELETE = 4; + progress.data.JSDO._OP_SUBMIT = 5; + + /* Offline support: saving data to local storage */ + progress.data.JSDO.ALL_DATA = 1; + progress.data.JSDO.CHANGES_ONLY = 2; + + // Arrays elements as individual fields + // Separator must have at least one characters + progress.data.JSDO.ARRAY_INDEX_SEPARATOR = "_"; + + // setup inheritance for JSDO + progress.data.JSDO.prototype = new progress.util.Observable(); + progress.data.JSDO.prototype.constructor = progress.data.JSDO; + progress.data.JSDO.prototype.toString = function (radix) { + return "JSDO"; + }; + + // setup inheritance for table reference + progress.data.JSTableRef.prototype = new progress.util.Observable(); + progress.data.JSTableRef.prototype.constructor = progress.data.JSTableRef; + progress.data.JSTableRef.prototype.toString = function (radix) { + return "JSTableRef"; + }; + + // Built-in Plugins + progress.data.PluginManager.addPlugin("JFP", { + requestMapping: function(jsdo, params, info) { + var sortFields, + field, + fieldName, + fieldInfo, + tableName, + filter, + sortDir, + ablFilter, + sqlQuery, + methodProperties, + capabilities, + index, + position, + option, + capabilitiesObject, + reqCapabilities = { + filter: { options: [ "ablFilter", "sqlQuery" ], mapping: undefined }, + top: { options: [ "top" ], mapping: undefined }, + skip: { options: [ "skip" ], mapping: undefined }, + id: { options: [ "id" ], mapping: undefined }, + sort: { options: [ "orderBy" ], mapping: undefined } + }, + doConversion = true, + param; + + if (info.operation === "read") { + capabilitiesObject = {}; + methodProperties = jsdo.getMethodProperties(info.operation); + capabilities = methodProperties.capabilities; + + if (capabilities) { + capabilities = capabilities.replace(/\s/g, "").split(","); + for (index = 0; index < capabilities.length; index += 1) { + capabilitiesObject[capabilities[index]] = true; + } + } + for (param in params) { + if (param && (params[param] !== undefined) && reqCapabilities[param]) { + for (index = 0; index < reqCapabilities[param].options.length; index += 1) { + option = reqCapabilities[param].options[index]; + if (capabilitiesObject[option]) { + reqCapabilities[param].mapping = option; + break; + } + } + if (!reqCapabilities[param].mapping) { + throw new Error(msg.getMsgText("jsdoMSG120", + reqCapabilities[param].options.join("' or '"), param)); + } + } + } + + if (jsdo._defaultTableRef && params.tableRef === undefined) { + tableName = jsdo._defaultTableRef._name; + } + else { + tableName = params.tableRef; + } + + if (params.sort) { + // Convert sort expression to JFP format + + if (typeof(params.sort) === "object" && !(params.sort instanceof Array)) { + // Kendo UI sort format - object + // Make params.sort an array + params.sort = (Object.keys( params.sort).length > 1) ? [params.sort] : []; + } + sortFields = ""; + for (index = 0; index < params.sort.length; index += 1) { + field = params.sort[index]; + sortDir = ""; + + if (typeof(field) === "string") { + // setSortFields format + // Extract fieldName and sortDir from string + fieldName = field; + position = field.indexOf(":"); + if (position !== -1) { + sortDir = fieldName.substring(position + 1); + fieldName = fieldName.substring(0, position); + switch(sortDir.toLowerCase()) { + case "desc": + case "descending": + sortDir = "desc"; + break; + } + } + } else { + // Kendo UI sort format - array + // Extract fieldName and sortDir from object + fieldName = field.field; + if (params.sort[index].dir === "desc") { + sortDir = params.sort[index].dir; + } + } + if (tableName) { + // Use original fieldName instead of serialized name + fieldInfo = jsdo[tableName]._fields[fieldName.toLowerCase()]; + if (fieldInfo && fieldInfo.origName) { + fieldName = fieldInfo.origName; + } + } + if (sortDir === "desc") { + fieldName += " DESC"; + } + sortFields += fieldName; + if (index < params.sort.length - 1) { + sortFields += ","; + } + } + } + // Check for empty object + if (typeof(params.filter) === "object" && !(params.filter instanceof Array)) { + params.filter = (Object.keys(params.filter).length >= 1) ? params.filter : undefined; + } + + if (params.filter) { + // If filter is specified as string, then no conversion is necessary + if (typeof params.filter === 'string') { + doConversion = false; + } + + params.tableRef = tableName; + + if (doConversion && (params.tableRef === undefined)) { + throw new Error(msg.getMsgText("jsdoMSG045", "fill() or read()", "params", + "tableRef")); + } + + if (reqCapabilities["filter"].mapping === "ablFilter") { + if (doConversion) { + ablFilter = progress.util._convertToABLWhereString( + jsdo._buffers[params.tableRef], params.filter); + } + else { + ablFilter = params.filter; + } + } + else if (reqCapabilities["filter"].mapping === "sqlQuery") { + if (doConversion) { + sqlQuery = progress.util._convertToSQLQueryString( + jsdo._buffers[params.tableRef], params.filter, true); + } + else { + sqlQuery = params.filter; + } + } + } + + filter = JSON.stringify({ + ablFilter: ablFilter, + sqlQuery: sqlQuery, + orderBy: sortFields, + skip: params.skip, + top: params.top, + id: params.id + }); + + params = {filter: filter}; + } + return params; + } + }); + + if (typeof progress.ui == 'undefined') + progress.ui = {}; + progress.ui.UITableRef = function UITableRef(tableRef) { + this._tableRef = tableRef; + this._listview = null; + this._detailPage = null; + this._listviewContent = undefined; + + this.addItem = function (format) { + var detailForm; + + if (!this._tableRef.record) + throw new Error(msg.getMsgText("jsdoMSG002", this._name)); + + if (!this._listview) return; + + format = format ? format : this._listview.format; + detailForm = (this._detailPage && this._detailPage.name) ? this._detailPage.name : ""; + + if (this._listviewContent === undefined) { + this.clearItems(); + } + var text = this._listview.itemTemplate ? + this._listview.itemTemplate : progress.ui.UIHelper._itemTemplate; + + text = text.replace(new RegExp('{__format__}', 'g'), format); + text = text.replace(new RegExp('{__id__}', 'g'), this._tableRef.record.data._id); + text = text.replace(new RegExp('{__page__}', 'g'), detailForm); + + for (var field in this._tableRef.record.data) { + var value = this._tableRef.record.data[field]; + text = text.replace(new RegExp('{' + field + '}', 'g'), + (value !== undefined && value !== null) ? value : ""); + } + + this._listviewContent += text; + }; + + this.clearItems = function () { + if (this._listview) { + this._listviewContent = ''; + var listviewElement = document.getElementById(this._listview.name); + if (listviewElement) { + listviewElement.innerHTML = ''; + } + } + }; + + this._getFormFieldValue = function (fieldName, detailPageName) { + var value = null, field; + + if (detailPageName === undefined) { + if (this._detailPage && this._detailPage.name) + detailPageName = this._detailPage.name; + } + + if (typeof($) == 'function' && detailPageName) { + field = $("#" + detailPageName + " #" + fieldName); + if (!field || field.length === 0) + field = $("#" + detailPageName + ' [dsid="' + fieldName + '"]'); + if (field && field.length == 1) + value = field.val(); + } + else { + field = document.getElementById(fieldName); + if (field) { + value = field.value; + } + } + + return value; + }; + + this._setFormField = function (fieldName, value, detailPageName) { + var field = null; + + if (detailPageName === undefined) { + if (this._detailPage && this._detailPage.name) + detailPageName = this._detailPage.name; + } + + if (typeof($) == 'function' && detailPageName) { + field = $("#" + detailPageName + " #" + fieldName); + if (!field || field.length === 0) + field = $("#" + detailPageName + ' [dsid="' + fieldName + '"]'); + if (field && field.length == 1) + field.val(value); + } + else { + field = document.getElementById(fieldName); + if (field) { + field.value = value; + } + } + }; + + /* + * Assigns field values from the form. + */ + this.assign = function (detailPageName) { + if (!this._tableRef.record) + throw new Error(msg.getMsgText("jsdoMSG002", this._tableRef._name)); + if ((arguments.length !== 0) && (typeof detailPageName != 'string')) + throw new Error(msg.getMsgText("jsdoMSG024", "UIHelper", "assign()")); + + // Ensure creation of before image record + this._tableRef.record.assign(null); + + var fieldName; + var schema = this._tableRef.getSchema(); + for (var i = 0; i < schema.length; i++) { + fieldName = schema[i].name; + if (fieldName == '_id') continue; + var value = this._getFormFieldValue(fieldName, detailPageName); + // CR OE00241289 Should always copy over field value unless undefined, + // user may have explicitly set it to blank + if (typeof value != 'undefined') { + if (typeof value == 'string' && schema[i].type != 'string') { + value = this._tableRef._jsdo._convertType(value, + schema[i].type, + schema[i].items ? schema[i].items.type : null); + } + this._tableRef.record.data[fieldName] = value; + } + } + + // Ensure order of record + this._tableRef.record._sortRecord(); + + return true; + }; + + this.display = function (pageName) { + if (!this._tableRef.record) + throw new Error(msg.getMsgText("jsdoMSG002", this._tableRef._name)); + + // Display record to form + var schema = this._tableRef.getSchema(); + for (var i = 0; i < schema.length; i++) { + this._setFormField(schema[i].name, this._tableRef.record.data[schema[i].name], pageName); + } + this._setFormField('_id', this._tableRef.record.data._id, pageName); + }; + + this.showListView = function () { + if (!this._listview) return; + + var uiTableRef = this; + var listviewElement; + if (typeof($) == 'function') { + listviewElement = $("#" + this._listview.name); + if (listviewElement && listviewElement.length == 1) { + listviewElement.html(this._listviewContent ? this._listviewContent : ''); + try { + if (listviewElement.attr("data-filter") === "true" + && typeof listviewElement.filterable === "function") { + listviewElement.filterable("refresh"); + } + else { + listviewElement.listview("refresh"); + } + } + catch (e) { + // Workaround for issue with JQuery Mobile throwning exception on refresh + } + } + + if (this._listview.autoLink) { + // Add trigger for 'tap' event to items + $("#" + this._listview.name + " li").each( + function (/* index */) { + $(this).bind('click', + function (/* event, ui */) { + var jsrecord = uiTableRef.getListViewRecord(this); + uiTableRef.display(); + if (typeof(uiTableRef._listview.onSelect) == 'function') { + uiTableRef._listview.onSelect(event, this, jsrecord); + } + }); + }); + } + } + else { + listviewElement = document.getElementById(this._listview.name); + if (listviewElement) { + listviewElement.innerHTML = this._listviewContent; + } + + if (this._listview.autoLink) { + var element = document.getElementById(this._listview.name); + if (element && element.childElementCount > 0) { + for (var i = 0; i < element.children.length; i++) { + element.children[i].onclick = function () { + var jsrecord = this.getListViewRecord(this); + this.display(); + if (typeof(uiTableRef._listview.onSelect) == 'function') { + uiTableRef._listview.onSelect(event, this, jsrecord); + } + }; + } + } + } + } + + this._listviewContent = undefined; + }; + + this.getFormFields = function (fields) { + var i; + + if (!this._tableRef._schema) + return ''; + if (!(fields instanceof Array)) + fields = null; + else { + var tmpFields = {}; + for (i = 0; i < fields.length; i++) { + tmpFields[fields[i]] = fields[i]; + } + fields = tmpFields; + } + var htmltext; + if (!fields || fields['_id']) { + htmltext = ''; + } + else + htmltext = ''; + htmltext += '
'; + + for (i = 0; i < this._tableRef._schema.length; i++) { + var fieldName = this._tableRef._schema[i].name; + if (fieldName == '_id') continue; + if (fieldName.length > 0 && fieldName.charAt(0) == '_') continue; + if (fields && fields[fieldName] === undefined) continue; + var fieldLabel = this._tableRef._schema[i].title ? + this._tableRef._schema[i].title : this._tableRef._schema[i].name; + var text = (this._detailPage && this._detailPage.fieldTemplate) ? + this._detailPage.fieldTemplate : progress.ui.UIHelper._fieldTemplate; + text = text.replace(new RegExp('{__label__}', 'g'), fieldLabel); + text = text.replace(new RegExp('{__name__}', 'g'), this._tableRef._schema[i].name); + htmltext += text; + } + htmltext += '
'; + fields = null; + return htmltext; + }; + + this.getListViewRecord = function (htmlIElement) { + var id = htmlIElement.getAttribute('data-id'); + return this._tableRef.findById(id); + }; + + this.getFormRecord = function (detailPageName) { + var id = this._getFormFieldValue('_id', detailPageName); + return this._tableRef.findById(id); + }; + + this._getIdOfElement = function (name) { + if (typeof($) == 'function') { + var element = $("#" + name); + if (!element || element.length === 0) { + element = $('[dsid="' + name + '"]'); + if (element && element.length == 1) { + var id = element.attr("id"); + if (id) + return id; + } + } + } + return name; + }; + + this.setDetailPage = function setDetailPage(obj) { + if (!obj || (typeof(obj) != 'object')) + throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "object")); + if (!obj.name || (typeof(obj.name) != 'string')) + throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "name")); + this._detailPage = obj; + this._detailPage.name = this._getIdOfElement(this._detailPage.name); + }; + this.setListView = function setListView(obj) { + if (!obj || (typeof(obj) != 'object')) + throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "object")); + if (!obj.name || (typeof(obj.name) != 'string')) + throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "name")); + if (obj.format && (typeof(obj.name) != 'string')) + throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "format")); + + this._listview = obj; + this._listview.name = this._getIdOfElement(this._listview.name); + if (!this._listview.format) { + if (typeof($) == 'function') { + for (var i = 0; i < this._tableRef._schema.length; i++) { + var fieldName = this._tableRef._schema[i].name; + + var field = $("#" + this._listview.name + ' [dsid="' + fieldName + '"]'); + if (field && field.length == 1) { + field.html('{' + fieldName + '}'); + } + } + } + var text = document.getElementById(this._listview.name).innerHTML; + var pos = text.indexOf(''; + progress.ui.UIHelper._defaultFieldTemplate = '
' + + '' + + '
'; + progress.ui.UIHelper._itemTemplate = progress.ui.UIHelper._defaultItemTemplate; + progress.ui.UIHelper._fieldTemplate = progress.ui.UIHelper._defaultFieldTemplate; + + progress.ui.UIHelper.setItemTemplate = function (template) { + progress.ui.UIHelper._itemTemplate = template ? template : progress.ui.UIHelper._defaultItemTemplate; + }; + + progress.ui.UIHelper.setFieldTemplate = function (template) { + progress.ui.UIHelper._fieldTemplate = + template ? template : progress.ui.UIHelper._defaultFieldTemplate; + }; + +})(); + +//this is so that we can see the code in Chrome's Source tab when script is loaded via XHR + +/* +progress.session.js Version: 5.0.0 + +Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +/*global progress:true */ +(function () { + + /* define these if not defined yet - they may already be defined if + progress.js was included first */ + if (progress === undefined) { + progress = {}; + } + if (progress.data === undefined) { + progress.data = {}; + } + + progress.data.ServicesManager = {}; + progress.data.ServicesManager._services = []; + progress.data.ServicesManager._resources = []; + progress.data.ServicesManager._data = []; + progress.data.ServicesManager._sessions = []; + progress.data.ServicesManager._jsdosessions = []; + /* + progress.data.ServicesManager.put = function(id, jsdo) { + progress.data.ServicesManager._data[id] = jsdo; + }; + progress.data.ServicesManager.get = function(id) { + return progress.data.ServicesManager._data[id]; + }; + */ + + progress.data.ServicesManager.addResource = function (id, resource) { + if (progress.data.ServicesManager._resources[id] === undefined) { + progress.data.ServicesManager._resources[id] = resource; + } + else { + throw new Error("A resource named '" + id + "' was already loaded."); + } + }; + progress.data.ServicesManager.getResource = function (id) { + return progress.data.ServicesManager._resources[id]; + }; + progress.data.ServicesManager.addService = function (id, service) { + if (progress.data.ServicesManager._services[id] === undefined) { + progress.data.ServicesManager._services[id] = service; + } + else { + throw new Error("A service named '" + id + "' was already loaded."); + } + }; + progress.data.ServicesManager.getService = function (id) { + return progress.data.ServicesManager._services[id]; + }; + progress.data.ServicesManager.addSession = function (catalogURI, session) { + if (progress.data.ServicesManager._sessions[catalogURI] === undefined) { + progress.data.ServicesManager._sessions[catalogURI] = session; + } + else { + throw new Error("Cannot load catalog '" + catalogURI + "' multiple times."); + } + }; + + progress.data.ServicesManager.addJSDOSession = function (catalogURI, jsdosession) { + if (progress.data.ServicesManager._jsdosessions[catalogURI] === undefined) { + progress.data.ServicesManager._jsdosessions[catalogURI] = jsdosession; + } + else { + throw new Error("Cannot load catalog '" + catalogURI + "' multiple times."); + } + }; + progress.data.ServicesManager.getSession = function (catalogURI) { + try { + return progress.data.ServicesManager._sessions[catalogURI]; + } + catch (e) { + return null; + } + }; + + progress.data.ServicesManager.cleanSession = function (session) { + var servicesKey, + resourcesKey, + sessionsKey, + service, + services = progress.data.ServicesManager._services, + resources = progress.data.ServicesManager._resources, + sessions = progress.data.ServicesManager._sessions, + jsdosessions = progress.data.ServicesManager._jsdosessions; + + // Delete the services and resources in the ServicesManager + // associated with the Session given + for (servicesKey in services) { + service = null; + if (services[servicesKey]._session === session) { + service = services[servicesKey]; + delete services[servicesKey]; + } + + if (!service) { + continue; + } + + for (resourcesKey in resources) { + if (resources[resourcesKey].service === service) { + delete resources[resourcesKey]; + } + } + } + + // Delete the session and jsdosession from the ServicesManager + for (sessionsKey in sessions) { + if (sessions[sessionsKey] === session) { + delete sessions[sessionsKey]; + + if(jsdosessions[sessionsKey]) { + delete jsdosessions[sessionsKey]; + } + } + } + }; + + /* + * Scans URL for parameters of the form {name} + * Returns array with the names + */ + function extractParamsFromURL(url) { + var urlParams = [], + paramName = null; + + if (typeof (url) === 'string') { + url.split("").forEach(function (c) { + if (c === '{') { + paramName = ""; + } else if (c === '}') { + if (paramName) { + urlParams.push(paramName); + } + paramName = null; + } else if (paramName !== null) { + paramName += c; + } + }); + } + return urlParams; + } + + /* + * Adds the catalog.json file provided by the catalog parameter, which is a JSDO + * that has loaded the catalog + */ + progress.data.ServicesManager.addCatalog = function (services, session) { + var name, value; + + if (!services) { + throw new Error("Cannot find 'services' property in catalog file."); + } + if (services instanceof Array) { + + // first check if there are duplicates before we add them to our cache, + // which only handles unique values + services.forEach(function (service) { + // don't allow services with the same name across sessions + if (progress.data.ServicesManager.getService(service.name) !== undefined) { + throw new Error("A service named '" + service.name + "' was already loaded."); + } + + if (service.resources instanceof Array) { + service.resources.forEach(function (resource) { + if (progress.data.ServicesManager.getResource(resource.name) !== undefined) { + throw new Error("A resource named '" + resource.name + "' was already loaded."); + } + }); + } + else { + throw new Error("Missing 'resources' array in catalog."); + } + }); + + for (var j = 0; j < services.length; j++) { + services[j]._session = session; + this.addService(services[j].name, services[j]); // Register the service + var resources = services[j].resources; + var baseAddress = services[j].address; + if (resources instanceof Array) { + for (var i = 0; i < resources.length; i++) { + var resource = resources[i]; + resource.fn = {}; + resource.service = services[j]; + resources[i].url = baseAddress + resources[i].path; + // Register resource + progress.data.ServicesManager.addResource(resources[i].name, resources[i]); + + // Process schema + resource.fields = null; + resource.primaryKeys = null; + if (resource.schema) { + resource.fields = {}; + resource.primaryKeys = {}; + resource._dataSetName = undefined; + resource._tempTableName = undefined; + var properties = null; + + var keys, field; + + try { + if (typeof resource.schema.properties != 'undefined') { + keys = Object.keys(resource.schema.properties); + properties = resource.schema.properties; + if (keys.length == 1) { + if (typeof resource.schema.properties[keys[0]].properties != + 'undefined') { + // Schema corresponds to a DataSet + resource._dataSetName = keys[0]; + } + else if (typeof resource.schema.properties[keys[0]].items != + 'undefined') { + // Schema corresponds to a temp-table + resource.dataProperty = keys[0]; + properties = resource.schema.properties[keys[0]].items.properties; + resource._tempTableName = resource.dataProperty; + resource.primaryKeys[resource._tempTableName] = + resource.schema.properties[keys[0]].primaryKey; + } + } + } + else { + keys = Object.keys(resource.schema); + if (keys.length == 1) { + resource.dataProperty = keys[0]; + if (typeof resource.schema[keys[0]].items != 'undefined') { + // Catalog format correspond to Table Schema + properties = resource.schema[keys[0]].items.properties; + resource._tempTableName = resource.dataProperty; + resource.primaryKeys[resource._tempTableName] = + resource.schema[keys[0]].primaryKey; + } + else if (typeof resource.schema[keys[0]].properties != 'undefined') { + // Catalog format correspond to DataSet Schema + resource._dataSetName = keys[0]; + resource.dataProperty = null; + properties = resource.schema; + } + } + } + } + catch (e) { + throw new Error("Error parsing catalog file."); + } + + var tableName; + if (properties) { + if (resource._dataSetName) { + properties = properties[resource._dataSetName].properties; + for (tableName in properties) { + resource.fields[tableName] = []; + resource.primaryKeys[tableName] = properties[tableName].primaryKey; + var tableProperties; + if (properties[tableName].items + && properties[tableName].items.properties) { + tableProperties = properties[tableName].items.properties; + } + else { + tableProperties = properties[tableName].properties; + } + for (field in tableProperties) { + tableProperties[field].name = field; + if (field != '_id') + resource.fields[tableName].push(tableProperties[field]); + } + } + } + else { + tableName = resource.dataProperty ? resource.dataProperty : ""; + resource.fields[tableName] = []; + for (field in properties) { + properties[field].name = field; + if (field != '_id') + resource.fields[tableName].push(properties[field]); + } + } + } + else + throw new Error("Error parsing catalog file."); + } + else + resource.fields = null; + + // Validate relationship property + if ((resource.relations instanceof Array) + && resource.relations[0] + && resource.relations[0].RelationName) { + throw new Error( + "Relationship properties in catalog must begin with lowercase."); + } + // Process operations + resource.generic = {}; + if (resource.operations) { + for (var idx = 0; idx < resource.operations.length; idx++) { + if (resource.operations[idx].path) { + resource.operations[idx].url = + resource.url + resource.operations[idx].path; + } + else { + resource.operations[idx].url = resource.url; + } + if (!resource.operations[idx].params) { + resource.operations[idx].params = []; + } + if (!resource.operations[idx].type) { + resource.operations[idx].type = "INVOKE"; + } + + // Set opname - validation of opname is done later + var opname = resource.operations[idx].type.toLowerCase(); + + // Set default verb based on operation + if (!resource.operations[idx].verb) { + switch (opname) { + case 'create': + resource.operations[idx].verb = "POST"; + break; + case 'read': + resource.operations[idx].verb = "GET"; + break; + case 'update': + case 'invoke': + case 'submit': + case 'count': + resource.operations[idx].verb = "PUT"; + break; + case 'delete': + resource.operations[idx].verb = "DELETE"; + break; + default: + break; + } + } + + // Point fn to operations + var func = function fn(object, async) { + var deferred; + + // Add static variable fnName to function + if (typeof fn.fnName == 'undefined') { + fn.fnName = arguments[0]; // Name of function + fn.definition = arguments[1]; // Operation definition + return; + } + + var reqBody = null; + var url = fn.definition.url; + var jsdo = this; + var xhr = null; + + var request = {}; + var i; + + if (object) { + if (typeof (object) != "object") { + throw new Error("Catalog error: Function '" + + fn.fnName + "' requires an object as a parameter."); + } + var objParam; + if (object instanceof XMLHttpRequest + || (object.constructor + && object.constructor.name === "XMLHttpRequest")) { + jsdo = object.jsdo; + xhr = object; + objParam = xhr.objParam; + + // use the request from the xhr request if possible + request = xhr.request; + } + else { + objParam = object; + } + + if (typeof async == 'undefined') { + async = this._async; + } + else { + async = Boolean(async); + } + + request.objParam = objParam; + + // Process objParam + var isInvoke = (fn.definition.type.toUpperCase() == 'INVOKE'); + for (i = 0; i < fn.definition.params.length; i++) { + name = fn.definition.params[i].name; + switch (fn.definition.params[i].type) { + case 'PATH': + case 'QUERY': + case 'MATRIX': + var value = null; + if (objParam) + value = objParam[name]; + if (!value) + value = ""; + if (url.indexOf('{' + name + '}') == -1) { + throw new Error("Catalog error: Reference to " + + fn.definition.params[i].type + " parameter '" + + name + "' is missing in path."); + } + url = url.replace( + new RegExp('{' + name + '}', 'g'), + encodeURIComponent(value)); + break; + case 'REQUEST_BODY': + case 'REQUEST_BODY,RESPONSE_BODY': + case 'RESPONSE_BODY,REQUEST_BODY': + if (xhr && !reqBody) { + reqBody = objParam; + } + else { + var reqParam = objParam[name]; + if (isInvoke + && (fn.definition.params[i].xType + && ("DATASET,TABLE".indexOf( + fn.definition.params[i].xType) != -1))) { + var unwrapped = (jsdo._resource.service.settings + && jsdo._resource.service.settings.unwrapped); + if (unwrapped) { + // Remove extra level if found + if ((typeof (reqParam) == 'object') + && (Object.keys(reqParam).length == 1) + && (typeof (reqParam[name]) == 'object')) + reqParam = reqParam[name]; + } + else { + // Add extra level if not found + if ((typeof (reqParam) == 'object') + && (typeof (reqParam[name]) == 'undefined')) { + reqParam = {}; + reqParam[name] = objParam[name]; + } + } + } + if (!reqBody) { + reqBody = {}; + } + reqBody[name] = reqParam; + } + break; + case 'RESPONSE_BODY': + break; + default: + throw new Error("Catalog error: " + + "Unexpected parameter type '" + + fn.definition.params[i].type + "'."); + } + } + + // URL has parameters + if (url.indexOf('{') != -1) { + var paramsFromURL = extractParamsFromURL(url); + for (i = 0; i < paramsFromURL.length; i++) { + name = paramsFromURL[i]; + value = null; + if (objParam) + value = objParam[name]; + if (!value) + value = ""; + if (typeof (value) === "object") { + value = JSON.stringify(value); + } + url = url.replace( + new RegExp('{' + name + '}', 'g'), + encodeURIComponent(value)); + } + } + } + + request.fnName = fn.fnName; + request.async = async; + + if (request.deferred === undefined) { + deferred = new progress.util.Deferred(); + request.deferred = deferred; + } + + var data = jsdo._httpRequest(xhr, fn.definition.verb, + url, reqBody, request, async); + return data; + }; + // End of Function Definition + + switch (resource.operations[idx].verb.toLowerCase()) { + case 'get': + case 'post': + case 'put': + case 'delete': + break; + default: + throw new Error("Catalog error: Unexpected HTTP verb '" + + resource.operations[idx].verb + + "' found while parsing the catalog."); + } + + switch (opname) { + case 'invoke': + break; + case 'create': + case 'read': + case 'update': + case 'delete': + case 'submit': + case 'count': + if (typeof (resource.generic[opname]) == "function") { + throw new Error("Catalog error: Multiple '" + + resource.operations[idx].type + + "' operations specified in the catalog for resource '" + + resource.name + "'."); + } + else + resource.generic[opname] = func; + break; + default: + throw new Error("Catalog error: Unexpected operation '" + + resource.operations[idx].type + + "' found while parsing the catalog."); + } + + // Set fnName + name = resource.operations[idx].name; + if (opname === "invoke" || opname === "count") { + resource.fn[name] = {}; + resource.fn[name]["function"] = func; + } + else { + name = "_" + opname; + } + func(name, resource.operations[idx]); + } + } + } + } + } + } + else { + throw new Error("Missing 'services' array in catalog."); + } + + }; + + /* + * Prints debug information about the ServicesManager. + */ + progress.data.ServicesManager.printDebugInfo = function (resourceName) { + if (resourceName) { + //console.log("** ServicesManager **"); + //console.log("** BEGIN **"); + var resource = progress.data.ServicesManager.getResource(resourceName); + if (resource) { + var cSchema = "Schema:\n"; + var cOperations = "Operations: " + resource.operations.length + "\n"; + for (var field in resource.schema.properties) { + cSchema += "\nName: " + field + + "\n"; + } + + for (var i = 0; i < resource.operations.length; i++) { + cOperations += "\n" + i + + "\nName: " + resource.operations[i].name + + "\nURL: " + resource.operations[i].url + + "\ntype: " + resource.operations[i].type + + "\nverb: " + resource.operations[i].verb + + "\nparams: " + resource.operations[i].params.length + + "\n"; + } + console.log("** DEBUG INFO **\nResource name: %s\nURL:%s\n%s\n%s\n\n", + resource.name, resource.url, cSchema, cOperations); + } + else + console.log("Resource not found"); + //console.log("** END **"); + } + }; + + + /* + * Contains information about a server-side Mobile service. + * Properties of args parameter for constructor: + * @param name the name of the service + * @param uri the URI of the service + */ + progress.data.MobileServiceObject = function MobileServiceObject(args) { + var _name = args.name; + Object.defineProperty( + this, + 'name', + { + get: function () { + return _name; + }, + enumerable: true + } + ); + + var _uri = args.uri; + Object.defineProperty( + this, + 'uri', + { + get: function () { + return _uri; + }, + enumerable: true + } + ); + }; + + /* + An object that maintains the X-CLIENT-PROPS header string + The data for the string is stored in the internal variable named contextObject and is + always up to date. The internal var contextString isn't created until the first time it's + needed (the first get of the contextHeader property), and then it's updated an cached + A call to setContext or setContextProperty updates contextObject but sets contextString to + null, which signals that it needs to be updated. If contextObject is an empty object, + contextString is set to undefined to indicate that no header is to be sent + */ + progress.data.ContextProperties = function () { + var contextObject = {}, + contextString; // if null, contextObject has been changed but string wasn't updated yet + + // the string to be sent in the X-CLIENT-PROPS header (unless Session.xClientProps has been set) + Object.defineProperty( + this, + 'contextHeader', + { + get: function () { + var header; + + if (contextString === null) { // needs to be updated + header = JSON.stringify(contextObject); + if (header === "{}") { + contextString = undefined; + } else { + contextString = header; + } + } + + return contextString; + }, + enumerable: true + } + ); + + /* determine whether the property is already present, and - + add it if it's not present + remove it if propertyValue is explicitly passed as undefined + otherwise replace its value (even if the new value is null or "") + */ + this.setContextProperty = function (propertyName, propertyValue) { + if (arguments.length < 2) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText( + "jsdoMSG122", + 'Session', + 'setContextProperty', + 2 + )); + } + if (arguments.length !== 2) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText( + "jsdoMSG122", + "Session", + "setContextProperty", + 2 + )); + } + if (typeof propertyName !== "string") { + // {1}: Parameter {1} must be of type {3} in {4} call. + throw new Error(progress.data._getMsgText( + "jsdoMSG121", + 'Session', + 1, + 'string', + 'setContextProperty' + )); + } + + if (propertyValue === undefined) { + delete contextObject[propertyName]; // OK if it doesn't exist -- no error + } else { + contextObject[propertyName] = propertyValue; + } + contextString = null; // must be updated on next get of this.contextHeader + }; + + this.setContext = function (context) { + var prop; + + if (arguments.length < 1) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'setContext', 1)); + } + if (arguments.length > 1) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'setContext', 1)); + } + if (typeof context === "object") { + /* Copy the properties of the context passed in as an argument into + * an internal contextObject. (Note that if the context object passed in + * has a prototype, this code copies them, too) + */ + contextObject = {}; + for (prop in context) { + if (context.hasOwnProperty(prop)) { + if (typeof context[prop] !== "function") { + contextObject[prop] = context[prop]; + } + } + } + } else if ((context === undefined) || (context === null)) { + contextObject = {}; + } else { + // {1}: Parameter {1} must be of type {3} in {4} call. + throw new Error(progress.data._getMsgText( + "jsdoMSG121", + 'Session', + 1, + 'Object', + 'setContextProperty' + )); + } + contextString = null; // must be updated on next get of this.contextHeader + }; + + this.getContext = function () { + if (arguments.length > 0) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContext', 0)); + } + return contextObject; + }; + + this.getContextProperty = function (propertyName) { + if (arguments.length < 1) { + // {1}: Incorrect number of arguments in {2} call. There should be {3}. + throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContextProperty', 1)); + } + if (arguments.length > 1) { + // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; + throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContextProperty', 1)); + } + return contextObject[propertyName]; + }; + + }; // end of ContextProperties + + /* + * Manages authentication and session ID information for a service. + * + * Use: OE mobile developer instantiates a session and calls addCatalog() to load + * information for one or more services defined in a catalog file. + * + * Developer instantiates JDSOs as needed. + * Usually all of the JSDOs will use the same session, but if a client-side + * service needs resources from more than one REST app, there would need to be more + * than one session + * + */ + progress.data.Session = function Session(options) { + + var defPropSupported = false; + if ((typeof Object.defineProperty) === "function") { + defPropSupported = true; + } + + var that = this, + jsdosession, // "backpointer" if this Session is being used by a JSDOSession + isUserAgentiOS = false, // checked just below this var statement + isFirefox = false, // checked just below this var statement + isEdge = false, // checked just below this var statement + isIE = false, // checked just below this var statement + canPassCredentialsToOpenWithCORS = false, // False will always work if creds are correct + defaultiOSBasicAuthTimeout = 4000, + deviceIsOnline = true, // online until proven offline + restApplicationIsOnline = false, // was the Mobile Web Application that this Session object + // connects to online the last time it was checked? + // (value is always false if session is not logged in) + oepingAvailable = false, + defaultPartialPingURI = "/rest/_oeping", + partialPingURI = defaultPartialPingURI, + _storageKey, + _authProvider = null, + customCredentials = false, + + // Note: the variables above here are used during the lifetime of the object; the ones below + // are only used while the constructor is executing + storedAuthModel, + storedURI, + newURI, + stateWasReadFromStorage = false; + + // This is a hidden argument to suppress this warning and be re-used for future warnings + if (!options || options._silent !== true) { + console.warn( + "Session: As of JSDO 4.4, the Session object has been deprecated. " + + "Please use the JSDOSession object instead." + ); + } + + if (typeof navigator !== "undefined") { + if (typeof navigator.userAgent !== "undefined") { + isUserAgentiOS = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i); + isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + // detect that we're running in MS Edge browser + isEdge = navigator.userAgent.indexOf('Edge/') > -1; + // detect that we're running in IE 11 (or IE 11 in pre-11 mode) or IE 10 browser + isIE = ((navigator.userAgent.indexOf('Trident/')) > -1 + || (navigator.userAgent.indexOf('MSIE 10') > -1)); + } + } + + // Firefox, Edge, and IE will throw an error on the send() if CORS is being used for the request + // and we have included credentials in the URI (which is what passing them to open() does), + canPassCredentialsToOpenWithCORS = !(isFirefox || isEdge || isIE); + + // When using basic authentication, we can pass the user name and password to the XMLHttpRequest.open() + // method. However, in some browsers, passing credentials to open() will result in the xhr's .send() + // method throwing an error. The goal of this function is to figure out whether it's safe to include + // the credentials. It returns false if there could be a problem, true otherwise. + // Note: currently it does this solely on the basis of what browser we are running in, regardless + // of whether the request will actually use the CORS protocol. Ideally, we should take into account whether + // the request will actually require CORS. The question is whether we can reliably do that. + // The reason for taking the specific request into account is that there are drawbacks to not passing the + // credentials when we are NOT using CORS, namely that if the credentials are invalid, some browsers will + // put up their own prompt for credentials in non-CORS situations (those browsers are IE, Edge, and Chrome) + function canPassCredentialsToOpen() { + return canPassCredentialsToOpenWithCORS; + } + + this._onlineHandler = function () { + setDeviceIsOnline(true); + that.trigger("online", that, null); + }; + + this._offlineHandler = function () { + setDeviceIsOnline(false); + that.trigger("offline", that, progress.data.Session.DEVICE_OFFLINE, null); + }; + + if ((typeof window !== "undefined") && (window.addEventListener)) { + window.addEventListener("online", this._onlineHandler, false); + window.addEventListener("offline", this._offlineHandler, false); + } + + /* constants and properties - define them as properties via the defineProperty() + * function, which has "writable" and "configurable" parameters that both + * default to false, so these calls create properties that are read-only + * + * IF WE DECIDE THAT WE CAN ASSUME WE ALWAYS RUN WITH A VERSION OF JAVASCRIPT THAT SUPPORTS + * Object.DefineProperty(), WE CAN DELETE THE defPropSupported VARIABLE, THE TEST OF IT BELOW, + * AND THE 'ELSE' CLAUSE BELOW AND ALL THE setXxxx functions (AND CHANGE THE CALLS TO THE setXxxx + * FUNCTIONS SO THEY JUST REFER TO THE PROPERTY) + * + */ + + // define these unconditionally so we don't get a warning on the push calls that they might + // have been uninitialized + var _catalogURIs = []; + var _services = []; + var _jsdos = []; + + this.onOpenRequest = null; + + var _password = null; + + if (defPropSupported) { + var _userName = null; + Object.defineProperty( + this, + 'userName', + { + get: function () { + return _userName; + }, + enumerable: true + } + ); + + var _loginTarget = '/static/home.html'; + Object.defineProperty( + this, + 'loginTarget', + { + get: function () { + return _loginTarget; + }, + enumerable: true + } + ); + + var _serviceURI = null; + Object.defineProperty( + this, + 'serviceURI', + { + get: function () { + return _serviceURI; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'catalogURIs', + { + get: function () { + return _catalogURIs; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'services', + { + get: function () { + return _services; + }, + enumerable: true + } + ); + + var _loginResult = null; + Object.defineProperty( + this, + 'loginResult', + { + get: function () { + return _loginResult; + }, + enumerable: true + } + ); + + var _loginHttpStatus = null; + Object.defineProperty( + this, + 'loginHttpStatus', + { + get: function () { + return _loginHttpStatus; + }, + enumerable: true + } + ); + + var _clientContextId = null; + Object.defineProperty( + this, + 'clientContextId', + { + get: function () { + return _clientContextId; + }, + enumerable: true + } + ); + + var _authenticationModel = progress.data.Session.AUTH_TYPE_ANON; + Object.defineProperty( + this, + 'authenticationModel', + { + get: function () { + return _authenticationModel; + }, + set: function (newval) { + if (newval) { + newval = newval.toLowerCase(); + } + switch (newval) { + case progress.data.Session.AUTH_TYPE_FORM: + case progress.data.Session.AUTH_TYPE_BASIC: + case progress.data.Session.AUTH_TYPE_ANON: + case progress.data.Session.AUTH_TYPE_SSO: + case null: + _authenticationModel = newval; + storeSessionInfo("authenticationModel", newval); + break; + default: + throw new Error( + "Error setting Session.authenticationModel. '" + + newval + "' is an invalid value." + ); + } + }, + enumerable: true + } + ); + + var _lastSessionXHR = null; + Object.defineProperty( + this, + 'lastSessionXHR', + { + get: function () { + return _lastSessionXHR; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'connected', + { + get: function () { + return (this.loginResult === progress.data.Session.LOGIN_SUCCESS) + && restApplicationIsOnline + && deviceIsOnline; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'JSDOs', + { + get: function () { + return _jsdos; + }, + enumerable: true + } + ); + + var _pingInterval = 0; + var _timeoutID = null; + Object.defineProperty( + this, + 'pingInterval', + { + get: function () { + return _pingInterval; + }, + set: function (newval) { + if ((typeof newval === "number") && (newval >= 0)) { + _pingInterval = newval; + storeSessionInfo("pingInterval", newval); + if (newval > 0) { + // if we're logged in, start autopinging + if (this.loginResult === progress.data.Session.LOGIN_SUCCESS) { + _timeoutID = setTimeout(this._autoping, newval); + } + } else if (newval === 0) { + clearTimeout(_timeoutID); + _pingInterval = 0; + } + } else { + throw new Error( + "Error setting Session.pingInterval. '" + + newval + "' is an invalid value." + ); + } + }, + enumerable: true + } + ); + + var _contextProperties = new progress.data.ContextProperties(); + Object.defineProperty( + this, + "_contextProperties", + { + get: function () { + return _contextProperties; + }, + enumerable: false + } + ); + + var isInvalidated = false; + Object.defineProperty( + this, + "_isInvalidated", + { + get: function () { + return isInvalidated; + }, + enumerable: false + } + ); + + // used internally, not supported as part of the Session API (tho authProvider is part + // of the *JSDOSession* API) + Object.defineProperty( + this, + "_authProvider", + { + get: function () { + return _authProvider; + }, + set: function (newval) { + if (_authProvider) { + throw new Error( + "Internal Error setting Session._authProvider. '" + + "The property has already been set." + ); + } + + setAuthProvider(newval); + }, + enumerable: false + } + ); + } else { + this.userName = null; + this.loginTarget = '/static/home.html'; + this.serviceURI = null; + this.catalogURIs = []; + this.services = []; + this.loginResult = null; + this.loginHttpStatus = null; + this.clientContextId = null; + this.authenticationModel = progress.data.Session.AUTH_TYPE_ANON; + this.lastSessionXHR = null; + } + + // stores data value using the JSDOSession's storage key plus the infoName + // argument as a key. If there is no infoName, just uses the storage key + // by itself (the latter case is intended to serve as a flag that we have + // stored this JSDOSession's data before) + // + function storeSessionInfo(infoName, value) { + var key; + if (that.loginResult === progress.data.Session.LOGIN_SUCCESS && + typeof(sessionStorage) === 'object' && _storageKey) { + + key = _storageKey; + if (infoName) { + key = key + "." + infoName; + } + if (typeof value !== 'undefined') { + sessionStorage.setItem(key, JSON.stringify(value)); + } + } + } + + function retrieveSessionInfo(infoName) { + var key, + jsonStr, + value = null; + if (typeof sessionStorage === 'object' && _storageKey) { + key = _storageKey; + if (infoName) { + key = key + "." + infoName; + } + jsonStr = sessionStorage.getItem(key); + if (jsonStr !== null) { + try { + value = JSON.parse(jsonStr); + } catch (e) { + value = null; + } + } + return value; + } + } + + function clearSessionInfo(infoName) { + var key; + if (typeof (sessionStorage) === 'object' && _storageKey) { + key = _storageKey; + if (infoName) { + key = key + "." + infoName; + sessionStorage.removeItem(key); + } + } + } + + function storeAllSessionInfo() { + if (_storageKey) { + storeSessionInfo("loginResult", that.loginResult); + storeSessionInfo("userName", that.userName); + storeSessionInfo("serviceURI", that.serviceURI); + storeSessionInfo("loginHttpStatus", that.loginHttpStatus); + storeSessionInfo("authenticationModel", that.authenticationModel); + storeSessionInfo("pingInterval", that.pingInterval); + storeSessionInfo("oepingAvailable", oepingAvailable); + storeSessionInfo("partialPingURI", partialPingURI); + storeSessionInfo("clientContextId", that.clientContextId); + storeSessionInfo("deviceIsOnline", deviceIsOnline); + storeSessionInfo("restApplicationIsOnline", restApplicationIsOnline); + if (that._authProvider) { + storeSessionInfo( + "_authProvider.init", + { + uri: that._authProvider.uri, + authenticationModel: that._authProvider.authenticationModel + } + ); + } + storeSessionInfo(_storageKey, true); + } + } + + function clearAllSessionInfo() { + if (_storageKey) { + if (retrieveSessionInfo(_storageKey)) { + clearSessionInfo("loginResult"); + clearSessionInfo("userName"); + clearSessionInfo("serviceURI"); + clearSessionInfo("loginHttpStatus"); + clearSessionInfo("clientContextId"); + clearSessionInfo("deviceIsOnline"); + clearSessionInfo("restApplicationIsOnline"); + clearSessionInfo("authenticationModel"); + clearSessionInfo("pingInterval"); + clearSessionInfo("oepingAvailable"); + clearSessionInfo("partialPingURI"); + clearSessionInfo("_authProvider.init"); + clearSessionInfo(_storageKey); + } + } + } + + function setSessionInfoFromStorage(key) { + var authproviderInitObject; + if (retrieveSessionInfo(key)) { + setLoginResult(retrieveSessionInfo("loginResult"), this); + setUserName(retrieveSessionInfo("userName"), this); + setServiceURI(retrieveSessionInfo("serviceURI"), this); + setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"), this); + setClientContextID(retrieveSessionInfo("clientContextId"), this); + setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline")); + setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline")); + that.authenticationModel = retrieveSessionInfo("authenticationModel"); + that.pingInterval = retrieveSessionInfo("pingInterval"); + setOepingAvailable(retrieveSessionInfo("oepingAvailable")); + setPartialPingURI(retrieveSessionInfo("partialPingURI")); + // if information on an AuthenticationProvider for the session is in storage, and if + // the authProvider hasn't already been set for this Session, create a new authProvider + // using the same info as the old one. This would be likely to happen if the app's code + // had used the old JSDOSession.login API, where we create the AuthenticationProvider + // automatically during login instead of the code passing one to the constructor + if (!that._authProvider) { + authproviderInitObject = retrieveSessionInfo("_authProvider.init"); + if (authproviderInitObject) { + setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject)); + } + } + } + } + + function setUserName(newname, sessionObject) { + if (defPropSupported) { + _userName = newname; + } else { + sessionObject.userName = newname; + } + + storeSessionInfo("userName", newname); + } + + function setLoginTarget(target, sessionObject) { + if (defPropSupported) { + _loginTarget = target; + } else { + sessionObject.loginTarget = target; + } + } + + function setServiceURI(url, sessionObject) { + if (defPropSupported) { + _serviceURI = url; + } else { + sessionObject.serviceURI = url; + } + + storeSessionInfo("serviceURI", url); + } + + function pushCatalogURIs(url, sessionObject) { + if (defPropSupported) { + _catalogURIs.push(url); + } else { + sessionObject.catalogURIs.push(url); + } + } + + function pushService(serviceObject, sessionObject) { + if (defPropSupported) { + _services.push(serviceObject); + } else { + sessionObject.services.push(serviceObject); + } + } + + function findService(serviceName) { + _services.forEach(function (service) { + if (service.name === serviceName) { + return service; + } + }); + return null; + } + + function setLoginResult(result, sessionObject) { + if (defPropSupported) { + _loginResult = result; + } else { + sessionObject.loginResult = result; + } + + if (result === progress.data.Session.LOGIN_SUCCESS) { + storeSessionInfo("loginResult", result); + } else { + // Let's clear sessionStorage since we logged out or something went bad! + clearAllSessionInfo(); + } + } + + function setLoginHttpStatus(status, sessionObject) { + if (defPropSupported) { + _loginHttpStatus = status; + } else { + sessionObject.loginHttpStatus = status; + } + + storeSessionInfo("loginHttpStatus", status); + } + + function setClientContextIDfromXHR(xhr, sessionObject) { + if (xhr) { + setClientContextID(getResponseHeaderNoError(xhr, "X-CLIENT-CONTEXT-ID"), sessionObject); + } + } + + function setClientContextID(ccid, sessionObject) { + if (defPropSupported) { + _clientContextId = ccid; + } else { + sessionObject.clientContextId = ccid; + } + + storeSessionInfo("clientContextId", ccid); + } + + function setLastSessionXHR(xhr, sessionObject) { + if (defPropSupported) { + _lastSessionXHR = xhr; + } else { + sessionObject.lastSessionXHR = xhr; + } + } + + function setDeviceIsOnline(value) { + deviceIsOnline = value; + + storeSessionInfo("deviceIsOnline", value); + } + + function setAuthProvider(value) { + // Do this to preserve authprovider's null-ness. + _authProvider = value ? value : null; + } + + function setRestApplicationIsOnline(value) { + restApplicationIsOnline = value; + + storeSessionInfo("restApplicationIsOnline", value); + } + + function setOepingAvailable(value) { + oepingAvailable = value; + + storeSessionInfo("oepingAvailable", value); + } + + function setPartialPingURI(value) { + partialPingURI = value; + + storeSessionInfo("partialPingURI", value); + } + + /* + When using CORS, if the client asks for a response header that is not among + the headers exposed by the Web application, the user agent may write an error + to the console, e.g., "REFUSED TO GET UNSAFE HEADER". This function checks for + a given response header in a way that will avoid the error message. It does this + by requesting all headers and then checking to see whether the desired header + is present (it will not be present, even if the server sent it, if the server has not + also allowed that header). The function caches the string returned by getAllResponseHeaders + by storing it on the xhr that was used in the request. It does the caching in + case there is another header to be checked. + */ + function getResponseHeaderNoError(xhr, headerName) { + var allHeaders = xhr._pdsResponseHeaders, + regExp; + + if (allHeaders === undefined) { + allHeaders = xhr.getAllResponseHeaders(); + if (allHeaders) { + xhr._pdsResponseHeaders = allHeaders; + } else { + xhr._pdsResponseHeaders = null; + } + } + if (allHeaders) { + regExp = new RegExp("^" + headerName + ":", "mi"); + if (allHeaders.match(regExp)) { + return xhr.getResponseHeader(headerName); + } + } + + return null; + } + + // "Methods" + + this._pushJSDOs = function (jsdo) { + _jsdos.push(jsdo); + }; + + + /* _openRequest (intended for progress.data library use only) + * calls open() for an xhr -- the assumption is that this is an xhr for a JSDO, and we need to add + * some session management information for the request, such as user credentials and a session ID if + * there is one + * + * The callback parameter is to support async calls --- it's possible that the call in here to + * _openRequestAndAuthorize will make an async request (for token refresh), so it's expected that + * callers will invoke _openRequest with a callback parameter for async execution + */ + this._openRequest = function (xhr, verb, url, async, callback) { + var urlPlusCCID, + that = this; + + function afterOpenAndAuthorize(arg) { + // _openRequestAndAuthorize can return either an Error or an xhr + // TODO: we might need to fix this + if (arg instanceof Error) { + throw arg; + } else { + // add CCID header + if (that.clientContextId && (that.clientContextId !== "0")) { + xhr.setRequestHeader("X-CLIENT-CONTEXT-ID", that.clientContextId); + } + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(that, xhr); + + if (typeof that.onOpenRequest === 'function') { + var params = { + "xhr": xhr, + "verb": verb, + "uri": urlPlusCCID, + "async": async, + "formPreTest": false, + "session": that + }; + that.onOpenRequest(params); + // xhr = params.xhr; //Note that, currently, this would have no effect in the caller. + } + if (callback) { + callback(); + } + } + } + + if (this._isInvalidated) { + // Session: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "Session")); + } + + if (this.loginResult !== progress.data.Session.LOGIN_SUCCESS + && !this._authProvider && this.authenticationModel) { + throw new Error("Attempted to make server request when there is no active session."); + } + + // if resource url is not absolute, add the REST app url to the front + urlPlusCCID = this._prependAppURL(url); + + // add CCID as JSESSIONID query string to url + urlPlusCCID = this._addCCIDtoURL(urlPlusCCID); + + // add time stamp to the url + if (progress.data.Session._useTimeStamp) { + urlPlusCCID = progress.data.Session._addTimeStampToURL(urlPlusCCID); + } + + // should be able to remove this check and only do what's in the "if" when we no longer + // support calling the Session API directly (need to keep that now because tdriver, for + // one, uses the Session object, and uses it synchronously + if (this._authProvider) { + this._authProvider._openRequestAndAuthorize( + xhr, + verb, + urlPlusCCID, + async, + afterOpenAndAuthorize + ); + } else { + this._setXHRCredentials(xhr, verb, urlPlusCCID, this.userName, _password, async); + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + _addWithCredentialsAndAccept(xhr, "application/json"); + } + afterOpenAndAuthorize(xhr); + } + + }; + + // callback used in login to determine whether ping is available on server + this.pingTestCallback = function (cbArgs) { + var foundOeping = cbArgs.pingResult ? true : false; + + setOepingAvailable(foundOeping); + }; + + // generic async callback, currently used by login(), addCatalog(), logout(), connect, and disconnect + this._onReadyStateChangeGeneric = function () { + var xhr = this; + var result; + var errorObject; + + clearTimeout(xhr._requestTimeout); // for the iOS Basic Auth bug + + if (xhr.readyState === 4) { + result = null; + errorObject = null; + + // initial processing of the response from the Web application + if ((typeof xhr.onResponseFn) === 'function') { + try { + result = xhr.onResponseFn(xhr); + // ( note that result will remain null if this is a logout() ) + } catch (e) { + errorObject = e; + } + } + // handle the results of the processing (e.g., fire any events required) + if ((typeof xhr.onResponseProcessedFn) === 'function') { + if (!result) { + result = progress.data.Session.GENERAL_FAILURE; + } + xhr.onResponseProcessedFn(xhr.pdsession, result, errorObject, xhr); + } + } + }; + + // Intended only for internal use by the JSDO library + // NOTE: disconnect does not currently send a request to the Web application for the Anonymous or + // OE SSO models. It's conceivable, though unlikely, that it might. For that reason, the design is + // similar to the functions that DO make a server request. There is a "setup" function (this one) + // and a separate function to process the "result" (_processDisconnectResult, below). Currently the + // setup function is minimal and just calls _processDisconnectResult directly. If we ever do need to + // send a server request, _processDisconnectResult will be specified as the callback to be invoked + // from onReadyStateChangeGeneric. The possibility of this potential enhancement is the reason for + // the odd signature of _processDisconnectResult, which has a currently unused first parameter for + // the potential XHR. + this._disconnect = function (deferred) { + + // Note: we use the "no harm, no foul" approach for disconnect. If you aren't connected, it's + // regarded as a success rather than cause for throwing an error. + this._processDisconnectResult(null, deferred); + }; + + + // This is separate from _disconnect for cases in which _disconnect makes a server request. + // If there has been a server request, xhr should be valid and deferred will be undefined + // If there was no server request, xhr will be undefined and deferred will be valid. + // If this needs to be enhanced to support server requests, see _procesLoginResponse as + // a general model + // Probably the only time this function will be called as the result of a server request is with + // Form authentication, and even then it's questionable + this._processDisconnectResult = function (xhr, deferred) { + + this._reinitializeAfterLogout(this, progress.data.Session.SUCCESS); + this._disconnectComplete(this, progress.data.Session.SUCCESS, null, null, deferred); + }; + + this._disconnectComplete = function (pdsession, result, errObj, xhr, deferred) { + pdsession.trigger("afterDisconnect", pdsession, result, errObj, xhr, deferred); + }; + + + // GET RID OF progress.data.Session login CODE (AND RELATED) IF WE DROP SUPPORT FOR USING + // THE OLD progress.data.Session API DIRECTLY (mainly a problem for existing code (tdriver), + // or anyone who wants to call methods synchronously, which should be no one) + /* login + * + */ + + // store password here until successful login; only then do we store it in the Session object + var pwSave = null; + // store user name here until successful login; only then do we store it in the Session object + var unameSave = null; + this.login = function (serviceURI, loginUserName, loginPassword, loginTarget) { + var uname, + pw, + isAsync = false, + args = [], + deferred, + iOSBasicAuthTimeout, + uriForRequest; // "decorated" version of serviceURI, used to actually send the request + + pwSave = null; // in case these are left over from a previous login + unameSave = null; + + if (!defPropSupported) { + // this is here on the presumably slim chance that we're running with a + // version of JavaScript that doesn't support defineProperty (otherwise + // the lower casing will have already happened). When we decide that it's + // OK to remove our conditionalization of property definitions, we should + // get rid of this whole conditional + this.authenticationModel = this.authenticationModel.toLowerCase(); + } + + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // Session: Cannot call login() when authenticationModel is SSO. + // Please use the AuthenticationProvider object instead. + throw new Error(progress.data._getMsgText("jsdoMSG057", 'Session', 'login()')); + } + + if (this.loginResult === progress.data.Session.LOGIN_SUCCESS || this._authProvider) { + throw new Error("Attempted to call login() on a Session object that is already logged in."); + } + + if (arguments.length > 0) { + if (arguments[0] && typeof arguments[0] === 'object') { + // Note that arguments[0].serviceURI may be undefined because when the JSDOSession + // uses a Session internally, it passes serviceURI to the constructor. The other + // properties may be present, though + args[0] = arguments[0].serviceURI; + args[1] = arguments[0].userName; + args[2] = arguments[0].password; + args[3] = arguments[0].loginTarget; + args[4] = arguments[0].async; + + /* Special for JSDOSession: if this method was called by a JSDOSession object, + it passes deferred and jsdosession and we need to eventually attach them + to the XHR we use so that the promise created by the JSDOSession will work + correctly + */ + deferred = arguments[0].deferred; + + iOSBasicAuthTimeout = arguments[0].iOSBasicAuthTimeout; + if (typeof iOSBasicAuthTimeout === 'undefined') { + iOSBasicAuthTimeout = defaultiOSBasicAuthTimeout; + } else if (iOSBasicAuthTimeout && (typeof iOSBasicAuthTimeout !== 'number')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'login', + 'The iOSBasicAuthTimeout argument was invalid.' + )); + } + } else { + args = arguments; + } + } + + if (args.length > 0) { + if (args[0]) { + var restURLtemp = args[0]; + + // get rid of trailing '/' because appending service url that starts with '/' + // will cause request failures + if (restURLtemp[restURLtemp.length - 1] === "/") { + restURLtemp = restURLtemp.substring(0, restURLtemp.length - 1); + } + setServiceURI(restURLtemp, this); + } else if (!this.serviceURI) { + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); + throw new Error("Session.login() is missing the serviceURI argument."); + } + + if (args[1]) { + uname = args[1]; + } + + if (args[2]) { + pw = args[2]; + } + + if (args[3]) { + setLoginTarget(args[3], this); + } + + if (args[4]) { + if (typeof (args[4]) === 'boolean') { + isAsync = args[4]; + } else { + throw new Error("Session.login() was passed an async setting that is not a boolean."); + } + } + } else { + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); + throw new Error("Session.login() is missing the serviceURI argument."); + } + + // use these temp cred variables later; if login succeeds, we'll use them to set the + // real credentials + unameSave = uname; + pwSave = pw; + + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_ANON || + this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + /* anonymous should NOT have a username and password passed (this is + probably unnecessary because the XHR seems to send the request without + credentials first, then intercept the 401 if there is one and try again, + this time with credentials. Just making sure. + */ + /* For form authentication, we may as well not send the user name and password + * on this request, since we are just trying to test whether the authentication + * has already happened and they are therefore irrelevant + */ + uname = null; + pw = null; + } + + var xhr = new XMLHttpRequest(); + xhr.pdsession = this; + + try { + uriForRequest = this.serviceURI + this.loginTarget; + if (progress.data.Session._useTimeStamp) { + uriForRequest = progress.data.Session._addTimeStampToURL(uriForRequest); + } + this._setXHRCredentials(xhr, 'GET', uriForRequest, uname, pw, isAsync); + + progress.data.Session._setNoCacheHeaders(xhr); + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(this, xhr); + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + _addWithCredentialsAndAccept( + xhr, + "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + ); + } + + xhr._isAsync = isAsync; + if (isAsync) { + xhr.onreadystatechange = this._onReadyStateChangeGeneric; + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + xhr.onResponseFn = this._afterFormPretestLogin; + } else { + xhr.onResponseFn = this._processLoginResult; + xhr.onResponseProcessedFn = this._loginComplete; + } + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC + && isUserAgentiOS + && iOSBasicAuthTimeout > 0) { + xhr._requestTimeout = setTimeout( + function () { + clearTimeout(xhr._requestTimeout); + xhr._iosTimeOutExpired = true; + xhr.abort(); + }, + iOSBasicAuthTimeout + ); + } + xhr._jsdosession = jsdosession; // in case the caller is a JSDOSession + xhr._deferred = deferred; // in case the caller is a JSDOSession + } + + if (typeof this.onOpenRequest === 'function') { + var isFormPreTest = false; + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + isFormPreTest = true; + } + + // set this here in case onOpenRequest checks it + setLastSessionXHR(xhr, this); + var params = { + "xhr": xhr, + "verb": "GET", + "uri": this.serviceURI + this.loginTarget, + "async": false, + "formPreTest": isFormPreTest, + "session": this + }; + this.onOpenRequest(params); + xhr = params.xhr; // just in case it has been changed + } + setLastSessionXHR(xhr, this); + xhr.send(null); + } catch (e) { + clearTimeout(xhr._requestTimeout); + setLoginHttpStatus(xhr.status, this); + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); + unameSave = null; + pwSave = null; + throw e; + } + + if (isAsync) { + return progress.data.Session.ASYNC_PENDING; + } else { + setLoginHttpStatus(xhr.status, this); + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + return (this._afterFormPretestLogin(xhr)); + } else { + return (this._processLoginResult(xhr)); + } + } + }; + + + this._afterFormPretestLogin = function (xhr) { + var pdsession = xhr.pdsession; + setLoginHttpStatus(xhr.status, xhr.pdsession); + + var formLoginParams = { + "xhr": xhr, + "pw": pwSave, + "uname": unameSave, + "theSession": pdsession + }; + try { + return doFormLogin(formLoginParams); + } catch (e) { + pwSave = null; + unameSave = null; + throw e; + } + }; + + /* doFormLogin + * This function handles logging in to a service that uses form-based authentication. It's separate + * from the main login function because it's long. One of the things it does is examine the + * response from an initial attempt to get the login target without credentials (done in the main + * login() function) to determine whether the user has already been authenticated. Although a + * current OE Mobile Web application (as of 5/30/2013) will return an error if authentication + * failed on a form login, previous versions and non-OE servers return a + * redirect to a login page and the user agent (browser or native wrapper) + * usually then fetches the redirect location and returns it along with a + * 200 Success status, when in fcat it was an authentication failure. Hence + * the need to analyze the response to try to figure out what we get back. + * + */ + function doFormLogin(args) { + var xhr = args.xhr; + var theSession = args.theSession; + var oldXHR; + + // check whether we got the OE REST Form based error response + var contentType = null; + var needAuth = false; + var params = { + "session": theSession, + "xhr": xhr, + "statusFromjson": null + }; + + contentType = xhr.getResponseHeader("Content-Type"); + + if (contentType && contentType.indexOf("application/json") >= 0) { + handleJSONLoginResponse(params); + if (!params.statusFromjson || (params.statusFromjson >= 400 && params.statusFromjson < 500)) { + needAuth = true; + } else { + // either the response shows that we're already authenticated, or + // there's some error other than an authentication error + setLoginHttpStatus(params.statusFromjson, theSession); + } + } else { + // need to do only 200 for async to work with MWA down + if (theSession.loginHttpStatus === 200) { + if (_gotLoginForm(xhr)) { + needAuth = true; + } + // else we are assuming we truly retrieved the login target and + // therefore we were previously authenticated + } + // else had an error, just return it + } + + if (needAuth) { + // create new XHR, because if this is an async call we don't want to + // confuse things by using this xhr to send another request while we're + // still processing its old request (this function, doFormLogin(), may + // have been called from onReadyStateChangeGeneric and it's conceivable + // that that function has more code to execute involving this xhr) + oldXHR = xhr; + xhr = new XMLHttpRequest(); + args.xhr = xhr; + params.xhr = xhr; + + // need to transfer any properties that the Session code stored in the + // the xhr that need to persist across the 2 requests made by a our + // login implementation for Form auth + xhr.pdsession = oldXHR.pdsession; + xhr._isAsync = oldXHR._isAsync; + xhr._deferred = oldXHR._deferred; // special for JSDOSession + xhr._jsdosession = oldXHR._jsdosession; // special for JSDOSession + + xhr.open('POST', theSession.serviceURI + "/static/auth/j_spring_security_check", xhr._isAsync); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.setRequestHeader("Cache-Control", "max-age=0"); + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(theSession, xhr); + + _addWithCredentialsAndAccept(xhr, "application/json"); + + try { + + // Note: this gives a developer a way to change certain aspects of how we do the + // form-based login, but we will still be assuming that we are going directly to + // j_spring_security_check and including credentials in the body. They really should not + // try to change that. + // + if (typeof theSession.onOpenRequest === 'function') { + var cbparams = { + "xhr": xhr, + "verb": "POST", + "uri": theSession.serviceURI + "/static/auth/j_spring_security_check", + "async": xhr._isAsync, + "formPreTest": false, + "session": theSession + }; + theSession.onOpenRequest(cbparams); + xhr = cbparams.xhr; + } + + if (xhr._isAsync) { + xhr.onreadystatechange = theSession._onReadyStateChangeGeneric; + xhr.onResponseFn = theSession._afterFormLogin; + xhr.onResponseProcessedFn = theSession._loginComplete; + } + + // j_username=username&j_password=password&submit=Submit + xhr.send("j_username=" + encodeURIComponent(args.uname) + + "&j_password=" + encodeURIComponent(args.pw) + "&submit=Submit"); + } catch (e) { + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, theSession); + setLoginHttpStatus(xhr.status, theSession); + // null the temporary credentials variables + unameSave = null; + pwSave = null; + throw e; + } + } + + if (xhr._isAsync && !needAuth) { + xhr.onResponseProcessedFn = theSession._loginComplete; + return theSession._afterFormLogin(xhr); + } + if (!xhr._isAsync) { + return theSession._afterFormLogin(xhr); + } + + } + + this._afterFormLogin = function (xhr) { + // check what we got + var theSession = xhr.pdsession; + var params = { + "session": theSession, + "xhr": xhr, + "statusFromjson": null + }; + var contentType = xhr.getResponseHeader("Content-Type"); + + if (contentType && contentType.indexOf("application/json") >= 0) { + handleJSONLoginResponse(params); + if (!params.statusFromjson) { + throw new Error( + "Internal OpenEdge Mobile client error handling login response. HTTP status: " + + xhr.status + "." + ); + } + + setLoginHttpStatus(params.statusFromjson, theSession); + } else { + if (xhr.status === 200) { + // Was the response actually the login failure page or the login page itself (in case + // the appSecurity config file sets the login failure url so the server sends the login + // page again)? If so, call it an error because the credentials apparently failed to be + // authenticated + if (_gotLoginFailure(xhr) || _gotLoginForm(xhr)) { + setLoginHttpStatus(401, theSession); + } else { + setLoginHttpStatus(xhr.status, theSession); + } + } + } + + return theSession._processLoginResult(xhr); + }; + + + this._processLoginResult = function (xhr) { + /* OK, one way or another, by hook or by crook, the Session object's loginHttpStatus + * has been set to the value that indicates the real outcome of the + * login, after adjusting for form-based authentication and anything + * else. At this point, it should be just a matter of examining + * this.loginHttpStatus, using it to set this.loginResult, maybe doing + * some other work appropriate to the outcome of the login, and returning + * this.loginResult. + */ + var pdsession = xhr.pdsession; + + setLoginHttpStatus(xhr.status, xhr.pdsession); + + if (pdsession.loginHttpStatus === 200) { + setLoginResult(progress.data.Session.LOGIN_SUCCESS, pdsession); + setRestApplicationIsOnline(true); + setUserName(unameSave, pdsession); + _password = pwSave; + pdsession._saveClientContextId(xhr); + storeAllSessionInfo(); // save info to persistent storage + + var pingTestArgs = { + pingURI: null, + async: true, + onCompleteFn: null, + fireEventIfOfflineChange: true, + onReadyStateFn: pdsession._pingtestOnReadyStateChange + }; + pingTestArgs.pingURI = pdsession._makePingURI(); + pdsession._sendPing(pingTestArgs); // see whether the ping feature is available + } else { + if (pdsession.loginHttpStatus === 401) { + setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE, pdsession); + } else { + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, pdsession); + } + } + setLastSessionXHR(xhr, pdsession); + updateContextPropsFromResponse(pdsession, xhr); + + // null the temporary credentials variables + unameSave = null; + pwSave = null; + if (xhr._iosTimeOutExpired) { + throw new Error(progress.data._getMsgText("jsdoMSG047", "login")); + } + + // return loginResult even if it's an async operation -- the async handler + // (e.g., onReadyStateChangeGeneric) will just ignore + return pdsession.loginResult; + }; + + + this._loginComplete = function (pdsession, result, errObj, xhr) { + pdsession.trigger("afterLogin", pdsession, result, errObj, xhr); + }; + + // GET RID OF progress.data.Session logout CODE (AND RELATED) IF WE DROP SUPPORT FOR USING + // THE OLD progress.data.Session API DIRECTLY (mainly a problem for existing code (tdriver), + // or anyone who wants to call methods synchronously, which should be no one) + this.logout = function (args) { + var isAsync = false, + errorObject = null, + xhr, + deferred, + params; + + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // Session: Cannot call logout() when authenticationModel is SSO. + // Please use the AuthenticationProvider object instead. + throw new Error(progress.data._getMsgText("jsdoMSG057", 'Session', 'logout()')); + } + + if (this.loginResult !== progress.data.Session.LOGIN_SUCCESS && this.authenticationModel) { + throw new Error("Attempted to call logout when there is no active session."); + } + + if (typeof args === 'object') { + isAsync = args.async; + if (isAsync && (typeof isAsync !== 'boolean')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "Session", + 'logout', + 'The async argument was invalid.' + )); + } + /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes + deferred and jsdosession and we need to eventually attach them to the XHR we use + so that the promise created by the JSDOSession will work correctly + */ + deferred = args.deferred; + } + + xhr = new XMLHttpRequest(); + xhr.pdsession = this; + try { + /* logout when auth model is anonymous is a no-op on the server side + (but we need to set _jsdosession and _deferred anyway to make promise work + if logout was called by a JSDOSession) */ + xhr._jsdosession = jsdosession; // in case the caller is a JSDOSession + xhr._deferred = deferred; // in case the caller is a JSDOSession + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM || + this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { + if (isAsync) { + xhr.onreadystatechange = this._onReadyStateChangeGeneric; + xhr.onResponseFn = this._processLogoutResult; + xhr.onResponseProcessedFn = this._logoutComplete; + } + + + xhr.open('GET', this.serviceURI + "/static/auth/j_spring_security_logout", isAsync); + + /* instead of calling _addWithCredentialsAndAccept, we code the withCredentials + * and setRequestHeader inline so we can do it slightly differently. That + * function deliberately sets the request header inside the try so we don't + * run into a FireFox oddity that would give us a successful login and then + * a failure on getCatalog (see the comment on that function). On logout, + * however, we don't care -- just send the Accept header so we can get a 200 + * response + */ + try { + xhr.withCredentials = true; + } catch (e) { + // Empty + } + + xhr.setRequestHeader("Accept", "application/json"); + + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(this, xhr); + + if (typeof this.onOpenRequest === 'function') { + setLastSessionXHR(xhr, this); + params = { + "xhr": xhr, + "verb": "GET", + "uri": this.serviceURI + "/static/auth/j_spring_security_logout", + "async": false, + "formPreTest": false, + "session": this + }; + this.onOpenRequest(params); + xhr = params.xhr; + } + + setLastSessionXHR(xhr, this); + xhr.send(); + } else { + xhr._anonymousLogoutOK = true; + } + } catch (e) { + this._reinitializeAfterLogout(this, false); + throw e; + } + + if (!isAsync) { + try { + this._processLogoutResult(xhr); + } catch (e) { + throw e; + } + } + + if (isAsync && this.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { + // fake async for Anonymous -- fire afterLogout event + try { + this._processLogoutResult(xhr); + } catch (e) { + errorObject = e; + } + this._logoutComplete(this, null, errorObject, xhr); + } + + }; + + // This function erases all evidence of itself from the ServicesManager and + // flips a bit to prevent it to be used in the future + this.invalidate = function () { + isInvalidated = true; + cleanServicesManager(); + }; + + this._logoutComplete = function (pdsession, result, errorObject, xhr) { + // ignore result, it doesn't apply to logout -- is probably null or GENERAL_FAILURE + // we include it so onReadyStateChangeGeneric calls this correctly + pdsession.trigger("afterLogout", pdsession, errorObject, xhr); + }; + + this._processLogoutResult = function (xhr) { + var logoutSucceeded; + var pdsession = xhr.pdsession; + var basicStatusOK = false; + + if (xhr._anonymousLogoutOK) { + logoutSucceeded = true; + } else if (xhr.status !== 200) { + /* Determine whether an error returned from the server is really an error + */ + if (pdsession.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { + /* If the Auth model is Basic, we probably got back a 404 Not found. + * But that's OK, because logout from Basic is meaningless on the + * server side unless it happens to be stateful, which is the only + * reason we even try calling j_spring_security_logout + */ + if (xhr.status === 404) { + logoutSucceeded = true; + } else { + logoutSucceeded = false; + throw new Error("Error logging out, HTTP status = " + xhr.status); + } + } else { + // for Form auth, any error on logout is an error + logoutSucceeded = false; + + // page refresh - we should call _reinitializeAfterLogout, or do something, so that + // caller can try logging in again (this is not a problem specific to page refresh, + // but the case of a page refresh after a server has gone down emphasizes it) + + throw new Error("Error logging out, HTTP status = " + xhr.status); + } + } else { + logoutSucceeded = true; + } + + updateContextPropsFromResponse(pdsession, xhr); + pdsession._reinitializeAfterLogout(pdsession, logoutSucceeded); + }; + + this._reinitializeAfterLogout = function (pdsession, success) { + setLoginResult(null, pdsession); + setLoginHttpStatus(null, pdsession); + setClientContextID(null, pdsession); + setUserName(null, pdsession); + setAuthProvider(null); + + _password = null; + + if (success) { + setRestApplicationIsOnline(false); + setOepingAvailable(false); + setPartialPingURI(defaultPartialPingURI); + setLastSessionXHR(null, pdsession); + clearTimeout(_timeoutID); // stop autopinging + } + }; + + /* addCatalog + * + */ + this.addCatalog = function (arg1, arg2, arg3, arg4) { + var catalogURI, + catalogUserName, + catalogPassword, + isAsync = false, + xhr, + deferred, + iOSBasicAuthTimeout, + catalogIndex, + authProvider, + that = this; + + function addCatalogAfterOpen() { + /* This is here as much for CORS situations as the possibility that there might be an + * out of date cached version of the catalog. The CORS problem happens if you have + * accessed the catalog locally and then run an app on a different server that requests + * the catalog. Your browser already has the catalog, but the request used to get it was + * a non-CORS request and the browser will raise an error + */ + progress.data.Session._setNoCacheHeaders(xhr); + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(that, xhr); + + if (isAsync) { + xhr.onreadystatechange = that._onReadyStateChangeGeneric; + xhr.onResponseFn = that._processAddCatalogResult; + xhr.onResponseProcessedFn = that._addCatalogComplete; + + if (that.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC + && isUserAgentiOS + && iOSBasicAuthTimeout) { + xhr._requestTimeout = setTimeout(function () { + clearTimeout(xhr._requestTimeout); + xhr._iosTimeOutExpired = true; + xhr.abort(); + }, + iOSBasicAuthTimeout); + } + + // in case the caller is a JSDOSession + xhr._jsdosession = jsdosession; + xhr._deferred = deferred; + xhr._catalogIndex = catalogIndex; + } + + try { + if (typeof that.onOpenRequest === 'function') { + setLastSessionXHR(xhr, that); + var params = { + "xhr": xhr, + "verb": "GET", + "uri": catalogURI, + "async": false, + "formPreTest": false, + "session": that + }; + that.onOpenRequest(params); + xhr = params.xhr; + } + + setLastSessionXHR(xhr, that); + xhr.send(null); + } catch (e) { + throw new Error("Error retrieving catalog '" + catalogURI + "'.\n" + e.message); + } + if (isAsync) { + return progress.data.Session.ASYNC_PENDING; + } else { + return that._processAddCatalogResult(xhr); + } + + } + + if (this._isInvalidated) { + // JSDOSession: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); + } + + // Assume we're using a custom username/pw/authprovider + customCredentials = true; + + // check whether the args were passed in a single object. If so, copy them + // to the named arguments and a variable + if (arguments.length > 0) { + if (typeof arg1 === 'object') { + // check whether it's OK to add a catalog whilst offline + if (!arguments[0].offlineAddCatalog) { + if ((this.loginResult !== progress.data.Session.LOGIN_SUCCESS + && !this._authProvider) + && this.authenticationModel) { + throw new Error("Attempted to call addCatalog when there is no active session."); + } + } + + catalogURI = arg1.catalogURI; + if (!catalogURI || (typeof catalogURI !== 'string')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'addCatalog', + 'The catalogURI argument was missing or invalid.' + )); + } + catalogUserName = arg1.userName; + if (catalogUserName && (typeof catalogUserName !== 'string')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'addCatalog', + 'The catalogUserName argument was invalid.' + )); + } + catalogPassword = arg1.password; + if (catalogPassword && (typeof catalogPassword !== 'string')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'addCatalog', + 'The catalogPassword argument was invalid.' + )); + } + isAsync = arg1.async; + if (isAsync && (typeof isAsync !== 'boolean')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'addCatalog', + 'The async argument was invalid.' + )); + } + iOSBasicAuthTimeout = arg1.iOSBasicAuthTimeout; + if (typeof iOSBasicAuthTimeout === 'undefined') { + iOSBasicAuthTimeout = defaultiOSBasicAuthTimeout; + } else if (iOSBasicAuthTimeout && (typeof iOSBasicAuthTimeout !== 'number')) { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + 'Session', + 'addCatalog', + 'The iOSBasicAuthTimeout argument was invalid.' + )); + } + authProvider = arg1.authProvider; + + /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes + deferred, jsdosession, and catalogIndex and we need to eventually attach them to the + XHR we use so that the promise created by the JSDOSession will work correctly + */ + deferred = arg1.deferred; + catalogIndex = arg1.catalogIndex; + } else { + catalogURI = arg1; + if (typeof catalogURI !== 'string') { + throw new Error("First argument to Session.addCatalog must be the URL of the catalog."); + } + catalogUserName = arg2; + if (catalogUserName && (typeof catalogUserName !== 'string')) { + throw new Error("Second argument to Session.addCatalog must be a user name string."); + } + catalogPassword = arg3; + if (catalogPassword && (typeof catalogPassword !== 'string')) { + throw new Error("Third argument to Session.addCatalog must be a password string."); + } + } + } else { + throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog."); + } + + if (!authProvider) { + authProvider = this._authProvider; + + // Guess we're using the default credentials passed earlier + customCredentials = false; + } + + // Note: we expect that there will always be an authProvider if a login has been done. + // Therefore, we don't need to set catalogUsername and catalogPassword if they aren't + // passed in. What we should do here, when we extend the AuthenticationProvider API + // for the older auth models, is take any uname and pw passed in and create an auth + // provider, log in to the catalogURI with it, create an authImpl, and then fetch the + // catalog. + if (!catalogUserName) { + catalogUserName = this.userName; + } + + if (!catalogPassword) { + catalogPassword = _password; + } + + xhr = new XMLHttpRequest(); + xhr.pdsession = this; + xhr._catalogURI = catalogURI; + + // for now we don't support multiple version of the catalog across sessions + if (progress.data.ServicesManager.getSession(catalogURI) !== undefined) { + if (isAsync) { + /* + Attempt to get the event to fire AFTER this call returns ASYNC_PENDING + (and if the method was called from a JSDOSession, create an xhr to communicate + information related to promises back to its afterAddCatalog handler). Note that + the xhr is never used to make a request, it just carries data in the way + expected by the handler) + */ + // in case the caller is a JSDOSession + xhr._jsdosession = jsdosession; + xhr._deferred = deferred; + xhr._catalogIndex = catalogIndex; + + setTimeout( + this._addCatalogComplete, + 10, + this, + progress.data.Session.CATALOG_ALREADY_LOADED, + null, + xhr + ); + + return progress.data.Session.ASYNC_PENDING; + } + return progress.data.Session.CATALOG_ALREADY_LOADED; + } + + if (authProvider) { + authProvider._openRequestAndAuthorize(xhr, 'GET', catalogURI, isAsync, addCatalogAfterOpen); + // existing code in JSDOSession addCatalog expects to get this as a return value, + // have to return it now + return progress.data.Session.ASYNC_PENDING; + } else { // should be able to get rid of this if we do away with synchronous (old Session API) support + this._setXHRCredentials(xhr, 'GET', catalogURI, catalogUserName, catalogPassword, isAsync); + // Note that we are not adding the CCID to the URL or as a header, because the catalog may not + // be stored with the REST app and even if it is, the AppServer ID shouldn't be relevant + + return addCatalogAfterOpen(); + } + + }; + + this._processAddCatalogResult = function (xhr) { + var _catalogHttpStatus = xhr.status; + var theSession = xhr.pdsession; + var servicedata; + var catalogURI = xhr._catalogURI, + serviceURL, + theJSDOSession = jsdosession; + + // Only change the Session's state if the default AuthProv is being used + if (!customCredentials) { + toggleOnlineState(xhr); + } + + if (((_catalogHttpStatus === 200) || (_catalogHttpStatus === 0)) && xhr.responseText) { + servicedata = theSession._parseCatalog(xhr); + try { + progress.data.ServicesManager.addCatalog(servicedata, theSession); + } catch (e) { + if (progress.data.ServicesManager.getSession(catalogURI) !== undefined) { + /* this failed because the catalog had already been loaded, but the code + in addCatalog did not catch that, probably because we are executing + the JSDOSession addCatalog with multiple catalogURIs passed, and 2 + are the same + */ + return progress.data.Session.CATALOG_ALREADY_LOADED; + } + // different catalogs, with same resource name + throw new Error("Error processing catalog '" + catalogURI + "'. \n" + e.message); + } + // create a mobile service object and add it to the Session's array of same + servicedata.forEach(function (service) { + serviceURL = theSession._prependAppURL(service.address); + pushService( + new progress.data.MobileServiceObject( + { + name: service.name, + uri: serviceURL + } + ), + theSession + ); + + if (service.settings && service.settings.useXClientProps && !theSession.xClientProps) { + console.warn( + "Catalog warning: Service settings property 'useXClientProps' " + + "is true but 'xClientProps' property has not been set." + ); + } + }); + + pushCatalogURIs(catalogURI, theSession); + progress.data.ServicesManager.addSession(catalogURI, theSession); + if (theJSDOSession) { + progress.data.ServicesManager.addJSDOSession(catalogURI, theJSDOSession); + } + } else if (_catalogHttpStatus === 401) { + return progress.data.AuthenticationProvider._getAuthFailureReason(xhr); + } else if (xhr._iosTimeOutExpired) { + throw new Error(progress.data._getMsgText("jsdoMSG047", "addCatalog")); + } else { + throw new Error( + "Error retrieving catalog '" + catalogURI + + "'. Http status: " + _catalogHttpStatus + "." + ); + } + + return progress.data.Session.SUCCESS; + }; + + this._addCatalogComplete = function (pdsession, result, errObj, xhr) { + pdsession.trigger("afterAddCatalog", pdsession, result, errObj, xhr); + }; + + + /* + * ping -- determine whether the Mobile Web Application that the Session object represents + * is available, which includes determining whether its associated AppServer is running + * Also determine whether the Mobile services managed by this Session object are available + * (which means simply that they're known to the Mobile Web Application) + * (Implementation note: be sure that this Session object's "connected" + * property retains its current value until the end of this function, where + * it gets updated, if necessary, after calling _isOnlineStateChange + * + * Signatures : + * @param arg + * There are 2 signatures -- + * - no argument -- do an async ping of the Session's Mobile Web application. The only effect + * of the ping will be firing an offline or an online event, if appropriate + * The ping function itself will return false to the caller + * - object argument -- the object's properties provide the input args. They are all + * optional (if for some reason the caller passes an object that has no properties, it's + * the same as passing no argument at all). The properties may be: + * async -- tells whether to execute the ping asynchronously (which is the default) + * onCompleteFn -- if async, this will be called when response returns + * doNotFireEvent -- used internally, controls whether the ping method causes an offline + * or online event to be fired if there has been a change (the default is that it + * does, but our Session._checkServiceResponse() sets this to true so that it can + * control the firing of the event) + * offlineReason -- if present, and if the ping code discovers that teh server is offline, + * the ping code will set this with its best guess + * as to the reason the server is offline + */ + this.ping = function (args) { + var pingResult = false, + pingArgs = { + pingURI: null, + async: true, + onCompleteFn: null, + fireEventIfOfflineChange: true, + onReadyStateFn: this._onReadyStateChangePing, + offlineReason: null + }; + + if (this._isInvalidated) { + // Session: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "Session")); + } + + if ((!this._authProvider) && (this.loginResult !== progress.data.Session.LOGIN_SUCCESS)) { + throw new Error("Attempted to call ping when not logged in."); + } + + if (args) { + if (args.async !== undefined) { + // when we do background pinging (because pingInterval is set), + // we pass in an arg that is just an object that has an async property, + // set to true. This can be expanded to enable other kinds of ping calls + // to be done async (so that application developers can do so, if we decide + // to support that) + pingArgs.async = args.async; + } + + if (args.doNotFireEvent !== undefined) { + pingArgs.fireEventIfOfflineChange = !args.doNotFireEvent; + } + + if (args.onCompleteFn && (typeof args.onCompleteFn) === 'function') { + pingArgs.onCompleteFn = args.onCompleteFn; + } + /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes + deferred and jsdosession and we need to eventually attach them to the XHR we use so that + the promise created by the JSDOSession will work correctly + */ + pingArgs.deferred = args.deferred; + pingArgs.jsdosession = args.jsdosession; + + } + + + /* Ping the Mobile Web Application (this will also determine whether AppServer is available) + * Call _processPingResult() if we're synchronous, otherwise the handler for the xhr.send() + * will call it + */ + pingArgs.pingURI = that._makePingURI(); + that._sendPing(pingArgs); + if (!pingArgs.async) { + if (pingArgs.xhr) { + pingResult = that._processPingResult(pingArgs); + if (args.offlineReason !== undefined) { + args.offlineReason = pingArgs.offlineReason; + } + } else { + pingResult = false; // no xhr returned from _sendPing, something must have gone wrong + } + + if (args.xhr !== undefined) { + // if it's a sync ping, return the xhr if caller indicates they want it + // (there's almost guaranteed to be one, even if the ping was never sent + // if for some reason there isn't, we give them the null or undefined we ended up with) + args.xhr = pingArgs.xhr; + } + } + // else it's async, deliberately returning false + // so developer not misled into thinking the ping succeeded + + return pingResult; + }; + + + // "protected" Functions + + /* + * given a value of true or false for being online for the Mobile Web Application + * managed by this Session object, determine whether that changes the current + * state of being offline or online. + * Returns true if the input state is a change from the current state + * + * Signature : + * @param isOnline Required. True to determine whether online is a state change, false to + * determine whether offline constitutes a state change. Boolean. + * + */ + this._isOnlineStateChange = function (isOnline) { + var stateChanged = false; + + if (isOnline && !(this.connected)) { + stateChanged = true; + } else if (!isOnline && (this.connected)) { + stateChanged = true; + } + + return stateChanged; + }; + + + /* + * given information about the response from a request made to a service, + * do the following: + * + * determine whether the online status of the Session has changed, and + * set the Session's Connected property accordingly + * if the Session's online status has changed, fire the appropriate event + * + * Signature : + * @param xhr Required. The xhr that was used to make the request. Object + * @param success Required. True if caller regards the request as having succeeded. Boolean + * @param request Required. The JSDO request object created for making the request. Object. + * + */ + this._checkServiceResponse = function (xhr, success, request) { + var offlineReason = null, + wasOnline = this.connected; + updateContextPropsFromResponse(this, xhr); + + /* first of all, if there are no subscriptions to offline or online events, don't + * bother -- we don't want to run the risk of messing things up by calling ping + * if the app developer isn't interested (especially because that may mean that + * ping isn't enabled on the server, anyway) + */ + if (!this._events) { + return; + } + var offlineObservers = this._events.offline || []; + var onlineObservers = this._events.online || []; + if ((offlineObservers.length === 0) && (onlineObservers.length === 0)) { + return; + } + + /* even though this function gets called as a result of trying to + * contact the server, don't bother to change anything if we already + * know that the device (or user agent, or client machine) is offline. + * We can't assume anything about the state of the server if we can't + * even get to the internet from the client + */ + + // if the call to the server was a success, we will assume we are online, + // both server and device + if (success) { + setRestApplicationIsOnline(true); + setDeviceIsOnline(true); // presumably this is true (probably was already true) + } else { + /* Request failed, determine whether it's because server is offline + * Do this even if the Session was already in an offline state, because + * we need to determine whether the failure was due to still being + * offline, or whether it's now possible to communicate with the + * server but the problem was something else. + */ + + if (deviceIsOnline) { + /* ping the server to get better information on whether this is an offline case + * NB: synchronous ping for simplicity, maybe should consider async so as not + * to potentially freeze UI + */ + var localPingArgs = { + doNotFireEvent: true, // do in this fn so we have the request + offlineReason: null, + async: false + }; + if (!(that.ping(localPingArgs))) { + offlineReason = localPingArgs.offlineReason; + setRestApplicationIsOnline(false); + } else { + // ping returned true, so even though the original request failed, + // we are online and the failure must have been due to something else + setRestApplicationIsOnline(true); + } + } + // else deviceIsOnline was already false, so the offline event should already have + // been fired for that reason and there is no need to do anything else + } + + if (wasOnline && !this.connected) { + this.trigger("offline", this, offlineReason, request); + } else if (!wasOnline && this.connected) { + this.trigger("online", this, request); + } + }; + + /* Decide whether, on the basis of information returned by a server request, the + * Mobile Web Application managed by this Session object is online, where online + * means that the ping response was a 200 and, IF the body of the response contains + * JSON with an AppServerStatus property, that AppServerStatus Status property has + * a pingStatus property set to true + * i.e., the body has an AppServerStatus.PingStatus set to true + * (if the body doesn't contain JSON with an AppServerStatus, we use just the HTTP + * response status code to decide) + * + * Returns: true if the response meets the above conditions, false if it doesn't + * + * Parameters: + * args, with properties: + * xhr - the XMLHttpRequest used to make the request + * offlineReason - if the function determines that the app is offline, + * it sets offlineReason to the reason for that decision, + * for the use of the caller + * fireEventIfOfflineChange - if true, the function fires an offline or online + * event if there has been a change (i.e., the online state determined + * by the function is different from what it had been when the function + * began executing) + * usingOepingFormat - OPTIONAL. The function's default assumption is that the value + * of the session's internal oepingAvailable variable indicates whether the + * the response body will be in the format used by the OpenEdge oeping service. + * A caller can override this assumption by using this property to true or false. + * (the isAuthorized code sets this to false because it doesn't use oeping + * but does call this function) + */ + this._processPingResult = function (args) { + var xhr = args.xhr, + pingResponseJSON, + appServerStatus = null, + wasOnline = this.connected, + connectedBeforeCallback, + assumeOepingFormat; + + if (args.hasOwnProperty('usingOepingFormat')) { + assumeOepingFormat = args.usingOepingFormat; + } else { + assumeOepingFormat = oepingAvailable; + } + + /* first determine whether the Web server and the Mobile Web Application (MWA) + * are available + */ + if (xhr.status >= 200 && xhr.status < 300) { + updateContextPropsFromResponse(this, xhr); + if (assumeOepingFormat) { + try { + pingResponseJSON = JSON.parse(xhr.responseText); + appServerStatus = pingResponseJSON.AppServerStatus; + } catch (e) { + /* We got a successful response from calling our ping URI, but it + * didn't return valid JSON. If we think that the oeping REST API + * is available on the server (so we should have gotten valid + * json), log this to the console. + * + */ + console.error("Unable to parse ping response."); + } + } + toggleOnlineState(xhr); + } else { + if (deviceIsOnline) { + if (xhr.status === 0) { + args.offlineReason = progress.data.Session.SERVER_OFFLINE; + setRestApplicationIsOnline(false); + } else if ((xhr.status === 404) || (xhr.status === 410)) { + /* if we get a 404, it means the Web server is up, but it + * can't find the resource we requested (either _oeping or + * the login target), therefore the Mobile Web application + * must be unavailable (410 is Gone) + */ + args.offlineReason = progress.data.Session.WEB_APPLICATION_OFFLINE; + setRestApplicationIsOnline(false); + } else { + /* There's some error, but we can't say for sure that it's because + * the Web application is unavailable. May be an authentication problem, + * internal server error, or for some reason our ping request was + * invalid (unlikely to happen if it previously succeeded). + * In particular, if the server uses Form authentication, it + * may have come back online but now the session id + * is no longer valid. + */ + setRestApplicationIsOnline(true); + } + } else { + args.offlineReason = progress.data.Session.DEVICE_OFFLINE; + } + } + + // is the AppServer online? appServerStatus will be non-null only + // if the ping request returned 200, meaning the other things are OK + // (connection to server, Tomcat, Mobile Web application) + if (appServerStatus) { + if (appServerStatus.PingStatus === "false") { + args.offlineReason = progress.data.Session.APPSERVER_OFFLINE; + setRestApplicationIsOnline(false); + } else { + setRestApplicationIsOnline(true); + } + } + + /* We call any async ping callback handler and then, after that returns, fire an + offline or online event if necessary. + When deciding whether to fire an event, the responsibility of this _processPingResult() + function is to decide about the event on the basis of the data returned from the ping + that it is currently processing. Therefore, since the ping callback that is just about + to be called could change the outcome of the event decision (for example, if the handler + calls logout(), thus setting Session.connected to false)), we save the current value of + Session.connected and use that saved value to decide about the event after the ping + handler returns. + (If the application programmer wants to get an event fired as a result of something + that happens in the ping handler, they should call a ping() *after* that. + */ + connectedBeforeCallback = this.connected; + + if ((typeof xhr.onCompleteFn) === 'function') { + xhr.onCompleteFn({ + pingResult: this.connected, + xhr: xhr, + offlineReason: args.offlineReason + }); + } + + // decide whether to fire an event, and if so do it + if (args.fireEventIfOfflineChange) { + if (wasOnline && !connectedBeforeCallback) { + that.trigger("offline", that, args.offlineReason, null); + } else if (!wasOnline && connectedBeforeCallback) { + that.trigger("online", that, null); + } + } + + return this.connected; + }; + + + this._onReadyStateChangePing = function () { + var xhr = this; + var args; + + if (xhr.readyState === 4) { + args = { + xhr: xhr, + fireEventIfOfflineChange: true, + offlineReason: null + }; + that._processPingResult(args); + if (_pingInterval > 0) { + _timeoutID = setTimeout(that._autoping, _pingInterval); + } + } + }; + + this._pingtestOnReadyStateChange = function () { + var xhr = this; + + if (xhr.readyState === 4) { + var foundOeping = false; + if (xhr.status >= 200 && xhr.status < 300) { + foundOeping = true; + } else { + setPartialPingURI(that.loginTarget); + console.warn("Default ping target not available, will use loginTarget instead."); + } + setOepingAvailable(foundOeping); + + // If we're here, we've just logged in. If pingInterval has been set, we need + // to start autopinging + if (_pingInterval > 0) { + _timeoutID = setTimeout(that._autoping, _pingInterval); + } + } + }; + + /* + * args: pingURI + * async + * onCompleteFn used only if async is true + * + * (deliberately not catching thrown error) + */ + this._sendPing = function (args) { + var xhr = new XMLHttpRequest(), + that = this; + + function sendPingAfterOpen() { + if (args.async) { + xhr.onreadystatechange = args.onReadyStateFn; + xhr.onCompleteFn = args.onCompleteFn; + xhr._jsdosession = jsdosession; // in case the Session is part of a JSDOSession + xhr._deferred = args.deferred; // in case the Session is part of a JSDOSession + } + progress.data.Session._setNoCacheHeaders(xhr); + // set X-CLIENT-PROPS header + setRequestHeaderFromContextProps(that, xhr); + if (that.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { + _addWithCredentialsAndAccept( + xhr, + "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + ); + } + xhr.send(null); + } + + try { + if (this._authProvider) { + this._authProvider._openRequestAndAuthorize( + xhr, + 'GET', + args.pingURI, + args.async, + sendPingAfterOpen + ); + } else { + // get rid of this if we do away with synchronous support (i.e., customer use of + // old Session API) + this._setXHRCredentials(xhr, "GET", args.pingURI, this.userName, _password, args.async); + + // Sending the XHR request after opening the channel + if (xhr.readyState === 1) { + sendPingAfterOpen(); + } + } + } catch (e) { + args.error = e; + } + + args.xhr = xhr; + }; + + this._makePingURI = function () { + var pingURI = this.serviceURI + partialPingURI; + // had caching problem with Firefox in its offline mode + if (progress.data.Session._useTimeStamp) { + pingURI = progress.data.Session._addTimeStampToURL(pingURI); + } + return pingURI; + }; + + + /* + * autoping -- callback + */ + this._autoping = function () { + that.ping({async: true}); + }; + + + // TODO for API revamp: get rid of this method and replace it with implementations + // of AUthenticationImplementation.openRequest that are specific to the + // auth models (assuming we can use some sort of subclassing or interface design) + // (and when we remove this, remove the calls to it in this file) + /* _setXHRCredentials (intended for progress.data library use only) + * set credentials as needed, both via the xhr's open method and setting the + * Authorization header directly + */ + this._setXHRCredentials = function (xhr, verb, uri, userName, password, async) { + + // note that we do not set credentials if userName is null. + // Null userName indicates that the developer is depending on the browser to + // get and manage the credentials, and we need to make sure we don't interfere with that + if ( + userName + && this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC + ) { + + // See the comment at the definition of the canPassCredentialsToOpen() function + // for why we pass credentials to open() in some cases but not others. (If we're not using + // Basic auth, we never pass credentials) + if (canPassCredentialsToOpen()) { + xhr.open(verb, uri, async, userName, password); + } else { + xhr.open(verb, uri, async); + } + + // set Authorization header + var auth = _make_basic_auth(userName, password); + xhr.setRequestHeader('Authorization', auth); + } else { + xhr.open(verb, uri, async); + } + }; + + /* _addCCIDtoURL (intended for progress.data library use only) + * Add the Client Context ID being used by a session on an OE REST application, if we have + * previously stored one from a response from the server + */ + this._addCCIDtoURL = function (url) { + var urlPart1, + urlPart2, + jsessionidStr, + index; + + if (this.clientContextId && (this.clientContextId !== "0")) { + // Should we test protocol, + // host and port in addition to path to ensure that jsessionid is only sent + // when request applies to the REST app (it might not be if the catalog is somewhere else) + if (url.substring(0, this.serviceURI.length) === this.serviceURI) { + jsessionidStr = ";" + "JSESSIONID=" + this.clientContextId; + index = url.indexOf('?'); + if (index === -1) { + url += jsessionidStr; // just append the jsessionid path parameter to the path + } else { + // insert jsessionid path parameter before the first query parameter + urlPart1 = url.substring(0, index); + urlPart2 = url.substring(index); + url = urlPart1 + jsessionidStr + urlPart2; + } + } + } + return url; + }; + + /* _saveClientContextId (intended for progress.data library use only) + * If the CCID hasn't been set for the session yet, check the xhr for it and store it. + * (If it has been set, assume that the existing one is correct and do nothing. We could + * enhance this function by checking to see whether the new one matches the existing one. + * Not sure what to do if that's the case -- overwrite the old one? ignore the new one? + * Should at least log a warning or error + */ + this._saveClientContextId = function (xhr) { + // do this unconditionally (even if there is already a client-context-id), because + // if basic authentication is set up such that it uses sessions, and cookies are disabled, + // the server will generate a different session on each request and the X-CLIENT-CONTEXT-ID + // will therefore be different + setClientContextIDfromXHR(xhr, this); + }; + + this._parseCatalog = function (xhr) { + var jsonObject; + var catalogdata; + + try { + jsonObject = JSON.parse(xhr.responseText); + catalogdata = jsonObject.services; + } catch (e) { + console.error("Unable to parse response. Make sure catalog has correct format."); + catalogdata = null; + } + + return catalogdata; + }; + + /* _prependAppURL + * Prepends the URL of the Web application + * (the 1st parameter passed to login, stored in this.serviceURI) + * to whatever string is passed in. If the string passed in is an absolute URL, this function does + * nothing except return a copy. This function ensures that the resulting URL has the correct number + * of slashes between the web app url and the string passed in (currently that means that if what's + * passed in has no initial slash, the function adds one) + */ + this._prependAppURL = function (oldURL) { + if (!oldURL) { + /* If oldURL is null, just return the app URL. (It's not the responsibility of this + * function to decide whether having a null URL is an error. Its only responsibility + * is to prepend the App URL to whatever it gets passed + * (and make sure the result is a valid URL) + */ + return this.serviceURI; + } + var newURL = oldURL; + var pat = /^https?:\/\//i; + if (!pat.test(newURL)) { + if (newURL.indexOf("/") !== 0) { + newURL = "/" + newURL; + } + + newURL = this.serviceURI + newURL; + } + return newURL; + }; + + + // Functions + + // get rid of this if we get rid of synchronous (old Session object API) support? + // Set an XMLHttpRequest object's withCredentials attribute and Accept header, + // using a try-catch so that if setting withCredentials throws an error it doesn't + // interrupt execution (this is a workaround for the fact that Firefox doesn't + // allow you to set withCredentials when you're doing a synchronous operation) + // The setting of the Accept header is included here, and happens after the + // attempt to set withCredentials, to make the behavior in 11.3.0 match + // the behavior in 11.2.1 -- for Firefox, in a CORS situation, login() will + // fail. (If we allowed the Accept header to be set, login() would succeed + // because of that but addCatalog() would fail because no JSESSIONID would + // be sent due to withCredentials not being true) + function _addWithCredentialsAndAccept(xhr, acceptString) { + try { + xhr.withCredentials = true; + xhr.setRequestHeader("Accept", acceptString); + } catch (e) { + // Empty + } + } + + // get rid of this if we get rid of synchronous (old Session API) support? + // (because it's in AuthenticationProviderBasic) + // from http://coderseye.com/2007/how-to-do-http-basic-auth-in-ajax.html + function _make_basic_auth(user, pw) { + var tok = user + ':' + pw; + var hash = btoa(tok); + return "Basic " + hash; + } + + /* The next 2 functions, _gotLoginForm() and _gotLoginFailure(), attempt to determine whether + * a server response consists of + * the application's login page or login failure page. Currently (release 11.2), this + * is the only way we have of determining that a request made to the server that's + * configured for form-based authentication failed due to authentication (i.e., + * authentication hadn't happened before the request and either invalid credentials or + * no credentials were sent to the server). That's because, due to the fact that the browser + * or native wrapper typically intercepts the redirect involved in an unauthenticated request + * to a server that's using using form auth, all we see in the XHR is a success status code + * plus whatever page we were redirected to. + * In the future, we expect to enhance the OE REST adapter so that it will return a status code + * indicating failure for form-based authentication, and we can reimplement these functions so + * they check for that code rather than do the simplistic string search. + */ + + // Determines whether the content of the xhr is the login page. Assumes + // use of a convention for testing for login page + var loginFormIDString = "j_spring_security_check"; + + function _gotLoginForm(xhr) { + // is the response contained in an xhr actually the login page? + return _findStringInResponseHTML(xhr, loginFormIDString); + } + + // Determines whether the content of the xhr is the login failure page. Assumes + // use of a convention for testing for login fail page + var loginFailureIdentificationString = "login failed"; + + function _gotLoginFailure(xhr) { + return _findStringInResponseHTML(xhr, loginFailureIdentificationString); + } + + // Does a given xhr contain html and does that html contain a given string? + function _findStringInResponseHTML(xhr, searchString) { + if (!xhr.responseText) { + return false; + } + var contentType = xhr.getResponseHeader("Content-Type"); + + if (contentType && + (contentType.indexOf("text/html") >= 0) && + (xhr.responseText.indexOf(searchString) >= 0) + ) { + return true; + } + + return false; + } + + // get rid of this if we get rid of synchronous (old Session API) support? + /* sets the statusFromjson property in the params object to indicate + * the status of a response from an OE Mobile Web application that has + * to do with authentication (the response to a login request, or a + * response to a request for a resource where there was an error having + * to do with authentication */ + function handleJSONLoginResponse(params) { + // Parse the json in the response to see whether it's the special OE REST service + // response. If it is, check the result (which should be consistent with the status from + // the xhr) + var jsonObject; + params.statusFromjson = null; + try { + jsonObject = JSON.parse(params.xhr.responseText); + + if ( + jsonObject.status_code !== undefined + && jsonObject.status_txt !== undefined + ) { + params.statusFromjson = jsonObject.status_code; + } + } catch (e) { + // invalid json + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, params.session); + setLoginHttpStatus(params.xhr.status, params.session); + throw new Error("Unable to parse login response from server."); + } + + } + + function setRequestHeaderFromContextProps(session, xhr) { + if (session.xClientProps) { + xhr.setRequestHeader("X-CLIENT-PROPS", session.xClientProps); + } else if (session._contextProperties.contextHeader !== undefined) { + xhr.setRequestHeader("X-CLIENT-PROPS", session._contextProperties.contextHeader); + } + } + + function toggleOnlineState(xhr) { + var pdsession = that; + + setLoginHttpStatus(xhr.status, pdsession); + + if (pdsession.loginHttpStatus >= 200 && pdsession.loginHttpStatus < 400) { + setLoginResult(progress.data.Session.LOGIN_SUCCESS, pdsession); + setRestApplicationIsOnline(true); + pdsession._saveClientContextId(xhr); + storeAllSessionInfo(); // save info to persistent storage + } else { + // Taking a page from _processPingResult where we set the rest application as offline if it's one of + // these error codes + if ( + pdsession.loginHttpStatus === 0 + || pdsession.loginHttpStatus === 400 + || pdsession.loginHttpStatus === 410 + ) { + setRestApplicationIsOnline(false); + setLoginResult( + progress.data.AuthenticationProvider._getAuthFailureReason(xhr), + pdsession + ); + } else { + // Otherwise if it's probably an internal error or auth problem. + // Either way, we know it's still online. + setRestApplicationIsOnline(true); + setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, pdsession); + } + } + + setLastSessionXHR(xhr, pdsession); + updateContextPropsFromResponse(pdsession, xhr); + + return pdsession.loginResult; + } + + function updateContextPropsFromResponse(session, xhr) { + /* determine whether the response contains an X-CLIENT_PROPS header and, if so, + set the Session's context + */ + var contextString, + context; + + if (xhr) { + contextString = getResponseHeaderNoError(xhr, "X-CLIENT-PROPS"); + if (contextString) { + try { + context = JSON.parse(contextString); + } catch (e) { + // Empty + } + if (typeof context === "object") { + session._contextProperties.setContext(context); + } else { + //{1}: A server response included an invalid {2} header. + throw new Error(progress.data._getMsgText("jsdoMSG123", 'Session', 'X-CLIENT-PROPS')); + } + } else if (contextString === "") { + // If header is "", clear the X-CLIENT-PROPS context, + session._contextProperties.setContext({}); + } + // if header is absent (getResponseHeader will return null), don't change _contextProperties + } + } + + // Remove all resources, services, and sessions related to this Session from the ServicesManager + function cleanServicesManager() { + progress.data.ServicesManager.cleanSession(that); + } + + // process constructor options and do other initialization + + // If a storage key (name property of a JSDOSession) was passed to the constructor, + // use it to try to retrieve state data from a previous JSDOSession instance that + // had the same name. This code was introduced to handle page refreshes, but could + // be used for other purposes. + if (typeof options === 'object') { + + jsdosession = options.jsdosession; + newURI = options.serviceURI; + setAuthProvider(options.authProvider); // do this BEFORE calling setSessionInfoFromStorage + + if (options.authProvider && options.authProvider.hasClientCredentials()) { + _loginResult = progress.data.Session.LOGIN_SUCCESS; + } + + // get rid of trailing '/' because appending service url that starts with '/' + // will cause request failures + if (newURI && newURI[newURI.length - 1] === "/") { + newURI = newURI.substring(0, newURI.length - 1); + } + + _storageKey = options._storageKey; + if (_storageKey) { + if (retrieveSessionInfo(_storageKey)) { + storedAuthModel = retrieveSessionInfo("authenticationModel"); + storedURI = retrieveSessionInfo("serviceURI"); + + if ( + (storedAuthModel !== options.authenticationModel) || + (storedURI !== newURI) + ) { + clearAllSessionInfo(); + } else { + // Note: be sure we have set authProvider (if any) from options before + // calling setSessionInfoFromStorage (important so that the logic in + // setSessionInfoFromStorage that re-creates an AuthenticationProvider + // after page refresh only gets used if the app is using the old JSDOSession.login) + setSessionInfoFromStorage(_storageKey); + stateWasReadFromStorage = true; + } + } + // _storageKey is in essence the flag for page refresh; we are not supporting page refresh for Basic + // auth, so clear it even if it was passed in. + // (But had to set and keep _storageKey until this point so that the above validation of + // serviceURI and auth model will be done even in the case where there's a mismatch and + // the new auth model is Basic. This statement will go away when we support page refresh with + // Basic) + if (options.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { + _storageKey = undefined; + } + } + + // If we didn't read state info from storage, we need to set the serviceURI and probably + // the authenticationModel + if (!stateWasReadFromStorage) { + if (newURI) { + setServiceURI(newURI, this); + } + if (options.authenticationModel) { + this.authenticationModel = options.authenticationModel; + } + } + } + + }; // End of Session + progress.data.Session._useTimeStamp = true; + + var SEQ_MAX_VALUE = 999999999999999; + // 15 - 9 + var _tsseq = SEQ_MAX_VALUE; + // Initialized to SEQ_MAX_VALUE to initialize values. + var _tsprefix1 = 0; + var _tsprefix2 = 0; + + // this._getNextTimeStamp = function () { + progress.data.Session._getNextTimeStamp = function () { + var seq; + + _tsseq += 1; + seq = _tsseq; + + if (seq >= SEQ_MAX_VALUE) { + _tsseq = 1; + seq = 1; + var t = Math.floor((Date.now ? Date.now() : (new Date().getTime())) / 10000); + if (_tsprefix1 === t) { + _tsprefix2 += 1; + if (_tsprefix2 >= SEQ_MAX_VALUE) { + _tsprefix2 = 1; + } + } else { + _tsprefix1 = t; + Math.random(); // Ignore call to random + _tsprefix2 = Math.round(Math.random() * 10000000000); + } + } + + return _tsprefix1 + "-" + _tsprefix2 + "-" + seq; + }; + + /* + * _addTimeStampToURL (intended for progress.data library use only) + * Add a time stamp to the a URL to prevent caching of the request. + * Set progress.data.Session._useTimeStamp = false to turn off. + */ + progress.data.Session._addTimeStampToURL = function (url) { + var timeStamp = "_ts=" + progress.data.Session._getNextTimeStamp(); + url += ((url.indexOf('?') === -1) ? "?" : "&") + timeStamp; + return url; + }; + + // Do whatever it takes to direct the XMLHttpRequest not to fulfill the request + // from a cache + // (convenience method --- we do this several different places in the code) + progress.data.Session._setNoCacheHeaders = function (xhr) { + xhr.setRequestHeader("Cache-Control", "no-cache"); + xhr.setRequestHeader("Pragma", "no-cache"); + }; + + + + // Constants for progress.data.Session + if ((typeof Object.defineProperty) === 'function') { + Object.defineProperty( + progress.data.Session, + 'LOGIN_AUTHENTICATION_REQUIRED', + { + value: 0, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'LOGIN_SUCCESS', + { + value: 1, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'LOGIN_AUTHENTICATION_FAILURE', + { + value: 2, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'LOGIN_GENERAL_FAILURE', + { + value: 3, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'CATALOG_ALREADY_LOADED', + { + value: 4, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'ASYNC_PENDING', + { + value: 5, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'EXPIRED_TOKEN', + { + value: 6, + enumerable: true + } + ); + + Object.defineProperty( + progress.data.Session, + 'SUCCESS', + { + value: 1, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'AUTHENTICATION_FAILURE', + { + value: 2, + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'GENERAL_FAILURE', + { + value: 3, + enumerable: true + } + ); + + Object.defineProperty( + progress.data.Session, + 'AUTH_TYPE_ANON', + { + value: "anonymous", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'AUTH_TYPE_BASIC', + { + value: "basic", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'AUTH_TYPE_FORM', + { + value: "form", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'AUTH_TYPE_SSO', + { + value: "sso", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'AUTH_TYPE_FORM_SSO', + { + value: "form_sso", + enumerable: true + } + ); + + Object.defineProperty( + progress.data.Session, + 'DEVICE_OFFLINE', + { + value: "Device is offline", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'SERVER_OFFLINE', + { + value: "Cannot contact server", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'WEB_APPLICATION_OFFLINE', + { + value: "Mobile Web Application is not available", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'SERVICE_OFFLINE', + { + value: "REST web Service is not available", + enumerable: true + } + ); + Object.defineProperty( + progress.data.Session, + 'APPSERVER_OFFLINE', + { + value: "AppServer is not available", + enumerable: true + } + ); + } else { + progress.data.Session.LOGIN_SUCCESS = 1; + progress.data.Session.LOGIN_AUTHENTICATION_FAILURE = 2; + progress.data.Session.LOGIN_GENERAL_FAILURE = 3; + progress.data.Session.CATALOG_ALREADY_LOADED = 4; + + progress.data.Session.SUCCESS = 1; + progress.data.Session.AUTHENTICATION_FAILURE = 2; + progress.data.Session.GENERAL_FAILURE = 3; + + progress.data.Session.AUTH_TYPE_ANON = "anonymous"; + progress.data.Session.AUTH_TYPE_BASIC = "basic"; + progress.data.Session.AUTH_TYPE_FORM = "form"; + progress.data.Session.AUTH_TYPE_SSO = "sso"; + + /* deliberately not including the "offline reasons" that are defined in the + * 1st part of the conditional. We believe that we can be used only in environments where + * ECMAScript 5 is supported, so let's put that assumption to the test + */ + } + + //setup inheritance for Session -- specifically for incorporating an Observable object + progress.data.Session.prototype = new progress.util.Observable(); + progress.data.Session.prototype.constructor = progress.data.Session; + function validateSessionSubscribe(args, evt, listenerData) { + listenerData.operation = undefined; + var found = false; + + // make sure this event is one that we support + this._eventNames.forEach(function (eventName) { + if (evt === eventName.toLowerCase()) { + found = true; + } + }); + + if (!found) { + throw new Error(progress.data._getMsgText("jsdoMSG042", evt)); + } + + if (args.length < 2) { + throw new Error(progress.data._getMsgText("jsdoMSG038", 2)); + } + + if (typeof args[0] !== 'string') { + throw new Error(progress.data._getMsgText("jsdoMSG039")); + } + + if (typeof args[1] !== 'function') { + throw new Error(progress.data._getMsgText("jsdoMSG040")); + } + + listenerData.fn = args[1]; + + if (args.length > 2) { + if (typeof args[2] !== 'object') { + throw new Error(progress.data._getMsgText("jsdoMSG041", evt)); + } else { + listenerData.scope = args[2]; + } + } + } + // events supported by Session + progress.data.Session.prototype._eventNames = + ["offline", "online", "afterLogin", "afterAddCatalog", "afterLogout", "afterDisconnect"]; + // callback to validate subscribe and unsubscribe + progress.data.Session.prototype.validateSubscribe = validateSessionSubscribe; + progress.data.Session.prototype.toString = function (radix) { + return "progress.data.Session"; + }; + + + /* + progress.data.JSDOSession + Like progress.data.Session, but the methods are async-only and return promises. + (first implementation uses progress.data.Session to do the work, but conceivably + that implementation could be changed to something different) + The JSDOSession object keeps the same underlying pdsession object for the lifetime + of the JSDOSession object -- i.e., even after logout and subsequent login, the pdsession + is re-used rather than re-created. + */ + progress.data.JSDOSession = function JSDOSession(options) { + var _pdsession, + _serviceURI, + that = this, + _name; + + // PROPERTIES + // Approach: Use the properties of the underlying progress.data.Session object whenever + // possible. + Object.defineProperty( + this, + 'authenticationModel', + { + get: function () { + return _pdsession ? _pdsession.authenticationModel : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'authProvider', + { + get: function () { + return _pdsession ? _pdsession._authProvider : null; + }, + enumerable: true + } + ); + Object.defineProperty( + this, + 'catalogURIs', + { + get: function () { + return _pdsession ? _pdsession.catalogURIs : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'clientContextId', + { + get: function () { + return _pdsession ? _pdsession.clientContextId : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'connected', + { + get: function () { + return _pdsession ? _pdsession.connected : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'JSDOs', + { + get: function () { + return _pdsession ? _pdsession.JSDOs : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'loginResult', + { + get: function () { + return _pdsession ? _pdsession.loginResult : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'loginHttpStatus', + { + get: function () { + return _pdsession ? _pdsession.loginHttpStatus : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'onOpenRequest', + { + get: function () { + return _pdsession ? _pdsession.onOpenRequest : undefined; + }, + set: function (newval) { + if (_pdsession) { + _pdsession.onOpenRequest = newval; + } + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'pingInterval', + { + get: function () { + return _pdsession ? _pdsession.pingInterval : undefined; + }, + set: function (newval) { + if (_pdsession) { + _pdsession.pingInterval = newval; + } + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'services', + { + get: function () { + return _pdsession ? _pdsession.services : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'serviceURI', + { + get: function () { + if (_pdsession && _pdsession.serviceURI) { + return _pdsession.serviceURI; + } else { + return _serviceURI; + } + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'userName', + { + get: function () { + return _pdsession ? _pdsession.userName : undefined; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + 'name', + { + get: function () { + return _name; + }, + enumerable: true + } + ); + + Object.defineProperty( + this, + "_isInvalidated", + { + get: function () { + return _pdsession._isInvalidated; + }, + enumerable: false + } + ); + + // PRIVATE FUNCTIONS + + + // Wrapper to make it easier to change the promise implementation we use. + // Note that in the JSDO library's first implementation of promise support, + // the "promise" parameter for this function is actually a jQuery Deferred object + function settlePromise(promise, fulfill, result, info) { + if (fulfill) { + promise.resolve(that, result, info); + } else { + promise.reject(that, result, info); + } + } + + // use this for the events fired by progress.data.Session that can be handled with common code + function genericSessionEventHandler(pdsession, result, errorObject, xhr, deferred) { + var myDeferred; + + if (xhr) { + myDeferred = xhr._deferred; + } else { + myDeferred = deferred; + } + + settlePromise( + myDeferred, + result === progress.data.Session.SUCCESS ? true : false, + result, + { + errorObject: errorObject, + xhr: xhr + } + ); + } + + function onAfterAddCatalog(pdsession, result, errorObject, xhr) { + var deferred, + fulfill = false, + settleResult, + info; + + if (result === progress.data.Session.EXPIRED_TOKEN) { + settleResult = progress.data.Session.EXPIRED_TOKEN; + } else if (result === progress.data.Session.LOGIN_AUTHENTICATION_FAILURE) { + settleResult = progress.data.Session.LOGIN_AUTHENTICATION_FAILURE; + } else { + settleResult = progress.data.Session.GENERAL_FAILURE; + } + + if (xhr && xhr._deferred) { + deferred = xhr._deferred; + + /* add the result for this addCatalog to the result array. */ + if ( + result !== progress.data.Session.SUCCESS && + result !== progress.data.Session.CATALOG_ALREADY_LOADED + ) { + + result = result || progress.data.Session.GENERAL_FAILURE; + + /* Set a property on the deferred to indicates that the "overall" result was + a failure. When we decide whether to reject or resolve the promise, we reject + if it's set to GENERAL_FAILURE, otherwise we resolve the promise + (really only need to set this once, but simpler code if we just set (or possibly + re-set) it whenever we find an error, plus if, at some point while we're still + processing, it's important to know whether we've already had an error, we can + check the property) + */ + deferred._overallCatalogResult = progress.data.Session.GENERAL_FAILURE; + } + + deferred._results[xhr._catalogIndex] = { + catalogURI: xhr._catalogURI, + result: result, + errorObject: errorObject, + xhr: xhr + }; + deferred._numCatalogsProcessed += 1; + if (deferred._numCatalogsProcessed === deferred._numCatalogs) { + deferred._processedPromise = true; + + if (!deferred._overallCatalogResult) { + fulfill = true; + settleResult = progress.data.Session.SUCCESS; + } + if (settleResult === progress.data.Session.SUCCESS) { + if (xhr._deferred._results.length === 1) { + info = xhr._deferred._results[0]; + } else { + info = { + xhr: xhr, + result: settleResult, + details: xhr._deferred._results + }; + } + } else { + if (xhr._deferred._results.length === 1) { + info = xhr._deferred._results[0]; + } else { + info = { + xhr: xhr, + result: settleResult, + errorObject: new Error(progress.data._getMsgText("jsdoMSG512")), + details: xhr._deferred._results + }; + } + } + settlePromise( + xhr._deferred, + fulfill, + settleResult, + info + ); + } + } + } + + function onAfterLogout(pdsession, errorObject, xhr) { + var result = progress.data.Session.GENERAL_FAILURE, + fulfill = false; + if (xhr && xhr._deferred) { + /* Note: loginResult gets cleared on successful logout, so testing it for false + to confirm that logout succeeded + */ + if (!errorObject && !pdsession.loginResult) { + result = progress.data.Session.SUCCESS; + fulfill = true; + } + settlePromise( + xhr._deferred, + fulfill, + result, + { + errorObject: errorObject, + xhr: xhr + } + ); + } + } + + function onPingComplete(args) { + var xhr = args.xhr; + if (xhr && xhr._deferred) { + settlePromise( + xhr._deferred, + args.pingResult, // this tells settlePromise whether to resolve or reject + args.pingResult, // this is the result value passed to the promise handler + { + offlineReason: args.offlineReason, + xhr: xhr + } + ); + } + } + + // METHODS + + // login() + // Creates an AuthenticationProvider and calls its login() method. Any errors thrown by the + // Auth Provider's constructor or login will bubble up to the caller, otherwise this method + // returns the promise from the A-P's login call. + this.login = function (username, password, options) { + var deferred = new progress.util.Deferred(), + iOSBasicAuthTimeout; + + function callIsAuthorized() { + that.isAuthorized() + .then(function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.resolve(that, object.result, object.info); + }, function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.reject(that, object.result, object.info); + }); + } + + try { + // console.warn( + // "JSDOSession: As of JSDO 4.4, login() has been deprecated. Please use " + // + "the AuthenticationProvider API instead." + // ); + + if (this._isInvalidated) { + // JSDOSession: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); + } + + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // JSDOSession: Cannot call login() when authenticationModel is SSO. + // Please use the AuthenticationProvider object instead. + throw new Error(progress.data._getMsgText("jsdoMSG057", 'JSDOSession', 'login()')); + } + + if (typeof options === 'object') { + iOSBasicAuthTimeout = options.iOSBasicAuthTimeout; + } + + // As part of JSDOSession's login we create a new authProvider always. However, when a valid + // authProvider is provided as part of JSDOSession's constructor. i.e., when we already have + // a valid authProvider, performing login operation is not allowed. We throw an error. + if (!_pdsession._authProvider) { + // is there a better way to do this? Need it because we didn't have the authprovider when + // running the constructor + _pdsession._authProvider = new progress.data.AuthenticationProvider({ + uri: this.serviceURI, + authenticationModel: this.authenticationModel + }); + + _pdsession._authProvider.logout() + .then(function () { + return _pdsession._authProvider.login(username, password); + }) + .then(function () { + callIsAuthorized(); + }, function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.reject(that, object.result, object.info); + }); + } else { + throw new Error(progress.data._getMsgText("jsdoMSG062", 'JSDOSession', 'login()')); + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + // This method terminates the JSDOSession's ability to send requests to its serviceURI. + // Remove the reference to the AuthenticationProvider that was passed to connect(). + // Will be a no-op if connect() has not yet been called successfully. + // This method reinitializes the Session object back to the state it was in just after being created. + // Retains the serviceURI, authenticationModel, and name values. + // Delete any of the object's data that had been persisted (for example, to sessionStorage to support + // page refresh). + // Data for any catalogs loaded by the JSDOSession will NOT be deleted. + // See additional commecnts at the Session._disconnect method. + this.disconnect = function () { + var deferred = new progress.util.Deferred(), + errorObject; + + try { + _pdsession.subscribe('afterDisconnect', genericSessionEventHandler, this); + + _pdsession._disconnect(deferred); + } catch (e) { + // JSDOSession: Unexpected error calling disconnect: {e.message} + errorObject = new Error( + progress.data._getMsgText("jsdoMSG049", "JSDOSession", "disconnect", e.message) + ); + } + + if (errorObject) { + if (progress.util.Deferred.useJQueryPromises) { + throw errorObject; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: errorObject + }); + } + } else { + return deferred.promise(); + } + }; + + this.addCatalog = function (catalogURI, unameOrOpts, password, opts) { + var deferred = new progress.util.Deferred(), + catalogURIs, + numCatalogs, + catalogIndex, + addResult, + errorObject, + iOSBasicAuthTimeout, + username, + options, + authProvider; + + try { + if (this._isInvalidated) { + // JSDOSession: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); + } + + // check whether 1st param is a string or an array + if (typeof catalogURI === "string") { + catalogURIs = [catalogURI]; + } else if (catalogURI instanceof Array) { + catalogURIs = catalogURI; + } else { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "JSDOSession", + "addCatalog", + "The first argument must be a string or an array of strings specifying the URI of the catalog." + )); + } + + // type check the 2nd param if it exists + if (unameOrOpts) { + if (typeof unameOrOpts === "string") { + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // Session: Cannot pass username and password to addCatalog when + // authenticationModel is SSO. Pass an AuthenticationProvider instead. + throw new Error(progress.data._getMsgText("jsdoMSG058", 'Session')); + } + username = unameOrOpts; + // explictly ignore any authProvider if using the (catURI, uname, pw, options) signature + if (opts) { + options = opts; + options.authProvider = undefined; + } + } else if (typeof unameOrOpts === "object") { + options = unameOrOpts; + } else { + // JSDOSession: Argument 2 must be of type object in addCatalog call. + throw new Error(progress.data._getMsgText( + "jsdoMSG121", + "JSDOSession", + "2", + "object", + "addCatalog" + )); + } + } + + if (typeof options === 'object') { + // possible override for the workaround for the Cordova iOS async Basic auth bug + iOSBasicAuthTimeout = options.iOSBasicAuthTimeout; + if (options.authProvider) { + authProvider = options.authProvider; + } else if (this.authProvider) { + authProvider = this.authProvider; + } + } + + // Error out if no authProvider or username was given + if (!authProvider && !this.authProvider && !username) { + throw new Error(progress.data._getMsgText("jsdoMSG511")); + } + + /* When we're done processing all catalogs, we pass an array of results to resolve() or + reject(). We're attaching this array to the deferred object, in case the app makes + multiple addCatalog calls (if the array was attached to the JSDOSession, + the 2nd call might overwrite the first) + */ + + /* Add properties to the deferred object for this call to store the total + number of catalogs that are to be done, the number that ahve been processed, + and a reference to an array of results. + Loop through the array of catalogURIs, calling addCatalog for each one. If a call + throws an error or returns something other than ASYNC_PENDING, create a result object + for that catalog and add the result object to the resultArray. Otherwise, the result + object will be added by the afterAddCatalog handler. + If all of the Session.addCatalog calls throw an error or return something other + than ASYNC_PENDING, this function will reject the promise and return. Otherwise + the afterAddCatalog handler will resolve or reject the promise after all calls have + been processed. + Note that we try to make sure that each entry in the results array is in the same position + as its catalogURI in the input array. + */ + // if a catalogURI has no protocol, pdsession will assume it's relative to the serviceURI, + // if there has been a login + // NOTE: this means if the app is trying to load a local catalog, it MUST + // specify the file: protocol (and we need to make sure that works on all platforms) + + _pdsession.subscribe('afterAddCatalog', onAfterAddCatalog, this); + + numCatalogs = catalogURIs.length; + deferred._numCatalogs = numCatalogs; + deferred._numCatalogsProcessed = 0; + deferred._results = []; + deferred._results.length = numCatalogs; + + for (catalogIndex = 0; catalogIndex < numCatalogs; catalogIndex += 1) { + errorObject = undefined; + addResult = undefined; + try { + addResult = _pdsession.addCatalog( + { + catalogURI: catalogURIs[catalogIndex], + async: true, + userName: username, + password: password, + deferred: deferred, + catalogIndex: catalogIndex, + iOSBasicAuthTimeout: iOSBasicAuthTimeout, + authProvider: authProvider, + offlineAddCatalog: true + } + ); // OK to get catalog if offline + } catch (e) { + errorObject = new Error("JSDOSession: Unable to send addCatalog request. " + e.message); + } + + if (addResult !== progress.data.Session.ASYNC_PENDING) { + /* Set a property on the deferred to indicate that the "overall" result was + a failure. When we decide whether to reject or resolve the promise, we reject + if it's set to GENERAL_FAILURE, otherwise we resolve the promise + (really only need to set this once, but simpler code if we just set (or possibly + re-set) it whenever we find an error, plus if, at some point while we're still + processing, it's important to know whether we've already had an error, we can + check the property) + */ + deferred._overallCatalogResult = progress.data.Session.GENERAL_FAILURE; + if (errorObject) { + addResult = progress.data.Session.GENERAL_FAILURE; + } + deferred._results[catalogIndex] = { + catalogURI: catalogURIs[catalogIndex], + result: addResult, + errorObject: errorObject, + xhr: undefined + }; + deferred._numCatalogsProcessed += 1; + } + } + + if ((deferred._numCatalogsProcessed === numCatalogs) && !deferred._processedPromise) { + /* The goal here is to handle the case where all the catalogs + have been processed but the afterAddCatalog handler may not be invoked at the + end (the obvious example is if there are no async requests actually made by + Session.addCatalog). In that case, we have to resolve/reject from here. Chances are + very good that if we're doing this here, there's been at least one error, but just + to be sure, we check the deferred._overallCatalogResult anyway + */ + if (deferred._overallCatalogResult === progress.data.Session.GENERAL_FAILURE) { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, deferred._results); + } else { + deferred.resolve(this, progress.data.Session.SUCCESS, deferred._results); + } + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + // Note that this will work for either of these cases: + // - app originally called JSDOSession.login (so we implicitly created the AuthenticationProvider) + // - app created an AuthenticationProvider and passed it to connect, but now for some reason has + // called logout (this is actually a nice shortcut for someone who has used getSession) + // (NB: we should not allow this for SSO, tho) + // + // Note that we also don't support login/logout on the JSDOSession for page refresh + this.logout = function () { + var deferred = new progress.util.Deferred(), + authProv = this.authProvider; + + try { + // console.warn( + // "JSDOSession: As of 4.4, logout() has been deprecated. Please use " + // + "the AuthenticationProvider API instead." + // ); + + if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // JSDOSession: Cannot call logout() when authenticationModel is SSO. + // Please use the AuthenticationProvider object instead. + throw new Error(progress.data._getMsgText( + "jsdoMSG057", + 'JSDOSession', + 'logout()' + )); + } + + this.disconnect() + .then(function () { + if (authProv) { + return authProv.logout(); + } + // if there's no AP, just resolve immediately successfully + deferred.resolve(that, progress.data.Session.SUCCESS, {}); + }) + .then(function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.resolve(that, object.result, object.info); + }, function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.reject(that, object.result, object.info); + }); + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(that, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + + return deferred.promise(); + }; + + + this.invalidate = function () { + _pdsession.invalidate(); + return this.logout(); + }; + + this.ping = function () { + var deferred = new progress.util.Deferred(); + + try { + if (this._isInvalidated) { + // JSDOSession: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); + } + + try { + _pdsession.ping({ + async: true, + deferred: deferred, + onCompleteFn: onPingComplete + }); + } catch (e) { + throw new Error("JSDOSession: Unable to send ping request. " + e.message); + } + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + + return deferred.promise(); + }; + + // Determine whether the JSDOSession can currently access its web application. + // The use expected for this method is to determine whether a JSDOSession that has + // previously authenticated to its web application still has authorization. + // For example, if the JSDOSession is using Form authentication, is the server + // session still valid or did it expire? + this.isAuthorized = function () { + var deferred = new progress.util.Deferred(), + xhr = new XMLHttpRequest(), + result, + that = this; + + try { + if (this._isInvalidated) { + // JSDOSession: This session has been invalidated and cannot be used. + throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); + } + + // If we logged in successfuly using login() or if we have an AuthProvider, make the call + if (this.loginResult === progress.data.Session.LOGIN_SUCCESS || this.authProvider) { + _pdsession._openRequest( + xhr, + "GET", + _pdsession.loginTarget, + true, + function () { + xhr.onreadystatechange = function () { + // do we need this xhr var? The one declared in isAuthorized seems to be in scope + var xhr = this, + cbresult, + info; + + if (xhr.readyState === 4) { + info = { + xhr: xhr, + offlineReason: undefined, + fireEventIfOfflineChange: true, + usingOepingFormat: false + }; + + // call _processPingResult because it has logic for + // detecting change in online/offline state + _pdsession._processPingResult(info); + + if (xhr.status >= 200 && xhr.status < 300) { + deferred.resolve( + that, + progress.data.Session.SUCCESS, + info + ); + } else { + if (xhr.status === 401) { + cbresult = progress.data.AuthenticationProvider._getAuthFailureReason(xhr); + } else { + cbresult = progress.data.Session.GENERAL_FAILURE; + } + deferred.reject(that, cbresult, info); + } + } + }; + + try { + xhr.send(); + } catch (e) { + throw new Error("JSDOSession: Unable to validate authorization. " + e.message); + } + } + ); + } else { + // Never logged in (or logged in and logged out). Regardless of what the reason + // was that there wasn't a login, the bottom line is that authentication is required + result = progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED; + deferred.reject(that, result, {xhr: xhr}); + } + + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(that, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + // set the properties that are passed between client and Web application in the + // X-CLIENT-PROPS header. This sets the complete set of properties all at once; + // it replaces any existing context + + this.setContext = function (context) { + _pdsession._contextProperties.setContext(context); + }; + + // Set or remove an individual property in the set of the properties that are passed + // between client and Web application in the X-CLIENT-PROPS header. This operates only + // on the property identiofied by propertyName; all other existing properties remain + // as they are. + // If the propertyName is not part of the context, this call adds it + // If it is part of the context, this call updates it, unless - + // If propertyValue is undefined, this call removes the property + this.setContextProperty = function (propertyName, propertyValue) { + _pdsession._contextProperties.setContextProperty(propertyName, propertyValue); + }; + + // get the set of properties that are passed between client and Web application in the + // X-CLIENT-PROPS header. Returns an object that has the properties + this.getContext = function () { + return _pdsession._contextProperties.getContext(); + }; + + // get the value of an individual property that is in the set of properties passed between + // client and Web application in the X-CLIENT-PROPS header + this.getContextProperty = function (propertyName) { + return _pdsession._contextProperties.getContextProperty(propertyName); + }; + + + this._onlineHandler = function (session, request) { + that.trigger("online", that, request); + }; + + this._offlineHandler = function (session, offlineReason, request) { + that.trigger("offline", that, offlineReason, request); + }; + + // PROCESS CONSTRUCTOR ARGUMENTS + // validate constructor input arguments + if ((arguments.length > 0) && (typeof arguments[0] === 'object')) { + + // (options is the name of the arguments[0] parameter) + if (options.serviceURI && (typeof options.serviceURI === "string")) { + _serviceURI = options.serviceURI; + } else { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "JSDOSession", + "the constructor", + "The options parameter must include a 'serviceURI' property that is a string." + )); + } + + if (options.authenticationModel) { + if (typeof options.authenticationModel !== "string") { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "JSDOSession", + "the constructor", + "The authenticationModel property of the options parameter must be a string." + )); + } + + options.authenticationModel = options.authenticationModel.toLowerCase(); + } else { + options.authenticationModel = progress.data.Session.AUTH_TYPE_ANON; + } + + // TODO: clean this up. Maybe make an immediate function + if (options.authProvider) { + if (typeof options.authProvider !== 'object') { + // JSDOSession: The 'options' parameter passed to the 'constructor' function + // has an invalid value for the 'authProvider' property. + throw new Error(progress.data._getMsgText( + "jsdoMSG502", + "JSDOSession", + "options", + "constructor", + "authProvider" + )); + } + + if ( + ( + options.authProvider.authenticationModel !== progress.data.Session.AUTH_TYPE_FORM_SSO + && options.authProvider.authenticationModel !== options.authenticationModel + ) + || + ( + options.authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_FORM_SSO + && options.authenticationModel !== progress.data.Session.AUTH_TYPE_SSO + ) + ) { + // JSDOSession: Error in constructor. The authenticationModels of the " + + // AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible."; + throw new Error(progress.data._getMsgText( + "jsdoMSG059", + "JSDOSession", + options.authProvider.authenticationModel, + options.authenticationModel + )); + } + // Check if the provider exposes the required API. + if (typeof options.authProvider.hasClientCredentials === 'function') { + if (!options.authProvider.hasClientCredentials()) { + // JSDOSession: The AuthenticationProvider is not managing valid credentials. + throw new Error(progress.data._getMsgText("jsdoMSG125", "JSDOSession")); + } + } else { + // JSDOSession: AuthenticationProvider objects must have a hasClientCredentials method. + throw new Error(progress.data._getMsgText( + "jsdoMSG505", + "JSDOSession", + "AuthenticationProvider", + "hasClientCredentials" + )); + } + } else if (options.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + // JSDOSession: If a JSDOSession object is using the SSO authentication model, + // the options object passed to its constructor must include an authProvider property. + throw new Error(progress.data._getMsgText("jsdoMSG508")); + } + + } else { + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "JSDOSession", + "the constructor", + "The options argument was missing or invalid." + )); + } + + _name = options.name; + + _pdsession = new progress.data.Session({ + _storageKey: _name, + _silent: true, + authenticationModel: options.authenticationModel, + serviceURI: options.serviceURI, + jsdosession: this, + authProvider: options.authProvider + }); + + try { + if (options.context) { + this.setContext(options.context); + } + _pdsession.subscribe("online", this._onlineHandler, this); + _pdsession.subscribe("offline", this._offlineHandler, this); + } catch (err) { + _pdsession = undefined; // so it will be garbage collected + throw err; + } + + }; // end of JSDOSession + + //set up inheritance for JSDOSession -- specifically for incorporating an Observable object + progress.data.JSDOSession.prototype = new progress.util.Observable(); + progress.data.JSDOSession.prototype.constructor = progress.data.JSDOSession; + function validateJSDOSessionSubscribe(args, evt, listenerData) { + listenerData.operation = undefined; + var found = false; + + // make sure this event is one that we support + this._eventNames.forEach(function (eventName) { + if (evt === eventName.toLowerCase()) { + found = true; + } + }); + if (!found) { + throw new Error(progress.data._getMsgText("jsdoMSG042", evt)); + } + + if (args.length < 2) { + throw new Error(progress.data._getMsgText("jsdoMSG038", 2)); + } + + if (typeof args[0] !== 'string') { + throw new Error(progress.data._getMsgText("jsdoMSG039")); + } + + if (typeof args[1] !== 'function') { + throw new Error(progress.data._getMsgText("jsdoMSG040")); + } + + listenerData.fn = args[1]; + + if (args.length > 2) { + if (typeof args[2] !== 'object') { + throw new Error(progress.data._getMsgText("jsdoMSG041", evt)); + } + + listenerData.scope = args[2]; + } + } + // events supported by JSDOSession + progress.data.JSDOSession.prototype._eventNames = + ["offline", "online"]; + // callback to validate subscribe and unsubscribe + progress.data.JSDOSession.prototype.validateSubscribe = validateJSDOSessionSubscribe; + progress.data.JSDOSession.prototype.toString = function (radix) { + return "progress.data.JSDOSession"; + }; + + progress.data.getSession = function (options) { + var deferred = new progress.util.Deferred(), + authProvider, + promise, + authProviderInitObject = {}; + + // This is the reject handler for session-related operations + // login, addCatalog, and logout + function sessionRejectHandler(object, result, info) { + // The object parameter may include the following properties + // - originator + // - result + // - info + object = progress.util.Deferred.getParamObject(object, result, info); + // undo the AuthenticationProvider's login if it succeeded + if (authProvider && authProvider.hasClientCredentials()) { + var callback = function () { + deferred.reject(object.result, object.info); + }; + // finally + authProvider.logout().then(callback, callback); + } else { + deferred.reject(object.result, object.info); + } + } + + // This is the reject handler for the login callback + function callbackRejectHandler(reason) { + deferred.reject(progress.data.Session.GENERAL_FAILURE, {"reason": reason}); + } + + function loginHandler(object) { + var jsdosession; + + try { + jsdosession = new progress.data.JSDOSession(options); + try { + jsdosession.isAuthorized() + .then(function() { + return jsdosession.addCatalog(options.catalogURI); + }, sessionRejectHandler) + .then(function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); + }, sessionRejectHandler); + } catch (e) { + sessionRejectHandler( + jsdosession, + progress.data.Session.GENERAL_FAILURE, + {errorObject: e} + ); + } + } catch (ex) { + sessionRejectHandler( + jsdosession, + progress.data.Session.GENERAL_FAILURE, + {errorObject: ex} + ); + } + } + + // This function calls login using credentials from the appropriate source + // Note that as currently implemented, this should NOT be called when + // ANONYMOUS auth is being used, because it unconditionally returns + // AUTHENTICATION_FAILURE if there are no credentials and no loginCallback + function callLogin(provider) { + var errorObject; + + // Use the login callback if we are passed one + // NOTE: Do we even use logincallback? Remove this??? + if (typeof options.loginCallback !== 'undefined') { + options.loginCallback() + .then(function (result) { + try { + provider.login(result.username, result.password) + .then(loginHandler, sessionRejectHandler); + } catch (e) { + sessionRejectHandler( + provider, + progress.data.Session.GENERAL_FAILURE, + { + errorObject: e + } + ); + } + }, callbackRejectHandler); + } else if (options.username && options.password) { + try { + provider.login(options.username, options.password) + .then(loginHandler, sessionRejectHandler); + } catch (e) { + sessionRejectHandler( + provider, + progress.data.Session.GENERAL_FAILURE, + { + errorObject: e + } + ); + } + } else { + // getSession(): The login method was not executed because no credentials were supplied. + errorObject = new Error(progress.data._getMsgText( + "jsdoMSG052", + "getSession()" + )); + sessionRejectHandler( + provider, + progress.data.Session.AUTHENTICATION_FAILURE, + { + // including an Error object to make clear why there is no xhr (normally there would + // be one for an authentication failure) + errorObject: errorObject + } + ); + } + } + + if (typeof options !== 'object') { + // getSession(): 'options' must be of type 'object' + throw new Error(progress.data._getMsgText( + "jsdoMSG503", + "getSession()", + "options", + "object" + )); + } + + if (typeof options.loginCallback !== 'undefined' && + typeof options.loginCallback !== 'function') { + // getSession(): 'options.loginCallback' must be of type 'function' + throw new Error(progress.data._getMsgText( + "jsdoMSG503", + "getSession()", + "options.loginCallback", + "function" + )); + } + + // Create the AuthenticationProvider and let it handle the argument parsing + try { + // If authenticationURI is not set, use serviceURI (except for SSO) + // Note: the test will of course catch any value that evaluates to false, not just undefined or + // null (which are the main concern), but that's probably OK + if (options.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { + if (!options.authenticationURI || !options.authProviderAuthenticationModel) { + // "progress.data.getSession: If the getSession method is passed AUTH_TYPE_SSO as + // the authenticationModel, it must also be passed an authenticationURI and an + // authProviderAuthenticationModel." + throw new Error(progress.data._getMsgText("jsdoMSG509")); + } + } + + if (options.authenticationURI) { + authProviderInitObject.uri = options.authenticationURI; + authProviderInitObject.authenticationModel = options.authProviderAuthenticationModel; + + // if auth uri has been passed, there must be an authProviderAuthenticationModel + if (typeof authProviderInitObject.authenticationModel !== "string") { + // JSDOSession: The 'object' parameter passed to the 'getSession' function + // has an invalid value for the 'authProviderAuthenticationModel' property. + throw new Error(progress.data._getMsgText( + "jsdoMSG502", + "progress.data.getSession", + "object", + "getSession", + "authProviderAuthenticationModel" + )); + } + } else { + authProviderInitObject.uri = options.serviceURI; + authProviderInitObject.authenticationModel = options.authenticationModel; + } + + authProvider = new progress.data.AuthenticationProvider(authProviderInitObject); + options.authProvider = authProvider; + + if (authProvider.hasClientCredentials()) { + loginHandler(authProvider); + } else { + // If model is anon, just log in. + if (authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { + authProvider.login() + .then(loginHandler, sessionRejectHandler); + } else { + // We need to log-in with credentials. + callLogin(authProvider); + } + } + } catch (error) { + // throw error; + sessionRejectHandler( + null, + progress.data.Session.GENERAL_FAILURE, + { + errorObject: error + } + ); + } + + return deferred.promise(); + }; + + progress.data.invalidateAllSessions = function () { + var jsdosession, + key, + deferred = new progress.util.Deferred(), + jsdosessions = progress.data.ServicesManager._jsdosessions, + invalidatePromises = []; + + try { + for (key in jsdosessions) { + if (jsdosessions.hasOwnProperty(key)) { + jsdosession = jsdosessions[key]; + + invalidatePromises.push(jsdosession.invalidate()); + } + } + + progress.util.Deferred.when(invalidatePromises) + .then(function () { + deferred.resolve(progress.data.Session.SUCCESS); + }, function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.reject(progress.data.Session.GENERAL_FAILURE, info); + }); + + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + // Using beautiful jquery shenanigans + return deferred.promise(); + }; + +})(); + +if (typeof exports !== "undefined") { + exports.progress = progress; +} + + +/* +progress.auth.js Version: 4.4.0-3 + +Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ + +(function () { + + "use strict"; // note that this makes JSLint complain if you use arguments[x] + + /*global progress : true*/ + /*global storage, XMLHttpRequest*/ + + /* define these if not defined yet - they may already be defined if + progress.js was included first */ + if (typeof progress === "undefined") { + progress = {}; + } + if (typeof progress.data === "undefined") { + progress.data = {}; + } + + // This is really more along the lines of a Factory method in that it explicitly creates an object + // and returns it based on the the authModel parameter (rather than following the default JS + // pattern of adding properties to the "this" object created for it and passed in by the runtime). + // NOTE: If we support multiple AuthenticationProviders that get different tokens from the same + // server, we may need to add a "name" property to the initObject to use as a storage key + + progress.data.AuthenticationProvider = function AuthenticationProvider (initObject) { + var authProv, + authModel, + uri; + + // process constructor arguments + if (typeof initObject === 'object') { + + // these 2 calls throw an appropriate error if the check doesn't pass + this._checkStringArg( + "constructor", + initObject.authenticationModel, + "initObject.authenticationModel", + "initObject.authenticationModel" + ); + + this._checkStringArg( + "constructor", + initObject.uri, + "init-object.uri", + "init-object.uri" + ); + } else { + // AuthenticationProvider: Invalid signature for constructor. The init-object argument + // was missing or invalid. + throw new Error(progress.data._getMsgText( + "jsdoMSG033", + "AuthenticationProvider", + "the constructor", + "The init-object argument was missing or invalid." + )); + } + + authModel = initObject.authenticationModel.toLowerCase(); + switch (authModel) { + case progress.data.Session.AUTH_TYPE_ANON: + this._initialize(initObject.uri, progress.data.Session.AUTH_TYPE_ANON, + {"_loginURI": progress.data.AuthenticationProvider._homeLoginURIBase}); + authProv = this; + break; + case progress.data.Session.AUTH_TYPE_BASIC: + authProv = new progress.data.AuthenticationProviderBasic(initObject.uri); + break; + case progress.data.Session.AUTH_TYPE_FORM: + authProv = new progress.data.AuthenticationProviderForm(initObject.uri); + break; + case progress.data.Session.AUTH_TYPE_FORM_SSO: + authProv = new progress.data.AuthenticationProviderSSO(initObject.uri); + break; + default: + // AuthenticationProvider: The 'init-object' parameter passed to the 'constructor' function + // has an invalid value for the 'authenticationModel' property. + throw new Error(progress.data._getMsgText( + "jsdoMSG502", + "AuthenticationProvider", + "init-object", + "constructor", + "authenticationModel" + )); + //break; + } + + return authProv; + }; + + + // ADD METHODS TO THE AuthenticationProvider PROTOYPE + + // GENERIC IMPLEMENTATION FOR login METHOD THAT THE API IMPLEMENTATIONS OF login CAN CALL + // (technically, they don't override it, they each have small login methods that call this) + progress.data.AuthenticationProvider.prototype._loginProto = + function (sendParam) { + var deferred = new progress.util.Deferred(), + xhr, + uriForRequest, + header, + that = this; + + try { + if (this._loggedIn) { + // "The login method was not executed because the AuthenticationProvider is + // already logged in." + throw new Error(progress.data._getMsgText("jsdoMSG051", "AuthenticationProvider")); + } + + xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + // process the response from the Web application + that._processLoginResult(xhr, deferred); + } + }; + + if (progress.data.Session._useTimeStamp) { + uriForRequest = progress.data.Session._addTimeStampToURL(this._loginURI); + } else { + uriForRequest = this._loginURI; + } + + this._openLoginRequest(xhr, uriForRequest); + + // We specify application/json for the response so that, if a bad request is sent, an + // OE Web application will directly send back a 401 with error info in the body as JSON. + // So we force the accept header to application/json because if we make an anonymous + // request to a FORM/BASIC backend, it might redirect us to a login page since we have + // no credentials. And since we can technically access JUST the login page, the XHR + // will identify it as SUCCESS. If we specify "application/json", no redirects will + // happen, just a plain old "401 GET OUTTA HERE" code. + xhr.setRequestHeader("Accept", "application/json"); + + xhr.send(sendParam); + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + + + // PUBLIC METHODS (and their "helpers") (documented as part of the JSDO library API) + + // login API method -- just a shell that calls loginProto + progress.data.AuthenticationProvider.prototype.login = function () { + return this._loginProto(); + }; + + // HELPER FOR login METHOD, PROBABLY OVERRIDDEN IN MOST CONSTRUCTORS + progress.data.AuthenticationProvider.prototype._openLoginRequest = function (xhr, uri) { + xhr.open('GET', uri, true); + progress.data.Session._setNoCacheHeaders(xhr); + }; + + // HELPER FOR login METHOD, PROBABLY OVERRIDDEN IN MOST CONSTRUCTORS + progress.data.AuthenticationProvider.prototype._processLoginResult = function (xhr, deferred) { + var result; + + if (xhr.status === 200) { + // Need to set loggedIn now so we can call logout from here if there's an + // error processing the response (e.g., authentication succeeded but we didn't get a + // token for some reason) + this._loggedIn = true; + this._storeInfo(); + result = progress.data.Session.SUCCESS; + } else if (xhr.status === 401) { + // If this is Anonymous, somebody gave us the wrong authenticationModel! + result = progress.data.Session.AUTHENTICATION_FAILURE; + } else { + result = progress.data.Session.GENERAL_FAILURE; + } + + this._settlePromise(deferred, result, {"xhr": xhr}); + }; + + + // logout API METHOD -- SOME CONSTRUCTORS OR PROTOTYPES WILL OVERRIDE THIS + progress.data.AuthenticationProvider.prototype.logout = function () { + var deferred = new progress.util.Deferred(); + + try { + this._reset(); + deferred.resolve(this, progress.data.Session.SUCCESS, {}); + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + // hasClientCredentials API METHOD -- PROBABLY ONLY OVERRIDDEN BY SSO + progress.data.AuthenticationProvider.prototype.hasClientCredentials = function () { + return this._loggedIn; + }; + + // hasRefreshToken API METHOD -- returns false for all AutghenticationProvider types except SSO, + // which overrides it + progress.data.AuthenticationProvider.prototype.hasRefreshToken = function () { + return false; + }; + + // QUASI-PUBLIC METHOD + + // general-purpose method for opening requests (mainly for jsdo calls) + // This method is not part of the documented API that a developer would + // program against, but it gets used in a validation check by the JSDOSESSION, because the + // JSDOSESSION code expects it to be present. The point here is that if a developer were to + // create their own AuthenticationProvider object, it would need to include this method + // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change + // it to use promises + progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize = function (xhr, + verb, + uri, + async, + callback) { + var errorObject; + + if (this.hasClientCredentials()) { + xhr.open(verb, uri, async); + + // Check out why we do this in _loginProto + xhr.setRequestHeader("Accept", "application/json"); + callback(xhr); + } else { + // AuthenticationProvider: The AuthenticationProvider is not managing valid credentials. + errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); + callback(errorObject); + } + }; + + // GENERAL PURPOSE "INTERNAL" METHODS, NOT RELATED TO SPECIFIC API ELEMENTS + // (not documented, intended for use only within the JSDO library) + + // General purpose method for initializing an object + progress.data.AuthenticationProvider.prototype._initialize = function (uriParam, + authModel, + targetURIs) { + var tempURI, + target; + + Object.defineProperty(this, 'uri', + { + get: function () { + return this._uri; + }, + enumerable: true + }); + + Object.defineProperty(this, 'authenticationModel', + { + get: function () { + return this._authenticationModel; + }, + enumerable: true + }); + + + // get rid of trailing '/' because appending service url that starts with '/' + // will cause request failures + if (uriParam[uriParam.length - 1] === "/") { + tempURI = uriParam.substring(0, uriParam.length - 1); + } else { + tempURI = uriParam; + } + + // take the modified authentication uri and prepend it to all of the targets passed + // in. E.g., the targetURIs object will include a "loginURI" property that has the + // uri segment which is to be added to the auth uri for logging in + for (target in targetURIs) { + if (targetURIs.hasOwnProperty(target)) { + this[target] = tempURI + targetURIs[target]; + } + } + + this._authenticationModel = authModel; + this._uri = uriParam; // keep the uri property the same as what was passed in + + this._loggedIn = false; + this._dataKeys = { + uri: ".uri", + loggedIn: ".loggedIn" + }; + + // future: for page refresh -- storeSessionInfo("authenticationModel", authenticationModel); + + if (typeof sessionStorage === "undefined") { + // "AuthenticationProvider: No support for sessionStorage." + throw new Error(progress.data._getMsgText("jsdoMSG126", + "AuthenticationProvider", + "sessionStorage")); + } + // if you switch to a different type of storage, change the error message argument above + this._storage = sessionStorage; + + // maybe should come up with something more intelligent than this + this._storageKey = this._uri; // or name + this._dataKeys.uri = this._storageKey + this._dataKeys.uri; + this._dataKeys.loggedIn = this._storageKey + this._dataKeys.loggedIn; + + if (this._retrieveLoggedIn()) { + this._loggedIn = true; + } + }; + + + // Store data in storage with the uri as the key. setItem() throws. (Should add an + // option for the developer to specify the key) + // a "QuotaExceededError" error if there is insufficient storage space or + // "the user has disabled storage for the site" (Web storage spec at WHATWG) + progress.data.AuthenticationProvider.prototype._storeInfo = function () { + this._storage.setItem(this._dataKeys.uri, JSON.stringify(this._uri)); + this._storage.setItem(this._dataKeys.loggedIn, JSON.stringify(this._loggedIn)); + }; + + // Get a piece of state data from storage. Returns null if the item isn't in storage + progress.data.AuthenticationProvider.prototype._retrieveInfoItem = function (propName) { + var jsonStr = this._storage.getItem(propName), + value = null; + + if (jsonStr !== null) { + try { + value = JSON.parse(jsonStr); + } catch (e) { + value = null; + } + } + return value; + }; + + // Get an AuthenticationProvider's uri from storage + progress.data.AuthenticationProvider.prototype._retrieveURI = function () { + return this._retrieveInfoItem(this._dataKeys.uri); + }; + + // Get an AuthenticationProvider's logon status from storage + progress.data.AuthenticationProvider.prototype._retrieveLoggedIn = function () { + return this._retrieveInfoItem(this._dataKeys.loggedIn); + }; + + // Clear the persistent storage used by an AuthenticationProvider + progress.data.AuthenticationProvider.prototype._clearInfo = function (info) { + this._storage.removeItem(this._dataKeys.uri); + this._storage.removeItem(this._dataKeys.loggedIn); + }; + + // Put the internal state back to where it is when the constructor finishes + // running (so the authentication model and uri are not changed, but other data is reset. + // and storage is cleared out) + progress.data.AuthenticationProvider.prototype._reset = function () { + this._clearInfo(); + this._loggedIn = false; + }; + + + // General purpose utility method, no overrides expected + progress.data.AuthenticationProvider.prototype._settlePromise = function (deferred, result, info) { + if (result === progress.data.Session.SUCCESS) { + deferred.resolve(this, result, info); + } else { + deferred.reject(this, result, info); + } + }; + + // General purpose utility method, no overrides expected + progress.data.AuthenticationProvider.prototype._checkStringArg = function (fnName, + argToCheck, + argPosition, + argName) { + // TODO: ? distinguish between undefined (so we can give developer a clue that they + // may be missing a property) and defined but wrong type + if (typeof argToCheck !== "string") { + // AuthenticationProvider: Argument {param-position} must be of type string in {fnName} call. + throw new Error(progress.data._getMsgText( + "jsdoMSG121", + "AuthenticationProvider", + argPosition, + "string", + fnName + )); + } else if (argToCheck.length === 0) { + // AuthenticationProvider: {param-name} cannot be an empty string. + throw new Error(progress.data._getMsgText( + "jsdoMSG501", + "AuthenticationProvider", + argName, + fnName + )); + } + }; + + + // "STATIC" PROPERTIES AND METHODS -- not on the prototype -- you cannot access these through an + // object created by "new" --- they are properties of the AuthenticationProvider constructor function + + // Takes an XHR as an input. If the xhr status is 401 (Unauthorized), determines whether + // the auth failure was due to an expired token. Returns progress.data.Session.EXPIRED_TOKEN + // if it was, progress.data.Session.AUTHENTICATION_FAILURE if it wasn't, null if the xhr status wasn't 401 + progress.data.AuthenticationProvider._getAuthFailureReason = function (xhr) { + var contentType, + jsonObject, + result = progress.data.Session.AUTHENTICATION_FAILURE; + + if (xhr.status === 401) { + contentType = xhr.getResponseHeader("Content-Type"); + if (contentType && (contentType.indexOf("application/json") > -1) && xhr.responseText) { + jsonObject = JSON.parse(xhr.responseText); + if (jsonObject.error === "sso.token.expired_token") { + result = progress.data.Session.EXPIRED_TOKEN; + } + } + } else { + result = null; + } + return result; + }; + + Object.defineProperty(progress.data.AuthenticationProvider, '_homeLoginURIBase', { + value: "/static/home.html", + enumerable: true + }); + Object.defineProperty(progress.data.AuthenticationProvider, '_springLoginURIBase', { + value: "/static/auth/j_spring_security_check", + enumerable: true + }); + Object.defineProperty(progress.data.AuthenticationProvider, '_springLogoutURIBase', { + value: "/static/auth/j_spring_security_logout", + enumerable: true + }); + Object.defineProperty(progress.data.AuthenticationProvider, '_springFormTokenLoginURIBase', { + value: progress.data.AuthenticationProvider._springLoginURIBase + "?OECP=yes", + enumerable: true + }); + Object.defineProperty(progress.data.AuthenticationProvider, '_springFormTokenRefreshURIBase', { + value: "/static/auth/token?op=refresh", + enumerable: true + }); + +}()); + + +/* +progress.auth.basic.js Version: 4.4.0-3 + +Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ + +(function () { + + "use strict"; // note that this makes JSLint complain if you use arguments[x] + + /*global progress : true*/ + /*global storage, XMLHttpRequest, msg, btoa*/ + + progress.data.AuthenticationProviderBasic = function (uri) { + var defaultiOSBasicAuthTimeout, // TO DO: need to implement the use of this + userName = null, + password = null, + fn; + + // process constructor arguments, etc. + this._initialize(uri, progress.data.Session.AUTH_TYPE_BASIC, + {"_loginURI": progress.data.AuthenticationProvider._homeLoginURIBase}); + + // We don't support refresh for BASIC so get rid of anything in sessionStorage + // Remember to take this out when we support refresh for BASIC. + this._reset(); + + // PRIVATE FUNCTIONS + + // from http://coderseye.com/2007/how-to-do-http-basic-auth-in-ajax.html + function make_basic_auth_header(user, pw) { + var tok = user + ':' + pw, + hash = btoa(tok); + return "Basic " + hash; + } + + // "INTERNAL" METHODS + // Override the protoype's method but call it from within the override + // (Define the override here in the constructor so it has access to instance variables) + this._reset = function () { + userName = null; + password = null; + progress.data.AuthenticationProviderBasic.prototype._reset.apply(this); + }; + + // Override the protoype's method (this method does not invoke the prototype's copy) + // (Define the override here in the constructor so it has access to instance variables) + this._openLoginRequest = function (xhr, uri) { + var auth; + + xhr.open("GET", uri, true); // but see comments below inside the "if userName" + // may have to go with that approach + + if (userName) { + + // set Authorization header + auth = make_basic_auth_header(userName, password); + xhr.setRequestHeader('Authorization', auth); + } + + progress.data.Session._setNoCacheHeaders(xhr); + }; + + // Override the protoype's method but call it from within the override + // (Define the override here in the constructor so it has access to instance variables) + this._processLoginResult = function _basic_processLoginResult(xhr, deferred) { + progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply( + this, + [xhr, deferred] + ); + if (!this._loggedIn) { + // login failed, clear the credentials + userName = null; + password = null; + } + }; + + // Override the protoype's method (this method does not invoke the prototype's copy, but + // calls a prototype general-purpose login method) + // (Define the override here in the constructor so it has access to instance variables) + this.login = function (userNameParam, passwordParam) { + // these throw if the check fails (may want to do something more elegant) + this._checkStringArg("login", userNameParam, 1, "userName"); + this._checkStringArg("login", passwordParam, 2, "password"); + + userName = userNameParam; + password = passwordParam; + return this._loginProto(); + }; + + // Override the protoype's method (this method does not invoke the prototype's copy) + // (Define the override here in the constructor so it has access to instance variables) + // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change + // it to use promises + this._openRequestAndAuthorize = function (xhr, verb, uri, async, callback) { + var auth, + errorObject; + + if (this.hasClientCredentials()) { + + xhr.open(verb, uri, async); // but see comments below inside the "if userName" + // may have to go with that approach + + if (userName) { + + // set Authorization header + auth = make_basic_auth_header(userName, password); + xhr.setRequestHeader('Authorization', auth); + } + + progress.data.Session._setNoCacheHeaders(xhr); + callback(xhr); + } else { + // AuthenticationProvider: The AuthenticationProvider is not managing valid credentials. + errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); + callback(errorObject); + } + }; + }; + + + // Give this constructor the prototype from the "base" AuthenticationProvider + // Do this indirectly by way of an intermediate object so changes to the prototype ("method overrides") + // don't affect other types of AuthenticationProviders that use the prototype) + function BasicProxy() {} + BasicProxy.prototype = progress.data.AuthenticationProvider.prototype; + progress.data.AuthenticationProviderBasic.prototype = new BasicProxy(); + + // Reset the prototype's constructor property so it points to AuthenticationProviderForm rather than + // the one that it just inherited (this is pretty much irrelevant though - the correct constructor + // will get called regardless) + progress.data.AuthenticationProviderBasic.prototype.constructor = + progress.data.AuthenticationProviderBasic; + + + // OVERRIDE METHODS ON PROTOTYPE IF NECESSARY AND POSSIBLE + // (SOME METHODS ARE OVERRIDDEN IN THE CONSTRUCTOR BECAUSE THEY NEED ACCESS TO INSTANCE VARIABLES) + + // NOTE: There are no overrides of the following methods (either here or in the constructor). + // This object uses these methods from the original prototype(i.e., the implementations from the + // AuthenticationProvider object): + // logout (API method) + // hasClientCredentials (API method) + +}()); + +/* +progress.auth.form.js Version: 5.0.0 + +Copyright (c) 2016-2018 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ + +(function () { + + "use strict"; // note that this makes JSLint complain if you use arguments[x] + + /*global progress : true*/ + /*global XMLHttpRequest*/ + + var fn; + + progress.data.AuthenticationProviderForm = function (uri) { + + // PROCESS CONSTRUCTOR ARGUMENTS, CREATE API PROPERTIES, ETC. + this._initialize(uri, progress.data.Session.AUTH_TYPE_FORM, + {"_loginURI": progress.data.AuthenticationProvider._springLoginURIBase, + "_logoutURI": progress.data.AuthenticationProvider._springLogoutURIBase + }); + }; + + // Start by giving this constructor the prototype from the "base" AuthenticationProvider + // Do this indirectly by way of an intermediate object so changes to the prototype ("method overrides") + // don't affect other types of AuthenticationProviders that use the prototype) + function FormProxy() {} + FormProxy.prototype = progress.data.AuthenticationProvider.prototype; + progress.data.AuthenticationProviderForm.prototype = + new FormProxy(); + + // Reset the prototype's constructor property so it points to AuthenticationProviderForm rather than + // the one that it just inherited (this is pretty much irrelevant though - the correct constructor + // will get called regardless) + progress.data.AuthenticationProviderForm.prototype.constructor = + progress.data.AuthenticationProviderForm; + + + // OVERRIDE THE "BASE" AuthenticationProvider PROTOYPE METHODS WHERE NECESSARY + + // All of the methods defined here as part of the AuthenticationProviderForm prototype (instead + // of in the AuthenticationProviderForm constructor) can be inherited by the AuthenticationProviderSSO + // prototype without incurring the overhead of creating a full-blown instance of + // AuthenticationProviderForm to serve as the prototype for the SSO constructor. + // Note: if it turns out that any of the methods defined this way need access to internal variables + // of an AuthenticationProviderForm object, they'll need to be moved out of here. + + // NOTE: There are no overrides of the following methods (either here or in the constructor). + // This object uses these methods from the original prototype(i.e., the implementations from the + // AuthenticationProvider object): + // _reset (general-purpose helper) + // hasClientCredentials (API method) + // _processLoginResult (API helper method) + + + // login API METHOD AND "HELPERS" + progress.data.AuthenticationProviderForm.prototype.login = function (userNameParam, passwordParam) { + var deferred = new progress.util.Deferred(), + xhr, + that = this; + + // these throw if the check fails (may want to do something more elegant) + this._checkStringArg("login", userNameParam, 1, "userName"); + this._checkStringArg("login", passwordParam, 2, "password"); + + return this._loginProto("j_username=" + encodeURIComponent(userNameParam) + + "&j_password=" + encodeURIComponent(passwordParam) + "&submit=Submit"); + }; + + // login helper + // Override the protoype's method (this method does not invoke the prototype's copy) + // By defining this here, we can have the SSO AuthenticationProvider use it without + // incurring the overhead of creating a Form instance as the prototype for the SSO constructor + progress.data.AuthenticationProviderForm.prototype._openLoginRequest = function (xhr, uri) { + + xhr.open('POST', uri, true); + + xhr.setRequestHeader("Cache-Control", "max-age=0"); + xhr.setRequestHeader("Pragma", "no-cache"); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + xhr.withCredentials = true; + + }; + + // logout API METHOD AND "HELPERS" + // Override the prototype method and do not call it because the Anonymous AuthenticationProvider + // doesn't make a server call for logout + // (But this method does do what the SSO AuthenticationProvider needs, so keep it on + // the Form prototype if possible) + progress.data.AuthenticationProviderForm.prototype.logout = function () { + var deferred = new progress.util.Deferred(), + xhr, + that = this; + + try { + if (!this._loggedIn) { + // logout is regarded as a success if the AuthenticationProvider isn't logged in + deferred.resolve(this, progress.data.Session.SUCCESS, {}); + } else { + xhr = new XMLHttpRequest(); + this._openLogoutRequest(xhr); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + // process the response from the Web application + that._processLogoutResult(xhr, deferred); + } + }; + + xhr.send(); + } + + // Unconditionally reset --- even if the actual server request fails, we still want + // to reset this AuthenticationProvider so it can try a login if desired. + // We also reset even in the case where we're not logged in, just in case. + // (In the future we can add a parameter that controls whether the reinit is unconditional, + // if the developer wants to log out of the token server session but contnue to use the token) + this._reset(); + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + // logout helper (there is no version defined in the original protoype) + progress.data.AuthenticationProviderForm.prototype._openLogoutRequest = function (xhr) { + xhr.open('GET', this._logoutURI, true); + xhr.setRequestHeader("Cache-Control", "max-age=0"); + xhr.withCredentials = true; + xhr.setRequestHeader("Accept", "application/json"); + }; + + // logout helper (there is no version defined in the original protoype) + progress.data.AuthenticationProviderForm.prototype._processLogoutResult = function (xhr, deferred) { + var result; + + if (xhr.status === 200) { + result = progress.data.Session.SUCCESS; + } else if (xhr.status === 401) { + // treat this as a success because the most likely cause is that the session expired + // (Note that an 11.7 OE PAS Web application will return a 200 if we log out with + // an expired JSESSIONID, so this code may not be executed anyway) + result = progress.data.Session.SUCCESS; + } else { + result = progress.data.Session.GENERAL_FAILURE; + } + + this._settlePromise(deferred, result, {"xhr": xhr}); + + }; + + // GENERAL PURPOSE METHOD FOR OPENING REQUESTS (MAINLY FOR JSDO CALLS) + // Override the protoype's method but call it from within the override + // Since the override is being put into the constructor's prototype, and + // since it calls the overridden method which had originally been in the prototype, + // we add a "_super" property to the overriding method so it can still access the original method + // (We could just call that method directly in here like this: + // progress.data.AuthenticationProviderProto.prototype._openRequestAndAuthorize + // but if we ever change the place where we get the initial protoype for + // AuthenticationProviderForm from, we would need to remember to change that here. + // The use of the _super property will handle that automatically, plus it was more fun + // to do it this way) + // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change + // it to use promises + fn = progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize; + progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize = + function (xhr, verb, uri, async, callback) { + + function afterSuper(errorObject) { + if (errorObject instanceof Error) { + callback(errorObject); + } else { + xhr.withCredentials = true; + callback(xhr); + } + } + + try { + progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply( + this, + [xhr, verb, uri, async, afterSuper] + ); + } catch (e) { + callback(e); + } + }; + progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super = fn; + + +}()); + +/* +progress.auth.sso.js Version: 4.4.0-3 + +Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + */ + +(function () { + + "use strict"; // note that this makes JSLint complain if you use arguments[x] + + /*global progress : true*/ + + var fn; + + // ADD AN OPTIONS PARAM THAT CAN INCLUDE A NAME FOR PAGE REFRESH? + progress.data.AuthenticationProviderSSO = function (uri) { + var that = this, + // SSO specific + _automaticTokenRefresh, + temp, + ssoTokenInfo = null, + tokenDataKeys = { // SSO specific + token: ".access_token", + refreshToken: ".refresh_token", + tokenType: ".token_type", + expiration: ".expires_in", + accessTokenExpiration: ".accessTokenExpiration" + }; + + // PRIVATE FUNCTIONS + // (The constructor uses local variables and functions mainly to try to protect the token + // information as much as possible. A few could probably be defined as properties/methods, but + // there's currently no need for that because the AuthenticationProvider API has no objects + // that inherit from AuthenticationProviderSSO.) + + // Store the given token with the uri as the key. setItem() throws + // a "QuotaExceededError" error if there is insufficient storage space or + // "the user has disabled storage for the site" (Web storage spec at WHATWG) + function storeTokenInfo(info) { + var date, + accessTokenExpiration; + + if (info.access_token.length) { + that._storage.setItem(tokenDataKeys.token, JSON.stringify(info.access_token)); + } + if (info.refresh_token.length) { + that._storage.setItem(tokenDataKeys.refreshToken, JSON.stringify(info.refresh_token)); + // The time given for the access token's expiration is in seconds. We transform it + // into milliseconds and add it to date.getTime() for a more standard format. + date = new Date(); + // This should probably be renamed accessTokenRefreshThreshold + accessTokenExpiration = date.getTime() + (info.expires_in * 1000 * 0.75); + that._storage.setItem(tokenDataKeys.accessTokenExpiration, JSON.stringify(accessTokenExpiration)); + } else { + // if there is no refresh token, remove any existing one. This handles the case where + // we got a new token via refresh, but now we're not being given any more refresh tokens + that._storage.removeItem(tokenDataKeys.refreshToken); + that._storage.removeItem(tokenDataKeys.accessTokenExpiration); + } + that._storage.setItem(tokenDataKeys.tokenType, JSON.stringify(info.token_type)); + that._storage.setItem(tokenDataKeys.expiration, JSON.stringify(info.expires_in)); + } + + // get one of the pieces of data related to tokens from storage (could be the token itself, or + // the refresh token, expiration info, etc.). Returns null if the item isn't in storage + function retrieveTokenProperty(propName) { + var jsonStr = that._storage.getItem(propName), + value = null; + + if (jsonStr !== null) { + try { + value = JSON.parse(jsonStr); + } catch (e) { + value = null; + } + } + return value; + } + + function retrieveToken() { + return retrieveTokenProperty(tokenDataKeys.token); + } + + function retrieveRefreshToken() { + return retrieveTokenProperty(tokenDataKeys.refreshToken); + } + + function retrieveAccessTokenExpiration() { + return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration); + } + + function retrieveTokenType() { + return retrieveTokenProperty(tokenDataKeys.tokenType); + } + + // This is going to be hardcoded for now. This can very + // possibly change in the future if we decide to expose + // the token to the user. + function getToken() { + return retrieveToken(); + } + + function retrieveExpiration() { + return retrieveTokenProperty(tokenDataKeys.expiration); + } + + function clearTokenInfo(info) { + that._storage.removeItem(tokenDataKeys.token); + that._storage.removeItem(tokenDataKeys.refreshToken); + that._storage.removeItem(tokenDataKeys.tokenType); + that._storage.removeItem(tokenDataKeys.expiration); + that._storage.removeItem(tokenDataKeys.accessTokenExpiration); + } + + // function is SSO specific + function openRefreshRequest(xhr) { + xhr.open('POST', that._refreshURI, true); + xhr.setRequestHeader("Cache-Control", "max-age=0"); + xhr.withCredentials = true; + xhr.setRequestHeader("Content-Type", "application/json"); + xhr.setRequestHeader("Accept", "application/json"); + } + + // function is SSO specific + function processRefreshResult(xhr, deferred) { + var errorObject, + result, + ssoTokenJSON; + + if (xhr.status === 200) { + // get token and store it; if that goes well, resolve the promise, otherwise reject it + try { + ssoTokenInfo = JSON.parse(xhr.responseText); + + if (ssoTokenInfo.access_token) { + storeTokenInfo(ssoTokenInfo); + // got the token info, its access_token has a value, and storeTokenInfo() + // didn't thrown an error, so call this a success + result = progress.data.Session.SUCCESS; + } else { + result = progress.data.Session.GENERAL_FAILURE; + // {1}: Unexpected error calling refresh: {error-string} + // ( No token returned from server) + errorObject = new Error(progress.data._getMsgText( + "jsdoMSG049", + "AuthenticationProvider", + "refresh", + progress.data._getMsgText("jsdoMSG050") + )); + } + } catch (ex) { + result = progress.data.Session.GENERAL_FAILURE; + // {1}: Unexpected error calling refresh: {error-string} + // (error could be thrown from storeTokenInfo when it calls setItem()) + errorObject = new Error(progress.data._getMsgText( + "jsdoMSG049", + "AuthenticationProvider", + "refresh", + ex.message + )); + } + } else if (xhr.status === 401) { + that._reset(); // treat authentication failure as the equivalent of a logout + result = progress.data.Session.AUTHENTICATION_FAILURE; + } else { + result = progress.data.Session.GENERAL_FAILURE; + } + + that._settlePromise(deferred, result, {"xhr": xhr, + "errorObject": errorObject}); // OK if undefined + } + + + this._processLoginResult = function (xhr, deferred) { + var errorObject, + result, + ssoTokenJSON; + + if (xhr.status === 200) { + // Need to set loggedIn now so we can call logout from here if there's an + // error processing the response (e.g., authentication succeeded but we didn't get a + // token for some reason) + this._loggedIn = true; + + // get token and store it; if that goes well, resolve the promise, otherwise reject it + try { + ssoTokenInfo = JSON.parse(xhr.responseText); + + if (ssoTokenInfo.access_token) { + storeTokenInfo(ssoTokenInfo); + // got the token info, its access_token has a value, and storeTokenInfo() + // didn't throw an error, so call this a success + result = progress.data.Session.SUCCESS; + } else { + result = progress.data.Session.GENERAL_FAILURE; + // {1}: Unexpected error calling login: {error-string} + // ( No token returned from server) + errorObject = new Error(progress.data._getMsgText( + "jsdoMSG049", + "AuthenticationProvider", + "login", + progress.data._getMsgText("jsdoMSG050") + )); + } + } catch (ex) { + result = progress.data.Session.GENERAL_FAILURE; + // {1}: Unexpected error calling login: {error-string} + // (error could be thrown from storeTokenInfo when it calls setItem()) + errorObject = new Error(progress.data._getMsgText( + "jsdoMSG049", + "AuthenticationProvider", + "login", + ex.message + )); + } + + // log out if there was an error processing the response so the app can try to log in again + if (result !== progress.data.Session.SUCCESS) { + // call logout, but ignore its outcome -- just tell caller that login failed + var callback = function (params) { + params = progress.util.Deferred.getParamObject(params); + params.provider._settlePromise(deferred, result, {"xhr": xhr, + "errorObject": errorObject}); + }; + // finally + this.logout() + .then(callback, callback); + return; // so we don't execute the reject below, which could invoke the fail handler + // before we're done with the logout + } + + } else if (xhr.status === 401) { + result = progress.data.Session.AUTHENTICATION_FAILURE; + } else { + result = progress.data.Session.GENERAL_FAILURE; + } + + this._settlePromise(deferred, result, {"xhr": xhr}); + }; + + + // Override the protoype's method but call it from within the override. (Define the override + // here in the constructor so it has access to the internal function and variable) + this._reset = function () { + progress.data.AuthenticationProviderSSO.prototype._reset.apply(this); + clearTokenInfo(); + ssoTokenInfo = null; + }; + + + // Override the protoype's method but call it from within the override. (Define the override + // here in the constructor so it has access to the internal function getToken() ) + // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change + // it to use promises + this._openRequestAndAuthorize = function (xhr, + verb, + uri, + async, + callback) { + var that = this, + date, + errorObject; + + function afterRefreshCheck(provider, result, info) { + // if refresh failed because of auth failure, we will have gotten rid of the + // token and reset the auth provider + if (result === progress.data.Session.AUTHENTICATION_FAILURE) { + callback(new Error(progress.data._getMsgText("jsdoMSG060"))); + } else { + // We've done the refresh check (and possible refresh) for SSO, now execute + // the base _openRequest... method, which does common things for Form-based + progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply( + that, + [xhr, verb, uri, async, function (errorObject) { + if (errorObject instanceof Error) { + callback(errorObject); + } else { + xhr.setRequestHeader('Authorization', "oecp " + getToken()); + callback(xhr); + } + }] + ); + } + } + + if (this.hasClientCredentials()) { + // Every token given has an expiration "hint". If the token's lifespan + // is close to or past that limit, then a refresh is done. + // No matter what the outcome of the refresh, keep in mind we always + // send the original request. + date = new Date(); + if (this.automaticTokenRefresh && + this.hasRefreshToken() && + date.getTime() > retrieveAccessTokenExpiration()) { + try { + var callback = function (params, result, info) { + params = progress.util.Deferred.getParamObject(params, result, info); + afterRefreshCheck(params.provider, params.result, params.info); + }; + // finally + this.refresh() + .then(callback, callback); + } catch (e) { + callback(e); + } + } else { + afterRefreshCheck(this, progress.data.Session.SUCCESS, null); + } + } else { + // This message is SSO specific, unless we can come up with a more general message + // JSDOSession: The AuthenticationProvider needs to be managing a valid token. + errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); + callback(errorObject); + } + }; + + + // API METHODS + + // override the prototype's hasClientCredentials method + this.hasClientCredentials = function () { + return (retrieveToken() === null ? false : true); + }; + + + this.refresh = function () { + var deferred = new progress.util.Deferred(), + xhr; + + try { + if (!this._loggedIn) { + // "The refresh method was not executed because the AuthenticationProvider is not logged in." + throw new Error(progress.data._getMsgText("jsdoMSG053", "AuthenticationProvider", "refresh")); + } + + if (!this.hasRefreshToken()) { + // "Token refresh was not executed because the AuthenticationProvider does not have a + // refresh token." + throw new Error(progress.data._getMsgText("jsdoMSG054", "AuthenticationProvider")); + } + + xhr = new XMLHttpRequest(); + openRefreshRequest(xhr); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + // process the response from the Web application + processRefreshResult(xhr, deferred); + } + }; + + xhr.send('{"token_type":"' + retrieveTokenType() + '","refresh_token":"' + + retrieveRefreshToken() + '"}'); + } catch (error) { + if (progress.util.Deferred.useJQueryPromises) { + throw error; + } else { + deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { + errorObject: error + }); + } + } + return deferred.promise(); + }; + + + this.hasRefreshToken = function () { + return (retrieveRefreshToken() === null ? false : true); + }; + + + // PROCESS CONSTRUCTOR ARGUMENTS, CREATE API PROPERTIES, ETC. + this._initialize(uri, + progress.data.Session.AUTH_TYPE_FORM_SSO, + {"_loginURI": progress.data.AuthenticationProvider._springFormTokenLoginURIBase, + "_logoutURI": progress.data.AuthenticationProvider._springLogoutURIBase, + "_refreshURI": progress.data.AuthenticationProvider._springFormTokenRefreshURIBase + }); + + // in addition to the standard AuthenticationProvider properties, an SSO provider also has a property + // to control automatic token refresh (it's enabled by default on the assumption that developers + // will usually want this) + _automaticTokenRefresh = true; + Object.defineProperty(this, 'automaticTokenRefresh', + { + get: function () { + return _automaticTokenRefresh; + }, + set: function (value) { + if (value === true || value === false) { + _automaticTokenRefresh = value; + } else { + throw new Error(progress.data._getMsgText("jsdoMSG061", + "AuthenticationProvider", + "automaticTokenRefresh")); + } + }, + enumerable: true + }); + + // add the automaticTokenRefresh key to the base class's list of data keys + this._dataKeys.automaticTokenRefresh = this._storageKey + ".automaticTokenRefresh"; + // set it from storage, if it's in storage + temp = this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh); + if (temp === false) { + _automaticTokenRefresh = false; + } + + // We're currently storing the token in storage with the + // uri as the key. This is subject to change later. + tokenDataKeys.token = this._storageKey + tokenDataKeys.token; + tokenDataKeys.refreshToken = this._storageKey + tokenDataKeys.refreshToken; + tokenDataKeys.tokenType = this._storageKey + tokenDataKeys.tokenType; + tokenDataKeys.expiration = this._storageKey + tokenDataKeys.expiration; + tokenDataKeys.accessTokenExpiration = this._storageKey + tokenDataKeys.accessTokenExpiration; + + // NOTE: we rely on the prototype's logic to set this._loggedIn. An alternative could be to + // use the presence of a token to determine that, but it's conceivable that we could be + // logged in but for some reason not have a token (e.g., a token expired, or we logged in + // but the authentication server did not return a token) + if (retrieveToken()) { + this._loggedIn = true; + } + + // END OF CONSTRUCTOR PROCESSING + + }; + // END OF AuthenticationProviderSSO CONSTRUCTOR + + // NOTE: This is used only for the SSO authentication. + // Define the prototype as an instance of an AuthenticationProviderForm object + function SSOProxy() {} + SSOProxy.prototype = progress.data.AuthenticationProviderForm.prototype; + progress.data.AuthenticationProviderSSO.prototype = + new SSOProxy(); + + // But reset the constructor back to the SSO constructor (this is pretty much irrelevant, + // though. The correct constructor would be called anyway. It's mainly for the sake of anyone + // wanting to see what the constructor of an object is (maybe a framework) + progress.data.AuthenticationProviderSSO.prototype.constructor = + progress.data.AuthenticationProviderSSO; + + // override the base AuthenticationProvider _storeInfo and _clearinfo, but keep refs so they + // can be invoked within the overrides + fn = progress.data.AuthenticationProviderSSO.prototype._storeInfo; + progress.data.AuthenticationProviderSSO.prototype._storeInfo = + function () { + progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this); + this._storage.setItem(this._dataKeys.automaticTokenRefresh, + JSON.stringify(this._automaticTokenRefresh)); + }; + progress.data.AuthenticationProviderSSO.prototype._storeInfo._super = fn; + + fn = progress.data.AuthenticationProviderSSO.prototype._clearInfo; + progress.data.AuthenticationProviderSSO.prototype._clearInfo = + function () { + progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this); + this._storage.removeItem(this._dataKeys.automaticTokenRefresh); + }; + progress.data.AuthenticationProviderSSO.prototype._clearInfo._super = fn; + + + + // NOTE: There are no overrides of the following methods (either here or in the constructor). + // This object uses these methods from the original prototype(i.e., the implementations from the + // Auth...Form object) because for an OE SSO token server, the login/logout model is Form (the + // only difference is the use of a special URI query string in the login (see the call to + // initialize() in the SSO constructor (above)): + // login (API method) + // _openLoginRequest (API helper method) + // logout (API method) + // _openLogoutRequest (API helper method) + // _processLogoutResult (API helper method) + + // NOTE: All overrides are implemented in the constructor (rather than adding them to the prototype) + // because they need access to variables and/or functions that are defined in the constructor + // (in an attempt to protect the token info somewhat) + +}()); + diff --git a/index.html b/index.html new file mode 100644 index 0000000..f195391 --- /dev/null +++ b/index.html @@ -0,0 +1,500 @@ + + + + Mocha + + + + +
+
+
    +
  • show failures only
  • +
+
    +
  • passes: 1
  • +
  • pending: 0
  • +
  • failures: 0
  • +
  • duration: 1.3s
  • +
+
+
  • Smoke Tests

    • Ping Test

      • should have a successful connection to the backend39ms

        session.ping().then((object) => {
        +    // If we have successfully logged into the backend, the result
        +    // of our ping() should be true
        +    expect(object.result).to.be.true;
        +}).then(done, done);
+
+ + + diff --git a/package.json b/package.json index fe7f2d3..30713be 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,10 @@ "typings/" ], "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "concurrently \"reload -b -s build/index.html\" \"npm run watch:js\"", + "build:jsdo": "concat -o build/progress.jsdo.js src/progress.util.js src/progress.js src/progress.session.js src/auth/progress.auth.js src/auth/progress.auth.basic.js src/auth/progress.auth.form.js src/auth/progress.auth.sso.js", + "watch:js": "onchange \"src/**/*\" \"test/**/*\" -i -- npm run test:mocha", + "test:mocha": "npm run build:jsdo && mocha --recursive --reporter mocha-simple-html-reporter --reporter-options output=build/index.html" }, "repository": { "type": "git", @@ -32,5 +35,14 @@ "homepage": "https://github.com/progress/JSDO#readme", "dependencies": {}, "peerDependencies": {}, - "optionalDependencies": {} + "optionalDependencies": {}, + "devDependencies": { + "chai": "^4.1.2", + "concat": "^1.0.3", + "concurrently": "^3.5.1", + "mocha": "^5.2.0", + "mocha-simple-html-reporter": "^1.1.0", + "onchange": "^4.0.0", + "reload": "^2.2.2" + } } diff --git a/test/smoke.js b/test/smoke.js new file mode 100644 index 0000000..f72f544 --- /dev/null +++ b/test/smoke.js @@ -0,0 +1,49 @@ +const chai = require('chai'); +const expect = chai.expect; + +const progress = require("../lib/progress.jsdo").progress; + +describe('Smoke Tests', () => { + // INFORMATION YEAH + const options = { + catalogURI: "http://oemobiledemo.progress.com/OEMobileDemoServices/static/r_Sports_with_SubmitService.json", + serviceURI: "http://oemobiledemo.progress.com/OEMobileDemoServices", + resourceName: "CustomerSubmit", + tableRef: "ttCustomer", + filter: "CustNum > 2990", + model: "anonymous" + }; + + const CustNum = 3000; + + var session; + + // Sets up the tests + before(function (done) { + progress.data.getSession({ + serviceURI: options.serviceURI, + catalogURI: options.catalogURI, + authenticationModel: options.model + }).then((object) => { + session = object.jsdosession; + }).then(done, done); + }); + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done(), () => done()); + }); + + + // Our first test. + describe('Ping Test', () => { + it('should have a successful connection to the backend', function(done) { + session.ping().then((object) => { + // If we have successfully logged into the backend, the result + // of our ping() should be true + expect(object.result).to.be.true; + }).then(done, done); + + }); + }); +}); \ No newline at end of file From ffeec4bf67bb1ea958234c4e22de14d3bfa99fc7 Mon Sep 17 00:00:00 2001 From: joshualan Date: Mon, 4 Jun 2018 19:21:42 -0400 Subject: [PATCH 12/84] Adding more smoke tests, added teamcity integration --- build/index.html | 27 ++++++++++++++++++++---- package.json | 5 ++++- test/smoke.js | 53 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/build/index.html b/build/index.html index f160653..030657b 100644 --- a/build/index.html +++ b/build/index.html @@ -424,17 +424,36 @@
  • show failures only
    • -
    • passes: 1
    • +
    • passes: 4
    • pending: 0
    • failures: 0
    • duration: 1.3s
    -
    • Smoke Tests

      • Ping Test

        • should have a successful connection to the backend38ms

          session.ping().then((object) => {
          +            
          • Smoke Tests

            • getSession Tests

              • should fail to connect to a non-existent backend35ms

                let getSession = progress.data.getSession({
                +    serviceURI: options.serviceURI + "fake",
                +    catalogURI: options.catalogURI,
                +    authenticationModel: options.model
                +}).then((object) => {
                +    return expect.fail(null, null, "getSession succeeded on a non-existent backend?");
                +}, (object) => {
                +    return object.result;
                +}); 
                +return expect(getSession).to.eventually.equal(progress.data.Session.GENERAL_FAILURE);
              • should connect to an existing anonymous backend56ms

                let getSession = progress.data.getSession({
                +    serviceURI: options.serviceURI,
                +    catalogURI: options.catalogURI,
                +    authenticationModel: options.model
                +}).then((object) => {
                +    session = object.jsdosession;
                +    return object.result; 
                +});
                +return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS);
            • Ping Test

              • should have a successful connection to the backend31ms

                let ping = session.ping().then((object) => {
                     // If we have successfully logged into the backend, the result
                     // of our ping() should be true
                -    expect(object.result).to.be.true;
                -}).then(done, done);
          + //return object.result; + return true; +}); +return expect(ping).to.eventually.equal(true);
        • test0ms

          expect(true).to.be.true;
    - - diff --git a/package.json b/package.json index c054043..9a108c7 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,10 @@ "typings/" ], "scripts": { - "test": "concurrently \"reload -b -s build/index.html\" \"npm run watch:js\"", - "build:jsdo": "concat -o build/progress.jsdo.js src/progress.util.js src/progress.js src/progress.session.js src/auth/progress.auth.js src/auth/progress.auth.basic.js src/auth/progress.auth.form.js src/auth/progress.auth.sso.js", - "watch:js": "onchange \"src/**/*\" \"test/**/*\" -i -- npm run test:mocha", - "test:mocha": "npm run build:jsdo && mocha --recursive --reporter mocha-simple-html-reporter --reporter-options output=build/index.html", - "test:tc": "mocha --recursive --reporter mocha-teamcity-reporter" + "test": "npm run build:jsdo && mocha --recursive", + "test:smokes": "npm run build:jsdo && mocha test/smoke*.js", + "build:jsdo": "mkdirp build && concat -o build/progress.jsdo.js src/progress.util.js src/progress.js src/progress.session.js src/auth/progress.auth.js src/auth/progress.auth.basic.js src/auth/progress.auth.form.js src/auth/progress.auth.sso.js", + "test:tc": "npm run build:jsdo && mocha --recursive --reporter mocha-teamcity-reporter" }, "repository": { "type": "git", @@ -41,11 +40,8 @@ "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "concat": "^1.0.3", - "concurrently": "^3.5.1", + "mkdirp": "^0.5.1", "mocha": "^5.2.0", - "mocha-simple-html-reporter": "^1.1.0", - "mocha-teamcity-reporter": "^2.4.0", - "onchange": "^4.0.0", - "reload": "^2.2.2" + "mocha-teamcity-reporter": "^2.4.0" } } diff --git a/test/smoke.js b/test/smoke.js index 3a02da6..208430a 100644 --- a/test/smoke.js +++ b/test/smoke.js @@ -6,36 +6,28 @@ const progress = require("../lib/progress.jsdo").progress; chai.use(chaiAsPromised); +// Might be a good idea to separate this into their own files down the line! It should be +// relatively easy. + describe('Smoke Tests', () => { // INFORMATION YEAH const options = { - catalogURI: "http://oemobiledemo.progress.com/OEMobileDemoServices/static/r_Sports_with_SubmitService.json", - serviceURI: "http://oemobiledemo.progress.com/OEMobileDemoServices", - resourceName: "CustomerSubmit", + catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", + serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", + resourceName: "Customer", tableRef: "ttCustomer", filter: "CustNum > 2990", model: "anonymous" }; - const CustNum = 3000; + const CustName = "SmokeTest3000"; let session, - ap; - - // Sets up the tests - before(function (done) { - progress.data.getSession({ - serviceURI: options.serviceURI, - catalogURI: options.catalogURI, - authenticationModel: options.model - }).then((object) => { - session = object.jsdosession; - }).then(done, done); - }); + jsdo; // Logout of the session after we are done after((done) => { - session.invalidate().then(() => done(), () => done()); + session.invalidate().then(() => done()); }); describe('getSession Tests', function () { @@ -53,6 +45,21 @@ describe('Smoke Tests', () => { return expect(getSession).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); }); + it('should connect to an existing basic backend', function () { + let getSession = progress.data.getSession({ + serviceURI: "http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/", + catalogURI: "http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/static/CustomerService.json", + authenticationModel: "basic", + username: "basicuser", + password: "basicpassword" + }).then((object) => { + object.jsdosession.invalidate(); + return object.result; + }); + + return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); + }); + it('should connect to an existing anonymous backend', function () { let getSession = progress.data.getSession({ serviceURI: options.serviceURI, @@ -65,28 +72,171 @@ describe('Smoke Tests', () => { return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); }); + }); - describe('JSDOSession API Tests', function () { + describe('JSDO Tests', function () { + describe('JSDO Instantiation Tests', function() { + it('should successfully create a JSDO', function() { + jsdo = new progress.data.JSDO({name: options.resourceName}); + expect(jsdo).to.be.an.instanceof(progress.data.JSDO); + }); + + it('should successfully call fill()', function() { + let fill = jsdo.fill().then((object) => { + return object.success; + }); + + return expect(fill).to.eventually.be.true; + }); + + it('should have a jsdo filled with actual data from the backend', function() { + expect(jsdo.hasData()).to.be.true; + }); + }); + + describe('JSDO CUD Tests', function () { + // Clean up the backend to make sure that there isn't an customer record with a CustNum of 3000 + // already in store + function clean(callback) { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + jsdo.saveChanges().then(() => { + return jsdo.fill(); + }).then(() => callback()); + } + + before(function(done) { + clean(done); + }); + + after(function(done) { + clean(done); + }); + + it('should successfully create a record on the backend', function() { + jsdo.ttCustomer.add({ + Name: CustName, + SalesRep: 'NS', + Balance: '2.10', + State: 'MA', + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.true; + }); + + it('should successfully update a record on the backend', function() { + const newState = "NH"; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.assign({State: newState}); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName && customer.data.State === newState) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.true; + }); + + it('should fail to update a record to have the same primary index as another record', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.assign({CustNum: 1}); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return object.success; + }, function (object) { + return object.success; + }); + + return expect(save).to.eventually.be.false; + }); + + it('should successfully delete a record on the backend', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.false; + }); + }); }); - // Our first test. - describe('Ping Test', () => { - it('should have a successful connection to the backend', function() { + describe('JSDOSession API Tests', function () { + it('should successfully ping() the backend', function() { let ping = session.ping().then((object) => { // If we have successfully logged into the backend, the result // of our ping() should be true - //return object.result; return true; }); return expect(ping).to.eventually.equal(true); }); - it('test', function () { - expect(true).to.be.true; + it('should have a successful call to isAuthorized()', function() { + let isAuthorized = session.isAuthorized().then((object) => { + // If we have successfully logged into the backend, the result + // of our ping() should be true + return object.result; + }); + + return expect(isAuthorized).to.eventually.equal(progress.data.Session.SUCCESS); }); + + it('should not have a connection to the backend after an invalidate', function() { + let isAuthorized = session.invalidate().then(() => { + return session.isAuthorized(); + }).then((object) => { + return object.result; + }, function(object) { + return object.result + }); + + return expect(isAuthorized).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); + }) }); }); \ No newline at end of file From 9e1133914597f400d223cdb463d2028712a84f9c Mon Sep 17 00:00:00 2001 From: joshualan Date: Thu, 7 Jun 2018 18:11:59 -0400 Subject: [PATCH 14/84] Removed the build folder completely --- build/progress.jsdo.js | 15014 --------------------------------------- 1 file changed, 15014 deletions(-) delete mode 100644 build/progress.jsdo.js diff --git a/build/progress.jsdo.js b/build/progress.jsdo.js deleted file mode 100644 index c1ac383..0000000 --- a/build/progress.jsdo.js +++ /dev/null @@ -1,15014 +0,0 @@ -/*eslint no-global-assign: ["error", {"exceptions": ["localStorage"]}]*/ -/*global XMLHttpRequest:true, require, console, localStorage:true, sessionStorage:true, $:true, Promise, setTimeout */ -/* -progress.util.js Version: 5.0.0 - -Copyright (c) 2014-2018 Progress Software Corporation and/or its subsidiaries or affiliates. - -Contains support objects used by the jsdo and/or session object - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ -/*global progress:true, btoa:true*/ -/*jslint nomen: true*/ - -(function () { - // Pre-release code to detect enviroment and load required modules for Node.js and NativeScript - // Requirements: - // - XMLHttpRequest - // - localStorage - // - sessionStorage - // - Promise object (Promises with the same interface as jQuery Promises) - - // Notes: - // Required packages should be installed before loading progress-jsdo. - // Node.js: - // - xmlhttprequest - // - node-localstorage - // NativeScript: - // - nativescript-localstorage - // - base-64 - - var isNativeScript = false, - isNodeJS = false; - - var pkg_xmlhttprequest = "xmlhttprequest", - pkg_nodeLocalstorage = "node-localstorage", - pkg_nativescriptLocalstorage = "nativescript-localstorage", - pkg_fileSystemAccess = "file-system/file-system-access" - ; - - // If XMLHttpRequest is undefined, enviroment would appear to be Node.js - // load xmlhttprequest module - // Web browser and NativeScript clients have a built-in XMLHttpRequest object - if (typeof XMLHttpRequest === "undefined") { - isNodeJS = true; - try { - XMLHttpRequest = require("" + pkg_xmlhttprequest).XMLHttpRequest; - // xhrc = require("xmlhttprequest-cookie"); - // XMLHttpRequest = xhrc.XMLHttpRequest; - } catch(e) { - console.error("Error: JSDO library requires XMLHttpRequest object in Node.js.\n" - + "Please install xmlhttprequest package."); - } - } - - // Detect if the environment is NativeScript - if (!isNodeJS - && (typeof localStorage === "undefined" - || typeof sessionStorage === "undefined")) { - try { - require("" + pkg_fileSystemAccess); - isNativeScript = true; - } catch(exception1) { - isNativeScript = false; - } - } - - // If localStorage or sessionStorage is not defined, - // we need to load the corresponding support module - - // If environment is NativeScript, load required modules - if (isNativeScript) { - try { - // load module nativescript-localstorage - if (typeof sessionStorage === "undefined") { - sessionStorage = require("" + pkg_nativescriptLocalstorage); - } - if (typeof localStorage === "undefined") { - localStorage = require("" + pkg_nativescriptLocalstorage); - } - } catch(exception2) { - console.error("Error: JSDO library requires localStorage and sessionStorage objects in NativeScript.\n" - + "Please install nativescript-localstorage package."); - } - - // load module base-64 - try { - if (typeof btoa === "undefined") { - btoa = require("base-64").encode; - } - } catch(exception3) { - console.error("Error: JSDO library requires btoa() function in NativeScript.\n" - + "Please install base-64 package."); - } - } - - // If environment is NodeJS, load module node-localstorage - if (isNodeJS) { - var LocalStorage; - if (typeof localStorage === "undefined") { - try { - var module = require("" + pkg_nodeLocalstorage); - LocalStorage = module.LocalStorage; - localStorage = new LocalStorage('./scratch1'); - } catch(e) { - console.error("Error: JSDO library requires localStorage and sessionStorage objects in Node.js.\n" - + "Please install node-localstorage package."); - } - } - - if (typeof sessionStorage === "undefined" - && typeof LocalStorage !== "undefined") { - sessionStorage = new LocalStorage('./scratch2'); - } - - // load module base-64 - try { - if (typeof btoa === "undefined") { - btoa = require("base-64").encode; - } - } catch(exception3) { - console.error("Error: JSDO library requires btoa() function in Node.js.\n" - + "Please install base-64 package."); - } - } -}()); - -(function () { - - /* Define these if not defined yet - they may already be defined if - * progress.js was included first */ - if (typeof progress === "undefined") { - progress = {}; - } - - if (typeof progress.data === "undefined") { - progress.data = {}; - } - - progress.util = {}; - - var STRING_OBJECT_TYPE = "String", - DATE_OBJECT_TYPE = "Date", - CHARACTER_ABL_TYPE = "CHARACTER"; - - /** - * Deferred class to provide access to ES6 and JQuery Promises. - * - * @class - */ - progress.util.Deferred = /** @class */ (function () { - function Deferred() { - this._deferred = {}; - } - - /** - * Returns a Promise object. - */ - Deferred.prototype.promise = function () { - var that = this; - - if (progress.util.Deferred.useJQueryPromises) { - if (typeof($) !== 'undefined' && typeof($.Deferred) === 'function') { - this._deferred._jQuerydeferred = $.Deferred(); - this._promise = this._deferred._jQuerydeferred.promise(); - } else { - throw new Error("JQuery Promises not found in environment."); - } - } else { - this._promise = new Promise(function (resolve, reject) { - that._deferred.resolve = resolve; - that._deferred.reject = reject; - }); - } - - if (this._resolveArguments || this._rejectArguments) { - setTimeout(function () { - if (that._resolveArguments) { - that.resolve.apply(that, that._resolveArguments); - } else if (that._rejectArguments) { - that.reject.apply(that, that._rejectArguments); - } - }, 500); - } - - // return null; - return this._promise; - - }; - - /** - * Calls the underlying resolve() method. - */ - Deferred.prototype.resolve = function (arg1, arg2, arg3) { - if (this._promise) { - if (this._deferred._jQuerydeferred) { - this._deferred._jQuerydeferred.resolve.apply(this, arguments); - } else { - var object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); - this._deferred.resolve(object); - } - } else { - this._resolveArguments = arguments; - } - }; - - /** - * Calls the underlying reject() method. - */ - Deferred.prototype.reject = function (arg1, arg2, arg3) { - if (this._promise) { - if (this._deferred._jQuerydeferred) { - this._deferred._jQuerydeferred.reject.apply(this, arguments); - } else { - var object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); - this._deferred.reject(object); - } - } else { - this._rejectArguments = arguments; - } - }; - - /** - * @property {boolean} useJQueryPromises - Tells the Deferred object to use jQuery Promises. - */ - Deferred.useJQueryPromises = false; - - /** - * Returns a deferred object based on a collection. - */ - Deferred.when = function (deferreds) { - if (progress.util.Deferred.useJQueryPromises) { - return $.when.apply($, deferreds); - } else { - return Promise.all(deferreds); - } - } - - /** - * Returns an object with the parameters to resolve()/reject(). - */ - Deferred.getParamObject1 = function (arg1, arg2, arg3) { - var object = {}, - objectName; - - try { - if ((typeof(arg1) === "undefined") || (arg1 === null)) { - object.result = arg2; - object.info = arg3; - } else { - objectName = arg1.constructor.name.toLowerCase(); - if (!objectName) { - objectName = typeof(arg1); - } - - // Map some object name to use a particular property name - switch (objectName) { - case "authenticationprovider": - objectName = "provider" - break; - case "number": - objectName = "result" - break; - default: - break; - } - object[objectName] = arg1; - if (objectName === "jsdo") { - object.success = arg2; - if (arg3 && arg3.xhr) { - object.request = arg3; - } else { - object.info = arg3; - } - } else { - if (objectName === "result") { - object.info = arg2; - if (arg3) { - object.info2 = arg3; - } - } else { - object.result = arg2; - object.info = arg3; - } - } - } - } catch(e) { - console.log("Error: Undetermined argument in getParamObject() call."); - } - - return object; - } - - /** - * Returns an object with the parameters to resolve()/reject() based on the Promise type. - */ - Deferred.getParamObject = function (arg1, arg2, arg3) { - var object = {}; - - if (progress.util.Deferred.useJQueryPromises) { - object = progress.util.Deferred.getParamObject1(arg1, arg2, arg3); - } else { - if (typeof(arg1) === "undefined") { - object.result = arg2; - object.info = arg3; - arg1 = object; - } - return arg1; - } - - return object; - }; - - return Deferred; - }()); - - /** - * Utility class that allows subscribing and unsubscribing from named events. - * - * @returns {progress.util.Observable} - */ - progress.util.Observable = function () { - /* - * Example format of the events object. Some event delegates may only - * have a function setup, others may optionally have scope, and possibly an operation filter - * - * var events = { - * afterfill : [{ - * scope : {}, // this is optional - * fn : function () {}, - * operation : 'getCustomers' // this is optional - * }, ...] - * - * } - * - * - * - */ - - /* - * remove the given function from the array of observers - */ - function _filterObservers(observers, fn, scope, operation) { - return observers.filter(function (el) { - if (el.fn !== fn || el.scope !== scope || el.operation !== operation) { - return el; - } - }, this); - } - - /* - * validate the arguments passed to the subscribe function - */ - this.validateSubscribe = function (args, evt, listenerData) { - - if (args.length >= 2 && (typeof args[0] === 'string') && (typeof args[1] === 'string')) { - listenerData.operation = args[1]; - listenerData.fn = args[2]; - listenerData.scope = args[3]; - - } else if (args.length >= 2 && (typeof args[0] === 'string') && (typeof args[1] === 'function')) { - listenerData.operation = undefined; - listenerData.scope = args[2]; - listenerData.fn = args[1]; - } else { - throw new Error(); - } - - }; - - - /* - * bind the specified function so it receives callbacks when the - * specified event name is called. Event name is not case sensitive. - * An optional scope can be provided so that the function is executed - * in the given scope. If no scope is given, then the function will be - * called without scope. - * - * If the same function is registered for the same event a second time with - * the same scope the original subscription is removed and replaced with the new function - * to be called in the new scope. - * - * This method has two signatures. - * - * Signature 1: - * @param evt The name of the event to bind a handler to. String. Not case sensitive. - * @param fn The function callback for the event . Function. - * @param scope The scope the function is to be run in. Object. Optional. - * - * Signature 2: - * - * @param evt The name of the event to bind a handler to. String. Not case sensitive - * @param operation The name of the operation to bind to. String. Case sensitive. - * @param fn The function callback for the event . Function. - * @param scope The scope the function is to be run in. Object. Optional. - - */ - this.subscribe = function (evt, operation, fn, scope) { - var listenerData, - observers; - - if (!evt) { - throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "subscribe")); - } - - if (typeof evt !== 'string') { - throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), - "subscribe", progress.data._getMsgText("jsdoMSG039"))); - } - - this._events = this._events || {}; - evt = evt.toLowerCase(); - listenerData = {fn: undefined, scope: undefined, operation: undefined}; - - try { - this.validateSubscribe(arguments, evt, listenerData); - } catch (e) { - throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), - "subscribe", e.message)); - } - - observers = this._events[evt] || []; - - // make sure we don't add duplicates - observers = _filterObservers(observers, listenerData.fn, - listenerData.scope, listenerData.operation); - observers.push(listenerData); - this._events[evt] = observers; - - return this; - }; - - /* - * remove the specified function so it no longer receives events from - * the given name. event name is not case sensitive. - * - * This method has two signaturues. - * Signature 1: - * @param evt Required. The name of the event for which to unbind the given function. String. - * @param fn Required. The function to remove from the named event. Function. - * @param scope Optional. The function scope in which to remove the listener. Object. - * - * Signature 2: - * - * @param evt Required. The name of the event for which to unbind the given function. - String. Not case sensitive - * @param operation Required. The name of the operation to receive events. String. Case Sensitive - * @param fn Required. The function to remove from the named event. Function. - * @param scope Optional. The function scope in which to remove the listener. Object. - * - */ - this.unsubscribe = function (evt, operation, fn, scope) { - var listenerData, - observers; - - if (!evt) { - throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "unsubscribe")); - } - - if (typeof evt !== 'string') { - throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), - "unsubscribe", progress.data._getMsgText("jsdoMSG037"))); - } - - this._events = this._events || {}; - evt = evt.toLowerCase(); - listenerData = {fn: undefined, scope: undefined, operation: undefined}; - try { - this.validateSubscribe(arguments, evt, listenerData); - } catch (e) { - // throw new Error("Invalid signature for unsubscribe. " + e.message); - throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), - "unsubscribe", e.message)); - } - - observers = this._events[evt] || []; - if (observers.length > 0) { - this._events[evt] = _filterObservers(observers, listenerData.fn, - listenerData.scope, listenerData.operation); - } - - return this; - }; - - /* - * trigger an event of the given name, and pass the specified data to - * the subscribers of the event. Event name is not case sensitive. - * A variable numbers of arguments can be passed as arguments to the event handler. - * - * This method has two signatures - * Signature 1: - * @param evt The name of the event to fire. String. Not case sensitive. - * @param operation The name of the operation. String. Case sensitive - * @param args Optional. A variable number of arguments to pass to the event handlers. - * - * Signature 2: - * @param evt The name of the event to fire. String. Not case sensitive - * @param args Optional. A variable number of arguments to pass to the event handlers. - */ - this.trigger = function (evt, operation, args) { - var observers, - op; - - if (!evt) { - throw new Error(progress.data._getMsgText("jsdoMSG037", this.toString(), "trigger")); - } - - this._events = this._events || {}; - evt = evt.toLowerCase(); - observers = this._events[evt] || []; - if (observers.length > 0) { - args = Array.prototype.slice.call(arguments); - - if ((arguments.length >= 2) - && (typeof evt === 'string') - && (typeof operation === 'string')) { - // in alt format the second argument is the event name, - // and the first is the operation name - op = operation; - args = args.length > 2 ? args.slice(2) : []; - } else if (arguments.length >= 1 && (typeof evt === 'string')) { - op = undefined; - args = args.length > 1 ? args.slice(1) : []; - } else { - throw new Error(progress.data._getMsgText("jsdoMSG033", this.toString(), "trigger")); - } - - observers.forEach(function (el) { - if (el.operation === op) { - el.fn.apply(el.scope, args); - } - }); - - } - - return this; - }; - - // unbind all listeners from the given event. If the - // evt is undefined, then all listeners for all events are unbound - // evnt name is not case sensitive - // @param evt Optional. The name of the event to unbind. If not passed, then all events are unbound - this.unsubscribeAll = function (evt, operation) { - var observers; - - if (evt) { - this._events = this._events || {}; - if (typeof evt === 'string') { - evt = evt.toLowerCase(); - observers = this._events[evt] || []; - - observers.forEach(function (el) { - if (el.operation) { - this.unsubscribe(evt, el.operation, el.fn, el.scope); - } else { - this.unsubscribe(evt, el.fn, el.scope); - } - }, this); - } - } else { - this._events = {}; - } - - return this; - }; - }; - - - /** - * Utility class that saves/reads data to localStorage - * - * @returns {progress.data.LocalStorage} - */ - progress.data.LocalStorage = function LocalStorage() { - - /*global localStorage */ - if (typeof localStorage === "undefined") { - // "progress.data.LocalStorage: No support for localStorage." - throw new Error(progress.data._getMsgText("jsdoMSG126", "progress.data.LocalStorage", "localStorage")); - } - - - // "Methods" - - this.saveToLocalStorage = function (name, dataObj) { - localStorage.setItem(name, JSON.stringify(dataObj)); - }; - - this.readFromLocalStorage = function (name) { - - var jsonStr = localStorage.getItem(name), - dataObj = null; - - if (jsonStr !== null) { - try { - dataObj = JSON.parse(jsonStr); - } catch (e) { - dataObj = null; - } - } - return dataObj; - }; - - this.clearLocalStorage = function (name) { - localStorage.removeItem(name); - }; - - }; // End of LocalStorage - - - ///////////////////////////////////////////////////////////////////////////////////////// - // Utility Functions - - /* - * Converts the specified filter object to an OpenEdge ABL Where String. - * - * @param tableRef - handle to the table in jsdo, where string is applied to. - * @param filter - the filter object to convert. - * - * @returns - translated OE where string. - */ - progress.util._convertToABLWhereString = function (tableRef, filter) { - var result = [], - logic = filter.logic || "and", - idx, - length, - field, - fieldInfo, - type, - format, - operator, - value, - ablType, - //filters = (filter.filters) ? filter.filters : [filter], - filters = filter.filters || [filter], - - whereOperators = { - eq: "=", - neq: "<>", - gt: ">", - gte: ">=", - lt: "<", - lte: "<=", - contains : "INDEX", - doesnotcontain: "INDEX", - endswith: "R-INDEX", - startswith: "BEGINS", - isnull: "ISNULL", - isnotnull: "ISNOTNULL", - isempty: "ISEMPTY", - isnotempty: "ISNOTEMPTY" - }; - - for (idx = 0, length = filters.length; idx < length; idx += 1) { - filter = filters[idx]; - field = filter.field; - value = filter.value; - - if (filter.filters) { - filter = progress.util._convertToABLWhereString(tableRef, filter); - } else { - // Use original field name instead of serialized name - if (field && tableRef._name) { - fieldInfo = tableRef._jsdo[tableRef._name]._fields[field.toLowerCase()]; - if (fieldInfo && fieldInfo.origName) { - field = fieldInfo.origName; - } - } - - operator = whereOperators[filter.operator]; - - if (operator === undefined) { - throw new Error("The operator " + filter.operator + " is not valid."); - } - - switch (filter.operator) { - case "isnull": - case "isnotnull": - case "isempty": - case "isnotempty": - value = undefined; - break; - } - - if (operator && value !== undefined) { - type = progress.util._getObjectType(value); - - // We need to build a template format string for the where string. - // We'll first add positional info for the value - if (type === STRING_OBJECT_TYPE) { - format = "'{1}'"; - value = value.replace(/'/g, "~'"); - } else if (type === DATE_OBJECT_TYPE) { - ablType = tableRef._getABLType(field); - if (ablType === "DATE") { - format = "DATE({1:MM, dd, yyyy})"; - } else if (ablType === "DATETIME-TZ") { - // zzz here means to translate timezone offset into minutes - format = "DATETIME-TZ({1:MM, dd, yyyy, hh, mm, ss, fff, zzz})"; - } else { - format = "DATETIME({1:MM, dd, yyyy, hh, mm, ss, fff})"; - } - } else { - format = "{1}"; - } - - // Most where strings are in the format: field operator value. Ex. custnum < 100 - // An exception to this is INDEX() and R-INDEX() which have format: operator field value - // Ex. R-INDEX(name, "LTD") - if (operator === "INDEX" || operator === "R-INDEX") { - if (type !== STRING_OBJECT_TYPE) { - throw new Error("Error parsing filter object. The operator " + filter.operator + - " requires a string value"); - } - if (filter.operator === "doesnotcontain") { - format = "{0}(" + "{2}, " + format + ") = 0"; - } else if (filter.operator === "contains") { - format = "{0}(" + "{2}, " + format + ") > 0"; - } else { // else filter.operator = "endswith" - format = "{2} MATCHES '*{1}'"; - } - } else { - format = "{2} {0} " + format; - } - - filter = progress.util._format(format, operator, value, field); - } else if (operator && value === undefined) { - if (filter.operator === "isempty" || filter.operator === "isnotempty") { - ablType = tableRef._getABLType(field); - if (ablType !== CHARACTER_ABL_TYPE) { - throw new Error("Error parsing filter object. The operator " + filter.operator + - " requires a CHARACTER field"); - } - if (filter.operator === "isempty") { - format = "{2} = ''"; - } else if (filter.operator === "isnotempty") { - format = "{2} <> ''"; - } - } else { - if (filter.operator === "isnull") { - format = "{2} = ?"; - } else if (filter.operator === "isnotnull") { - format = "{2} <> ?"; - } else { - format = "{2} {0} ?"; - } - } - - // format, operator {0}, value {1}, field {2} - filter = progress.util._format(format, operator, value, field); - } - } - - result.push(filter); - } - - filter = result.join(" " + logic + " "); - - if (result.length > 1) { - filter = "(" + filter + ")"; - } - - return filter; - }; - - - /* - * Converts the specified filter object to an SQL Query String. - * - * @param tableName - tableName of table in jsdo, where clause is applied to. - * @param filter - the filter object to convert. - * - * @returns - translated SQL where clause. - */ - progress.util._convertToSQLQueryString = function (tableRef, filter, addSelect) { - var result = [], - logic = filter.logic || "and", - idx, - length, - field, - type, - format, - operator, - value, - fieldFormat, - filters = filter.filters || [filter], - filterStr, - usingLike = true, - - whereOperators = { - eq: "=", - neq: "!=", - gt: ">", - gte: ">=", - lt: "<", - lte: "<=", - contains : "LIKE", - doesnotcontain: "NOT LIKE", - endswith: "LIKE", - startswith: "LIKE", - isnull: "ISNULL", - isnotnull: "ISNOTNULL", - isempty: "ISEMPTY", - isnotempty: "ISNOTEMPTY" - }; - - if (typeof addSelect === "undefined") { - addSelect = false; - } - - for (idx = 0, length = filters.length; idx < length; idx += 1) { - filter = filters[idx]; - field = filter.field; - value = filter.value; - - if (filter.filters) { - filterStr = progress.util._convertToSQLQueryString(tableRef, filter, false); - } else { - operator = whereOperators[filter.operator]; - - if (operator === undefined) { - throw new Error("The operator " + filter.operator + " is not valid."); - } - - switch (filter.operator) { - case "isnull": - case "isnotnull": - case "isempty": - case "isnotempty": - value = undefined; - break; - } - - if (operator && value !== undefined) { - type = progress.util._getObjectType(value); - - if (operator === "LIKE" || operator === "NOT LIKE") { - if (type !== STRING_OBJECT_TYPE) { - throw new Error("Error parsing filter object. The operator " + filter.operator + - " requires a string value"); - } - } - - if (type === STRING_OBJECT_TYPE) { - format = "'{1}'"; - value = value.replace(/'/g, "''"); - } else if (type === DATE_OBJECT_TYPE) { - fieldFormat = tableRef._getFormat(field); - if (fieldFormat === "date") { - format = "'{1:yyyy-MM-dd}'"; - } else if (fieldFormat === "date-time") { - format = "{1:#ISO(iso)}"; - } else if (fieldFormat === "time") { - format = "'{1:FFF}'"; - } - } else { - format = "{1}"; - } - - // We need to build a template format string for the where string. - // We'll first add positional info for the value, which is represented by {1} - if (filter.operator === "startswith") { - format = "'{1}%'"; - } else if (filter.operator === "endswith") { - format = "'%{1}'"; - } else if (filter.operator === "contains" || filter.operator === "doesnotcontain") { - format = "'%{1}%'"; - } else { - usingLike = false; - } - - if (usingLike) { - value = value.replace(/%/g, '\\%'); - value = value.replace(/_/g, '\\_'); - } - - format = "{2} {0} " + format; - filterStr = progress.util._format(format, operator, value, field); - } else if (operator && value === undefined) { - if (filter.operator === "isempty" || filter.operator === "isnotempty") { - type = tableRef._fields[field.toLowerCase()].type; - if (type !== STRING_OBJECT_TYPE.toLowerCase()) { - throw new Error("Error parsing filter object. The operator " + filter.operator + - " requires a string field"); - } - if (filter.operator === "isempty") { - format = "{2} = ''"; - } else if (filter.operator === "isnotempty") { - format = "{2} != ''"; - } - } else { - if (filter.operator === "isnull") { - format = "{2} IS NULL"; - } else if (filter.operator === "isnotnull") { - format = "{2} IS NOT NULL"; - } else { - format = "{2} {0} NULL"; - } - } - - // format, operator {0}, value {1}, field {2} - filterStr = progress.util._format(format, operator, value, field); - } - } - - result.push(filterStr); - } - - filterStr = result.join(" " + logic + " "); - - if (result.length > 1) { - filterStr = "(" + filterStr + ")"; - } - - if (addSelect === true) { - filterStr = "SELECT * FROM " + tableRef._name + " WHERE " + filterStr; - } - - return filterStr; - }; - - - /* - * Returns the object type; Example "String", "Date" - * Constants for object type values are defined above. - * - * @param value - the object whose type is returned - */ - progress.util._getObjectType = function (value) { - // Returns [object xxx]. Removing [object ] - return Object.prototype.toString.call(value).slice(8, -1); - }; - - - /* - * Substitutes in a variable number of arguments into specified format string (with place-holders) - * - * @param fmt - the format string with place-holders, eg. "{0} text {1}". - * - * @returns - formatted string. - */ - progress.util._format = function (fmt) { - /*jslint regexp: true*/ - var values = arguments, - formatRegExp = /\{(\d+)(:[^\}]+)?\}/g; - /*jslint regexp: false*/ - - return fmt.replace(formatRegExp, function (match, index, placeholderFormat) { - var value = values[parseInt(index, 10) + 1]; - - return progress.util._toString(value, placeholderFormat ? placeholderFormat.substring(1) : ""); - }); - - }; - - /* - * Converts the specified value param to a string. - * - * @param value - object to convert - * @param fmt - optional format string with place-holders, eg. "MM dd yyyy". - * - * @returns - converted string. - */ - progress.util._toString = function (value, fmt) { - var str; - - if (fmt) { - if (progress.util._getObjectType(value) === "Date") { - return progress.util._formatDate(value, fmt); - } - } - - if (typeof value === "number") { - str = value.toString(); - } else { - str = (value !== undefined ? value : ""); - } - - return str; - }; - - /* - * Accepts string representing number and optionally pads it with "0"'s to conform to - * specified number of digits. - * - * @param number - string representing number to pad. - * @param digit - number of digits desired for padded string. If not specified, default is 2. - * - * @returns - padded string representing number. - */ - progress.util._pad = function (number, digits) { - var zeros = ["", "0", "00", "000", "0000"], - end; - - number = String(number); - digits = digits || 2; - end = digits - number.length; - - if (end) { - return zeros[digits].substring(0, end) + number; - } - return number; - }; - - /* - * Converts the specified date param to a string. - * - * @param date - date object to convert - * @param fmt - format string with place-holders, eg. "MM dd yyyy". - * - * @returns - converted string. - */ - progress.util._formatDate = function (date, format) { - /*jslint regexp: true*/ - var dateFormatRegExp = - /dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g; - /*jslint regexp: false*/ - - return format.replace(dateFormatRegExp, function (match) { - var minutes, - result, - sign; - - if (match === "dd") { - result = progress.util._pad(date.getDate()); - } else if (match === "MM") { - result = progress.util._pad(date.getMonth() + 1); - } else if (match === "yyyy") { - result = progress.util._pad(date.getFullYear(), 4); - } else if (match === "hh") { - result = progress.util._pad(date.getHours()); - } else if (match === "mm") { - result = progress.util._pad(date.getMinutes()); - } else if (match === "ss") { - result = progress.util._pad(date.getSeconds()); - } else if (match === "fff") { - result = progress.util._pad(date.getMilliseconds(), 3); - } else if (match === "FFF") { - result = String(date.getTime()); - } else if (match === "zzz") { - // timezone is returned in minutes - minutes = date.getTimezoneOffset(); - sign = minutes < 0; - result = (sign ? "+" : "-") + minutes; - } else if (match === "iso") { - result = date.toISOString(); - } - - return result !== undefined ? result : match.slice(1, match.length - 1); - }); - }; - - /* - * Processes settings in a jsdoSettings object. - * This method is used by project templates. - */ - progress.util.jsdoSettingsProcessor = function jsdoSettingsProcessor(jsdoSettings) { - if (typeof jsdoSettings === 'object') { - if (jsdoSettings.authenticationModel === undefined || jsdoSettings.authenticationModel === "") { - jsdoSettings.authenticationModel = "ANONYMOUS"; - } - } - }; - -}()); - -/* -progress.js Version: 5.0.0 - -Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ - -/*global $, progress:true*/ -(function () { - - // "use strict"; - - var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS = 20, - PROGRESS_JSDO_OP_STRING = ["none", "create", "read", "update", "delete", "submit"], - PROGRESS_JSDO_ROW_STATE_STRING = ["", "created", "", "modified", "deleted"]; - - /* define these if not defined yet - they may already be defined if - progress.session.js was included first */ - if (typeof progress === 'undefined') { - progress = {}; - } - if (typeof progress.data === 'undefined') { - progress.data = {}; - } - - progress.data._nextid = 0; - progress.data._uidprefix = "" + ( Date.now ? Date.now() : (new Date().getTime())); - - /* 15 - 9 */ - var UID_MAX_VALUE = 999999999999999; - - progress.data._getNextId = function () { - var uid = ++progress.data._nextid; - if (uid >= UID_MAX_VALUE) { - progress.data._nextid = uid = 1; - progress.data._uidprefix = "" + ( Date.now ? Date.now() : (new Date().getTime())); - } - - return progress.data._uidprefix + "-" + uid; - }; - - - var msg = {}; - msg.msgs = {}; - // msg numbers 0 - 99 are related to use of the API (methods and properties we expose to developers) - // 100 - 109 relate to network errors - // 110 - 998 are for miscellaneous errors - - msg.msgs.jsdoMSG000 = "JSDO, Internal Error: {1}"; - msg.msgs.jsdoMSG001 = "JSDO: JSDO has multiple tables. Please use {1} at the table reference level."; - msg.msgs.jsdoMSG002 = "JSDO: Working record for '{1}' is undefined."; - msg.msgs.jsdoMSG003 = "JSDO: {1} function requires a function as a parameter."; - msg.msgs.jsdoMSG004 = "JSDO: Unable to find resource '{1}' in the catalog."; - msg.msgs.jsdoMSG005 = "JSDO: Data for table '{1}' was not specified in addRecords() call."; - msg.msgs.jsdoMSG006 = "JSDO: Data for JSDO was not specified in addRecords() call."; - msg.msgs.jsdoMSG007 = "JSDO: Test function in {1} must return a boolean."; - msg.msgs.jsdoMSG008 = "JSDO: Invalid keyFields parameter in addRecords() call."; - msg.msgs.jsdoMSG009 = "JSDO: KeyField '{1}' in addRecords() call was not found in the schema."; - msg.msgs.jsdoMSG010 = "JSDO: Field '{1}' in relationship was not found in the schema."; - msg.msgs.jsdoMSG011 = "UIHelper: JSDO has multiple tables. " + - "Please use {1} at the table reference level."; - msg.msgs.jsdoMSG012 = "UIHelper: Invalid {2} parameter in {1} call."; - msg.msgs.jsdoMSG020 = "JSDO: tableName parameter must be a string in addRecords() call."; - msg.msgs.jsdoMSG021 = "JSDO: addMode parameter must be specified in addRecords() call."; - msg.msgs.jsdoMSG022 = "JSDO: Invalid addMode specified in addRecords() call."; - msg.msgs.jsdoMSG023 = "JSDO: Duplicate found in addRecords() call using APPEND mode."; - msg.msgs.jsdoMSG024 = "{1}: Unexpected signature in call to {2} function."; - msg.msgs.jsdoMSG025 = "{1}: Invalid parameters in call to {2} function."; - msg.msgs.jsdoMSG026 = "JSDO: saveChanges requires a " + - "CREATE, UPDATE, DELETE or SUBMIT operation to be defined."; - msg.msgs.jsdoMSG030 = "JSDO: Invalid {1}, expected {2}."; - msg.msgs.jsdoMSG031 = "JSDO: Specified sort field name '{1}' was not found in the schema."; - msg.msgs.jsdoMSG032 = "JSDO: Before-image data already exists for record in addRecords() call."; - msg.msgs.jsdoMSG033 = "{1}: Invalid signature for {2}. {3}"; - msg.msgs.jsdoMSG034 = "JSDO: In '{1}' function, JSON data is missing _id"; - msg.msgs.jsdoMSG035 = "JSDO: In '{1}' function, before-image JSON data is missing prods:clientId"; - msg.msgs.jsdoMSG036 = "JSDO: '{1}' can only be called for a dataset"; - msg.msgs.jsdoMSG037 = "{1}: Event name must be provided for {2}."; - msg.msgs.jsdoMSG038 = "Too few arguments. There must be at least {1}."; - msg.msgs.jsdoMSG039 = "The name of the event is not a string."; - msg.msgs.jsdoMSG040 = "The event listener is not a function."; - msg.msgs.jsdoMSG041 = "The event listener scope is not an object."; - msg.msgs.jsdoMSG042 = "'{1}' is not a defined event for this object."; - msg.msgs.jsdoMSG043 = "{1}: A session object was requested to check the status of a Mobile " + - "Service named '{2}', but it has not loaded the definition of that service."; - msg.msgs.jsdoMSG044 = "JSDO: In '{1}' function, {2} is missing {3} property."; - msg.msgs.jsdoMSG045 = "JSDO: {1} function: {2} is missing {3} property."; - msg.msgs.jsdoMSG046 = "JSDO: {1} operation is not defined."; - msg.msgs.jsdoMSG047 = "{1} timeout expired."; - msg.msgs.jsdoMSG048 = "{1}: {2} method has argument '{3}' that is missing property '{4}'."; - msg.msgs.jsdoMSG049 = "{1}: Unexpected error calling {2}: {3}"; - msg.msgs.jsdoMSG050 = "No token returned from server"; - msg.msgs.jsdoMSG051 = "{1} The login method was not executed because the AuthenticationProvider is already logged in."; - msg.msgs.jsdoMSG052 = "{1}: The login method was not executed because no credentials were supplied."; - msg.msgs.jsdoMSG053 = "{1}: {2} was not executed because the AuthenticationProvider is not logged in."; - msg.msgs.jsdoMSG054 = "{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token."; - msg.msgs.jsdoMSG055 = "{1}: Token refresh was not executed because the authentication model is not sso."; - msg.msgs.jsdoMSG056 = "{1}: Already logged in."; - msg.msgs.jsdoMSG057 = "{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead."; - msg.msgs.jsdoMSG058 = "{1}: Cannot pass username and password to addCatalog when authenticationModel " + - "is sso. Pass an AuthenticationProvider instead."; - msg.msgs.jsdoMSG059 = "{1}: Error in constructor. The authenticationModels of the " + - "AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible."; - msg.msgs.jsdoMSG060 = "AuthenticationProvider: AuthenticationProvider is no longer logged in. " + - "Tried to refresh SSO token but failed due to authentication error at token server."; - msg.msgs.jsdoMSG061 = "{1}: Attempted to set {2} property to an invalid value."; - msg.msgs.jsdoMSG062 = "{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in."; - - // 100 - 109 relate to network errors - msg.msgs.jsdoMSG100 = "JSDO: Unexpected HTTP response. Too many records."; - msg.msgs.jsdoMSG101 = "Network error while executing HTTP request."; - - // 110 - 499 are for miscellaneous errors - msg.msgs.jsdoMSG110 = "Catalog error: idProperty not specified for resource '{1}'. " + - "idProperty is required {2}."; - msg.msgs.jsdoMSG111 = "Catalog error: Schema '{1}' was not found in catalog."; - msg.msgs.jsdoMSG112 = "Catalog error: Output parameter '{1}' was not found for operation '{2}'."; - msg.msgs.jsdoMSG113 = "Catalog error: Found xType '{1}' for output parameter '{2}' " + - "for operation '{3}' but xType DATASET, TABLE or ARRAY was expected."; - msg.msgs.jsdoMSG114 = "JSDO: idProperty '{1}' is missing from '{2}' record."; - msg.msgs.jsdoMSG115 = "JSDO: Invalid option specified in {1}() call."; - msg.msgs.jsdoMSG116 = "JSDO: {1} parameter must be a string in {2} call."; - msg.msgs.jsdoMSG117 = "JSDO: Schema from storage area '{1}' does not match JSDO schema"; - msg.msgs.jsdoMSG118 = "JSDO: Plugin '{1}' was not found."; - msg.msgs.jsdoMSG119 = "JSDO: A mappingType is expected when 'capabilities' is set." + - " Please specify a plugin (ex: JFP)."; - msg.msgs.jsdoMSG120 = "JSDO: Parameter '{2}' requires capability '{1}' in the catalog."; - msg.msgs.jsdoMSG121 = "{1}: Argument {2} must be of type {3} in {4} call."; - msg.msgs.jsdoMSG122 = "{1}: Incorrect number of arguments in {2} call. There should be {3}."; - msg.msgs.jsdoMSG123 = "{1}: A server response included an invalid '{2}' header."; - msg.msgs.jsdoMSG124 = "JSDO: autoApplyChanges is not supported for saveChanges(true) " + - "with a temp-table. Use jsdo.autoApplyChanges = false."; - msg.msgs.jsdoMSG125 = "{1}: The AuthenticationProvider is not managing valid credentials."; - msg.msgs.jsdoMSG126 = "{1}: No support for {2}."; - msg.msgs.jsdoMSG127 = "JSDO: acceptRowChanges() cannot be called for record with _rejected === true."; - - // 500 - 998 are for generic errors - msg.msgs.jsdoMSG500 = "{1}: '{2}' objects must contain a '{3}' property."; - msg.msgs.jsdoMSG501 = "{1}: '{2}' in '{3}' function cannot be an empty string."; - msg.msgs.jsdoMSG502 = "{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for " + - "its '{4}' property."; - msg.msgs.jsdoMSG503 = "{1}: '{2}' must be of type '{3}'."; - msg.msgs.jsdoMSG504 = "{1}: {2} has an invalid value for the '{3}' property."; - msg.msgs.jsdoMSG505 = "{1}: '{2}' objects must have a '{3}' method."; - // use message below if invalid parameter value is an object - msg.msgs.jsdoMSG506 = "{1}: Invalid argument for the {2} parameter in {3} call."; - // use message below if invalid parameter value is a primitive - msg.msgs.jsdoMSG507 = "{1}: '{2}' is an invalid value for the {3} parameter in {4} call."; - msg.msgs.jsdoMSG508 = "JSDOSession: If a JSDOSession object is using the SSO authentication model, " + - "the options object passed to its constructor must include an authProvider property."; - msg.msgs.jsdoMSG509 = "progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, " + - "authenticationURI and authProviderAuthenticationModel are required parameters."; - msg.msgs.jsdoMSG510 = "{1}: This session has been invalidated and cannot be used."; - msg.msgs.jsdoMSG511 = "JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or " + - "connect() has been successfully called."; - msg.msgs.jsdoMSG512 = "JSDOSession: Error while loading multiple catalogs."; - - msg.msgs.jsdoMSG998 = "JSDO: JSON object in addRecords() must be DataSet or Temp-Table data."; - - msg.getMsgText = function (n, args) { - var text = msg.msgs[n], - i; - if (!text) { - throw new Error("Message text was not found by getMsgText()"); - } - for (i = 1; i < arguments.length; i += 1) { - text = text.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]); - } - - return text; - }; - - progress.data._getMsgText = msg.getMsgText; - - progress.data.PluginManager = {}; - progress.data.PluginManager._plugins = {}; - - progress.data.PluginManager.addPlugin = function(name, plugin) { - if (progress.data.PluginManager._plugins[name] === undefined) { - progress.data.PluginManager._plugins[name] = plugin; - } - else { - throw new Error("A plugin named '" + name + "' is already registered."); - } - }; - - progress.data.PluginManager.getPlugin = function (name) { - return progress.data.PluginManager._plugins[name]; - }; - - progress.data.JSIndexEntry = function JSIndexEntry(index) { - this.index = index; - }; - - progress.data.JSTableRef = function JSTableRef(jsdo, tableName) { - this._jsdo = jsdo; - this._name = tableName; - this._schema = null; - this._primaryKeys = null; - this._fields = null; - this._processed = {}; - this._visited = false; - - // record is used to represent the current record for a table reference - this.record = null; - - // Data structure - this._data = []; - this._index = {}; - this._tmpIndex = {}; - this._hasEmptyBlocks = false; - - // Arrays to keep track of changes - this._beforeImage = {}; - this._added = []; - this._changed = {}; - this._deleted = []; - this._lastErrors = []; - this._convertForServer; - - this._createIndex = function () { - var i, block, id, idProperty; - this._index = {}; - this._tmpIndex = {}; - this._hasEmptyBlocks = false; - for (i = 0; i < this._data.length; i += 1) { - block = this._data[i]; - if (!block) { - this._hasEmptyBlocks = true; - continue; - } - id = this._data[i]._id; - if (!id) { - idProperty = this._jsdo._resource.idProperty; - if (typeof(idProperty) == "string") { - id = this._data[i][idProperty]; - if (id === undefined) { - throw new Error(msg.getMsgText("jsdoMSG114", idProperty, this._name)); - } - id += ""; - } - else { - id = progress.data._getNextId(); - } - id += ""; // ID Property - this._data[i]._id = id; - } - this._index[id] = new progress.data.JSIndexEntry(i); - } - this._needCompaction = false; - }; - - this._compact = function () { - var newDataArray = [], i, block; - - for (i = 0; i < this._data.length; i += 1) { - block = this._data[i]; - if (block) { - newDataArray.push(block); - } - } - this._data = newDataArray; - this._createIndex(); - }; - - this._loadBeforeImageData = function (jsonObject, beforeImageJsonIndex, keyFields) { - var prodsBeforeData = jsonObject[this._jsdo._dataSetName]["prods:before"], - tmpIndex = {}, - record, - record2, - recordId, - key, - tmpKeyIndex, - id, - jsrecord, - tmpDataIndex, - tmpDeletedIndex, - i, - j; - - if (prodsBeforeData && prodsBeforeData[this._name]) { - - if ((Object.keys(this._beforeImage).length !== 0) && keyFields && (keyFields.length !== 0)) { - tmpKeyIndex = {}; - for (id in this._beforeImage) { - jsrecord = this._findById(id, false); - - if (jsrecord) { - key = this._getKey(jsrecord.data, keyFields); - tmpKeyIndex[key] = jsrecord.data; - } - } - } - - for (i = 0; i < prodsBeforeData[this._name].length; i++) { - record = prodsBeforeData[this._name][i]; - tmpIndex[record["prods:id"]] = record; - - if (record["prods:rowState"] == "deleted") { - key = undefined; - - if (keyFields && (keyFields.length !== 0)) { - key = this._getKey(record, keyFields); - } - - if (tmpKeyIndex) { - if (tmpKeyIndex[key] !== undefined) { - throw new Error(msg.getMsgText("jsdoMSG032")); - } - } - - if ((tmpDataIndex === undefined) && keyFields && (keyFields.length !== 0)) { - tmpDataIndex = {}; - tmpDeletedIndex = {}; - - for (var j = 0; j < this._data.length; j++) { - record2 = this._data[j]; - if (!record2) continue; - - var key2 = this._getKey(record2, keyFields); - tmpDataIndex[key2] = record2; - } - - // We also want to check if _deleted record already exists - for (j = 0; j < this._deleted.length; j++) { - record2 = this._deleted[j].data; - if (!record2) continue; - - var key2 = this._getKey(record2, keyFields); - tmpDeletedIndex[key2] = record2; - } - } - - // First check to see if this deleted record is already in _deleted array - if (key !== undefined) { - record2 = tmpDeletedIndex[key]; - if (record2 !== undefined) { - // If record is already in _deleted array, then nothing more to do here - continue; - } - } - - if (key !== undefined) { - record2 = tmpDataIndex[key]; - if (record2 !== undefined) { - var jsrecord = this._findById(record2._id, false); - if (jsrecord) jsrecord._remove(false); - record._id = record2._id; - } - } - - if (record._id === undefined) - record._id = progress.data._getNextId(); - var copy = {}; - this._jsdo._copyRecord( - this._tableRef, record, copy); - this._jsdo._deleteProdsProperties(copy); - this._beforeImage[record._id] = copy; - var jsrecord = new progress.data.JSRecord(this, copy); - this._deleted.push(jsrecord); - } - } - } - - // Process data using jsonObject instead of _data - // First check if there is after-data for table. Can be called with just before-image data - var tableObject = jsonObject[this._jsdo._dataSetName][this._name]; - if (tableObject) { - for (i = 0; i < jsonObject[this._jsdo._dataSetName][this._name].length; i++) { - record = jsonObject[this._jsdo._dataSetName][this._name][i]; - recordId = undefined; - if (beforeImageJsonIndex && record["prods:id"]) { - recordId = beforeImageJsonIndex[record["prods:id"]]; - } - switch (record["prods:rowState"]) { - case "created": - if (recordId === undefined) { - recordId = record._id; - } - - // If recordId and record._id are undefined, the record was not processed - if (recordId !== undefined) { - this._beforeImage[recordId] = null; - this._added.push(recordId); - } - break; - case "modified": - var beforeRecord = tmpIndex[record["prods:id"]]; - if (beforeRecord === undefined) { - beforeRecord = {}; - } - - if (recordId === undefined) { - recordId = record._id; - } - // If recordId and record._id are undefined, the record was not processed - if (recordId !== undefined) { - beforeRecord._id = record._id; - - var copy = {}; - this._jsdo._copyRecord( - this._tableRef, beforeRecord, copy); - this._jsdo._deleteProdsProperties(copy); - - this._beforeImage[recordId] = copy; - this._changed[recordId] = record; - - this._beforeImage[beforeRecord._id] = copy; - this._changed[beforeRecord._id] = record; - } - break; - case undefined: - break; // rowState is only specified for records that have changed - default: - throw new Error(msg.getMsgText("jsdoMSG030", - "rowState value in before-image data", "'created' or 'modified'")); - } - } - } - - // Process prods:errors - var prodsErrors = jsonObject[this._jsdo._dataSetName]["prods:errors"]; - if (prodsErrors) { - for (i = 0; i < prodsErrors[this._name].length; i++) { - var item = prodsErrors[this._name][i]; - var recordId = beforeImageJsonIndex[item["prods:id"]]; - var jsrecord = this._findById(recordId, false); - if (jsrecord) { - jsrecord.data._errorString = item["prods:error"]; - } - } - } - - tmpIndex = null; - }; - - /* - * Clears all data (including any pending changes) in buffer - */ - this._clearData = function () { - this._setRecord(null); - - // Data structure - this._data = []; - this._index = {}; - this._tmpIndex = {}; - this._createIndex(); - - // Arrays to keep track of changes - this._beforeImage = {}; - this._added = []; - this._changed = {}; - this._deleted = []; - }; - - this.hasData = function () { - var data; - - // Check if we should return this table with its nested child table's data as nested - if (this._jsdo._nestChildren) { - data = this._getDataWithNestedChildren(this._data); - } - else { - data = this._getRelatedData(); - } - - if (this._hasEmptyBlocks) { - for (var i = 0; i < data.length; i++) { - var block = data[i]; - if (!block) { - return true; - } - } - } - - return data.length !== 0; - }; - - // Public method that returns data. Before returning data, - // a compaction is performed (removal of null record entries) - this.getData = function (params) { - if (this._needCompaction || this._hasEmptyBlocks) { - this._compact(); - } - - return this._getData(params); - } - - // Private method that returns data. It optimizes compaction (removal of null record entries) - this._getData = function (params) { - var i, - data, - numEmptyBlocks, - newDataArray, - block, - field; - - if (this._needCompaction) { - this._compact(); - } - - if (params && params.filter) { - throw new Error("Not implemented in current version"); - } - // Check if we should return this table with its nested child table's data as nested - else if (this._jsdo._nestChildren) { - data = this._getDataWithNestedChildren(this._data); - } - else { - data = this._getRelatedData(); - } - - if (this._hasEmptyBlocks) { - numEmptyBlocks = 0; - newDataArray = []; - for (i = 0; i < data.length; i += 1) { - block = data[i]; - if (block) { - newDataArray.push(block); - } - else { - numEmptyBlocks++; - } - } - if ((numEmptyBlocks * 100 / this._data.length) >= PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS) - this._needCompaction = true; - - data = newDataArray; - } - else { - // Creates a copy of the data if sort and top are specified - // so that the sorting does not happen in the JSDO memory but - // in a copy of the records - if (params && (params.sort || params.top)) { - newDataArray = []; - for (i = 0; i < data.length; i += 1) { - newDataArray.push(data[i]); - } - data = newDataArray; - } - } - - if (params && (params.sort || params.top)) { - if (params.sort) { - // Converts sort option from Kendo UI to sort option used by the JSDO - var sortFields = []; - for (i = 0; i < params.sort.length; i += 1) { - field = params.sort[i].field; - if (params.sort[i].dir == "desc") { - field += ":DESC"; - } - sortFields.push(field); - } - - // Obtain sortObject from sort options to get compare functions - var sortObject = this._processSortFields(sortFields); - if (sortObject.sortFields && sortObject.sortFields.length > 0) { - sortObject.tableRef = this; - data.sort(this._getCompareFn(sortObject)); - } - } - - if (params.top) { - if (typeof(params.skip) == "undefined") { - params.skip = 0; - } - - data = data.splice(params.skip, params.top); - } - } - - return data; - }; - - this._recToDataObject = function (record, includeChildren) { - var array = [record]; - var dataObject = array; - - if (typeof(includeChildren) == 'undefined') { - includeChildren = false; - } - if (this._jsdo._dataSetName) { - dataObject = {}; - dataObject[this._jsdo._dataSetName] = {}; - dataObject[this._jsdo._dataSetName][this._name] = array; - if (includeChildren && this._children.length > 0) { - var jsrecord = this._findById(record._id, false); - if (jsrecord) { - for (var i = 0; i < this._children.length; i++) { - var tableName = this._children[i]; - dataObject[this._jsdo._dataSetName][tableName] = - this._jsdo._buffers[tableName]._getRelatedData(jsrecord); - } - } - } - } - else { - if (this._jsdo._dataProperty) { - dataObject = {}; - dataObject[this._jsdo._dataProperty] = array; - } - } - return dataObject; - }; - - this._recFromDataObject = function (dataObject) { - var data = {}; - if (dataObject) { - if (this._jsdo._dataSetName) { - if (dataObject[this._jsdo._dataSetName]) - data = dataObject[this._jsdo._dataSetName][this._name]; - } - else { - if (this._jsdo._dataProperty) { - if (dataObject[this._jsdo._dataProperty]) - data = dataObject[this._jsdo._dataProperty]; - } - else if (dataObject.data) { - data = dataObject.data; - } - else { - data = dataObject; - } - } - } - - return data instanceof Array ? data[0] : data; - }; - - // Property: schema - this.getSchema = function () { - return this._schema; - }; - this.setSchema = function (schema) { - this._schema = schema; - }; - - // Private method that returns the ABL data type for the specified field - this._getABLType = function (fieldName) { - var i, schema; - - schema = this.getSchema(); - - for (i = 0; i < schema.length; i++) { - if (schema[i].name == fieldName) { - return schema[i].ablType; - } - } - - return undefined; - }; - - // Private method that returns format property (from catalog) for the specified field - this._getFormat = function (fieldName) { - var i, schema; - - schema = this.getSchema(); - - for (i = 0; i < schema.length; i++) { - if (schema[i].name == fieldName) { - return schema[i].format; - } - } - - return undefined; - }; - - - - this.add = function (values) { - return this._add(values, true, true); - }; - - // Alias for add() method - this.create = this.add; - - this._add = function (values, trackChanges, setWorkingRecord) { - if (typeof(trackChanges) == 'undefined') { - trackChanges = true; - } - if (typeof(setWorkingRecord) == 'undefined') { - setWorkingRecord = true; - } - var record = {}, - i, - j, - value, - prefixElement, - name; - - if (typeof values === "undefined") { - values = {}; - } - - // Assign values from the schema - var schema = this.getSchema(); - for (i = 0; i < schema.length; i++) { - var fieldName = schema[i].name; - if (schema[i].type == "array") { - record[fieldName] = []; - if (schema[i].maxItems) { - for (j = 0; j < schema[i].maxItems; j++) { - record[fieldName][j] = this._jsdo._getDefaultValue(schema[i]); - } - } - - // Assign array values from object parameter - value = values[fieldName]; - if (typeof value != "undefined") { - record[fieldName] = value; - delete values[fieldName]; - } - // Assign values from individual fields from flattened arrays - prefixElement = this._jsdo._getArrayField(fieldName); - if (!record[fieldName]) { - record[fieldName] = []; - } - for (j = 0; j < schema[i].maxItems; j += 1) { - name = prefixElement.name + (j+1); - value = values[name]; - if (typeof value != "undefined") { - if (!this._fields[name.toLowerCase()]) { - // Skip element if a field with the same name exists - // Remove property from object for element since it is not part of the actual schema - delete values[prefixElement.name + (j+1)]; - if (typeof value == 'string' && schema[i].items.type != 'string') { - value = this._jsdo._convertType(value, - schema[i].items.type, - null); - } - record[fieldName][j] = value; - } - } - } - } - else { - record[fieldName] = this._jsdo._getDefaultValue(schema[i]); - } - } - - // Assign values based on a relationship - if (this._jsdo.useRelationships && this._relationship && this._parent) { - if (this._jsdo._buffers[this._parent].record) { - for (j = 0; j < this._relationship.length; j++) { - record[this._relationship[j].childFieldName] = - this._jsdo._buffers[this._parent].record.data[this._relationship[j].parentFieldName]; - } - } - else - throw new Error(msg.getMsgText("jsdoMSG002", this._parent)); - } - // Assign values from object parameter - for (var v in values) { - record[v] = values[v]; - } - - // Specify _id field - do not use schema default - var id; - var idProperty; - if ((idProperty = this._jsdo._resource.idProperty) !== undefined) { - id = record[idProperty]; - } - if (!id) { - id = progress.data._getNextId(); - } - else { - id += ""; - } - id += ""; // ID Property - record._id = id; - - if (this.autoSort - && this._sortRecords - && (this._sortFn !== undefined || this._sortObject.sortFields !== undefined)) { - if (this._needsAutoSorting) { - this._data.push(record); - this._sort(); - } - else { - // Find position of new record in _data and use splice - for (i = 0; i < this._data.length; i++) { - if (this._data[i] === null) continue; // Skip null elements - var ret = this._sortFn ? - this._sortFn(record, this._data[i]) : - this._compareFields(record, this._data[i]); - if (ret == -1) break; - } - this._data.splice(i, 0, record); - } - this._createIndex(); - } - else { - this._data.push(record); - this._index[record._id] = new progress.data.JSIndexEntry(this._data.length - 1); - } - - var jsrecord = new progress.data.JSRecord(this, record); - - // Set record property ignoring relationships - if (setWorkingRecord) - this._setRecord(jsrecord, true); - - if (trackChanges) { - // Save before image - this._beforeImage[record._id] = null; - // End - Save before image - this._added.push(record._id); - } - return jsrecord; - }; - - /* - * Returns records related to the specified jsrecord. - * If jsrecord is not specified the parent working record is used. - */ - this._getRelatedData = function (jsrecord) { - var data = []; - - if (this._data.length === 0) return data; - - if (typeof(jsrecord) == 'undefined') { - if (this._jsdo.useRelationships && this._relationship && this._parent) { - jsrecord = this._jsdo._buffers[this._parent].record; - if (!jsrecord) - throw new Error(msg.getMsgText("jsdoMSG002", this._parent)); - } - } - if (jsrecord) { - // Filter records using relationship - for (var i = 0; i < this._data.length; i++) { - var block = this._data[i]; - if (!block) continue; - - var match = false; - for (var j = 0; j < this._relationship.length; j++) { - match = (jsrecord.data[this._relationship[j].parentFieldName] == - this._data[i][this._relationship[j].childFieldName]); - if (!match) break; - } - if (match) - data.push(this._data[i]); - } - } - else - data = this._data; - - return data; - }; - - - // This method is called on a parent table that has child tables - // where the relationship is specified as NESTED. - // It returns a json array that contains the parent rows. - // If a parent row is involved in nested relationship, - // then references to the child rows are added - // to the parent row in a child table array (providing the nested format) - // We are using the internal jsdo _data arrays, - // and adding a child table array to each parent row that has children. - // Once the caller is done with the nested data, they can call jsdo._unnestData() - // which removes these child table references - this._getDataWithNestedChildren = function (data) { - - // Walk through all the rows and determine if any of its child tables - // should be associated (nested) with the current record - for (var i = 0; i < data.length; i++) { - var parentRecord = data[i]; - - // Now walk thru the parent's children to find any nested children - if (this._children && this._children.length > 0) { - for (var j = 0; j < this._children.length; j++) { - var childBuf = this._jsdo._buffers[this._children[j]]; - - if (childBuf._isNested) { - // If child is nested, then we should walk child records to find matches - for (var k = 0; k < childBuf._data.length; k++) { - var childRecord = childBuf._data[k]; - if (!childRecord) continue; - - var match = false; - for (var m = 0; m < childBuf._relationship.length; m++) { - match = (parentRecord[childBuf._relationship[m].parentFieldName] == - childRecord[childBuf._relationship[m].childFieldName]); - if (!match) break; - } - if (match) { - // Make sure that this parentRecord has an array for its child rows - if (!parentRecord[childBuf._name]) { - parentRecord[childBuf._name] = []; - } - parentRecord[childBuf._name].push(childRecord); - } - - - } // end for; finished adding all child rows for parentRecord - - // The child table may have its own nested children so call recursively - // Use child row array in current parentRecord - if (childBuf._hasNestedChild()) { - childBuf._getDataWithNestedChildren(parentRecord[childBuf._name]); - } - - - } // end if (childBuf._isNested) - } - } - - - } - return data; - - }; - - this._findFirst = function () { - if (this._jsdo.useRelationships && this._relationship && this._parent) { - if (this._jsdo._buffers[this._parent].record) { - // Filter records using relationship - for (var i = 0; i < this._data.length; i++) { - var block = this._data[i]; - if (!block) continue; - - var match = false; - var parentFieldName, childFieldName; - for (var j = 0; j < this._relationship.length; j++) { - parentFieldName = this._relationship[j].parentFieldName; - childFieldName = this._relationship[j].childFieldName; - match = (this._jsdo._buffers[this._parent].record.data[parentFieldName] == - this._data[i][childFieldName]); - if (!match) break; - } - if (match) { - return new progress.data.JSRecord(this, this._data[i]); - } - } - } - } - else { - for (var i = 0; i < this._data.length; i++) { - var block = this._data[i]; - if (!block) continue; - - return new progress.data.JSRecord(this, this._data[i]); - } - } - - - return undefined; - }; - - this._setRecord = function (jsrecord, ignoreRelationships) { - if (jsrecord) { - this.record = jsrecord; - } - else { - this.record = undefined; - } - - // Set child records only if useRelationships is true - if (this._jsdo.useRelationships) { - ignoreRelationships = ((typeof(ignoreRelationships) == 'boolean') && ignoreRelationships); - - if (this._children && this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - var childTable = this._jsdo._buffers[this._children[i]]; - if (!ignoreRelationships && this.record && childTable._relationship) { - childTable._setRecord(childTable._findFirst()); - } - else { - childTable._setRecord(undefined, ignoreRelationships); - } - } - } - } - - if (this._jsdo._defaultTableRef) { - this._jsdo.record = this.record; - } - }; - - this.assign = function (values) { - if (this.record) { - return this.record.assign(values); - } - else - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - }; - - // Alias for assign() method - this.update = this.assign; - - this.remove = function () { - if (this.record) { - return this.record._remove(true); - } - else - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - }; - - this._remove = function (bTrackChanges) { - if (this.record) { - return this.record._remove(bTrackChanges); - } - else - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - }; - - this.getId = function () { - if (this.record) { - return this.record.data._id; - } - else - return 0; - }; - - // getErrors() - JSTableRef - this.getErrors = function () { - return this._lastErrors; - }; - - this.getErrorString = function () { - if (this.record) { - return this.record.data._errorString; - } - else - return 0; - }; - - this.findById = function (id) { - return this._findById(id, true); - }; - - this._findById = function (id, setWorkingRecord) { - if (typeof(setWorkingRecord) == 'undefined') { - setWorkingRecord = true; - } - if (id && this._index[id]) { - var record = this._data[this._index[id].index]; - this.record = record ? (new progress.data.JSRecord(this, record)) : null; - if (setWorkingRecord) - this._setRecord(this.record); - return this.record; - } - - if (setWorkingRecord) - this._setRecord(null); - return null; - }; - - /* - * Finds a record in the JSDO memory using the specified function to determine the record. - */ - this.find = function (fn) { - if (typeof(fn) != 'function') { - throw new Error(msg.getMsgText("jsdoMSG003", "find()")); - } - var data = this._getRelatedData(); - - for (var i = 0; i < data.length; i++) { - var block = data[i]; - if (!block) { - continue; - } - this._setRecord(new progress.data.JSRecord(this, data[i])); - var result = fn(this.record); - if (typeof(result) != 'boolean') { - throw new Error(msg.getMsgText("jsdoMSG007", "find()")); - } - if (result) { - return this.record; - } - } - - this._setRecord(null); - return null; - }; - - /* - * Loops through the records - */ - this.foreach = function (fn) { - if (typeof(fn) != 'function') { - throw new Error(msg.getMsgText("jsdoMSG003", "foreach()")); - } - var numEmptyBlocks = 0; - if (this._needCompaction) - this._compact(); - - var data = this._getRelatedData(); - - this._inforeach = true; - for (var i = 0; i < data.length; i++) { - var block = data[i]; - if (!block) { - numEmptyBlocks++; - continue; - } - - this._setRecord(new progress.data.JSRecord(this, data[i])); - var result = fn(this.record); - if ((typeof(result) != 'undefined') && !result) - break; - } - - this._inforeach = false; - - if ((numEmptyBlocks * 100 / this._data.length) >= PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS) - this._needCompaction = true; - }; - - this._equalRecord = function (rec1, rec2, keyFields) { - var field; - var match = true; - for (var i = 0; i < keyFields.length; i++) { - var fieldName = keyFields[i]; - var value1 = rec1[fieldName]; - var value2 = rec2[fieldName]; - - if (!jsdo[tableName].caseSensitive) { - field = jsdo[tableName]._fields[fieldName.toLowerCase()]; - if (field && field.type == "string") { - if (value1 !== undefined && value1 !== null) - value1 = value1.toUpperCase(); - if (value2 !== undefined && value2 !== null) - value2 = value2.toUpperCase(); - } - } - - match = (value1 == value2); - if (!match) return false; - } - return true; - }; - - // Private method to merge changes using merge modes: APPEND, EMPTY, MERGE and REPLACE - this._getKey = function (record, keyFields) { - var keyObject = {}; - for (var i = 0; i < keyFields.length; i++) { - var fieldName = keyFields[i]; - var value = record[fieldName]; - - if (!jsdo[tableName].caseSensitive) { - var field = jsdo[tableName]._fields[fieldName.toLowerCase()]; - if (field && field.type == "string") { - if (value !== undefined && value !== null) - value = value.toUpperCase(); - } - } - keyObject[fieldName] = value; - } - return JSON.stringify(keyObject); - }; - - this._getCompareFn = function (sortObject) { - if (typeof sortObject == 'function') { - return function (rec1, rec2) { - if (rec1 === null) return 1; - if (rec2 === null) return -1; - - var jsrec1 = new progress.data.JSRecord(this, rec1); - var jsrec2 = new progress.data.JSRecord(this, rec2); - return sortObject(jsrec1, jsrec2); - }; - } - else return function (rec1, rec2) { - var tableRef = sortObject.tableRef; - var sortFields = sortObject.sortFields; - if (!(sortFields instanceof Array)) return 0; - var sortAscending = sortObject.sortAscending; - - if (rec1 === null) return 1; - if (rec2 === null) return -1; - - var field; - for (var i = 0; i < sortFields.length; i++) { - var fieldName = sortFields[i]; - var value1 = rec1[fieldName]; - var value2 = rec2[fieldName]; - - if (!tableRef.caseSensitive) { - field = tableRef._fields[fieldName.toLowerCase()]; - if (field && field.type == "string") { - if (value1 !== undefined && value1 !== null) - value1 = value1.toUpperCase(); - if (value2 !== undefined && value2 !== null) - value2 = value2.toUpperCase(); - } - } - if (value1 > value2 || (value1 === undefined || value1 === null)) - return sortAscending[i] ? 1 : -1; - else if (value1 < value2 || (value2 === undefined && value2 === null)) - return sortAscending[i] ? -1 : 1; - } - return 0; - }; - }; - - this._sortObject = {}; - this._sortObject.tableRef = this; - this._sortObject.sortFields = undefined; - this._sortObject.sortAscending = undefined; - this._compareFields = this._getCompareFn(this._sortObject); - - // _sortRecords - Tells the table reference whether to sort on add, assign and addRecords - this._sortRecords = true; - // Tells the table reference whether an autoSort is required on an add or assign - this._needsAutoSorting = false; - this._sortFn = undefined; - if ((typeof Object.defineProperty) == 'function') { - this._autoSort = true; - Object.defineProperty( - this, - "autoSort", - { - get: function () { - return this._autoSort; - }, - set: function (value) { - if (value) { - this._autoSort = true; - if (this._sortFn || this._sortObject.sortFields) { - this._sort(); - this._createIndex(); - } - } - else - this._autoSort = false; - }, - enumerable: true, - writeable: true - }); - this._caseSensitive = false; - Object.defineProperty( - this, - "caseSensitive", - { - get: function () { - return this._caseSensitive; - }, - set: function (value) { - if (value) { - this._caseSensitive = true; - } - else - this._caseSensitive = false; - if (this.autoSort && - (this._sortObject.sortFields && !this._sortFn)) { - this._sort(); - this._createIndex(); - } - }, - enumerable: true, - writeable: true - }); - } - else { - this.autoSort = true; - this.caseSensitive = false; // caseSensitive is false by default - } - - this._processSortFields = function (sortFields) { - var sortObject = {}; - if (sortFields instanceof Array) { - sortObject.sortFields = sortFields; - sortObject.sortAscending = []; - sortObject.fields = {}; - for (var i = 0; i < sortObject.sortFields.length; i++) { - var idx; - var fieldName; - var field; - - if (typeof (sortObject.sortFields[i]) != 'string') { - throw new Error(msg.getMsgText("jsdoMSG030", "sort field name", "string element")); - } - if ((idx = sortObject.sortFields[i].indexOf(':')) != -1) { - fieldName = sortObject.sortFields[i].substring(0, idx); - var sortOrder = sortObject.sortFields[i].substring(idx + 1); - switch (sortOrder.toUpperCase()) { - case 'ASCENDING': - case 'ASC': - sortObject.sortAscending[i] = true; - break; - case 'DESCENDING': - case 'DESC': - sortObject.sortAscending[i] = false; - break; - default: - throw new Error(msg.getMsgText("jsdoMSG030", - "sort order '" + sortObject.sortFields[i].substring(idx + 1) + "'", - "ASCENDING or DESCENDING")); - } - } - else { - fieldName = sortObject.sortFields[i]; - sortObject.sortAscending[i] = true; - } - if (fieldName != "_id" && this._fields) { - field = this._fields[fieldName.toLowerCase()]; - if (field) { - if (field.type == "array") - throw new Error(msg.getMsgText("jsdoMSG030", "data type found in sort", - "scalar field")); - fieldName = field.name; - } - else - throw new Error(msg.getMsgText("jsdoMSG031", fieldName)); - } - sortObject.sortFields[i] = fieldName; - sortObject.fields[fieldName] = fieldName; - } - } - else { - sortObject.sortFields = undefined; - sortObject.sortAscending = undefined; - sortObject.fields = undefined; - } - return sortObject; - }; - - this.setSortFields = function (sortFields) { - if (sortFields === undefined || sortFields === null) { - this._sortObject.sortFields = undefined; - this._sortObject.sortAscending = undefined; - } - else if (sortFields instanceof Array) { - var sortObject = this._processSortFields(sortFields); - this._sortObject.sortFields = sortObject.sortFields; - this._sortObject.sortAscending = sortObject.sortAscending; - this._sortObject.fields = sortObject.fields; - - if (this.autoSort) { - this._sort(); - this._createIndex(); - } - } - else - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "setSortFields()")); - }; - - this.setSortFn = function (fn) { - // Check that fn parameter is a function - // Valid values are a function, undefined, or null - // Documentation mentions null as a way to clear the sort function - if (fn && typeof (fn) != 'function') { - throw new Error(msg.getMsgText("jsdoMSG030", "parameter in setSortFn()", - "function parameter")); - } - this._sortFn = fn ? this._getCompareFn(fn) : undefined; - if (this.autoSort) { - this._sort(); - this._createIndex(); - } - }; - - this.sort = function (arg1) { - if (arg1 === undefined || arg1 === null) { - throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "sort()")); - } - if (arguments.length !== 1 || - (!(arg1 instanceof Array) && typeof(arg1) != 'function')) { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "sort()")); - } - - if (arg1 instanceof Array) { - var sortObject = this._processSortFields(arg1); - if (sortObject.sortFields && sortObject.sortFields.length > 0) - this._sort(sortObject); - } - else { - this._sort(arg1); - } - this._createIndex(); - }; - - this._sort = function (arg1) { - if (arguments.length === 0 && - (!this.autoSort || (this._sortFn === undefined && this._sortObject.sortFields === undefined))) - return; - - if (arguments.length === 0) { - if (this._sortFn) { - // Sort using function - this._data.sort(this._sortFn); - } - else { - // Sort using sort fields - this._data.sort(this._compareFields); - } - this._needsAutoSorting = false; - } - else { - if (typeof(arg1) == 'function') { - // Sort using function - this._data.sort(this._getCompareFn(arg1)); - } - else { - // Sort using sort fields - arg1.tableRef = this; - this._data.sort(this._getCompareFn(arg1)); - } - if (this.autoSort) - this._needsAutoSorting = true; - } - }; - - /* - * Reads a JSON object into the JSDO memory for the specified table reference. - */ - this.addRecords = function (jsonObject, addMode, keyFields, trackChanges, isInvoke) { - this._jsdo._addRecords(this._name, jsonObject, addMode, keyFields, trackChanges, isInvoke); - }; - - /* - * Accepts changes for the specified table reference. - */ - this.acceptChanges = function () { - var tableRef = this; - - // First, let's remove any "prods:" properties from created and updated records. - // Don't have to worry about deleted records, since they're going away. - for (var id in tableRef._beforeImage) { - // Create - if (tableRef._beforeImage[id] === null) { - var jsrecord = tableRef._findById(id, false); - if (jsrecord !== null) { - tableRef._jsdo._deleteProdsProperties(jsrecord.data, true); - } - - } - // Update - else if (this._changed[id] !== undefined) { - var jsrecord = this._findById(id, false); - if (jsrecord !== null) { - tableRef._jsdo._deleteProdsProperties(jsrecord.data, true); - } - } - } - - tableRef._processed = {}; - tableRef._added = []; - tableRef._changed = {}; - tableRef._deleted = []; - tableRef._beforeImage = {}; - }; - - /* - * Rejects changes for the specified table reference. - */ - this.rejectChanges = function () { - // Reject changes - for (var id in this._beforeImage) { - if (this._beforeImage[id] === null) { - // Undo create - this._jsdo._undoCreate(this, id); - } - else if (this._changed[id] !== undefined) { - // Undo update - this._jsdo._undoUpdate(this, id, true); - } - else { - // Undo delete - this._jsdo._undoDelete(this, id, true); - } - } - - var tableRef = this; - tableRef._processed = {}; - tableRef._added = []; - tableRef._changed = {}; - tableRef._deleted = []; - }; - - this.hasChanges = function () { - return (Object.keys(this._beforeImage).length !== 0); - }; - - this.getChanges = function () { - var result = []; - for (var id in this._beforeImage) { - var item = {rowState: "", record: null}; - // Create - if (this._beforeImage[id] === null) { - item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE]; - item.record = this._findById(id, false); - } - // Update - else if (this._changed[id] !== undefined) { - item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE]; - item.record = this._findById(id, false); - } - // Delete - else { - item.rowState = PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE]; - item.record = new progress.data.JSRecord(this, this._beforeImage[id]); - } - result.push(item); - } - return result; - }; - - /* - * Private method to clear out _errorString for the specified table reference. - * If a row change was rejected, _errorString was set. - * If saveChanges() is called to retry the row change, _errorString needs to be reset. - * This could occur if the autoApplyChanges property is false. - */ - this._clearErrorStrings = function () { - var record = null; - - for (var id in this._beforeImage) { - // Create has id only in _beforeImage entry - if (this._beforeImage[id] === null) { - record = this._findById(id, false); - if (record) { - delete record.data._errorString; - } - } - else { - // Get Updated entry - record = this._findById(id, false); - if (record) { - delete record.data._errorString; - } - else { - // Deleted entry only in beforeImage table - delete this._beforeImage[id]._errorString; - } - } - } - }; - - /* - * Private method to apply changes for the specified table reference. - * If _errorString has been set for a row, row change is rejected. - * If it has not been set, acceptRowChanges() is called. - */ - this._applyChanges = function () { - var i; - - for (var id in this._beforeImage) { - // Create - if (this._beforeImage[id] === null) { - var jsrecord = this._findById(id, false); - - // Check _tmpIndex for temporary _id - if (jsrecord === null - && this._jsdo._resource.idProperty !== undefined) { - if (this._tmpIndex[id]) { - var record = this._data[this._tmpIndex[id].index]; - jsrecord = record ? (new progress.data.JSRecord(this, record)) : null; - delete this._tmpIndex[id]; - } - } - - if (jsrecord !== null) { - if (jsrecord.data._rejected - || (jsrecord.data._errorString !== undefined)) { - this._jsdo._undoCreate(this, id); - } - else { - jsrecord.acceptRowChanges(); - } - } - else { - // Record not present in JSDO memory - // Delete after Create - var found = false; - for (var i = 0; i < this._deleted.length; i++) { - found = (this._deleted[i].data._id == id); - if (found) break; - } - if (!found) { - throw new Error(msg.getMsgText("jsdoMSG000", - "Created record appears to be deleted without a delete operation.")); - } - } - } - // Update - else if (this._changed[id] !== undefined) { - var jsrecord = this._findById(id, false); - if (jsrecord !== null) { - // Record found in JSDO memory - if (jsrecord.data._rejected - || (jsrecord.data._errorString !== undefined)) { - this._jsdo._undoUpdate(this, id); - } - else { - jsrecord.acceptRowChanges(); - } - } - else { - // Record not present in JSDO memory - // Delete after Update - if (this._beforeImage[id]._rejected - || (this._beforeImage[id]._errorString !== undefined)) { - this._jsdo._undoDelete(this, id); - } - else { - var found = false; - for (i = 0; i < this._deleted.length; i++) { - found = (this._deleted[i].data._id == id); - if (found) break; - } - if (!found) { - throw new Error(msg.getMsgText("jsdoMSG000", - "Updated record appears to be deleted without a delete operation.")); - } - } - } - } - // Delete - else { - if (this._beforeImage[id]._rejected - || (this._beforeImage[id]._errorString !== undefined)) { - this._jsdo._undoDelete(this, id); - } - } - } - - var tableRef = this; - tableRef._processed = {}; - tableRef._added = []; - tableRef._changed = {}; - tableRef._deleted = []; - tableRef._beforeImage = {}; - }; - - - /* - * Accepts row changes for the working record at the table reference level. - */ - this.acceptRowChanges = function () { - if (this.record) - return this.record.acceptRowChanges(); - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - }; - - /* - * Rejects row changes for the working record at the table reference level. - */ - this.rejectRowChanges = function () { - if (this.record) - return this.record.rejectRowChanges(); - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - }; - - - /* This method returns true - * if this table has any child tables and at least one of those tables is nested. - * Else if returns false. - */ - this._hasNestedChild = function () { - var hasNestedChild = false; - var childBufObj; - - // If table has children, see if any relationship is NESTED - if (this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - childBufObj = this._jsdo._buffers[this._children[i]]; - - if (childBufObj._isNested) { - hasNestedChild = true; - break; - } - } - } - - return hasNestedChild; - }; - }; - - /* - * Returns a JSRecord for the specified JSDO. - * @param jsdo the JSDO - * @param record the values of the record - */ - progress.data.JSRecord = function JSRecord(tableRef, record) { - this._tableRef = tableRef; - this.data = record; - - this.getId = function () { - return this.data._id ? this.data._id : null; - }; - - this.getErrorString = function () { - return this.data._errorString; - }; - - /* - * Saves a copy of the current record to the before image. - */ - this._saveBeforeImageUpdate = function () { - // Save before image - if (this._tableRef._beforeImage[this.data._id] === undefined) { - // this.data._index = index; - var copy = {}; - this._tableRef._jsdo._copyRecord( - this._tableRef, this.data, copy); - this._tableRef._beforeImage[this.data._id] = copy; - } - - if (this._tableRef._changed[this.data._id] === undefined) { - this._tableRef._changed[this.data._id] = this.data; - } - // End - Save before image - }; - - /* - * - */ - this._sortRecord = function (fields) { - var index = this._tableRef._index[this.data._id].index; - var record = this._tableRef._data[index]; - - if (this._tableRef.autoSort - && this._tableRef._sortRecords - && (this._tableRef._sortFn !== undefined - || this._tableRef._sortObject.sortFields !== undefined)) { - - if (this._tableRef._sortObject.fields) { - if (typeof fields == 'string') { - if (this._tableRef._sortObject.fields[fields] === undefined) - return; // Only sort records if the the specified field is in the sort fields - } - else if (fields instanceof Array) { - var found = false; - for (var i = 0; i < fields.length; i++) { - if (this._tableRef._sortObject.fields[fields[i]] !== undefined) { - found = true; - break; - } - } - if (!found) - return; // Only sort records if the the specified fields are in the sort fields - } - } - - if (this._tableRef._needsAutoSorting) { - this._tableRef._sort(); - this._tableRef._createIndex(); - } - else { - // Find position of new record in _data and use splice - for (var i = 0; i < this._tableRef._data.length; i++) { - if (this._tableRef._data[i] === null) continue; // Skip null elements - if (i == index) continue; // Skip changed record - var ret = this._tableRef._sortFn ? - this._tableRef._sortFn(record, this._tableRef._data[i]) : - this._tableRef._compareFields(record, this._tableRef._data[i]); - if (ret == -1) break; - } - - if (i > index) { - i--; - } - if (i != index) { - this._tableRef._data.splice(index, 1); - this._tableRef._data.splice(i, 0, record); - this._tableRef._createIndex(); - } - } - } - }; - - /* - * Assigns the specified values. - * @param record parameter with the record values - */ - this.assign = function (record) { - if (record === undefined) - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "assign() or update()")); - - this._saveBeforeImageUpdate(); - - var fieldName, - i, - j, - value, - schema = this._tableRef.getSchema(), - prefixElement, - name; - - if (record) { - for (i = 0; i < schema.length; i += 1) { - fieldName = schema[i].name; - value = record[fieldName]; - if (typeof value != "undefined") { - if (typeof value == 'string' && schema[i].type != 'string') { - value = this._tableRef._jsdo._convertType(value, - schema[i].type, - schema[i].items ? schema[i].items.type : null); - } - this.data[fieldName] = value; - } - if (schema[i].type === "array") { - // Assign values from individual fields from flattened arrays - prefixElement = this._tableRef._jsdo._getArrayField(fieldName); - if (!this.data[fieldName]) { - this.data[fieldName] = []; - } - for (j = 0; j < schema[i].maxItems; j += 1) { - name = prefixElement.name + (j+1); - value = record[name]; - if (typeof value != "undefined") { - // Skip element if a field with the same name exists - if (!this._tableRef._fields[name.toLowerCase()]) { - if (typeof value == 'string' && schema[i].items.type != 'string') { - value = this._tableRef._jsdo._convertType(value, - schema[i].items.type, - null); - } - this.data[fieldName][j] = value; - } - } - } - } - } - - this._sortRecord(); - } - return true; - }; - - // Alias for assign() method - this.update = this.assign; - - /* - * Removes the JSRecord. - */ - this.remove = function () { - return this._remove(true); - }; - - this._remove = function (bTrackChanges) { - if (typeof(bTrackChanges) == 'undefined') { - bTrackChanges = true; - } - - var index = this._tableRef._index[this.data._id].index; - var jsrecord = this._tableRef._findById(this.data._id, false); - - if (bTrackChanges) { - // Save before image - var record = this._tableRef._beforeImage[this.data._id]; - if (record === undefined) { - // Record does not exist in the before image - this.data._index = index; - this._tableRef._beforeImage[this.data._id] = this.data; - } - else { - // Record exists in the before image - if (record) { - // Record is not null - a null entry in the before image indicates - // corresponds to an add - // Save the index of the record - // so that an undo would restore the record in the same position in _data - record._index = index; - } - } - // End - Save before image - this._tableRef._deleted.push(jsrecord); - } - - // Set entry to null instead of removing entry - index requires positions to be persistent - this._tableRef._data[index] = null; - this._tableRef._hasEmptyBlocks = true; - delete this._tableRef._index[this.data._id]; - - // Set record property - this._tableRef._setRecord(null); - - return true; - }; - - /* - * Accepts row changes for the specified record. - */ - this.acceptRowChanges = function () { - var id = this.data._id; - if (this._tableRef._beforeImage[id] !== undefined) { - if (this.data._rejected) { - throw new Error(msg.getMsgText("jsdoMSG127")); - } - if (this._tableRef._beforeImage[id] === null) { - // Accept create - // Remove element from _added - for (var i = 0; i < this._tableRef._added.length; i++) { - if (this._tableRef._added[i] == id) { - this._tableRef._added.splice(i, 1); - break; - } - } - this._tableRef._jsdo._deleteProdsProperties(this.data, true); - } - else if (this._tableRef._changed[id] !== undefined) { - // Accept update - delete this._tableRef._changed[id]; - this._tableRef._jsdo._deleteProdsProperties(this.data, true); - } - else { - // Accept delete - // Remove element from _deleted - for (var i = 0; i < this._tableRef._deleted.length; i++) { - if (this._tableRef._deleted[i].data._id == id) { - this._tableRef._deleted.splice(i, 1); - break; - } - } - } - delete tableRef._beforeImage[id]; - } - }; - - /* - * Rejects row changes for the specified record. - */ - this.rejectRowChanges = function () { - var id = this.data._id; - if (this._tableRef._beforeImage[id] !== undefined) { - if (this._tableRef._beforeImage[id] === null) { - // Undo create - this._tableRef._jsdo._undoCreate(this._tableRef, id); - // Remove element from _added - for (var i = 0; i < this._tableRef._added.length; i++) { - if (this._tableRef._added[i] == id) { - this._tableRef._added.splice(i, 1); - break; - } - } - } - else if (this._tableRef._changed[id] !== undefined) { - // Undo update - this._tableRef._jsdo._undoUpdate(this._tableRef, id, true); - delete this._tableRef._changed[id]; - } - else { - // Undo delete - this._tableRef._jsdo._undoDelete(this._tableRef, id, true); - // Remove element from _deleted - for (var i = 0; i < this._tableRef._deleted.length; i++) { - if (this._tableRef._deleted[i].data._id == id) { - this._tableRef._deleted.splice(i, 1); - break; - } - } - } - delete tableRef._beforeImage[id]; - } - }; - - }; - - /* - * Returns a JSDO for the specified resource. - * @param resNameOrParmObj: the resource name or an object that contains the initial values for the JSDO - * (if this is an object, it should include the name property with the resource name - * @param serviceName : name of service (ignored if 1st param is an object containing the initial values) - */ - progress.data.JSDO = function JSDO(resNameOrParmObj, serviceName) { - var _super = {}; - - if (typeof progress.data.Session == 'undefined') { - throw new Error('ERROR: You must include progress.session.js'); - } - - _super.subscribe = this.subscribe; - - // Override for Observable.subscribe - this.subscribe = function(evt) { - var args = Array.prototype.slice.call(arguments); - if (typeof evt === "string") { - // Aliases for events - switch(evt.toLowerCase()) { - case "beforeread": - args[0] = "beforefill"; - break; - case "afterread": - args[0] = "afterfill"; - break; - } - } - _super.subscribe.apply(this, args); - }; - - this._defineProperty = function (tableName, fieldName) { - Object.defineProperty( - this._buffers[tableName], - fieldName, - { - get: function fnGet() { - var name, - index, - element, - fieldInfo; - if (this.record) { - index = fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR); - if (index > 0 && !this._fields[fieldName.toLowerCase()]) { - // Skip element if a field with the same name exists - // Check if field is a flattened array field by quickly checking for the separator - // Extract name and index element - name = fieldName.substring(0, index); - element = fieldName.substring(index + progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length); - fieldInfo = this._fields[name.toLowerCase()]; - if (!isNaN(element) && fieldInfo && (fieldInfo.type === "array")) { - return this.record.data[name][element - 1]; - } - } - return this.record.data[fieldName]; - } - else - return null; - }, - set: function (value) { - var name = fieldName, - index, - element, - fieldInfo; - if (this.record) { - this.record._saveBeforeImageUpdate(); - - try { - index = fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR); - if (index > 0 && !this._fields[fieldName.toLowerCase()]) { - // Skip element if a field with the same name exists - name = fieldName.substring(0, index); - element = fieldName.substring(index + progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length); - fieldInfo = this._fields[name.toLowerCase()]; - if (!isNaN(element) && fieldInfo && (fieldInfo.type === "array")) { - this.record.data[name][element - 1] = value; - return; - } - } - this.record.data[fieldName] = value; - } - finally { - this.record._sortRecord(name); - } - } - }, - enumerable: true, - writeable: true - }); - }; - - Object.defineProperty( - this, - 'hasSubmitOperation', - { - get: function () { - return this._hasSubmitOperation; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'hasCUDOperations', - { - get: function () { - return this._hasCUDOperations; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'defaultTableRef', - { - get: function () { - return this._defaultTableRef; - }, - enumerable: true - } - ); - - // Initial values - this._buffers = {}; // Object of table references - this._numBuffers = 0; - this._defaultTableRef = null; - - this._async = true; - this._dataProperty = null; - this._dataSetName = null; - this.operations = []; - this.useRelationships = true; - - this._session = null; - this._needCompaction = false; - - this._hasCUDOperations = false; - this._hasSubmitOperation = false; - this._useSubmit = false; // For saving saveChanges(useSubmit) param - - this.autoApplyChanges = true; // default should be true to support 11.2 behavior - this._lastErrors = []; - this._localStorage = null; - this._convertForServer; - this._fillMergeMode; - var autoFill = false; - - // Initialize JSDO using init values - if (!arguments[0]) { - throw new Error("JSDO: Parameters are required in constructor."); - } - - if (typeof(arguments[0]) == "string") { - this.name = arguments[0]; - // if ( arguments[1] && (typeof(arguments[1]) == "string") ) - // localServiceName = serviceName; - } - else if (typeof(arguments[0]) == "object") { - var args = arguments[0]; - for (var v in args) { - switch (v) { - case 'autoFill': - autoFill = args[v]; - break; - case 'events': - this._events = {}; - for (var eventName in args[v]) { - this._events[eventName.toLowerCase()] = args[v][eventName]; - } - break; - case 'dataProperty': - this._dataProperty = args[v]; - break; - default: - this[v] = args[v]; - } - } - } - /* error out if caller didn't pass the resource name */ - if ((!this.name) /*|| !(this._session)*/) { - // make this error message more specific? - throw new Error("JSDO: JSDO constructor is missing the value for 'name'"); - } - - /* perform some basic validation on the event object for the proper structure if provided */ - if (this._events) { - if ((typeof this._events) !== 'object') { - throw new Error("JSDO: JSDO constructor event object is not defined as an object"); - } - - /* make sure all the event handlers are sane */ - for (var prop in this._events) { - var evt = this._events[prop]; - if (!(evt instanceof Array)) { - throw new Error('JSDO: JSDO constructor event object for ' + prop + ' must be an array'); - } - evt.forEach(function (el) { - if ((typeof el) !== 'object') { - throw new Error("JSDO: JSDO constuctor event object for " + - prop + " is not defined as an object"); - } - /* listener must have at least fn property defined as a function */ - if ((typeof el.fn) !== 'function') { - throw new Error("JSDO: JSDO event listener for " + prop + " is not a function."); - } - /* scope is optional, but must be an object if provided */ - if (el.scope && (typeof el.scope) !== 'object') { - throw new Error("JSDO: JSDO event listener scope for " + prop + " is not an object."); - } - }); - } - } - - if (this.name) { - // Read resource definition from the Catalog - save reference to JSDO - // Enhance this to deal with multiple services loaded and the same resource - // name is used by more than one service (use the local serviceName var) - this._resource = progress.data.ServicesManager.getResource(this.name); - if (this._resource) { - if (!this.url) - this.url = this._resource.url; - if (!this._dataSetName && this._resource._dataSetName) { - // Catalog defines a DataSet - this._dataSetName = this._resource._dataSetName; - - // Define TableRef property in the JSDO - if (this._resource.dataProperty) { - var buffer = this[this._resource.dataProperty] - = new progress.data.JSTableRef(this, this._resource.dataProperty); - this._buffers[this._resource.dataProperty] = buffer; - } - else { - for (var tableName in this._resource.fields) { - var buffer = this[tableName] - = new progress.data.JSTableRef(this, tableName); - this._buffers[tableName] = buffer; - } - } - } - if (!this._dataProperty && this._resource.dataProperty) - this._dataProperty = this._resource.dataProperty; - - if (!this._dataSetName) { - var tableName = this._dataProperty ? this._dataProperty : ""; - this._buffers[tableName] = new progress.data.JSTableRef(this, tableName); - if (tableName) - this[tableName] = this._buffers[tableName]; - } - - // Set idProperty from table reference level at the resource level - var properties, - tableName; - if (this._dataSetName - && this._resource.schema - && this._resource.schema.properties[this._dataSetName]) { - properties = this._resource.schema.properties[this._dataSetName].properties; - if (Object.keys(properties).length === 1) { - tableName = Object.keys(properties)[0]; - if (properties[tableName].idProperty) { - this._resource.idProperty = properties[tableName].idProperty; - } - } - } - - // Add functions for operations to JSDO object - for (var fnName in this._resource.fn) { - this[fnName] = this._resource.fn[fnName]["function"]; - } - // Check if CUD operations have been defined - this._hasCUDOperations = - this._resource.generic["create"] !== undefined - || this._resource.generic["update"] !== undefined - || this._resource.generic["delete"] !== undefined; - this._hasSubmitOperation = this._resource.generic["submit"] !== undefined; - - /* get a session object, using name of the service to look it up in the list of - * sessions maintained by the ServicesManager - */ - if (!this._session) { - var myservice = progress.data.ServicesManager.getService(this._resource.service.name); - this._session = myservice._session; - this._session._pushJSDOs(this); - } - } - else { - throw new Error(msg.getMsgText("jsdoMSG004", this.name)); - } - } - else { - this._buffers[""] = new progress.data.JSTableRef(this, ""); - } - - if (!this._session) { - throw new Error("JSDO: Unable to get user session for resource '" + this.name + "'"); - } - - // Calculate _numBuffers and _defaultTableRef - for (var buf in this._buffers) { - this._buffers[buf]._parent = null; - this._buffers[buf]._children = []; - // The _relationship object is only specified for the child buffer. - // Currently it is limited to only a single relationship. ie. It does not support the - // where the child buffer is involved in more than one data-relation - this._buffers[buf]._relationship = null; - this._buffers[buf]._isNested = false; - if (!this._defaultTableRef) - this._defaultTableRef = this._buffers[buf]; - this._numBuffers++; - } - if (this._numBuffers != 1) - this._defaultTableRef = null; - else { - // record is used to represent the current record for a table reference - // data corresponds to the values (JSON object) of the data - this.record = null; - } - - // Define caseSensitive property at the JSDO level - if ((typeof Object.defineProperty) == 'function') { - this._caseSensitive = false; // caseSensitive is false by default - Object.defineProperty( - this, - "caseSensitive", - { - get: function () { - return this._caseSensitive; - }, - set: function (value) { - this._caseSensitive = value ? true : false; - - for (var buf in this._buffers) { - this._buffers[buf].caseSensitive = this._caseSensitive; - } - }, - enumerable: true, - writeable: true - }); - this._autoSort = true; // autoSort is true by default - Object.defineProperty( - this, - "autoSort", - { - get: function () { - return this._autoSort; - }, - set: function (value) { - this._autoSort = value ? true : false; - - for (var buf in this._buffers) { - this._buffers[buf].autoSort = this._autoSort; - } - }, - enumerable: true, - writeable: true - }); - } - - // Define _properties property at the JSDO level - this._properties = {}; - if ((typeof Object.defineProperty) == 'function') { - Object.defineProperty( this, - "this._properties", - { - get: function () { - return this._properties; - }, - enumerable: false - } - ); - - } - - - // Set schema for TableRef - if (this._resource && this._resource.fields) { - for (var buf in this._buffers) { - this._buffers[buf]._schema = this._resource.fields[buf]; - this._buffers[buf]._primaryKeys = this._resource.primaryKeys[buf]; - - // Create _fields object used to validate fields as case-insensitive. - this._buffers[buf]._fields = {}; - var fields = this._buffers[buf]._schema; - for (var i = 0; i < fields.length; i++) { - this._buffers[buf]._fields[fields[i].name.toLowerCase()] = fields[i]; - if (typeof(fields[i].origName) !== "undefined") { - if ((typeof(fields[i].origName) !== "string") - || (fields[i].origName.trim() === "")) { - throw new Error(msg.getMsgText("jsdoMSG504", - "JSDO", "Field '" + fields[i].name + "' in resource '" + this._resource.name + "'", "origName")); - } - } - } - - if (this._buffers[buf]._schema && (typeof Object.defineProperty) == 'function') { - // Add fields as properties of the TableRef object - for (var i = 0; i < this._buffers[buf]._schema.length; i++) { - var fieldName = this._buffers[buf]._schema[i].name, - fieldInfo = this._buffers[buf]._schema[i]; - if (typeof(this._buffers[buf][fieldName]) == 'undefined') { - this._defineProperty(buf, fieldName); - } - if (fieldInfo.type === "array") { - for (var j = 0; j < fieldInfo.maxItems; j += 1) { - var name = fieldName + progress.data.JSDO.ARRAY_INDEX_SEPARATOR + (j + 1); - // Skip element if a field with the same name exists - // Only create property if the name is not being used - if (!this._buffers[buf]._fields[name.toLowerCase()]) { - this._defineProperty(buf, name); - } - } - } - } - } - } - // Set schema for when dataProperty is used but not specified via the catalog - if (this._defaultTableRef - && !this._defaultTableRef._schema - && this._resource.fields[""]) { - this._defaultTableRef._schema = this._resource.fields[""]; - } - } - else { - if (this._defaultTableRef) - this._defaultTableRef._schema = []; - } - - // Set isNested property - if (this._numBuffers > 1) { - for (var buf in this._buffers) { - var fields = []; - var found = false; - for (var i = 0; i < this._buffers[buf]._schema.length; i++) { - var field = this._buffers[buf]._schema[i]; - - if (field.items - && field.type == "array" && field.items.$ref) { - if (this._buffers[field.name]) { - found = true; - this._buffers[field.name]._isNested = true; - } - } - else - fields.push(field); - } - // Replace list of fields - removing nested datasets from schema - if (found) - this._buffers[buf]._schema = fields; - } - } - - // Process relationships - if (this._resource && this._resource.relations) { - for (var i = 0; i < this._resource.relations.length; i++) { - var relationship = this._resource.relations[i]; - - // Set relationship information ignoring self-referencing (recursive) relationships - if (relationship.childName - && relationship.parentName - && (relationship.childName !== relationship.parentName)) { - // Set casing of fields in relationFields to be the same as in the schema - if (relationship.relationFields instanceof Array) { - for (var j = 0; j < relationship.relationFields.length; j++) { - var fieldName; - var field; - if (this._buffers[relationship.parentName]._fields) { - fieldName = relationship.relationFields[j].parentFieldName; - field=this._buffers[relationship.parentName]._fields[fieldName.toLowerCase()]; - if (field) { - relationship.relationFields[j].parentFieldName = field.name; - } - else - throw new Error(msg.getMsgText("jsdoMSG010", fieldName)); - } - if (this._buffers[relationship.childName]._fields) { - fieldName = relationship.relationFields[j].childFieldName; - field=this._buffers[relationship.childName]._fields[fieldName.toLowerCase()]; - if (field) { - relationship.relationFields[j].childFieldName = field.name; - } - else - throw new Error(msg.getMsgText("jsdoMSG010", fieldName)); - } - } - } - this._buffers[relationship.childName]._parent = relationship.parentName; - this._buffers[relationship.childName]._relationship = relationship.relationFields; - this._buffers[relationship.parentName]._children.push(relationship.childName); - } - } - } - - - this._getDefaultValue = function (field) { - var defaultValue, - t, m, d, - isDate = false; - - if ((field.type === "string") - && field.format - && (field.format.indexOf("date") !== -1) - && (field["default"])) { - isDate = true; - } else if ((field.type === "array") - && field.ablType - && (field.ablType.indexOf("DATE") != -1) - && (field["default"])) { - isDate = true; - } else { - defaultValue = field["default"]; - } - - if (isDate) { - switch (field["default"].toUpperCase()) { - case "NOW": - defaultValue = new Date().toISOString(); - break; - case "TODAY": - t = new Date(); - m = String((t.getMonth() + 1)); - if (m.length === 1) { - m = '0' + m; - } - d = String((t.getDate())); - if (d.length === 1) { - d = '0' + d; - } - defaultValue = t.getFullYear() + '-' + m + '-' + d; - break; - default: - defaultValue = field["default"]; - } - } - - return defaultValue; - }; - - // Method to calculate the element information of an array given the name, index, and value - // Parameters: - // arrayFieldName The name o the field - // index Optional parameter - if index is null/undefined the name of the element is the prefix - // value Optional parameter - this._getArrayField = function (arrayFieldName, index, value) { - var element = {}; - // ABL arrays are 1-based - element.name = arrayFieldName + progress.data.JSDO.ARRAY_INDEX_SEPARATOR + ((index >= 0) ? (index + 1) : ""); - element.value = value ? value[index] : undefined; - return element; - }; - - this.isDataSet = function () { - return this._dataSetName ? true : false; - }; - - /* handler for invoke operation complete */ - this._invokeComplete = function (jsdo, success, request) { - // only fire on async requests - if (request.async && request.fnName) { - jsdo.trigger('afterInvoke', request.fnName, jsdo, success, request); - } - - if (request.deferred) { - if (success) { - request.deferred.resolve(jsdo, success, request); - } - else { - request.deferred.reject(jsdo, success, request); - } - } - }; - - /* handler for invoke operation success */ - this._invokeSuccess = function (/* jsdo, success, request */) { - // do nothing - }; - - /* handler for invoke operation error */ - this._invokeError = function (/* jsdo, success, request */) { - // do nothing - }; - - /* - * Performs an HTTP request using the specified parameters. This is - * used to perform remote calls for the JSDO for operations defined. - * - */ - this._httpRequest = function (xhr, method, url, reqBody, request) { - - function afterOpenRequest() { - var input = null; - if (reqBody) { - xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); - input = JSON.stringify(reqBody); - } - - try { - xhr.send(input); - } catch (e) { - request.success = false; - request.exception = e; - // let Session check for online/offline - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - } - } - - // if xhr wasn't passed we'll create our own since this is an invoke operation - // if xhr is passed, then it is probably a CRUD operation which is setup with XHR - // in call to session - if (!xhr) { - xhr = new XMLHttpRequest(); - - // only setup the callback handlers if we're responsible for creating the - // xhr call which happens on invoke operations...which is the normal case - // the CRUD operations setup their own callbacks and they have their own - // event handlers so we don't use them here. - xhr.onCompleteFn = this._invokeComplete; - xhr.onSuccessFn = this._invokeSuccess; - xhr.onErrorFn = this._invokeError; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - - // for invokes we always fire the invoke when doing async - if (request.async && request.fnName) { - this.trigger('beforeInvoke', request.fnName, this, request); - } - - // For Invoke operations, wrap reqBody in a request object - // This is not required for CRUD operations since the whole - // reqBody is mapped to the parameter - if (reqBody) { - if (this._resource && this._resource.service) { - var useRequest = this._resource.service.useRequest; - if (this._resource.service.settings - && this._resource.service.settings.useRequest !== undefined) { - useRequest = this._resource.service.settings.useRequest; - } - if (useRequest) { - reqBody = {request: reqBody}; - } - } - } - } - - xhr.request = request; - xhr.jsdo = this; - request.jsdo = this; - request.xhr = xhr; - - this._session._openRequest(xhr, method, url, request.async, afterOpenRequest); - - return request; // Note: for the async case, this does not give us exactly the same behavior - // as when afterOpenRequest is called synchronously, because this returns - // request before its xhr has had its open() called - }; - - - // This method currently is just used by the JSDOReadService. - // It returns data in its non-nested (default) format - this._getDataObject = function () { - var dataObject = {}; - if (this._dataSetName) { - dataObject[this._dataSetName] = {}; - - var oldUseRelationships = this.useRelationships; - // Turn off useRelationships so that getData() returns all the records - try { - this.useRelationships = false; - for (var buf in this._buffers) { - dataObject[this._dataSetName][buf] = this._buffers[buf].getData(); - } - } - finally { - // Restore useRelationships - this.useRelationships = oldUseRelationships; - } - } - else { - if (this._dataProperty) { - dataObject[this._dataProperty] = this.getData(); - } - else - return this.getData(); // Array - } - return dataObject; - }; - - - // This method currently is just used by the JSDOReadService. - // Now that the JSDO Services support nested data, we want to return data nested for those - // relationships that are marked nested. - // - // This method returns a data object containing the nested data. - // If a parent row is involved in nested relationship, - // then references to its child rows are added to the parent row in a child table array - // (providing the nested format). - // We are using the internal jsdo _data arrays, - // and adding a child table array to each parent row that has children. - // Once the caller is done with the nested data, - // they can call jsdo._unnestData() which removes these child table references - // - this._getDataObjectAsNested = function () { - var dataObject = {}; - if (this._dataSetName) { - dataObject[this._dataSetName] = {}; - - try { - // First walk thru all buffers. We need to determine if any of the buffers are - // involved in a nested relationship. If so, we want to return the child's - // data in nested format. - for (var buf in this._buffers) { - var bufObj = this._buffers[buf]; - - - // If this is a child table, and its involved in a nested relationship, - // then just skip. - // This table's data will be nested within each parent row when we - // process the parent table. - if (bufObj._isNested) continue; - - this._nestChildren = false; // default to false - - // If table has children, see if any relationship is NESTED - if (bufObj._children.length > 0) { - for (var i = 0; i < bufObj._children.length; i++) { - var childBufObj = this._buffers[bufObj._children[i]]; - - if (childBufObj._isNested) { - this._nestChildren = true; - break; - } - } - } - - dataObject[this._dataSetName][buf] = this._buffers[buf].getData(); - } - } - catch (e) { - throw new Error(msg.getMsgText("jsdoMSG000", e.message)); - } - finally { - // Set back to default avlue - this._nestChildren = false; - } - } - else { - if (this._dataProperty) { - dataObject[this._dataProperty] = this.getData(); - } - else - return this.getData(); // Array - } - return dataObject; - }; - - - // This method is used in conjunction with _getDataObjectAsNested() in the JSDOReadService. - // _getDataObjectAsNested() adds arrays of child row references to their parent rows. - // Once the JSDOReadService has done its data mapping, we need to remove the references since - // internally the JSDO stores its data in unnested format. - this._unnestData = function () { - - if (this._dataSetName) { - var parentRecord; - var bufObj; - var childBufObj; - - // First walk thru all buffers. We need to determine if any of the buffers are parent - // buffers involved in a nested relationship. If so, then we'll look for any child row arrays - // to delete - for (var buf in this._buffers) { - bufObj = this._buffers[buf]; - - // If we know this table has at least one nested child table, we'll walk thru - // all its rows to determine if the rows have any child row arrays. - // It's more efficient to just walk thru the parent row list once, so we'll - // check for all child row arrays here - - if (bufObj._hasNestedChild()) { - // Now must walk thru the parent rows and delete any child row arrays - for (var i = 0; i < bufObj._data.length; i++) { - parentRecord = bufObj._data[i]; - - for (var j = 0; j < bufObj._children.length; j++) { - childBufObj = this._buffers[bufObj._children[j]]; - - if (parentRecord[childBufObj._name]) { - delete parentRecord[childBufObj._name]; - } - } - - } - } - } // end for - } - }; - - - this._recToDataObject = function (record, includeChildren) { - if (this._defaultTableRef) - return this._defaultTableRef._recToDataObject(record, includeChildren); - throw new Error(msg.getMsgText("jsdoMSG001", "_recToDataObject()")); - }; - - this._recFromDataObject = function (dataObject) { - if (this._defaultTableRef) - return this._defaultTableRef._recFromDataObject(dataObject); - throw new Error(msg.getMsgText("jsdoMSG001", "_recFromDataObject()")); - }; - - this.add = function (obj) { - if (this._defaultTableRef) - return this._defaultTableRef.add(obj); - throw new Error(msg.getMsgText("jsdoMSG001", "add() or create()")); - }; - - // Alias for add() method - this.create = this.add; - - this.hasData = function () { - for (var buf in this._buffers) { - if (this._buffers[this._buffers[buf]._name].hasData()) - return true; - } - return false; - }; - - this.getData = function (params) { - if (this._defaultTableRef) - return this._defaultTableRef.getData(params); - throw new Error(msg.getMsgText("jsdoMSG001", "getData()")); - }; - - this.getSchema = function () { - if (this._defaultTableRef) - return this._defaultTableRef.getSchema(); - throw new Error(msg.getMsgText("jsdoMSG001", "getSchema()")); - }; - - this.findById = function (id) { - if (this._defaultTableRef) - return this._defaultTableRef.findById(id); - throw new Error(msg.getMsgText("jsdoMSG001", "findById()")); - }; - - this._convertType = function (value, type, itemType) { - if ((typeof value != 'string') || (type === null)) return value; - var result = value; - try { - if (type == 'array') { - var result = []; - - value = value.slice(1, value.length - 1); - var elements = value.split(','); - var convertItem = (itemType && (itemType != 'string')); - for (var i = 0; i < elements.length; i++) { - result[i] = convertItem ? this._convertType(elements[i], itemType, null) : elements[i]; - } - } - else if (type == 'integer') { - result = parseInt(value); - } - else if (type == 'number') { - result = parseFloat(value); - } - else { - result = value; - } - } - catch (e) { - throw new Error(msg.getMsgText("jsdoMSG000", - "Error converting string to native type: " + e.message)); - } - return result; - }; - - this.assign = function (values) { - if (this._defaultTableRef) { - return this._defaultTableRef.assign(values); - } - else - throw new Error(msg.getMsgText("jsdoMSG001", "assign() or update()")); - }; - - // Alias for assign() method - this.update = this.assign; - - this.remove = function () { - if (this._defaultTableRef) { - return this._defaultTableRef.remove(); - } - else - throw new Error(msg.getMsgText("jsdoMSG001", "remove()")); - }; - - this.getId = function () { - if (this._defaultTableRef) - return this._defaultTableRef.getId(); - throw new Error(msg.getMsgText("jsdoMSG001", "getId()")); - }; - - // getErrors() - JSDO - this.getErrors = function () { - if (this._defaultTableRef) - return this._defaultTableRef.getErrors(); - throw new Error(msg.getMsgText("jsdoMSG001", "getErrors()")); - }; - - this.getErrorString = function () { - if (this._defaultTableRef) - return this._defaultTableRef.getErrorString(); - throw new Error(msg.getMsgText("jsdoMSG001", "getErrorString()")); - }; - - /* - * Finds a record in the JSDO memory using the specified function to determine the record. - */ - this.find = function (fn) { - if (this._defaultTableRef) - return this._defaultTableRef.find(fn); - throw new Error(msg.getMsgText("jsdoMSG001", "find()")); - }; - - this.foreach = function (fn) { - if (this._defaultTableRef) - return this._defaultTableRef.foreach(fn); - throw new Error(msg.getMsgText("jsdoMSG001", "foreach()")); - }; - - this.setSortFields = function (sortFields) { - if (this._defaultTableRef) - return this._defaultTableRef.setSortFields(sortFields); - throw new Error(msg.getMsgText("jsdoMSG001", "setSortFields()")); - }; - - this.setSortFn = function (fn) { - if (this._defaultTableRef) - return this._defaultTableRef.setSortFn(fn); - throw new Error(msg.getMsgText("jsdoMSG001", "setSortFn()")); - }; - - this.sort = function (arg1) { - if (this._defaultTableRef) - return this._defaultTableRef.sort(arg1); - throw new Error(msg.getMsgText("jsdoMSG001", "sort()")); - }; - - this._clearErrors = function (clearErrorString) { - /* Default to false */ - if (typeof(clearErrorString) == 'undefined') { - clearErrorString = false; - } - - this._lastErrors = []; - for (var buf in this._buffers) { - this._buffers[buf]._lastErrors = []; - - // Clears out errorString for any rejected row change - if (clearErrorString) { - this._buffers[buf]._clearErrorStrings() - } - } - }; - - /** - * setAllRecordsRejected - * - * Sets _allRecordsRejected flag to indicate whether all records have been rejected - * in a saveChanges() call. - * If changes are specified as an array, the changes are used to calculate the flag. - * - * @param {*} param - Array with changes or boolean with value - */ - this._setAllRecordsRejected = function (param) { - var changes, - hasErrors, - hasRejected, - hasCommittedRecords, - i; - - // Note: This function is a single one-stop convenient function to set - // _allRecordsRejected and _someRecordsRejected. - // This logic can be optimized by setting the flags while processing the response. - if (param instanceof Object) { - if (param instanceof Array) { - changes = param; - hasErrors = false; - - this._allRecordsRejected = false; - this._someRecordsRejected = false; - - for (var buf in this._buffers) { - if (this._buffers[buf]._lastErrors.length > 0) { - hasErrors = true; - } - } - if (hasErrors) { - this._allRecordsRejected = true; - this._someRecordsRejected = true; - - for (i = 0; i < changes.length; i += 1) { - if (changes[i].record && !changes[i].record.data._rejected) { - this._allRecordsRejected = false; - return; - } - } - } else if (changes.length > 0) { - this._allRecordsRejected = true; - this._someRecordsRejected = false; - hasCommittedRecords = false; - - for (i = 0; i < changes.length; i += 1) { - if (changes[i].record) { - if (changes[i].record.data._rejected) { - this._someRecordsRejected = true; - } else { - hasCommittedRecords = true; - } - } - } - if (hasCommittedRecords && !this._someRecordsRejected) { - this._allRecordsRejected = false; - } - } - } else { - if (param.operations instanceof Array) { - if (param.operations.length > 0 - && !param.operations[0].success) { - // First operation failed - this._allRecordsRejected = true; - this._someRecordsRejected = true; - - for (i = 0; i < param.operations.length; i += 1) { - if (param.operations[i].success) { - this._allRecordsRejected = false; - return; - } - } - } else { - // Not all operations were rejected - this._allRecordsRejected = false; - this._someRecordsRejected = false; - - for (i = 0; i < param.operations.length; i += 1) { - if (!param.operations[i].success) { - this._someRecordsRejected = true; - return; - } - } - } - } - } - } else { - // Possible values: true, false, undefined - this._allRecordsRejected = param; - this._someRecordsRejected = param; - } - }; - - /* - * Loads data from the HTTP resource. - */ - this.fill = function () { - var objParam, - promise, - properties, - mapping; - - try { - // Clear errors before sending request - this._clearErrors(); - - // Reset _allRecordsRejected - this._setAllRecordsRejected(undefined); - - // Process parameters - if (arguments.length !== 0) { - // Call to fill() has parameters - if (typeof(arguments[0]) == 'function') { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", "fill() or read()")); - } - - properties = this.getMethodProperties("read"); - - // Get plugin if mappingType is not undefined, null, or "" - if (properties && properties.mappingType) { - mapping = progress.data.PluginManager.getPlugin(properties.mappingType); - if (!mapping) { - throw new Error(msg.getMsgText("jsdoMSG118", properties.mappingType)); - } - } - - // fill( string); - var filter; - if (arguments[0] === null || arguments[0] === undefined) { - filter = ""; - } - else if (typeof(arguments[0]) == "string") { - filter = arguments[0]; - objParam = {filter: filter}; - } - else if (typeof(arguments[0]) == "object") { - // options - // ablFilter, id, top, skip, sort - - if (arguments[0].mergeMode){ - this._fillMergeMode = arguments[0].mergeMode - switch(arguments[0].mergeMode) { - case progress.data.JSDO.MODE_APPEND: - case progress.data.JSDO.MODE_EMPTY: - case progress.data.JSDO.MODE_MERGE: - case progress.data.JSDO.MODE_REPLACE: - break; - default: - throw new Error(msg.getMsgText("jsdoMSG022")); - } - - } - - // Use plugin if mappingType is not undefined, null, or "" - if (mapping) { - if (typeof(mapping.requestMapping) === "function") { - objParam = mapping.requestMapping(this, arguments[0], { operation: "read" }); - } - else { - objParam = arguments[0]; - } - } - else { - if (properties.capabilities) { - throw new Error(msg.getMsgText("jsdoMSG119")); - } - objParam = arguments[0]; - } - } - else { - throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "fill() or read()")); - } - } - else { - // fill(); - objParam = null; - } - - var xhr = new XMLHttpRequest(); - var request = { - xhr: xhr, - jsdo: this, - objParam: objParam - }; - - xhr.request = request; - xhr.jsdo = this; - - xhr.onSuccessFn = this._fillSuccess; - xhr.onErrorFn = this._fillError; - xhr.onCompleteFn = this._fillComplete; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - - this.trigger("beforeFill", this, request); - - if (this._resource) { - if (typeof(this._resource.generic.read) == "function") { - xhr.objParam = objParam; - this._resource.generic.read.call(this, xhr, this._async); - if (xhr.request.deferred) { - promise = xhr.request.deferred.promise(); - } - } - else { - throw new Error("JSDO: READ operation is not defined."); - } - } - else { - // Old approach to call READ - this._session._openRequest(xhr, 'GET', this.url, this._async); - try { - xhr.send(null); - } - catch (e) { - request.exception = e; - // get the Client Context ID (AppServer ID) - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - } - } - - // This is the scenario where the read.call did not reach server. i.e., - // some problem in between making successful call to server and we are - // completing the fill() operation with necessary cleanup operations - if (request.success == false && request.exception) { - - if ((typeof xhr.onErrorFn) == 'function') { - xhr.onErrorFn(xhr.jsdo, request.success, request); - } - - // get the Client Context ID (AppServer ID) - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - - if ((typeof xhr.onCompleteFn) == 'function') { - xhr.onCompleteFn(xhr.jsdo, request.success, request); - } - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - var deferred; - if (!(xhr && xhr.deferred)) { - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - } - deferred.reject(this, false, { - errorObject: error - }); - } - } - return promise; - }; - - // Alias for fill() method - this.read = this.fill; - - /* - * Clears all data (including any pending changes) for each buffer in JSDO - */ - this._clearData = function () { - for (var buf in this._buffers) { - this._buffers[buf]._clearData(); - } - }; - - /* - * Executes a CRUD operation using the built-in API. - */ - this._execGenericOperation = function (operation, objParam, request, - onCompleteFn, onSuccessFn, onErrorFn) { - - var xhr = new XMLHttpRequest(); - request.xhr = xhr; - request.jsdo = this; - request.objParam = objParam; - request.operation = operation; - xhr.jsdo = this; - xhr.onCompleteFn = onCompleteFn; - xhr.onSuccessFn = onSuccessFn; - xhr.onErrorFn = onErrorFn; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - xhr.request = request; - - this._convertRequestData(objParam); - - var operationStr; - switch (operation) { - case progress.data.JSDO._OP_READ: - case progress.data.JSDO._OP_CREATE: - case progress.data.JSDO._OP_UPDATE: - case progress.data.JSDO._OP_DELETE: - case progress.data.JSDO._OP_SUBMIT: - operationStr = PROGRESS_JSDO_OP_STRING[operation]; - break; - default: - throw new Error("JSDO: Unexpected operation " + operation + " in HTTP request."); - } - - if (this._resource) { - if (typeof(this._resource.generic[operationStr]) == "function") { - xhr.objParam = objParam; - this._resource.generic[operationStr](xhr, this._async); - } - else { - // "JSDO: {1} operation is not defined." - throw new Error(msg.getMsgText("jsdoMSG046", operationStr.toUpperCase() )); - } - } - }; - - // Determines if any fields need a conversion when data sent to backend - this._initConvertForServer = function () { - var i, buf, schema; - - // If set, we're good. Field lists for conversion have already been created - if (this._convertForServer !== undefined) { - return; - } - - this._convertForServer = false; - for (buf in this._buffers) { - schema = this._buffers[buf].getSchema(); - this._buffers[buf]._convertFieldsForServer = []; - this._buffers[buf]._convertForServer = false; - - // Check if any fields need conversion - for (i = 0; i < schema.length; i++) { - if (schema[i].ablType && this._ablTypeNeedsConversion(schema[i].ablType)) { - this._buffers[buf]._convertFieldsForServer.push({name: schema[i].name, - ablType: schema[i].ablType}); - } - } - if (this._buffers[buf]._convertFieldsForServer.length > 0) { - this._convertForServer = true; - this._buffers[buf]._convertForServer = true; - } - } - }; - - this._convertRequestData = function (objParam) { - var buf, - beforeData; - - if (this._convertForServer === false) { - return; - } - - // We know at least one table has a field to convert - for (buf in this._buffers) { - if (this._buffers[buf]._convertForServer) { - if (objParam[this._dataSetName]) { - // First convert after-table - if (objParam[this._dataSetName][buf]) { - this._convertTableData(this._buffers[buf], objParam[this._dataSetName][buf]); - } - - // Now let's convert before-image data - beforeData = objParam[this._dataSetName]["prods:before"]; - if (beforeData && beforeData[buf]) { - this._convertTableData(this._buffers[buf], beforeData[buf]); - } - } - // This is for case where saveChanges(false) is called with no before-image data - else if (objParam[buf]) { - this._convertTableData(this._buffers[buf], objParam[buf]); - } - } - } - }; - - this._convertTableData = function (tableRef, tableData) { - var i; - - for (i = 0; i < tableData.length; i++) { - this._convertRowData(tableRef, tableData[i]); - } - }; - - this._convertRowData = function (tableRef, record) { - var i, - field; - - for (i = 0; i < tableRef._convertFieldsForServer.length; i += 1) { - field = tableRef._convertFieldsForServer[i]; - record[field.name] = this._convertField(record[field.name], field.ablType); - } - }; - - this._convertField = function (value, ablType) { - var result; - - if (value === undefined || value === null) { - return value; - } - - if (value instanceof Array) { - var resultArray = []; - for (var i = 0; i < value.length; i++) { - resultArray[i] = this._convertField(value[i], ablType); - } - return resultArray; - } - - try { - switch (ablType.toUpperCase()) { - case "DATE": - case "DATETIME": - if (typeof value === 'string') { - result = value; - } - else if (value instanceof Date) { - result = this._convertDate(value, ablType.toUpperCase()); - } - else { - throw new Error("Unexpected value for " + ablType.toUpperCase() + "."); - } - break; - default: - result = value; - break; - } - } - catch (e) { - throw new Error(msg.getMsgText("jsdoMSG000", - "Error in _convertField for value: " + value + ". " + e.message)); - } - - return result; - }; - - // Convert Date object to string for DATE and DATETIME ablTypes - // Not necessary to do for DATETIME-TZ since JSON.stringify() will do correct conversion - this._convertDate = function (value, ablType) { - var result = value; - - // DATE format should be in ISO 8601 format yyyy-mm-dd - // DATETIME format should be in ISO 8601 format yyyy-mm-ddThh:mm:ss.sss - if (ablType === "DATE" || ablType === "DATETIME") { - result = progress.util._pad(value.getFullYear(), 4) + '-' + - progress.util._pad(value.getMonth() + 1) + '-' + - progress.util._pad(value.getDate()); - - if (ablType === "DATETIME") { - result = result + "T" + - progress.util._pad(value.getHours()) + ":" + - progress.util._pad(value.getMinutes()) + ":" + - progress.util._pad(value.getSeconds()) + "." + - progress.util._pad(value.getMilliseconds(), 3); - } - } - - return result; - }; - - - this._ablTypeNeedsConversion = function (ablType) { - - var needsConversion = false; - - switch (ablType.toUpperCase()) { - case "DATE": - case "DATETIME": - needsConversion = true; - break; - } - - return needsConversion; - }; - - - - this._undefWorkingRecord = function () { - // Set record property - for (var buf in this._buffers) { - this._buffers[buf]._setRecord(null); - } - }; - - /* - * Saves changes in the JSDO. Save any outstanding changes for CREATES, UPDATE, and DELETEs - */ - this.saveChanges = function (useSubmit) { - var deferred, - promise, - request; - - try { - if (useSubmit === undefined) { - useSubmit = false; - } - else if (typeof(useSubmit) != 'boolean') { - throw new Error(msg.getMsgText("jsdoMSG025", "JSDO", "saveChanges()")); - } - - // _fireCUDTriggersForSubmit() needs to know how saveChanges() was called - this._useSubmit = useSubmit; - - // confirm the availability of the operations required for executing this saveChanges call - // (_checkThatJSDOHasRequiredOperations() throws an error if there's a missing operation, - // which this method deliberately allows to bubble up to the caller) - this._checkThatJSDOHasRequiredOperations(); - - // Don't allow Submit with just a temp-table if autoApplyChanges is true - if ( !this._dataSetName && this._useSubmit && this.autoApplyChanges) { - /* error message: "autoApplyChanges is not supported for submit with a temp-table */ - /* Use jsdo.autoApplyChanges = false." */ - throw new Error(msg.getMsgText("jsdoMSG124")); - } - - // Check if any data being sent to server needs to first be converted - this._initConvertForServer(); - - // Clear errors before sending request - this._clearErrors(true); - - // Reset _allRecordsRejected - this._setAllRecordsRejected(undefined); - - request = { - jsdo: this - }; - - this.trigger("beforeSaveChanges", this, request); - - if (useSubmit) { - /* Pass in request object. - * Need to use same request object so before and after saveChanges events - * are in sync in JSDO Submit Service. */ - promise = this._syncDataSetForSubmit(request); - } - else if (this._dataSetName) { - promise = this._syncDataSetForCUD(); - } - else { - promise = this._syncSingleTable(); - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - deferred.reject(this, false, { - errorObject: error - }); - } - } - return promise; - }; - - /* - * _checkThatJSDOHasRequiredOperations - - This method is intended to be used by the saveChanges() method to determine whether - the JSDO's resource definition includes the operations necessary for executing the - types of changes that are pending in the JSDO. It checks for Submit if saveChanges - was called with useSubmit set to true, otherwise it checks whatever CUD operations are - pending. - The JSDO's internal _useSubmit property must be set correctly before this method - is called - */ - this._checkThatJSDOHasRequiredOperations = function( ) { - var checkedDelete = false, - checkedCreate = false, - checkedUpdate = false, - buf, - tableRef; - - if (!this._hasCUDOperations && !this._hasSubmitOperation) { - throw new Error(msg.getMsgText("jsdoMSG026")); - } - - // Validate the use of Submit - if (this._useSubmit) { - if (!this._hasSubmitOperation) { - // "JSDO: {1} operation is not defined."; - throw new Error(msg.getMsgText("jsdoMSG046", "SUBMIT")); - } - else { - return; - } - } - - if (!this._resource) { - // Need the _resource property to do the validation. If not present, just return - // and let execution run as normal (presumably there will be an error) - return; - } - - // Find the pending operations and make sure they are defined - for (buf in this._buffers) { - - tableRef = this._buffers[buf]; - - if (!checkedDelete && tableRef._deleted.length > 0) { - this._confirmOperationExists( progress.data.JSDO._OP_DELETE ); - checkedDelete = true; - } - - if (!checkedCreate && tableRef._added.length > 0) { - this._confirmOperationExists( progress.data.JSDO._OP_CREATE ); - checkedCreate = true; - } - - if (!checkedUpdate && Object.keys(tableRef._changed).length > 0) { - this._confirmOperationExists( progress.data.JSDO._OP_UPDATE ); - checkedUpdate = true; - } - - if ( checkedDelete && checkedCreate && checkedUpdate ) { - break; - } - } - - }; - - // Determines whether a given operation is defined by the JSDO's resource - // throws an error if it's not defined - this._confirmOperationExists = function(operation) { - var operationStr = PROGRESS_JSDO_OP_STRING[operation]; - if (typeof(this._resource.generic[operationStr]) !== "function") { - // "JSDO: {1} operation is not defined." - throw new Error(msg.getMsgText("jsdoMSG046", operationStr.toUpperCase() )); - } - }; - - this.invoke = function (name, object) { - var deferred, promise; - - try { - var request = this[name](object); - if (request.deferred) { - deferred = request.deferred; - promise = request.deferred.promise(); - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - if (!deferred) { - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - } - deferred.reject(this, false, { - errorObject: error - }); - } - } - return promise; - }; - - /* - * Synchronizes changes for a TableRef - * - * @param operation HTTP operation to be performed - * @param tableRef Handle to the TableRef - * @param batch Optional. batch information associated with the sync operation. - * If not specified a new one will be created. Used for saving datasets. - */ - this._syncTableRef = function (operation, tableRef, batch) { - var rowData, - requestData, - jsonObject, - dataSetObject; - - if (tableRef._visited) return; - tableRef._visited = true; - - //ensure batch object is sane - if (!batch) { - batch = { - operations: [] - }; - } else if (!batch.operations) { - batch.operations = []; - } - - // Before children - // Create parent records before children - switch (operation) { - case progress.data.JSDO._OP_CREATE: - for (var i = 0; i < tableRef._added.length; i++) { - var id = tableRef._added[i]; - var jsrecord = tableRef._findById(id, false); - - if (!jsrecord) continue; - if (tableRef._processed[id]) continue; - tableRef._processed[id] = jsrecord.data; - - rowData = {}; - jsonObject = {}; - - // Make copy of row data, in case we need to convert data for backend.. - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - - if (this.isDataSet()) { - jsonObject[this._dataSetName] = {}; - dataSetObject = jsonObject[this._dataSetName]; - if (this._useBeforeImage("create")) { - dataSetObject["prods:hasChanges"] = true; - dataSetObject[tableRef._name] = []; - - // Dont need to send prods:id for create, - // no before table or error table to match - // Dont need to send prods:clientId - since only sending one record - rowData["prods:rowState"] = "created"; - rowData["prods:clientId"] = jsrecord.data._id; - - delete rowData["_id"]; - - dataSetObject[tableRef._name].push(rowData); - } - else { - dataSetObject[tableRef._name] = []; - dataSetObject[tableRef._name].push(rowData); - } - } - else { - jsonObject = rowData; - } - - - var request = { - operation: operation, - batch: batch, - jsrecord: jsrecord, - jsdo: this - }; - batch.operations.push(request); - - jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); - this.trigger("beforeCreate", this, jsrecord, request); - - this._execGenericOperation( - progress.data.JSDO._OP_CREATE, jsonObject, request, this._createComplete, - this._createSuccess, this._createError); - } - break; - case progress.data.JSDO._OP_UPDATE: - for (var id in tableRef._changed) { - var jsrecord = tableRef._findById(id, false); - - if (!jsrecord) continue; - if (tableRef._processed[id]) continue; - tableRef._processed[id] = jsrecord.data; - - rowData = {}; - jsonObject = {}; - requestData = {}; - - // Make copy of row data, in case we need to convert data for backend.. - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - - var useBeforeImageFormat = false; - if (this.isDataSet()) { - if (this._useBeforeImage("update")) { - useBeforeImageFormat = true; - jsonObject[this._dataSetName] = {}; - dataSetObject = jsonObject[this._dataSetName]; - dataSetObject["prods:hasChanges"] = true; - dataSetObject[tableRef._name] = []; - - // Dont need to send prods:clientId - since only sending one record - rowData["prods:id"] = jsrecord.data._id; - rowData["prods:rowState"] = "modified"; - rowData["prods:clientId"] = jsrecord.data._id; - delete rowData["_id"]; - - dataSetObject[tableRef._name].push(rowData); - - // Now create before-table data - dataSetObject["prods:before"] = {}; - var beforeObject = dataSetObject["prods:before"]; - beforeObject[tableRef._name] = []; - - var beforeRowData = {}; - // Dont need to send prods:clientId - since only sending one record - beforeRowData["prods:id"] = jsrecord.data._id; - - tableRef._jsdo._copyRecord(tableRef, - tableRef._beforeImage[jsrecord.data._id], beforeRowData); - delete beforeRowData["_id"]; - - beforeObject[tableRef._name].push(beforeRowData); - } - } - - if (!useBeforeImageFormat) { - if (this._resource.service - && this._resource.service.settings - && this._resource.service.settings.sendOnlyChanges) { - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData, - tableRef._beforeImage[jsrecord.data._id]); - - if (this._resource.idProperty) { - requestData[this._resource.idProperty] = - jsrecord.data[this._resource.idProperty]; - } - else { - throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, - " for sendOnlyChanges property")); - } - } - else - requestData = rowData; - - if (this.isDataSet()) { - jsonObject[this._dataSetName] = {}; - dataSetObject = jsonObject[this._dataSetName]; - dataSetObject[tableRef._name] = []; - dataSetObject[tableRef._name].push(requestData); - } - else { - jsonObject = rowData; - } - } - - var request = { - jsrecord: jsrecord, - operation: operation, - batch: batch, - jsdo: this - }; - batch.operations.push(request); - - jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); - this.trigger("beforeUpdate", this, jsrecord, request); - - this._execGenericOperation( - progress.data.JSDO._OP_UPDATE, jsonObject, request, this._updateComplete, - this._updateSuccess, this._updateError); - } - break; - } - - // Call _syncTableRef on child tables - for (var i = 0; i < tableRef._children.length; i++) { - var childTableName = tableRef._children[i]; - this._syncTableRef( - operation, this._buffers[childTableName], batch); - } - - // After children - // Delete parent records after children - - if (operation == progress.data.JSDO._OP_DELETE) { - for (var i = 0; i < tableRef._deleted.length; i++) { - var id = tableRef._deleted[i]._id; - var jsrecord = tableRef._deleted[i]; - - if (!jsrecord) continue; - tableRef._processed[id] = jsrecord.data; - - rowData = {}; - jsonObject = {}; - requestData = {}; - - // Make copy of row data, in case we need to convert data for backend.. - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - - var useBeforeImageFormat = false; - if (this.isDataSet()) { - if (this._useBeforeImage("delete")) { - useBeforeImageFormat = true; - jsonObject[this._dataSetName] = {}; - dataSetObject = jsonObject[this._dataSetName]; - dataSetObject["prods:hasChanges"] = true; - - // There is no after tables for deletes, so just create before-table data - dataSetObject["prods:before"] = {}; - var beforeObject = dataSetObject["prods:before"]; - beforeObject[tableRef._name] = []; - - var beforeRowData = {}; - - // Dont need to send prods:id for delete, no after table or error table to match - // Dont need to send prods:clientId - since only sending one record - beforeRowData["prods:rowState"] = "deleted"; - beforeRowData["prods:clientId"] = jsrecord.data._id; - - tableRef._jsdo._copyRecord(tableRef, - tableRef._beforeImage[rowData._id], beforeRowData); - beforeObject[tableRef._name].push(beforeRowData); - } - } - - if (!useBeforeImageFormat) { - if (this._resource.service - && this._resource.service.settings - && this._resource.service.settings.sendOnlyChanges) { - if (this._resource.idProperty) { - requestData[this._resource.idProperty] = - jsrecord.data[this._resource.idProperty]; - } - else { - throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, - " for sendOnlyChanges property")); - } - } - else { - requestData = rowData; - } - - if (this.isDataSet()) { - jsonObject[this._dataSetName] = {}; - dataSetObject = jsonObject[this._dataSetName]; - dataSetObject[tableRef._name] = []; - dataSetObject[tableRef._name].push(requestData); - } - else { - jsonObject = rowData; - } - } - - var request = { - batch: batch, - jsrecord: jsrecord, - operation: operation, - jsdo: this - }; - - batch.operations.push(request); - - jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); - this.trigger("beforeDelete", this, jsrecord, request); - - this._execGenericOperation( - progress.data.JSDO._OP_DELETE, jsonObject, request, this._deleteComplete, - this._deleteSuccess, this._deleteError); - } - } - }; - - /* - * Returns true if the specified operation type was specified in the catalog as useBeforeImage, - * else it returns false. - */ - this._useBeforeImage = function (opType) { - - for (var idx = 0; idx < this._resource.operations.length; idx++) { - if (this._resource.operations[idx].type == opType) { - return this._resource.operations[idx].useBeforeImage; - } - } - - return false; - }; - - - /* - * Synchronizes changes for a DataSet. This is called when we send over one row at at time - * to Create, Update and Delete methods. - * It handles row with or without before-image data. - */ - this._syncDataSetForCUD = function () { - var batch = { - operations: [] - }, - deferred, - promise; - - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - batch.deferred = deferred; - - // Process buffers - // Synchronize deletes - for (var buf in this._buffers) { - this._buffers[buf]._visited = false; - } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._syncTableRef( - progress.data.JSDO._OP_DELETE, tableRef, batch); - } - - // Synchronize adds - for (var buf in this._buffers) { - this._buffers[buf]._visited = false; - } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._syncTableRef( - progress.data.JSDO._OP_CREATE, tableRef, batch); - } - - // Synchronize updates - for (var buf in this._buffers) { - this._buffers[buf]._visited = false; - } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._syncTableRef( - progress.data.JSDO._OP_UPDATE, tableRef, batch); - } - - if (this.autoApplyChanges) { - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - tableRef._processed = {}; - tableRef._added = []; - tableRef._changed = {}; - tableRef._deleted = []; - } - } - - // OE00229270 If _async is false, this ensures that afterSaveChanges() is called just once - // We now do this after all operations have been processed - // Alternatively, scenario where the saveChanges() is invoked without - // performing any operations. In that scenario we have to process this. - if (!this._async || (batch.operations && batch.operations.length === 0)) { - if (this._isBatchComplete(batch)) { - var success = this._isBatchSuccess(batch); - var request = { - batch: batch, - success: success - }; - this._undefWorkingRecord(); - - // Save error messages - this._lastErrors = []; - if (!success && batch.operations) { - this._updateLastErrors(this, batch, null); - } - this._setAllRecordsRejected(batch); - - this._fireAfterSaveChanges(success, request); - } - } - // end OE00229270 - - return promise; - }; - - - /* - * Synchronizes changes for a single table - */ - this._syncSingleTable = function () { - var deferred, promise; - if (!this._defaultTableRef) return; - var tableRef = this._defaultTableRef; - - var batch = { - operations: [] - }; - - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - batch.deferred = deferred; - - var fireAfterSaveChanges = false; - - // Skip delete for records that were added - // mark them as processed - var addedRecords = {}; - for (var i = 0; i < tableRef._added.length; i++) { - var id = tableRef._added[i]; - addedRecords[id] = id; - } - for (var i = 0; i < tableRef._deleted.length; i++) { - var jsrecord = tableRef._deleted[i]; - if (!jsrecord) continue; - - var id = jsrecord.data._id; - if (addedRecords[id]) { - // Set request object - // Properties async, fnName, objParam, and response - // are not set when the HTTP request is suppressed - var request = { - success: true, - xhr: undefined, - operation: progress.data.JSDO._OP_DELETE, - batch: batch, - jsrecord: jsrecord, - jsdo: this - }; - batch.operations.push(request); - tableRef._processed[id] = jsrecord.data; - - var jsdo = request.jsdo; - try { - request.jsrecord._tableRef.trigger("afterDelete", jsdo, request.jsrecord, - request.success, request); - jsdo.trigger("afterDelete", jsdo, request.jsrecord, request.success, request); - } finally { - request.complete = true; - } - - fireAfterSaveChanges = true; - } - } - addedRecords = null; - - // Synchronize deletes - for (var i = 0; i < tableRef._deleted.length; i++) { - var jsrecord = tableRef._deleted[i]; - if (!jsrecord) continue; - - var id = jsrecord.data._id; - if (tableRef._processed[id]) continue; - - tableRef._processed[id] = jsrecord.data; - fireAfterSaveChanges = false; - - var xhr = new XMLHttpRequest(); - xhr.jsdo = this; - - var request = { - xhr: xhr, - operation: progress.data.JSDO._OP_DELETE, - batch: batch, - jsrecord: jsrecord, - jsdo: this - }; - batch.operations.push(request); - xhr.onCompleteFn = this._deleteComplete; - xhr.onSuccessFn = this._deleteSuccess; - xhr.onErrorFn = this._deleteError; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - xhr.request = request; - - jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); - this.trigger("beforeDelete", this, jsrecord, request); - - var requestData = {}; - if (this._resource.service - && this._resource.service.settings - && this._resource.service.settings.sendOnlyChanges) { - if (this._resource.idProperty) { - requestData[this._resource.idProperty] = jsrecord.data[this._resource.idProperty]; - } - else { - throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, - " for sendOnlyChanges property")); - } - } - else { - // We must copy record in case _convertRowData() needs to make conversion - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData); - } - - if (tableRef._convertForServer) { - this._convertRowData(tableRef, requestData); - } - - if (this._resource) { - if (typeof(this._resource.generic["delete"]) == "function") { - xhr.objParam = requestData; - this._resource.generic["delete"].call(this, xhr, this._async); - } - else { - throw new Error("JSDO: DELETE operation is not defined."); - } - } - else { - this._session._openRequest(xhr, 'DELETE', this.url + '/' + id, true); - try { - xhr.send(null); - } catch (e) { - request.success = false; - request.exception = e; - // let Session check for online/offline - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - } - - } - } - - // Synchronize adds - for (var i = 0; i < tableRef._added.length; i++) { - var id = tableRef._added[i]; - var jsrecord = tableRef._findById(id, false); - var requestData = {}; - - if (!jsrecord) continue; - if (tableRef._processed[id]) continue; - tableRef._processed[id] = jsrecord.data; - fireAfterSaveChanges = false; - - var xhr = new XMLHttpRequest(); - xhr.jsdo = this; - var request = { - xhr: xhr, - jsrecord: jsrecord, - batch: batch, - operation: progress.data.JSDO._OP_CREATE, - jsdo: this - }; - batch.operations.push(request); - xhr.onCompleteFn = this._createComplete; - xhr.onSuccessFn = this._createSuccess; - xhr.onErrorFn = this._createError; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - xhr.request = request; - - jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); - this.trigger("beforeCreate", this, jsrecord, request); - - if (this._resource) { - if (typeof(this._resource.generic.create) == "function") { - this._copyRecord(tableRef, jsrecord.data, requestData); - if (this._resource.idProperty !== undefined && jsrecord.data._id !== undefined) { - // Remove _id when idProperty is set - delete requestData._id; - } - - if (tableRef._convertForServer) { - this._convertRowData(tableRef, requestData); - } - - xhr.objParam = requestData; - - this._resource.generic.create.call(this, xhr, this._async); - } - else { - throw new Error("JSDO: CREATE operation is not defined."); - } - - } - else { - this._session._openRequest(xhr, 'POST', this.url, true); - xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); - this._copyRecord(tableRef, jsrecord.data, requestData); - - if (tableRef._convertForServer) { - this._convertRowData(tableRef, requestData); - } - var input = JSON.stringify(requestData); - - try { - xhr.send(input); - } catch (e) { - request.success = false; - request.exception = e; - // let Session check for online/offline - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - } - - } - } - - // Synchronize updates - for (var id in tableRef._changed) { - var jsrecord = tableRef._findById(id, false); - - if (!jsrecord) continue; - if (tableRef._processed[id]) continue; - tableRef._processed[id] = jsrecord.data; - fireAfterSaveChanges = false; - - var xhr = new XMLHttpRequest(); - var request = { - xhr: xhr, - jsrecord: jsrecord, - operation: progress.data.JSDO._OP_UPDATE, - batch: batch, - jsdo: this - }; - xhr.request = request; - xhr.jsdo = this; - batch.operations.push(request); - xhr.onCompleteFn = this._updateComplete; - xhr.onSuccessFn = this._updateSuccess; - xhr.onErrorFn = this._updateError; - xhr.onreadystatechange = this.onReadyStateChangeGeneric; - - jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); - this.trigger("beforeUpdate", this, jsrecord, request); - - var requestData = {}; - if (this._resource.service - && this._resource.service.settings - && this._resource.service.settings.sendOnlyChanges) { - - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData, - tableRef._beforeImage[jsrecord.data._id]); - - if (this._resource.idProperty) { - requestData[this._resource.idProperty] = jsrecord.data[this._resource.idProperty]; - } - else { - throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, - " for sendOnlyChanges property")); - } - } - else { - // We must copy record in case _convertRowData() needs to make conversion - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, requestData); - } - - if (tableRef._convertForServer) { - this._convertRowData(tableRef, requestData); - } - - if (this._resource) { - if (typeof(this._resource.generic.update) == "function") { - xhr.objParam = requestData; - this._resource.generic.update.call(this, xhr, this._async); - } - else { - throw new Error("JSDO: UPDATE operation is not defined."); - } - } - else { - this._session._openRequest(xhr, 'PUT', this.url + '/' + id, this._async); - xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); - - var input = JSON.stringify(requestData); - - try { - xhr.send(input); - } catch (e) { - request.success = false; - request.exception = e; - // let Session check for online/offline - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - } - } - } - - if (this.autoApplyChanges) { - // Arrays to keep track of changes - tableRef._added = []; - tableRef._changed = {}; - tableRef._deleted = []; - tableRef._processed = {}; - } - - // OE00229270 If _async is false, fire afterSaveChanges() after all operations are processed - if (!this._async) - fireAfterSaveChanges = true; - - if (fireAfterSaveChanges) { - var jsdo = this; - var request = { - batch: batch, - success: true - }; - - // Save error messages - jsdo._lastErrors = []; - if (batch.operations) { - jsdo._updateLastErrors(jsdo, batch, null); - } - - jsdo._undefWorkingRecord(); - jsdo._fireAfterSaveChanges(request.success, request); - } - - return promise; - }; - - /************************************************************************ - * - * Synchronizes changes for a DataSet or a temp-table, sending over the entire change-set - * to saveChanges() on server - * If sync'ing a DataSet, sends over before-image and after-image data. - */ - this._syncDataSetForSubmit = function (request) { - var deferred, - promise, - jsonObject, - completeFn = this._saveChangesComplete, - successFn = this._saveChangesSuccess, - errorFn = this._saveChangesError; - - deferred = new progress.util.Deferred(); - promise = deferred.promise(); - request.deferred = deferred; - - request.jsrecords = []; - - // First thing to do is to create jsonObject with before and after image data for all - // records in change-set (creates, updates and deletes) - if ( this._dataSetName ) { - jsonObject = this._createChangeSet(this._dataSetName, false, request); - } - else { - // just a temp-table. Need to create it somewhat differently from DS - // (no before and after image data) - jsonObject = this._createTTChangeSet(this._defaultTableRef, request); - successFn = this._saveChangesSuccessTT; // will process success response differently from DS - } - - this._execGenericOperation(progress.data.JSDO._OP_SUBMIT, jsonObject, request, - completeFn, successFn, errorFn); - - return promise; - }; - - /************************************************************************ - * - * Private method that creates a jsonObject with before and after image data for all - * records in change-set (creates, updates and deletes) - * - * Params: dataSetName is required. - * alwaysCreateTable is required. If true, always create table array (even if no data/changes) - * request is optional - */ - this._createChangeSet = function (dataSetName, alwaysCreateTable, request) { - var changeSetJsonObject = {}; - - changeSetJsonObject[dataSetName] = {}; - var dataSetJsonObject = changeSetJsonObject[dataSetName]; - - var hasChanges = dataSetJsonObject["prods:hasChanges"] = this._hasChanges(); - if (hasChanges) { - if ((alwaysCreateTable === true)) { - for (var buf in this._buffers) { - dataSetJsonObject[this._buffers[buf]._name] = []; - } - } - - // First do deletes - //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._addDeletesToChangeSet(tableRef, dataSetJsonObject, request); - } - - // Adds - //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._addCreatesToChangeSet(tableRef, dataSetJsonObject, request); - } - - // Updates - //for (var buf in this._buffers) { this._buffers[buf]._visited = false; } - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._addChangesToChangeSet(tableRef, dataSetJsonObject, request); - } - - // Clear _processed map - for (var buf in this._buffers) { - this._buffers[buf]._processed = {}; - } - } - - // Check if change set is empty - // A saveChanges() with a delete of new record would result in an empty change set - // An empty DataSet is sent to the server to ensure that AfterSaveChanges fires - var keys = Object.keys(changeSetJsonObject[dataSetName]); - if (keys.length == 1 && keys[0] == "prods:hasChanges") { - for (var buf in this._buffers) { - dataSetJsonObject[this._buffers[buf]._name] = []; - } - dataSetJsonObject["prods:hasChanges"] = false; - } - - return changeSetJsonObject; - }; - - /************************************************************************ - * - * Private method that creates a jsonObject for the created and changed records - * in a temp-table. There is no before-image information. This is used in the - * case of a Submit operation when the JSDO is just for a temp-table - * - * Params: dataSetName is required. - * alwaysCreateTable is required. If true, always create table array (even if no data/changes) - * request is optional - */ - this._createTTChangeSet = function (tableRef, request) { - var changeSetJsonObject = {}, - hasChanges, - tempTableJsonObject, - i, - id, - jsrecord; - - changeSetJsonObject[tableRef._name] = []; - tempTableJsonObject = changeSetJsonObject[tableRef._name]; - - hasChanges = this._hasChanges(); - if (hasChanges) { - - // (note that we do not send deleted rows on submit for a temp-table) - - // Adds - for (i = 0; i < tableRef._added.length; i++) { - id = tableRef._added[i]; - jsrecord = tableRef._findById(id, false); - if (jsrecord) { - if ( !tableRef._processed[jsrecord.data._id] ) { - this._addRowToTTChangeSet(tableRef, jsrecord, tempTableJsonObject, - request, "beforeCreate"); - } - } - } - - // changed rows - for (id in tableRef._changed) { - if (tableRef._changed.hasOwnProperty(id)) { - jsrecord = tableRef._findById(id, false); - if (jsrecord) { - if ( !tableRef._processed[jsrecord.data._id] ) { - this._addRowToTTChangeSet(tableRef, jsrecord, tempTableJsonObject, - request, "beforeUpdate"); - } - } - } - } - - // Clear _processed map - tableRef._processed = {}; - } - - return changeSetJsonObject; - }; - - this._addRowToTTChangeSet = function (tableRef, jsrecord, tempTableJsonObject, request, event) { - var rowData = {}; - - tableRef._processed[jsrecord.data._id] = jsrecord.data; - - // Store jsrecord in request object so we can access it when saveChanges completes, - // in order to run afterCreate events - if (typeof(request) != 'undefined') { - request.jsrecords.push(jsrecord); - - // Need to call beforeCreate trigger when saveChanges(true) is called - jsrecord._tableRef.trigger(event, this, jsrecord, request); - this.trigger(event, this, jsrecord, request); - } - - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - delete rowData["_id"]; - - tempTableJsonObject.push(rowData); - }; - - /************************************************************************ - * - * Private method that creates a jsonObject with data and also before image data - * for all records in change-set (creates, updates and deletes) - * - * Params: dataSetName is required. - * It returns jsonObject that can be used as input to addRecords() - */ - this._createDataAndChangeSet = function (dataSetName) { - var jsonObject = {}; - - jsonObject[dataSetName] = {}; - var dataSetJsonObject = jsonObject[dataSetName]; - - /* We always want to create tables (even if there's no data) so we can compare schemas - * of data in local storage to JSDO's schema */ - for (var buf in this._buffers) - dataSetJsonObject[this._buffers[buf]._name] = []; - - if (this._hasChanges()) { - dataSetJsonObject["prods:hasChanges"] = true; - } - - // Add data from each table. This will also add bi data for any created or updated rows - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._addRecordsToObject(tableRef, dataSetJsonObject); - } - - // Now do deletes - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - this._addDeletesToChangeSet(tableRef, dataSetJsonObject); - } - - // Clear _processed map - for (var buf in this._buffers) { - this._buffers[buf]._processed = {}; - } - return jsonObject; - }; - - // This method adds all record for specified table into dataSetJsonObject. - // If record has bi data, it adds that as well - this._addRecordsToObject = function (tableRef, dataSetJsonObject) { - - if (tableRef._data.length > 0 && !dataSetJsonObject[tableRef._name]) - dataSetJsonObject[tableRef._name] = []; - - for (var i = 0; i < tableRef._data.length; i++) { - var record = tableRef._data[i]; - if (!record) continue; - - // Check if record has bi data, can only determine if it's created or changed since - // deleted rows are not in after data - if (this._doesRecordHaveCreateBIData(tableRef, record._id) === true) { - var jsrecord = tableRef._findById(record._id, false); - if (!jsrecord) continue; - if (tableRef._processed[jsrecord.data._id]) continue; - this._addCreatedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject); - } - if (this._doesRecordHaveUpdateBIData(tableRef, record._id) === true) { - var jsrecord = tableRef._findById(record._id, false); - if (!jsrecord) continue; - if (tableRef._processed[jsrecord.data._id]) continue; - this._addChangedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject); - } - else { - if (tableRef._processed[record._id]) continue; - tableRef._processed[record._id] = record; - - var rowData = {}; - - tableRef._jsdo._copyRecord(tableRef, record, rowData); - delete rowData["_id"]; - - dataSetJsonObject[tableRef._name].push(rowData); - } - } - }; - - - // Check if specified after record has bi data for newly created record. - // Returns True if after record has corresponding bi data, else false - this._doesRecordHaveCreateBIData = function (tableRef, id) { - for (var i = 0; i < tableRef._added.length; i++) { - if (tableRef._added[i] === id) - return true; - } - - return false; - }; - - // Check if specified after record has bi data for updated record. - // Returns True if after record has corresponding bi data, else false - this._doesRecordHaveUpdateBIData = function (tableRef, id) { - for (var changedId in tableRef._changed) { - if (changedId === id) - return true; - } - - return false; - }; - - - // If a create, remove or update exists, method returns true, else returns false - this._hasChanges = function () { - var hasChanges = false; - - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - - var hasUpdates = false; - for (var id in tableRef._changed) { - hasUpdates = true; - break; - } - - if (tableRef._deleted.length > 0 || tableRef._added.length > 0 || hasUpdates) { - hasChanges = true; - break; - } - } - - return hasChanges; - }; - - // This method is used when saveChanges() is called, and also when storing data to local storage. - // The request param should be defined for saveChanges(), - // but not needed when storing data to local storage - this._addDeletesToChangeSet = function (tableRef, dataSetJsonObject, request) { - // There is no after table for deletes, so just create before-table data - for (var i = 0; i < tableRef._deleted.length; i++) { - var jsrecord = tableRef._deleted[i]; - - if (!jsrecord) continue; - - if (jsrecord.data - && jsrecord.data._id !== undefined - && tableRef._beforeImage[jsrecord.data._id] === null) { - // Deleted record is for a new record - do not send deleted record to server - continue; - } - - this._addDeletedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); - } - }; - - this._addDeletedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { - tableRef._processed[jsrecord.data._id] = jsrecord.data; - - // Store jsrecord in request object so we can access it when saveChanges completes, - // in order to run afterDelete events - jsrecord.data["prods:rowState"] = "deleted"; - - if (typeof(request) != 'undefined') { - request.jsrecords.push(jsrecord); - - // Need to call beforeDelete trigger if saveChanges(true) is called - jsrecord._tableRef.trigger("beforeDelete", this, jsrecord, request); - this.trigger("beforeDelete", this, jsrecord, request); - } - - var beforeRowData = {}; - // AppServer will roundtrip this back to jsdo client - beforeRowData["prods:clientId"] = jsrecord.data._id; - beforeRowData["prods:rowState"] = "deleted"; - - var beforeTableJsonObject = this._getTableInBeforeJsonObject(dataSetJsonObject, tableRef._name); - tableRef._jsdo._copyRecord(tableRef, tableRef._beforeImage[jsrecord.data._id], beforeRowData); - delete beforeRowData["_id"]; - - beforeTableJsonObject.push(beforeRowData); - }; - - // This method is used when saveChanges() is called, and also when storing data to local storage. - // The request param should be defined for saveChanges(), - // but not needed when storing data to local storage - this._addCreatesToChangeSet = function (tableRef, dataSetJsonObject, request) { - // There is no before table for creates, so just create after-table data - for (var i = 0; i < tableRef._added.length; i++) { - var id = tableRef._added[i]; - var jsrecord = tableRef._findById(id, false); - if (!jsrecord) continue; - if (tableRef._processed[jsrecord.data._id]) continue; - - this._addCreatedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); - } - }; - - this._addCreatedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { - tableRef._processed[jsrecord.data._id] = jsrecord.data; - - if (!dataSetJsonObject[tableRef._name]) { - dataSetJsonObject[tableRef._name] = []; - } - - // Store jsrecord in request object so we can access it when saveChanges completes, - // in order to run afterCreate events - jsrecord.data["prods:rowState"] = "created"; - - if (typeof(request) != 'undefined') { - request.jsrecords.push(jsrecord); - - // Need to call beforeCreate trigger when saveChanges(true) is called - jsrecord._tableRef.trigger("beforeCreate", this, jsrecord, request); - this.trigger("beforeCreate", this, jsrecord, request); - } - - var rowData = {}; - // AppServer will roundtrip this back to jsdo client - rowData["prods:clientId"] = jsrecord.data._id; - rowData["prods:rowState"] = "created"; - - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - delete rowData["_id"]; - - dataSetJsonObject[tableRef._name].push(rowData); - }; - - // This method is used when saveChanges() is called, and also when storing data to local storage. - // The request param should be defined for saveChanges(), - // but not needed when storing data to local storage - this._addChangesToChangeSet = function (tableRef, dataSetJsonObject, request) { - // For Changes, there is both before and after table data - for (var id in tableRef._changed) { - var jsrecord = tableRef._findById(id, false); - if (!jsrecord) continue; - if (tableRef._processed[jsrecord.data._id]) continue; - - this._addChangedRowToChangeSet(tableRef, jsrecord, dataSetJsonObject, request); - } - }; - - this._addChangedRowToChangeSet = function (tableRef, jsrecord, dataSetJsonObject, request) { - tableRef._processed[jsrecord.data._id] = jsrecord.data; - - if (!dataSetJsonObject[tableRef._name]) { - dataSetJsonObject[tableRef._name] = []; - } - - // Store jsrecord in request object so we can access it when saveChanges completes, in order - // to run afterUpdate events - jsrecord.data["prods:rowState"] = "modified"; - - if (typeof(request) != 'undefined') { - request.jsrecords.push(jsrecord); - - // Need to call beforeUpdate trigger when saveChanges(true) is called - jsrecord._tableRef.trigger("beforeUpdate", this, jsrecord, request); - this.trigger("beforeUpdate", this, jsrecord, request); - } - - var rowData = {}; - // Required by AppServer in before-image data. Matches before row - rowData["prods:id"] = jsrecord.data._id; - // AppServer will roundtrip this back to jsdo client - rowData["prods:clientId"] = jsrecord.data._id; - rowData["prods:rowState"] = "modified"; - - tableRef._jsdo._copyRecord(tableRef, jsrecord.data, rowData); - delete rowData["_id"]; - - dataSetJsonObject[tableRef._name].push(rowData); - - // Now add before-image data - var beforeTableJsonObject = this._getTableInBeforeJsonObject(dataSetJsonObject, tableRef._name); - var beforeRowData = {}; - // Required by AppServer in before-image data. Matches after row - beforeRowData["prods:id"] = jsrecord.data._id; - - tableRef._jsdo._copyRecord(tableRef, tableRef._beforeImage[jsrecord.data._id], beforeRowData); - //delete beforeRowData["_id"]; - - beforeTableJsonObject.push(beforeRowData); - }; - - - // Private method to get table's json object from the specified dataset json object. - // If it hasn't been created yet, this method creates it. - this._getTableInBeforeJsonObject = function (dataSetJsonObject, tableName) { - if (!dataSetJsonObject["prods:before"]) { - dataSetJsonObject["prods:before"] = {}; - } - var beforeObject = dataSetJsonObject["prods:before"]; - - if (!beforeObject[tableName]) { - beforeObject[tableName] = []; - } - - return beforeObject[tableName]; - }; - - - /********************************************************************* - * - * Reads a JSON object into the JSDO memory. - */ - this.addRecords = function (jsonObject, addMode, keyFields, trackChanges, isInvoke) { - if (this.isDataSet()) { - if (jsonObject instanceof Array) { - if (!this._defaultTableRef) { - throw new Error(msg.getMsgText("jsdoMSG998")); - } - } - else { - if (jsonObject === undefined || jsonObject === null) { - jsonObject = {}; - } - - if (jsonObject[this._dataSetName]) { - jsonObject = jsonObject[this._dataSetName]; - } - } - - // Allow empty object in addRecords with MODE_EMPTY - if (addMode != progress.data.JSDO.MODE_EMPTY) { - if (Object.keys(jsonObject).length === 0) - throw new Error(msg.getMsgText("jsdoMSG006")); - } - - var oldUseRelationships = this.useRelationships; - // Turn off useRelationships since addRecords() does not use the working record - this.useRelationships = false; - try { - for (var buf in this._buffers) { - // Read data for tables in JSON object - if (jsonObject[this._buffers[buf]._name]) - this._addRecords(this._buffers[buf]._name, jsonObject, addMode, - keyFields, trackChanges, isInvoke); - else if (addMode == progress.data.JSDO.MODE_EMPTY) { - this._buffers[this._buffers[buf]._name]._clearData(); - } - } - } finally { - // Restore useRelationships - this.useRelationships = oldUseRelationships; - } - } - else if (this._defaultTableRef) { - this._addRecords(this._defaultTableRef._name, jsonObject, addMode, keyFields, - trackChanges, isInvoke); - } - }; - - /* - * Copies the fields of the source record to the target record. - * Preserves the _id of the target record. - */ - this._copyRecord = function (tableRef, source, target, onlyChangesRecord) { - for (var field in source) { - - if (onlyChangesRecord !== undefined) { - if (source[field] == onlyChangesRecord[field]) - continue; - } - - // Fix for PSC00277769 - if (source[field] === undefined || source[field] === null) { - target[field] = source[field]; - } - else if (source[field] instanceof Date) { - target[field] = source[field]; - } - else if (typeof source[field] === 'object') { - var newObject = source[field] instanceof Array ? [] : {}; - this._copyRecord(tableRef, source[field], newObject); - target[field] = newObject; - } - else - target[field] = source[field]; - } - }; - - /* - * Deletes the "prods:" properties when no longer needed, - * typically when doing acceptChanges, rejectChanges, or _applyChanges. - * These properties are used to transfer before-image info between client JSDO and AppServer. - * - * Also, it optionally clears out the errorString field depending upon value of clearErrorString. - * To be consistent with the handling of - * the ABL's Buffer ERROR-STRING attribute, - * the errorString field should be cleared out when doing acceptChanges() or rejectChanges(). - */ - this._deleteProdsProperties = function (record, clearErrorString, deleteRowState) { - - /* Default to false */ - if (typeof(clearErrorString) == 'undefined') { - clearErrorString = false; - } - - /* Default to true */ - if (typeof(deleteRowState) == 'undefined') { - deleteRowState = true; - } - - if (record) { - delete record["prods:id"]; - delete record["prods:hasErrors"]; - delete record["prods:clientId"]; - delete record["prods:rejected"]; - delete record._rejected; - - if (deleteRowState) { - delete record["prods:rowState"]; - } - - if (clearErrorString) { - delete record._errorString; - } - } - }; - - this._addRecords = function (tableName, jsonObject, addMode, keyFields, trackChanges, isInvoke) { - var beforeImageJsonObject = null; - var beforeImageJsonIndex = null; - - if (jsonObject && (this._dataSetName !== undefined)) { - if (jsonObject[this._dataSetName] && - jsonObject[this._dataSetName]["prods:hasChanges"]) { - beforeImageJsonObject = jsonObject; - beforeImageJsonIndex = {}; - } - else if (jsonObject["prods:hasChanges"]) { - beforeImageJsonObject = {}; - beforeImageJsonObject[this._dataSetName] = jsonObject; - beforeImageJsonIndex = {}; - } - } - - if (typeof(tableName) != 'string') - throw new Error(msg.getMsgText("jsdoMSG020")); - if (!addMode) - throw new Error(msg.getMsgText("jsdoMSG021")); - - switch (addMode) { - case progress.data.JSDO.MODE_APPEND: - case progress.data.JSDO.MODE_EMPTY: - case progress.data.JSDO.MODE_MERGE: - case progress.data.JSDO.MODE_REPLACE: - break; - default: - throw new Error(msg.getMsgText("jsdoMSG022")); - } - - if (!keyFields) - keyFields = []; - else { - if (!(keyFields instanceof Array) && (typeof(keyFields) == 'object')) { - if (keyFields[tableName]) { - keyFields = keyFields[tableName]; - } - else { - keyFields = []; - } - } - } - - if (!(keyFields instanceof Array)) { - throw new Error(msg.getMsgText("jsdoMSG008")); - } - - // Check that the specified field names are in the schema - if (this._buffers[tableName]._fields) { - for (var i = 0; i < keyFields.length; i++) { - var field = this._buffers[tableName]._fields[keyFields[i].toLowerCase()]; - if (field === undefined) { - throw new Error(msg.getMsgText("jsdoMSG009", keyFields[i])); - } - else { - keyFields[i] = field.name; - } - } - } - - trackChanges = trackChanges ? true : false; - - if (tableName) { - if (!(jsonObject instanceof Array)) { - var data = null; - - if (jsonObject === undefined || jsonObject === null) { - jsonObject = {}; - } - - if (this.isDataSet()) { - if (jsonObject[this._dataSetName]) - data = jsonObject[this._dataSetName][tableName]; - else if (jsonObject[tableName]) - data = jsonObject[tableName]; - } else { - if (this._dataProperty) - data = jsonObject[this._dataProperty]; - else if (jsonObject.data) - data = jsonObject.data; - } - - - if (data instanceof Array) { - // saveJsonObject = jsonObject; - jsonObject = data; - } - else if ((addMode == progress.data.JSDO.MODE_EMPTY) - && (typeof (jsonObject) == 'object') - && (Object.keys(jsonObject).length === 0)) { - jsonObject = []; // Allow empty object in addRecords with - // MODE_EMPTY - } - // Allow empty object when called by restoreChangesOnlyForTable() - // where there are only deletes - in bi data - else if ((addMode == progress.data.JSDO.MODE_REPLACE) - && (typeof (jsonObject) == 'object') - && (beforeImageJsonObject)) { - jsonObject = []; - } - } - - if (!(jsonObject instanceof Array)) { - throw new Error(msg.getMsgText("jsdoMSG005", tableName)); - } - - var dataHasBeenProcessed = false; - try { - this._buffers[tableName]._sortRecords = false; - if (keyFields.length === 0 || addMode == progress.data.JSDO.MODE_EMPTY) { - // Quick merge - if (addMode == progress.data.JSDO.MODE_EMPTY) { - this._buffers[tableName]._clearData(); - } - // APPEND, MERGE, REPLACE - for (var i = 0; i < jsonObject.length; i++) { - var jsrecord = this._buffers[tableName]._add(jsonObject[i], trackChanges, false); - jsonObject[i]._id = jsrecord.data._id; - if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { - beforeImageJsonIndex[jsonObject[i]["prods:id"]] = jsrecord.data._id; - } - if (beforeImageJsonObject) { - this._deleteProdsProperties(jsrecord.data); - } - } - } - else { - // Build temporary index - var tmpIndex; - - if (this._buffers[tableName]._data.length * jsonObject.length >= 10) { - tmpIndex = {}; - - for (var i = 0; i < this._buffers[tableName]._data.length; i++) { - var record = this._buffers[tableName]._data[i]; - if (!record) continue; - - var key = this._buffers[tableName]._getKey(record, keyFields); - tmpIndex[key] = record; - } - - } - else - tmpIndex = null; // Do not use an index - var checkBeforeImage = - (Object.keys(this._buffers[tableName]._beforeImage).length !== 0); - for (var i = 0; i < jsonObject.length; i++) { - var match = false; - var record = null; - - // Check for duplicates - if (tmpIndex) { - var key = this._buffers[tableName]._getKey(jsonObject[i], keyFields); - record = tmpIndex[key]; - match = (record !== undefined); - } - else { - for (var j = 0; j < this._buffers[tableName]._data.length; j++) { - record = this._buffers[tableName]._data[j]; - if (!record) continue; - match = - (this._buffers[tableName]._equalRecord(jsonObject[i], record, keyFields)); - if (match) { - // Duplicate found - break; - } - } - } - - if (match) { - if (isInvoke - && (this._resource.idProperty !== undefined) - && (jsonObject[i]._id === undefined)) { - // Add _id to jsonObject - jsonObject[i]._id = record._id; - } - - // If beforeRecord is null, there is entry in _beforeImage for a create. - // If beforeRecord is undefined, there is no entry - var beforeRecord = this._buffers[tableName]._beforeImage[record._id]; - if (checkBeforeImage - && (jsonObject[i]["prods:id"] !== undefined) - && (typeof beforeRecord !== 'undefined')) { - // Only throw exception if the existing bi data - // is not the same as the new bi data - var isAfterSame = this._sameData(jsonObject[i], record); - var isBeforeSame = true; - - // For creates, beforeRecord will be null - if (beforeRecord) { - var beforeObject = this._getBeforeRecordFromObject(jsonObject[i], - beforeImageJsonObject, tableName); - if (beforeObject) - isBeforeSame = this._sameData(beforeObject, beforeRecord); - } - - if (!isAfterSame || !isBeforeSame) - throw new Error(msg.getMsgText("jsdoMSG032")); - } - - switch (addMode) { - case progress.data.JSDO.MODE_APPEND: - throw new Error(msg.getMsgText("jsdoMSG023")); - case progress.data.JSDO.MODE_MERGE: - /* Ignore duplicate */ - if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { - beforeImageJsonIndex[jsonObject[i]["prods:id"]] = record._id; - } - break; - case progress.data.JSDO.MODE_REPLACE: - if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { - beforeImageJsonIndex[jsonObject[i]["prods:id"]] = record._id; - } - - if (jsonObject[i]._id === undefined) - jsonObject[i]._id = record._id; - this._copyRecord( - this._buffers[tableName], - jsonObject[i], record); - this._deleteProdsProperties(record); - break; - default: - break; - } - } - else { - // Add record - var jsrecord = - this._buffers[tableName]._add(jsonObject[i], trackChanges, false); - jsonObject[i]._id = jsrecord.data._id; - if (beforeImageJsonIndex && jsonObject[i]["prods:id"]) { - beforeImageJsonIndex[jsonObject[i]["prods:id"]] = jsrecord.data._id; - } - if (beforeImageJsonObject) { - this._deleteProdsProperties(jsrecord.data); - } - if (tmpIndex) { - var key = this._buffers[tableName]._getKey(jsrecord.data, keyFields); - tmpIndex[key] = jsrecord.data; - } - } - - } - tmpIndex = null; - } - dataHasBeenProcessed = true; - } - finally { - this._buffers[tableName]._sortRecords = true; - this._buffers[tableName]._sort(); - this._buffers[tableName]._createIndex(); - - if (dataHasBeenProcessed && beforeImageJsonObject) { - this._buffers[tableName]._loadBeforeImageData(beforeImageJsonObject, - beforeImageJsonIndex, keyFields); - } - } - } - }; - - // This method returns corresponding bi record of the afterRecord from specified jsonObject - this._getBeforeRecordFromObject = function (afterRecord, jsonObject, tablename) { - var beforeData = jsonObject[this._dataSetName]["prods:before"]; - var id = afterRecord["prods:id"]; - var beforeRecord; - - if (!beforeData) return beforeRecord; - - // First check to see if the before data is the same - for (var i = 0; i < beforeData[tablename].length; i++) { - var record = beforeData[tablename][i]; - if (record["prods:id"] && id == record["prods:id"]) { - beforeRecord = record; - break; - } - } - - return beforeRecord; - }; - - this._sameData = function (record1, record2) { - var value1, value2; - for (var fieldName in record1) { - if (fieldName.substring(0, 5) != "prods" && fieldName != "_id") { - value1 = record1[fieldName]; - value2 = record2[fieldName]; - - if (value1 > value2 || value1 === null) - return false; - else if (value1 < value2 || value2 === null) - return false; - } - } - - return true; - }; - - - // private method to merge changes after a read operation - this._mergeRead = function (jsonObject, xhr) { - if (this.isDataSet()) { - if (this._dataProperty) { - var datasetBuffer = this._buffers[this._dataProperty]; - datasetBuffer._data = jsonObject[this._dataSetName][this._dataProperty]; - if (datasetBuffer.autoSort) { - datasetBuffer._sort(); - } - datasetBuffer._createIndex(); - } - else { - // Load data from JSON object into _data - for (var buf in this._buffers) { - var data; - if (jsonObject[this._dataSetName]) - data = jsonObject[this._dataSetName][buf]; - else - data = null; - data = data ? data : []; - - // We want to merge records based on the mergeMode that is coming to fill() operation. - // i.e., a mergeMode can be APPEND, MERGE, REPLACE or EMPTY. Excluding EMPTY because this is already - // taken care in the _fillSuccess - - if (this._fillMergeMode) { - - // Check for the availability of the buffer (temp-table). If we don't find any, then we want to assign an - // empty array such that we proceed with addRecords() operation with an empty dataset - if (this.isDataSet() && jsonObject[this._dataSetName] && !jsonObject[this._dataSetName][this._buffers[buf]._name]) { - jsonObject[this._dataSetName][this._buffers[buf]._name] = []; - } - - switch (this._fillMergeMode) { - case progress.data.JSDO.MODE_APPEND: - this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_APPEND); - break; - case progress.data.JSDO.MODE_MERGE: - this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_MERGE, this._buffers[buf]._primaryKeys); - break; - case progress.data.JSDO.MODE_REPLACE: - this._buffers[buf].addRecords(jsonObject, progress.data.JSDO.MODE_REPLACE, this._buffers[buf]._primaryKeys); - break; - default: - throw new Error(msg.getMsgText("jsdoMSG022")); - } - - } else { - this._buffers[buf]._data = data; - } - - if (this._buffers[buf].autoSort) { - this._buffers[buf]._sort(); - } - this._buffers[buf]._createIndex(); - if (jsonObject[this._dataSetName] - && jsonObject[this._dataSetName]["prods:hasChanges"]) { - this._buffers[buf]._loadBeforeImageData(jsonObject); - } - } - - // Reset the fillMergeMode back to default such that it will not affect upcoming fill() operations - this._fillMergeMode = undefined; - - // Load nested data into _data - if (this._numBuffers > 1) { - for (var buf in this._buffers) { - if (this._buffers[buf]._isNested - && this._buffers[buf]._parent - && this._buffers[this._buffers[buf]._parent]) { - var srcData = this._buffers[this._buffers[buf]._parent]._data; - var data = []; - for (var i = 0; i < srcData.length; i++) { - if (srcData[i][buf] !== undefined) { - for (var j = 0; j < srcData[i][buf].length; j++) { - data.push(srcData[i][buf][j]); - } - delete srcData[i][buf]; - } - } - this._buffers[buf]._data = data; - if (this._buffers[buf].autoSort) { - this._buffers[buf]._sort(); - } - this._buffers[buf]._createIndex(); - } - } - } - } - } - else { - if (jsonObject instanceof Array) { - this._defaultTableRef._data = jsonObject; - } - else { - if (this._dataProperty) - this._defaultTableRef._data = jsonObject[this._dataProperty]; - else if (jsonObject.data) - this._defaultTableRef._data = jsonObject.data; - else { - this._defaultTableRef._data = []; - this._defaultTableRef._data[0] = jsonObject; - } - } - } - - for (var buf in this._buffers) { - if (this._buffers[buf].autoSort) { - this._buffers[buf]._sort(); - } - this._buffers[buf]._createIndex(); - } - }; - - /** - * Replace existing record data and index entry with new record data. - */ - this._mergeUpdateRecord = function (tableRef, recordId, record) { - var index = tableRef._index[recordId].index; - record._id = recordId; - - if (!tableRef._data[index]) { - tableRef._data[index] = {}; - } - this._copyRecord(this._tableRef, record, tableRef._data[index]); - record = tableRef._data[index]; - - if (tableRef._jsdo._resource.idProperty !== undefined) { - var id = tableRef._data[index][tableRef._jsdo._resource.idProperty]; - if (id !== undefined) { - id += ""; // ID Property - - // Delete index entry for recordId (_id) - delete tableRef._index[recordId]; - - if (tableRef._beforeImage[recordId] === null) { - // Save old recordId (_id) to _tmpIndex - tableRef._tmpIndex[recordId] = new progress.data.JSIndexEntry(index); - } - - // Create index entry with new id - tableRef._index[id] = new progress.data.JSIndexEntry(index); - record._id = id; - } - } - - return record; - }; - - - /** - *update existing record data with specified error string - */ - this._setErrorString = function (tableRef, recordId, errorString, setInBeforeTable) { - - if (setInBeforeTable) { - // Ensure that object exists, it's null for deleted rows - if (tableRef._beforeImage[recordId]) { - tableRef._beforeImage[recordId]._errorString = errorString; - } - } - else { - var index = tableRef._index[recordId].index; - tableRef._data[index]._errorString = errorString; - } - }; - - /* - * Returns the array with the data from the specified dataObject. - */ - this._arrayFromDataObject = function (dataObject, tableRef) { - var data; - - if (dataObject === undefined) return undefined; - if (this._dataSetName) { - if (dataObject[this._dataSetName]) - data = dataObject[this._dataSetName][tableRef._name]; - } - else { - // check if data returned as array - if (dataObject instanceof Array) { - data = dataObject; - } else { - // or if data property is set - if (this._dataProperty) { - data = dataObject[this._dataProperty]; - } else if (dataObject.data) { - // or just try with 'data' as the data property name - data = dataObject.data; - } - } - } - - return data; - }; - - ///////////////////////////////////////////////////////////////////////////////////////////// - // - // Private method to merge changes after a create or update operation. - // This method is called to merge changes when server's Create or Update methods were called. - // - // It returns true if it found error for row in before-image data (prods:hasErrors = true) - // It returns false if there is no before-image data or prods:hasErrors property is absent - this._mergeUpdateForCUD = function (jsonObject, xhr) { - var hasError = false, - errorString; - - // Update dataset with changes from server - if (this._dataSetName) { - var dataSetJsonObject = jsonObject[this._dataSetName]; - - // only updates the specified record - var tableRef = xhr.request.jsrecord._tableRef; - var tableJsonObject = this._arrayFromDataObject(jsonObject, tableRef); - - if (tableJsonObject instanceof Array) { - if (tableJsonObject.length > 1) { - xhr.request.success = false; - throw new Error(msg.getMsgText("jsdoMSG100")); - } - - for (var i = 0; i < tableJsonObject.length; i++) { - var recordId = xhr.request.jsrecord.getId(); - - if (!recordId) { - throw new Error(msg.getMsgText("jsdoMSG034", "_mergeUpdateForCUD()")); - } - - // Determine if error string (get prods_id before _mergeUpdateRecord() is called, - // since it removes all prods properties) - errorString = undefined; - - if (tableJsonObject[i]["prods:hasErrors"]) { - var prods_id = tableJsonObject[i]["prods:id"]; - errorString = - this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); - hasError = true; - } - - var record = this._mergeUpdateRecord(tableRef, recordId, tableJsonObject[i]); - if (errorString) - this._setErrorString(tableRef, recordId, errorString, false); - - // Set _rejected property - if (tableJsonObject[i]["prods:rejected"] - || errorString) { - record._rejected = true; - if (errorString === "REJECTED") { - delete record._errorString; - } - } - - xhr.request.jsrecord = new progress.data.JSRecord(tableRef, record); - } - } - } else { - // update single record with changes from server - var tableRef = this._defaultTableRef; - var data = this._arrayFromDataObject(jsonObject); - - if (data instanceof Array) { - if (data.length > 1) { - xhr.request.success = false; - throw new Error(msg.getMsgText("jsdoMSG100")); - } - - for (var i = 0; i < data.length; i++) { - var recordId = xhr.request.jsrecord.getId(); - - if (!recordId) { - throw new Error(msg.getMsgText("jsdoMSG034", "_mergeUpdateForCUD()")); - } - - var record = this._mergeUpdateRecord(tableRef, recordId, data[i]); - xhr.request.jsrecord = new progress.data.JSRecord(tableRef, record); - } - } - } - - return hasError; - }; - - - ///////////////////////////////////////////////////////////////////////////////////////////// - // - // Private method to determine if deleted row (from delete operation) returned from AppServer - // was returned with an error in the before-image data. - // - // It returns true if it found an error for row in before-image data (prods:hasErrors = true) - // It returns false if there is no before-image data or prods:hasErrors property is absent - - this._checkForDeleteError = function (dataSetJsonObject, xhr) { - var hasError = false; - var tableRef = xhr.request.jsrecord._tableRef; - - var beforeJsonObject = dataSetJsonObject["prods:before"]; - - // No merge is necessary for deletes, but we need to see - // if there are any errors on deletes records. - // delete records are not in after table, only in before table - if (beforeJsonObject) { - var beforeTableJsonObject = beforeJsonObject[tableRef._name]; - - if (beforeTableJsonObject.length > 1) { - xhr.request.success = false; - throw new Error(msg.getMsgText("jsdoMSG100")); - } - // clientId is same as _id - var recordId = beforeTableJsonObject[0]["prods:clientId"]; - if (!recordId) { - throw new Error(msg.getMsgText("jsdoMSG035", "_checkForDeleteError()")); - } - - // Determine if row was returned with error string - if (beforeTableJsonObject[0]["prods:hasErrors"]) { - var prods_id = beforeTableJsonObject[0]["prods:id"]; - var errorString = - this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); - this._setErrorString(tableRef, recordId, errorString, true); - hasError = true; - } - } - - return hasError; - }; - - ///////////////////////////////////////////////////////////////////////////////////////////// - // - // Private method to merge changes after a call to saveChanges. - // This method is called when saveChanges(useSubmit) was called with useSubmit=true. - // This can process/merge one or more created, deleted or updated records. - // In order for a jsonObject to have before-image data, it must be associated with a dataset. - // - // It only merges changes in the after table. But we need to look at before-image table to see - // if there were any errors passed back for the deletes - // - this._mergeUpdateForSubmit = function (jsonObject, xhr) { - var errorString; - - //if (!this._dataSetName || !jsonObject[this._dataSetName]["prods:hasChanges"]) - if (!this._dataSetName) { - // "_mergeUpdateForSubmit() can only be called for a dataset" - throw new Error(msg.getMsgText("jsdoMSG036", "_mergeUpdateForSubmit()")); - } - - // response is sent back with extra dataset object wrapper - var dataSetJsonObject = jsonObject[this._dataSetName]; - if (dataSetJsonObject[this._dataSetName]) - dataSetJsonObject = dataSetJsonObject[this._dataSetName]; - - var beforeJsonObject = dataSetJsonObject["prods:before"]; - - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - - var tableJsonObject = dataSetJsonObject[tableRef._name]; - if (tableJsonObject instanceof Array) { - for (var i = 0; i < tableJsonObject.length; i++) { - - var recordId = tableJsonObject[i]["prods:clientId"]; - if (!recordId) { - throw new Error(msg.getMsgText("jsdoMSG035", "_mergeUpdateForSubmit()")); - } - - // Determine if error string (get prods_id before _mergeUpdateRecord() is called, - // since it removes all prods properties) - errorString = undefined; - - if (tableJsonObject[i]["prods:hasErrors"]) { - var prods_id = tableJsonObject[i]["prods:id"]; - errorString = - this._getErrorStringFromJsonObject(dataSetJsonObject, tableRef, prods_id); - } - var record = this._mergeUpdateRecord(tableRef, recordId, tableJsonObject[i]); - if (errorString) { - this._setErrorString(tableRef, recordId, errorString, false); - } - - // Set _rejected property so it can be checked in applyChanges() - if (tableJsonObject[i]["prods:rejected"] - || errorString) { - record._rejected = true; - if (errorString === "REJECTED") { - delete record._errorString; - } - } - - // Now need to update jsrecords. - // We use this data when we fire create, update and delete events. - // Updating so that it contains latest data (data sent back from server) - var jsrecords = xhr.request.jsrecords; - for (var idx = 0; idx < jsrecords.length; idx++) { - if (jsrecords[idx].data["_id"] == recordId) { - jsrecords[idx].data = record; - break; - } - } - } - } - } - - // No merge is necessary for deletes, - // but we need to see if there are any errors on deletes records. - // delete records are not in after table, only in before table - if (beforeJsonObject) { - for (var buf in this._buffers) { - var tableRef = this._buffers[buf]; - var beforeTableJsonObject = beforeJsonObject[tableRef._name]; - var errorString; - - if (beforeTableJsonObject instanceof Array) { - for (var i = 0; i < beforeTableJsonObject.length; i++) { - - if (beforeTableJsonObject[i]["prods:rowState"] == "deleted") { - var recordId = beforeTableJsonObject[i]["prods:clientId"]; - if (!recordId) { - throw new Error(msg.getMsgText("jsdoMSG035", "_mergeUpdateForSubmit()")); - } - - errorString = undefined; - // If row was returned with error string, just copy that over to jsdo record - if (beforeTableJsonObject[i]["prods:hasErrors"]) { - var prods_id = beforeTableJsonObject[i]["prods:id"]; - - errorString = this._getErrorStringFromJsonObject(dataSetJsonObject, - tableRef, prods_id); - this._setErrorString(tableRef, recordId, errorString, true); - } - - // Set _rejected property so it can be checked in applyChanges() - if ((beforeTableJsonObject[i]["prods:rejected"] - || errorString) - && tableRef._beforeImage[recordId]) { - tableRef._beforeImage[recordId]._rejected = true; - if (errorString === "REJECTED") { - delete tableRef._beforeImage[recordId]._errorString; - } - } - } - } - } - } - } - }; - - ///////////////////////////////////////////////////////////////////////////////////////////// - // - // Private method that fires afterCreate, afterUpdate and afterDelete (CUD) triggers after - // saveChanges(true) is called. We must fire create, update and delete triggers - // for each record that was sent to backend submit operation - this._fireCUDTriggersForSubmit = function (request) { - // Before firing triggers, delete prods properties (except rowState) so they don't appear in data - for (var idx = 0; idx < request.jsrecords.length; idx++) { - this._deleteProdsProperties(request.jsrecords[idx].data, false, false); - } - - for (var idx = 0; idx < request.jsrecords.length; idx++) { - var jsrecord = request.jsrecords[idx]; - switch (jsrecord.data["prods:rowState"]) { - case "created": - jsrecord._tableRef.trigger("afterCreate", this, jsrecord, request.success, request); - this.trigger("afterCreate", this, jsrecord, request.success, request); - break; - case "modified": - jsrecord._tableRef.trigger("afterUpdate", this, jsrecord, request.success, request); - this.trigger("afterUpdate", this, jsrecord, request.success, request); - break; - case "deleted": - jsrecord._tableRef.trigger("afterDelete", this, jsrecord, request.success, request); - this.trigger("afterDelete", this, jsrecord, request.success, request); - break; - } - } - }; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // - // Private method to return error for specified row - // from jsonObject's prods:errors object (before-data) sent over from AppServer - // - this._getErrorStringFromJsonObject = function (dataSetJsonObject, tableRef, prods_id) { - var tableJsonObject; - var errorsJsonObject = dataSetJsonObject["prods:errors"]; - - if (errorsJsonObject) { - tableJsonObject = errorsJsonObject[tableRef._name]; - } - - if (tableJsonObject instanceof Array) { - for (var i = 0; i < tableJsonObject.length; i++) { - - var id = tableJsonObject[i]["prods:id"]; - if (id === prods_id) { - var errorString = tableJsonObject[i]["prods:error"]; - return errorString === null ? - "Server returned unspecified error. Please check log files." : errorString; - } - } - } - - return undefined; - }; - - this._fillSuccess = function (jsdo, success, request) { - var xhr = request.xhr, - properties, - mapping; - - // Need to check if responseMapping was specified; developer can specify - // plug-in to manipulate response - properties = jsdo.getMethodProperties("read"); - - if (properties && properties.mappingType) { - mapping = progress.data.PluginManager.getPlugin(properties.mappingType); - if (!mapping) { - throw new Error(progress.data._getMsgText("jsdoMSG118", properties.mappingType)); - } - - if (typeof (mapping.responseMapping) === "function") { - request.response = mapping.responseMapping(jsdo, request.response, { operation: "read" }); - } - } - - // Here check for the mergeMode flag of fill() operation and performing accordingly. - // When the mergeMode is EMPTY or if the fillMergeMode is NOT set then only we will be performing clearData operation - if(!request.jsdo._fillMergeMode || request.jsdo._fillMergeMode === progress.data.JSDO.MODE_EMPTY) { - jsdo._clearData(); - } - jsdo._mergeRead(request.response, xhr); - - // Set working record - for (var buf in jsdo._buffers) { - if (!jsdo._buffers[buf]._parent || !jsdo.useRelationships) { - jsdo._buffers[buf]._setRecord(jsdo._buffers[buf]._findFirst()); - } - } - }; - - this._fillComplete = function (jsdo, success, request) { - jsdo.trigger("afterFill", jsdo, request.success, request); - if (request.deferred) { - if (success) { - request.deferred.resolve(jsdo, success, request); - } - else { - request.deferred.reject(jsdo, success, request); - } - } - }; - - this._fillError = function (jsdo, success, request) { - jsdo._clearData(); - jsdo._updateLastErrors(jsdo, null, null, request); - }; - - this._undoCreate = function (tableRef, id) { - // Undo operation - // Remove record from JSDO memory - var entry = tableRef._index[id]; - if (entry !== undefined) { - var index = entry.index; - tableRef._data[index] = null; - } - tableRef._hasEmptyBlocks = true; - delete tableRef._index[id]; - delete tableRef._beforeImage[id]; - // End - Undo operation - }; - - this._undoUpdate = function (tableRef, id, deleteProdsProps) { - /* Default to false */ - if (typeof(deleteProdsProps) == 'undefined') { - deleteProdsProps = false; - } - - // Undo operation - // Restore from before image - var record = tableRef._beforeImage[id]; - - // Before image points to an existing record - if (record) { - var index = tableRef._index[id].index; - tableRef._jsdo._copyRecord(tableRef, record, tableRef._data[index]); - if (deleteProdsProps) - tableRef._jsdo._deleteProdsProperties(tableRef._data[index], true); - } - delete tableRef._beforeImage[id]; - // End - Restore before image - }; - - this._undoDelete = function (tableRef, id, deleteProdsProps) { - /* Default to false */ - if (typeof(deleteProdsProps) == 'undefined') { - deleteProdsProps = false; - } - - // Restore from before image - var record = tableRef._beforeImage[id]; - - // Before image points to an existing record - if (record) { - var index = record._index; - delete record._index; - if (deleteProdsProps) - tableRef._jsdo._deleteProdsProperties(record, true); - - if ((index !== undefined) && (tableRef._data[index] === null)) { - tableRef._data[index] = record; - } - else { - tableRef._data.push(record); - index = tableRef._data.length - 1; - } - tableRef._index[id] = new progress.data.JSIndexEntry(index); - } - delete tableRef._beforeImage[id]; - // End - Restore before image - }; - - this._deleteComplete = function (jsdo, success, request) { - var xhr = request.xhr; - var jsrecord = request.jsrecord; - - try { - // Before firing trigger, delete prods properties so they don't appear in data - jsdo._deleteProdsProperties(jsrecord.data, false); - - jsrecord._tableRef.trigger("afterDelete", jsdo, jsrecord, request.success, request); - jsdo.trigger("afterDelete", jsdo, jsrecord, request.success, request); - - } finally { - request.complete = true; - jsdo._checkSaveComplete(xhr); - } - }; - - this._deleteSuccess = function (jsdo, success, request) { - var xhr = request.xhr; - var jsonObject = request.response; - var beforeJsonObject = null; - var dataSetJsonObject = null; - var data; - - //Even though this is _deleteSuccess, if before-image data is returned, the call of - // delete operation could return a success, but we have to check if error was returned - // in before-image data - var hasError = false; - if (jsdo._useBeforeImage("delete")) { - dataSetJsonObject = jsonObject[jsdo._dataSetName]; - beforeJsonObject = dataSetJsonObject["prods:before"]; - - if (beforeJsonObject) { - data = beforeJsonObject[request.jsrecord._tableRef._name]; - } - } - else { - data = jsdo._arrayFromDataObject(jsonObject, request.jsrecord._tableRef); - } - - if (data instanceof Array) { - if (data.length > 1) { - request.success = false; - throw new Error(msg.getMsgText("jsdoMSG100")); - } - } - - if (beforeJsonObject) { - hasError = jsdo._checkForDeleteError(dataSetJsonObject, xhr); - } - - if (hasError) - request.success = false; - - if (jsdo.autoApplyChanges) { - if (!hasError) { - // Clear before image - delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; - // End - Clear before image - } - else { - jsdo._deleteError(jsdo, success, request); - } - } - }; - - this._deleteError = function (jsdo, success, request) { - if (jsdo.autoApplyChanges) { - jsdo._undoDelete(request.jsrecord._tableRef, request.jsrecord.data._id); - } - }; - - this._createComplete = function (jsdo, success, request) { - var xhr = request.xhr; - var jsrecord = request.jsrecord; - - try { - // Before firing trigger, delete prods properties so they don't appear in data - jsdo._deleteProdsProperties(jsrecord.data, false); - - jsrecord._tableRef.trigger("afterCreate", jsdo, jsrecord, request.success, request); - jsdo.trigger("afterCreate", jsdo, jsrecord, request.success, request); - } finally { - request.complete = true; - jsdo._checkSaveComplete(xhr); - } - }; - - this._createSuccess = function (jsdo, success, request) { - var xhr = request.xhr; - var record = request.response; - var hasError = jsdo._mergeUpdateForCUD(record, xhr); - - if (hasError) - request.success = false; - - if (jsdo.autoApplyChanges) { - if (!hasError) { - // Clear before image - delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; - // End - Clear before image - } - else { - jsdo._createError(jsdo, success, request); - } - } - }; - - this._createError = function (jsdo, success, request) { - if (jsdo.autoApplyChanges) { - jsdo._undoCreate(request.jsrecord._tableRef, request.jsrecord.data._id); - } - }; - - - this._updateComplete = function (jsdo, success, request) { - var xhr = request.xhr; - var jsrecord = request.jsrecord; - try { - // Before firing trigger, delete prods properties so they don't appear in data - jsdo._deleteProdsProperties(jsrecord.data, false); - - jsrecord._tableRef.trigger("afterUpdate", jsdo, jsrecord, request.success, request); - jsdo.trigger("afterUpdate", jsdo, jsrecord, request.success, request); - } finally { - request.complete = true; - jsdo._checkSaveComplete(xhr); - } - }; - - this._updateSuccess = function (jsdo, success, request) { - var xhr = request.xhr; - var hasError = jsdo._mergeUpdateForCUD(request.response, xhr); - - if (hasError) { - request.success = false; - } - - if (jsdo.autoApplyChanges) { - if (!hasError) { - request.success = true; - // Clear before image - delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]; - // End - Clear before image - } - else { - jsdo._updateError(jsdo, success, request); - } - } - }; - - this._updateError = function (jsdo, success, request) { - - if (jsdo.autoApplyChanges) { - request.success = false; - jsdo._undoUpdate(request.jsrecord._tableRef, request.jsrecord.data._id); - } - }; - - - this._saveChangesSuccess = function (jsdo, success, request) { - var records = request.response; - jsdo._mergeUpdateForSubmit(records, request.xhr); - - // Ensure that that the _lastErrors variable has been cleared - jsdo._clearErrors(); - var changes = jsdo.getChanges(); - jsdo._updateLastErrors(jsdo, null, changes); - - jsdo._setAllRecordsRejected(changes); - - if (jsdo.autoApplyChanges) { - jsdo._applyChanges(); - } - }; - - - this._saveChangesError = function (jsdo, success, request) { - jsdo._setAllRecordsRejected(true); - if (jsdo.autoApplyChanges) { - jsdo.rejectChanges(); - } - jsdo._updateLastErrors(jsdo, null, null, request); - }; - - /* _saveChangesSuccessTT - internal function called after a Submit of a temp-table (not DataSet) returns success - This method does not attempt to do any merging of records into the JSDO memory. The - absence of _id for the records means that the only way we could possibly do a "merge" - would be to delete the changed rceords in the JSDO memory and then add the records - that were returned form the data service, but that would invalidate the _id's that - the Kendo datasource depends on. The application programmmer must do the merging in - the afterSaveChanges handler - - *** Submit(temp-table) is not supported. This method will be removed in a future version. *** - */ - this._saveChangesSuccessTT = function (jsdo, success, request) { - var changes; - - // Ensure that that the _lastErrors variable has been cleared - jsdo._clearErrors(); - changes = jsdo.getChanges(); - jsdo._updateLastErrors(jsdo, null, changes); - jsdo._setAllRecordsRejected(false); - }; - - this._saveChangesComplete = function (jsdo, success, request) { - // Success with errors - if ((request.xhr.status >= 200 && request.xhr.status < 300) - && (jsdo._lastErrors.length > 0 || jsdo._someRecordsRejected)) { - request.success = false; - } - - // If saveChanges(true) was called, then we must fire create, update and delete triggers - // for each record that was sent to submit operation - if (jsdo._useSubmit === true) { - jsdo._fireCUDTriggersForSubmit(request); - } - - jsdo._undefWorkingRecord(); - jsdo._fireAfterSaveChanges(request.success, request); - - }; - - this._fireAfterSaveChanges = function (success, request) { - this.trigger("afterSaveChanges", this, success, request); - - if (request.jsrecords) { - if (request.deferred) { - if (success) { - request.deferred.resolve(this, success, request); - } - else { - request.deferred.reject(this, success, request); - } - } - } - else if (request.batch && request.batch.deferred) { - if (success) { - request.batch.deferred.resolve(this, success, request); - } - else { - request.batch.deferred.reject(this, success, request); - } - } - - // Clear error string when autoApplyChanges is true - var clearErrorString = this.autoApplyChanges; - - // This will be set if submit operation was performed - if (request.jsrecords) { - for (var idx = 0; idx < request.jsrecords.length; idx++) { - var jsrecord = request.jsrecords[idx]; - if (clearErrorString) { - delete jsrecord.data._errorString; - } - delete jsrecord.data["prods:rowState"]; - } - } - else if (request.batch && request.batch.operations) { - for (var idx = 0; idx < request.batch.operations.length; idx++) { - var jsrecord = request.batch.operations[idx].jsrecord; - if (clearErrorString) { - delete jsrecord.data._errorString; - } - } - } - }; - - /* - * Returns errors in response associated with the HTTP request.records related to the specified jsrecord. - */ - this._getErrorsFromRequest = function(request) { - var errors = [], // Array of objects with properties: type, id, error, errorNum, responseText - errorArray = [], - errorObject, - retValString, - j, - i; - - if (request && !request.success) { - if (request.xhr.status >= 400 && request.xhr.status < 600) { - try { - var responseObject = JSON.parse(request.xhr.responseText); - - // responseText could be an array, an object or just text. - // If it is an array, each object would have properties _errors and optional _retVal. - // If it is not an array, the object would have properties _errors and optional _retVal. - // If it is text, the content could also be an HTML page, this error is handle using "HTTP Status". - if (responseObject instanceof Array) { - errorArray = responseObject; - } else if (responseObject instanceof Object) { - errorArray.push(responseObject); - } - for (i = 0; i < errorArray.length; i += 1) { - errorObject = errorArray[i]; - if (errorObject._retVal) { - errors.push({ - type: progress.data.JSDO.RETVAL, - error: errorObject._retVal - }); - retValString = errorObject._retVal; - } else { - retValString = null; - } - if (errorObject._errors instanceof Array) { - for (j = 0; j < errorObject._errors.length; j += 1) { - if ((errorObject._errors[j]._errorNum === 0) - && (errorObject._errors[j]._errorMsg === retValString)) { - // Suppress additional error msg if it is same as return value - continue; - } - errors.push({ - type: progress.data.JSDO.APP_ERROR, - error: errorObject._errors[j]._errorMsg, - errorNum: errorObject._errors[j]._errorNum - }); - } - } - } - } - catch (e) { - // Ignore exceptions - } - } - if (request.exception) { - errors.push({ - type: progress.data.JSDO.ERROR, - error: request.exception - }); - } - if (errors.length === 0 - && request.xhr - && (request.xhr.status >= 400 && request.xhr.status < 600)) { - errors.push({ - type: progress.data.JSDO.ERROR, - error: "Error: HTTP Status " + request.xhr.status + " " + request.xhr.statusText, - responseText: request.xhr.responseText - }); - } - } - return errors; - }; - - this._updateLastErrors = function (jsdo, batch, changes, request) { - var errors, - errorText, - responseObject, - i, - j, - buf; - - if (batch) { - if (batch.operations === undefined) return; - for (i = 0; i < batch.operations.length; i++) { - request = batch.operations[i]; - if (!request.success && request.xhr) { - if (request.xhr.status >= 200 && request.xhr.status < 300) { - // Add error string to jsdo._lastErrors - jsdo._lastErrors.push({errorString: request.jsrecord.data._errorString}); - // Add error object to jsdo.._lastErrors - jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({ - type: progress.data.JSDO.DATA_ERROR, - id: request.jsrecord.data._id, - error: request.jsrecord.data._errorString}); - } - else { - errors = this._getErrorsFromRequest(request); - errorText = ""; - for (j = 0; j < errors.length; j += 1) { - if (errors.length > 1 && errors[j].error.indexOf("(7243)") != -1) { - // If there are more error messages - // supress error "The Server application has returned an error. (7243)" - continue; - } - // Add error to table reference - if (request.jsrecord - && (errors[j].type === progress.data.JSDO.APP_ERROR - || errors[j].type === progress.data.JSDO.RETVAL)) { - errors[j].id = request.jsrecord.data._id; - request.jsrecord._tableRef._lastErrors.push(errors[j]); - } - if (errorText.length === 0) { - errorText = errors[j].error; - } - else { - errorText += "\n" + errors[j].error; - } - } - // Add error string to jsdo._lastErrors - jsdo._lastErrors.push({errorString: errorText}); - } - } - } - } - else if (changes instanceof Array) { - for (i = 0; i < changes.length; i++) { - if (changes[i].record && changes[i].record.data._errorString !== undefined) { - jsdo._lastErrors.push({errorString: changes[i].record.data._errorString}); - jsdo._buffers[changes[i].record._tableRef._name]._lastErrors.push({ - type: progress.data.JSDO.DATA_ERROR, - id: changes[i].record.data._id, - error: changes[i].record.data._errorString}); - } - } - } - else if (request - && !request.success - && request.xhr - && ((request.xhr.status >= 400 && request.xhr.status < 600) || request.xhr.status === 0)) { - errors = this._getErrorsFromRequest(request); - errorText = ""; - for (j = 0; j < errors.length; j += 1) { - if (errors.length > 1 && errors[j].error.indexOf("(7243)") != -1) { - // If there are more error messages - // supress error "The Server application has returned an error. (7243)" - continue; - } - // Add error to all table references - for (buf in this._buffers) { - this._buffers[buf]._lastErrors.push(errors[j]); - } - if (errorText.length === 0) { - errorText = errors[j].error; - } - else { - errorText += "\n" + errors[j].error; - } - } - jsdo._lastErrors.push({errorString: errorText}); - } - }; - - // Check if all the xhr operations associated with the batch for which - // this xhr object is related have completed (not necessarily to success). - // If all XHR operations have completed this fires 'afterSaveChanges' event - this._checkSaveComplete = function (xhr) { - if (xhr.request) { - var jsdo = xhr.request.jsdo; - var batch = xhr.request.batch; - // OE00229270 Should only do afterSaveChanges if _async - if (jsdo && batch && jsdo._async) { - if (jsdo._isBatchComplete(batch)) { - var success = jsdo._isBatchSuccess(batch); - var request = { - batch: batch, - success: success - }; - jsdo._undefWorkingRecord(); - - // Save error messages - jsdo._lastErrors = []; - if (!success && batch.operations) { - jsdo._updateLastErrors(jsdo, batch, null); - } - this._setAllRecordsRejected(batch); - - jsdo._fireAfterSaveChanges(success, request); - } - } - } - }; - - - /* - * determine if a batch of XHR requests has completed in which all requests are successful - */ - this._isBatchSuccess = function (batch) { - if (batch.operations) { - for (var i = 0; i < batch.operations.length; i++) { - if (!batch.operations[i].success) { - return false; - } - } - } - return true; - }; - - /* - * determine if all XHR requests from the batch of saves have completed (not necessarily to success) - */ - this._isBatchComplete = function (batch) { - if (batch.operations) { - for (var i = 0; i < batch.operations.length; i++) { - var request = batch.operations[i]; - // we have to check against the 'complete' flag because xhr.readyState - // might be set async by the browser - // while we're still in the middle of processing some other requests's response - if (!request.complete) { - return false; - } - } - } - return true; - }; - - this._mergeInvoke = function (jsonObject, xhr) { - var operation, i; - - if (xhr.request.fnName !== undefined - && xhr.jsdo._resource.fn[xhr.request.fnName] !== undefined) { - operation = xhr.jsdo._resource.fn[xhr.request.fnName].operation; - } - else - operation = null; - if (operation === undefined) { - // Operation data is only required for invoke operations with mergeMode: true - operation = null; - for (i = 0; i < xhr.jsdo._resource.operations.length; i++) { - if (xhr.jsdo._resource.operations[i].name == xhr.request.fnName) { - operation = xhr.jsdo._resource.operations[i]; - break; - } - } - xhr.jsdo._resource.fn[xhr.request.fnName].operation = operation; - } - if (operation !== null && operation.mergeMode) { - try { - var mergeMode = progress.data.JSDO["MODE_" + operation.mergeMode.toUpperCase()]; - if (mergeMode === null) { - throw new Error(msg.getMsgText("jsdoMSG030", "mergeMode property", - "EMPTY, APPEND, MERGE or REPLACE")); - } - if (xhr.jsdo._resource.idProperty === undefined) { - throw new Error(msg.getMsgText("jsdoMSG110", this._resource.name, - " by mergeMode property in invoke operation")); - } - var dataParameterName; - if (xhr.jsdo.isDataSet()) { - dataParameterName = xhr.jsdo._resource._dataSetName; - } - else if (xhr.jsdo._resource.dataProperty !== undefined) { - dataParameterName = xhr.jsdo._resource.dataProperty; - } - else if (xhr.jsdo._resource._tempTableName !== undefined) { - dataParameterName = xhr.jsdo._resource._tempTableName; - } - else { - throw new Error(msg.getMsgText("jsdoMSG111", "")); - } - - var found = false; - for (i = 0; i < operation.params.length; i++) { - if (operation.params[i].name == dataParameterName) { - if (operation.params[i].type.indexOf('RESPONSE_BODY') != -1) { - if ((operation.params[i].xType !== undefined) - && (operation.params[i].xType != 'DATASET') - && (operation.params[i].xType != 'TABLE') - && (operation.params[i].xType != 'ARRAY')) { - throw new Error(msg.getMsgText("jsdoMSG113", operation.params[i].xType, - dataParameterName, xhr.request.fnName)); - } - found = true; - break; - } - } - } - - if (!found) { - throw new Error(msg.getMsgText("jsdoMSG112", dataParameterName, xhr.request.fnName)); - } - xhr.jsdo.addRecords(xhr.request.response[dataParameterName], - mergeMode, [xhr.jsdo._resource.idProperty], false, true); - } - catch (e) { - xhr.request.success = false; - xhr.request.exception = e; - } - } - }; - - this.onReadyStateChangeGeneric = function () { - var xhr = this; - if (xhr.readyState == 4) { - var request = xhr.request; - - /* try to parse response even if request is considered "failed" due to http status */ - try { - request.response = JSON.parse(xhr.responseText); - // in some cases the object back from appserver has a "response" property which represents - // the real content of the JSON...happens when multiple output parameters are returned. - // this of course assumes no one names their root object "response". - if (request.response && request.response.response) { - request.response = request.response.response; - } - } catch (e) { - request.response = undefined; - } - - try { - if ((xhr.status >= 200 && xhr.status < 300) - || (xhr.status === 0 && xhr.responseText !== "")) { - - request.success = true; - // get the Client Context ID (AppServer ID) - xhr.jsdo._session._saveClientContextId(xhr); - if ((typeof xhr.onSuccessFn) == 'function') { - var operation; - if (xhr.request.fnName !== undefined - && xhr.jsdo._resource.fn[xhr.request.fnName] !== undefined) { - operation = xhr.jsdo._resource.fn[xhr.request.fnName].operation; - } - else - operation = null; - if ((operation === undefined) || (operation !== null && operation.mergeMode)) - xhr.jsdo._mergeInvoke(request.response, xhr); - if (request.success) - xhr.onSuccessFn(xhr.jsdo, request.success, request); - else if ((typeof xhr.onErrorFn) == 'function') - xhr.onErrorFn(xhr.jsdo, request.success, request); - } - - } else { - request.success = false; - if (xhr.status === 0) { - request.exception = new Error(msg.getMsgText("jsdoMSG101")); - } - if ((typeof xhr.onErrorFn) == 'function') { - xhr.onErrorFn(xhr.jsdo, request.success, request); - } - } - } catch (e) { - request.success = false; - request.exception = e; - if ((typeof xhr.onErrorFn) == 'function') { - xhr.onErrorFn(xhr.jsdo, request.success, request); - } - } - // get the Client Context ID (AppServer ID) - xhr.jsdo._session._checkServiceResponse(xhr, request.success, request); - - if ((typeof xhr.onCompleteFn) == 'function') { - xhr.onCompleteFn(xhr.jsdo, request.success, request); - } - - } - }; - - /* - * Accepts changes for all table references in the JSDO. - */ - this.acceptChanges = function () { - for (var buf in this._buffers) { - this._buffers[this._buffers[buf]._name].acceptChanges(); - } - }; - - /* - * Rejects changes for the table references in the JSDO. - */ - this.rejectChanges = function () { - for (var buf in this._buffers) { - this._buffers[this._buffers[buf]._name].rejectChanges(); - } - }; - - /* - * Returns an array with changes for all table references in the JSDO. - */ - this.getChanges = function () { - var result = []; - for (var buf in this._buffers) { - var changes = this._buffers[this._buffers[buf]._name].getChanges(); - result = result.concat(changes); - } - return result; - }; - - this.hasChanges = function () { - for (var buf in this._buffers) { - if (this._buffers[this._buffers[buf]._name].hasChanges()) - return true; - } - return false; - }; - - /* - * Private method to apply changes for all table references in the JSDO. - * If _errorString has been set for a row, rejectRowChanges() is called. - * If it has not been set, acceptRowChanges() is called. - */ - this._applyChanges = function () { - for (var buf in this._buffers) { - this._buffers[this._buffers[buf]._name]._applyChanges(); - } - }; - - /* - * Accepts row changes for the working record using the JSDO reference. - */ - this.acceptRowChanges = function () { - if (this._defaultTableRef) - return this._defaultTableRef.acceptRowChanges(); - throw new Error(msg.getMsgText("jsdoMSG001", "acceptRowChanges()")); - }; - - /* - * Reject row changes for the working record using the JSDO reference. - */ - this.rejectRowChanges = function () { - if (this._defaultTableRef) - return this._defaultTableRef.rejectRowChanges(); - throw new Error(msg.getMsgText("jsdoMSG001", "rejectRowChanges()")); - }; - - /* - * Sets complete set of properties for the jsdo. All existing properties are replaced with new set - */ - this.setProperties = function( propertiesObject ) { - var prop; - - if (arguments.length < 1) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'setProperties', 1)); - } - if (arguments.length > 1) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'setProperties', 1)); - } - if ( typeof propertiesObject == "object" ) { - /* Copy properties of the propertiesObject argument into _properties. - * Note that if object passed in has a prototype, this code copies them too) - */ - this._properties = {}; - - for (prop in propertiesObject) { - if( propertiesObject.hasOwnProperty(prop) ) { - if (typeof propertiesObject[prop] !== "function" ) { - this._properties[prop] = propertiesObject[prop]; - } - } - } - } - else if ( (propertiesObject === undefined) || (propertiesObject === null) ) { - this._properties = {}; - } - else { - // {1}: Parameter {1} must be of type {3} in {4} call. - throw new Error(progress.data._getMsgText("jsdoMSG121", 'JSDO', 1, 'Object', - 'setProperties')); - } - }; - - /* - * Set or remove an individual property in the property set maintained by the jsdo. - * This operates only on the property identified by propertyName; - * all other existing properties remain as they are. - * If the propertyName is not part of the context, this call adds it. - * If it exists, it is updated, unless - - * If propertyValue is undefined, this call removes the property - */ - this.setProperty = function( propertyName, propertyValue) { - if (arguments.length < 2) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', - 'setProperty', 2)); - } - if (arguments.length !== 2) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", "JSDO", - "setProperty", 2)); - } - if (typeof propertyName !== "string") { - // {1}: Parameter {1} must be of type {3} in {4} call. - throw new Error(progress.data._getMsgText("jsdoMSG121", 'JSDO', 1, 'string', - 'setProperty')); - } - - if ( propertyValue === undefined ) { - delete this._properties[propertyName]; // OK if it doesn't exist -- no error - } - else { - this._properties[propertyName] = propertyValue; - } - }; - - /* - * Gets the set of jsdo properties. Returns an object containing all the properties - */ - this.getProperties = function( ) { - if (arguments.length > 0) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperties', 0)); - } - return this._properties; - }; - - /* Gets the value of an individual property in the jsdo property set - */ - this.getProperty = function( propertyName) { - if (arguments.length < 1) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperty', 1)); - } - if (arguments.length > 1) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'JSDO', 'getProperty', 1)); - } - return this._properties[propertyName]; - - }; - - /////////////////////////////////////////////////////////////////////////// - // - // The following methods provide support for Object Pesistence - - /* - * Saves JSDO memory (and optionally pending changes) to local storage. - * - * saveLocal() - * saveLocal(name) - * saveLocal(dataMode) - * saveLocal(name, dataMode) - * - */ - this.saveLocal = function saveLocal(arg1, arg2) { - var name; - var dataMode; - - if (arguments.length > 2) { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); - } - - if (typeof(arg1) == 'string' || arg1 === null || arg1 === undefined) { - name = arg1; - dataMode = arg2; - } - else { - name = null; - dataMode = arg1; - } - - if (name === undefined || name === null || name === "") { - name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; - } - if (typeof(dataMode) == 'undefined') { - dataMode = progress.data.JSDO.ALL_DATA; - } - else { - switch (dataMode) { - case progress.data.JSDO.ALL_DATA: - case progress.data.JSDO.CHANGES_ONLY: - break; - default: - throw new Error(msg.getMsgText("jsdoMSG115", arguments.callee.name)); - } - } - - if (this._localStorage === null) { - // Must first instantiate _localStorage object - this._localStorage = new progress.data.LocalStorage(); - } - - var dataObj = this._prepareDataObjectForLocalStorage(dataMode); - this._localStorage.saveToLocalStorage(name, dataObj); - }; - - /* - * Reads localStorage (based upon name) into JSDO memory - * (localStorage may or may not have pending changes). - * readLocal() - * readLocal(name) - * - */ - this.readLocal = function readLocal(name) { - if (arguments.length > 1) { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); - } - if (name === undefined || name === null || name === "") { - name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; - } - else if (typeof(name) != 'string') { - throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); - } - - if (this._localStorage === null) { - this._localStorage = new progress.data.LocalStorage(); - } - - var object = this._localStorage.readFromLocalStorage(name); - - // If storage area does not exist (i.e. object = null) then don't update JSDO local memory - if (object) { - if (this._hasMatchingSchema(object) === false) - throw new Error(msg.getMsgText("jsdoMSG117", name)); - - // For readLocal(), JSDO should first be emptied of data, so using MODE_EMPTY - this._restoreFromLocalStorage(object, progress.data.JSDO.MODE_EMPTY); - } - - return object !== null; - }; - - /* - * Reads localStorage (based upon name) into JSDO memory - * (localStorage may or may not have pending changes). - * addLocalRecords(addMode) - * addLocalRecords(addMode, keyFields) - * addLocalRecords(name, addMode) - * addLocalRecords(name, addMode, keyFields) - */ - this.addLocalRecords = function addLocalRecords(arg1, arg2, arg3) { - var name; - var addMode; - var keyFields; - - if (arguments.length < 1) { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); - } - - if (typeof(arg1) == 'string') { - name = arg1; - addMode = arg2; - keyFields = arg3; - } - else { - name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; - addMode = arg1; - keyFields = arg2; - } - - if (typeof(name) == 'undefined' || name === null || name === "") { - name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; - } - else if (typeof(name) != 'string') { - throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); - } - - if (addMode != progress.data.JSDO.MODE_REPLACE) { - throw new Error(msg.getMsgText("jsdoMSG115", arguments.callee.name)); - } - - if (this._localStorage === null) { - this._localStorage = new progress.data.LocalStorage(); - } - - var object = this._localStorage.readFromLocalStorage(name); - - // If storage area does not exist (i.e. object = null) then don't update JSDO local memory - if (object) { - if (this._hasMatchingSchema(object) === false) - throw new Error(msg.getMsgText("jsdoMSG117", name)); - - try { - this._restoreFromLocalStorage(object, addMode, keyFields); - } - catch (e) { - var text = e.message; - throw new Error(text.replace(new RegExp('addRecords', 'g'), 'addLocalRecords')); - } - } - - return object !== null; - }; - - - /* - * This method returns True if each buffer in the jsdo contains a primary key. - */ - this._containsPrimaryKeys = function _containsPrimaryKeys() { - - for (var buf in this._buffers) { - if (this._buffers[buf]._primaryKeys === null) - return false; - } - - return true; - }; - - /* - * Compares JSDO's dataset/table names with those in specified storage object. - * Returns true if they match (or if storageObject is null or empty), else false. - */ - this._hasMatchingSchema = function _hasMatchingSchema(storageObject) { - var isValid = true; - - if (storageObject === null || (Object.keys(storageObject).length === 0)) - return true; - - - if (this._dataSetName) { - if (storageObject[this._dataSetName]) { - for (var buf in this._buffers) - if (storageObject[this._dataSetName][buf] === undefined) { - isValid = false; - break; - } - } - else - isValid = false; // dataset should be in storage area - } - else if (this._dataProperty) { - // If array, we had to wrap in "fake" dataset, so unwrap it - storageObject = storageObject["_localStorage"]; - if (storageObject === undefined || storageObject[this._dataProperty] === undefined) - isValid = false; - } - else { - // If temp-table, we had to wrap in "fake" dataset, so unwrap it - storageObject = storageObject["_localStorage"]; - if (storageObject === undefined || storageObject[this._defaultTableRef._name] === undefined) - isValid = false; - } - - return isValid; - }; - - - /* - * Clears the data saved to local storage. - * - * deleteLocal() - * deleteLocal(name) - */ - this.deleteLocal = function deleteLocal(name) { - if (arguments.length > 1) { - throw new Error(msg.getMsgText("jsdoMSG024", "JSDO", arguments.callee.name + "()")); - } - if (name === undefined || name === null || name === "") { - name = "jsdo_" + this._resource.service.name + "_" + this._resource.name; - } - else if (typeof(name) != 'string') { - throw new Error(msg.getMsgText("jsdoMSG116", "name", arguments.callee.name + "()")); - } - - if (this._localStorage === null) { - this._localStorage = new progress.data.LocalStorage(); - } - this._localStorage.clearLocalStorage(name); - }; - - - // This method is used by saveLocal() to return a jsonObject with current JSDO data based upon option. - // - // In order to take advantage of existing code (createChangeSet() and addRecords()) and particularly - // to use the processing of before-data in addRecords(), for tables and arrays, we create a dummy - // dataset name: _localStorage. - this._prepareDataObjectForLocalStorage = function (option) { - - var storageObject = {}; - - // DataSets - if (this._dataSetName) { - switch (option) { - case progress.data.JSDO.ALL_DATA: - storageObject = this._createDataAndChangeSet(this._dataSetName); - break; - - case progress.data.JSDO.CHANGES_ONLY: - storageObject = this._createChangeSet(this._dataSetName, true); - break; - } - } - // Arrays - else if (this._dataProperty) { - switch (option) { - case progress.data.JSDO.ALL_DATA: - storageObject = this._createDataAndChangeSet("_localStorage"); - break; - - case progress.data.JSDO.CHANGES_ONLY: - storageObject = this._createChangeSet("_localStorage", true); - break; - } - } - // Temp Tables - else { - switch (option) { - case progress.data.JSDO.ALL_DATA: - storageObject = this._createDataAndChangeSet("_localStorage"); - break; - - case progress.data.JSDO.CHANGES_ONLY: - storageObject = this._createChangeSet("_localStorage", true); - break; - } - } - - return storageObject; - }; - - - // Restore the data retrieved from local storage to the JSDO based upon the specified addMode - this._restoreFromLocalStorage = function (storageObject, addMode, keyFields) { - - if (storageObject && (Object.keys(storageObject).length > 0)) { - if (this._dataSetName) { - // Walk thru all tables to retrieve data - for (var buf in this._buffers) - this._restoreDataForTable(this._buffers[buf], storageObject, addMode, keyFields); - } - // Either temp-table or array - else - this._restoreDataForTable(this._defaultTableRef, storageObject, addMode, keyFields); - } - else if (addMode === progress.data.JSDO.MODE_EMPTY) - this._clearData(); - }; - - - this._restoreDataForTable = function (tableRef, jsonObject, addMode, keyFields) { - - // If primaryKeys not found, check if the idProperty is there - keyFields = keyFields !== undefined ? keyFields : tableRef._primaryKeys; - if (keyFields === undefined && this._resource.idProperty) { - keyFields = []; - keyFields[0] = this._resource.idProperty; - } - - if (this._dataSetName) { - var oldUseRelationships = this.useRelationships; - // Turn off useRelationships since addRecords() does not use the working record - this.useRelationships = false; - - try { - tableRef.addRecords(jsonObject, addMode, keyFields); - } finally { - // Restore useRelationships - this.useRelationships = oldUseRelationships; - } - } - // else it's either an array (this._dataProperty) or a temp-table - else { - // Creating dummy dataset name: "_localStorage" for tables and arrays - this._dataSetName = "_localStorage"; - tableRef.addRecords(jsonObject, addMode, keyFields); - this._dataSetName = null; - } - }; - - this.getMethodProperties = function(operation, name) { - var idx; - - if (this._resource._operations) { - if (this._resource._operations[operation]) { - return this._resource._operations[operation]; - } - } - else { - this._resource._operations = {}; - } - for (var idx = 0; idx < this._resource.operations.length; idx++) { - if (this._resource.operations[idx].type == operation) { - return (this._resource._operations[operation] = this._resource.operations[idx]); - } - } - }; - - /////////////////////////////////////////////////////////////////////////// - - // Load data - if (autoFill) - this.fill(); - - }; // End of JSDO - - // Constants for progress.data.JSDO - if ((typeof Object.defineProperty) == 'function') { - Object.defineProperty(progress.data.JSDO, 'MODE_APPEND', { - value: 1, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'MODE_EMPTY', { - value: 2, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'MODE_MERGE', { - value: 3, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'MODE_REPLACE', { - value: 4, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'ERROR', { - value: -1, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'APP_ERROR', { - value: -2, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'RETVAL', { - value: -3, - enumerable: true - }); - Object.defineProperty(progress.data.JSDO, 'DATA_ERROR', { - value: -4, - enumerable: true - }); - } else { - progress.data.JSDO.MODE_APPEND = 1; - progress.data.JSDO.MODE_EMPTY = 2; - progress.data.JSDO.MODE_MERGE = 3; - progress.data.JSDO.MODE_REPLACE = 4; - } - - /* CRUD */ - progress.data.JSDO._OP_CREATE = 1; - progress.data.JSDO._OP_READ = 2; - progress.data.JSDO._OP_UPDATE = 3; - progress.data.JSDO._OP_DELETE = 4; - progress.data.JSDO._OP_SUBMIT = 5; - - /* Offline support: saving data to local storage */ - progress.data.JSDO.ALL_DATA = 1; - progress.data.JSDO.CHANGES_ONLY = 2; - - // Arrays elements as individual fields - // Separator must have at least one characters - progress.data.JSDO.ARRAY_INDEX_SEPARATOR = "_"; - - // setup inheritance for JSDO - progress.data.JSDO.prototype = new progress.util.Observable(); - progress.data.JSDO.prototype.constructor = progress.data.JSDO; - progress.data.JSDO.prototype.toString = function (radix) { - return "JSDO"; - }; - - // setup inheritance for table reference - progress.data.JSTableRef.prototype = new progress.util.Observable(); - progress.data.JSTableRef.prototype.constructor = progress.data.JSTableRef; - progress.data.JSTableRef.prototype.toString = function (radix) { - return "JSTableRef"; - }; - - // Built-in Plugins - progress.data.PluginManager.addPlugin("JFP", { - requestMapping: function(jsdo, params, info) { - var sortFields, - field, - fieldName, - fieldInfo, - tableName, - filter, - sortDir, - ablFilter, - sqlQuery, - methodProperties, - capabilities, - index, - position, - option, - capabilitiesObject, - reqCapabilities = { - filter: { options: [ "ablFilter", "sqlQuery" ], mapping: undefined }, - top: { options: [ "top" ], mapping: undefined }, - skip: { options: [ "skip" ], mapping: undefined }, - id: { options: [ "id" ], mapping: undefined }, - sort: { options: [ "orderBy" ], mapping: undefined } - }, - doConversion = true, - param; - - if (info.operation === "read") { - capabilitiesObject = {}; - methodProperties = jsdo.getMethodProperties(info.operation); - capabilities = methodProperties.capabilities; - - if (capabilities) { - capabilities = capabilities.replace(/\s/g, "").split(","); - for (index = 0; index < capabilities.length; index += 1) { - capabilitiesObject[capabilities[index]] = true; - } - } - for (param in params) { - if (param && (params[param] !== undefined) && reqCapabilities[param]) { - for (index = 0; index < reqCapabilities[param].options.length; index += 1) { - option = reqCapabilities[param].options[index]; - if (capabilitiesObject[option]) { - reqCapabilities[param].mapping = option; - break; - } - } - if (!reqCapabilities[param].mapping) { - throw new Error(msg.getMsgText("jsdoMSG120", - reqCapabilities[param].options.join("' or '"), param)); - } - } - } - - if (jsdo._defaultTableRef && params.tableRef === undefined) { - tableName = jsdo._defaultTableRef._name; - } - else { - tableName = params.tableRef; - } - - if (params.sort) { - // Convert sort expression to JFP format - - if (typeof(params.sort) === "object" && !(params.sort instanceof Array)) { - // Kendo UI sort format - object - // Make params.sort an array - params.sort = (Object.keys( params.sort).length > 1) ? [params.sort] : []; - } - sortFields = ""; - for (index = 0; index < params.sort.length; index += 1) { - field = params.sort[index]; - sortDir = ""; - - if (typeof(field) === "string") { - // setSortFields format - // Extract fieldName and sortDir from string - fieldName = field; - position = field.indexOf(":"); - if (position !== -1) { - sortDir = fieldName.substring(position + 1); - fieldName = fieldName.substring(0, position); - switch(sortDir.toLowerCase()) { - case "desc": - case "descending": - sortDir = "desc"; - break; - } - } - } else { - // Kendo UI sort format - array - // Extract fieldName and sortDir from object - fieldName = field.field; - if (params.sort[index].dir === "desc") { - sortDir = params.sort[index].dir; - } - } - if (tableName) { - // Use original fieldName instead of serialized name - fieldInfo = jsdo[tableName]._fields[fieldName.toLowerCase()]; - if (fieldInfo && fieldInfo.origName) { - fieldName = fieldInfo.origName; - } - } - if (sortDir === "desc") { - fieldName += " DESC"; - } - sortFields += fieldName; - if (index < params.sort.length - 1) { - sortFields += ","; - } - } - } - // Check for empty object - if (typeof(params.filter) === "object" && !(params.filter instanceof Array)) { - params.filter = (Object.keys(params.filter).length >= 1) ? params.filter : undefined; - } - - if (params.filter) { - // If filter is specified as string, then no conversion is necessary - if (typeof params.filter === 'string') { - doConversion = false; - } - - params.tableRef = tableName; - - if (doConversion && (params.tableRef === undefined)) { - throw new Error(msg.getMsgText("jsdoMSG045", "fill() or read()", "params", - "tableRef")); - } - - if (reqCapabilities["filter"].mapping === "ablFilter") { - if (doConversion) { - ablFilter = progress.util._convertToABLWhereString( - jsdo._buffers[params.tableRef], params.filter); - } - else { - ablFilter = params.filter; - } - } - else if (reqCapabilities["filter"].mapping === "sqlQuery") { - if (doConversion) { - sqlQuery = progress.util._convertToSQLQueryString( - jsdo._buffers[params.tableRef], params.filter, true); - } - else { - sqlQuery = params.filter; - } - } - } - - filter = JSON.stringify({ - ablFilter: ablFilter, - sqlQuery: sqlQuery, - orderBy: sortFields, - skip: params.skip, - top: params.top, - id: params.id - }); - - params = {filter: filter}; - } - return params; - } - }); - - if (typeof progress.ui == 'undefined') - progress.ui = {}; - progress.ui.UITableRef = function UITableRef(tableRef) { - this._tableRef = tableRef; - this._listview = null; - this._detailPage = null; - this._listviewContent = undefined; - - this.addItem = function (format) { - var detailForm; - - if (!this._tableRef.record) - throw new Error(msg.getMsgText("jsdoMSG002", this._name)); - - if (!this._listview) return; - - format = format ? format : this._listview.format; - detailForm = (this._detailPage && this._detailPage.name) ? this._detailPage.name : ""; - - if (this._listviewContent === undefined) { - this.clearItems(); - } - var text = this._listview.itemTemplate ? - this._listview.itemTemplate : progress.ui.UIHelper._itemTemplate; - - text = text.replace(new RegExp('{__format__}', 'g'), format); - text = text.replace(new RegExp('{__id__}', 'g'), this._tableRef.record.data._id); - text = text.replace(new RegExp('{__page__}', 'g'), detailForm); - - for (var field in this._tableRef.record.data) { - var value = this._tableRef.record.data[field]; - text = text.replace(new RegExp('{' + field + '}', 'g'), - (value !== undefined && value !== null) ? value : ""); - } - - this._listviewContent += text; - }; - - this.clearItems = function () { - if (this._listview) { - this._listviewContent = ''; - var listviewElement = document.getElementById(this._listview.name); - if (listviewElement) { - listviewElement.innerHTML = ''; - } - } - }; - - this._getFormFieldValue = function (fieldName, detailPageName) { - var value = null, field; - - if (detailPageName === undefined) { - if (this._detailPage && this._detailPage.name) - detailPageName = this._detailPage.name; - } - - if (typeof($) == 'function' && detailPageName) { - field = $("#" + detailPageName + " #" + fieldName); - if (!field || field.length === 0) - field = $("#" + detailPageName + ' [dsid="' + fieldName + '"]'); - if (field && field.length == 1) - value = field.val(); - } - else { - field = document.getElementById(fieldName); - if (field) { - value = field.value; - } - } - - return value; - }; - - this._setFormField = function (fieldName, value, detailPageName) { - var field = null; - - if (detailPageName === undefined) { - if (this._detailPage && this._detailPage.name) - detailPageName = this._detailPage.name; - } - - if (typeof($) == 'function' && detailPageName) { - field = $("#" + detailPageName + " #" + fieldName); - if (!field || field.length === 0) - field = $("#" + detailPageName + ' [dsid="' + fieldName + '"]'); - if (field && field.length == 1) - field.val(value); - } - else { - field = document.getElementById(fieldName); - if (field) { - field.value = value; - } - } - }; - - /* - * Assigns field values from the form. - */ - this.assign = function (detailPageName) { - if (!this._tableRef.record) - throw new Error(msg.getMsgText("jsdoMSG002", this._tableRef._name)); - if ((arguments.length !== 0) && (typeof detailPageName != 'string')) - throw new Error(msg.getMsgText("jsdoMSG024", "UIHelper", "assign()")); - - // Ensure creation of before image record - this._tableRef.record.assign(null); - - var fieldName; - var schema = this._tableRef.getSchema(); - for (var i = 0; i < schema.length; i++) { - fieldName = schema[i].name; - if (fieldName == '_id') continue; - var value = this._getFormFieldValue(fieldName, detailPageName); - // CR OE00241289 Should always copy over field value unless undefined, - // user may have explicitly set it to blank - if (typeof value != 'undefined') { - if (typeof value == 'string' && schema[i].type != 'string') { - value = this._tableRef._jsdo._convertType(value, - schema[i].type, - schema[i].items ? schema[i].items.type : null); - } - this._tableRef.record.data[fieldName] = value; - } - } - - // Ensure order of record - this._tableRef.record._sortRecord(); - - return true; - }; - - this.display = function (pageName) { - if (!this._tableRef.record) - throw new Error(msg.getMsgText("jsdoMSG002", this._tableRef._name)); - - // Display record to form - var schema = this._tableRef.getSchema(); - for (var i = 0; i < schema.length; i++) { - this._setFormField(schema[i].name, this._tableRef.record.data[schema[i].name], pageName); - } - this._setFormField('_id', this._tableRef.record.data._id, pageName); - }; - - this.showListView = function () { - if (!this._listview) return; - - var uiTableRef = this; - var listviewElement; - if (typeof($) == 'function') { - listviewElement = $("#" + this._listview.name); - if (listviewElement && listviewElement.length == 1) { - listviewElement.html(this._listviewContent ? this._listviewContent : ''); - try { - if (listviewElement.attr("data-filter") === "true" - && typeof listviewElement.filterable === "function") { - listviewElement.filterable("refresh"); - } - else { - listviewElement.listview("refresh"); - } - } - catch (e) { - // Workaround for issue with JQuery Mobile throwning exception on refresh - } - } - - if (this._listview.autoLink) { - // Add trigger for 'tap' event to items - $("#" + this._listview.name + " li").each( - function (/* index */) { - $(this).bind('click', - function (/* event, ui */) { - var jsrecord = uiTableRef.getListViewRecord(this); - uiTableRef.display(); - if (typeof(uiTableRef._listview.onSelect) == 'function') { - uiTableRef._listview.onSelect(event, this, jsrecord); - } - }); - }); - } - } - else { - listviewElement = document.getElementById(this._listview.name); - if (listviewElement) { - listviewElement.innerHTML = this._listviewContent; - } - - if (this._listview.autoLink) { - var element = document.getElementById(this._listview.name); - if (element && element.childElementCount > 0) { - for (var i = 0; i < element.children.length; i++) { - element.children[i].onclick = function () { - var jsrecord = this.getListViewRecord(this); - this.display(); - if (typeof(uiTableRef._listview.onSelect) == 'function') { - uiTableRef._listview.onSelect(event, this, jsrecord); - } - }; - } - } - } - } - - this._listviewContent = undefined; - }; - - this.getFormFields = function (fields) { - var i; - - if (!this._tableRef._schema) - return ''; - if (!(fields instanceof Array)) - fields = null; - else { - var tmpFields = {}; - for (i = 0; i < fields.length; i++) { - tmpFields[fields[i]] = fields[i]; - } - fields = tmpFields; - } - var htmltext; - if (!fields || fields['_id']) { - htmltext = ''; - } - else - htmltext = ''; - htmltext += '
    '; - - for (i = 0; i < this._tableRef._schema.length; i++) { - var fieldName = this._tableRef._schema[i].name; - if (fieldName == '_id') continue; - if (fieldName.length > 0 && fieldName.charAt(0) == '_') continue; - if (fields && fields[fieldName] === undefined) continue; - var fieldLabel = this._tableRef._schema[i].title ? - this._tableRef._schema[i].title : this._tableRef._schema[i].name; - var text = (this._detailPage && this._detailPage.fieldTemplate) ? - this._detailPage.fieldTemplate : progress.ui.UIHelper._fieldTemplate; - text = text.replace(new RegExp('{__label__}', 'g'), fieldLabel); - text = text.replace(new RegExp('{__name__}', 'g'), this._tableRef._schema[i].name); - htmltext += text; - } - htmltext += '
    '; - fields = null; - return htmltext; - }; - - this.getListViewRecord = function (htmlIElement) { - var id = htmlIElement.getAttribute('data-id'); - return this._tableRef.findById(id); - }; - - this.getFormRecord = function (detailPageName) { - var id = this._getFormFieldValue('_id', detailPageName); - return this._tableRef.findById(id); - }; - - this._getIdOfElement = function (name) { - if (typeof($) == 'function') { - var element = $("#" + name); - if (!element || element.length === 0) { - element = $('[dsid="' + name + '"]'); - if (element && element.length == 1) { - var id = element.attr("id"); - if (id) - return id; - } - } - } - return name; - }; - - this.setDetailPage = function setDetailPage(obj) { - if (!obj || (typeof(obj) != 'object')) - throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "object")); - if (!obj.name || (typeof(obj.name) != 'string')) - throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "name")); - this._detailPage = obj; - this._detailPage.name = this._getIdOfElement(this._detailPage.name); - }; - this.setListView = function setListView(obj) { - if (!obj || (typeof(obj) != 'object')) - throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "object")); - if (!obj.name || (typeof(obj.name) != 'string')) - throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "name")); - if (obj.format && (typeof(obj.name) != 'string')) - throw new Error(msg.getMsgText("jsdoMSG012", arguments.callee.name, "format")); - - this._listview = obj; - this._listview.name = this._getIdOfElement(this._listview.name); - if (!this._listview.format) { - if (typeof($) == 'function') { - for (var i = 0; i < this._tableRef._schema.length; i++) { - var fieldName = this._tableRef._schema[i].name; - - var field = $("#" + this._listview.name + ' [dsid="' + fieldName + '"]'); - if (field && field.length == 1) { - field.html('{' + fieldName + '}'); - } - } - } - var text = document.getElementById(this._listview.name).innerHTML; - var pos = text.indexOf(''; - progress.ui.UIHelper._defaultFieldTemplate = '
    ' + - '' + - '
    '; - progress.ui.UIHelper._itemTemplate = progress.ui.UIHelper._defaultItemTemplate; - progress.ui.UIHelper._fieldTemplate = progress.ui.UIHelper._defaultFieldTemplate; - - progress.ui.UIHelper.setItemTemplate = function (template) { - progress.ui.UIHelper._itemTemplate = template ? template : progress.ui.UIHelper._defaultItemTemplate; - }; - - progress.ui.UIHelper.setFieldTemplate = function (template) { - progress.ui.UIHelper._fieldTemplate = - template ? template : progress.ui.UIHelper._defaultFieldTemplate; - }; - -})(); - -//this is so that we can see the code in Chrome's Source tab when script is loaded via XHR - -/* -progress.session.js Version: 5.0.0 - -Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*/ - -/*global progress:true */ -(function () { - - /* define these if not defined yet - they may already be defined if - progress.js was included first */ - if (progress === undefined) { - progress = {}; - } - if (progress.data === undefined) { - progress.data = {}; - } - - progress.data.ServicesManager = {}; - progress.data.ServicesManager._services = []; - progress.data.ServicesManager._resources = []; - progress.data.ServicesManager._data = []; - progress.data.ServicesManager._sessions = []; - progress.data.ServicesManager._jsdosessions = []; - /* - progress.data.ServicesManager.put = function(id, jsdo) { - progress.data.ServicesManager._data[id] = jsdo; - }; - progress.data.ServicesManager.get = function(id) { - return progress.data.ServicesManager._data[id]; - }; - */ - - progress.data.ServicesManager.addResource = function (id, resource) { - if (progress.data.ServicesManager._resources[id] === undefined) { - progress.data.ServicesManager._resources[id] = resource; - } - else { - throw new Error("A resource named '" + id + "' was already loaded."); - } - }; - progress.data.ServicesManager.getResource = function (id) { - return progress.data.ServicesManager._resources[id]; - }; - progress.data.ServicesManager.addService = function (id, service) { - if (progress.data.ServicesManager._services[id] === undefined) { - progress.data.ServicesManager._services[id] = service; - } - else { - throw new Error("A service named '" + id + "' was already loaded."); - } - }; - progress.data.ServicesManager.getService = function (id) { - return progress.data.ServicesManager._services[id]; - }; - progress.data.ServicesManager.addSession = function (catalogURI, session) { - if (progress.data.ServicesManager._sessions[catalogURI] === undefined) { - progress.data.ServicesManager._sessions[catalogURI] = session; - } - else { - throw new Error("Cannot load catalog '" + catalogURI + "' multiple times."); - } - }; - - progress.data.ServicesManager.addJSDOSession = function (catalogURI, jsdosession) { - if (progress.data.ServicesManager._jsdosessions[catalogURI] === undefined) { - progress.data.ServicesManager._jsdosessions[catalogURI] = jsdosession; - } - else { - throw new Error("Cannot load catalog '" + catalogURI + "' multiple times."); - } - }; - progress.data.ServicesManager.getSession = function (catalogURI) { - try { - return progress.data.ServicesManager._sessions[catalogURI]; - } - catch (e) { - return null; - } - }; - - progress.data.ServicesManager.cleanSession = function (session) { - var servicesKey, - resourcesKey, - sessionsKey, - service, - services = progress.data.ServicesManager._services, - resources = progress.data.ServicesManager._resources, - sessions = progress.data.ServicesManager._sessions, - jsdosessions = progress.data.ServicesManager._jsdosessions; - - // Delete the services and resources in the ServicesManager - // associated with the Session given - for (servicesKey in services) { - service = null; - if (services[servicesKey]._session === session) { - service = services[servicesKey]; - delete services[servicesKey]; - } - - if (!service) { - continue; - } - - for (resourcesKey in resources) { - if (resources[resourcesKey].service === service) { - delete resources[resourcesKey]; - } - } - } - - // Delete the session and jsdosession from the ServicesManager - for (sessionsKey in sessions) { - if (sessions[sessionsKey] === session) { - delete sessions[sessionsKey]; - - if(jsdosessions[sessionsKey]) { - delete jsdosessions[sessionsKey]; - } - } - } - }; - - /* - * Scans URL for parameters of the form {name} - * Returns array with the names - */ - function extractParamsFromURL(url) { - var urlParams = [], - paramName = null; - - if (typeof (url) === 'string') { - url.split("").forEach(function (c) { - if (c === '{') { - paramName = ""; - } else if (c === '}') { - if (paramName) { - urlParams.push(paramName); - } - paramName = null; - } else if (paramName !== null) { - paramName += c; - } - }); - } - return urlParams; - } - - /* - * Adds the catalog.json file provided by the catalog parameter, which is a JSDO - * that has loaded the catalog - */ - progress.data.ServicesManager.addCatalog = function (services, session) { - var name, value; - - if (!services) { - throw new Error("Cannot find 'services' property in catalog file."); - } - if (services instanceof Array) { - - // first check if there are duplicates before we add them to our cache, - // which only handles unique values - services.forEach(function (service) { - // don't allow services with the same name across sessions - if (progress.data.ServicesManager.getService(service.name) !== undefined) { - throw new Error("A service named '" + service.name + "' was already loaded."); - } - - if (service.resources instanceof Array) { - service.resources.forEach(function (resource) { - if (progress.data.ServicesManager.getResource(resource.name) !== undefined) { - throw new Error("A resource named '" + resource.name + "' was already loaded."); - } - }); - } - else { - throw new Error("Missing 'resources' array in catalog."); - } - }); - - for (var j = 0; j < services.length; j++) { - services[j]._session = session; - this.addService(services[j].name, services[j]); // Register the service - var resources = services[j].resources; - var baseAddress = services[j].address; - if (resources instanceof Array) { - for (var i = 0; i < resources.length; i++) { - var resource = resources[i]; - resource.fn = {}; - resource.service = services[j]; - resources[i].url = baseAddress + resources[i].path; - // Register resource - progress.data.ServicesManager.addResource(resources[i].name, resources[i]); - - // Process schema - resource.fields = null; - resource.primaryKeys = null; - if (resource.schema) { - resource.fields = {}; - resource.primaryKeys = {}; - resource._dataSetName = undefined; - resource._tempTableName = undefined; - var properties = null; - - var keys, field; - - try { - if (typeof resource.schema.properties != 'undefined') { - keys = Object.keys(resource.schema.properties); - properties = resource.schema.properties; - if (keys.length == 1) { - if (typeof resource.schema.properties[keys[0]].properties != - 'undefined') { - // Schema corresponds to a DataSet - resource._dataSetName = keys[0]; - } - else if (typeof resource.schema.properties[keys[0]].items != - 'undefined') { - // Schema corresponds to a temp-table - resource.dataProperty = keys[0]; - properties = resource.schema.properties[keys[0]].items.properties; - resource._tempTableName = resource.dataProperty; - resource.primaryKeys[resource._tempTableName] = - resource.schema.properties[keys[0]].primaryKey; - } - } - } - else { - keys = Object.keys(resource.schema); - if (keys.length == 1) { - resource.dataProperty = keys[0]; - if (typeof resource.schema[keys[0]].items != 'undefined') { - // Catalog format correspond to Table Schema - properties = resource.schema[keys[0]].items.properties; - resource._tempTableName = resource.dataProperty; - resource.primaryKeys[resource._tempTableName] = - resource.schema[keys[0]].primaryKey; - } - else if (typeof resource.schema[keys[0]].properties != 'undefined') { - // Catalog format correspond to DataSet Schema - resource._dataSetName = keys[0]; - resource.dataProperty = null; - properties = resource.schema; - } - } - } - } - catch (e) { - throw new Error("Error parsing catalog file."); - } - - var tableName; - if (properties) { - if (resource._dataSetName) { - properties = properties[resource._dataSetName].properties; - for (tableName in properties) { - resource.fields[tableName] = []; - resource.primaryKeys[tableName] = properties[tableName].primaryKey; - var tableProperties; - if (properties[tableName].items - && properties[tableName].items.properties) { - tableProperties = properties[tableName].items.properties; - } - else { - tableProperties = properties[tableName].properties; - } - for (field in tableProperties) { - tableProperties[field].name = field; - if (field != '_id') - resource.fields[tableName].push(tableProperties[field]); - } - } - } - else { - tableName = resource.dataProperty ? resource.dataProperty : ""; - resource.fields[tableName] = []; - for (field in properties) { - properties[field].name = field; - if (field != '_id') - resource.fields[tableName].push(properties[field]); - } - } - } - else - throw new Error("Error parsing catalog file."); - } - else - resource.fields = null; - - // Validate relationship property - if ((resource.relations instanceof Array) - && resource.relations[0] - && resource.relations[0].RelationName) { - throw new Error( - "Relationship properties in catalog must begin with lowercase."); - } - // Process operations - resource.generic = {}; - if (resource.operations) { - for (var idx = 0; idx < resource.operations.length; idx++) { - if (resource.operations[idx].path) { - resource.operations[idx].url = - resource.url + resource.operations[idx].path; - } - else { - resource.operations[idx].url = resource.url; - } - if (!resource.operations[idx].params) { - resource.operations[idx].params = []; - } - if (!resource.operations[idx].type) { - resource.operations[idx].type = "INVOKE"; - } - - // Set opname - validation of opname is done later - var opname = resource.operations[idx].type.toLowerCase(); - - // Set default verb based on operation - if (!resource.operations[idx].verb) { - switch (opname) { - case 'create': - resource.operations[idx].verb = "POST"; - break; - case 'read': - resource.operations[idx].verb = "GET"; - break; - case 'update': - case 'invoke': - case 'submit': - case 'count': - resource.operations[idx].verb = "PUT"; - break; - case 'delete': - resource.operations[idx].verb = "DELETE"; - break; - default: - break; - } - } - - // Point fn to operations - var func = function fn(object, async) { - var deferred; - - // Add static variable fnName to function - if (typeof fn.fnName == 'undefined') { - fn.fnName = arguments[0]; // Name of function - fn.definition = arguments[1]; // Operation definition - return; - } - - var reqBody = null; - var url = fn.definition.url; - var jsdo = this; - var xhr = null; - - var request = {}; - var i; - - if (object) { - if (typeof (object) != "object") { - throw new Error("Catalog error: Function '" + - fn.fnName + "' requires an object as a parameter."); - } - var objParam; - if (object instanceof XMLHttpRequest - || (object.constructor - && object.constructor.name === "XMLHttpRequest")) { - jsdo = object.jsdo; - xhr = object; - objParam = xhr.objParam; - - // use the request from the xhr request if possible - request = xhr.request; - } - else { - objParam = object; - } - - if (typeof async == 'undefined') { - async = this._async; - } - else { - async = Boolean(async); - } - - request.objParam = objParam; - - // Process objParam - var isInvoke = (fn.definition.type.toUpperCase() == 'INVOKE'); - for (i = 0; i < fn.definition.params.length; i++) { - name = fn.definition.params[i].name; - switch (fn.definition.params[i].type) { - case 'PATH': - case 'QUERY': - case 'MATRIX': - var value = null; - if (objParam) - value = objParam[name]; - if (!value) - value = ""; - if (url.indexOf('{' + name + '}') == -1) { - throw new Error("Catalog error: Reference to " + - fn.definition.params[i].type + " parameter '" + - name + "' is missing in path."); - } - url = url.replace( - new RegExp('{' + name + '}', 'g'), - encodeURIComponent(value)); - break; - case 'REQUEST_BODY': - case 'REQUEST_BODY,RESPONSE_BODY': - case 'RESPONSE_BODY,REQUEST_BODY': - if (xhr && !reqBody) { - reqBody = objParam; - } - else { - var reqParam = objParam[name]; - if (isInvoke - && (fn.definition.params[i].xType - && ("DATASET,TABLE".indexOf( - fn.definition.params[i].xType) != -1))) { - var unwrapped = (jsdo._resource.service.settings - && jsdo._resource.service.settings.unwrapped); - if (unwrapped) { - // Remove extra level if found - if ((typeof (reqParam) == 'object') - && (Object.keys(reqParam).length == 1) - && (typeof (reqParam[name]) == 'object')) - reqParam = reqParam[name]; - } - else { - // Add extra level if not found - if ((typeof (reqParam) == 'object') - && (typeof (reqParam[name]) == 'undefined')) { - reqParam = {}; - reqParam[name] = objParam[name]; - } - } - } - if (!reqBody) { - reqBody = {}; - } - reqBody[name] = reqParam; - } - break; - case 'RESPONSE_BODY': - break; - default: - throw new Error("Catalog error: " + - "Unexpected parameter type '" + - fn.definition.params[i].type + "'."); - } - } - - // URL has parameters - if (url.indexOf('{') != -1) { - var paramsFromURL = extractParamsFromURL(url); - for (i = 0; i < paramsFromURL.length; i++) { - name = paramsFromURL[i]; - value = null; - if (objParam) - value = objParam[name]; - if (!value) - value = ""; - if (typeof (value) === "object") { - value = JSON.stringify(value); - } - url = url.replace( - new RegExp('{' + name + '}', 'g'), - encodeURIComponent(value)); - } - } - } - - request.fnName = fn.fnName; - request.async = async; - - if (request.deferred === undefined) { - deferred = new progress.util.Deferred(); - request.deferred = deferred; - } - - var data = jsdo._httpRequest(xhr, fn.definition.verb, - url, reqBody, request, async); - return data; - }; - // End of Function Definition - - switch (resource.operations[idx].verb.toLowerCase()) { - case 'get': - case 'post': - case 'put': - case 'delete': - break; - default: - throw new Error("Catalog error: Unexpected HTTP verb '" + - resource.operations[idx].verb + - "' found while parsing the catalog."); - } - - switch (opname) { - case 'invoke': - break; - case 'create': - case 'read': - case 'update': - case 'delete': - case 'submit': - case 'count': - if (typeof (resource.generic[opname]) == "function") { - throw new Error("Catalog error: Multiple '" + - resource.operations[idx].type + - "' operations specified in the catalog for resource '" + - resource.name + "'."); - } - else - resource.generic[opname] = func; - break; - default: - throw new Error("Catalog error: Unexpected operation '" + - resource.operations[idx].type + - "' found while parsing the catalog."); - } - - // Set fnName - name = resource.operations[idx].name; - if (opname === "invoke" || opname === "count") { - resource.fn[name] = {}; - resource.fn[name]["function"] = func; - } - else { - name = "_" + opname; - } - func(name, resource.operations[idx]); - } - } - } - } - } - } - else { - throw new Error("Missing 'services' array in catalog."); - } - - }; - - /* - * Prints debug information about the ServicesManager. - */ - progress.data.ServicesManager.printDebugInfo = function (resourceName) { - if (resourceName) { - //console.log("** ServicesManager **"); - //console.log("** BEGIN **"); - var resource = progress.data.ServicesManager.getResource(resourceName); - if (resource) { - var cSchema = "Schema:\n"; - var cOperations = "Operations: " + resource.operations.length + "\n"; - for (var field in resource.schema.properties) { - cSchema += "\nName: " + field - + "\n"; - } - - for (var i = 0; i < resource.operations.length; i++) { - cOperations += "\n" + i - + "\nName: " + resource.operations[i].name - + "\nURL: " + resource.operations[i].url - + "\ntype: " + resource.operations[i].type - + "\nverb: " + resource.operations[i].verb - + "\nparams: " + resource.operations[i].params.length - + "\n"; - } - console.log("** DEBUG INFO **\nResource name: %s\nURL:%s\n%s\n%s\n\n", - resource.name, resource.url, cSchema, cOperations); - } - else - console.log("Resource not found"); - //console.log("** END **"); - } - }; - - - /* - * Contains information about a server-side Mobile service. - * Properties of args parameter for constructor: - * @param name the name of the service - * @param uri the URI of the service - */ - progress.data.MobileServiceObject = function MobileServiceObject(args) { - var _name = args.name; - Object.defineProperty( - this, - 'name', - { - get: function () { - return _name; - }, - enumerable: true - } - ); - - var _uri = args.uri; - Object.defineProperty( - this, - 'uri', - { - get: function () { - return _uri; - }, - enumerable: true - } - ); - }; - - /* - An object that maintains the X-CLIENT-PROPS header string - The data for the string is stored in the internal variable named contextObject and is - always up to date. The internal var contextString isn't created until the first time it's - needed (the first get of the contextHeader property), and then it's updated an cached - A call to setContext or setContextProperty updates contextObject but sets contextString to - null, which signals that it needs to be updated. If contextObject is an empty object, - contextString is set to undefined to indicate that no header is to be sent - */ - progress.data.ContextProperties = function () { - var contextObject = {}, - contextString; // if null, contextObject has been changed but string wasn't updated yet - - // the string to be sent in the X-CLIENT-PROPS header (unless Session.xClientProps has been set) - Object.defineProperty( - this, - 'contextHeader', - { - get: function () { - var header; - - if (contextString === null) { // needs to be updated - header = JSON.stringify(contextObject); - if (header === "{}") { - contextString = undefined; - } else { - contextString = header; - } - } - - return contextString; - }, - enumerable: true - } - ); - - /* determine whether the property is already present, and - - add it if it's not present - remove it if propertyValue is explicitly passed as undefined - otherwise replace its value (even if the new value is null or "") - */ - this.setContextProperty = function (propertyName, propertyValue) { - if (arguments.length < 2) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText( - "jsdoMSG122", - 'Session', - 'setContextProperty', - 2 - )); - } - if (arguments.length !== 2) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText( - "jsdoMSG122", - "Session", - "setContextProperty", - 2 - )); - } - if (typeof propertyName !== "string") { - // {1}: Parameter {1} must be of type {3} in {4} call. - throw new Error(progress.data._getMsgText( - "jsdoMSG121", - 'Session', - 1, - 'string', - 'setContextProperty' - )); - } - - if (propertyValue === undefined) { - delete contextObject[propertyName]; // OK if it doesn't exist -- no error - } else { - contextObject[propertyName] = propertyValue; - } - contextString = null; // must be updated on next get of this.contextHeader - }; - - this.setContext = function (context) { - var prop; - - if (arguments.length < 1) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'setContext', 1)); - } - if (arguments.length > 1) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'setContext', 1)); - } - if (typeof context === "object") { - /* Copy the properties of the context passed in as an argument into - * an internal contextObject. (Note that if the context object passed in - * has a prototype, this code copies them, too) - */ - contextObject = {}; - for (prop in context) { - if (context.hasOwnProperty(prop)) { - if (typeof context[prop] !== "function") { - contextObject[prop] = context[prop]; - } - } - } - } else if ((context === undefined) || (context === null)) { - contextObject = {}; - } else { - // {1}: Parameter {1} must be of type {3} in {4} call. - throw new Error(progress.data._getMsgText( - "jsdoMSG121", - 'Session', - 1, - 'Object', - 'setContextProperty' - )); - } - contextString = null; // must be updated on next get of this.contextHeader - }; - - this.getContext = function () { - if (arguments.length > 0) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContext', 0)); - } - return contextObject; - }; - - this.getContextProperty = function (propertyName) { - if (arguments.length < 1) { - // {1}: Incorrect number of arguments in {2} call. There should be {3}. - throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContextProperty', 1)); - } - if (arguments.length > 1) { - // {1}: Incorrect number of arguments in {2} call. There should be only {3}."; - throw new Error(progress.data._getMsgText("jsdoMSG122", 'Session', 'getContextProperty', 1)); - } - return contextObject[propertyName]; - }; - - }; // end of ContextProperties - - /* - * Manages authentication and session ID information for a service. - * - * Use: OE mobile developer instantiates a session and calls addCatalog() to load - * information for one or more services defined in a catalog file. - * - * Developer instantiates JDSOs as needed. - * Usually all of the JSDOs will use the same session, but if a client-side - * service needs resources from more than one REST app, there would need to be more - * than one session - * - */ - progress.data.Session = function Session(options) { - - var defPropSupported = false; - if ((typeof Object.defineProperty) === "function") { - defPropSupported = true; - } - - var that = this, - jsdosession, // "backpointer" if this Session is being used by a JSDOSession - isUserAgentiOS = false, // checked just below this var statement - isFirefox = false, // checked just below this var statement - isEdge = false, // checked just below this var statement - isIE = false, // checked just below this var statement - canPassCredentialsToOpenWithCORS = false, // False will always work if creds are correct - defaultiOSBasicAuthTimeout = 4000, - deviceIsOnline = true, // online until proven offline - restApplicationIsOnline = false, // was the Mobile Web Application that this Session object - // connects to online the last time it was checked? - // (value is always false if session is not logged in) - oepingAvailable = false, - defaultPartialPingURI = "/rest/_oeping", - partialPingURI = defaultPartialPingURI, - _storageKey, - _authProvider = null, - customCredentials = false, - - // Note: the variables above here are used during the lifetime of the object; the ones below - // are only used while the constructor is executing - storedAuthModel, - storedURI, - newURI, - stateWasReadFromStorage = false; - - // This is a hidden argument to suppress this warning and be re-used for future warnings - if (!options || options._silent !== true) { - console.warn( - "Session: As of JSDO 4.4, the Session object has been deprecated. " - + "Please use the JSDOSession object instead." - ); - } - - if (typeof navigator !== "undefined") { - if (typeof navigator.userAgent !== "undefined") { - isUserAgentiOS = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i); - isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; - // detect that we're running in MS Edge browser - isEdge = navigator.userAgent.indexOf('Edge/') > -1; - // detect that we're running in IE 11 (or IE 11 in pre-11 mode) or IE 10 browser - isIE = ((navigator.userAgent.indexOf('Trident/')) > -1 - || (navigator.userAgent.indexOf('MSIE 10') > -1)); - } - } - - // Firefox, Edge, and IE will throw an error on the send() if CORS is being used for the request - // and we have included credentials in the URI (which is what passing them to open() does), - canPassCredentialsToOpenWithCORS = !(isFirefox || isEdge || isIE); - - // When using basic authentication, we can pass the user name and password to the XMLHttpRequest.open() - // method. However, in some browsers, passing credentials to open() will result in the xhr's .send() - // method throwing an error. The goal of this function is to figure out whether it's safe to include - // the credentials. It returns false if there could be a problem, true otherwise. - // Note: currently it does this solely on the basis of what browser we are running in, regardless - // of whether the request will actually use the CORS protocol. Ideally, we should take into account whether - // the request will actually require CORS. The question is whether we can reliably do that. - // The reason for taking the specific request into account is that there are drawbacks to not passing the - // credentials when we are NOT using CORS, namely that if the credentials are invalid, some browsers will - // put up their own prompt for credentials in non-CORS situations (those browsers are IE, Edge, and Chrome) - function canPassCredentialsToOpen() { - return canPassCredentialsToOpenWithCORS; - } - - this._onlineHandler = function () { - setDeviceIsOnline(true); - that.trigger("online", that, null); - }; - - this._offlineHandler = function () { - setDeviceIsOnline(false); - that.trigger("offline", that, progress.data.Session.DEVICE_OFFLINE, null); - }; - - if ((typeof window !== "undefined") && (window.addEventListener)) { - window.addEventListener("online", this._onlineHandler, false); - window.addEventListener("offline", this._offlineHandler, false); - } - - /* constants and properties - define them as properties via the defineProperty() - * function, which has "writable" and "configurable" parameters that both - * default to false, so these calls create properties that are read-only - * - * IF WE DECIDE THAT WE CAN ASSUME WE ALWAYS RUN WITH A VERSION OF JAVASCRIPT THAT SUPPORTS - * Object.DefineProperty(), WE CAN DELETE THE defPropSupported VARIABLE, THE TEST OF IT BELOW, - * AND THE 'ELSE' CLAUSE BELOW AND ALL THE setXxxx functions (AND CHANGE THE CALLS TO THE setXxxx - * FUNCTIONS SO THEY JUST REFER TO THE PROPERTY) - * - */ - - // define these unconditionally so we don't get a warning on the push calls that they might - // have been uninitialized - var _catalogURIs = []; - var _services = []; - var _jsdos = []; - - this.onOpenRequest = null; - - var _password = null; - - if (defPropSupported) { - var _userName = null; - Object.defineProperty( - this, - 'userName', - { - get: function () { - return _userName; - }, - enumerable: true - } - ); - - var _loginTarget = '/static/home.html'; - Object.defineProperty( - this, - 'loginTarget', - { - get: function () { - return _loginTarget; - }, - enumerable: true - } - ); - - var _serviceURI = null; - Object.defineProperty( - this, - 'serviceURI', - { - get: function () { - return _serviceURI; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'catalogURIs', - { - get: function () { - return _catalogURIs; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'services', - { - get: function () { - return _services; - }, - enumerable: true - } - ); - - var _loginResult = null; - Object.defineProperty( - this, - 'loginResult', - { - get: function () { - return _loginResult; - }, - enumerable: true - } - ); - - var _loginHttpStatus = null; - Object.defineProperty( - this, - 'loginHttpStatus', - { - get: function () { - return _loginHttpStatus; - }, - enumerable: true - } - ); - - var _clientContextId = null; - Object.defineProperty( - this, - 'clientContextId', - { - get: function () { - return _clientContextId; - }, - enumerable: true - } - ); - - var _authenticationModel = progress.data.Session.AUTH_TYPE_ANON; - Object.defineProperty( - this, - 'authenticationModel', - { - get: function () { - return _authenticationModel; - }, - set: function (newval) { - if (newval) { - newval = newval.toLowerCase(); - } - switch (newval) { - case progress.data.Session.AUTH_TYPE_FORM: - case progress.data.Session.AUTH_TYPE_BASIC: - case progress.data.Session.AUTH_TYPE_ANON: - case progress.data.Session.AUTH_TYPE_SSO: - case null: - _authenticationModel = newval; - storeSessionInfo("authenticationModel", newval); - break; - default: - throw new Error( - "Error setting Session.authenticationModel. '" - + newval + "' is an invalid value." - ); - } - }, - enumerable: true - } - ); - - var _lastSessionXHR = null; - Object.defineProperty( - this, - 'lastSessionXHR', - { - get: function () { - return _lastSessionXHR; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'connected', - { - get: function () { - return (this.loginResult === progress.data.Session.LOGIN_SUCCESS) - && restApplicationIsOnline - && deviceIsOnline; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'JSDOs', - { - get: function () { - return _jsdos; - }, - enumerable: true - } - ); - - var _pingInterval = 0; - var _timeoutID = null; - Object.defineProperty( - this, - 'pingInterval', - { - get: function () { - return _pingInterval; - }, - set: function (newval) { - if ((typeof newval === "number") && (newval >= 0)) { - _pingInterval = newval; - storeSessionInfo("pingInterval", newval); - if (newval > 0) { - // if we're logged in, start autopinging - if (this.loginResult === progress.data.Session.LOGIN_SUCCESS) { - _timeoutID = setTimeout(this._autoping, newval); - } - } else if (newval === 0) { - clearTimeout(_timeoutID); - _pingInterval = 0; - } - } else { - throw new Error( - "Error setting Session.pingInterval. '" - + newval + "' is an invalid value." - ); - } - }, - enumerable: true - } - ); - - var _contextProperties = new progress.data.ContextProperties(); - Object.defineProperty( - this, - "_contextProperties", - { - get: function () { - return _contextProperties; - }, - enumerable: false - } - ); - - var isInvalidated = false; - Object.defineProperty( - this, - "_isInvalidated", - { - get: function () { - return isInvalidated; - }, - enumerable: false - } - ); - - // used internally, not supported as part of the Session API (tho authProvider is part - // of the *JSDOSession* API) - Object.defineProperty( - this, - "_authProvider", - { - get: function () { - return _authProvider; - }, - set: function (newval) { - if (_authProvider) { - throw new Error( - "Internal Error setting Session._authProvider. '" - + "The property has already been set." - ); - } - - setAuthProvider(newval); - }, - enumerable: false - } - ); - } else { - this.userName = null; - this.loginTarget = '/static/home.html'; - this.serviceURI = null; - this.catalogURIs = []; - this.services = []; - this.loginResult = null; - this.loginHttpStatus = null; - this.clientContextId = null; - this.authenticationModel = progress.data.Session.AUTH_TYPE_ANON; - this.lastSessionXHR = null; - } - - // stores data value using the JSDOSession's storage key plus the infoName - // argument as a key. If there is no infoName, just uses the storage key - // by itself (the latter case is intended to serve as a flag that we have - // stored this JSDOSession's data before) - // - function storeSessionInfo(infoName, value) { - var key; - if (that.loginResult === progress.data.Session.LOGIN_SUCCESS && - typeof(sessionStorage) === 'object' && _storageKey) { - - key = _storageKey; - if (infoName) { - key = key + "." + infoName; - } - if (typeof value !== 'undefined') { - sessionStorage.setItem(key, JSON.stringify(value)); - } - } - } - - function retrieveSessionInfo(infoName) { - var key, - jsonStr, - value = null; - if (typeof sessionStorage === 'object' && _storageKey) { - key = _storageKey; - if (infoName) { - key = key + "." + infoName; - } - jsonStr = sessionStorage.getItem(key); - if (jsonStr !== null) { - try { - value = JSON.parse(jsonStr); - } catch (e) { - value = null; - } - } - return value; - } - } - - function clearSessionInfo(infoName) { - var key; - if (typeof (sessionStorage) === 'object' && _storageKey) { - key = _storageKey; - if (infoName) { - key = key + "." + infoName; - sessionStorage.removeItem(key); - } - } - } - - function storeAllSessionInfo() { - if (_storageKey) { - storeSessionInfo("loginResult", that.loginResult); - storeSessionInfo("userName", that.userName); - storeSessionInfo("serviceURI", that.serviceURI); - storeSessionInfo("loginHttpStatus", that.loginHttpStatus); - storeSessionInfo("authenticationModel", that.authenticationModel); - storeSessionInfo("pingInterval", that.pingInterval); - storeSessionInfo("oepingAvailable", oepingAvailable); - storeSessionInfo("partialPingURI", partialPingURI); - storeSessionInfo("clientContextId", that.clientContextId); - storeSessionInfo("deviceIsOnline", deviceIsOnline); - storeSessionInfo("restApplicationIsOnline", restApplicationIsOnline); - if (that._authProvider) { - storeSessionInfo( - "_authProvider.init", - { - uri: that._authProvider.uri, - authenticationModel: that._authProvider.authenticationModel - } - ); - } - storeSessionInfo(_storageKey, true); - } - } - - function clearAllSessionInfo() { - if (_storageKey) { - if (retrieveSessionInfo(_storageKey)) { - clearSessionInfo("loginResult"); - clearSessionInfo("userName"); - clearSessionInfo("serviceURI"); - clearSessionInfo("loginHttpStatus"); - clearSessionInfo("clientContextId"); - clearSessionInfo("deviceIsOnline"); - clearSessionInfo("restApplicationIsOnline"); - clearSessionInfo("authenticationModel"); - clearSessionInfo("pingInterval"); - clearSessionInfo("oepingAvailable"); - clearSessionInfo("partialPingURI"); - clearSessionInfo("_authProvider.init"); - clearSessionInfo(_storageKey); - } - } - } - - function setSessionInfoFromStorage(key) { - var authproviderInitObject; - if (retrieveSessionInfo(key)) { - setLoginResult(retrieveSessionInfo("loginResult"), this); - setUserName(retrieveSessionInfo("userName"), this); - setServiceURI(retrieveSessionInfo("serviceURI"), this); - setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"), this); - setClientContextID(retrieveSessionInfo("clientContextId"), this); - setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline")); - setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline")); - that.authenticationModel = retrieveSessionInfo("authenticationModel"); - that.pingInterval = retrieveSessionInfo("pingInterval"); - setOepingAvailable(retrieveSessionInfo("oepingAvailable")); - setPartialPingURI(retrieveSessionInfo("partialPingURI")); - // if information on an AuthenticationProvider for the session is in storage, and if - // the authProvider hasn't already been set for this Session, create a new authProvider - // using the same info as the old one. This would be likely to happen if the app's code - // had used the old JSDOSession.login API, where we create the AuthenticationProvider - // automatically during login instead of the code passing one to the constructor - if (!that._authProvider) { - authproviderInitObject = retrieveSessionInfo("_authProvider.init"); - if (authproviderInitObject) { - setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject)); - } - } - } - } - - function setUserName(newname, sessionObject) { - if (defPropSupported) { - _userName = newname; - } else { - sessionObject.userName = newname; - } - - storeSessionInfo("userName", newname); - } - - function setLoginTarget(target, sessionObject) { - if (defPropSupported) { - _loginTarget = target; - } else { - sessionObject.loginTarget = target; - } - } - - function setServiceURI(url, sessionObject) { - if (defPropSupported) { - _serviceURI = url; - } else { - sessionObject.serviceURI = url; - } - - storeSessionInfo("serviceURI", url); - } - - function pushCatalogURIs(url, sessionObject) { - if (defPropSupported) { - _catalogURIs.push(url); - } else { - sessionObject.catalogURIs.push(url); - } - } - - function pushService(serviceObject, sessionObject) { - if (defPropSupported) { - _services.push(serviceObject); - } else { - sessionObject.services.push(serviceObject); - } - } - - function findService(serviceName) { - _services.forEach(function (service) { - if (service.name === serviceName) { - return service; - } - }); - return null; - } - - function setLoginResult(result, sessionObject) { - if (defPropSupported) { - _loginResult = result; - } else { - sessionObject.loginResult = result; - } - - if (result === progress.data.Session.LOGIN_SUCCESS) { - storeSessionInfo("loginResult", result); - } else { - // Let's clear sessionStorage since we logged out or something went bad! - clearAllSessionInfo(); - } - } - - function setLoginHttpStatus(status, sessionObject) { - if (defPropSupported) { - _loginHttpStatus = status; - } else { - sessionObject.loginHttpStatus = status; - } - - storeSessionInfo("loginHttpStatus", status); - } - - function setClientContextIDfromXHR(xhr, sessionObject) { - if (xhr) { - setClientContextID(getResponseHeaderNoError(xhr, "X-CLIENT-CONTEXT-ID"), sessionObject); - } - } - - function setClientContextID(ccid, sessionObject) { - if (defPropSupported) { - _clientContextId = ccid; - } else { - sessionObject.clientContextId = ccid; - } - - storeSessionInfo("clientContextId", ccid); - } - - function setLastSessionXHR(xhr, sessionObject) { - if (defPropSupported) { - _lastSessionXHR = xhr; - } else { - sessionObject.lastSessionXHR = xhr; - } - } - - function setDeviceIsOnline(value) { - deviceIsOnline = value; - - storeSessionInfo("deviceIsOnline", value); - } - - function setAuthProvider(value) { - // Do this to preserve authprovider's null-ness. - _authProvider = value ? value : null; - } - - function setRestApplicationIsOnline(value) { - restApplicationIsOnline = value; - - storeSessionInfo("restApplicationIsOnline", value); - } - - function setOepingAvailable(value) { - oepingAvailable = value; - - storeSessionInfo("oepingAvailable", value); - } - - function setPartialPingURI(value) { - partialPingURI = value; - - storeSessionInfo("partialPingURI", value); - } - - /* - When using CORS, if the client asks for a response header that is not among - the headers exposed by the Web application, the user agent may write an error - to the console, e.g., "REFUSED TO GET UNSAFE HEADER". This function checks for - a given response header in a way that will avoid the error message. It does this - by requesting all headers and then checking to see whether the desired header - is present (it will not be present, even if the server sent it, if the server has not - also allowed that header). The function caches the string returned by getAllResponseHeaders - by storing it on the xhr that was used in the request. It does the caching in - case there is another header to be checked. - */ - function getResponseHeaderNoError(xhr, headerName) { - var allHeaders = xhr._pdsResponseHeaders, - regExp; - - if (allHeaders === undefined) { - allHeaders = xhr.getAllResponseHeaders(); - if (allHeaders) { - xhr._pdsResponseHeaders = allHeaders; - } else { - xhr._pdsResponseHeaders = null; - } - } - if (allHeaders) { - regExp = new RegExp("^" + headerName + ":", "mi"); - if (allHeaders.match(regExp)) { - return xhr.getResponseHeader(headerName); - } - } - - return null; - } - - // "Methods" - - this._pushJSDOs = function (jsdo) { - _jsdos.push(jsdo); - }; - - - /* _openRequest (intended for progress.data library use only) - * calls open() for an xhr -- the assumption is that this is an xhr for a JSDO, and we need to add - * some session management information for the request, such as user credentials and a session ID if - * there is one - * - * The callback parameter is to support async calls --- it's possible that the call in here to - * _openRequestAndAuthorize will make an async request (for token refresh), so it's expected that - * callers will invoke _openRequest with a callback parameter for async execution - */ - this._openRequest = function (xhr, verb, url, async, callback) { - var urlPlusCCID, - that = this; - - function afterOpenAndAuthorize(arg) { - // _openRequestAndAuthorize can return either an Error or an xhr - // TODO: we might need to fix this - if (arg instanceof Error) { - throw arg; - } else { - // add CCID header - if (that.clientContextId && (that.clientContextId !== "0")) { - xhr.setRequestHeader("X-CLIENT-CONTEXT-ID", that.clientContextId); - } - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(that, xhr); - - if (typeof that.onOpenRequest === 'function') { - var params = { - "xhr": xhr, - "verb": verb, - "uri": urlPlusCCID, - "async": async, - "formPreTest": false, - "session": that - }; - that.onOpenRequest(params); - // xhr = params.xhr; //Note that, currently, this would have no effect in the caller. - } - if (callback) { - callback(); - } - } - } - - if (this._isInvalidated) { - // Session: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "Session")); - } - - if (this.loginResult !== progress.data.Session.LOGIN_SUCCESS - && !this._authProvider && this.authenticationModel) { - throw new Error("Attempted to make server request when there is no active session."); - } - - // if resource url is not absolute, add the REST app url to the front - urlPlusCCID = this._prependAppURL(url); - - // add CCID as JSESSIONID query string to url - urlPlusCCID = this._addCCIDtoURL(urlPlusCCID); - - // add time stamp to the url - if (progress.data.Session._useTimeStamp) { - urlPlusCCID = progress.data.Session._addTimeStampToURL(urlPlusCCID); - } - - // should be able to remove this check and only do what's in the "if" when we no longer - // support calling the Session API directly (need to keep that now because tdriver, for - // one, uses the Session object, and uses it synchronously - if (this._authProvider) { - this._authProvider._openRequestAndAuthorize( - xhr, - verb, - urlPlusCCID, - async, - afterOpenAndAuthorize - ); - } else { - this._setXHRCredentials(xhr, verb, urlPlusCCID, this.userName, _password, async); - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - _addWithCredentialsAndAccept(xhr, "application/json"); - } - afterOpenAndAuthorize(xhr); - } - - }; - - // callback used in login to determine whether ping is available on server - this.pingTestCallback = function (cbArgs) { - var foundOeping = cbArgs.pingResult ? true : false; - - setOepingAvailable(foundOeping); - }; - - // generic async callback, currently used by login(), addCatalog(), logout(), connect, and disconnect - this._onReadyStateChangeGeneric = function () { - var xhr = this; - var result; - var errorObject; - - clearTimeout(xhr._requestTimeout); // for the iOS Basic Auth bug - - if (xhr.readyState === 4) { - result = null; - errorObject = null; - - // initial processing of the response from the Web application - if ((typeof xhr.onResponseFn) === 'function') { - try { - result = xhr.onResponseFn(xhr); - // ( note that result will remain null if this is a logout() ) - } catch (e) { - errorObject = e; - } - } - // handle the results of the processing (e.g., fire any events required) - if ((typeof xhr.onResponseProcessedFn) === 'function') { - if (!result) { - result = progress.data.Session.GENERAL_FAILURE; - } - xhr.onResponseProcessedFn(xhr.pdsession, result, errorObject, xhr); - } - } - }; - - // Intended only for internal use by the JSDO library - // NOTE: disconnect does not currently send a request to the Web application for the Anonymous or - // OE SSO models. It's conceivable, though unlikely, that it might. For that reason, the design is - // similar to the functions that DO make a server request. There is a "setup" function (this one) - // and a separate function to process the "result" (_processDisconnectResult, below). Currently the - // setup function is minimal and just calls _processDisconnectResult directly. If we ever do need to - // send a server request, _processDisconnectResult will be specified as the callback to be invoked - // from onReadyStateChangeGeneric. The possibility of this potential enhancement is the reason for - // the odd signature of _processDisconnectResult, which has a currently unused first parameter for - // the potential XHR. - this._disconnect = function (deferred) { - - // Note: we use the "no harm, no foul" approach for disconnect. If you aren't connected, it's - // regarded as a success rather than cause for throwing an error. - this._processDisconnectResult(null, deferred); - }; - - - // This is separate from _disconnect for cases in which _disconnect makes a server request. - // If there has been a server request, xhr should be valid and deferred will be undefined - // If there was no server request, xhr will be undefined and deferred will be valid. - // If this needs to be enhanced to support server requests, see _procesLoginResponse as - // a general model - // Probably the only time this function will be called as the result of a server request is with - // Form authentication, and even then it's questionable - this._processDisconnectResult = function (xhr, deferred) { - - this._reinitializeAfterLogout(this, progress.data.Session.SUCCESS); - this._disconnectComplete(this, progress.data.Session.SUCCESS, null, null, deferred); - }; - - this._disconnectComplete = function (pdsession, result, errObj, xhr, deferred) { - pdsession.trigger("afterDisconnect", pdsession, result, errObj, xhr, deferred); - }; - - - // GET RID OF progress.data.Session login CODE (AND RELATED) IF WE DROP SUPPORT FOR USING - // THE OLD progress.data.Session API DIRECTLY (mainly a problem for existing code (tdriver), - // or anyone who wants to call methods synchronously, which should be no one) - /* login - * - */ - - // store password here until successful login; only then do we store it in the Session object - var pwSave = null; - // store user name here until successful login; only then do we store it in the Session object - var unameSave = null; - this.login = function (serviceURI, loginUserName, loginPassword, loginTarget) { - var uname, - pw, - isAsync = false, - args = [], - deferred, - iOSBasicAuthTimeout, - uriForRequest; // "decorated" version of serviceURI, used to actually send the request - - pwSave = null; // in case these are left over from a previous login - unameSave = null; - - if (!defPropSupported) { - // this is here on the presumably slim chance that we're running with a - // version of JavaScript that doesn't support defineProperty (otherwise - // the lower casing will have already happened). When we decide that it's - // OK to remove our conditionalization of property definitions, we should - // get rid of this whole conditional - this.authenticationModel = this.authenticationModel.toLowerCase(); - } - - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // Session: Cannot call login() when authenticationModel is SSO. - // Please use the AuthenticationProvider object instead. - throw new Error(progress.data._getMsgText("jsdoMSG057", 'Session', 'login()')); - } - - if (this.loginResult === progress.data.Session.LOGIN_SUCCESS || this._authProvider) { - throw new Error("Attempted to call login() on a Session object that is already logged in."); - } - - if (arguments.length > 0) { - if (arguments[0] && typeof arguments[0] === 'object') { - // Note that arguments[0].serviceURI may be undefined because when the JSDOSession - // uses a Session internally, it passes serviceURI to the constructor. The other - // properties may be present, though - args[0] = arguments[0].serviceURI; - args[1] = arguments[0].userName; - args[2] = arguments[0].password; - args[3] = arguments[0].loginTarget; - args[4] = arguments[0].async; - - /* Special for JSDOSession: if this method was called by a JSDOSession object, - it passes deferred and jsdosession and we need to eventually attach them - to the XHR we use so that the promise created by the JSDOSession will work - correctly - */ - deferred = arguments[0].deferred; - - iOSBasicAuthTimeout = arguments[0].iOSBasicAuthTimeout; - if (typeof iOSBasicAuthTimeout === 'undefined') { - iOSBasicAuthTimeout = defaultiOSBasicAuthTimeout; - } else if (iOSBasicAuthTimeout && (typeof iOSBasicAuthTimeout !== 'number')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'login', - 'The iOSBasicAuthTimeout argument was invalid.' - )); - } - } else { - args = arguments; - } - } - - if (args.length > 0) { - if (args[0]) { - var restURLtemp = args[0]; - - // get rid of trailing '/' because appending service url that starts with '/' - // will cause request failures - if (restURLtemp[restURLtemp.length - 1] === "/") { - restURLtemp = restURLtemp.substring(0, restURLtemp.length - 1); - } - setServiceURI(restURLtemp, this); - } else if (!this.serviceURI) { - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); - throw new Error("Session.login() is missing the serviceURI argument."); - } - - if (args[1]) { - uname = args[1]; - } - - if (args[2]) { - pw = args[2]; - } - - if (args[3]) { - setLoginTarget(args[3], this); - } - - if (args[4]) { - if (typeof (args[4]) === 'boolean') { - isAsync = args[4]; - } else { - throw new Error("Session.login() was passed an async setting that is not a boolean."); - } - } - } else { - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); - throw new Error("Session.login() is missing the serviceURI argument."); - } - - // use these temp cred variables later; if login succeeds, we'll use them to set the - // real credentials - unameSave = uname; - pwSave = pw; - - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_ANON || - this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - /* anonymous should NOT have a username and password passed (this is - probably unnecessary because the XHR seems to send the request without - credentials first, then intercept the 401 if there is one and try again, - this time with credentials. Just making sure. - */ - /* For form authentication, we may as well not send the user name and password - * on this request, since we are just trying to test whether the authentication - * has already happened and they are therefore irrelevant - */ - uname = null; - pw = null; - } - - var xhr = new XMLHttpRequest(); - xhr.pdsession = this; - - try { - uriForRequest = this.serviceURI + this.loginTarget; - if (progress.data.Session._useTimeStamp) { - uriForRequest = progress.data.Session._addTimeStampToURL(uriForRequest); - } - this._setXHRCredentials(xhr, 'GET', uriForRequest, uname, pw, isAsync); - - progress.data.Session._setNoCacheHeaders(xhr); - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(this, xhr); - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - _addWithCredentialsAndAccept( - xhr, - "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ); - } - - xhr._isAsync = isAsync; - if (isAsync) { - xhr.onreadystatechange = this._onReadyStateChangeGeneric; - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - xhr.onResponseFn = this._afterFormPretestLogin; - } else { - xhr.onResponseFn = this._processLoginResult; - xhr.onResponseProcessedFn = this._loginComplete; - } - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC - && isUserAgentiOS - && iOSBasicAuthTimeout > 0) { - xhr._requestTimeout = setTimeout( - function () { - clearTimeout(xhr._requestTimeout); - xhr._iosTimeOutExpired = true; - xhr.abort(); - }, - iOSBasicAuthTimeout - ); - } - xhr._jsdosession = jsdosession; // in case the caller is a JSDOSession - xhr._deferred = deferred; // in case the caller is a JSDOSession - } - - if (typeof this.onOpenRequest === 'function') { - var isFormPreTest = false; - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - isFormPreTest = true; - } - - // set this here in case onOpenRequest checks it - setLastSessionXHR(xhr, this); - var params = { - "xhr": xhr, - "verb": "GET", - "uri": this.serviceURI + this.loginTarget, - "async": false, - "formPreTest": isFormPreTest, - "session": this - }; - this.onOpenRequest(params); - xhr = params.xhr; // just in case it has been changed - } - setLastSessionXHR(xhr, this); - xhr.send(null); - } catch (e) { - clearTimeout(xhr._requestTimeout); - setLoginHttpStatus(xhr.status, this); - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, this); - unameSave = null; - pwSave = null; - throw e; - } - - if (isAsync) { - return progress.data.Session.ASYNC_PENDING; - } else { - setLoginHttpStatus(xhr.status, this); - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - return (this._afterFormPretestLogin(xhr)); - } else { - return (this._processLoginResult(xhr)); - } - } - }; - - - this._afterFormPretestLogin = function (xhr) { - var pdsession = xhr.pdsession; - setLoginHttpStatus(xhr.status, xhr.pdsession); - - var formLoginParams = { - "xhr": xhr, - "pw": pwSave, - "uname": unameSave, - "theSession": pdsession - }; - try { - return doFormLogin(formLoginParams); - } catch (e) { - pwSave = null; - unameSave = null; - throw e; - } - }; - - /* doFormLogin - * This function handles logging in to a service that uses form-based authentication. It's separate - * from the main login function because it's long. One of the things it does is examine the - * response from an initial attempt to get the login target without credentials (done in the main - * login() function) to determine whether the user has already been authenticated. Although a - * current OE Mobile Web application (as of 5/30/2013) will return an error if authentication - * failed on a form login, previous versions and non-OE servers return a - * redirect to a login page and the user agent (browser or native wrapper) - * usually then fetches the redirect location and returns it along with a - * 200 Success status, when in fcat it was an authentication failure. Hence - * the need to analyze the response to try to figure out what we get back. - * - */ - function doFormLogin(args) { - var xhr = args.xhr; - var theSession = args.theSession; - var oldXHR; - - // check whether we got the OE REST Form based error response - var contentType = null; - var needAuth = false; - var params = { - "session": theSession, - "xhr": xhr, - "statusFromjson": null - }; - - contentType = xhr.getResponseHeader("Content-Type"); - - if (contentType && contentType.indexOf("application/json") >= 0) { - handleJSONLoginResponse(params); - if (!params.statusFromjson || (params.statusFromjson >= 400 && params.statusFromjson < 500)) { - needAuth = true; - } else { - // either the response shows that we're already authenticated, or - // there's some error other than an authentication error - setLoginHttpStatus(params.statusFromjson, theSession); - } - } else { - // need to do only 200 for async to work with MWA down - if (theSession.loginHttpStatus === 200) { - if (_gotLoginForm(xhr)) { - needAuth = true; - } - // else we are assuming we truly retrieved the login target and - // therefore we were previously authenticated - } - // else had an error, just return it - } - - if (needAuth) { - // create new XHR, because if this is an async call we don't want to - // confuse things by using this xhr to send another request while we're - // still processing its old request (this function, doFormLogin(), may - // have been called from onReadyStateChangeGeneric and it's conceivable - // that that function has more code to execute involving this xhr) - oldXHR = xhr; - xhr = new XMLHttpRequest(); - args.xhr = xhr; - params.xhr = xhr; - - // need to transfer any properties that the Session code stored in the - // the xhr that need to persist across the 2 requests made by a our - // login implementation for Form auth - xhr.pdsession = oldXHR.pdsession; - xhr._isAsync = oldXHR._isAsync; - xhr._deferred = oldXHR._deferred; // special for JSDOSession - xhr._jsdosession = oldXHR._jsdosession; // special for JSDOSession - - xhr.open('POST', theSession.serviceURI + "/static/auth/j_spring_security_check", xhr._isAsync); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xhr.setRequestHeader("Cache-Control", "max-age=0"); - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(theSession, xhr); - - _addWithCredentialsAndAccept(xhr, "application/json"); - - try { - - // Note: this gives a developer a way to change certain aspects of how we do the - // form-based login, but we will still be assuming that we are going directly to - // j_spring_security_check and including credentials in the body. They really should not - // try to change that. - // - if (typeof theSession.onOpenRequest === 'function') { - var cbparams = { - "xhr": xhr, - "verb": "POST", - "uri": theSession.serviceURI + "/static/auth/j_spring_security_check", - "async": xhr._isAsync, - "formPreTest": false, - "session": theSession - }; - theSession.onOpenRequest(cbparams); - xhr = cbparams.xhr; - } - - if (xhr._isAsync) { - xhr.onreadystatechange = theSession._onReadyStateChangeGeneric; - xhr.onResponseFn = theSession._afterFormLogin; - xhr.onResponseProcessedFn = theSession._loginComplete; - } - - // j_username=username&j_password=password&submit=Submit - xhr.send("j_username=" + encodeURIComponent(args.uname) - + "&j_password=" + encodeURIComponent(args.pw) + "&submit=Submit"); - } catch (e) { - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, theSession); - setLoginHttpStatus(xhr.status, theSession); - // null the temporary credentials variables - unameSave = null; - pwSave = null; - throw e; - } - } - - if (xhr._isAsync && !needAuth) { - xhr.onResponseProcessedFn = theSession._loginComplete; - return theSession._afterFormLogin(xhr); - } - if (!xhr._isAsync) { - return theSession._afterFormLogin(xhr); - } - - } - - this._afterFormLogin = function (xhr) { - // check what we got - var theSession = xhr.pdsession; - var params = { - "session": theSession, - "xhr": xhr, - "statusFromjson": null - }; - var contentType = xhr.getResponseHeader("Content-Type"); - - if (contentType && contentType.indexOf("application/json") >= 0) { - handleJSONLoginResponse(params); - if (!params.statusFromjson) { - throw new Error( - "Internal OpenEdge Mobile client error handling login response. HTTP status: " + - xhr.status + "." - ); - } - - setLoginHttpStatus(params.statusFromjson, theSession); - } else { - if (xhr.status === 200) { - // Was the response actually the login failure page or the login page itself (in case - // the appSecurity config file sets the login failure url so the server sends the login - // page again)? If so, call it an error because the credentials apparently failed to be - // authenticated - if (_gotLoginFailure(xhr) || _gotLoginForm(xhr)) { - setLoginHttpStatus(401, theSession); - } else { - setLoginHttpStatus(xhr.status, theSession); - } - } - } - - return theSession._processLoginResult(xhr); - }; - - - this._processLoginResult = function (xhr) { - /* OK, one way or another, by hook or by crook, the Session object's loginHttpStatus - * has been set to the value that indicates the real outcome of the - * login, after adjusting for form-based authentication and anything - * else. At this point, it should be just a matter of examining - * this.loginHttpStatus, using it to set this.loginResult, maybe doing - * some other work appropriate to the outcome of the login, and returning - * this.loginResult. - */ - var pdsession = xhr.pdsession; - - setLoginHttpStatus(xhr.status, xhr.pdsession); - - if (pdsession.loginHttpStatus === 200) { - setLoginResult(progress.data.Session.LOGIN_SUCCESS, pdsession); - setRestApplicationIsOnline(true); - setUserName(unameSave, pdsession); - _password = pwSave; - pdsession._saveClientContextId(xhr); - storeAllSessionInfo(); // save info to persistent storage - - var pingTestArgs = { - pingURI: null, - async: true, - onCompleteFn: null, - fireEventIfOfflineChange: true, - onReadyStateFn: pdsession._pingtestOnReadyStateChange - }; - pingTestArgs.pingURI = pdsession._makePingURI(); - pdsession._sendPing(pingTestArgs); // see whether the ping feature is available - } else { - if (pdsession.loginHttpStatus === 401) { - setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE, pdsession); - } else { - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, pdsession); - } - } - setLastSessionXHR(xhr, pdsession); - updateContextPropsFromResponse(pdsession, xhr); - - // null the temporary credentials variables - unameSave = null; - pwSave = null; - if (xhr._iosTimeOutExpired) { - throw new Error(progress.data._getMsgText("jsdoMSG047", "login")); - } - - // return loginResult even if it's an async operation -- the async handler - // (e.g., onReadyStateChangeGeneric) will just ignore - return pdsession.loginResult; - }; - - - this._loginComplete = function (pdsession, result, errObj, xhr) { - pdsession.trigger("afterLogin", pdsession, result, errObj, xhr); - }; - - // GET RID OF progress.data.Session logout CODE (AND RELATED) IF WE DROP SUPPORT FOR USING - // THE OLD progress.data.Session API DIRECTLY (mainly a problem for existing code (tdriver), - // or anyone who wants to call methods synchronously, which should be no one) - this.logout = function (args) { - var isAsync = false, - errorObject = null, - xhr, - deferred, - params; - - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // Session: Cannot call logout() when authenticationModel is SSO. - // Please use the AuthenticationProvider object instead. - throw new Error(progress.data._getMsgText("jsdoMSG057", 'Session', 'logout()')); - } - - if (this.loginResult !== progress.data.Session.LOGIN_SUCCESS && this.authenticationModel) { - throw new Error("Attempted to call logout when there is no active session."); - } - - if (typeof args === 'object') { - isAsync = args.async; - if (isAsync && (typeof isAsync !== 'boolean')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "Session", - 'logout', - 'The async argument was invalid.' - )); - } - /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes - deferred and jsdosession and we need to eventually attach them to the XHR we use - so that the promise created by the JSDOSession will work correctly - */ - deferred = args.deferred; - } - - xhr = new XMLHttpRequest(); - xhr.pdsession = this; - try { - /* logout when auth model is anonymous is a no-op on the server side - (but we need to set _jsdosession and _deferred anyway to make promise work - if logout was called by a JSDOSession) */ - xhr._jsdosession = jsdosession; // in case the caller is a JSDOSession - xhr._deferred = deferred; // in case the caller is a JSDOSession - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_FORM || - this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { - if (isAsync) { - xhr.onreadystatechange = this._onReadyStateChangeGeneric; - xhr.onResponseFn = this._processLogoutResult; - xhr.onResponseProcessedFn = this._logoutComplete; - } - - - xhr.open('GET', this.serviceURI + "/static/auth/j_spring_security_logout", isAsync); - - /* instead of calling _addWithCredentialsAndAccept, we code the withCredentials - * and setRequestHeader inline so we can do it slightly differently. That - * function deliberately sets the request header inside the try so we don't - * run into a FireFox oddity that would give us a successful login and then - * a failure on getCatalog (see the comment on that function). On logout, - * however, we don't care -- just send the Accept header so we can get a 200 - * response - */ - try { - xhr.withCredentials = true; - } catch (e) { - // Empty - } - - xhr.setRequestHeader("Accept", "application/json"); - - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(this, xhr); - - if (typeof this.onOpenRequest === 'function') { - setLastSessionXHR(xhr, this); - params = { - "xhr": xhr, - "verb": "GET", - "uri": this.serviceURI + "/static/auth/j_spring_security_logout", - "async": false, - "formPreTest": false, - "session": this - }; - this.onOpenRequest(params); - xhr = params.xhr; - } - - setLastSessionXHR(xhr, this); - xhr.send(); - } else { - xhr._anonymousLogoutOK = true; - } - } catch (e) { - this._reinitializeAfterLogout(this, false); - throw e; - } - - if (!isAsync) { - try { - this._processLogoutResult(xhr); - } catch (e) { - throw e; - } - } - - if (isAsync && this.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { - // fake async for Anonymous -- fire afterLogout event - try { - this._processLogoutResult(xhr); - } catch (e) { - errorObject = e; - } - this._logoutComplete(this, null, errorObject, xhr); - } - - }; - - // This function erases all evidence of itself from the ServicesManager and - // flips a bit to prevent it to be used in the future - this.invalidate = function () { - isInvalidated = true; - cleanServicesManager(); - }; - - this._logoutComplete = function (pdsession, result, errorObject, xhr) { - // ignore result, it doesn't apply to logout -- is probably null or GENERAL_FAILURE - // we include it so onReadyStateChangeGeneric calls this correctly - pdsession.trigger("afterLogout", pdsession, errorObject, xhr); - }; - - this._processLogoutResult = function (xhr) { - var logoutSucceeded; - var pdsession = xhr.pdsession; - var basicStatusOK = false; - - if (xhr._anonymousLogoutOK) { - logoutSucceeded = true; - } else if (xhr.status !== 200) { - /* Determine whether an error returned from the server is really an error - */ - if (pdsession.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { - /* If the Auth model is Basic, we probably got back a 404 Not found. - * But that's OK, because logout from Basic is meaningless on the - * server side unless it happens to be stateful, which is the only - * reason we even try calling j_spring_security_logout - */ - if (xhr.status === 404) { - logoutSucceeded = true; - } else { - logoutSucceeded = false; - throw new Error("Error logging out, HTTP status = " + xhr.status); - } - } else { - // for Form auth, any error on logout is an error - logoutSucceeded = false; - - // page refresh - we should call _reinitializeAfterLogout, or do something, so that - // caller can try logging in again (this is not a problem specific to page refresh, - // but the case of a page refresh after a server has gone down emphasizes it) - - throw new Error("Error logging out, HTTP status = " + xhr.status); - } - } else { - logoutSucceeded = true; - } - - updateContextPropsFromResponse(pdsession, xhr); - pdsession._reinitializeAfterLogout(pdsession, logoutSucceeded); - }; - - this._reinitializeAfterLogout = function (pdsession, success) { - setLoginResult(null, pdsession); - setLoginHttpStatus(null, pdsession); - setClientContextID(null, pdsession); - setUserName(null, pdsession); - setAuthProvider(null); - - _password = null; - - if (success) { - setRestApplicationIsOnline(false); - setOepingAvailable(false); - setPartialPingURI(defaultPartialPingURI); - setLastSessionXHR(null, pdsession); - clearTimeout(_timeoutID); // stop autopinging - } - }; - - /* addCatalog - * - */ - this.addCatalog = function (arg1, arg2, arg3, arg4) { - var catalogURI, - catalogUserName, - catalogPassword, - isAsync = false, - xhr, - deferred, - iOSBasicAuthTimeout, - catalogIndex, - authProvider, - that = this; - - function addCatalogAfterOpen() { - /* This is here as much for CORS situations as the possibility that there might be an - * out of date cached version of the catalog. The CORS problem happens if you have - * accessed the catalog locally and then run an app on a different server that requests - * the catalog. Your browser already has the catalog, but the request used to get it was - * a non-CORS request and the browser will raise an error - */ - progress.data.Session._setNoCacheHeaders(xhr); - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(that, xhr); - - if (isAsync) { - xhr.onreadystatechange = that._onReadyStateChangeGeneric; - xhr.onResponseFn = that._processAddCatalogResult; - xhr.onResponseProcessedFn = that._addCatalogComplete; - - if (that.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC - && isUserAgentiOS - && iOSBasicAuthTimeout) { - xhr._requestTimeout = setTimeout(function () { - clearTimeout(xhr._requestTimeout); - xhr._iosTimeOutExpired = true; - xhr.abort(); - }, - iOSBasicAuthTimeout); - } - - // in case the caller is a JSDOSession - xhr._jsdosession = jsdosession; - xhr._deferred = deferred; - xhr._catalogIndex = catalogIndex; - } - - try { - if (typeof that.onOpenRequest === 'function') { - setLastSessionXHR(xhr, that); - var params = { - "xhr": xhr, - "verb": "GET", - "uri": catalogURI, - "async": false, - "formPreTest": false, - "session": that - }; - that.onOpenRequest(params); - xhr = params.xhr; - } - - setLastSessionXHR(xhr, that); - xhr.send(null); - } catch (e) { - throw new Error("Error retrieving catalog '" + catalogURI + "'.\n" + e.message); - } - if (isAsync) { - return progress.data.Session.ASYNC_PENDING; - } else { - return that._processAddCatalogResult(xhr); - } - - } - - if (this._isInvalidated) { - // JSDOSession: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); - } - - // Assume we're using a custom username/pw/authprovider - customCredentials = true; - - // check whether the args were passed in a single object. If so, copy them - // to the named arguments and a variable - if (arguments.length > 0) { - if (typeof arg1 === 'object') { - // check whether it's OK to add a catalog whilst offline - if (!arguments[0].offlineAddCatalog) { - if ((this.loginResult !== progress.data.Session.LOGIN_SUCCESS - && !this._authProvider) - && this.authenticationModel) { - throw new Error("Attempted to call addCatalog when there is no active session."); - } - } - - catalogURI = arg1.catalogURI; - if (!catalogURI || (typeof catalogURI !== 'string')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'addCatalog', - 'The catalogURI argument was missing or invalid.' - )); - } - catalogUserName = arg1.userName; - if (catalogUserName && (typeof catalogUserName !== 'string')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'addCatalog', - 'The catalogUserName argument was invalid.' - )); - } - catalogPassword = arg1.password; - if (catalogPassword && (typeof catalogPassword !== 'string')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'addCatalog', - 'The catalogPassword argument was invalid.' - )); - } - isAsync = arg1.async; - if (isAsync && (typeof isAsync !== 'boolean')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'addCatalog', - 'The async argument was invalid.' - )); - } - iOSBasicAuthTimeout = arg1.iOSBasicAuthTimeout; - if (typeof iOSBasicAuthTimeout === 'undefined') { - iOSBasicAuthTimeout = defaultiOSBasicAuthTimeout; - } else if (iOSBasicAuthTimeout && (typeof iOSBasicAuthTimeout !== 'number')) { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - 'Session', - 'addCatalog', - 'The iOSBasicAuthTimeout argument was invalid.' - )); - } - authProvider = arg1.authProvider; - - /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes - deferred, jsdosession, and catalogIndex and we need to eventually attach them to the - XHR we use so that the promise created by the JSDOSession will work correctly - */ - deferred = arg1.deferred; - catalogIndex = arg1.catalogIndex; - } else { - catalogURI = arg1; - if (typeof catalogURI !== 'string') { - throw new Error("First argument to Session.addCatalog must be the URL of the catalog."); - } - catalogUserName = arg2; - if (catalogUserName && (typeof catalogUserName !== 'string')) { - throw new Error("Second argument to Session.addCatalog must be a user name string."); - } - catalogPassword = arg3; - if (catalogPassword && (typeof catalogPassword !== 'string')) { - throw new Error("Third argument to Session.addCatalog must be a password string."); - } - } - } else { - throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog."); - } - - if (!authProvider) { - authProvider = this._authProvider; - - // Guess we're using the default credentials passed earlier - customCredentials = false; - } - - // Note: we expect that there will always be an authProvider if a login has been done. - // Therefore, we don't need to set catalogUsername and catalogPassword if they aren't - // passed in. What we should do here, when we extend the AuthenticationProvider API - // for the older auth models, is take any uname and pw passed in and create an auth - // provider, log in to the catalogURI with it, create an authImpl, and then fetch the - // catalog. - if (!catalogUserName) { - catalogUserName = this.userName; - } - - if (!catalogPassword) { - catalogPassword = _password; - } - - xhr = new XMLHttpRequest(); - xhr.pdsession = this; - xhr._catalogURI = catalogURI; - - // for now we don't support multiple version of the catalog across sessions - if (progress.data.ServicesManager.getSession(catalogURI) !== undefined) { - if (isAsync) { - /* - Attempt to get the event to fire AFTER this call returns ASYNC_PENDING - (and if the method was called from a JSDOSession, create an xhr to communicate - information related to promises back to its afterAddCatalog handler). Note that - the xhr is never used to make a request, it just carries data in the way - expected by the handler) - */ - // in case the caller is a JSDOSession - xhr._jsdosession = jsdosession; - xhr._deferred = deferred; - xhr._catalogIndex = catalogIndex; - - setTimeout( - this._addCatalogComplete, - 10, - this, - progress.data.Session.CATALOG_ALREADY_LOADED, - null, - xhr - ); - - return progress.data.Session.ASYNC_PENDING; - } - return progress.data.Session.CATALOG_ALREADY_LOADED; - } - - if (authProvider) { - authProvider._openRequestAndAuthorize(xhr, 'GET', catalogURI, isAsync, addCatalogAfterOpen); - // existing code in JSDOSession addCatalog expects to get this as a return value, - // have to return it now - return progress.data.Session.ASYNC_PENDING; - } else { // should be able to get rid of this if we do away with synchronous (old Session API) support - this._setXHRCredentials(xhr, 'GET', catalogURI, catalogUserName, catalogPassword, isAsync); - // Note that we are not adding the CCID to the URL or as a header, because the catalog may not - // be stored with the REST app and even if it is, the AppServer ID shouldn't be relevant - - return addCatalogAfterOpen(); - } - - }; - - this._processAddCatalogResult = function (xhr) { - var _catalogHttpStatus = xhr.status; - var theSession = xhr.pdsession; - var servicedata; - var catalogURI = xhr._catalogURI, - serviceURL, - theJSDOSession = jsdosession; - - // Only change the Session's state if the default AuthProv is being used - if (!customCredentials) { - toggleOnlineState(xhr); - } - - if (((_catalogHttpStatus === 200) || (_catalogHttpStatus === 0)) && xhr.responseText) { - servicedata = theSession._parseCatalog(xhr); - try { - progress.data.ServicesManager.addCatalog(servicedata, theSession); - } catch (e) { - if (progress.data.ServicesManager.getSession(catalogURI) !== undefined) { - /* this failed because the catalog had already been loaded, but the code - in addCatalog did not catch that, probably because we are executing - the JSDOSession addCatalog with multiple catalogURIs passed, and 2 - are the same - */ - return progress.data.Session.CATALOG_ALREADY_LOADED; - } - // different catalogs, with same resource name - throw new Error("Error processing catalog '" + catalogURI + "'. \n" + e.message); - } - // create a mobile service object and add it to the Session's array of same - servicedata.forEach(function (service) { - serviceURL = theSession._prependAppURL(service.address); - pushService( - new progress.data.MobileServiceObject( - { - name: service.name, - uri: serviceURL - } - ), - theSession - ); - - if (service.settings && service.settings.useXClientProps && !theSession.xClientProps) { - console.warn( - "Catalog warning: Service settings property 'useXClientProps' " - + "is true but 'xClientProps' property has not been set." - ); - } - }); - - pushCatalogURIs(catalogURI, theSession); - progress.data.ServicesManager.addSession(catalogURI, theSession); - if (theJSDOSession) { - progress.data.ServicesManager.addJSDOSession(catalogURI, theJSDOSession); - } - } else if (_catalogHttpStatus === 401) { - return progress.data.AuthenticationProvider._getAuthFailureReason(xhr); - } else if (xhr._iosTimeOutExpired) { - throw new Error(progress.data._getMsgText("jsdoMSG047", "addCatalog")); - } else { - throw new Error( - "Error retrieving catalog '" + catalogURI - + "'. Http status: " + _catalogHttpStatus + "." - ); - } - - return progress.data.Session.SUCCESS; - }; - - this._addCatalogComplete = function (pdsession, result, errObj, xhr) { - pdsession.trigger("afterAddCatalog", pdsession, result, errObj, xhr); - }; - - - /* - * ping -- determine whether the Mobile Web Application that the Session object represents - * is available, which includes determining whether its associated AppServer is running - * Also determine whether the Mobile services managed by this Session object are available - * (which means simply that they're known to the Mobile Web Application) - * (Implementation note: be sure that this Session object's "connected" - * property retains its current value until the end of this function, where - * it gets updated, if necessary, after calling _isOnlineStateChange - * - * Signatures : - * @param arg - * There are 2 signatures -- - * - no argument -- do an async ping of the Session's Mobile Web application. The only effect - * of the ping will be firing an offline or an online event, if appropriate - * The ping function itself will return false to the caller - * - object argument -- the object's properties provide the input args. They are all - * optional (if for some reason the caller passes an object that has no properties, it's - * the same as passing no argument at all). The properties may be: - * async -- tells whether to execute the ping asynchronously (which is the default) - * onCompleteFn -- if async, this will be called when response returns - * doNotFireEvent -- used internally, controls whether the ping method causes an offline - * or online event to be fired if there has been a change (the default is that it - * does, but our Session._checkServiceResponse() sets this to true so that it can - * control the firing of the event) - * offlineReason -- if present, and if the ping code discovers that teh server is offline, - * the ping code will set this with its best guess - * as to the reason the server is offline - */ - this.ping = function (args) { - var pingResult = false, - pingArgs = { - pingURI: null, - async: true, - onCompleteFn: null, - fireEventIfOfflineChange: true, - onReadyStateFn: this._onReadyStateChangePing, - offlineReason: null - }; - - if (this._isInvalidated) { - // Session: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "Session")); - } - - if ((!this._authProvider) && (this.loginResult !== progress.data.Session.LOGIN_SUCCESS)) { - throw new Error("Attempted to call ping when not logged in."); - } - - if (args) { - if (args.async !== undefined) { - // when we do background pinging (because pingInterval is set), - // we pass in an arg that is just an object that has an async property, - // set to true. This can be expanded to enable other kinds of ping calls - // to be done async (so that application developers can do so, if we decide - // to support that) - pingArgs.async = args.async; - } - - if (args.doNotFireEvent !== undefined) { - pingArgs.fireEventIfOfflineChange = !args.doNotFireEvent; - } - - if (args.onCompleteFn && (typeof args.onCompleteFn) === 'function') { - pingArgs.onCompleteFn = args.onCompleteFn; - } - /* Special for JSDOSession: if this method was called by a JSDOSession object, it passes - deferred and jsdosession and we need to eventually attach them to the XHR we use so that - the promise created by the JSDOSession will work correctly - */ - pingArgs.deferred = args.deferred; - pingArgs.jsdosession = args.jsdosession; - - } - - - /* Ping the Mobile Web Application (this will also determine whether AppServer is available) - * Call _processPingResult() if we're synchronous, otherwise the handler for the xhr.send() - * will call it - */ - pingArgs.pingURI = that._makePingURI(); - that._sendPing(pingArgs); - if (!pingArgs.async) { - if (pingArgs.xhr) { - pingResult = that._processPingResult(pingArgs); - if (args.offlineReason !== undefined) { - args.offlineReason = pingArgs.offlineReason; - } - } else { - pingResult = false; // no xhr returned from _sendPing, something must have gone wrong - } - - if (args.xhr !== undefined) { - // if it's a sync ping, return the xhr if caller indicates they want it - // (there's almost guaranteed to be one, even if the ping was never sent - // if for some reason there isn't, we give them the null or undefined we ended up with) - args.xhr = pingArgs.xhr; - } - } - // else it's async, deliberately returning false - // so developer not misled into thinking the ping succeeded - - return pingResult; - }; - - - // "protected" Functions - - /* - * given a value of true or false for being online for the Mobile Web Application - * managed by this Session object, determine whether that changes the current - * state of being offline or online. - * Returns true if the input state is a change from the current state - * - * Signature : - * @param isOnline Required. True to determine whether online is a state change, false to - * determine whether offline constitutes a state change. Boolean. - * - */ - this._isOnlineStateChange = function (isOnline) { - var stateChanged = false; - - if (isOnline && !(this.connected)) { - stateChanged = true; - } else if (!isOnline && (this.connected)) { - stateChanged = true; - } - - return stateChanged; - }; - - - /* - * given information about the response from a request made to a service, - * do the following: - * - * determine whether the online status of the Session has changed, and - * set the Session's Connected property accordingly - * if the Session's online status has changed, fire the appropriate event - * - * Signature : - * @param xhr Required. The xhr that was used to make the request. Object - * @param success Required. True if caller regards the request as having succeeded. Boolean - * @param request Required. The JSDO request object created for making the request. Object. - * - */ - this._checkServiceResponse = function (xhr, success, request) { - var offlineReason = null, - wasOnline = this.connected; - updateContextPropsFromResponse(this, xhr); - - /* first of all, if there are no subscriptions to offline or online events, don't - * bother -- we don't want to run the risk of messing things up by calling ping - * if the app developer isn't interested (especially because that may mean that - * ping isn't enabled on the server, anyway) - */ - if (!this._events) { - return; - } - var offlineObservers = this._events.offline || []; - var onlineObservers = this._events.online || []; - if ((offlineObservers.length === 0) && (onlineObservers.length === 0)) { - return; - } - - /* even though this function gets called as a result of trying to - * contact the server, don't bother to change anything if we already - * know that the device (or user agent, or client machine) is offline. - * We can't assume anything about the state of the server if we can't - * even get to the internet from the client - */ - - // if the call to the server was a success, we will assume we are online, - // both server and device - if (success) { - setRestApplicationIsOnline(true); - setDeviceIsOnline(true); // presumably this is true (probably was already true) - } else { - /* Request failed, determine whether it's because server is offline - * Do this even if the Session was already in an offline state, because - * we need to determine whether the failure was due to still being - * offline, or whether it's now possible to communicate with the - * server but the problem was something else. - */ - - if (deviceIsOnline) { - /* ping the server to get better information on whether this is an offline case - * NB: synchronous ping for simplicity, maybe should consider async so as not - * to potentially freeze UI - */ - var localPingArgs = { - doNotFireEvent: true, // do in this fn so we have the request - offlineReason: null, - async: false - }; - if (!(that.ping(localPingArgs))) { - offlineReason = localPingArgs.offlineReason; - setRestApplicationIsOnline(false); - } else { - // ping returned true, so even though the original request failed, - // we are online and the failure must have been due to something else - setRestApplicationIsOnline(true); - } - } - // else deviceIsOnline was already false, so the offline event should already have - // been fired for that reason and there is no need to do anything else - } - - if (wasOnline && !this.connected) { - this.trigger("offline", this, offlineReason, request); - } else if (!wasOnline && this.connected) { - this.trigger("online", this, request); - } - }; - - /* Decide whether, on the basis of information returned by a server request, the - * Mobile Web Application managed by this Session object is online, where online - * means that the ping response was a 200 and, IF the body of the response contains - * JSON with an AppServerStatus property, that AppServerStatus Status property has - * a pingStatus property set to true - * i.e., the body has an AppServerStatus.PingStatus set to true - * (if the body doesn't contain JSON with an AppServerStatus, we use just the HTTP - * response status code to decide) - * - * Returns: true if the response meets the above conditions, false if it doesn't - * - * Parameters: - * args, with properties: - * xhr - the XMLHttpRequest used to make the request - * offlineReason - if the function determines that the app is offline, - * it sets offlineReason to the reason for that decision, - * for the use of the caller - * fireEventIfOfflineChange - if true, the function fires an offline or online - * event if there has been a change (i.e., the online state determined - * by the function is different from what it had been when the function - * began executing) - * usingOepingFormat - OPTIONAL. The function's default assumption is that the value - * of the session's internal oepingAvailable variable indicates whether the - * the response body will be in the format used by the OpenEdge oeping service. - * A caller can override this assumption by using this property to true or false. - * (the isAuthorized code sets this to false because it doesn't use oeping - * but does call this function) - */ - this._processPingResult = function (args) { - var xhr = args.xhr, - pingResponseJSON, - appServerStatus = null, - wasOnline = this.connected, - connectedBeforeCallback, - assumeOepingFormat; - - if (args.hasOwnProperty('usingOepingFormat')) { - assumeOepingFormat = args.usingOepingFormat; - } else { - assumeOepingFormat = oepingAvailable; - } - - /* first determine whether the Web server and the Mobile Web Application (MWA) - * are available - */ - if (xhr.status >= 200 && xhr.status < 300) { - updateContextPropsFromResponse(this, xhr); - if (assumeOepingFormat) { - try { - pingResponseJSON = JSON.parse(xhr.responseText); - appServerStatus = pingResponseJSON.AppServerStatus; - } catch (e) { - /* We got a successful response from calling our ping URI, but it - * didn't return valid JSON. If we think that the oeping REST API - * is available on the server (so we should have gotten valid - * json), log this to the console. - * - */ - console.error("Unable to parse ping response."); - } - } - toggleOnlineState(xhr); - } else { - if (deviceIsOnline) { - if (xhr.status === 0) { - args.offlineReason = progress.data.Session.SERVER_OFFLINE; - setRestApplicationIsOnline(false); - } else if ((xhr.status === 404) || (xhr.status === 410)) { - /* if we get a 404, it means the Web server is up, but it - * can't find the resource we requested (either _oeping or - * the login target), therefore the Mobile Web application - * must be unavailable (410 is Gone) - */ - args.offlineReason = progress.data.Session.WEB_APPLICATION_OFFLINE; - setRestApplicationIsOnline(false); - } else { - /* There's some error, but we can't say for sure that it's because - * the Web application is unavailable. May be an authentication problem, - * internal server error, or for some reason our ping request was - * invalid (unlikely to happen if it previously succeeded). - * In particular, if the server uses Form authentication, it - * may have come back online but now the session id - * is no longer valid. - */ - setRestApplicationIsOnline(true); - } - } else { - args.offlineReason = progress.data.Session.DEVICE_OFFLINE; - } - } - - // is the AppServer online? appServerStatus will be non-null only - // if the ping request returned 200, meaning the other things are OK - // (connection to server, Tomcat, Mobile Web application) - if (appServerStatus) { - if (appServerStatus.PingStatus === "false") { - args.offlineReason = progress.data.Session.APPSERVER_OFFLINE; - setRestApplicationIsOnline(false); - } else { - setRestApplicationIsOnline(true); - } - } - - /* We call any async ping callback handler and then, after that returns, fire an - offline or online event if necessary. - When deciding whether to fire an event, the responsibility of this _processPingResult() - function is to decide about the event on the basis of the data returned from the ping - that it is currently processing. Therefore, since the ping callback that is just about - to be called could change the outcome of the event decision (for example, if the handler - calls logout(), thus setting Session.connected to false)), we save the current value of - Session.connected and use that saved value to decide about the event after the ping - handler returns. - (If the application programmer wants to get an event fired as a result of something - that happens in the ping handler, they should call a ping() *after* that. - */ - connectedBeforeCallback = this.connected; - - if ((typeof xhr.onCompleteFn) === 'function') { - xhr.onCompleteFn({ - pingResult: this.connected, - xhr: xhr, - offlineReason: args.offlineReason - }); - } - - // decide whether to fire an event, and if so do it - if (args.fireEventIfOfflineChange) { - if (wasOnline && !connectedBeforeCallback) { - that.trigger("offline", that, args.offlineReason, null); - } else if (!wasOnline && connectedBeforeCallback) { - that.trigger("online", that, null); - } - } - - return this.connected; - }; - - - this._onReadyStateChangePing = function () { - var xhr = this; - var args; - - if (xhr.readyState === 4) { - args = { - xhr: xhr, - fireEventIfOfflineChange: true, - offlineReason: null - }; - that._processPingResult(args); - if (_pingInterval > 0) { - _timeoutID = setTimeout(that._autoping, _pingInterval); - } - } - }; - - this._pingtestOnReadyStateChange = function () { - var xhr = this; - - if (xhr.readyState === 4) { - var foundOeping = false; - if (xhr.status >= 200 && xhr.status < 300) { - foundOeping = true; - } else { - setPartialPingURI(that.loginTarget); - console.warn("Default ping target not available, will use loginTarget instead."); - } - setOepingAvailable(foundOeping); - - // If we're here, we've just logged in. If pingInterval has been set, we need - // to start autopinging - if (_pingInterval > 0) { - _timeoutID = setTimeout(that._autoping, _pingInterval); - } - } - }; - - /* - * args: pingURI - * async - * onCompleteFn used only if async is true - * - * (deliberately not catching thrown error) - */ - this._sendPing = function (args) { - var xhr = new XMLHttpRequest(), - that = this; - - function sendPingAfterOpen() { - if (args.async) { - xhr.onreadystatechange = args.onReadyStateFn; - xhr.onCompleteFn = args.onCompleteFn; - xhr._jsdosession = jsdosession; // in case the Session is part of a JSDOSession - xhr._deferred = args.deferred; // in case the Session is part of a JSDOSession - } - progress.data.Session._setNoCacheHeaders(xhr); - // set X-CLIENT-PROPS header - setRequestHeaderFromContextProps(that, xhr); - if (that.authenticationModel === progress.data.Session.AUTH_TYPE_FORM) { - _addWithCredentialsAndAccept( - xhr, - "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ); - } - xhr.send(null); - } - - try { - if (this._authProvider) { - this._authProvider._openRequestAndAuthorize( - xhr, - 'GET', - args.pingURI, - args.async, - sendPingAfterOpen - ); - } else { - // get rid of this if we do away with synchronous support (i.e., customer use of - // old Session API) - this._setXHRCredentials(xhr, "GET", args.pingURI, this.userName, _password, args.async); - - // Sending the XHR request after opening the channel - if (xhr.readyState === 1) { - sendPingAfterOpen(); - } - } - } catch (e) { - args.error = e; - } - - args.xhr = xhr; - }; - - this._makePingURI = function () { - var pingURI = this.serviceURI + partialPingURI; - // had caching problem with Firefox in its offline mode - if (progress.data.Session._useTimeStamp) { - pingURI = progress.data.Session._addTimeStampToURL(pingURI); - } - return pingURI; - }; - - - /* - * autoping -- callback - */ - this._autoping = function () { - that.ping({async: true}); - }; - - - // TODO for API revamp: get rid of this method and replace it with implementations - // of AUthenticationImplementation.openRequest that are specific to the - // auth models (assuming we can use some sort of subclassing or interface design) - // (and when we remove this, remove the calls to it in this file) - /* _setXHRCredentials (intended for progress.data library use only) - * set credentials as needed, both via the xhr's open method and setting the - * Authorization header directly - */ - this._setXHRCredentials = function (xhr, verb, uri, userName, password, async) { - - // note that we do not set credentials if userName is null. - // Null userName indicates that the developer is depending on the browser to - // get and manage the credentials, and we need to make sure we don't interfere with that - if ( - userName - && this.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC - ) { - - // See the comment at the definition of the canPassCredentialsToOpen() function - // for why we pass credentials to open() in some cases but not others. (If we're not using - // Basic auth, we never pass credentials) - if (canPassCredentialsToOpen()) { - xhr.open(verb, uri, async, userName, password); - } else { - xhr.open(verb, uri, async); - } - - // set Authorization header - var auth = _make_basic_auth(userName, password); - xhr.setRequestHeader('Authorization', auth); - } else { - xhr.open(verb, uri, async); - } - }; - - /* _addCCIDtoURL (intended for progress.data library use only) - * Add the Client Context ID being used by a session on an OE REST application, if we have - * previously stored one from a response from the server - */ - this._addCCIDtoURL = function (url) { - var urlPart1, - urlPart2, - jsessionidStr, - index; - - if (this.clientContextId && (this.clientContextId !== "0")) { - // Should we test protocol, - // host and port in addition to path to ensure that jsessionid is only sent - // when request applies to the REST app (it might not be if the catalog is somewhere else) - if (url.substring(0, this.serviceURI.length) === this.serviceURI) { - jsessionidStr = ";" + "JSESSIONID=" + this.clientContextId; - index = url.indexOf('?'); - if (index === -1) { - url += jsessionidStr; // just append the jsessionid path parameter to the path - } else { - // insert jsessionid path parameter before the first query parameter - urlPart1 = url.substring(0, index); - urlPart2 = url.substring(index); - url = urlPart1 + jsessionidStr + urlPart2; - } - } - } - return url; - }; - - /* _saveClientContextId (intended for progress.data library use only) - * If the CCID hasn't been set for the session yet, check the xhr for it and store it. - * (If it has been set, assume that the existing one is correct and do nothing. We could - * enhance this function by checking to see whether the new one matches the existing one. - * Not sure what to do if that's the case -- overwrite the old one? ignore the new one? - * Should at least log a warning or error - */ - this._saveClientContextId = function (xhr) { - // do this unconditionally (even if there is already a client-context-id), because - // if basic authentication is set up such that it uses sessions, and cookies are disabled, - // the server will generate a different session on each request and the X-CLIENT-CONTEXT-ID - // will therefore be different - setClientContextIDfromXHR(xhr, this); - }; - - this._parseCatalog = function (xhr) { - var jsonObject; - var catalogdata; - - try { - jsonObject = JSON.parse(xhr.responseText); - catalogdata = jsonObject.services; - } catch (e) { - console.error("Unable to parse response. Make sure catalog has correct format."); - catalogdata = null; - } - - return catalogdata; - }; - - /* _prependAppURL - * Prepends the URL of the Web application - * (the 1st parameter passed to login, stored in this.serviceURI) - * to whatever string is passed in. If the string passed in is an absolute URL, this function does - * nothing except return a copy. This function ensures that the resulting URL has the correct number - * of slashes between the web app url and the string passed in (currently that means that if what's - * passed in has no initial slash, the function adds one) - */ - this._prependAppURL = function (oldURL) { - if (!oldURL) { - /* If oldURL is null, just return the app URL. (It's not the responsibility of this - * function to decide whether having a null URL is an error. Its only responsibility - * is to prepend the App URL to whatever it gets passed - * (and make sure the result is a valid URL) - */ - return this.serviceURI; - } - var newURL = oldURL; - var pat = /^https?:\/\//i; - if (!pat.test(newURL)) { - if (newURL.indexOf("/") !== 0) { - newURL = "/" + newURL; - } - - newURL = this.serviceURI + newURL; - } - return newURL; - }; - - - // Functions - - // get rid of this if we get rid of synchronous (old Session object API) support? - // Set an XMLHttpRequest object's withCredentials attribute and Accept header, - // using a try-catch so that if setting withCredentials throws an error it doesn't - // interrupt execution (this is a workaround for the fact that Firefox doesn't - // allow you to set withCredentials when you're doing a synchronous operation) - // The setting of the Accept header is included here, and happens after the - // attempt to set withCredentials, to make the behavior in 11.3.0 match - // the behavior in 11.2.1 -- for Firefox, in a CORS situation, login() will - // fail. (If we allowed the Accept header to be set, login() would succeed - // because of that but addCatalog() would fail because no JSESSIONID would - // be sent due to withCredentials not being true) - function _addWithCredentialsAndAccept(xhr, acceptString) { - try { - xhr.withCredentials = true; - xhr.setRequestHeader("Accept", acceptString); - } catch (e) { - // Empty - } - } - - // get rid of this if we get rid of synchronous (old Session API) support? - // (because it's in AuthenticationProviderBasic) - // from http://coderseye.com/2007/how-to-do-http-basic-auth-in-ajax.html - function _make_basic_auth(user, pw) { - var tok = user + ':' + pw; - var hash = btoa(tok); - return "Basic " + hash; - } - - /* The next 2 functions, _gotLoginForm() and _gotLoginFailure(), attempt to determine whether - * a server response consists of - * the application's login page or login failure page. Currently (release 11.2), this - * is the only way we have of determining that a request made to the server that's - * configured for form-based authentication failed due to authentication (i.e., - * authentication hadn't happened before the request and either invalid credentials or - * no credentials were sent to the server). That's because, due to the fact that the browser - * or native wrapper typically intercepts the redirect involved in an unauthenticated request - * to a server that's using using form auth, all we see in the XHR is a success status code - * plus whatever page we were redirected to. - * In the future, we expect to enhance the OE REST adapter so that it will return a status code - * indicating failure for form-based authentication, and we can reimplement these functions so - * they check for that code rather than do the simplistic string search. - */ - - // Determines whether the content of the xhr is the login page. Assumes - // use of a convention for testing for login page - var loginFormIDString = "j_spring_security_check"; - - function _gotLoginForm(xhr) { - // is the response contained in an xhr actually the login page? - return _findStringInResponseHTML(xhr, loginFormIDString); - } - - // Determines whether the content of the xhr is the login failure page. Assumes - // use of a convention for testing for login fail page - var loginFailureIdentificationString = "login failed"; - - function _gotLoginFailure(xhr) { - return _findStringInResponseHTML(xhr, loginFailureIdentificationString); - } - - // Does a given xhr contain html and does that html contain a given string? - function _findStringInResponseHTML(xhr, searchString) { - if (!xhr.responseText) { - return false; - } - var contentType = xhr.getResponseHeader("Content-Type"); - - if (contentType && - (contentType.indexOf("text/html") >= 0) && - (xhr.responseText.indexOf(searchString) >= 0) - ) { - return true; - } - - return false; - } - - // get rid of this if we get rid of synchronous (old Session API) support? - /* sets the statusFromjson property in the params object to indicate - * the status of a response from an OE Mobile Web application that has - * to do with authentication (the response to a login request, or a - * response to a request for a resource where there was an error having - * to do with authentication */ - function handleJSONLoginResponse(params) { - // Parse the json in the response to see whether it's the special OE REST service - // response. If it is, check the result (which should be consistent with the status from - // the xhr) - var jsonObject; - params.statusFromjson = null; - try { - jsonObject = JSON.parse(params.xhr.responseText); - - if ( - jsonObject.status_code !== undefined - && jsonObject.status_txt !== undefined - ) { - params.statusFromjson = jsonObject.status_code; - } - } catch (e) { - // invalid json - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, params.session); - setLoginHttpStatus(params.xhr.status, params.session); - throw new Error("Unable to parse login response from server."); - } - - } - - function setRequestHeaderFromContextProps(session, xhr) { - if (session.xClientProps) { - xhr.setRequestHeader("X-CLIENT-PROPS", session.xClientProps); - } else if (session._contextProperties.contextHeader !== undefined) { - xhr.setRequestHeader("X-CLIENT-PROPS", session._contextProperties.contextHeader); - } - } - - function toggleOnlineState(xhr) { - var pdsession = that; - - setLoginHttpStatus(xhr.status, pdsession); - - if (pdsession.loginHttpStatus >= 200 && pdsession.loginHttpStatus < 400) { - setLoginResult(progress.data.Session.LOGIN_SUCCESS, pdsession); - setRestApplicationIsOnline(true); - pdsession._saveClientContextId(xhr); - storeAllSessionInfo(); // save info to persistent storage - } else { - // Taking a page from _processPingResult where we set the rest application as offline if it's one of - // these error codes - if ( - pdsession.loginHttpStatus === 0 - || pdsession.loginHttpStatus === 400 - || pdsession.loginHttpStatus === 410 - ) { - setRestApplicationIsOnline(false); - setLoginResult( - progress.data.AuthenticationProvider._getAuthFailureReason(xhr), - pdsession - ); - } else { - // Otherwise if it's probably an internal error or auth problem. - // Either way, we know it's still online. - setRestApplicationIsOnline(true); - setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE, pdsession); - } - } - - setLastSessionXHR(xhr, pdsession); - updateContextPropsFromResponse(pdsession, xhr); - - return pdsession.loginResult; - } - - function updateContextPropsFromResponse(session, xhr) { - /* determine whether the response contains an X-CLIENT_PROPS header and, if so, - set the Session's context - */ - var contextString, - context; - - if (xhr) { - contextString = getResponseHeaderNoError(xhr, "X-CLIENT-PROPS"); - if (contextString) { - try { - context = JSON.parse(contextString); - } catch (e) { - // Empty - } - if (typeof context === "object") { - session._contextProperties.setContext(context); - } else { - //{1}: A server response included an invalid {2} header. - throw new Error(progress.data._getMsgText("jsdoMSG123", 'Session', 'X-CLIENT-PROPS')); - } - } else if (contextString === "") { - // If header is "", clear the X-CLIENT-PROPS context, - session._contextProperties.setContext({}); - } - // if header is absent (getResponseHeader will return null), don't change _contextProperties - } - } - - // Remove all resources, services, and sessions related to this Session from the ServicesManager - function cleanServicesManager() { - progress.data.ServicesManager.cleanSession(that); - } - - // process constructor options and do other initialization - - // If a storage key (name property of a JSDOSession) was passed to the constructor, - // use it to try to retrieve state data from a previous JSDOSession instance that - // had the same name. This code was introduced to handle page refreshes, but could - // be used for other purposes. - if (typeof options === 'object') { - - jsdosession = options.jsdosession; - newURI = options.serviceURI; - setAuthProvider(options.authProvider); // do this BEFORE calling setSessionInfoFromStorage - - if (options.authProvider && options.authProvider.hasClientCredentials()) { - _loginResult = progress.data.Session.LOGIN_SUCCESS; - } - - // get rid of trailing '/' because appending service url that starts with '/' - // will cause request failures - if (newURI && newURI[newURI.length - 1] === "/") { - newURI = newURI.substring(0, newURI.length - 1); - } - - _storageKey = options._storageKey; - if (_storageKey) { - if (retrieveSessionInfo(_storageKey)) { - storedAuthModel = retrieveSessionInfo("authenticationModel"); - storedURI = retrieveSessionInfo("serviceURI"); - - if ( - (storedAuthModel !== options.authenticationModel) || - (storedURI !== newURI) - ) { - clearAllSessionInfo(); - } else { - // Note: be sure we have set authProvider (if any) from options before - // calling setSessionInfoFromStorage (important so that the logic in - // setSessionInfoFromStorage that re-creates an AuthenticationProvider - // after page refresh only gets used if the app is using the old JSDOSession.login) - setSessionInfoFromStorage(_storageKey); - stateWasReadFromStorage = true; - } - } - // _storageKey is in essence the flag for page refresh; we are not supporting page refresh for Basic - // auth, so clear it even if it was passed in. - // (But had to set and keep _storageKey until this point so that the above validation of - // serviceURI and auth model will be done even in the case where there's a mismatch and - // the new auth model is Basic. This statement will go away when we support page refresh with - // Basic) - if (options.authenticationModel === progress.data.Session.AUTH_TYPE_BASIC) { - _storageKey = undefined; - } - } - - // If we didn't read state info from storage, we need to set the serviceURI and probably - // the authenticationModel - if (!stateWasReadFromStorage) { - if (newURI) { - setServiceURI(newURI, this); - } - if (options.authenticationModel) { - this.authenticationModel = options.authenticationModel; - } - } - } - - }; // End of Session - progress.data.Session._useTimeStamp = true; - - var SEQ_MAX_VALUE = 999999999999999; - // 15 - 9 - var _tsseq = SEQ_MAX_VALUE; - // Initialized to SEQ_MAX_VALUE to initialize values. - var _tsprefix1 = 0; - var _tsprefix2 = 0; - - // this._getNextTimeStamp = function () { - progress.data.Session._getNextTimeStamp = function () { - var seq; - - _tsseq += 1; - seq = _tsseq; - - if (seq >= SEQ_MAX_VALUE) { - _tsseq = 1; - seq = 1; - var t = Math.floor((Date.now ? Date.now() : (new Date().getTime())) / 10000); - if (_tsprefix1 === t) { - _tsprefix2 += 1; - if (_tsprefix2 >= SEQ_MAX_VALUE) { - _tsprefix2 = 1; - } - } else { - _tsprefix1 = t; - Math.random(); // Ignore call to random - _tsprefix2 = Math.round(Math.random() * 10000000000); - } - } - - return _tsprefix1 + "-" + _tsprefix2 + "-" + seq; - }; - - /* - * _addTimeStampToURL (intended for progress.data library use only) - * Add a time stamp to the a URL to prevent caching of the request. - * Set progress.data.Session._useTimeStamp = false to turn off. - */ - progress.data.Session._addTimeStampToURL = function (url) { - var timeStamp = "_ts=" + progress.data.Session._getNextTimeStamp(); - url += ((url.indexOf('?') === -1) ? "?" : "&") + timeStamp; - return url; - }; - - // Do whatever it takes to direct the XMLHttpRequest not to fulfill the request - // from a cache - // (convenience method --- we do this several different places in the code) - progress.data.Session._setNoCacheHeaders = function (xhr) { - xhr.setRequestHeader("Cache-Control", "no-cache"); - xhr.setRequestHeader("Pragma", "no-cache"); - }; - - - - // Constants for progress.data.Session - if ((typeof Object.defineProperty) === 'function') { - Object.defineProperty( - progress.data.Session, - 'LOGIN_AUTHENTICATION_REQUIRED', - { - value: 0, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'LOGIN_SUCCESS', - { - value: 1, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'LOGIN_AUTHENTICATION_FAILURE', - { - value: 2, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'LOGIN_GENERAL_FAILURE', - { - value: 3, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'CATALOG_ALREADY_LOADED', - { - value: 4, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'ASYNC_PENDING', - { - value: 5, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'EXPIRED_TOKEN', - { - value: 6, - enumerable: true - } - ); - - Object.defineProperty( - progress.data.Session, - 'SUCCESS', - { - value: 1, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'AUTHENTICATION_FAILURE', - { - value: 2, - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'GENERAL_FAILURE', - { - value: 3, - enumerable: true - } - ); - - Object.defineProperty( - progress.data.Session, - 'AUTH_TYPE_ANON', - { - value: "anonymous", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'AUTH_TYPE_BASIC', - { - value: "basic", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'AUTH_TYPE_FORM', - { - value: "form", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'AUTH_TYPE_SSO', - { - value: "sso", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'AUTH_TYPE_FORM_SSO', - { - value: "form_sso", - enumerable: true - } - ); - - Object.defineProperty( - progress.data.Session, - 'DEVICE_OFFLINE', - { - value: "Device is offline", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'SERVER_OFFLINE', - { - value: "Cannot contact server", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'WEB_APPLICATION_OFFLINE', - { - value: "Mobile Web Application is not available", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'SERVICE_OFFLINE', - { - value: "REST web Service is not available", - enumerable: true - } - ); - Object.defineProperty( - progress.data.Session, - 'APPSERVER_OFFLINE', - { - value: "AppServer is not available", - enumerable: true - } - ); - } else { - progress.data.Session.LOGIN_SUCCESS = 1; - progress.data.Session.LOGIN_AUTHENTICATION_FAILURE = 2; - progress.data.Session.LOGIN_GENERAL_FAILURE = 3; - progress.data.Session.CATALOG_ALREADY_LOADED = 4; - - progress.data.Session.SUCCESS = 1; - progress.data.Session.AUTHENTICATION_FAILURE = 2; - progress.data.Session.GENERAL_FAILURE = 3; - - progress.data.Session.AUTH_TYPE_ANON = "anonymous"; - progress.data.Session.AUTH_TYPE_BASIC = "basic"; - progress.data.Session.AUTH_TYPE_FORM = "form"; - progress.data.Session.AUTH_TYPE_SSO = "sso"; - - /* deliberately not including the "offline reasons" that are defined in the - * 1st part of the conditional. We believe that we can be used only in environments where - * ECMAScript 5 is supported, so let's put that assumption to the test - */ - } - - //setup inheritance for Session -- specifically for incorporating an Observable object - progress.data.Session.prototype = new progress.util.Observable(); - progress.data.Session.prototype.constructor = progress.data.Session; - function validateSessionSubscribe(args, evt, listenerData) { - listenerData.operation = undefined; - var found = false; - - // make sure this event is one that we support - this._eventNames.forEach(function (eventName) { - if (evt === eventName.toLowerCase()) { - found = true; - } - }); - - if (!found) { - throw new Error(progress.data._getMsgText("jsdoMSG042", evt)); - } - - if (args.length < 2) { - throw new Error(progress.data._getMsgText("jsdoMSG038", 2)); - } - - if (typeof args[0] !== 'string') { - throw new Error(progress.data._getMsgText("jsdoMSG039")); - } - - if (typeof args[1] !== 'function') { - throw new Error(progress.data._getMsgText("jsdoMSG040")); - } - - listenerData.fn = args[1]; - - if (args.length > 2) { - if (typeof args[2] !== 'object') { - throw new Error(progress.data._getMsgText("jsdoMSG041", evt)); - } else { - listenerData.scope = args[2]; - } - } - } - // events supported by Session - progress.data.Session.prototype._eventNames = - ["offline", "online", "afterLogin", "afterAddCatalog", "afterLogout", "afterDisconnect"]; - // callback to validate subscribe and unsubscribe - progress.data.Session.prototype.validateSubscribe = validateSessionSubscribe; - progress.data.Session.prototype.toString = function (radix) { - return "progress.data.Session"; - }; - - - /* - progress.data.JSDOSession - Like progress.data.Session, but the methods are async-only and return promises. - (first implementation uses progress.data.Session to do the work, but conceivably - that implementation could be changed to something different) - The JSDOSession object keeps the same underlying pdsession object for the lifetime - of the JSDOSession object -- i.e., even after logout and subsequent login, the pdsession - is re-used rather than re-created. - */ - progress.data.JSDOSession = function JSDOSession(options) { - var _pdsession, - _serviceURI, - that = this, - _name; - - // PROPERTIES - // Approach: Use the properties of the underlying progress.data.Session object whenever - // possible. - Object.defineProperty( - this, - 'authenticationModel', - { - get: function () { - return _pdsession ? _pdsession.authenticationModel : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'authProvider', - { - get: function () { - return _pdsession ? _pdsession._authProvider : null; - }, - enumerable: true - } - ); - Object.defineProperty( - this, - 'catalogURIs', - { - get: function () { - return _pdsession ? _pdsession.catalogURIs : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'clientContextId', - { - get: function () { - return _pdsession ? _pdsession.clientContextId : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'connected', - { - get: function () { - return _pdsession ? _pdsession.connected : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'JSDOs', - { - get: function () { - return _pdsession ? _pdsession.JSDOs : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'loginResult', - { - get: function () { - return _pdsession ? _pdsession.loginResult : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'loginHttpStatus', - { - get: function () { - return _pdsession ? _pdsession.loginHttpStatus : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'onOpenRequest', - { - get: function () { - return _pdsession ? _pdsession.onOpenRequest : undefined; - }, - set: function (newval) { - if (_pdsession) { - _pdsession.onOpenRequest = newval; - } - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'pingInterval', - { - get: function () { - return _pdsession ? _pdsession.pingInterval : undefined; - }, - set: function (newval) { - if (_pdsession) { - _pdsession.pingInterval = newval; - } - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'services', - { - get: function () { - return _pdsession ? _pdsession.services : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'serviceURI', - { - get: function () { - if (_pdsession && _pdsession.serviceURI) { - return _pdsession.serviceURI; - } else { - return _serviceURI; - } - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'userName', - { - get: function () { - return _pdsession ? _pdsession.userName : undefined; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - 'name', - { - get: function () { - return _name; - }, - enumerable: true - } - ); - - Object.defineProperty( - this, - "_isInvalidated", - { - get: function () { - return _pdsession._isInvalidated; - }, - enumerable: false - } - ); - - // PRIVATE FUNCTIONS - - - // Wrapper to make it easier to change the promise implementation we use. - // Note that in the JSDO library's first implementation of promise support, - // the "promise" parameter for this function is actually a jQuery Deferred object - function settlePromise(promise, fulfill, result, info) { - if (fulfill) { - promise.resolve(that, result, info); - } else { - promise.reject(that, result, info); - } - } - - // use this for the events fired by progress.data.Session that can be handled with common code - function genericSessionEventHandler(pdsession, result, errorObject, xhr, deferred) { - var myDeferred; - - if (xhr) { - myDeferred = xhr._deferred; - } else { - myDeferred = deferred; - } - - settlePromise( - myDeferred, - result === progress.data.Session.SUCCESS ? true : false, - result, - { - errorObject: errorObject, - xhr: xhr - } - ); - } - - function onAfterAddCatalog(pdsession, result, errorObject, xhr) { - var deferred, - fulfill = false, - settleResult, - info; - - if (result === progress.data.Session.EXPIRED_TOKEN) { - settleResult = progress.data.Session.EXPIRED_TOKEN; - } else if (result === progress.data.Session.LOGIN_AUTHENTICATION_FAILURE) { - settleResult = progress.data.Session.LOGIN_AUTHENTICATION_FAILURE; - } else { - settleResult = progress.data.Session.GENERAL_FAILURE; - } - - if (xhr && xhr._deferred) { - deferred = xhr._deferred; - - /* add the result for this addCatalog to the result array. */ - if ( - result !== progress.data.Session.SUCCESS && - result !== progress.data.Session.CATALOG_ALREADY_LOADED - ) { - - result = result || progress.data.Session.GENERAL_FAILURE; - - /* Set a property on the deferred to indicates that the "overall" result was - a failure. When we decide whether to reject or resolve the promise, we reject - if it's set to GENERAL_FAILURE, otherwise we resolve the promise - (really only need to set this once, but simpler code if we just set (or possibly - re-set) it whenever we find an error, plus if, at some point while we're still - processing, it's important to know whether we've already had an error, we can - check the property) - */ - deferred._overallCatalogResult = progress.data.Session.GENERAL_FAILURE; - } - - deferred._results[xhr._catalogIndex] = { - catalogURI: xhr._catalogURI, - result: result, - errorObject: errorObject, - xhr: xhr - }; - deferred._numCatalogsProcessed += 1; - if (deferred._numCatalogsProcessed === deferred._numCatalogs) { - deferred._processedPromise = true; - - if (!deferred._overallCatalogResult) { - fulfill = true; - settleResult = progress.data.Session.SUCCESS; - } - if (settleResult === progress.data.Session.SUCCESS) { - if (xhr._deferred._results.length === 1) { - info = xhr._deferred._results[0]; - } else { - info = { - xhr: xhr, - result: settleResult, - details: xhr._deferred._results - }; - } - } else { - if (xhr._deferred._results.length === 1) { - info = xhr._deferred._results[0]; - } else { - info = { - xhr: xhr, - result: settleResult, - errorObject: new Error(progress.data._getMsgText("jsdoMSG512")), - details: xhr._deferred._results - }; - } - } - settlePromise( - xhr._deferred, - fulfill, - settleResult, - info - ); - } - } - } - - function onAfterLogout(pdsession, errorObject, xhr) { - var result = progress.data.Session.GENERAL_FAILURE, - fulfill = false; - if (xhr && xhr._deferred) { - /* Note: loginResult gets cleared on successful logout, so testing it for false - to confirm that logout succeeded - */ - if (!errorObject && !pdsession.loginResult) { - result = progress.data.Session.SUCCESS; - fulfill = true; - } - settlePromise( - xhr._deferred, - fulfill, - result, - { - errorObject: errorObject, - xhr: xhr - } - ); - } - } - - function onPingComplete(args) { - var xhr = args.xhr; - if (xhr && xhr._deferred) { - settlePromise( - xhr._deferred, - args.pingResult, // this tells settlePromise whether to resolve or reject - args.pingResult, // this is the result value passed to the promise handler - { - offlineReason: args.offlineReason, - xhr: xhr - } - ); - } - } - - // METHODS - - // login() - // Creates an AuthenticationProvider and calls its login() method. Any errors thrown by the - // Auth Provider's constructor or login will bubble up to the caller, otherwise this method - // returns the promise from the A-P's login call. - this.login = function (username, password, options) { - var deferred = new progress.util.Deferred(), - iOSBasicAuthTimeout; - - function callIsAuthorized() { - that.isAuthorized() - .then(function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.resolve(that, object.result, object.info); - }, function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.reject(that, object.result, object.info); - }); - } - - try { - // console.warn( - // "JSDOSession: As of JSDO 4.4, login() has been deprecated. Please use " - // + "the AuthenticationProvider API instead." - // ); - - if (this._isInvalidated) { - // JSDOSession: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); - } - - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // JSDOSession: Cannot call login() when authenticationModel is SSO. - // Please use the AuthenticationProvider object instead. - throw new Error(progress.data._getMsgText("jsdoMSG057", 'JSDOSession', 'login()')); - } - - if (typeof options === 'object') { - iOSBasicAuthTimeout = options.iOSBasicAuthTimeout; - } - - // As part of JSDOSession's login we create a new authProvider always. However, when a valid - // authProvider is provided as part of JSDOSession's constructor. i.e., when we already have - // a valid authProvider, performing login operation is not allowed. We throw an error. - if (!_pdsession._authProvider) { - // is there a better way to do this? Need it because we didn't have the authprovider when - // running the constructor - _pdsession._authProvider = new progress.data.AuthenticationProvider({ - uri: this.serviceURI, - authenticationModel: this.authenticationModel - }); - - _pdsession._authProvider.logout() - .then(function () { - return _pdsession._authProvider.login(username, password); - }) - .then(function () { - callIsAuthorized(); - }, function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.reject(that, object.result, object.info); - }); - } else { - throw new Error(progress.data._getMsgText("jsdoMSG062", 'JSDOSession', 'login()')); - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - // This method terminates the JSDOSession's ability to send requests to its serviceURI. - // Remove the reference to the AuthenticationProvider that was passed to connect(). - // Will be a no-op if connect() has not yet been called successfully. - // This method reinitializes the Session object back to the state it was in just after being created. - // Retains the serviceURI, authenticationModel, and name values. - // Delete any of the object's data that had been persisted (for example, to sessionStorage to support - // page refresh). - // Data for any catalogs loaded by the JSDOSession will NOT be deleted. - // See additional commecnts at the Session._disconnect method. - this.disconnect = function () { - var deferred = new progress.util.Deferred(), - errorObject; - - try { - _pdsession.subscribe('afterDisconnect', genericSessionEventHandler, this); - - _pdsession._disconnect(deferred); - } catch (e) { - // JSDOSession: Unexpected error calling disconnect: {e.message} - errorObject = new Error( - progress.data._getMsgText("jsdoMSG049", "JSDOSession", "disconnect", e.message) - ); - } - - if (errorObject) { - if (progress.util.Deferred.useJQueryPromises) { - throw errorObject; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: errorObject - }); - } - } else { - return deferred.promise(); - } - }; - - this.addCatalog = function (catalogURI, unameOrOpts, password, opts) { - var deferred = new progress.util.Deferred(), - catalogURIs, - numCatalogs, - catalogIndex, - addResult, - errorObject, - iOSBasicAuthTimeout, - username, - options, - authProvider; - - try { - if (this._isInvalidated) { - // JSDOSession: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); - } - - // check whether 1st param is a string or an array - if (typeof catalogURI === "string") { - catalogURIs = [catalogURI]; - } else if (catalogURI instanceof Array) { - catalogURIs = catalogURI; - } else { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "JSDOSession", - "addCatalog", - "The first argument must be a string or an array of strings specifying the URI of the catalog." - )); - } - - // type check the 2nd param if it exists - if (unameOrOpts) { - if (typeof unameOrOpts === "string") { - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // Session: Cannot pass username and password to addCatalog when - // authenticationModel is SSO. Pass an AuthenticationProvider instead. - throw new Error(progress.data._getMsgText("jsdoMSG058", 'Session')); - } - username = unameOrOpts; - // explictly ignore any authProvider if using the (catURI, uname, pw, options) signature - if (opts) { - options = opts; - options.authProvider = undefined; - } - } else if (typeof unameOrOpts === "object") { - options = unameOrOpts; - } else { - // JSDOSession: Argument 2 must be of type object in addCatalog call. - throw new Error(progress.data._getMsgText( - "jsdoMSG121", - "JSDOSession", - "2", - "object", - "addCatalog" - )); - } - } - - if (typeof options === 'object') { - // possible override for the workaround for the Cordova iOS async Basic auth bug - iOSBasicAuthTimeout = options.iOSBasicAuthTimeout; - if (options.authProvider) { - authProvider = options.authProvider; - } else if (this.authProvider) { - authProvider = this.authProvider; - } - } - - // Error out if no authProvider or username was given - if (!authProvider && !this.authProvider && !username) { - throw new Error(progress.data._getMsgText("jsdoMSG511")); - } - - /* When we're done processing all catalogs, we pass an array of results to resolve() or - reject(). We're attaching this array to the deferred object, in case the app makes - multiple addCatalog calls (if the array was attached to the JSDOSession, - the 2nd call might overwrite the first) - */ - - /* Add properties to the deferred object for this call to store the total - number of catalogs that are to be done, the number that ahve been processed, - and a reference to an array of results. - Loop through the array of catalogURIs, calling addCatalog for each one. If a call - throws an error or returns something other than ASYNC_PENDING, create a result object - for that catalog and add the result object to the resultArray. Otherwise, the result - object will be added by the afterAddCatalog handler. - If all of the Session.addCatalog calls throw an error or return something other - than ASYNC_PENDING, this function will reject the promise and return. Otherwise - the afterAddCatalog handler will resolve or reject the promise after all calls have - been processed. - Note that we try to make sure that each entry in the results array is in the same position - as its catalogURI in the input array. - */ - // if a catalogURI has no protocol, pdsession will assume it's relative to the serviceURI, - // if there has been a login - // NOTE: this means if the app is trying to load a local catalog, it MUST - // specify the file: protocol (and we need to make sure that works on all platforms) - - _pdsession.subscribe('afterAddCatalog', onAfterAddCatalog, this); - - numCatalogs = catalogURIs.length; - deferred._numCatalogs = numCatalogs; - deferred._numCatalogsProcessed = 0; - deferred._results = []; - deferred._results.length = numCatalogs; - - for (catalogIndex = 0; catalogIndex < numCatalogs; catalogIndex += 1) { - errorObject = undefined; - addResult = undefined; - try { - addResult = _pdsession.addCatalog( - { - catalogURI: catalogURIs[catalogIndex], - async: true, - userName: username, - password: password, - deferred: deferred, - catalogIndex: catalogIndex, - iOSBasicAuthTimeout: iOSBasicAuthTimeout, - authProvider: authProvider, - offlineAddCatalog: true - } - ); // OK to get catalog if offline - } catch (e) { - errorObject = new Error("JSDOSession: Unable to send addCatalog request. " + e.message); - } - - if (addResult !== progress.data.Session.ASYNC_PENDING) { - /* Set a property on the deferred to indicate that the "overall" result was - a failure. When we decide whether to reject or resolve the promise, we reject - if it's set to GENERAL_FAILURE, otherwise we resolve the promise - (really only need to set this once, but simpler code if we just set (or possibly - re-set) it whenever we find an error, plus if, at some point while we're still - processing, it's important to know whether we've already had an error, we can - check the property) - */ - deferred._overallCatalogResult = progress.data.Session.GENERAL_FAILURE; - if (errorObject) { - addResult = progress.data.Session.GENERAL_FAILURE; - } - deferred._results[catalogIndex] = { - catalogURI: catalogURIs[catalogIndex], - result: addResult, - errorObject: errorObject, - xhr: undefined - }; - deferred._numCatalogsProcessed += 1; - } - } - - if ((deferred._numCatalogsProcessed === numCatalogs) && !deferred._processedPromise) { - /* The goal here is to handle the case where all the catalogs - have been processed but the afterAddCatalog handler may not be invoked at the - end (the obvious example is if there are no async requests actually made by - Session.addCatalog). In that case, we have to resolve/reject from here. Chances are - very good that if we're doing this here, there's been at least one error, but just - to be sure, we check the deferred._overallCatalogResult anyway - */ - if (deferred._overallCatalogResult === progress.data.Session.GENERAL_FAILURE) { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, deferred._results); - } else { - deferred.resolve(this, progress.data.Session.SUCCESS, deferred._results); - } - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - // Note that this will work for either of these cases: - // - app originally called JSDOSession.login (so we implicitly created the AuthenticationProvider) - // - app created an AuthenticationProvider and passed it to connect, but now for some reason has - // called logout (this is actually a nice shortcut for someone who has used getSession) - // (NB: we should not allow this for SSO, tho) - // - // Note that we also don't support login/logout on the JSDOSession for page refresh - this.logout = function () { - var deferred = new progress.util.Deferred(), - authProv = this.authProvider; - - try { - // console.warn( - // "JSDOSession: As of 4.4, logout() has been deprecated. Please use " - // + "the AuthenticationProvider API instead." - // ); - - if (this.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // JSDOSession: Cannot call logout() when authenticationModel is SSO. - // Please use the AuthenticationProvider object instead. - throw new Error(progress.data._getMsgText( - "jsdoMSG057", - 'JSDOSession', - 'logout()' - )); - } - - this.disconnect() - .then(function () { - if (authProv) { - return authProv.logout(); - } - // if there's no AP, just resolve immediately successfully - deferred.resolve(that, progress.data.Session.SUCCESS, {}); - }) - .then(function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.resolve(that, object.result, object.info); - }, function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.reject(that, object.result, object.info); - }); - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(that, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - - return deferred.promise(); - }; - - - this.invalidate = function () { - _pdsession.invalidate(); - return this.logout(); - }; - - this.ping = function () { - var deferred = new progress.util.Deferred(); - - try { - if (this._isInvalidated) { - // JSDOSession: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); - } - - try { - _pdsession.ping({ - async: true, - deferred: deferred, - onCompleteFn: onPingComplete - }); - } catch (e) { - throw new Error("JSDOSession: Unable to send ping request. " + e.message); - } - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - - return deferred.promise(); - }; - - // Determine whether the JSDOSession can currently access its web application. - // The use expected for this method is to determine whether a JSDOSession that has - // previously authenticated to its web application still has authorization. - // For example, if the JSDOSession is using Form authentication, is the server - // session still valid or did it expire? - this.isAuthorized = function () { - var deferred = new progress.util.Deferred(), - xhr = new XMLHttpRequest(), - result, - that = this; - - try { - if (this._isInvalidated) { - // JSDOSession: This session has been invalidated and cannot be used. - throw new Error(progress.data._getMsgText("jsdoMSG510", "JSDOSession")); - } - - // If we logged in successfuly using login() or if we have an AuthProvider, make the call - if (this.loginResult === progress.data.Session.LOGIN_SUCCESS || this.authProvider) { - _pdsession._openRequest( - xhr, - "GET", - _pdsession.loginTarget, - true, - function () { - xhr.onreadystatechange = function () { - // do we need this xhr var? The one declared in isAuthorized seems to be in scope - var xhr = this, - cbresult, - info; - - if (xhr.readyState === 4) { - info = { - xhr: xhr, - offlineReason: undefined, - fireEventIfOfflineChange: true, - usingOepingFormat: false - }; - - // call _processPingResult because it has logic for - // detecting change in online/offline state - _pdsession._processPingResult(info); - - if (xhr.status >= 200 && xhr.status < 300) { - deferred.resolve( - that, - progress.data.Session.SUCCESS, - info - ); - } else { - if (xhr.status === 401) { - cbresult = progress.data.AuthenticationProvider._getAuthFailureReason(xhr); - } else { - cbresult = progress.data.Session.GENERAL_FAILURE; - } - deferred.reject(that, cbresult, info); - } - } - }; - - try { - xhr.send(); - } catch (e) { - throw new Error("JSDOSession: Unable to validate authorization. " + e.message); - } - } - ); - } else { - // Never logged in (or logged in and logged out). Regardless of what the reason - // was that there wasn't a login, the bottom line is that authentication is required - result = progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED; - deferred.reject(that, result, {xhr: xhr}); - } - - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(that, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - // set the properties that are passed between client and Web application in the - // X-CLIENT-PROPS header. This sets the complete set of properties all at once; - // it replaces any existing context - - this.setContext = function (context) { - _pdsession._contextProperties.setContext(context); - }; - - // Set or remove an individual property in the set of the properties that are passed - // between client and Web application in the X-CLIENT-PROPS header. This operates only - // on the property identiofied by propertyName; all other existing properties remain - // as they are. - // If the propertyName is not part of the context, this call adds it - // If it is part of the context, this call updates it, unless - - // If propertyValue is undefined, this call removes the property - this.setContextProperty = function (propertyName, propertyValue) { - _pdsession._contextProperties.setContextProperty(propertyName, propertyValue); - }; - - // get the set of properties that are passed between client and Web application in the - // X-CLIENT-PROPS header. Returns an object that has the properties - this.getContext = function () { - return _pdsession._contextProperties.getContext(); - }; - - // get the value of an individual property that is in the set of properties passed between - // client and Web application in the X-CLIENT-PROPS header - this.getContextProperty = function (propertyName) { - return _pdsession._contextProperties.getContextProperty(propertyName); - }; - - - this._onlineHandler = function (session, request) { - that.trigger("online", that, request); - }; - - this._offlineHandler = function (session, offlineReason, request) { - that.trigger("offline", that, offlineReason, request); - }; - - // PROCESS CONSTRUCTOR ARGUMENTS - // validate constructor input arguments - if ((arguments.length > 0) && (typeof arguments[0] === 'object')) { - - // (options is the name of the arguments[0] parameter) - if (options.serviceURI && (typeof options.serviceURI === "string")) { - _serviceURI = options.serviceURI; - } else { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "JSDOSession", - "the constructor", - "The options parameter must include a 'serviceURI' property that is a string." - )); - } - - if (options.authenticationModel) { - if (typeof options.authenticationModel !== "string") { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "JSDOSession", - "the constructor", - "The authenticationModel property of the options parameter must be a string." - )); - } - - options.authenticationModel = options.authenticationModel.toLowerCase(); - } else { - options.authenticationModel = progress.data.Session.AUTH_TYPE_ANON; - } - - // TODO: clean this up. Maybe make an immediate function - if (options.authProvider) { - if (typeof options.authProvider !== 'object') { - // JSDOSession: The 'options' parameter passed to the 'constructor' function - // has an invalid value for the 'authProvider' property. - throw new Error(progress.data._getMsgText( - "jsdoMSG502", - "JSDOSession", - "options", - "constructor", - "authProvider" - )); - } - - if ( - ( - options.authProvider.authenticationModel !== progress.data.Session.AUTH_TYPE_FORM_SSO - && options.authProvider.authenticationModel !== options.authenticationModel - ) - || - ( - options.authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_FORM_SSO - && options.authenticationModel !== progress.data.Session.AUTH_TYPE_SSO - ) - ) { - // JSDOSession: Error in constructor. The authenticationModels of the " + - // AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible."; - throw new Error(progress.data._getMsgText( - "jsdoMSG059", - "JSDOSession", - options.authProvider.authenticationModel, - options.authenticationModel - )); - } - // Check if the provider exposes the required API. - if (typeof options.authProvider.hasClientCredentials === 'function') { - if (!options.authProvider.hasClientCredentials()) { - // JSDOSession: The AuthenticationProvider is not managing valid credentials. - throw new Error(progress.data._getMsgText("jsdoMSG125", "JSDOSession")); - } - } else { - // JSDOSession: AuthenticationProvider objects must have a hasClientCredentials method. - throw new Error(progress.data._getMsgText( - "jsdoMSG505", - "JSDOSession", - "AuthenticationProvider", - "hasClientCredentials" - )); - } - } else if (options.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - // JSDOSession: If a JSDOSession object is using the SSO authentication model, - // the options object passed to its constructor must include an authProvider property. - throw new Error(progress.data._getMsgText("jsdoMSG508")); - } - - } else { - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "JSDOSession", - "the constructor", - "The options argument was missing or invalid." - )); - } - - _name = options.name; - - _pdsession = new progress.data.Session({ - _storageKey: _name, - _silent: true, - authenticationModel: options.authenticationModel, - serviceURI: options.serviceURI, - jsdosession: this, - authProvider: options.authProvider - }); - - try { - if (options.context) { - this.setContext(options.context); - } - _pdsession.subscribe("online", this._onlineHandler, this); - _pdsession.subscribe("offline", this._offlineHandler, this); - } catch (err) { - _pdsession = undefined; // so it will be garbage collected - throw err; - } - - }; // end of JSDOSession - - //set up inheritance for JSDOSession -- specifically for incorporating an Observable object - progress.data.JSDOSession.prototype = new progress.util.Observable(); - progress.data.JSDOSession.prototype.constructor = progress.data.JSDOSession; - function validateJSDOSessionSubscribe(args, evt, listenerData) { - listenerData.operation = undefined; - var found = false; - - // make sure this event is one that we support - this._eventNames.forEach(function (eventName) { - if (evt === eventName.toLowerCase()) { - found = true; - } - }); - if (!found) { - throw new Error(progress.data._getMsgText("jsdoMSG042", evt)); - } - - if (args.length < 2) { - throw new Error(progress.data._getMsgText("jsdoMSG038", 2)); - } - - if (typeof args[0] !== 'string') { - throw new Error(progress.data._getMsgText("jsdoMSG039")); - } - - if (typeof args[1] !== 'function') { - throw new Error(progress.data._getMsgText("jsdoMSG040")); - } - - listenerData.fn = args[1]; - - if (args.length > 2) { - if (typeof args[2] !== 'object') { - throw new Error(progress.data._getMsgText("jsdoMSG041", evt)); - } - - listenerData.scope = args[2]; - } - } - // events supported by JSDOSession - progress.data.JSDOSession.prototype._eventNames = - ["offline", "online"]; - // callback to validate subscribe and unsubscribe - progress.data.JSDOSession.prototype.validateSubscribe = validateJSDOSessionSubscribe; - progress.data.JSDOSession.prototype.toString = function (radix) { - return "progress.data.JSDOSession"; - }; - - progress.data.getSession = function (options) { - var deferred = new progress.util.Deferred(), - authProvider, - promise, - authProviderInitObject = {}; - - // This is the reject handler for session-related operations - // login, addCatalog, and logout - function sessionRejectHandler(object, result, info) { - // The object parameter may include the following properties - // - originator - // - result - // - info - object = progress.util.Deferred.getParamObject(object, result, info); - // undo the AuthenticationProvider's login if it succeeded - if (authProvider && authProvider.hasClientCredentials()) { - var callback = function () { - deferred.reject(object.result, object.info); - }; - // finally - authProvider.logout().then(callback, callback); - } else { - deferred.reject(object.result, object.info); - } - } - - // This is the reject handler for the login callback - function callbackRejectHandler(reason) { - deferred.reject(progress.data.Session.GENERAL_FAILURE, {"reason": reason}); - } - - function loginHandler(object) { - var jsdosession; - - try { - jsdosession = new progress.data.JSDOSession(options); - try { - jsdosession.isAuthorized() - .then(function() { - return jsdosession.addCatalog(options.catalogURI); - }, sessionRejectHandler) - .then(function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); - }, sessionRejectHandler); - } catch (e) { - sessionRejectHandler( - jsdosession, - progress.data.Session.GENERAL_FAILURE, - {errorObject: e} - ); - } - } catch (ex) { - sessionRejectHandler( - jsdosession, - progress.data.Session.GENERAL_FAILURE, - {errorObject: ex} - ); - } - } - - // This function calls login using credentials from the appropriate source - // Note that as currently implemented, this should NOT be called when - // ANONYMOUS auth is being used, because it unconditionally returns - // AUTHENTICATION_FAILURE if there are no credentials and no loginCallback - function callLogin(provider) { - var errorObject; - - // Use the login callback if we are passed one - // NOTE: Do we even use logincallback? Remove this??? - if (typeof options.loginCallback !== 'undefined') { - options.loginCallback() - .then(function (result) { - try { - provider.login(result.username, result.password) - .then(loginHandler, sessionRejectHandler); - } catch (e) { - sessionRejectHandler( - provider, - progress.data.Session.GENERAL_FAILURE, - { - errorObject: e - } - ); - } - }, callbackRejectHandler); - } else if (options.username && options.password) { - try { - provider.login(options.username, options.password) - .then(loginHandler, sessionRejectHandler); - } catch (e) { - sessionRejectHandler( - provider, - progress.data.Session.GENERAL_FAILURE, - { - errorObject: e - } - ); - } - } else { - // getSession(): The login method was not executed because no credentials were supplied. - errorObject = new Error(progress.data._getMsgText( - "jsdoMSG052", - "getSession()" - )); - sessionRejectHandler( - provider, - progress.data.Session.AUTHENTICATION_FAILURE, - { - // including an Error object to make clear why there is no xhr (normally there would - // be one for an authentication failure) - errorObject: errorObject - } - ); - } - } - - if (typeof options !== 'object') { - // getSession(): 'options' must be of type 'object' - throw new Error(progress.data._getMsgText( - "jsdoMSG503", - "getSession()", - "options", - "object" - )); - } - - if (typeof options.loginCallback !== 'undefined' && - typeof options.loginCallback !== 'function') { - // getSession(): 'options.loginCallback' must be of type 'function' - throw new Error(progress.data._getMsgText( - "jsdoMSG503", - "getSession()", - "options.loginCallback", - "function" - )); - } - - // Create the AuthenticationProvider and let it handle the argument parsing - try { - // If authenticationURI is not set, use serviceURI (except for SSO) - // Note: the test will of course catch any value that evaluates to false, not just undefined or - // null (which are the main concern), but that's probably OK - if (options.authenticationModel === progress.data.Session.AUTH_TYPE_SSO) { - if (!options.authenticationURI || !options.authProviderAuthenticationModel) { - // "progress.data.getSession: If the getSession method is passed AUTH_TYPE_SSO as - // the authenticationModel, it must also be passed an authenticationURI and an - // authProviderAuthenticationModel." - throw new Error(progress.data._getMsgText("jsdoMSG509")); - } - } - - if (options.authenticationURI) { - authProviderInitObject.uri = options.authenticationURI; - authProviderInitObject.authenticationModel = options.authProviderAuthenticationModel; - - // if auth uri has been passed, there must be an authProviderAuthenticationModel - if (typeof authProviderInitObject.authenticationModel !== "string") { - // JSDOSession: The 'object' parameter passed to the 'getSession' function - // has an invalid value for the 'authProviderAuthenticationModel' property. - throw new Error(progress.data._getMsgText( - "jsdoMSG502", - "progress.data.getSession", - "object", - "getSession", - "authProviderAuthenticationModel" - )); - } - } else { - authProviderInitObject.uri = options.serviceURI; - authProviderInitObject.authenticationModel = options.authenticationModel; - } - - authProvider = new progress.data.AuthenticationProvider(authProviderInitObject); - options.authProvider = authProvider; - - if (authProvider.hasClientCredentials()) { - loginHandler(authProvider); - } else { - // If model is anon, just log in. - if (authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { - authProvider.login() - .then(loginHandler, sessionRejectHandler); - } else { - // We need to log-in with credentials. - callLogin(authProvider); - } - } - } catch (error) { - // throw error; - sessionRejectHandler( - null, - progress.data.Session.GENERAL_FAILURE, - { - errorObject: error - } - ); - } - - return deferred.promise(); - }; - - progress.data.invalidateAllSessions = function () { - var jsdosession, - key, - deferred = new progress.util.Deferred(), - jsdosessions = progress.data.ServicesManager._jsdosessions, - invalidatePromises = []; - - try { - for (key in jsdosessions) { - if (jsdosessions.hasOwnProperty(key)) { - jsdosession = jsdosessions[key]; - - invalidatePromises.push(jsdosession.invalidate()); - } - } - - progress.util.Deferred.when(invalidatePromises) - .then(function () { - deferred.resolve(progress.data.Session.SUCCESS); - }, function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.reject(progress.data.Session.GENERAL_FAILURE, info); - }); - - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - // Using beautiful jquery shenanigans - return deferred.promise(); - }; - -})(); - -if (typeof exports !== "undefined") { - exports.progress = progress; -} - - -/* -progress.auth.js Version: 4.4.0-3 - -Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ - -(function () { - - "use strict"; // note that this makes JSLint complain if you use arguments[x] - - /*global progress : true*/ - /*global storage, XMLHttpRequest*/ - - /* define these if not defined yet - they may already be defined if - progress.js was included first */ - if (typeof progress === "undefined") { - progress = {}; - } - if (typeof progress.data === "undefined") { - progress.data = {}; - } - - // This is really more along the lines of a Factory method in that it explicitly creates an object - // and returns it based on the the authModel parameter (rather than following the default JS - // pattern of adding properties to the "this" object created for it and passed in by the runtime). - // NOTE: If we support multiple AuthenticationProviders that get different tokens from the same - // server, we may need to add a "name" property to the initObject to use as a storage key - - progress.data.AuthenticationProvider = function AuthenticationProvider (initObject) { - var authProv, - authModel, - uri; - - // process constructor arguments - if (typeof initObject === 'object') { - - // these 2 calls throw an appropriate error if the check doesn't pass - this._checkStringArg( - "constructor", - initObject.authenticationModel, - "initObject.authenticationModel", - "initObject.authenticationModel" - ); - - this._checkStringArg( - "constructor", - initObject.uri, - "init-object.uri", - "init-object.uri" - ); - } else { - // AuthenticationProvider: Invalid signature for constructor. The init-object argument - // was missing or invalid. - throw new Error(progress.data._getMsgText( - "jsdoMSG033", - "AuthenticationProvider", - "the constructor", - "The init-object argument was missing or invalid." - )); - } - - authModel = initObject.authenticationModel.toLowerCase(); - switch (authModel) { - case progress.data.Session.AUTH_TYPE_ANON: - this._initialize(initObject.uri, progress.data.Session.AUTH_TYPE_ANON, - {"_loginURI": progress.data.AuthenticationProvider._homeLoginURIBase}); - authProv = this; - break; - case progress.data.Session.AUTH_TYPE_BASIC: - authProv = new progress.data.AuthenticationProviderBasic(initObject.uri); - break; - case progress.data.Session.AUTH_TYPE_FORM: - authProv = new progress.data.AuthenticationProviderForm(initObject.uri); - break; - case progress.data.Session.AUTH_TYPE_FORM_SSO: - authProv = new progress.data.AuthenticationProviderSSO(initObject.uri); - break; - default: - // AuthenticationProvider: The 'init-object' parameter passed to the 'constructor' function - // has an invalid value for the 'authenticationModel' property. - throw new Error(progress.data._getMsgText( - "jsdoMSG502", - "AuthenticationProvider", - "init-object", - "constructor", - "authenticationModel" - )); - //break; - } - - return authProv; - }; - - - // ADD METHODS TO THE AuthenticationProvider PROTOYPE - - // GENERIC IMPLEMENTATION FOR login METHOD THAT THE API IMPLEMENTATIONS OF login CAN CALL - // (technically, they don't override it, they each have small login methods that call this) - progress.data.AuthenticationProvider.prototype._loginProto = - function (sendParam) { - var deferred = new progress.util.Deferred(), - xhr, - uriForRequest, - header, - that = this; - - try { - if (this._loggedIn) { - // "The login method was not executed because the AuthenticationProvider is - // already logged in." - throw new Error(progress.data._getMsgText("jsdoMSG051", "AuthenticationProvider")); - } - - xhr = new XMLHttpRequest(); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - // process the response from the Web application - that._processLoginResult(xhr, deferred); - } - }; - - if (progress.data.Session._useTimeStamp) { - uriForRequest = progress.data.Session._addTimeStampToURL(this._loginURI); - } else { - uriForRequest = this._loginURI; - } - - this._openLoginRequest(xhr, uriForRequest); - - // We specify application/json for the response so that, if a bad request is sent, an - // OE Web application will directly send back a 401 with error info in the body as JSON. - // So we force the accept header to application/json because if we make an anonymous - // request to a FORM/BASIC backend, it might redirect us to a login page since we have - // no credentials. And since we can technically access JUST the login page, the XHR - // will identify it as SUCCESS. If we specify "application/json", no redirects will - // happen, just a plain old "401 GET OUTTA HERE" code. - xhr.setRequestHeader("Accept", "application/json"); - - xhr.send(sendParam); - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - - - // PUBLIC METHODS (and their "helpers") (documented as part of the JSDO library API) - - // login API method -- just a shell that calls loginProto - progress.data.AuthenticationProvider.prototype.login = function () { - return this._loginProto(); - }; - - // HELPER FOR login METHOD, PROBABLY OVERRIDDEN IN MOST CONSTRUCTORS - progress.data.AuthenticationProvider.prototype._openLoginRequest = function (xhr, uri) { - xhr.open('GET', uri, true); - progress.data.Session._setNoCacheHeaders(xhr); - }; - - // HELPER FOR login METHOD, PROBABLY OVERRIDDEN IN MOST CONSTRUCTORS - progress.data.AuthenticationProvider.prototype._processLoginResult = function (xhr, deferred) { - var result; - - if (xhr.status === 200) { - // Need to set loggedIn now so we can call logout from here if there's an - // error processing the response (e.g., authentication succeeded but we didn't get a - // token for some reason) - this._loggedIn = true; - this._storeInfo(); - result = progress.data.Session.SUCCESS; - } else if (xhr.status === 401) { - // If this is Anonymous, somebody gave us the wrong authenticationModel! - result = progress.data.Session.AUTHENTICATION_FAILURE; - } else { - result = progress.data.Session.GENERAL_FAILURE; - } - - this._settlePromise(deferred, result, {"xhr": xhr}); - }; - - - // logout API METHOD -- SOME CONSTRUCTORS OR PROTOTYPES WILL OVERRIDE THIS - progress.data.AuthenticationProvider.prototype.logout = function () { - var deferred = new progress.util.Deferred(); - - try { - this._reset(); - deferred.resolve(this, progress.data.Session.SUCCESS, {}); - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - // hasClientCredentials API METHOD -- PROBABLY ONLY OVERRIDDEN BY SSO - progress.data.AuthenticationProvider.prototype.hasClientCredentials = function () { - return this._loggedIn; - }; - - // hasRefreshToken API METHOD -- returns false for all AutghenticationProvider types except SSO, - // which overrides it - progress.data.AuthenticationProvider.prototype.hasRefreshToken = function () { - return false; - }; - - // QUASI-PUBLIC METHOD - - // general-purpose method for opening requests (mainly for jsdo calls) - // This method is not part of the documented API that a developer would - // program against, but it gets used in a validation check by the JSDOSESSION, because the - // JSDOSESSION code expects it to be present. The point here is that if a developer were to - // create their own AuthenticationProvider object, it would need to include this method - // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change - // it to use promises - progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize = function (xhr, - verb, - uri, - async, - callback) { - var errorObject; - - if (this.hasClientCredentials()) { - xhr.open(verb, uri, async); - - // Check out why we do this in _loginProto - xhr.setRequestHeader("Accept", "application/json"); - callback(xhr); - } else { - // AuthenticationProvider: The AuthenticationProvider is not managing valid credentials. - errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); - callback(errorObject); - } - }; - - // GENERAL PURPOSE "INTERNAL" METHODS, NOT RELATED TO SPECIFIC API ELEMENTS - // (not documented, intended for use only within the JSDO library) - - // General purpose method for initializing an object - progress.data.AuthenticationProvider.prototype._initialize = function (uriParam, - authModel, - targetURIs) { - var tempURI, - target; - - Object.defineProperty(this, 'uri', - { - get: function () { - return this._uri; - }, - enumerable: true - }); - - Object.defineProperty(this, 'authenticationModel', - { - get: function () { - return this._authenticationModel; - }, - enumerable: true - }); - - - // get rid of trailing '/' because appending service url that starts with '/' - // will cause request failures - if (uriParam[uriParam.length - 1] === "/") { - tempURI = uriParam.substring(0, uriParam.length - 1); - } else { - tempURI = uriParam; - } - - // take the modified authentication uri and prepend it to all of the targets passed - // in. E.g., the targetURIs object will include a "loginURI" property that has the - // uri segment which is to be added to the auth uri for logging in - for (target in targetURIs) { - if (targetURIs.hasOwnProperty(target)) { - this[target] = tempURI + targetURIs[target]; - } - } - - this._authenticationModel = authModel; - this._uri = uriParam; // keep the uri property the same as what was passed in - - this._loggedIn = false; - this._dataKeys = { - uri: ".uri", - loggedIn: ".loggedIn" - }; - - // future: for page refresh -- storeSessionInfo("authenticationModel", authenticationModel); - - if (typeof sessionStorage === "undefined") { - // "AuthenticationProvider: No support for sessionStorage." - throw new Error(progress.data._getMsgText("jsdoMSG126", - "AuthenticationProvider", - "sessionStorage")); - } - // if you switch to a different type of storage, change the error message argument above - this._storage = sessionStorage; - - // maybe should come up with something more intelligent than this - this._storageKey = this._uri; // or name - this._dataKeys.uri = this._storageKey + this._dataKeys.uri; - this._dataKeys.loggedIn = this._storageKey + this._dataKeys.loggedIn; - - if (this._retrieveLoggedIn()) { - this._loggedIn = true; - } - }; - - - // Store data in storage with the uri as the key. setItem() throws. (Should add an - // option for the developer to specify the key) - // a "QuotaExceededError" error if there is insufficient storage space or - // "the user has disabled storage for the site" (Web storage spec at WHATWG) - progress.data.AuthenticationProvider.prototype._storeInfo = function () { - this._storage.setItem(this._dataKeys.uri, JSON.stringify(this._uri)); - this._storage.setItem(this._dataKeys.loggedIn, JSON.stringify(this._loggedIn)); - }; - - // Get a piece of state data from storage. Returns null if the item isn't in storage - progress.data.AuthenticationProvider.prototype._retrieveInfoItem = function (propName) { - var jsonStr = this._storage.getItem(propName), - value = null; - - if (jsonStr !== null) { - try { - value = JSON.parse(jsonStr); - } catch (e) { - value = null; - } - } - return value; - }; - - // Get an AuthenticationProvider's uri from storage - progress.data.AuthenticationProvider.prototype._retrieveURI = function () { - return this._retrieveInfoItem(this._dataKeys.uri); - }; - - // Get an AuthenticationProvider's logon status from storage - progress.data.AuthenticationProvider.prototype._retrieveLoggedIn = function () { - return this._retrieveInfoItem(this._dataKeys.loggedIn); - }; - - // Clear the persistent storage used by an AuthenticationProvider - progress.data.AuthenticationProvider.prototype._clearInfo = function (info) { - this._storage.removeItem(this._dataKeys.uri); - this._storage.removeItem(this._dataKeys.loggedIn); - }; - - // Put the internal state back to where it is when the constructor finishes - // running (so the authentication model and uri are not changed, but other data is reset. - // and storage is cleared out) - progress.data.AuthenticationProvider.prototype._reset = function () { - this._clearInfo(); - this._loggedIn = false; - }; - - - // General purpose utility method, no overrides expected - progress.data.AuthenticationProvider.prototype._settlePromise = function (deferred, result, info) { - if (result === progress.data.Session.SUCCESS) { - deferred.resolve(this, result, info); - } else { - deferred.reject(this, result, info); - } - }; - - // General purpose utility method, no overrides expected - progress.data.AuthenticationProvider.prototype._checkStringArg = function (fnName, - argToCheck, - argPosition, - argName) { - // TODO: ? distinguish between undefined (so we can give developer a clue that they - // may be missing a property) and defined but wrong type - if (typeof argToCheck !== "string") { - // AuthenticationProvider: Argument {param-position} must be of type string in {fnName} call. - throw new Error(progress.data._getMsgText( - "jsdoMSG121", - "AuthenticationProvider", - argPosition, - "string", - fnName - )); - } else if (argToCheck.length === 0) { - // AuthenticationProvider: {param-name} cannot be an empty string. - throw new Error(progress.data._getMsgText( - "jsdoMSG501", - "AuthenticationProvider", - argName, - fnName - )); - } - }; - - - // "STATIC" PROPERTIES AND METHODS -- not on the prototype -- you cannot access these through an - // object created by "new" --- they are properties of the AuthenticationProvider constructor function - - // Takes an XHR as an input. If the xhr status is 401 (Unauthorized), determines whether - // the auth failure was due to an expired token. Returns progress.data.Session.EXPIRED_TOKEN - // if it was, progress.data.Session.AUTHENTICATION_FAILURE if it wasn't, null if the xhr status wasn't 401 - progress.data.AuthenticationProvider._getAuthFailureReason = function (xhr) { - var contentType, - jsonObject, - result = progress.data.Session.AUTHENTICATION_FAILURE; - - if (xhr.status === 401) { - contentType = xhr.getResponseHeader("Content-Type"); - if (contentType && (contentType.indexOf("application/json") > -1) && xhr.responseText) { - jsonObject = JSON.parse(xhr.responseText); - if (jsonObject.error === "sso.token.expired_token") { - result = progress.data.Session.EXPIRED_TOKEN; - } - } - } else { - result = null; - } - return result; - }; - - Object.defineProperty(progress.data.AuthenticationProvider, '_homeLoginURIBase', { - value: "/static/home.html", - enumerable: true - }); - Object.defineProperty(progress.data.AuthenticationProvider, '_springLoginURIBase', { - value: "/static/auth/j_spring_security_check", - enumerable: true - }); - Object.defineProperty(progress.data.AuthenticationProvider, '_springLogoutURIBase', { - value: "/static/auth/j_spring_security_logout", - enumerable: true - }); - Object.defineProperty(progress.data.AuthenticationProvider, '_springFormTokenLoginURIBase', { - value: progress.data.AuthenticationProvider._springLoginURIBase + "?OECP=yes", - enumerable: true - }); - Object.defineProperty(progress.data.AuthenticationProvider, '_springFormTokenRefreshURIBase', { - value: "/static/auth/token?op=refresh", - enumerable: true - }); - -}()); - - -/* -progress.auth.basic.js Version: 4.4.0-3 - -Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ - -(function () { - - "use strict"; // note that this makes JSLint complain if you use arguments[x] - - /*global progress : true*/ - /*global storage, XMLHttpRequest, msg, btoa*/ - - progress.data.AuthenticationProviderBasic = function (uri) { - var defaultiOSBasicAuthTimeout, // TO DO: need to implement the use of this - userName = null, - password = null, - fn; - - // process constructor arguments, etc. - this._initialize(uri, progress.data.Session.AUTH_TYPE_BASIC, - {"_loginURI": progress.data.AuthenticationProvider._homeLoginURIBase}); - - // We don't support refresh for BASIC so get rid of anything in sessionStorage - // Remember to take this out when we support refresh for BASIC. - this._reset(); - - // PRIVATE FUNCTIONS - - // from http://coderseye.com/2007/how-to-do-http-basic-auth-in-ajax.html - function make_basic_auth_header(user, pw) { - var tok = user + ':' + pw, - hash = btoa(tok); - return "Basic " + hash; - } - - // "INTERNAL" METHODS - // Override the protoype's method but call it from within the override - // (Define the override here in the constructor so it has access to instance variables) - this._reset = function () { - userName = null; - password = null; - progress.data.AuthenticationProviderBasic.prototype._reset.apply(this); - }; - - // Override the protoype's method (this method does not invoke the prototype's copy) - // (Define the override here in the constructor so it has access to instance variables) - this._openLoginRequest = function (xhr, uri) { - var auth; - - xhr.open("GET", uri, true); // but see comments below inside the "if userName" - // may have to go with that approach - - if (userName) { - - // set Authorization header - auth = make_basic_auth_header(userName, password); - xhr.setRequestHeader('Authorization', auth); - } - - progress.data.Session._setNoCacheHeaders(xhr); - }; - - // Override the protoype's method but call it from within the override - // (Define the override here in the constructor so it has access to instance variables) - this._processLoginResult = function _basic_processLoginResult(xhr, deferred) { - progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply( - this, - [xhr, deferred] - ); - if (!this._loggedIn) { - // login failed, clear the credentials - userName = null; - password = null; - } - }; - - // Override the protoype's method (this method does not invoke the prototype's copy, but - // calls a prototype general-purpose login method) - // (Define the override here in the constructor so it has access to instance variables) - this.login = function (userNameParam, passwordParam) { - // these throw if the check fails (may want to do something more elegant) - this._checkStringArg("login", userNameParam, 1, "userName"); - this._checkStringArg("login", passwordParam, 2, "password"); - - userName = userNameParam; - password = passwordParam; - return this._loginProto(); - }; - - // Override the protoype's method (this method does not invoke the prototype's copy) - // (Define the override here in the constructor so it has access to instance variables) - // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change - // it to use promises - this._openRequestAndAuthorize = function (xhr, verb, uri, async, callback) { - var auth, - errorObject; - - if (this.hasClientCredentials()) { - - xhr.open(verb, uri, async); // but see comments below inside the "if userName" - // may have to go with that approach - - if (userName) { - - // set Authorization header - auth = make_basic_auth_header(userName, password); - xhr.setRequestHeader('Authorization', auth); - } - - progress.data.Session._setNoCacheHeaders(xhr); - callback(xhr); - } else { - // AuthenticationProvider: The AuthenticationProvider is not managing valid credentials. - errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); - callback(errorObject); - } - }; - }; - - - // Give this constructor the prototype from the "base" AuthenticationProvider - // Do this indirectly by way of an intermediate object so changes to the prototype ("method overrides") - // don't affect other types of AuthenticationProviders that use the prototype) - function BasicProxy() {} - BasicProxy.prototype = progress.data.AuthenticationProvider.prototype; - progress.data.AuthenticationProviderBasic.prototype = new BasicProxy(); - - // Reset the prototype's constructor property so it points to AuthenticationProviderForm rather than - // the one that it just inherited (this is pretty much irrelevant though - the correct constructor - // will get called regardless) - progress.data.AuthenticationProviderBasic.prototype.constructor = - progress.data.AuthenticationProviderBasic; - - - // OVERRIDE METHODS ON PROTOTYPE IF NECESSARY AND POSSIBLE - // (SOME METHODS ARE OVERRIDDEN IN THE CONSTRUCTOR BECAUSE THEY NEED ACCESS TO INSTANCE VARIABLES) - - // NOTE: There are no overrides of the following methods (either here or in the constructor). - // This object uses these methods from the original prototype(i.e., the implementations from the - // AuthenticationProvider object): - // logout (API method) - // hasClientCredentials (API method) - -}()); - -/* -progress.auth.form.js Version: 5.0.0 - -Copyright (c) 2016-2018 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ - -(function () { - - "use strict"; // note that this makes JSLint complain if you use arguments[x] - - /*global progress : true*/ - /*global XMLHttpRequest*/ - - var fn; - - progress.data.AuthenticationProviderForm = function (uri) { - - // PROCESS CONSTRUCTOR ARGUMENTS, CREATE API PROPERTIES, ETC. - this._initialize(uri, progress.data.Session.AUTH_TYPE_FORM, - {"_loginURI": progress.data.AuthenticationProvider._springLoginURIBase, - "_logoutURI": progress.data.AuthenticationProvider._springLogoutURIBase - }); - }; - - // Start by giving this constructor the prototype from the "base" AuthenticationProvider - // Do this indirectly by way of an intermediate object so changes to the prototype ("method overrides") - // don't affect other types of AuthenticationProviders that use the prototype) - function FormProxy() {} - FormProxy.prototype = progress.data.AuthenticationProvider.prototype; - progress.data.AuthenticationProviderForm.prototype = - new FormProxy(); - - // Reset the prototype's constructor property so it points to AuthenticationProviderForm rather than - // the one that it just inherited (this is pretty much irrelevant though - the correct constructor - // will get called regardless) - progress.data.AuthenticationProviderForm.prototype.constructor = - progress.data.AuthenticationProviderForm; - - - // OVERRIDE THE "BASE" AuthenticationProvider PROTOYPE METHODS WHERE NECESSARY - - // All of the methods defined here as part of the AuthenticationProviderForm prototype (instead - // of in the AuthenticationProviderForm constructor) can be inherited by the AuthenticationProviderSSO - // prototype without incurring the overhead of creating a full-blown instance of - // AuthenticationProviderForm to serve as the prototype for the SSO constructor. - // Note: if it turns out that any of the methods defined this way need access to internal variables - // of an AuthenticationProviderForm object, they'll need to be moved out of here. - - // NOTE: There are no overrides of the following methods (either here or in the constructor). - // This object uses these methods from the original prototype(i.e., the implementations from the - // AuthenticationProvider object): - // _reset (general-purpose helper) - // hasClientCredentials (API method) - // _processLoginResult (API helper method) - - - // login API METHOD AND "HELPERS" - progress.data.AuthenticationProviderForm.prototype.login = function (userNameParam, passwordParam) { - var deferred = new progress.util.Deferred(), - xhr, - that = this; - - // these throw if the check fails (may want to do something more elegant) - this._checkStringArg("login", userNameParam, 1, "userName"); - this._checkStringArg("login", passwordParam, 2, "password"); - - return this._loginProto("j_username=" + encodeURIComponent(userNameParam) + - "&j_password=" + encodeURIComponent(passwordParam) + "&submit=Submit"); - }; - - // login helper - // Override the protoype's method (this method does not invoke the prototype's copy) - // By defining this here, we can have the SSO AuthenticationProvider use it without - // incurring the overhead of creating a Form instance as the prototype for the SSO constructor - progress.data.AuthenticationProviderForm.prototype._openLoginRequest = function (xhr, uri) { - - xhr.open('POST', uri, true); - - xhr.setRequestHeader("Cache-Control", "max-age=0"); - xhr.setRequestHeader("Pragma", "no-cache"); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - - xhr.withCredentials = true; - - }; - - // logout API METHOD AND "HELPERS" - // Override the prototype method and do not call it because the Anonymous AuthenticationProvider - // doesn't make a server call for logout - // (But this method does do what the SSO AuthenticationProvider needs, so keep it on - // the Form prototype if possible) - progress.data.AuthenticationProviderForm.prototype.logout = function () { - var deferred = new progress.util.Deferred(), - xhr, - that = this; - - try { - if (!this._loggedIn) { - // logout is regarded as a success if the AuthenticationProvider isn't logged in - deferred.resolve(this, progress.data.Session.SUCCESS, {}); - } else { - xhr = new XMLHttpRequest(); - this._openLogoutRequest(xhr); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - // process the response from the Web application - that._processLogoutResult(xhr, deferred); - } - }; - - xhr.send(); - } - - // Unconditionally reset --- even if the actual server request fails, we still want - // to reset this AuthenticationProvider so it can try a login if desired. - // We also reset even in the case where we're not logged in, just in case. - // (In the future we can add a parameter that controls whether the reinit is unconditional, - // if the developer wants to log out of the token server session but contnue to use the token) - this._reset(); - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - // logout helper (there is no version defined in the original protoype) - progress.data.AuthenticationProviderForm.prototype._openLogoutRequest = function (xhr) { - xhr.open('GET', this._logoutURI, true); - xhr.setRequestHeader("Cache-Control", "max-age=0"); - xhr.withCredentials = true; - xhr.setRequestHeader("Accept", "application/json"); - }; - - // logout helper (there is no version defined in the original protoype) - progress.data.AuthenticationProviderForm.prototype._processLogoutResult = function (xhr, deferred) { - var result; - - if (xhr.status === 200) { - result = progress.data.Session.SUCCESS; - } else if (xhr.status === 401) { - // treat this as a success because the most likely cause is that the session expired - // (Note that an 11.7 OE PAS Web application will return a 200 if we log out with - // an expired JSESSIONID, so this code may not be executed anyway) - result = progress.data.Session.SUCCESS; - } else { - result = progress.data.Session.GENERAL_FAILURE; - } - - this._settlePromise(deferred, result, {"xhr": xhr}); - - }; - - // GENERAL PURPOSE METHOD FOR OPENING REQUESTS (MAINLY FOR JSDO CALLS) - // Override the protoype's method but call it from within the override - // Since the override is being put into the constructor's prototype, and - // since it calls the overridden method which had originally been in the prototype, - // we add a "_super" property to the overriding method so it can still access the original method - // (We could just call that method directly in here like this: - // progress.data.AuthenticationProviderProto.prototype._openRequestAndAuthorize - // but if we ever change the place where we get the initial protoype for - // AuthenticationProviderForm from, we would need to remember to change that here. - // The use of the _super property will handle that automatically, plus it was more fun - // to do it this way) - // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change - // it to use promises - fn = progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize; - progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize = - function (xhr, verb, uri, async, callback) { - - function afterSuper(errorObject) { - if (errorObject instanceof Error) { - callback(errorObject); - } else { - xhr.withCredentials = true; - callback(xhr); - } - } - - try { - progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply( - this, - [xhr, verb, uri, async, afterSuper] - ); - } catch (e) { - callback(e); - } - }; - progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super = fn; - - -}()); - -/* -progress.auth.sso.js Version: 4.4.0-3 - -Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - */ - -(function () { - - "use strict"; // note that this makes JSLint complain if you use arguments[x] - - /*global progress : true*/ - - var fn; - - // ADD AN OPTIONS PARAM THAT CAN INCLUDE A NAME FOR PAGE REFRESH? - progress.data.AuthenticationProviderSSO = function (uri) { - var that = this, - // SSO specific - _automaticTokenRefresh, - temp, - ssoTokenInfo = null, - tokenDataKeys = { // SSO specific - token: ".access_token", - refreshToken: ".refresh_token", - tokenType: ".token_type", - expiration: ".expires_in", - accessTokenExpiration: ".accessTokenExpiration" - }; - - // PRIVATE FUNCTIONS - // (The constructor uses local variables and functions mainly to try to protect the token - // information as much as possible. A few could probably be defined as properties/methods, but - // there's currently no need for that because the AuthenticationProvider API has no objects - // that inherit from AuthenticationProviderSSO.) - - // Store the given token with the uri as the key. setItem() throws - // a "QuotaExceededError" error if there is insufficient storage space or - // "the user has disabled storage for the site" (Web storage spec at WHATWG) - function storeTokenInfo(info) { - var date, - accessTokenExpiration; - - if (info.access_token.length) { - that._storage.setItem(tokenDataKeys.token, JSON.stringify(info.access_token)); - } - if (info.refresh_token.length) { - that._storage.setItem(tokenDataKeys.refreshToken, JSON.stringify(info.refresh_token)); - // The time given for the access token's expiration is in seconds. We transform it - // into milliseconds and add it to date.getTime() for a more standard format. - date = new Date(); - // This should probably be renamed accessTokenRefreshThreshold - accessTokenExpiration = date.getTime() + (info.expires_in * 1000 * 0.75); - that._storage.setItem(tokenDataKeys.accessTokenExpiration, JSON.stringify(accessTokenExpiration)); - } else { - // if there is no refresh token, remove any existing one. This handles the case where - // we got a new token via refresh, but now we're not being given any more refresh tokens - that._storage.removeItem(tokenDataKeys.refreshToken); - that._storage.removeItem(tokenDataKeys.accessTokenExpiration); - } - that._storage.setItem(tokenDataKeys.tokenType, JSON.stringify(info.token_type)); - that._storage.setItem(tokenDataKeys.expiration, JSON.stringify(info.expires_in)); - } - - // get one of the pieces of data related to tokens from storage (could be the token itself, or - // the refresh token, expiration info, etc.). Returns null if the item isn't in storage - function retrieveTokenProperty(propName) { - var jsonStr = that._storage.getItem(propName), - value = null; - - if (jsonStr !== null) { - try { - value = JSON.parse(jsonStr); - } catch (e) { - value = null; - } - } - return value; - } - - function retrieveToken() { - return retrieveTokenProperty(tokenDataKeys.token); - } - - function retrieveRefreshToken() { - return retrieveTokenProperty(tokenDataKeys.refreshToken); - } - - function retrieveAccessTokenExpiration() { - return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration); - } - - function retrieveTokenType() { - return retrieveTokenProperty(tokenDataKeys.tokenType); - } - - // This is going to be hardcoded for now. This can very - // possibly change in the future if we decide to expose - // the token to the user. - function getToken() { - return retrieveToken(); - } - - function retrieveExpiration() { - return retrieveTokenProperty(tokenDataKeys.expiration); - } - - function clearTokenInfo(info) { - that._storage.removeItem(tokenDataKeys.token); - that._storage.removeItem(tokenDataKeys.refreshToken); - that._storage.removeItem(tokenDataKeys.tokenType); - that._storage.removeItem(tokenDataKeys.expiration); - that._storage.removeItem(tokenDataKeys.accessTokenExpiration); - } - - // function is SSO specific - function openRefreshRequest(xhr) { - xhr.open('POST', that._refreshURI, true); - xhr.setRequestHeader("Cache-Control", "max-age=0"); - xhr.withCredentials = true; - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.setRequestHeader("Accept", "application/json"); - } - - // function is SSO specific - function processRefreshResult(xhr, deferred) { - var errorObject, - result, - ssoTokenJSON; - - if (xhr.status === 200) { - // get token and store it; if that goes well, resolve the promise, otherwise reject it - try { - ssoTokenInfo = JSON.parse(xhr.responseText); - - if (ssoTokenInfo.access_token) { - storeTokenInfo(ssoTokenInfo); - // got the token info, its access_token has a value, and storeTokenInfo() - // didn't thrown an error, so call this a success - result = progress.data.Session.SUCCESS; - } else { - result = progress.data.Session.GENERAL_FAILURE; - // {1}: Unexpected error calling refresh: {error-string} - // ( No token returned from server) - errorObject = new Error(progress.data._getMsgText( - "jsdoMSG049", - "AuthenticationProvider", - "refresh", - progress.data._getMsgText("jsdoMSG050") - )); - } - } catch (ex) { - result = progress.data.Session.GENERAL_FAILURE; - // {1}: Unexpected error calling refresh: {error-string} - // (error could be thrown from storeTokenInfo when it calls setItem()) - errorObject = new Error(progress.data._getMsgText( - "jsdoMSG049", - "AuthenticationProvider", - "refresh", - ex.message - )); - } - } else if (xhr.status === 401) { - that._reset(); // treat authentication failure as the equivalent of a logout - result = progress.data.Session.AUTHENTICATION_FAILURE; - } else { - result = progress.data.Session.GENERAL_FAILURE; - } - - that._settlePromise(deferred, result, {"xhr": xhr, - "errorObject": errorObject}); // OK if undefined - } - - - this._processLoginResult = function (xhr, deferred) { - var errorObject, - result, - ssoTokenJSON; - - if (xhr.status === 200) { - // Need to set loggedIn now so we can call logout from here if there's an - // error processing the response (e.g., authentication succeeded but we didn't get a - // token for some reason) - this._loggedIn = true; - - // get token and store it; if that goes well, resolve the promise, otherwise reject it - try { - ssoTokenInfo = JSON.parse(xhr.responseText); - - if (ssoTokenInfo.access_token) { - storeTokenInfo(ssoTokenInfo); - // got the token info, its access_token has a value, and storeTokenInfo() - // didn't throw an error, so call this a success - result = progress.data.Session.SUCCESS; - } else { - result = progress.data.Session.GENERAL_FAILURE; - // {1}: Unexpected error calling login: {error-string} - // ( No token returned from server) - errorObject = new Error(progress.data._getMsgText( - "jsdoMSG049", - "AuthenticationProvider", - "login", - progress.data._getMsgText("jsdoMSG050") - )); - } - } catch (ex) { - result = progress.data.Session.GENERAL_FAILURE; - // {1}: Unexpected error calling login: {error-string} - // (error could be thrown from storeTokenInfo when it calls setItem()) - errorObject = new Error(progress.data._getMsgText( - "jsdoMSG049", - "AuthenticationProvider", - "login", - ex.message - )); - } - - // log out if there was an error processing the response so the app can try to log in again - if (result !== progress.data.Session.SUCCESS) { - // call logout, but ignore its outcome -- just tell caller that login failed - var callback = function (params) { - params = progress.util.Deferred.getParamObject(params); - params.provider._settlePromise(deferred, result, {"xhr": xhr, - "errorObject": errorObject}); - }; - // finally - this.logout() - .then(callback, callback); - return; // so we don't execute the reject below, which could invoke the fail handler - // before we're done with the logout - } - - } else if (xhr.status === 401) { - result = progress.data.Session.AUTHENTICATION_FAILURE; - } else { - result = progress.data.Session.GENERAL_FAILURE; - } - - this._settlePromise(deferred, result, {"xhr": xhr}); - }; - - - // Override the protoype's method but call it from within the override. (Define the override - // here in the constructor so it has access to the internal function and variable) - this._reset = function () { - progress.data.AuthenticationProviderSSO.prototype._reset.apply(this); - clearTokenInfo(); - ssoTokenInfo = null; - }; - - - // Override the protoype's method but call it from within the override. (Define the override - // here in the constructor so it has access to the internal function getToken() ) - // TODO: This method uses a callback, primarily to avoid breaking tdriver tests. We should change - // it to use promises - this._openRequestAndAuthorize = function (xhr, - verb, - uri, - async, - callback) { - var that = this, - date, - errorObject; - - function afterRefreshCheck(provider, result, info) { - // if refresh failed because of auth failure, we will have gotten rid of the - // token and reset the auth provider - if (result === progress.data.Session.AUTHENTICATION_FAILURE) { - callback(new Error(progress.data._getMsgText("jsdoMSG060"))); - } else { - // We've done the refresh check (and possible refresh) for SSO, now execute - // the base _openRequest... method, which does common things for Form-based - progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply( - that, - [xhr, verb, uri, async, function (errorObject) { - if (errorObject instanceof Error) { - callback(errorObject); - } else { - xhr.setRequestHeader('Authorization', "oecp " + getToken()); - callback(xhr); - } - }] - ); - } - } - - if (this.hasClientCredentials()) { - // Every token given has an expiration "hint". If the token's lifespan - // is close to or past that limit, then a refresh is done. - // No matter what the outcome of the refresh, keep in mind we always - // send the original request. - date = new Date(); - if (this.automaticTokenRefresh && - this.hasRefreshToken() && - date.getTime() > retrieveAccessTokenExpiration()) { - try { - var callback = function (params, result, info) { - params = progress.util.Deferred.getParamObject(params, result, info); - afterRefreshCheck(params.provider, params.result, params.info); - }; - // finally - this.refresh() - .then(callback, callback); - } catch (e) { - callback(e); - } - } else { - afterRefreshCheck(this, progress.data.Session.SUCCESS, null); - } - } else { - // This message is SSO specific, unless we can come up with a more general message - // JSDOSession: The AuthenticationProvider needs to be managing a valid token. - errorObject = new Error(progress.data._getMsgText("jsdoMSG125", "AuthenticationProvider")); - callback(errorObject); - } - }; - - - // API METHODS - - // override the prototype's hasClientCredentials method - this.hasClientCredentials = function () { - return (retrieveToken() === null ? false : true); - }; - - - this.refresh = function () { - var deferred = new progress.util.Deferred(), - xhr; - - try { - if (!this._loggedIn) { - // "The refresh method was not executed because the AuthenticationProvider is not logged in." - throw new Error(progress.data._getMsgText("jsdoMSG053", "AuthenticationProvider", "refresh")); - } - - if (!this.hasRefreshToken()) { - // "Token refresh was not executed because the AuthenticationProvider does not have a - // refresh token." - throw new Error(progress.data._getMsgText("jsdoMSG054", "AuthenticationProvider")); - } - - xhr = new XMLHttpRequest(); - openRefreshRequest(xhr); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - // process the response from the Web application - processRefreshResult(xhr, deferred); - } - }; - - xhr.send('{"token_type":"' + retrieveTokenType() + '","refresh_token":"' + - retrieveRefreshToken() + '"}'); - } catch (error) { - if (progress.util.Deferred.useJQueryPromises) { - throw error; - } else { - deferred.reject(this, progress.data.Session.GENERAL_FAILURE, { - errorObject: error - }); - } - } - return deferred.promise(); - }; - - - this.hasRefreshToken = function () { - return (retrieveRefreshToken() === null ? false : true); - }; - - - // PROCESS CONSTRUCTOR ARGUMENTS, CREATE API PROPERTIES, ETC. - this._initialize(uri, - progress.data.Session.AUTH_TYPE_FORM_SSO, - {"_loginURI": progress.data.AuthenticationProvider._springFormTokenLoginURIBase, - "_logoutURI": progress.data.AuthenticationProvider._springLogoutURIBase, - "_refreshURI": progress.data.AuthenticationProvider._springFormTokenRefreshURIBase - }); - - // in addition to the standard AuthenticationProvider properties, an SSO provider also has a property - // to control automatic token refresh (it's enabled by default on the assumption that developers - // will usually want this) - _automaticTokenRefresh = true; - Object.defineProperty(this, 'automaticTokenRefresh', - { - get: function () { - return _automaticTokenRefresh; - }, - set: function (value) { - if (value === true || value === false) { - _automaticTokenRefresh = value; - } else { - throw new Error(progress.data._getMsgText("jsdoMSG061", - "AuthenticationProvider", - "automaticTokenRefresh")); - } - }, - enumerable: true - }); - - // add the automaticTokenRefresh key to the base class's list of data keys - this._dataKeys.automaticTokenRefresh = this._storageKey + ".automaticTokenRefresh"; - // set it from storage, if it's in storage - temp = this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh); - if (temp === false) { - _automaticTokenRefresh = false; - } - - // We're currently storing the token in storage with the - // uri as the key. This is subject to change later. - tokenDataKeys.token = this._storageKey + tokenDataKeys.token; - tokenDataKeys.refreshToken = this._storageKey + tokenDataKeys.refreshToken; - tokenDataKeys.tokenType = this._storageKey + tokenDataKeys.tokenType; - tokenDataKeys.expiration = this._storageKey + tokenDataKeys.expiration; - tokenDataKeys.accessTokenExpiration = this._storageKey + tokenDataKeys.accessTokenExpiration; - - // NOTE: we rely on the prototype's logic to set this._loggedIn. An alternative could be to - // use the presence of a token to determine that, but it's conceivable that we could be - // logged in but for some reason not have a token (e.g., a token expired, or we logged in - // but the authentication server did not return a token) - if (retrieveToken()) { - this._loggedIn = true; - } - - // END OF CONSTRUCTOR PROCESSING - - }; - // END OF AuthenticationProviderSSO CONSTRUCTOR - - // NOTE: This is used only for the SSO authentication. - // Define the prototype as an instance of an AuthenticationProviderForm object - function SSOProxy() {} - SSOProxy.prototype = progress.data.AuthenticationProviderForm.prototype; - progress.data.AuthenticationProviderSSO.prototype = - new SSOProxy(); - - // But reset the constructor back to the SSO constructor (this is pretty much irrelevant, - // though. The correct constructor would be called anyway. It's mainly for the sake of anyone - // wanting to see what the constructor of an object is (maybe a framework) - progress.data.AuthenticationProviderSSO.prototype.constructor = - progress.data.AuthenticationProviderSSO; - - // override the base AuthenticationProvider _storeInfo and _clearinfo, but keep refs so they - // can be invoked within the overrides - fn = progress.data.AuthenticationProviderSSO.prototype._storeInfo; - progress.data.AuthenticationProviderSSO.prototype._storeInfo = - function () { - progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this); - this._storage.setItem(this._dataKeys.automaticTokenRefresh, - JSON.stringify(this._automaticTokenRefresh)); - }; - progress.data.AuthenticationProviderSSO.prototype._storeInfo._super = fn; - - fn = progress.data.AuthenticationProviderSSO.prototype._clearInfo; - progress.data.AuthenticationProviderSSO.prototype._clearInfo = - function () { - progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this); - this._storage.removeItem(this._dataKeys.automaticTokenRefresh); - }; - progress.data.AuthenticationProviderSSO.prototype._clearInfo._super = fn; - - - - // NOTE: There are no overrides of the following methods (either here or in the constructor). - // This object uses these methods from the original prototype(i.e., the implementations from the - // Auth...Form object) because for an OE SSO token server, the login/logout model is Form (the - // only difference is the use of a special URI query string in the login (see the call to - // initialize() in the SSO constructor (above)): - // login (API method) - // _openLoginRequest (API helper method) - // logout (API method) - // _openLogoutRequest (API helper method) - // _processLogoutResult (API helper method) - - // NOTE: All overrides are implemented in the constructor (rather than adding them to the prototype) - // because they need access to variables and/or functions that are defined in the constructor - // (in an attempt to protect the token info somewhat) - -}()); - From 371235ec49bdd1a7d7e505d9166c3f4b5a5cf033 Mon Sep 17 00:00:00 2001 From: joshualan Date: Thu, 7 Jun 2018 23:03:07 -0400 Subject: [PATCH 15/84] Split up the smokes tests into their own individual files --- test/smoke.js | 242 -------------------------------------- test/smoke.jsdo.js | 160 +++++++++++++++++++++++++ test/smoke.jsdosession.js | 95 +++++++++++++++ 3 files changed, 255 insertions(+), 242 deletions(-) delete mode 100644 test/smoke.js create mode 100644 test/smoke.jsdo.js create mode 100644 test/smoke.jsdosession.js diff --git a/test/smoke.js b/test/smoke.js deleted file mode 100644 index 208430a..0000000 --- a/test/smoke.js +++ /dev/null @@ -1,242 +0,0 @@ -const chai = require('chai'); -const expect = chai.expect; -const chaiAsPromised = require("chai-as-promised"); - -const progress = require("../lib/progress.jsdo").progress; - -chai.use(chaiAsPromised); - -// Might be a good idea to separate this into their own files down the line! It should be -// relatively easy. - -describe('Smoke Tests', () => { - // INFORMATION YEAH - const options = { - catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", - serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", - resourceName: "Customer", - tableRef: "ttCustomer", - filter: "CustNum > 2990", - model: "anonymous" - }; - - const CustName = "SmokeTest3000"; - - let session, - jsdo; - - // Logout of the session after we are done - after((done) => { - session.invalidate().then(() => done()); - }); - - describe('getSession Tests', function () { - it('should fail to connect to a non-existent backend', function () { - let getSession = progress.data.getSession({ - serviceURI: options.serviceURI + "fake", - catalogURI: options.catalogURI, - authenticationModel: options.model - }).then((object) => { - return expect.fail(null, null, "getSession succeeded on a non-existent backend?"); - }, (object) => { - return object.result; - }); - - return expect(getSession).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); - }); - - it('should connect to an existing basic backend', function () { - let getSession = progress.data.getSession({ - serviceURI: "http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/", - catalogURI: "http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/static/CustomerService.json", - authenticationModel: "basic", - username: "basicuser", - password: "basicpassword" - }).then((object) => { - object.jsdosession.invalidate(); - return object.result; - }); - - return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); - }); - - it('should connect to an existing anonymous backend', function () { - let getSession = progress.data.getSession({ - serviceURI: options.serviceURI, - catalogURI: options.catalogURI, - authenticationModel: options.model - }).then((object) => { - session = object.jsdosession; - return object.result; - }); - - return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); - }); - - }); - - - describe('JSDO Tests', function () { - describe('JSDO Instantiation Tests', function() { - it('should successfully create a JSDO', function() { - jsdo = new progress.data.JSDO({name: options.resourceName}); - expect(jsdo).to.be.an.instanceof(progress.data.JSDO); - }); - - it('should successfully call fill()', function() { - let fill = jsdo.fill().then((object) => { - return object.success; - }); - - return expect(fill).to.eventually.be.true; - }); - - it('should have a jsdo filled with actual data from the backend', function() { - expect(jsdo.hasData()).to.be.true; - }); - }); - - describe('JSDO CUD Tests', function () { - // Clean up the backend to make sure that there isn't an customer record with a CustNum of 3000 - // already in store - function clean(callback) { - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - customer.remove(); - } - }); - - jsdo.saveChanges().then(() => { - return jsdo.fill(); - }).then(() => callback()); - } - - before(function(done) { - clean(done); - }); - - after(function(done) { - clean(done); - }); - - - it('should successfully create a record on the backend', function() { - jsdo.ttCustomer.add({ - Name: CustName, - SalesRep: 'NS', - Balance: '2.10', - State: 'MA', - }); - - let save = jsdo.saveChanges().then((object) => { - return jsdo.fill(); - }).then((object) => { - let found = false; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - found = true; - } - }); - return found; - }); - - return expect(save).to.eventually.be.true; - }); - - it('should successfully update a record on the backend', function() { - const newState = "NH"; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - customer.assign({State: newState}); - } - }); - - let save = jsdo.saveChanges().then((object) => { - return jsdo.fill(); - }).then((object) => { - let found = false; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName && customer.data.State === newState) { - found = true; - } - }); - return found; - }); - - return expect(save).to.eventually.be.true; - }); - - it('should fail to update a record to have the same primary index as another record', function() { - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - customer.assign({CustNum: 1}); - } - }); - - let save = jsdo.saveChanges().then((object) => { - return object.success; - }, function (object) { - return object.success; - }); - - return expect(save).to.eventually.be.false; - }); - - it('should successfully delete a record on the backend', function() { - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - customer.remove(); - } - }); - - let save = jsdo.saveChanges().then((object) => { - return jsdo.fill(); - }).then((object) => { - let found = false; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === CustName) { - found = true; - } - }); - return found; - }); - - return expect(save).to.eventually.be.false; - }); - }); - }); - - describe('JSDOSession API Tests', function () { - it('should successfully ping() the backend', function() { - let ping = session.ping().then((object) => { - // If we have successfully logged into the backend, the result - // of our ping() should be true - return true; - }); - - return expect(ping).to.eventually.equal(true); - }); - - it('should have a successful call to isAuthorized()', function() { - let isAuthorized = session.isAuthorized().then((object) => { - // If we have successfully logged into the backend, the result - // of our ping() should be true - return object.result; - }); - - return expect(isAuthorized).to.eventually.equal(progress.data.Session.SUCCESS); - }); - - it('should not have a connection to the backend after an invalidate', function() { - let isAuthorized = session.invalidate().then(() => { - return session.isAuthorized(); - }).then((object) => { - return object.result; - }, function(object) { - return object.result - }); - - return expect(isAuthorized).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); - }) - }); -}); \ No newline at end of file diff --git a/test/smoke.jsdo.js b/test/smoke.jsdo.js new file mode 100644 index 0000000..99f57b7 --- /dev/null +++ b/test/smoke.jsdo.js @@ -0,0 +1,160 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); + +const progress = require("../build/progress.jsdo").progress; + +chai.use(chaiAsPromised); + +describe('JSDO Smoke Tests', () => { + // INFORMATION YEAH + const options = { + catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", + serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", + resourceName: "Customer", + authenticationModel: "anonymous" + }; + + const CustName = "SmokeTest3000"; + + let session, + jsdo; + + before(function (done) { + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => done(), () => done()); + }); + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + describe('JSDO Instantiation Tests', function() { + it('should successfully create a JSDO', function() { + jsdo = new progress.data.JSDO({name: options.resourceName}); + expect(jsdo).to.be.an.instanceof(progress.data.JSDO); + }); + + it('should successfully call fill()', function() { + let fill = jsdo.fill().then((object) => { + return object.success; + }); + + return expect(fill).to.eventually.be.true; + }); + + it('should have a jsdo filled with actual data from the backend', function() { + expect(jsdo.hasData()).to.be.true; + }); + }); + + describe('JSDO CUD Tests', function () { + // Clean up the backend to make sure that there isn't an customer record with a CustNum of 3000 + // already in store + function clean(callback) { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + jsdo.saveChanges().then(() => { + return jsdo.fill(); + }).then(() => callback()); + } + + before(function(done) { + clean(done); + }); + + after(function(done) { + clean(done); + }); + + it('should successfully create a record on the backend', function() { + jsdo.ttCustomer.add({ + Name: CustName, + SalesRep: 'NS', + Balance: '2.10', + State: 'MA', + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.true; + }); + + it('should successfully update a record on the backend', function() { + const newState = "NH"; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.assign({State: newState}); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName && customer.data.State === newState) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.true; + }); + + it('should fail to update a record to have the same primary index as another record', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.assign({CustNum: 1}); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return object.success; + }, function (object) { + return object.success; + }); + + return expect(save).to.eventually.be.false; + }); + + it('should successfully delete a record on the backend', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + let save = jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + found = true; + } + }); + return found; + }); + + return expect(save).to.eventually.be.false; + }); + }); +}); \ No newline at end of file diff --git a/test/smoke.jsdosession.js b/test/smoke.jsdosession.js new file mode 100644 index 0000000..c9c1527 --- /dev/null +++ b/test/smoke.jsdosession.js @@ -0,0 +1,95 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require('chai-as-promised'); + +const progress = require("../build/progress.jsdo").progress; + +chai.use(chaiAsPromised); + +describe('JSDOSession Smoke Tests', () => { + // INFORMATION YEAH + const options = { + catalogURI: 'https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json', + serviceURI: 'https://oemobiledemo.progress.com/OEMobileDemoServices', + authenticationModel: 'anonymous' + }; + + let session; + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + describe('getSession Tests', function () { + it('should fail to connect to a non-existent backend', function () { + let getSession = progress.data.getSession({ + serviceURI: options.serviceURI + 'fake', + catalogURI: options.catalogURI, + authenticationModel: options.authenticationModel + }).then((object) => { + return expect.fail(null, null, 'getSession succeeded on a non-existent backend?'); + }, (object) => { + return object.result; + }); + + return expect(getSession).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); + }); + + it('should connect to an existing basic backend', function () { + let getSession = progress.data.getSession({ + serviceURI: 'http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/', + catalogURI: 'http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/static/CustomerService.json', + authenticationModel: 'basic', + username: 'basicuser', + password: 'basicpassword' + }).then((object) => { + object.jsdosession.invalidate(); + return object.result; + }); + + return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); + }); + + it('should connect to an existing anonymous backend', function () { + let getSession = progress.data.getSession(options).then((object) => { + session = object.jsdosession; + return object.result; + }); + + return expect(getSession).to.eventually.equal(progress.data.Session.SUCCESS); + }); + }); + + describe('JSDOSession API Tests', function () { + it('should successfully ping() the backend', function() { + let ping = session.ping().then((object) => { + return true; + }); + + return expect(ping).to.eventually.equal(true); + }); + + it('should have a successful call to isAuthorized()', function() { + let isAuthorized = session.isAuthorized().then((object) => { + // If we have successfully logged into the backend, the result + // of our ping() should be true + return object.result; + }); + + return expect(isAuthorized).to.eventually.equal(progress.data.Session.SUCCESS); + }); + + it('should not have a connection to the backend after an invalidate', function() { + let isAuthorized = session.invalidate().then(() => { + return session.isAuthorized(); + }).then((object) => { + return object.result; + }, function(object) { + return object.result + }); + + return expect(isAuthorized).to.eventually.equal(progress.data.Session.GENERAL_FAILURE); + }) + }); +}); \ No newline at end of file From 31cf99f45d3084d6e2d5565efeb2a8d132ea7206 Mon Sep 17 00:00:00 2001 From: edselg Date: Mon, 11 Jun 2018 16:35:11 -0400 Subject: [PATCH 16/84] Added code to process records in DataSource when using idProperty --- src/progress.data.kendo.js | 45 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/progress.data.kendo.js b/src/progress.data.kendo.js index 73d148d..72e4bde 100644 --- a/src/progress.data.kendo.js +++ b/src/progress.data.kendo.js @@ -255,6 +255,8 @@ if (typeof (kendo) !== "undefined") { elementName, copy; + // Remove prods:rowState property from data object + delete data["prods:rowState"]; if (!transport.useArrays && transport._convertTypes && (transport._convertFields._arrayFields.length > 0)) { copy = {}; transport.jsdo._copyRecord(transport.jsdo._buffers[transport.tableRef], data, copy); @@ -584,14 +586,17 @@ if (typeof (kendo) !== "undefined") { if (options.batch) { array = []; if (options.data.created instanceof Array) { - for (i = 0; i < options.data.created.length; i += 1) { - jsrecord = jsdo[transport.tableRef].findById( - options.data.created[i]._id - ); - if (jsrecord) { - record = transport._convertDataTypes(jsrecord.data); - array.push(record); - } else if (jsdo.autoApplyChanges) { + // Process changes for idProperty case + if (jsdo._resource.idProperty) { + if (request.jsrecords) { + for (i = 0; i < request.jsrecords.length; i += 1) { + if (request.jsrecords[i].data["prods:rowState"] === "created") { + record = transport._convertDataTypes(request.jsrecords[i].data); + array.push(record); + } + } + } + if (options.data.created.length !== array.length) { options.error( null, null, @@ -599,8 +604,25 @@ if (typeof (kendo) !== "undefined") { ); return; } + } else { + for (i = 0; i < options.data.created.length; i += 1) { + jsrecord = jsdo[transport.tableRef].findById( + options.data.created[i]._id + ); + if (jsrecord) { + record = transport._convertDataTypes(jsrecord.data); + array.push(record); + } else if (jsdo.autoApplyChanges) { + options.error( + null, + null, + new Error("Created record was not found in memory.") + ); + return; + } + } } - } + } options.success(array, "create"); array = []; @@ -648,7 +670,10 @@ if (typeof (kendo) !== "undefined") { && request.batch.operations instanceof Array && request.batch.operations.length === 1) { id = request.batch.operations[0].jsrecord.data._id; - } + } else if (request + && request.jsrecords instanceof Array + && request.jsrecords.length === 1) { + id = request.jsrecords[0].data._id; } else { id = options.data._id; } From d312f89f63d591d4888f4b9028f3433438554307 Mon Sep 17 00:00:00 2001 From: edselg Date: Tue, 12 Jun 2018 09:57:22 -0400 Subject: [PATCH 17/84] fixed issue --- src/progress.data.kendo.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/progress.data.kendo.js b/src/progress.data.kendo.js index 72e4bde..c1565cf 100644 --- a/src/progress.data.kendo.js +++ b/src/progress.data.kendo.js @@ -622,7 +622,7 @@ if (typeof (kendo) !== "undefined") { } } } - } + } options.success(array, "create"); array = []; @@ -673,7 +673,8 @@ if (typeof (kendo) !== "undefined") { } else if (request && request.jsrecords instanceof Array && request.jsrecords.length === 1) { - id = request.jsrecords[0].data._id; + id = request.jsrecords[0].data._id; + } } else { id = options.data._id; } @@ -684,6 +685,7 @@ if (typeof (kendo) !== "undefined") { } else { options.success({}); } + } }, _saveChanges: function (options) { From 0727462eee99c6c2a3941e59c37a0923a7413e23 Mon Sep 17 00:00:00 2001 From: edselg Date: Tue, 12 Jun 2018 11:58:58 -0400 Subject: [PATCH 18/84] Added support for idProperty for temp-table schema --- src/progress.data.kendo.js | 4 ++++ src/progress.js | 5 +++++ src/progress.util.js | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/progress.data.kendo.js b/src/progress.data.kendo.js index c1565cf..f2c84c5 100644 --- a/src/progress.data.kendo.js +++ b/src/progress.data.kendo.js @@ -358,6 +358,10 @@ if (typeof (kendo) !== "undefined") { } } } + + if (transport.jsdo._resource.idProperty) { + fields[transport.jsdo._resource.idProperty].editable = false; + } return fields; }, _getInitialValues: function () { diff --git a/src/progress.js b/src/progress.js index 66a8b6e..40dd8d3 100644 --- a/src/progress.js +++ b/src/progress.js @@ -2225,6 +2225,11 @@ limitations under the License. this._resource.idProperty = properties[tableName].idProperty; } } + } else if (this._resource.schema + && this._resource.schema.properties + && this._resource.schema.properties[tableName] + && this._resource.schema.properties[tableName].idProperty) { + this._resource.idProperty = this._resource.schema.properties[tableName].idProperty; } // Add functions for operations to JSDO object diff --git a/src/progress.util.js b/src/progress.util.js index 9c13b45..4f687eb 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -280,6 +280,8 @@ limitations under the License. object.success = arg2; if (arg3 && arg3.xhr) { object.request = arg3; + } else if (arg3 && arg3.batch) { + object.request = arg3; } else { object.info = arg3; } From 5a2b27a0fec465157f43be796d4fc17644f5e5a3 Mon Sep 17 00:00:00 2001 From: Nicolette Date: Tue, 12 Jun 2018 12:16:48 -0400 Subject: [PATCH 19/84] adjustments for build configurations --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a108c7..398fa23 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ "typings/" ], "scripts": { + "build:jsdo": "mkdirp build && concat -o build/progress.jsdo.js src/progress.util.js src/progress.js src/progress.session.js src/auth/progress.auth.js src/auth/progress.auth.basic.js src/auth/progress.auth.form.js src/auth/progress.auth.sso.js", "test": "npm run build:jsdo && mocha --recursive", "test:smokes": "npm run build:jsdo && mocha test/smoke*.js", - "build:jsdo": "mkdirp build && concat -o build/progress.jsdo.js src/progress.util.js src/progress.js src/progress.session.js src/auth/progress.auth.js src/auth/progress.auth.basic.js src/auth/progress.auth.form.js src/auth/progress.auth.sso.js", + "test:tc-smokes": "npm run build:jsdo && mocha test/smoke*.js --recursive --reporter mocha-teamcity-reporter", "test:tc": "npm run build:jsdo && mocha --recursive --reporter mocha-teamcity-reporter" }, "repository": { From 60fdc76a9579d9f4e6c0c4392532374c78d8b1c1 Mon Sep 17 00:00:00 2001 From: edselg Date: Fri, 15 Jun 2018 17:43:48 -0400 Subject: [PATCH 20/84] Changed info.batch to request.batch --- packages/ng-datasource/src/progress.data.ng.ds.js | 8 ++++---- packages/ng-datasource/src/progress.data.ng.ds.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index a617423..d8f7efa 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -489,8 +489,8 @@ var DataSource = /** @class */ (function () { } else { // Non-Submit case - if (result.info.batch.operations && result.info.batch.operations.length > 0) { - result.info.batch.operations.forEach(function (operation) { + if (result.request && result.request.batch.operations && result.request.batch.operations.length > 0) { + result.request.batch.operations.forEach(function (operation) { _this._copyRecord(operation.response, responseData); // In case of multiple operations we want to merge those records pertaining // to different operations in a single dataset and is sent as part of the @@ -501,10 +501,10 @@ var DataSource = /** @class */ (function () { // Scenario where the saveChanges is invoked directly without any Submit/Non-Submit // service as the serviceURI. We will resolve with an empty object } - else if (result.info.batch.operations.length === 0) { + else if (result.request && result.request.batch.operations.length === 0) { resolve({}); } - else { // Reject promise if either of above cases are met + else { // Reject promise if either of above cases are not met reject(new Error(_this .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); } diff --git a/packages/ng-datasource/src/progress.data.ng.ds.ts b/packages/ng-datasource/src/progress.data.ng.ds.ts index 9a88203..8c656db 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.ts +++ b/packages/ng-datasource/src/progress.data.ng.ds.ts @@ -575,8 +575,8 @@ export class DataSource { resolve(responseData); } else { // Non-Submit case - if (result.info.batch.operations && result.info.batch.operations.length > 0) { - result.info.batch.operations.forEach((operation) => { + if (result.request && result.request.batch.operations && result.request.batch.operations.length > 0) { + result.request.batch.operations.forEach((operation) => { this._copyRecord(operation.response, responseData); // In case of multiple operations we want to merge those records pertaining // to different operations in a single dataset and is sent as part of the @@ -586,9 +586,9 @@ export class DataSource { resolve(promResponse); // Scenario where the saveChanges is invoked directly without any Submit/Non-Submit // service as the serviceURI. We will resolve with an empty object - } else if (result.info.batch.operations.length === 0) { + } else if (result.request && result.request.batch.operations.length === 0) { resolve({}); - } else { // Reject promise if either of above cases are met + } else { // Reject promise if either of above cases are not met reject(new Error(this .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); } From f6277f3bf68a29795d7812ea083a5bebbf945925 Mon Sep 17 00:00:00 2001 From: joshualan Date: Fri, 29 Jun 2018 17:46:46 -0400 Subject: [PATCH 21/84] Added a fix to not use constructor.name --- src/progress.util.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/progress.util.js b/src/progress.util.js index 4f687eb..0345a85 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -259,7 +259,12 @@ limitations under the License. object.result = arg2; object.info = arg3; } else { - objectName = arg1.constructor.name.toLowerCase(); + if (arg1 instanceof progress.data.JSDOSession) { + objectName = "jsdosession"; + } else if (arg1 instanceof progress.data.AuthenticationProvider) { + objectName = "authenticationprovider"; + } + if (!objectName) { objectName = typeof(arg1); } From 8f4af16f6224a19a784962940b51ef955d0cd55d Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Mon, 9 Jul 2018 02:06:00 -0400 Subject: [PATCH 22/84] Updated contributing.md --- contributing.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/contributing.md b/contributing.md index 377c3a9..2192349 100644 --- a/contributing.md +++ b/contributing.md @@ -32,13 +32,14 @@ If you want to implement a new feature yourself, consider submitting it to the < Contribute to the Code Base === -Before you submit a Pull Request, consider the following guidelines: -* By submitting a pull request, you represent that you have the right to license your contribution to Progress and the community, and agree by submitting the patch that your contributions are licensed under the progress/JSDO license. -Notwithstanding the above, we reserve the right to ask you to sign a Contributor License Agreement (CLA) for larger changes. +This project only accepts contributions via Pull Requests and only the project moderators can check in to the main repository branch. + +Before you submit a Pull Request, consider the following guidelines. +* Read and sign the JSDO Contributor License Agreement. * Search GitHub for an open or closed Pull Request that relates to your submission. * Clone the repository. ```bash - git clone git@github.com:CloudDataObject/JSDO.git + git clone git@github.com:CloudDataObject/JSDO.git -b develop ``` * Initialize the submodule. ```bash @@ -48,20 +49,25 @@ Notwithstanding the above, we reserve the right to ask you to sign a Gitflow branching model so you will have to branch from our develop branch. +* Make your changes in a new `git` branch. We use the Gitflow branching model. * Commit your changes and create a descriptive commit message (the commit message is used to generate release notes). ```bash git commit -a ``` +* Ensure your changes pass the Mocha tests for the JSDO. +```bash + npm install + npm test +``` * Push your branch to GitHub. ```bash git push origin my-fix-branch ``` -* In GitHub, send a Pull Request to JSDO:master. +* In GitHub, send a Pull Request to JSDO:develop. * If we suggest changes, you can modify your branch, rebase, and force a new push to your GitHub repository to update the Pull Request. ```bash - git rebase master -i + git rebase develop -i git push -f ``` @@ -75,7 +81,7 @@ When the patch is reviewed and merged, you can safely delete your branch and pul ``` * Check out the develop branch. ```bash - git checkout master -f + git checkout develop -f ``` * Delete the local branch. ```bash @@ -83,7 +89,7 @@ When the patch is reviewed and merged, you can safely delete your branch and pul ``` * Update your develop branch with the latest upstream version. ``` - git pull --ff upstream master + git pull --ff upstream develop ``` [Back to Top][1] From 49db6ae8fed2adfbb46fe5868d8344fa8f2f1e5a Mon Sep 17 00:00:00 2001 From: joshualan Date: Tue, 10 Jul 2018 12:05:34 -0400 Subject: [PATCH 23/84] Updated to consider the JSDO and condensed code --- src/progress.util.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/progress.util.js b/src/progress.util.js index 0345a85..d19ccfd 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -259,27 +259,21 @@ limitations under the License. object.result = arg2; object.info = arg3; } else { + // Map some object name to use a particular property name + // We should probably spend some time down the line to truly use + // ES6 promises. if (arg1 instanceof progress.data.JSDOSession) { objectName = "jsdosession"; } else if (arg1 instanceof progress.data.AuthenticationProvider) { - objectName = "authenticationprovider"; - } - - if (!objectName) { + objectName = "provider"; + } else if (arg1 instanceof progress.data.JSDO) { + objectName = "jsdo"; + } else if (typeof(arg1) === "number") { + objectName = "result"; + } else { objectName = typeof(arg1); } - // Map some object name to use a particular property name - switch (objectName) { - case "authenticationprovider": - objectName = "provider" - break; - case "number": - objectName = "result" - break; - default: - break; - } object[objectName] = arg1; if (objectName === "jsdo") { object.success = arg2; From 49b130aee8f150890dc6535df9709e65220e5130 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 10 Jul 2018 13:46:03 -0400 Subject: [PATCH 24/84] Update contributing.md --- contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing.md b/contributing.md index 2192349..06b6a28 100644 --- a/contributing.md +++ b/contributing.md @@ -39,7 +39,7 @@ Before you submit a Pull Request, consider the following guidelines. * Search GitHub for an open or closed Pull Request that relates to your submission. * Clone the repository. ```bash - git clone git@github.com:CloudDataObject/JSDO.git -b develop + git clone git@github.com:progress/JSDO.git -b develop ``` * Initialize the submodule. ```bash From 9586f033dc41812095387164a7cdc5bec2563c1c Mon Sep 17 00:00:00 2001 From: joshualan Date: Tue, 10 Jul 2018 19:06:24 -0400 Subject: [PATCH 25/84] Added a change to only call count function when specifically doing paging --- packages/ng-datasource/src/progress.data.ng.ds.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.ts b/packages/ng-datasource/src/progress.data.ng.ds.ts index 8c656db..291ab87 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.ts +++ b/packages/ng-datasource/src/progress.data.ng.ds.ts @@ -354,7 +354,10 @@ export class DataSource { const data = this.getJsdoData(); - if ((this._options.countFnName && this._options.countFnName !== undefined) + // Only call count() function if paging is being used + // Paging is only used if the skip and top is being used during the fill. + if (typeof params !== "undefined" && + (typeof this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") && !(params.skip === 0 && params.top > data.length)) { // Server-side operations this.getRecCount( this._options.countFnName, From 69ae2cb0cfc2fb0237fc32f6f0c5cd252148d4d3 Mon Sep 17 00:00:00 2001 From: edselg Date: Fri, 20 Jul 2018 14:46:05 -0400 Subject: [PATCH 26/84] Add packages needed fo Mocha/Chai testing --- .gitignore | 1 + package.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 93c27fe..0eaa02c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .vscode +package-lock.json tmp tslint.json node_modules/ diff --git a/package.json b/package.json index 398fa23..5037c0c 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,14 @@ "peerDependencies": {}, "optionalDependencies": {}, "devDependencies": { + "base-64": "^0.1.0", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "concat": "^1.0.3", "mkdirp": "^0.5.1", "mocha": "^5.2.0", - "mocha-teamcity-reporter": "^2.4.0" + "mocha-teamcity-reporter": "^2.4.0", + "node-localstorage": "^1.3.1", + "xmlhttprequest": "^1.8.0" } } From 766b479ac9923fec1302afb05f8962f036ebaa01 Mon Sep 17 00:00:00 2001 From: edselg Date: Fri, 20 Jul 2018 17:37:25 -0400 Subject: [PATCH 27/84] Move packages to regular dependencies --- package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5037c0c..4bf191e 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,17 @@ "homepage": "https://github.com/progress/JSDO#readme", "dependencies": {}, "peerDependencies": {}, - "optionalDependencies": {}, - "devDependencies": { + "optionalDependencies": { "base-64": "^0.1.0", + "node-localstorage": "^1.3.1", + "xmlhttprequest": "^1.8.0" + }, + "devDependencies": { "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "concat": "^1.0.3", "mkdirp": "^0.5.1", "mocha": "^5.2.0", - "mocha-teamcity-reporter": "^2.4.0", - "node-localstorage": "^1.3.1", - "xmlhttprequest": "^1.8.0" + "mocha-teamcity-reporter": "^2.4.0" } } From 4f822fa4357eadb647a348bd8f6ae9737e426f79 Mon Sep 17 00:00:00 2001 From: edselg Date: Fri, 20 Jul 2018 17:49:37 -0400 Subject: [PATCH 28/84] Move nodejs dependencies to devDependencies --- package.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4bf191e..5037c0c 100644 --- a/package.json +++ b/package.json @@ -36,17 +36,16 @@ "homepage": "https://github.com/progress/JSDO#readme", "dependencies": {}, "peerDependencies": {}, - "optionalDependencies": { - "base-64": "^0.1.0", - "node-localstorage": "^1.3.1", - "xmlhttprequest": "^1.8.0" - }, + "optionalDependencies": {}, "devDependencies": { + "base-64": "^0.1.0", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "concat": "^1.0.3", "mkdirp": "^0.5.1", "mocha": "^5.2.0", - "mocha-teamcity-reporter": "^2.4.0" + "mocha-teamcity-reporter": "^2.4.0", + "node-localstorage": "^1.3.1", + "xmlhttprequest": "^1.8.0" } } From 1a0654e2c6c8bee9335416d23343899aaa3f7f3a Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Mon, 20 Aug 2018 15:39:22 -0400 Subject: [PATCH 29/84] Added a bug fix to ADAS-7282 --- packages/ng-datasource/src/progress.data.ng.ds.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index d8f7efa..796ee7d 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -289,7 +289,10 @@ var DataSource = /** @class */ (function () { } _this._initFromServer = true; var data = _this.getJsdoData(); - if ((_this._options.countFnName && _this._options.countFnName !== undefined) + // Only call count() function if paging is being used + // Paging is only used if the skip and top is being used during the fill. + if (typeof params !== "undefined" && + (typeof this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") && !(params.skip === 0 && params.top > data.length)) { // Server-side operations _this.getRecCount(_this._options.countFnName, { filter: result.request.objParam ? result.request.objParam.filter : undefined }) .then(function (res) { From d2e4245067335983aead85201fc833bbaa89121d Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Mon, 20 Aug 2018 16:32:35 -0400 Subject: [PATCH 30/84] Add floating underscore --- packages/ng-datasource/src/progress.data.ng.ds.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index 796ee7d..97039d7 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -292,7 +292,7 @@ var DataSource = /** @class */ (function () { // Only call count() function if paging is being used // Paging is only used if the skip and top is being used during the fill. if (typeof params !== "undefined" && - (typeof this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") + (typeof _this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") && !(params.skip === 0 && params.top > data.length)) { // Server-side operations _this.getRecCount(_this._options.countFnName, { filter: result.request.objParam ? result.request.objParam.filter : undefined }) .then(function (res) { From 0192c67e5bd07cac770f04fbdd404c7ab7d4cb2c Mon Sep 17 00:00:00 2001 From: Nicolette Date: Tue, 21 Aug 2018 14:28:28 -0400 Subject: [PATCH 31/84] fix + mocha tests --- src/progress.util.js | 2 +- test/regressions/ADAS-7828.js | 143 ++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 test/regressions/ADAS-7828.js diff --git a/src/progress.util.js b/src/progress.util.js index d19ccfd..948bb55 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -703,7 +703,7 @@ limitations under the License. format = "'{1}'"; value = value.replace(/'/g, "~'"); } else if (type === DATE_OBJECT_TYPE) { - ablType = tableRef._getABLType(field); + ablType = tableRef._getABLType(filter.field); if (ablType === "DATE") { format = "DATE({1:MM, dd, yyyy})"; } else if (ablType === "DATETIME-TZ") { diff --git a/test/regressions/ADAS-7828.js b/test/regressions/ADAS-7828.js new file mode 100644 index 0000000..acda61e --- /dev/null +++ b/test/regressions/ADAS-7828.js @@ -0,0 +1,143 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); + +const progress = require("../../build/progress.jsdo").progress; + +chai.use(chaiAsPromised); + +describe('JSDO Smoke Tests', () => { + // INFORMATION YEAH + const options = { + catalogURI: "http://localhost:8810/datetimebug/static/dtService.json", + serviceURI: "http://localhost:8810/datetimebug/", + resourceName: "MySalesRep", + authenticationModel: "anonymous" + }; + + const SalesRep = "SmokeTest3000"; + const SecondSalesRep = "SmokeTest3001"; + const CustDate = "1992-11-12"; + const SecondCustDate = "1992-09-22"; + + let session, + jsdo; + + before(function (done) { + errFunc = (err) => done(err); + + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => { + jsdo = new progress.data.JSDO({ name: options.resourceName }); + return jsdo.fill(); + }, errFunc) + .then(() => { + done(); + }, errFunc); + }); + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + describe('JFP Tests', function () { + // Clean up the backend to make sure that there isn't an salesrep record with a CustNum of 3000 + // already in store + function clean(callback) { + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.SalesRep === SalesRep || salesrep.data.SalesRep === SecondSalesRep) { + salesrep.remove(); + } + }); + + jsdo.saveChanges().then(() => { + return jsdo.fill(); + }).then(() => callback()); + } + + before(function (done) { + clean(done); + }); + + after(function (done) { + clean(done); + }); + + it('should successfully create records on the backend', function () { + jsdo.ttSalesrep.add({ + SalesRep: SalesRep, + BirthDate: CustDate + }); + + jsdo.ttSalesrep.add({ + SalesRep: SecondSalesRep, + BirthDate: SecondCustDate + }); + let save = jsdo.saveChanges().then((object) => { + + return jsdo.fill(); + + }).then((object) => { + let found = false; + let secondfound = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + if (salesrep.data.BirthDate == SecondCustDate) { + secondfound = true; + } + }); + return found && secondfound; + + }); + + return expect(save).to.eventually.be.true; + }); + + it('should successfully filter using a js date object on a hyphenated field', function () { + var d = new Date("11/12/1992"); + let filter = jsdo.fill({ filter: { field: "BirthDate", operator: "eq", value: d } }) + .then((object) => { + let found = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + }); + return found; + + }); + return expect(filter).to.eventually.be.true; + }); + + it('should successfully filter using multiple js date objects on a hyphenated field', function () { + var d = new Date("11/12/1992"); + var d2 = new Date("09/22/1992"); + let filter = jsdo.fill({ + logic: "or", + filters: [ + { field: "BirthDate", operator: "eq", value: d }, + { field: "BirthDate", operator: "eq", value: d2 } + ] + }) + .then((object) => { + let found = false; + let secondfound = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + if (salesrep.data.BirthDate == SecondCustDate) { + secondfound = true; + } + }); + return found && secondfound; + + }); + return expect(filter).to.eventually.be.true; + }); + }); +}); \ No newline at end of file From e5cde097ea176ea61220bdc665c37b26ffd1d636 Mon Sep 17 00:00:00 2001 From: Nicolette Date: Tue, 21 Aug 2018 14:34:50 -0400 Subject: [PATCH 32/84] fix ip --- test/regressions/ADAS-7828.JFP.DATE.js | 143 +++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 test/regressions/ADAS-7828.JFP.DATE.js diff --git a/test/regressions/ADAS-7828.JFP.DATE.js b/test/regressions/ADAS-7828.JFP.DATE.js new file mode 100644 index 0000000..8c37d82 --- /dev/null +++ b/test/regressions/ADAS-7828.JFP.DATE.js @@ -0,0 +1,143 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); + +const progress = require("../../build/progress.jsdo").progress; + +chai.use(chaiAsPromised); + +describe('JSDO Setup', () => { + // INFORMATION YEAH + const options = { + catalogURI: "http://172.30.112.74:8810/datetimebug/static/dtService.json", + serviceURI: "http://172.30.112.74:8810/datetimebug/", + resourceName: "MySalesRep", + authenticationModel: "anonymous" + }; + + const SalesRep = "SmokeTest3000"; + const SecondSalesRep = "SmokeTest3001"; + const CustDate = "1992-11-12"; + const SecondCustDate = "1992-09-22"; + + let session, + jsdo; + + before(function (done) { + errFunc = (err) => done(err); + + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => { + jsdo = new progress.data.JSDO({ name: options.resourceName }); + return jsdo.fill(); + }, errFunc) + .then(() => { + done(); + }, errFunc); + }); + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + describe('JFP Tests', function () { + // Clean up the backend to make sure that there isn't an salesrep record with a CustNum of 3000 + // already in store + function clean(callback) { + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.SalesRep === SalesRep || salesrep.data.SalesRep === SecondSalesRep) { + salesrep.remove(); + } + }); + + jsdo.saveChanges().then(() => { + return jsdo.fill(); + }).then(() => callback()); + } + + before(function (done) { + clean(done); + }); + + after(function (done) { + clean(done); + }); + + it('should successfully create records on the backend', function () { + jsdo.ttSalesrep.add({ + SalesRep: SalesRep, + BirthDate: CustDate + }); + + jsdo.ttSalesrep.add({ + SalesRep: SecondSalesRep, + BirthDate: SecondCustDate + }); + let save = jsdo.saveChanges().then((object) => { + + return jsdo.fill(); + + }).then((object) => { + let found = false; + let secondfound = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + if (salesrep.data.BirthDate == SecondCustDate) { + secondfound = true; + } + }); + return found && secondfound; + + }); + + return expect(save).to.eventually.be.true; + }); + + it('should successfully filter using a js date object on a hyphenated field', function () { + var d = new Date("11/12/1992"); + let filter = jsdo.fill({ filter: { field: "BirthDate", operator: "eq", value: d } }) + .then((object) => { + let found = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + }); + return found; + + }); + return expect(filter).to.eventually.be.true; + }); + + it('should successfully filter using multiple js date objects on a hyphenated field', function () { + var d = new Date("11/12/1992"); + var d2 = new Date("09/22/1992"); + let filter = jsdo.fill({ + logic: "or", + filters: [ + { field: "BirthDate", operator: "eq", value: d }, + { field: "BirthDate", operator: "eq", value: d2 } + ] + }) + .then((object) => { + let found = false; + let secondfound = false; + jsdo.ttSalesrep.foreach((salesrep) => { + if (salesrep.data.BirthDate === CustDate) { + found = true; + } + if (salesrep.data.BirthDate == SecondCustDate) { + secondfound = true; + } + }); + return found && secondfound; + + }); + return expect(filter).to.eventually.be.true; + }); + }); +}); \ No newline at end of file From d60086df6d0b8861961d43cd522d6fe51a03ba1a Mon Sep 17 00:00:00 2001 From: Nicolette Date: Tue, 21 Aug 2018 14:37:33 -0400 Subject: [PATCH 33/84] renamed --- test/regressions/ADAS-7828.js | 143 ---------------------------------- 1 file changed, 143 deletions(-) delete mode 100644 test/regressions/ADAS-7828.js diff --git a/test/regressions/ADAS-7828.js b/test/regressions/ADAS-7828.js deleted file mode 100644 index acda61e..0000000 --- a/test/regressions/ADAS-7828.js +++ /dev/null @@ -1,143 +0,0 @@ -const chai = require('chai'); -const expect = chai.expect; -const chaiAsPromised = require("chai-as-promised"); - -const progress = require("../../build/progress.jsdo").progress; - -chai.use(chaiAsPromised); - -describe('JSDO Smoke Tests', () => { - // INFORMATION YEAH - const options = { - catalogURI: "http://localhost:8810/datetimebug/static/dtService.json", - serviceURI: "http://localhost:8810/datetimebug/", - resourceName: "MySalesRep", - authenticationModel: "anonymous" - }; - - const SalesRep = "SmokeTest3000"; - const SecondSalesRep = "SmokeTest3001"; - const CustDate = "1992-11-12"; - const SecondCustDate = "1992-09-22"; - - let session, - jsdo; - - before(function (done) { - errFunc = (err) => done(err); - - progress.data.getSession(options).then((object) => { - session = object.jsdosession; - }).then(() => { - jsdo = new progress.data.JSDO({ name: options.resourceName }); - return jsdo.fill(); - }, errFunc) - .then(() => { - done(); - }, errFunc); - }); - - // Logout of the session after we are done - after((done) => { - session.invalidate().then(() => done()); - }); - - describe('JFP Tests', function () { - // Clean up the backend to make sure that there isn't an salesrep record with a CustNum of 3000 - // already in store - function clean(callback) { - jsdo.ttSalesrep.foreach((salesrep) => { - if (salesrep.data.SalesRep === SalesRep || salesrep.data.SalesRep === SecondSalesRep) { - salesrep.remove(); - } - }); - - jsdo.saveChanges().then(() => { - return jsdo.fill(); - }).then(() => callback()); - } - - before(function (done) { - clean(done); - }); - - after(function (done) { - clean(done); - }); - - it('should successfully create records on the backend', function () { - jsdo.ttSalesrep.add({ - SalesRep: SalesRep, - BirthDate: CustDate - }); - - jsdo.ttSalesrep.add({ - SalesRep: SecondSalesRep, - BirthDate: SecondCustDate - }); - let save = jsdo.saveChanges().then((object) => { - - return jsdo.fill(); - - }).then((object) => { - let found = false; - let secondfound = false; - jsdo.ttSalesrep.foreach((salesrep) => { - if (salesrep.data.BirthDate === CustDate) { - found = true; - } - if (salesrep.data.BirthDate == SecondCustDate) { - secondfound = true; - } - }); - return found && secondfound; - - }); - - return expect(save).to.eventually.be.true; - }); - - it('should successfully filter using a js date object on a hyphenated field', function () { - var d = new Date("11/12/1992"); - let filter = jsdo.fill({ filter: { field: "BirthDate", operator: "eq", value: d } }) - .then((object) => { - let found = false; - jsdo.ttSalesrep.foreach((salesrep) => { - if (salesrep.data.BirthDate === CustDate) { - found = true; - } - }); - return found; - - }); - return expect(filter).to.eventually.be.true; - }); - - it('should successfully filter using multiple js date objects on a hyphenated field', function () { - var d = new Date("11/12/1992"); - var d2 = new Date("09/22/1992"); - let filter = jsdo.fill({ - logic: "or", - filters: [ - { field: "BirthDate", operator: "eq", value: d }, - { field: "BirthDate", operator: "eq", value: d2 } - ] - }) - .then((object) => { - let found = false; - let secondfound = false; - jsdo.ttSalesrep.foreach((salesrep) => { - if (salesrep.data.BirthDate === CustDate) { - found = true; - } - if (salesrep.data.BirthDate == SecondCustDate) { - secondfound = true; - } - }); - return found && secondfound; - - }); - return expect(filter).to.eventually.be.true; - }); - }); -}); \ No newline at end of file From 59c02d118cc17f5c684b1b206fd59381c211f2f6 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 14:49:52 -0400 Subject: [PATCH 34/84] Initial commit --- .gitignore | 3 +- packages/ng-datasource/package.json | 11 ++- .../ng-datasource/regressions/ADAS-7282.js | 90 +++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100755 packages/ng-datasource/regressions/ADAS-7282.js diff --git a/.gitignore b/.gitignore index 93c27fe..fcc1fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ tslint.json node_modules/ scratch1/ scratch2/ -build/ \ No newline at end of file +build/ +packages/ng-datasource/package-lock.json diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index deb0891..0d8d379 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -11,6 +11,7 @@ "typings/" ], "scripts": { + "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { @@ -40,5 +41,13 @@ "rxjs": "^5.5.6" }, "peerDependencies": {}, - "optionalDependencies": {} + "optionalDependencies": {}, + "devDependencies": { + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "concat": "^1.0.3", + "mkdirp": "^0.5.1", + "mocha": "^5.2.0", + "mocha-teamcity-reporter": "^2.4.0" + } } diff --git a/packages/ng-datasource/regressions/ADAS-7282.js b/packages/ng-datasource/regressions/ADAS-7282.js new file mode 100755 index 0000000..29899f5 --- /dev/null +++ b/packages/ng-datasource/regressions/ADAS-7282.js @@ -0,0 +1,90 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); +const progress = require("@progress/jsdo-core").progress; +const DataSource = require("@progress/jsdo-node").DataSource; + +chai.use(chaiAsPromised); + +// This bug relates to ADAS-7282 +// This removes the functionality from the DataSource of count always being used +// if there was a count functionality present in the catalog, which is bad. + +//First describe +describe('ADAS-7282: DataSource invokes count operation bug', function () { + //options all the info required for creating a jsdo session + const options = { + serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", + catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/SportsService3.json", + resourceName: "SalesRep", + authenticationModel: "anonymous", + tableRef: "ttSalesRep" + }; + + //define your variables required for the tests below + let session, + jsdo, + dataSource; + + //before: getSession + before(function (done) { + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => done(), () => done()); + }); + + //after: Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + + //Second describe for CRUD tests + describe('JSDO Instantiation Tests', function () { + it('should successfully create a JSDO', function () { + jsdo = new progress.data.JSDO({ name: options.resourceName }); + expect(jsdo).to.be.an.instanceof(progress.data.JSDO); + dataSource = new DataSource({ + jsdo: jsdo, + tableRef: "ttSalesrep" + }); + }); + }); + + //1st Read without parameters + describe('read() without params', function () { + let data; + + //1st it () + it('should successfully call read()', function (done) { + let read = dataSource.read().toPromise() + .then((mydata) => { + return true; + }, (error) => { + return expect.fail(null, null, 'read({}) did not succeed: ' + error); + + }); + + expect(read).to.eventually.be.true.notify(done); + }); + + + //2nd it () + it('should successfully call read({})', function (done) { + let read = dataSource.read({}).toPromise() + .then((mydata) => { + data = mydata.data; + return true; + }, (error) => { + return expect.fail(null, null, 'read({}) did not succeed: ' + error); + }); + + expect(read).to.eventually.be.true.notify(done); + }); + + it('should have a read() that successfully grabs data', function () { + expect(data).to.be.an.instanceOf(Array); + }); + }); + +}); From 9f488227e9b177a7aa41688b3a364eb22e591003 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 14:51:37 -0400 Subject: [PATCH 35/84] Updated location and package.json --- packages/ng-datasource/package.json | 2 +- packages/ng-datasource/{ => test}/regressions/ADAS-7282.js | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/ng-datasource/{ => test}/regressions/ADAS-7282.js (100%) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 0d8d379..9e63af9 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -12,7 +12,7 @@ ], "scripts": { "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "npm run build:ds && mocha --recursive" }, "repository": { "type": "git", diff --git a/packages/ng-datasource/regressions/ADAS-7282.js b/packages/ng-datasource/test/regressions/ADAS-7282.js similarity index 100% rename from packages/ng-datasource/regressions/ADAS-7282.js rename to packages/ng-datasource/test/regressions/ADAS-7282.js From 156934b9056c81957825b49a1497fce33a5af266 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 14:54:50 -0400 Subject: [PATCH 36/84] Added dependencies and changed files or whatever --- packages/ng-datasource/package.json | 5 ++++- packages/ng-datasource/test/regressions/ADAS-7282.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 9e63af9..698fc1c 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -38,7 +38,10 @@ "dependencies": { "@angular/core": "^5.2.1", "@progress/jsdo-nativescript": "^5.0.0-0", - "rxjs": "^5.5.6" + "base-64": "^0.1.0", + "node-localstorage": "^1.3.1", + "rxjs": "^5.5.6", + "xmlhttprequest": "^1.8.0" }, "peerDependencies": {}, "optionalDependencies": {}, diff --git a/packages/ng-datasource/test/regressions/ADAS-7282.js b/packages/ng-datasource/test/regressions/ADAS-7282.js index 29899f5..4fca16d 100755 --- a/packages/ng-datasource/test/regressions/ADAS-7282.js +++ b/packages/ng-datasource/test/regressions/ADAS-7282.js @@ -2,7 +2,7 @@ const chai = require('chai'); const expect = chai.expect; const chaiAsPromised = require("chai-as-promised"); const progress = require("@progress/jsdo-core").progress; -const DataSource = require("@progress/jsdo-node").DataSource; +const DataSource = require("../../build/progress.data.node").DataSource; chai.use(chaiAsPromised); From 9c4447db9d5da65f9cd4376c0b3c2b5837d75d50 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 14:58:39 -0400 Subject: [PATCH 37/84] Added configuration stuff --- packages/ng-datasource/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 698fc1c..fc60c11 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -12,7 +12,10 @@ ], "scripts": { "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", - "test": "npm run build:ds && mocha --recursive" + "test": "npm run build:ds && mocha --recursive", + "test:smokes": "npm run build:ds && mocha test/smoke*.js", + "test:tc": "npm run build:ds && mocha --recursive --reporter mocha-teamcity-reporter", + "test:tc-smokes": "npm run build:ds && mocha test/smoke*.js --recursive --reporter mocha-teamcity-reporter" }, "repository": { "type": "git", From 373c87f3f92b1d712dde096415841ddefcebac36 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 15:49:47 -0400 Subject: [PATCH 38/84] Put in the correct location --- packages/node/package.json | 16 ++++++++++++++-- .../test/regressions/ADAS-7282.js | 0 2 files changed, 14 insertions(+), 2 deletions(-) rename packages/{ng-datasource => node}/test/regressions/ADAS-7282.js (100%) diff --git a/packages/node/package.json b/packages/node/package.json index 56db64d..1f5d37d 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -11,7 +11,11 @@ "typings/" ], "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", + "test": "npm run build:ds && mocha --recursive", + "test:smokes": "npm run build:ds && mocha test/smoke*.js", + "test:tc": "npm run build:ds && mocha --recursive --reporter mocha-teamcity-reporter", + "test:tc-smokes": "npm run build:ds && mocha test/smoke*.js --recursive --reporter mocha-teamcity-reporter" }, "repository": { "type": "git", @@ -41,5 +45,13 @@ "xmlhttprequest": "^1.8.0" }, "peerDependencies": {}, - "optionalDependencies": {} + "optionalDependencies": {}, + "devDependencies": { + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "concat": "^1.0.3", + "mkdirp": "^0.5.1", + "mocha": "^5.2.0", + "mocha-teamcity-reporter": "^2.4.0" + } } diff --git a/packages/ng-datasource/test/regressions/ADAS-7282.js b/packages/node/test/regressions/ADAS-7282.js similarity index 100% rename from packages/ng-datasource/test/regressions/ADAS-7282.js rename to packages/node/test/regressions/ADAS-7282.js From 2e6d093d3db493fa0900f95cf5874e99fdacefb6 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 15:53:22 -0400 Subject: [PATCH 39/84] Updated location of progress.data.ng.ds.js --- packages/node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/package.json b/packages/node/package.json index 1f5d37d..b7f3eb3 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -11,7 +11,7 @@ "typings/" ], "scripts": { - "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", + "build:ds": "mkdirp build && concat -o build/progress.data.node.js ../ng-datasource/src/progress.data.ng.ds.js", "test": "npm run build:ds && mocha --recursive", "test:smokes": "npm run build:ds && mocha test/smoke*.js", "test:tc": "npm run build:ds && mocha --recursive --reporter mocha-teamcity-reporter", From 3c789a5c058564959d7099cbe53508030c8350bd Mon Sep 17 00:00:00 2001 From: Edsel Garcia Cyntje Date: Tue, 21 Aug 2018 17:28:42 -0400 Subject: [PATCH 40/84] Add test for invoke updating JSDO memory --- test-services/Sports/Customer.cls | 287 ++++++++++++++++++++++++++++++ test-services/Sports/customer.i | 27 +++ test/smoke.invoke.js | 222 +++++++++++++++++++++++ 3 files changed, 536 insertions(+) create mode 100644 test-services/Sports/Customer.cls create mode 100644 test-services/Sports/customer.i create mode 100644 test/smoke.invoke.js diff --git a/test-services/Sports/Customer.cls b/test-services/Sports/Customer.cls new file mode 100644 index 0000000..49b557d --- /dev/null +++ b/test-services/Sports/Customer.cls @@ -0,0 +1,287 @@ +@program FILE(name="Customer.cls", module="AppServer"). +@openapi.openedge.export FILE(type="REST", executionMode="singleton", useReturnValue="false", writeDataSetBeforeImage="false"). +@progress.service.resource FILE(name="Customer", URI="/Customer", schemaName="dsCustomer", schemaFile="Sports/AppServer/customer.i"). + +USING Progress.Lang.*. + +USING OpenEdge.BusinessLogic.BusinessEntity. +USING Progress.Json.ObjectModel.*. + +BLOCK-LEVEL ON ERROR UNDO, THROW. + +CLASS Customer INHERITS BusinessEntity: + + {"customer.i"} + + DEFINE DATA-SOURCE srcCustomer FOR Customer. + + DEFINE VARIABLE iSeq AS INTEGER NO-UNDO. + + CONSTRUCTOR PUBLIC Customer(): + + DEFINE VAR hDataSourceArray AS HANDLE NO-UNDO EXTENT 1. + DEFINE VAR cSkipListArray AS CHAR NO-UNDO EXTENT 1. + + SUPER (DATASET dsCustomer:HANDLE). + + /* Data Source for each table in dataset. + Should be in table order as defined in DataSet */ + hDataSourceArray[1] = DATA-SOURCE srcCustomer:HANDLE. + + /* Skip-list entry array for each table in DataSet. + Should be in temp-table order as defined in DataSet */ + /* Each skip-list entry is a comma-separated list of field names + to be ignored in the CREATE statement */ + + cSkipListArray[1] = "CustNum". + + THIS-OBJECT:ProDataSource = hDataSourceArray. + THIS-OBJECT:SkipList = cSkipListArray. + + END CONSTRUCTOR. + + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="read", URI="?filter=~{filter~}", alias="", mediaType="application/json"). + @openapi.openedge.method.property (name="mappingType", value="JFP"). + @openapi.openedge.method.property (name="capabilities", value="ablFilter,top,skip,id,orderBy"). + METHOD PUBLIC VOID ReadCustomer( + INPUT filter AS CHARACTER, + OUTPUT DATASET dsCustomer): + + IF filter BEGINS "~{" THEN + THIS-OBJECT:JFPFillMethod (INPUT filter). + ELSE + DO: + BUFFER ttCustomer:HANDLE:BATCH-SIZE = 0. + BUFFER ttCustomer:SET-CALLBACK ("AFTER-ROW-FILL", "AddIdField"). + SUPER:ReadData(filter). + END. + END METHOD. + + /* Other CUD and Submit operation methods */ + + /*------------------------------------------------------------------------------ + Purpose: Create one or more new records + Notes: + ------------------------------------------------------------------------------*/ + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="create", URI="", alias="", mediaType="application/json"). + METHOD PUBLIC VOID CreateCustomer(INPUT-OUTPUT DATASET dsCustomer): + + SUPER:CreateData(DATASET dsCustomer BY-REFERENCE). + END METHOD. + + /*------------------------------------------------------------------------------ + Purpose: Update one or more records + Notes: + ------------------------------------------------------------------------------*/ + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="update", URI="", alias="", mediaType="application/json"). + METHOD PUBLIC VOID UpdateCustomer(INPUT-OUTPUT DATASET dsCustomer): + + SUPER:UpdateData(DATASET dsCustomer BY-REFERENCE). + END METHOD. + + /*------------------------------------------------------------------------------ + Purpose: Delete a record + Notes: + ------------------------------------------------------------------------------*/ + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="delete", URI="", alias="", mediaType="application/json"). + METHOD PUBLIC VOID DeleteCustomer(INPUT-OUTPUT DATASET dsCustomer): + + SUPER:DeleteData(DATASET dsCustomer BY-REFERENCE). + END METHOD. + + + METHOD PRIVATE VOID JFPFillMethod(INPUT filter AS CHARACTER): + + DEFINE VARIABLE jsonParser AS ObjectModelParser NO-UNDO. + DEFINE VARIABLE jsonObject AS JsonObject NO-UNDO. + DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. + DEFINE VARIABLE hQuery AS HANDLE NO-UNDO. + DEFINE VARIABLE lUseReposition AS LOGICAL NO-UNDO. + DEFINE VARIABLE iCount AS INTEGER NO-UNDO. + DEFINE VARIABLE ablFilter AS CHARACTER NO-UNDO. + DEFINE VARIABLE id AS CHARACTER INITIAL ? NO-UNDO. + DEFINE VARIABLE iMaxRows AS INTEGER INITIAL ? NO-UNDO. + DEFINE VARIABLE iSkipRows AS INTEGER INITIAL ? NO-UNDO. + DEFINE VARIABLE cOrderBy AS CHARACTER INITIAL "" NO-UNDO. + + /* purge any existing data */ + EMPTY TEMP-TABLE ttCustomer. + + jsonParser = NEW ObjectModelParser(). + jsonObject = CAST(jsonParser:Parse(filter), jsonObject). + iMaxRows = jsonObject:GetInteger("top") NO-ERROR. + iSkipRows = jsonObject:GetInteger("skip") NO-ERROR. + ablFilter = jsonObject:GetCharacter("ablFilter") NO-ERROR. + id = jsonObject:GetCharacter("id") NO-ERROR. + cOrderBy = jsonObject:GetCharacter("orderBy") NO-ERROR. + cWhere = "WHERE " + ablFilter NO-ERROR. + + IF cOrderBy > "" THEN + DO: + cOrderBy = REPLACE(cOrderBy, ",", " by "). + cOrderBy = "by " + cOrderBy + " ". + /* NOTE: id and seq fields should be removed from + cWhere and cOrderBy */ + cOrderBy = REPLACE(cOrderBy, "by id desc", ""). + cOrderBy = REPLACE(cOrderBy, "by id ", ""). + cOrderBy = REPLACE(cOrderBy, "by seq desc", ""). + cOrderBy = REPLACE(cOrderBy, "by seq ", ""). + END. + + lUseReposition = iSkipRows <> ?. + + IF iMaxRows <> ? AND iMaxRows > 0 THEN + DO: + BUFFER ttCustomer:HANDLE:BATCH-SIZE = iMaxRows. + END. + ELSE + DO: + IF id > "" THEN + BUFFER ttCustomer:HANDLE:BATCH-SIZE = 1. + ELSE + BUFFER ttCustomer:HANDLE:BATCH-SIZE = 0. + END. + + BUFFER ttCustomer:ATTACH-DATA-SOURCE(DATA-SOURCE srcCustomer:HANDLE). + + IF cOrderBy = ? THEN cOrderBy = "". + cWhere = IF cWhere > "" THEN (cWhere + " " + cOrderBy) + ELSE ("WHERE " + cOrderBy). + DATA-SOURCE srcCustomer:FILL-WHERE-STRING = cWhere. + + IF lUseReposition THEN + DO: + hQuery = DATA-SOURCE srcCustomer:QUERY. + hQuery:QUERY-OPEN. + + IF id > "" AND id <> "?" THEN + DO: + hQuery:REPOSITION-TO-ROWID(TO-ROWID(id)). + END. + ELSE IF iSkipRows <> ? AND iSkipRows > 0 THEN + DO: + hQuery:REPOSITION-TO-ROW(iSkipRows). + IF NOT AVAILABLE Customer THEN + hQuery:GET-NEXT() NO-ERROR. + END. + + iCount = 0. + REPEAT WHILE NOT hQuery:QUERY-OFF-END AND iCount < iMaxRows: + hQuery:GET-NEXT () NO-ERROR. + IF AVAILABLE Customer THEN + DO: + CREATE ttCustomer. + BUFFER-COPY Customer TO ttCustomer. + ASSIGN + ttCustomer.id = STRING(ROWID(Customer)) + iSeq = iSeq + 1 + ttCustomer.seq = iSeq. + END. + iCount = iCount + 1. + END. + END. + ELSE + DO: + IF id > "" THEN DATA-SOURCE srcCustomer:RESTART-ROWID(1) + = TO-ROWID ((id)). + BUFFER ttCustomer:SET-CALLBACK ("AFTER-ROW-FILL", "AddIdField"). + DATASET dsCustomer:FILL(). + END. + + FINALLY: + BUFFER ttCustomer:DETACH-DATA-SOURCE(). + END FINALLY. + + END METHOD. + + METHOD PUBLIC VOID AddIdField (INPUT DATASET dsCustomer): + ASSIGN + ttCustomer.id = STRING(ROWID(Customer)) + iSeq = iSeq + 1 + ttCustomer.seq = iSeq. + END. + + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false"). + @progress.service.resourceMapping(type="REST", operation="invoke", URI="/TestRead?filter=~{filter~}", alias="", mediaType="application/json"). + @openapi.openedge.method.property (name="mergeMode", value="empty"). + METHOD PUBLIC VOID TestRead(INPUT filter AS CHARACTER, OUTPUT DATASET dsCustomer, OUTPUT count AS INTEGER): + EMPTY TEMP-TABLE ttCustomer. + + // MESSAGE "DEBUG: " filter. + IF filter = "" OR filter = ? THEN + DO: + filter = "20". + END. + + count = 0. + FOR EACH Customer WHERE Customer.CustNum < INTEGER(filter) NO-LOCK: + CREATE ttCustomer. + BUFFER-COPY Customer TO ttCustomer. + count = count + 1. + END. + END. + + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="invoke", URI="/TestInvoke", alias="", mediaType="application/json"). + @openapi.openedge.method.property (name="mergeMode", value="replace"). + METHOD PUBLIC VOID TestInvoke(INPUT-OUTPUT DATASET dsCustomer): + SUPER:Submit(DATASET dsCustomer BY-REFERENCE). + FOR EACH ttCustomer: + FIND FIRST customer WHERE customer.custnum = ttCustomer.custnum NO-LOCK NO-ERROR. + IF AVAILABLE customer THEN + DO: + ttCustomer.id = STRING(ROWID(Customer)). + END. + END. + END. + + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false"). + @progress.service.resourceMapping(type="REST", operation="invoke", URI="/count?filter=~{filter~}", alias="", mediaType="application/json"). + METHOD PUBLIC VOID count( INPUT filter AS CHARACTER, OUTPUT numRecs AS INTEGER): + DEFINE VARIABLE jsonParser AS ObjectModelParser NO-UNDO. + DEFINE VARIABLE jsonObject AS JsonObject NO-UNDO. + DEFINE VARIABLE ablFilter AS CHARACTER NO-UNDO. + DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. + DEFINE VARIABLE qh AS HANDLE NO-UNDO. + + IF filter BEGINS "WHERE " THEN + cWhere = filter. + ELSE IF filter BEGINS "~{" THEN + DO: + jsonParser = NEW ObjectModelParser(). + jsonObject = CAST(jsonParser:Parse(filter), jsonObject). + ablFilter = jsonObject:GetCharacter("ablFilter") NO-ERROR. + cWhere = "WHERE " + ablFilter. + END. + ELSE IF filter NE "" THEN + DO: + /* Use filter as WHERE clause */ + cWhere = "WHERE " + filter. + END. + + CREATE QUERY qh. + qh:SET-BUFFERS(BUFFER Customer:HANDLE). + qh:QUERY-PREPARE("PRESELECT EACH Customer " + cWhere). + qh:QUERY-OPEN (). + numRecs = qh:NUM-RESULTS. + + END METHOD. + + @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="true"). + @progress.service.resourceMapping(type="REST", operation="submit", URI="/SubmitSCustomer", alias="", mediaType="application/json"). + METHOD PUBLIC VOID SubmitCustomer(INPUT-OUTPUT DATASET dsCustomer): + SUPER:Submit(DATASET dsCustomer BY-REFERENCE). + FOR EACH ttCustomer: + FIND FIRST customer WHERE customer.custnum = ttCustomer.custnum NO-LOCK NO-ERROR. + IF AVAILABLE customer THEN + DO: + ttCustomer.id = STRING(ROWID(Customer)). + END. + END. + END METHOD. + +END CLASS. \ No newline at end of file diff --git a/test-services/Sports/customer.i b/test-services/Sports/customer.i new file mode 100644 index 0000000..320d00d --- /dev/null +++ b/test-services/Sports/customer.i @@ -0,0 +1,27 @@ +@openapi.openedge.entity.property (name="idProperty", value="id"). +DEFINE TEMP-TABLE ttCustomer BEFORE-TABLE bttCustomer + FIELD id AS CHARACTER + FIELD seq AS INTEGER INITIAL ? + FIELD CustNum AS INTEGER INITIAL "0" LABEL "Cust Num" + FIELD Name AS CHARACTER LABEL "Name" + FIELD Address AS CHARACTER LABEL "Address" + FIELD Address2 AS CHARACTER LABEL "Address2" + FIELD Balance AS DECIMAL INITIAL "0" LABEL "Balance" + FIELD City AS CHARACTER LABEL "City" + FIELD Comments AS CHARACTER LABEL "Comments" + FIELD Contact AS CHARACTER LABEL "Contact" + FIELD Country AS CHARACTER INITIAL "USA" LABEL "Country" + FIELD CreditLimit AS DECIMAL INITIAL "1500" LABEL "Credit Limit" + FIELD Discount AS INTEGER INITIAL "0" LABEL "Discount" + FIELD EmailAddress AS CHARACTER LABEL "Email" + FIELD Fax AS CHARACTER LABEL "Fax" + FIELD Phone AS CHARACTER LABEL "Phone" + FIELD PostalCode AS CHARACTER LABEL "Postal Code" + FIELD SalesRep AS CHARACTER LABEL "Sales Rep" + FIELD State AS CHARACTER LABEL "State" + FIELD Terms AS CHARACTER INITIAL "Net30" LABEL "Terms" + INDEX seq IS PRIMARY UNIQUE seq + /* INDEX CustNum IS UNIQUE CustNum */ + . + +DEFINE DATASET dsCustomer FOR ttCustomer. \ No newline at end of file diff --git a/test/smoke.invoke.js b/test/smoke.invoke.js new file mode 100644 index 0000000..57deefc --- /dev/null +++ b/test/smoke.invoke.js @@ -0,0 +1,222 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); + +const progress = require("../build/progress.jsdo").progress; + +chai.use(chaiAsPromised); + +describe('JSDO Smoke Tests', () => { + // INFORMATION YEAH + const options = { + catalogURI: "https://10.128.57.41:65500/Sports/static/SportsService.json", + serviceURI: "https://10.128.57.41:65500/Sports", + resourceName: "Customer", + authenticationModel: "anonymous" + }; + + const CustName = "SmokeTest3000"; + const newState = "NH"; + + let session, + jsdo; + + let recordID; + + before(function (done) { + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => done(), () => done()); + }); + + // Logout of the session after we are done + after((done) => { + session.invalidate().then(() => done()); + }); + + describe('JSDO Instantiation Tests', function() { + it('should successfully create a JSDO', function() { + jsdo = new progress.data.JSDO({name: options.resourceName}); + expect(jsdo).to.be.an.instanceof(progress.data.JSDO); + }); + + it('should successfully call TestRead "11"', function() { + let CustNum = 11; + let fill = jsdo.invoke("TestRead", { + filter: "" + CustNum + }).then((object) => { + return object.request.response.count === CustNum - 1; + }, () => { + return false; + }); + + return expect(fill).to.eventually.be.true; + }); + + it('should successfully call TestRead "21"', function() { + let CustNum = 21; + let fill = jsdo.invoke("TestRead", { + filter: "" + CustNum + }).then((object) => { + return object.request.response.count === CustNum - 1; + }, () => { + return false; + }); + + return expect(fill).to.eventually.be.true; + }); + + it('should have a jsdo filled with actual data from the backend', function() { + expect(jsdo.hasData()).to.be.true; + }); + }); + + describe('JSDO CUD Tests', function () { + // Clean up the backend to make sure that there isn't an customer record with a CustNum of 3000 + // already in store + function clean(callback) { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + jsdo.saveChanges().then(() => { + return jsdo.fill(); + }).then(() => callback()); + } + + before(function(done) { + clean(done); + }); + + after(function(done) { + clean(done); + }); + + it('should successfully create a record on the backend and update JSDO memory', function() { + jsdo.ttCustomer.add({ + CustNum: 0, + Name: CustName, + SalesRep: 'NS', + Balance: '2.10', + State: 'MA', + }); + + let changes = jsdo._createChangeSet(jsdo._dataSetName, true); + let save = jsdo.invoke("TestInvoke", changes).then((object) => { + // Use server-side ID to find record in JSDO memory + recordID = object.request.response.dsCustomer.dsCustomer.ttCustomer[0]._id; + let jsrecord = jsdo.findById(recordID); + return jsrecord && (jsrecord.data.CustNum > 0) && (jsrecord.data.Name === CustName); + }); + + return expect(save).to.eventually.be.true; + }); + + it('should return the new record by reading using fill()', function() { + let found = jsdo.fill().then((object) => { + // Use server-side ID to find record in JSDO memory + let jsrecord = jsdo.findById(recordID); + return jsrecord && (jsrecord.data.CustNum > 0) && (jsrecord.data.Name === CustName); + }); + + return expect(found).to.eventually.be.true; + }); + + it('should successfully update a record on the backend', function() { + // Use server-side ID to find record in JSDO memory + let jsrecord = jsdo.findById(recordID); + jsrecord.assign({State: newState}); + + let changes = jsdo._createChangeSet(jsdo._dataSetName, true); + let save = jsdo.invoke("TestInvoke", changes).then((object) => { + // Use server-side ID to find record in JSDO memory + let jsrecord = jsdo.findById(recordID); + return jsrecord + && (jsrecord.data.CustNum > 0) + && (jsrecord.data.Name === CustName) + && (jsrecord.data.State === newState); + }); + + return expect(save).to.eventually.be.true; + }); + + it('should return the updated record by reading using fill()', function() { + let found = jsdo.fill().then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName && customer.data.State === newState) { + found = true; + } + }); + return found; + }); + + return expect(found).to.eventually.be.true; + }); + + it('should fail to update a record to have the same primary index as another record', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.assign({CustNum: 1}); + } + }); + + let changes = jsdo._createChangeSet(jsdo._dataSetName, true); + let save = jsdo.invoke("TestInvoke", changes).then((object) => { + // let save = jsdo.saveChanges().then((object) => { + var success = object.success; + try { + if (object.request.response.dsCustomer.dsCustomer["prods:errors"]) { + success = false; + } + } catch (e) { + // Ignore + } + return success; + }, function (object) { + return object.success; + }); + + return expect(save).to.eventually.be.false; + }); + + it('should successfully delete a record on the backend', function() { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName) { + customer.remove(); + } + }); + + let changes = jsdo._createChangeSet(jsdo._dataSetName, true); + let save = jsdo.invoke("TestInvoke", changes).then((object) => { + // Use server-side ID to find record in JSDO memory + let found = false; + let jsrecord = jsdo.findById(recordID); + if (jsrecord) { + found = true; + } + return found; + }); + + return expect(save).to.eventually.be.false; + }); + + it('should not find the deleted records by reading using fill()', function() { + let found = jsdo.fill().then((object) => { + let found = false; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === CustName && customer.data.State === newState) { + found = true; + } + }); + return found; + }); + + return expect(found).to.eventually.be.false; + }); + }); +}); \ No newline at end of file From bbd58c7215190e615027122c4b9c7a9febdb9411 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 19:18:39 -0400 Subject: [PATCH 41/84] Added types for fill()/read() --- typings/progress.all.d.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 0fc610d..b3f0e81 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -943,11 +943,26 @@ export module progress { } interface FilterOptions { - filter?: any; - id?: any; - skip?: any; - sort?: any; - top?: any; + filter?: string | FilterOption | FilterOption[]; + id?: string; + skip?: number; + sort?: SortOption | SortOption[]; + top?: number; + tableRef?: string; + } + + interface FilterOption { + field: string; + logic?: string; + operator: string; + value?: any; + filters?: FilterOption[]; + } + + interface SortOption { + field: string; + dir: string; + compare?: (arg1: any, arg2: any) => any; } interface JSDORequest { From bf3e4370aac032e5db376d60a0019b8a5be8adba Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 21 Aug 2018 23:26:44 -0400 Subject: [PATCH 42/84] Removed the compare function --- typings/progress.all.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index b3f0e81..342728f 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -962,7 +962,6 @@ export module progress { interface SortOption { field: string; dir: string; - compare?: (arg1: any, arg2: any) => any; } interface JSDORequest { From 5e9e45fae4f051015bdaa6ca125cfa247c39a668 Mon Sep 17 00:00:00 2001 From: Anil Kumar Kotha Date: Wed, 19 Sep 2018 16:34:13 -0400 Subject: [PATCH 43/84] Adding fix for bug - ADAS-9502 --- .../ng-datasource/src/progress.data.ng.ds.js | 59 ++++++++++------ .../ng-datasource/src/progress.data.ng.ds.ts | 69 +++++++++++++------ .../typings/progress.data.ng.ds.d.ts | 19 ++++- 3 files changed, 104 insertions(+), 43 deletions(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index 97039d7..c74fd78 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -24,12 +24,6 @@ between OpenEdge (Progress Data Object) with NativeScript. Author(s): maura, anikumar, egarcia */ -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; Object.defineProperty(exports, "__esModule", { value: true }); var core_1 = require("@angular/core"); var jsdo_core_1 = require("@progress/jsdo-core"); @@ -291,21 +285,21 @@ var DataSource = /** @class */ (function () { var data = _this.getJsdoData(); // Only call count() function if paging is being used // Paging is only used if the skip and top is being used during the fill. - if (typeof params !== "undefined" && + if (typeof params !== "undefined" && (typeof _this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") - && !(params.skip === 0 && params.top > data.length)) { // Server-side operations + && !(params.skip === 0 && params.top > data.length)) { _this.getRecCount(_this._options.countFnName, { filter: result.request.objParam ? result.request.objParam.filter : undefined }) .then(function (res) { if (res === undefined && res == null) { - reject(new Error(_this.normalizeError(res, "Unexpected response from 'Count Function' Operation", ""))); + reject(_this.normalizedErrorObj(res, "Unexpected response from 'Count Function' Operation", "")); } else { resolve({ data: data, total: res }); } }, function (error) { - reject(new Error(_this.normalizeError(error, "Problems invoking getRecCount function", ""))); + reject(_this.normalizedErrorObj(error, "Problems invoking getRecCount function", "")); }).catch(function (e) { - reject(new Error(_this.normalizeError(e, "Unknown error occurred calling count.", ""))); + reject(_this.normalizedErrorObj(e, "Unknown error occurred calling count.", "")); }); } else { @@ -313,7 +307,7 @@ var DataSource = /** @class */ (function () { resolve({ data: data, total: data.length }); } }).catch(function (result) { - reject(new Error(_this.normalizeError(result, "read", ""))); + reject(_this.normalizedErrorObj(result, "read", "")); }); }); obs = Observable_1.Observable.fromPromise(wrapperPromise); @@ -507,17 +501,17 @@ var DataSource = /** @class */ (function () { else if (result.request && result.request.batch.operations.length === 0) { resolve({}); } - else { // Reject promise if either of above cases are not met - reject(new Error(_this - .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); + else { + reject(_this + .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); } } }).catch(function (result) { if (_this.jsdo.autoApplyChanges) { _this.jsdo[_this._tableRef].rejectChanges(); } - reject(new Error(_this - .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); + reject(_this + .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); }); }); obs = Observable_1.Observable.fromPromise(promise); @@ -588,10 +582,10 @@ var DataSource = /** @class */ (function () { resolve(countVal); } catch (e) { - reject(new Error(_this.normalizeError(e, "getRecCount", ""))); + reject(_this.normalizedErrorObj(e, "getRecCount", "")); } }).catch(function (result) { - reject(new Error(_this.normalizeError(result, "Error invoking the 'Count' operation", ""))); + reject(_this.normalizedErrorObj(result, "Error invoking the 'Count' operation", "")); }); }); return getRecCountPromise; @@ -636,6 +630,28 @@ var DataSource = /** @class */ (function () { } return errorMsg; }; + /** + * This method is called after an error has occurred on a jsdo operation, and is + * used to get an error object. + * @param {any} result Object containing error info returned after execution of jsdo operation + * @param {string} operation String containing operation performed when error occurred + * @param {string} genericMsg If multiple errors are found in result object, if specified, + * this string will be returned as part of the new error object. If not specified, first error + * string will be returned. + * @returns A single error object with all information + */ + DataSource.prototype.normalizedErrorObj = function (result, operation, genericMsg) { + var errorObj = {}; + var eMsg = ""; + var object = {}; + if (result && result.jsdo && result.success == false) { + object = result.request; + } + eMsg = this.normalizeError(result, operation, genericMsg); + errorObj = new Error(eMsg); + errorObj.info = object; + return errorObj; + }; DataSource.prototype._copyRecord = function (source, target) { var field; var newObject; @@ -691,7 +707,7 @@ var DataSource = /** @class */ (function () { if (firstKey !== this._tableRef) { target[firstKey][this._tableRef].push(newEntry[firstKey][this._tableRef][0]); } - else { // Temp-table usecase + else { target[this._tableRef].push(newEntry[this._tableRef][0]); } return target; @@ -700,7 +716,8 @@ var DataSource = /** @class */ (function () { } }; DataSource = __decorate([ - core_1.Injectable() + core_1.Injectable(), + __metadata("design:paramtypes", [DataSourceOptions]) ], DataSource); return DataSource; }()); diff --git a/packages/ng-datasource/src/progress.data.ng.ds.ts b/packages/ng-datasource/src/progress.data.ng.ds.ts index 291ab87..9aa4a25 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.ts +++ b/packages/ng-datasource/src/progress.data.ng.ds.ts @@ -363,26 +363,26 @@ export class DataSource { this._options.countFnName, { filter: result.request.objParam ? result.request.objParam.filter : undefined }) .then((res) => { - if (res === undefined && res == null) { - reject(new Error(this.normalizeError(res, - "Unexpected response from 'Count Function' Operation", ""))); + if (res === undefined && res == null) { + reject(this.normalizedErrorObj(res, + "Unexpected response from 'Count Function' Operation", "")); } else { resolve({ data, total: res }); } - }, (error) => { - reject(new Error(this.normalizeError(error, - "Problems invoking getRecCount function", ""))); - }).catch((e) => { - reject(new Error(this.normalizeError(e, - "Unknown error occurred calling count.", ""))); + }, (error) => { + reject(this.normalizedErrorObj(error, + "Problems invoking getRecCount function", "")); + }).catch((e) => { + reject(this.normalizedErrorObj(e, + "Unknown error occurred calling count.", "")); }); } else { // Client side operations resolve({ data, total: data.length }); } - }).catch((result) => { - reject(new Error(this.normalizeError(result, "read", ""))); + }).catch((result) => { + reject(this.normalizedErrorObj(result, "read", "")); }); } ); @@ -592,16 +592,16 @@ export class DataSource { } else if (result.request && result.request.batch.operations.length === 0) { resolve({}); } else { // Reject promise if either of above cases are not met - reject(new Error(this - .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); + reject(this + .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); } } }).catch((result) => { if (this.jsdo.autoApplyChanges) { this.jsdo[this._tableRef].rejectChanges(); - } - reject(new Error(this - .normalizeError(result, "saveChanges", "Errors occurred while saving Changes."))); + } + reject(this + .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); }); } ); @@ -678,11 +678,11 @@ export class DataSource { } } resolve(countVal); - } catch (e) { - reject(new Error(this.normalizeError(e, "getRecCount", ""))); + } catch (e) { + reject(this.normalizedErrorObj(e, "getRecCount", "")); } - }).catch((result) => { - reject(new Error(this.normalizeError(result, "Error invoking the 'Count' operation", ""))); + }).catch((result) => { + reject(this.normalizedErrorObj(result, "Error invoking the 'Count' operation", "")); }); }); @@ -729,6 +729,33 @@ export class DataSource { return errorMsg; } + /** + * This method is called after an error has occurred on a jsdo operation, and is + * used to get an error object. + * @param {any} result Object containing error info returned after execution of jsdo operation + * @param {string} operation String containing operation performed when error occurred + * @param {string} genericMsg If multiple errors are found in result object, if specified, + * this string will be returned as part of the new error object. If not specified, first error + * string will be returned. + * @returns A single error object with all information + */ + private normalizedErrorObj(result: any, operation: string, genericMsg: string) { + let errorObj: {[key: string]: any} = {}; + let eMsg = ""; + let object: {[key: string]: any} = {}; + + if (result && result.jsdo && result.success == false) { + object = result.request; + } + + eMsg = this.normalizeError(result, operation, genericMsg); + + errorObj = new Error(eMsg); + errorObj.info = object; + + return errorObj; + } + private _copyRecord(source, target) { let field; let newObject; @@ -797,4 +824,4 @@ export class DataSource { } } } -} +} \ No newline at end of file diff --git a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts b/packages/ng-datasource/typings/progress.data.ng.ds.d.ts index daa628b..a2f8d4a 100644 --- a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts +++ b/packages/ng-datasource/typings/progress.data.ng.ds.d.ts @@ -25,7 +25,13 @@ export declare class DataSource { private _options; private _tableRef; private _initFromServer; + private _convertFields; + private _convertTypes; + private useArrays; constructor(options: DataSourceOptions); + _convertStringToDate(data: any, fieldName: any, targetFieldName?: any): void; + _convertDataTypes(data: any): any; + _initConvertTypes(): void; /** * Calls the jsdo.fill() retrieving data from the backend service * @returns An Observable which includes an Array followed @@ -85,7 +91,7 @@ export declare class DataSource { saveChanges(): Observable>; /** * First, retrieves data from JSDO local memory - * Then makes a copy of it, to ensure jsdo memory is only manipulated thru Data Source API + * Then makes a copy of it, to ensure jsdo memory is only manipulated thru DataSource API * Returns array of record objects * @returns Array */ @@ -107,6 +113,17 @@ export declare class DataSource { * @returns A single error message */ private normalizeError(result, operation, genericMsg); + /** + * This method is called after an error has occurred on a jsdo operation, and is + * used to get an error object. + * @param {any} result Object containing error info returned after execution of jsdo operation + * @param {string} operation String containing operation performed when error occurred + * @param {string} genericMsg If multiple errors are found in result object, if specified, + * this string will be returned as part of the new error object. If not specified, first error + * string will be returned. + * @returns A single error object with all information + */ + private normalizedErrorObj(result, operation, genericMsg); private _copyRecord(source, target); /** * This method is responsible for building a valid responseObject when multiple records From f47329666c96701a75dd29ee844624662e478dfe Mon Sep 17 00:00:00 2001 From: Anil Kumar Kotha Date: Wed, 19 Sep 2018 17:53:25 -0400 Subject: [PATCH 44/84] Updated JavaScript code to include decorate statements --- packages/ng-datasource/src/progress.data.ng.ds.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index c74fd78..c63e8a7 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -24,6 +24,13 @@ between OpenEdge (Progress Data Object) with NativeScript. Author(s): maura, anikumar, egarcia */ +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; + Object.defineProperty(exports, "__esModule", { value: true }); var core_1 = require("@angular/core"); var jsdo_core_1 = require("@progress/jsdo-core"); From 868b55d860bd5aa0b395516910eebb1b2b8b0450 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Wed, 19 Sep 2018 19:27:18 -0400 Subject: [PATCH 45/84] Added DataSource smoke tests --- packages/node/test/smoke.datasource.js | 265 +++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 packages/node/test/smoke.datasource.js diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js new file mode 100644 index 0000000..791d8db --- /dev/null +++ b/packages/node/test/smoke.datasource.js @@ -0,0 +1,265 @@ +const chai = require('chai'); +const expect = chai.expect; +const chaiAsPromised = require("chai-as-promised"); +const progress = require("@progress/jsdo-core").progress; +const DataSource = require("../build/progress.data.node").DataSource; +const rxjs = require("rxjs"); + +chai.use(chaiAsPromised); + +// These are smoke tests for the DataSource! :) + +describe('Datasource Smoke Tests', function () { + //options all the info required for creating a jsdo session + const options = { + serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", + catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", + resourceName: "Customer", + authenticationModel: "anonymous", + tableRef: "ttCustomer", + recName: "test9001" //+ (Math.random() * 100) + }; + + //define your variables required for the tests below + let session, + jsdo, + dataSource; + + //before: getSession + before(function (done) { + progress.data.getSession(options).then((object) => { + session = object.jsdosession; + }).then(() => { + jsdo = new progress.data.JSDO({ name: options.resourceName }); + }).then(() => done(), () => done()); + }); + + //after: Logout of the session after we are done + after((done) => { + done(); + }); + + describe('DataSource Instantiation Tests', function () { + it('should successfully create a DataSource', function () { + dataSource = new DataSource({ + jsdo: jsdo, + tableRef: options.tableRef + }); + + expect(dataSource).to.be.an.instanceOf(DataSource); + }); + }); + + //1st Read without parameters + describe('DataSource CRUD tests', function () { + let data, + rec; + + before(function () { + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === options.recName) { + customer.remove(); + // console.log(customer); + } + + jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + console.log(object); + let found = 0; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === options.recName) { + found += 1; + } + }); + // console.log(found); + }); + }); + }).setTimeout(5000); + + describe('DataSource Read tests', function () { + it('should have an Observable returned by read', function () { + let read = dataSource.read(); + expect(read).to.be.instanceOf(rxjs.Observable); + }); + + it('should successfully call read()', function () { + let read = dataSource.read().toPromise().then((mydata) => { + data = mydata.data; + // console.log(data); + return true; + }, (error) => { + return expect.fail(null, null, 'DataSource.read() failed: ' + error); + }); + + return expect(read).to.eventually.be.true; + }); + + it('should have a DataSource with data after the read()', function () { + return expect(data[0]["CustNum"]).to.be.a("number"); + }); + }); + + describe('DataSource Create tests', function () { + it('should successfully call create()', function () { + // { CustNum: 1, + // Country: 'Mexico', + // Name: 'NewItem', + // ... + // id: '0x0000000000000062', + // _id: '1537314778768-1' } + + let testRec = { + CustNum: '', + Name: options.recName, + State: 'MA', + Balance: 0 + }; + + expect(dataSource.create(testRec).Name).to.deep.equal(testRec.Name); + }); + + it('should successfully call saveChanges()', function () { + // expect(create).to.be.instanceOf(rxjs.Observable); + let create = dataSource.saveChanges().toPromise().then(() => { + return true; + }, (error) => { + return expect.fail(null, null, 'DataSource.create() failed: ' + error); + }); + + return expect(create).to.eventually.be.true; + }); + + it('should successfully create a single record in the backend', function () { + let count = 0; + dataSource.getData().forEach(element => { + if (element.Name === options.recName) { + count += 1; + } + + if (count === 1) { + // Save the element for the update test later + rec = element; + } + }); + + return expect(count).to.equal(1); + }); + }); + + describe('DataSource Update tests', function () { + it('should successfully call update()', function () { + rec.Country = "TestCountry"; + + expect(dataSource.update(rec).Country).to.deep.equal(rec.Country); + }); + + it('should successfully call saveChanges()', function () { + // expect(create).to.be.instanceOf(rxjs.Observable); + let update = dataSource.saveChanges().toPromise().then(() => { + return true; + }, (error) => { + return expect.fail(null, null, 'DataSource.create() failed: ' + error); + }); + + return expect(update).to.eventually.be.true; + }); + + it('should successfully update a single record in the backend', function () { + let count = 0; + dataSource.getData().forEach(element => { + if (element.Name === options.recName + && element.Country === "TestCountry") { + count += 1; + } + + // Save this element for the delete later + if (count === 1) { + rec = element; + } + }); + + return expect(count).to.equal(1); + }); + }); + + describe('DataSource Remove tests', function () { + it('should successfully call Remove()', function () { + + console.log(dataSource.remove(rec)); + + // expect(dataSource.update(rec).Country).to.deep.equal(rec.Country); + expect(1).to.equal(1); + }); + + it('should successfully call saveChanges()', function () { + let remove = dataSource.saveChanges().toPromise().then(() => { + return true; + }, (error) => { + return expect.fail(null, null, 'DataSource.create() failed: ' + error); + }); + + return expect(remove).to.eventually.be.true; + }); + + it('should successfully update a single record in the backend', function () { + let count = 0; + dataSource.getData().forEach(element => { + if (element.Name === options.recName) { + count += 1; + } + }); + + return expect(count).to.equal(0); + }); + }); + + after(function (done) { + // let foundTestRec; + // if (dataSource) { + // console.log("deleting"); + // dataSource.read().toPromise().then((mydata) => { + // mydata.data.forEach(element => { + // if (element.Name === options.recName) { + // foundTestRec = element; + // dataSource.remove(foundTestRec); + // } + // }); + // }); + + // if (foundTestRec) { + // dataSource.saveChanges().toPromise().then((d) => { + // console.log(d); + // }, (e) => { + // console.log(e); + // }).then(() => done(), () => done()); + // } else { + // done(); + // } + // } + + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === options.recName) { + customer.remove(); + } + + jsdo.saveChanges().then((object) => { + return jsdo.fill(); + }).then((object) => { + console.log(object); + let found = 0; + jsdo.ttCustomer.foreach((customer) => { + if (customer.data.Name === options.recName) { + found += 1; + } + }); + console.log(found); + }); + }); + + setTimeout(() => { + session.invalidate().then(() => done()); + }, 5000); + }).setTimeout(5000); + }); +}); From 3c72d95c1a6c35917ff7d57aec39e6199f5f2649 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Wed, 19 Sep 2018 19:31:44 -0400 Subject: [PATCH 46/84] Updated the timeout of cleaning up the records. --- packages/node/test/smoke.datasource.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index 791d8db..3dcb842 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -75,7 +75,7 @@ describe('Datasource Smoke Tests', function () { // console.log(found); }); }); - }).setTimeout(5000); + }); describe('DataSource Read tests', function () { it('should have an Observable returned by read', function () { @@ -237,7 +237,7 @@ describe('Datasource Smoke Tests', function () { // done(); // } // } - + this.timeout(5000); jsdo.ttCustomer.foreach((customer) => { if (customer.data.Name === options.recName) { customer.remove(); @@ -259,7 +259,7 @@ describe('Datasource Smoke Tests', function () { setTimeout(() => { session.invalidate().then(() => done()); - }, 5000); - }).setTimeout(5000); + }, 1500); + }); }); }); From 17bc2b865b9d5e50f8f7134c68c8d69390685aa2 Mon Sep 17 00:00:00 2001 From: Anil Date: Thu, 20 Sep 2018 11:41:18 -0400 Subject: [PATCH 47/84] Updated JavaScript transpiled code Updated JavaScript transpiled code to not include _metadata information --- packages/ng-datasource/src/progress.data.ng.ds.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js index c63e8a7..73536ff 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ b/packages/ng-datasource/src/progress.data.ng.ds.js @@ -723,8 +723,7 @@ var DataSource = /** @class */ (function () { } }; DataSource = __decorate([ - core_1.Injectable(), - __metadata("design:paramtypes", [DataSourceOptions]) + core_1.Injectable() ], DataSource); return DataSource; }()); From b4696e826ec89e8be1d4b7025a98b8331ed9bfdc Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Thu, 20 Sep 2018 11:56:46 -0400 Subject: [PATCH 48/84] Updated smoke tests --- packages/node/package.json | 6 ++- packages/node/test/smoke.datasource.js | 61 ++++---------------------- 2 files changed, 13 insertions(+), 54 deletions(-) diff --git a/packages/node/package.json b/packages/node/package.json index b7f3eb3..579f068 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -37,14 +37,16 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@angular/core": "^5.2.1", + "@angular/core": "^6.1.0", "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", "rxjs": "^5.5.6", "xmlhttprequest": "^1.8.0" }, - "peerDependencies": {}, + "peerDependencies": { + "@angular/core": "^6.1.0" + }, "optionalDependencies": {}, "devDependencies": { "chai": "^4.1.2", diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index 3dcb842..f948e04 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -34,11 +34,6 @@ describe('Datasource Smoke Tests', function () { }).then(() => done(), () => done()); }); - //after: Logout of the session after we are done - after((done) => { - done(); - }); - describe('DataSource Instantiation Tests', function () { it('should successfully create a DataSource', function () { dataSource = new DataSource({ @@ -55,28 +50,6 @@ describe('Datasource Smoke Tests', function () { let data, rec; - before(function () { - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === options.recName) { - customer.remove(); - // console.log(customer); - } - - jsdo.saveChanges().then((object) => { - return jsdo.fill(); - }).then((object) => { - console.log(object); - let found = 0; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === options.recName) { - found += 1; - } - }); - // console.log(found); - }); - }); - }); - describe('DataSource Read tests', function () { it('should have an Observable returned by read', function () { let read = dataSource.read(); @@ -185,11 +158,17 @@ describe('Datasource Smoke Tests', function () { describe('DataSource Remove tests', function () { it('should successfully call Remove()', function () { + let count = 0; - console.log(dataSource.remove(rec)); + dataSource.getData().forEach(element => { + if (element.Name === options.recName) { + if (dataSource.remove(element)) { + count += 1; + } + } + }); - // expect(dataSource.update(rec).Country).to.deep.equal(rec.Country); - expect(1).to.equal(1); + expect(count).to.equal(1); }); it('should successfully call saveChanges()', function () { @@ -215,28 +194,6 @@ describe('Datasource Smoke Tests', function () { }); after(function (done) { - // let foundTestRec; - // if (dataSource) { - // console.log("deleting"); - // dataSource.read().toPromise().then((mydata) => { - // mydata.data.forEach(element => { - // if (element.Name === options.recName) { - // foundTestRec = element; - // dataSource.remove(foundTestRec); - // } - // }); - // }); - - // if (foundTestRec) { - // dataSource.saveChanges().toPromise().then((d) => { - // console.log(d); - // }, (e) => { - // console.log(e); - // }).then(() => done(), () => done()); - // } else { - // done(); - // } - // } this.timeout(5000); jsdo.ttCustomer.foreach((customer) => { if (customer.data.Name === options.recName) { From 3f07f558a16c752fe2f08c4b09706087dfccf22c Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Thu, 20 Sep 2018 14:08:48 -0400 Subject: [PATCH 49/84] Updated package.json for everything into a peer dependency --- packages/angular/package.json | 5 +++-- packages/nativescript/package.json | 5 +++-- packages/ng-datasource/package.json | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index 9ed5915..79c4efb 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -33,11 +33,12 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@angular/core": "^5.2.1", "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "rxjs": "^5.5.6" }, - "peerDependencies": {}, + "peerDependencies": { + "@angular/core": "^6.1.0" + }, "optionalDependencies": {} } diff --git a/packages/nativescript/package.json b/packages/nativescript/package.json index 6b4dbcc..a42bd47 100644 --- a/packages/nativescript/package.json +++ b/packages/nativescript/package.json @@ -35,13 +35,14 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@angular/core": "^5.2.1", "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "nativescript-localstorage": "^1.1.5", "rxjs": "^5.5.6", "zone.js": "^0.8.18" }, - "peerDependencies": {}, + "peerDependencies": { + "@angular/core": "^6.1.0" + }, "optionalDependencies": {} } diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index fc60c11..3087963 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -39,14 +39,15 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@angular/core": "^5.2.1", "@progress/jsdo-nativescript": "^5.0.0-0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", "rxjs": "^5.5.6", "xmlhttprequest": "^1.8.0" }, - "peerDependencies": {}, + "peerDependencies": { + "@angular/core": "^6.1.0" + }, "optionalDependencies": {}, "devDependencies": { "chai": "^4.1.2", From a85cc19d486a113aa0d679fd1b94550e089668d7 Mon Sep 17 00:00:00 2001 From: joshualan Date: Mon, 24 Sep 2018 10:46:56 -0400 Subject: [PATCH 50/84] Removed dupe @angular/core --- packages/node/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/node/package.json b/packages/node/package.json index 579f068..61704aa 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -37,7 +37,6 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@angular/core": "^6.1.0", "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", From 13ea49d79241d1803cef4c42271bc0b9f8ffd5e5 Mon Sep 17 00:00:00 2001 From: Nicolette Date: Mon, 24 Sep 2018 13:22:10 -0400 Subject: [PATCH 51/84] upgrade rxjs add as peer dependency --- packages/angular/package.json | 6 +++--- packages/nativescript/package.json | 4 ++-- packages/ng-datasource/package.json | 4 ++-- packages/node/package.json | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index 79c4efb..9033603 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -34,11 +34,11 @@ "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { "@progress/jsdo-core": "^5.0.0", - "base-64": "^0.1.0", - "rxjs": "^5.5.6" + "base-64": "^0.1.0" }, "peerDependencies": { - "@angular/core": "^6.1.0" + "@angular/core": "^6.1.0", + "rxjs": "^6.0.0" }, "optionalDependencies": {} } diff --git a/packages/nativescript/package.json b/packages/nativescript/package.json index a42bd47..4b13517 100644 --- a/packages/nativescript/package.json +++ b/packages/nativescript/package.json @@ -38,11 +38,11 @@ "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "nativescript-localstorage": "^1.1.5", - "rxjs": "^5.5.6", "zone.js": "^0.8.18" }, "peerDependencies": { - "@angular/core": "^6.1.0" + "@angular/core": "^6.1.0", + "rxjs": "^6.0.0" }, "optionalDependencies": {} } diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 3087963..aabcf62 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -42,11 +42,11 @@ "@progress/jsdo-nativescript": "^5.0.0-0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", - "rxjs": "^5.5.6", "xmlhttprequest": "^1.8.0" }, "peerDependencies": { - "@angular/core": "^6.1.0" + "@angular/core": "^6.1.0", + "rxjs": "^6.0.0" }, "optionalDependencies": {}, "devDependencies": { diff --git a/packages/node/package.json b/packages/node/package.json index 61704aa..c2ec31e 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -40,11 +40,11 @@ "@progress/jsdo-core": "^5.0.0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", - "rxjs": "^5.5.6", "xmlhttprequest": "^1.8.0" }, "peerDependencies": { - "@angular/core": "^6.1.0" + "@angular/core": "^6.1.0", + "rxjs": "^6.0.0" }, "optionalDependencies": {}, "devDependencies": { From 6c0cba8dc53e2d9499ddf6072ac5ec31f2c7b0bf Mon Sep 17 00:00:00 2001 From: Nicolette Date: Mon, 24 Sep 2018 14:14:26 -0400 Subject: [PATCH 52/84] rx code changes --- .../ng-datasource/src/progress.data.ng.ds.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/ng-datasource/src/progress.data.ng.ds.ts b/packages/ng-datasource/src/progress.data.ng.ds.ts index 9aa4a25..77e4c4a 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.ts +++ b/packages/ng-datasource/src/progress.data.ng.ds.ts @@ -26,9 +26,8 @@ Author(s): maura, anikumar, egarcia import { Injectable } from "@angular/core"; import { progress } from "@progress/jsdo-core"; -import "rxjs/add/observable/fromPromise"; -import "rxjs/add/operator/catch"; -import { Observable } from "rxjs/Observable"; +import { Observable, from } from "rxjs"; +import { catchError } from "rxjs/operators"; export class DataSourceOptions { jsdo: progress.data.JSDO; @@ -387,10 +386,10 @@ export class DataSource { } ); - obs = Observable.fromPromise(wrapperPromise); - obs.catch((e) => { + obs = from(wrapperPromise); + obs.pipe(catchError((e) => { return []; - }); + })); return obs; } @@ -606,10 +605,10 @@ export class DataSource { } ); - obs = Observable.fromPromise(promise); - obs.catch((e) => { + obs = from(promise); + obs.pipe(catchError((e) => { return []; - }); + })); return obs; } From 3e7cf26227aaa05041603bffdf65ed28fabf02a2 Mon Sep 17 00:00:00 2001 From: Nicolette Date: Mon, 24 Sep 2018 14:20:15 -0400 Subject: [PATCH 53/84] update typings --- packages/ng-datasource/typings/progress.data.ng.ds.d.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts b/packages/ng-datasource/typings/progress.data.ng.ds.d.ts index a2f8d4a..bc4148f 100644 --- a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts +++ b/packages/ng-datasource/typings/progress.data.ng.ds.d.ts @@ -1,7 +1,6 @@ import { progress } from "@progress/jsdo-core"; -import "rxjs/add/observable/fromPromise"; -import "rxjs/add/operator/catch"; -import { Observable } from "rxjs/Observable"; +import { Observable, from } from "rxjs"; +import { catchError } from "rxjs/operators"; export declare class DataSourceOptions { jsdo: progress.data.JSDO; tableRef?: string; From 4667744f49887fd4ce4a2fe6c26b4c10060d8566 Mon Sep 17 00:00:00 2001 From: Nicolette Date: Mon, 24 Sep 2018 15:05:20 -0400 Subject: [PATCH 54/84] version 6 --- packages/angular/package.json | 4 ++-- packages/core/package.json | 2 +- packages/nativescript/package.json | 4 ++-- packages/ng-datasource/package.json | 4 ++-- packages/node/package.json | 8 +++----- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index 9033603..2e54d35 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-angular", - "version": "5.0.1", + "version": "6.0.0", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with Angular.", "main": "lib/progress.data.angular.js", "files": [ @@ -33,7 +33,7 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@progress/jsdo-core": "^5.0.0", + "@progress/jsdo-core": "^6.0.0", "base-64": "^0.1.0" }, "peerDependencies": { diff --git a/packages/core/package.json b/packages/core/package.json index 9c2ee1b..71638bd 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-core", - "version": "5.0.1", + "version": "6.0.0", "description": "JSDO Core Module", "main": "lib/progress.core.js", "files": [ diff --git a/packages/nativescript/package.json b/packages/nativescript/package.json index 4b13517..0d8aee6 100644 --- a/packages/nativescript/package.json +++ b/packages/nativescript/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-nativescript", - "version": "5.0.1", + "version": "6.0.0", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with NativeScript", "main": "lib/progress.data.ns.js", "files": [ @@ -35,7 +35,7 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@progress/jsdo-core": "^5.0.0", + "@progress/jsdo-core": "^6.0.0", "base-64": "^0.1.0", "nativescript-localstorage": "^1.1.5", "zone.js": "^0.8.18" diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index aabcf62..ac26663 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-nsds", - "version": "5.0.1", + "version": "6.0.0", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with NativeScript", "main": "lib/progress.data.ng.ds.js", "files": [ @@ -39,7 +39,7 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@progress/jsdo-nativescript": "^5.0.0-0", + "@progress/jsdo-nativescript": "^6.0.0-0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", "xmlhttprequest": "^1.8.0" diff --git a/packages/node/package.json b/packages/node/package.json index c2ec31e..b5011aa 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo-node", - "version": "5.0.1", + "version": "6.0.0", "description": "The Progress Data Source is a TypeScript implementation - Progress Data Source class for NativeScript, Angular and Node.js. This will provide a seamless integration between OpenEdge (Progress Data Object) with Node.js.", "main": "lib/progress.data.node.js", "files": [ @@ -37,12 +37,10 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@progress/jsdo-core": "^5.0.0", + "@progress/jsdo-core": "^6.0.0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", - "xmlhttprequest": "^1.8.0" - }, - "peerDependencies": { + "xmlhttprequest": "^1.8.0", "@angular/core": "^6.1.0", "rxjs": "^6.0.0" }, From 7ba5e7f11684c363971b76c742412f1627a61714 Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 15:51:09 -0400 Subject: [PATCH 55/84] Adding tsc build Adding tsc build info to package.json --- packages/ng-datasource/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index ac26663..f0b072e 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -11,6 +11,7 @@ "typings/" ], "scripts": { + "build": "tsc", "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", "test": "npm run build:ds && mocha --recursive", "test:smokes": "npm run build:ds && mocha test/smoke*.js", From 50bd95ab7cdea2abdc5a1f2523e70ea85c4cac7a Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 15:52:28 -0400 Subject: [PATCH 56/84] Adding new tsconfig file Created a new tsconfig file for the TypeScript files (Transpiled JavaScript and type definitions) --- packages/ng-datasource/tsconfig.json | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 packages/ng-datasource/tsconfig.json diff --git a/packages/ng-datasource/tsconfig.json b/packages/ng-datasource/tsconfig.json new file mode 100644 index 0000000..796ebd1 --- /dev/null +++ b/packages/ng-datasource/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "es5", + "declaration": true, + "outDir": "./tsFiles", + "experimentalDecorators": true, + "emitDecoratorMetadata": false, + "noEmitHelpers": false, + "noEmitOnError": true, + "lib": [ + "es6", + "dom", + "es2017" + ], + "baseUrl": ".", + "paths": { + "*": [ + "./node_modules/*" + ] + } + }, + "exclude": [ + "node_modules", + "platforms", + "**/*.aot.ts" + ] +} From 9ac90a45ea230a259a050877281d1d1919578c2c Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 15:53:04 -0400 Subject: [PATCH 57/84] Deleting type definitions file Deleting type definitions file as this gets generated dynamically --- .../typings/progress.data.ng.ds.d.ts | 134 ------------------ 1 file changed, 134 deletions(-) delete mode 100644 packages/ng-datasource/typings/progress.data.ng.ds.d.ts diff --git a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts b/packages/ng-datasource/typings/progress.data.ng.ds.d.ts deleted file mode 100644 index bc4148f..0000000 --- a/packages/ng-datasource/typings/progress.data.ng.ds.d.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { progress } from "@progress/jsdo-core"; -import { Observable, from } from "rxjs"; -import { catchError } from "rxjs/operators"; -export declare class DataSourceOptions { - jsdo: progress.data.JSDO; - tableRef?: string; - filter?: any; - sort?: any; - top?: number; - skip?: number; - mergeMode?: number; - readLocal?: boolean; - countFnName?: string; -} -export interface DataResult { - data: Array; - total: number; -} -export declare class DataSource { - jsdo: progress.data.JSDO; - readLocal: boolean; - _skipRec: number; - _isLastResultSetEmpty: boolean; - private _options; - private _tableRef; - private _initFromServer; - private _convertFields; - private _convertTypes; - private useArrays; - constructor(options: DataSourceOptions); - _convertStringToDate(data: any, fieldName: any, targetFieldName?: any): void; - _convertDataTypes(data: any): any; - _initConvertTypes(): void; - /** - * Calls the jsdo.fill() retrieving data from the backend service - * @returns An Observable which includes an Array followed - * by an attribute for specifying 'total' records - */ - read(params?: progress.data.FilterOptions): Observable; - /** - * Returns array of record objects from local memory - * @returns Array - */ - getData(): Array; - /** - * Calls the jsdo.add() method, creating a new record in JSDO memory - * jsdo.add() will either return the new record, or throws an exception - * @param data - Record to create is passed as an object - * @returns - If successful, an object of the new record is returned - */ - create(data: object): object; - /** - * Returns a copy of the record with the specified id. - * Note: current implementation uses jsdo's internal _id as id. - * @param id - id of record - * @returns - copy of record with specified id, else null if no record found - */ - findById(id: string): object; - /** - * Calls the jsdo.update() method, for updating a record in JSDO memory - * jsdo.update() will either return the updated record, or throws an exception - * @param data - Record to create is passed as an object - * @returns - boolean. True if successful, false if there is any failure - */ - update(data: any): boolean; - /** - * Deletes a record from JSDO memory by calling jsdo.remove() API. This accepts a record - * with a valid _id without which an error is reported - * @param data Provide valid record for deletion - * @returns boolean - True if the operation succeeds, false otherwise - */ - remove(data: any): boolean; - /** - * Returns true if the underlying jsdo has CUD support (create, update, delete operations). - * If not, it returns false. - */ - hasCUDSupport(): boolean; - /** - * Returns true if the underlying jsdo has Submit support (submit operation). - * If not, it returns false. - */ - hasSubmitSupport(): boolean; - /** - * Synchronizes to the server all record changes (creates, updates, and deletes) pending in - * JSDO memory for the current Data Object resource - * If jsdo.hasSubmitOperation is false, all record modifications are sent to server individually. - * When 'true', modifications are batched together and sent in single request - * @returns {object} Observable - */ - saveChanges(): Observable>; - /** - * First, retrieves data from JSDO local memory - * Then makes a copy of it, to ensure jsdo memory is only manipulated thru DataSource API - * Returns array of record objects - * @returns Array - */ - private getJsdoData(); - /** - * This method is used for fetching the 'count' of records from backend - * This method is used as part of read() operation when serverOperations is set by client - * @param {string} name Name of the method pertaining to 'Count' functionality - * @param {any} object Filter object - */ - private getRecCount(name, object); - /** - * This method is called after an error has occurred on a jsdo operation, and is - * used to get an error message. - * @param {any} result Object containing error info returned after execution of jsdo operation - * @param {string} operation String containing operation performed when error occurred - * @param {string} genericMsg If multiple errors are found in result object, if specified, - * this string will be returned. If not specified, first error string will be returned. - * @returns A single error message - */ - private normalizeError(result, operation, genericMsg); - /** - * This method is called after an error has occurred on a jsdo operation, and is - * used to get an error object. - * @param {any} result Object containing error info returned after execution of jsdo operation - * @param {string} operation String containing operation performed when error occurred - * @param {string} genericMsg If multiple errors are found in result object, if specified, - * this string will be returned as part of the new error object. If not specified, first error - * string will be returned. - * @returns A single error object with all information - */ - private normalizedErrorObj(result, operation, genericMsg); - private _copyRecord(source, target); - /** - * This method is responsible for building a valid responseObject when multiple records - * are involved in transaction - * @param source Actual dataset/record to be merged - * @param target Resultant dataset with all records information - */ - private _buildResponse(source, target); -} From b19ba195322e75f78cd36213028ebb72476cc41b Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 15:53:45 -0400 Subject: [PATCH 58/84] Deleting transpile JavaScript file Deleting transpile JavaScript file as this gets generated dynamically --- .../ng-datasource/src/progress.data.ng.ds.js | 730 ------------------ 1 file changed, 730 deletions(-) delete mode 100644 packages/ng-datasource/src/progress.data.ng.ds.js diff --git a/packages/ng-datasource/src/progress.data.ng.ds.js b/packages/ng-datasource/src/progress.data.ng.ds.js deleted file mode 100644 index 73536ff..0000000 --- a/packages/ng-datasource/src/progress.data.ng.ds.js +++ /dev/null @@ -1,730 +0,0 @@ -"use strict"; -/* -Progress Progress Data Source for Angular: 5.0.0 - -Copyright 2017-2018 Progress Software Corporation and/or its subsidiaries or affiliates. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -progress.data.ng.ds.ts Version: v5.0.0 - -Progress Data Source class for NativeScript, Angular. This will provide a seamless integration -between OpenEdge (Progress Data Object) with NativeScript. - -Author(s): maura, anikumar, egarcia - -*/ -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; - -Object.defineProperty(exports, "__esModule", { value: true }); -var core_1 = require("@angular/core"); -var jsdo_core_1 = require("@progress/jsdo-core"); -require("rxjs/add/observable/fromPromise"); -require("rxjs/add/operator/catch"); -var Observable_1 = require("rxjs/Observable"); -var DataSourceOptions = /** @class */ (function () { - function DataSourceOptions() { - } - return DataSourceOptions; -}()); -exports.DataSourceOptions = DataSourceOptions; -// tslint:disable max-classes-per-file -var DataSource = /** @class */ (function () { - function DataSource(options) { - this.jsdo = undefined; - // useArray === false means that arrays would be flattened - this.useArrays = false; - this.jsdo = options.jsdo; - this._initFromServer = false; - this._isLastResultSetEmpty = false; - this._options = options; - this.readLocal = options.readLocal !== undefined ? options.readLocal : false; - // Make sure autoApplyChanges = true - this.jsdo.autoApplyChanges = true; - if (!options.jsdo || !(options.jsdo instanceof jsdo_core_1.progress.data.JSDO)) { - throw new Error("DataSource: jsdo property must be set to a JSDO instance."); - } - if (this._options.tableRef === undefined && this.jsdo.defaultTableRef) { - this._options.tableRef = this.jsdo.defaultTableRef._name; - } - if (this._options.tableRef === undefined) { - throw new Error("DataSource: A tableRef must be specified when using a multi-table DataSet."); - } - else if (this.jsdo[this._options.tableRef] === undefined) { - throw new Error("DataSource: tableRef '" - + this._options.tableRef + "' is not present in underlying JSDO definition."); - } - this._tableRef = this._options.tableRef; - // Find out the name of 'Count' function from Catalog if defined as 'Count' operation - // instead of an INVOKE - if (this._options.countFnName !== undefined) { - if (typeof (this.jsdo[this._options.countFnName]) !== "function") { - throw new Error("Invoke operation '" + - this._options.countFnName + "' for countFnName is not defined."); - } - } - else if (this.jsdo["_resource"].generic.count !== undefined) { - for (var fnName in this.jsdo["_resource"].fn) { - if (this.jsdo["_resource"].generic.count === this.jsdo["_resource"].fn[fnName]["function"]) { - this._options.countFnName = fnName; - break; - } - } - } - this._initConvertTypes(); - } - // _convertStringToDate: - DataSource.prototype._convertStringToDate = function (data, fieldName, targetFieldName) { - var transport = this; - var array, ablType, orig; - if (!targetFieldName) { - targetFieldName = fieldName; - } - // Check if string is -- - array = transport._convertFields._datePattern.exec(data[targetFieldName]) || []; - if (array.length > 0) { - data[targetFieldName] = new Date(parseInt(array[1], 10), parseInt(array[2], 10) - 1, parseInt(array[3], 10)); - } - else { - ablType = transport.jsdo[transport._tableRef]._fields[fieldName.toLowerCase()].ablType; - if (ablType === "DATETIME") { - array = transport._convertFields._dateTimePattern.exec(data[targetFieldName]) || []; - if (array.length > 0) { - // Convert date to local time zone - data[targetFieldName] = new Date(parseInt(array[1], 10), parseInt(array[2], 10) - 1, parseInt(array[3], 10), parseInt(array[4], 10), parseInt(array[5], 10), parseInt(array[6], 10), parseInt(array[7], 10)); - } - } - // Check to see if it was converted - if (typeof (data[targetFieldName]) === "string") { - orig = data[targetFieldName]; - try { - data[targetFieldName] = new Date(data[targetFieldName]); - } - catch (e) { - // Conversion to a date object was not successful - data[targetFieldName] = orig; - console.log("DataSource: Internal Error: _convertStringToDate() could not convert to date object: " + orig); - } - } - } - }; - // _convertDataTypes: - // Converts data types in the specified data record. - // Data record could come from the JSDO or from the Kendo UI DataSource. - // Returns a reference to the record. - // Returns a copy when useArrays is undefined or false. - DataSource.prototype._convertDataTypes = function (data) { - var transport = this; - var i, k, fieldName, schemaInfo, prefixElement, elementName, copy; - // Use transport_jsdo as any to avoid exposing internal JSDO methods - var transport_jsdo = transport.jsdo; - if (!transport.useArrays && transport._convertTypes && (transport._convertFields._arrayFields.length > 0)) { - copy = {}; - transport_jsdo._copyRecord(transport_jsdo._buffers[transport._tableRef], data, copy); - data = copy; - } - if (!transport._convertTypes) { - return data; - } - for (k = 0; k < transport._convertFields._arrayFields.length; k += 1) { - fieldName = transport._convertFields._arrayFields[k]; - if (data[fieldName]) { - schemaInfo = transport.jsdo[transport._tableRef]._fields[fieldName.toLowerCase()]; - prefixElement = transport_jsdo._getArrayField(fieldName); - for (i = 0; i < schemaInfo.maxItems; i += 1) { - // ABL arrays are 1-based - elementName = prefixElement.name + (i + 1); - if (!transport.jsdo[transport._tableRef]._fields[elementName.toLowerCase()]) { - // Skip element if a field with the same name exists - // Extract value from array field into individual field - // Array is removed later - data[elementName] = data[fieldName][i]; - // Convert string DATE fields to JS DATE - if ((schemaInfo.ablType) - && (schemaInfo.ablType.indexOf("DATE") === 0) && (typeof (data[elementName]) === "string")) { - transport._convertStringToDate(data, fieldName, elementName); - } - } - } - if (!transport.useArrays) { - delete data[fieldName]; - } - } - } - for (k = 0; k < transport._convertFields._dateFields.length; k += 1) { - fieldName = transport._convertFields._dateFields[k]; - if (typeof (data[fieldName]) === "string") { - transport._convertStringToDate(data, fieldName); - } - } - return data; - }; - // _initConvertTypes: - // Initializes transport._convertTypes to indicate whether a conversion of the data is needed - // when it is passed to Kendo UI. - // This operation is currently only needed for date fields that are stored as strings. - // Sets array _dateFields to the fields of date fields to convert. - DataSource.prototype._initConvertTypes = function () { - var transport = this; - var i, schema, fieldName, convertDateFields = false; - var dateFields = [], arrayFields = []; - transport._convertTypes = false; - schema = transport.jsdo[transport._tableRef].getSchema(); - for (i = 0; i < schema.length; i += 1) { - fieldName = schema[i].name; - if (fieldName.length > 0 && fieldName.charAt(0) !== "_") { - if (schema[i].type === "string" && - schema[i].format && - (schema[i].format.indexOf("date") !== -1)) { - dateFields.push(fieldName); - if (!convertDateFields) { - convertDateFields = true; - } - } - else if (!transport.useArrays && schema[i].type === "array") { - arrayFields.push(fieldName); - if (!convertDateFields && schema[i].ablType && - schema[i].ablType.indexOf("DATE") === 0) { - convertDateFields = true; - } - } - } - } - if (dateFields.length > 0 || arrayFields.length > 0) { - transport._convertTypes = true; - // _convertFields: Object containing arrays for each data type to convert - transport._convertFields = {}; - transport._convertFields._arrayFields = []; - transport._convertFields._dateFields = []; - } - if (dateFields.length > 0) { - transport._convertFields._dateFields = dateFields; - } - if (convertDateFields) { - transport._convertFields._datePattern = new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?$"); - transport._convertFields._dateTimePattern = new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?" + - "T([0-9]{2})?:([0-9]{2})?:([0-9]{2})?.([0-9]{3})?$"); - } - if (arrayFields.length > 0) { - transport._convertFields._arrayFields = arrayFields; - } - }; - /** - * Calls the jsdo.fill() retrieving data from the backend service - * @returns An Observable which includes an Array followed - * by an attribute for specifying 'total' records - */ - DataSource.prototype.read = function (params) { - var _this = this; - var wrapperPromise; - var obs; - var filter = {}; - var jsdo = this.jsdo; - var tableRef = this._tableRef; - // If this is a DataSource for a child table, check if read() was performed on parent - if (!this._initFromServer) { - if (jsdo[tableRef]._parent) { - this._initFromServer = (jsdo[jsdo[tableRef]._parent]._data && - (jsdo[jsdo[tableRef]._parent]._data.length > 0)) - || (jsdo[tableRef]._data instanceof Array && (jsdo[tableRef]._data.length > 0)); - } - else { - this._initFromServer = (jsdo[tableRef]._data instanceof Array) && (jsdo[tableRef]._data.length > 0); - } - } - if (this.readLocal && this._initFromServer) { - return Observable_1.Observable.create(function (observer) { - var data = _this.getJsdoData(); - observer.next({ data: data, total: data.length }); - }); - } - if (params && Object.keys(params).length > 0) { - filter = params; - } - else { - // If params has no properties, use default values for filter criteria - if (this._options.filter || this._options.sort || this._options.top || this._options.skip) { - filter.filter = this._options.filter; - filter.sort = this._options.sort; - filter.top = this._options.top; - filter.skip = this._options.skip; - } - else { - filter = undefined; - } - } - // tableRef required for multi-table DataSets - if (filter) { - filter.tableRef = this._tableRef; - } - wrapperPromise = new Promise(function (resolve, reject) { - jsdo.fill(filter) - .then(function (result) { - // Verifying the latest resultset value and setting _isLastResultSetEmpty flag if empty - if (result.request.response[_this.jsdo["_dataSetName"]][_this._tableRef] - && result.request.response[_this.jsdo["_dataSetName"]][_this._tableRef].length === 0) { - _this._isLastResultSetEmpty = true; - } - else if (result.request.response[_this.jsdo["_dataSetName"]] - && result.request.response[_this.jsdo["_dataSetName"]][_this._tableRef] === undefined) { - _this._isLastResultSetEmpty = true; - } - else if (result.request.response[_this.jsdo["_dataSetName"]][_this._tableRef] - && result.request.response[_this.jsdo["_dataSetName"]][_this._tableRef].length !== 0) { - _this._isLastResultSetEmpty = false; - } - _this._initFromServer = true; - var data = _this.getJsdoData(); - // Only call count() function if paging is being used - // Paging is only used if the skip and top is being used during the fill. - if (typeof params !== "undefined" && - (typeof _this._options.countFnName !== "undefined" && typeof params.skip !== "undefined" && typeof params.top !== "undefined") - && !(params.skip === 0 && params.top > data.length)) { - _this.getRecCount(_this._options.countFnName, { filter: result.request.objParam ? result.request.objParam.filter : undefined }) - .then(function (res) { - if (res === undefined && res == null) { - reject(_this.normalizedErrorObj(res, "Unexpected response from 'Count Function' Operation", "")); - } - else { - resolve({ data: data, total: res }); - } - }, function (error) { - reject(_this.normalizedErrorObj(error, "Problems invoking getRecCount function", "")); - }).catch(function (e) { - reject(_this.normalizedErrorObj(e, "Unknown error occurred calling count.", "")); - }); - } - else { - // Client side operations - resolve({ data: data, total: data.length }); - } - }).catch(function (result) { - reject(_this.normalizedErrorObj(result, "read", "")); - }); - }); - obs = Observable_1.Observable.fromPromise(wrapperPromise); - obs.catch(function (e) { - return []; - }); - return obs; - }; - /** - * Returns array of record objects from local memory - * @returns Array - */ - DataSource.prototype.getData = function () { - return this.getJsdoData(); - }; - /** - * Calls the jsdo.add() method, creating a new record in JSDO memory - * jsdo.add() will either return the new record, or throws an exception - * @param data - Record to create is passed as an object - * @returns - If successful, an object of the new record is returned - */ - DataSource.prototype.create = function (data) { - var jsRecord; - var newRow = {}; - var saveUseRelationships = this.jsdo.useRelationships; - try { - this.jsdo.useRelationships = false; - jsRecord = this.jsdo[this._tableRef].add(data); - this._copyRecord(jsRecord.data, newRow); - } - catch (error) { - if (this.jsdo.autoApplyChanges) { - this.jsdo[this._tableRef].rejectChanges(); - } - throw error; - } - finally { - this.jsdo.useRelationships = saveUseRelationships; - } - return newRow; - }; - /** - * Returns a copy of the record with the specified id. - * Note: current implementation uses jsdo's internal _id as id. - * @param id - id of record - * @returns - copy of record with specified id, else null if no record found - */ - DataSource.prototype.findById = function (id) { - var jsRecord; - var row = {}; - // For now, we are using _id as our id to find records.. - jsRecord = this.jsdo[this._options.tableRef].findById(id, false); - if (jsRecord) { - this._copyRecord(jsRecord.data, row); - return row; - } - else { - return null; - } - }; - /** - * Calls the jsdo.update() method, for updating a record in JSDO memory - * jsdo.update() will either return the updated record, or throws an exception - * @param data - Record to create is passed as an object - * @returns - boolean. True if successful, false if there is any failure - */ - DataSource.prototype.update = function (data) { - var saveUseRelationships = this.jsdo.useRelationships; - if (!data && (data === undefined || null)) { - throw new Error("Unexpected signature for update() operation."); - } - var id = (data && data._id) ? data._id : null; - var jsRecord; - var retVal = false; - if (!id) { - throw new Error("DataSource.update(): data missing _id property"); - } - try { - this.jsdo.useRelationships = false; - jsRecord = this.jsdo[this._tableRef].findById(id); - if (jsRecord) { - // Found a valid record. Lets update now - retVal = jsRecord.assign(data); - this.jsdo.useRelationships = saveUseRelationships; - } - else { - throw new Error("DataSource.update(): Unable to find record with this id " + id); - } - } - catch (error) { - if (this.jsdo.autoApplyChanges) { - this.jsdo[this._tableRef].rejectChanges(); - } - throw error; - } - finally { - this.jsdo.useRelationships = saveUseRelationships; - } - return retVal; - }; - /** - * Deletes a record from JSDO memory by calling jsdo.remove() API. This accepts a record - * with a valid _id without which an error is reported - * @param data Provide valid record for deletion - * @returns boolean - True if the operation succeeds, false otherwise - */ - DataSource.prototype.remove = function (data) { - var retVal = false; - var id = (data && data._id) ? data._id : null; - var saveUseRelationships = this.jsdo.useRelationships; - var jsRecord; - if (!data && (data === undefined || null)) { - throw new Error("Unexpected signature for remove() operation."); - } - if (!id) { - throw new Error("DataSource.remove(): data missing _id property"); - } - try { - this.jsdo.useRelationships = false; - jsRecord = this.jsdo[this._tableRef].findById(id); - if (jsRecord) { - // Found a valid record. Lets delete the record - retVal = jsRecord.remove(data); - } - else { - throw new Error("DataSource.remove(): Unable to find record with this id " + id); - } - } - catch (error) { - if (this.jsdo.autoApplyChanges) { - this.jsdo[this._tableRef].rejectChanges(); - } - throw error; - } - finally { - this.jsdo.useRelationships = saveUseRelationships; - } - return retVal; - }; - /** - * Returns true if the underlying jsdo has CUD support (create, update, delete operations). - * If not, it returns false. - */ - DataSource.prototype.hasCUDSupport = function () { - return this.jsdo.hasCUDOperations; - }; - /** - * Returns true if the underlying jsdo has Submit support (submit operation). - * If not, it returns false. - */ - DataSource.prototype.hasSubmitSupport = function () { - return this.jsdo.hasSubmitOperation; - }; - /** - * Synchronizes to the server all record changes (creates, updates, and deletes) pending in - * JSDO memory for the current Data Object resource - * If jsdo.hasSubmitOperation is false, all record modifications are sent to server individually. - * When 'true', modifications are batched together and sent in single request - * @returns {object} Observable - */ - DataSource.prototype.saveChanges = function () { - var _this = this; - var promise; - var obs; - var promResponse = {}; - var tableRefVal; - promise = new Promise(function (resolve, reject) { - var responseData = {}; - _this.jsdo.saveChanges(_this.jsdo.hasSubmitOperation) - .then(function (result) { - tableRefVal = _this._tableRef; - if (_this.jsdo.hasSubmitOperation) { - // Submit case - _this._copyRecord(result.request.response, responseData); - resolve(responseData); - } - else { - // Non-Submit case - if (result.request && result.request.batch.operations && result.request.batch.operations.length > 0) { - result.request.batch.operations.forEach(function (operation) { - _this._copyRecord(operation.response, responseData); - // In case of multiple operations we want to merge those records pertaining - // to different operations in a single dataset and is sent as part of the - // response object for the consumer of this API. - _this._buildResponse(responseData, promResponse); - }); - resolve(promResponse); - // Scenario where the saveChanges is invoked directly without any Submit/Non-Submit - // service as the serviceURI. We will resolve with an empty object - } - else if (result.request && result.request.batch.operations.length === 0) { - resolve({}); - } - else { - reject(_this - .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); - } - } - }).catch(function (result) { - if (_this.jsdo.autoApplyChanges) { - _this.jsdo[_this._tableRef].rejectChanges(); - } - reject(_this - .normalizedErrorObj(result, "saveChanges", "Errors occurred while saving Changes.")); - }); - }); - obs = Observable_1.Observable.fromPromise(promise); - obs.catch(function (e) { - return []; - }); - return obs; - }; - /** - * First, retrieves data from JSDO local memory - * Then makes a copy of it, to ensure jsdo memory is only manipulated thru DataSource API - * Returns array of record objects - * @returns Array - */ - DataSource.prototype.getJsdoData = function () { - var _this = this; - var jsdo = this.jsdo; - var saveUseRelationships = jsdo.useRelationships; - var data; - var copy; - var array; - jsdo.useRelationships = false; - data = jsdo[this._tableRef].getData(); - jsdo.useRelationships = saveUseRelationships; - // Make copy of jsdo data for datasource - if (this._convertTypes) { - array = []; - data.forEach(function (item) { - if (!_this.useArrays && _this._convertFields._arrayFields.length > 0) { - // Use a reference - // _convertDataTypes() will create the copy for this case - copy = item; - } - else { - copy = Object.assign({}, item); - } - copy = _this._convertDataTypes(copy); - array.push(copy); - }); - data = array; - } - else { - data = (data.length > 0 ? data.map(function (item) { return Object.assign({}, item); }) : []); - } - return data; - }; - /** - * This method is used for fetching the 'count' of records from backend - * This method is used as part of read() operation when serverOperations is set by client - * @param {string} name Name of the method pertaining to 'Count' functionality - * @param {any} object Filter object - */ - DataSource.prototype.getRecCount = function (name, object) { - var _this = this; - var countVal; - var getRecCountPromise; - getRecCountPromise = new Promise(function (resolve, reject) { - _this.jsdo.invoke(name, object) - .then(function (result) { - try { - if (typeof (result.request.response) === "object" - && Object.keys(result.request.response).length === 1) { - countVal = Object.values(result.request.response)[0]; - if (typeof (countVal) !== "number") { - countVal = undefined; - } - } - resolve(countVal); - } - catch (e) { - reject(_this.normalizedErrorObj(e, "getRecCount", "")); - } - }).catch(function (result) { - reject(_this.normalizedErrorObj(result, "Error invoking the 'Count' operation", "")); - }); - }); - return getRecCountPromise; - }; - /** - * This method is called after an error has occurred on a jsdo operation, and is - * used to get an error message. - * @param {any} result Object containing error info returned after execution of jsdo operation - * @param {string} operation String containing operation performed when error occurred - * @param {string} genericMsg If multiple errors are found in result object, if specified, - * this string will be returned. If not specified, first error string will be returned. - * @returns A single error message - */ - DataSource.prototype.normalizeError = function (result, operation, genericMsg) { - var errorMsg = ""; - var lastErrors = null; - try { - if (result.info && result.info.errorObject) { - errorMsg = result.info.errorObject.message; - } - else if (result.jsdo) { - lastErrors = result.jsdo[this._tableRef].getErrors(); - if (lastErrors.length >= 1) { - // If generic message is provided, use that, else we'll just grab first message - if (lastErrors.length > 1 && genericMsg) { - errorMsg = genericMsg; - } - else { - errorMsg = lastErrors[0].error; - } - } - } - else if (result.message) { - errorMsg = result.message; - } - if (errorMsg === "") { - errorMsg = "Unknown error occurred when calling " + operation + "."; - } - } - catch (error) { - errorMsg = error.message; - } - return errorMsg; - }; - /** - * This method is called after an error has occurred on a jsdo operation, and is - * used to get an error object. - * @param {any} result Object containing error info returned after execution of jsdo operation - * @param {string} operation String containing operation performed when error occurred - * @param {string} genericMsg If multiple errors are found in result object, if specified, - * this string will be returned as part of the new error object. If not specified, first error - * string will be returned. - * @returns A single error object with all information - */ - DataSource.prototype.normalizedErrorObj = function (result, operation, genericMsg) { - var errorObj = {}; - var eMsg = ""; - var object = {}; - if (result && result.jsdo && result.success == false) { - object = result.request; - } - eMsg = this.normalizeError(result, operation, genericMsg); - errorObj = new Error(eMsg); - errorObj.info = object; - return errorObj; - }; - DataSource.prototype._copyRecord = function (source, target) { - var field; - var newObject; - if (!target) { - console.log("_copyRecord: target parameter is not defined"); - return; - } - for (field in source) { - if (source.hasOwnProperty(field)) { - // Ignore all internal fields, except _id - if (source[field] === undefined || source[field] === null || - (field.charAt(0) === "_" && field !== "_id") || - field.startsWith("prods:")) { - continue; - } - if (source[field] instanceof Date) { - target[field] = source[field]; - } - else if (typeof source[field] === "object") { - newObject = source[field] instanceof Array ? [] : {}; - this._copyRecord(source[field], newObject); - target[field] = newObject; - } - else { - target[field] = source[field]; - } - } - } - }; - /** - * This method is responsible for building a valid responseObject when multiple records - * are involved in transaction - * @param source Actual dataset/record to be merged - * @param target Resultant dataset with all records information - */ - DataSource.prototype._buildResponse = function (source, target) { - var newEntry = source; - var firstKey = Object.keys(source)[0]; - var secondKey = (firstKey) ? Object.keys(source[firstKey])[0] : undefined; - // Delete's on no submit services return empty datasets so - // don't add anything. - if (typeof source[firstKey] !== "undefined" - && typeof source[firstKey][secondKey] !== "undefined") { - if (Object.keys(target).length === 0) { - this._copyRecord(source, target); - } - else { - firstKey = Object.keys(target)[0]; - // Delete's on no submit services return empty datasets so - // don't add anything. - if (firstKey && typeof target[firstKey][this._tableRef] !== "undefined") { - // Dataset usecase - if (firstKey !== this._tableRef) { - target[firstKey][this._tableRef].push(newEntry[firstKey][this._tableRef][0]); - } - else { - target[this._tableRef].push(newEntry[this._tableRef][0]); - } - return target; - } - } - } - }; - DataSource = __decorate([ - core_1.Injectable() - ], DataSource); - return DataSource; -}()); -exports.DataSource = DataSource; From 50238c58bd4dc89788d2563d10aad7e0525b49ab Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 17:58:10 -0400 Subject: [PATCH 59/84] Removing jsdo-nativescript dependency Removing jsdo-nativescript dependency --- packages/ng-datasource/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index f0b072e..da3b317 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -39,8 +39,7 @@ "url": "https://github.com/progress/JSDO/issues" }, "homepage": "https://github.com/progress/JSDO#readme", - "dependencies": { - "@progress/jsdo-nativescript": "^6.0.0-0", + "dependencies": { "base-64": "^0.1.0", "node-localstorage": "^1.3.1", "xmlhttprequest": "^1.8.0" From b4ff7e1218a71095a63fd23e99613e317df31e53 Mon Sep 17 00:00:00 2001 From: Anil Date: Mon, 24 Sep 2018 18:20:05 -0400 Subject: [PATCH 60/84] Update package.json --- packages/ng-datasource/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index da3b317..06e7499 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -39,7 +39,8 @@ "url": "https://github.com/progress/JSDO/issues" }, "homepage": "https://github.com/progress/JSDO#readme", - "dependencies": { + "dependencies": { + "@progress/jsdo-core": "^6.0.0", "base-64": "^0.1.0", "node-localstorage": "^1.3.1", "xmlhttprequest": "^1.8.0" From 7bdc28a14ca2638a862079af689ebe892a51d7c1 Mon Sep 17 00:00:00 2001 From: Edsel Garcia Cyntje Date: Tue, 25 Sep 2018 10:34:22 -0400 Subject: [PATCH 61/84] Workaround for FilterOptions --- typings/progress.all.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 342728f..2cd8d8a 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -943,10 +943,12 @@ export module progress { } interface FilterOptions { - filter?: string | FilterOption | FilterOption[]; + // filter?: string | FilterOption | FilterOption[]; + filter?: any; id?: string; skip?: number; - sort?: SortOption | SortOption[]; + // sort?: SortOption | SortOption[]; + sort?: any; top?: number; tableRef?: string; } From f27cadac6e45667e54f6c5a8601ecd563d8b784d Mon Sep 17 00:00:00 2001 From: joshualan Date: Tue, 25 Sep 2018 13:59:21 -0400 Subject: [PATCH 62/84] Updated the typings file --- typings/progress.all.d.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 342728f..c46c303 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -1,5 +1,5 @@ /** - * Type definitions for progress.js 5.0 library. This is part of progress.all.js + * Type definitions for progress.js 6.0 library. This is part of progress.all.js * Project: Progress JSDO * Definitions by: egarcia, Traveleye, anikumar */ @@ -943,12 +943,13 @@ export module progress { } interface FilterOptions { - filter?: string | FilterOption | FilterOption[]; + filter?: string | FilterOptions | FilterOption | FilterOption[]; id?: string; skip?: number; sort?: SortOption | SortOption[]; top?: number; tableRef?: string; + logic?: string; } interface FilterOption { @@ -961,7 +962,7 @@ export module progress { interface SortOption { field: string; - dir: string; + dir?: string; } interface JSDORequest { From 18c82df29c387de127ba0e72f626fb959ab08cef Mon Sep 17 00:00:00 2001 From: joshualan Date: Tue, 25 Sep 2018 14:17:19 -0400 Subject: [PATCH 63/84] Updated headers and readme's --- package.json | 2 +- packages/core/readme.md | 2 +- packages/ng-datasource/src/progress.data.ng.ds.ts | 4 ++-- readme.md | 2 +- src/auth/progress.auth.basic.js | 2 +- src/auth/progress.auth.form.js | 2 +- src/auth/progress.auth.js | 2 +- src/auth/progress.auth.sso.js | 2 +- src/progress.data.kendo.js | 2 +- src/progress.js | 2 +- src/progress.session.js | 2 +- src/progress.util.js | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 5037c0c..2a037c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@progress/jsdo", - "version": "5.0.1", + "version": "6.0.0", "description": "The JSDO is a JavaScript implementation of the CDO Specification published by Progress Software Corporation.\r The JSDO is a free and open-source full-featured implementation that can be used in web, mobile web and hybrid mobile apps.", "main": "lib/progress.all.min.js", "files": [ diff --git a/packages/core/readme.md b/packages/core/readme.md index 5ffffc2..e6e89ed 100644 --- a/packages/core/readme.md +++ b/packages/core/readme.md @@ -7,7 +7,7 @@ Progress® Data Objects, which include the JSDO on the client, represent the Pro ### JSDO and OpenEdge compatibility | JSDO version | OpenEdge version | |----|----| -| 5.0.0 | 11.6.4, 11.7.x | +| 6.0.0, 5.0.0 | 11.6.4, 11.7.x | ### Download You can download a copy of the full JSDO to a zip file or the individual files below. diff --git a/packages/ng-datasource/src/progress.data.ng.ds.ts b/packages/ng-datasource/src/progress.data.ng.ds.ts index 77e4c4a..b76ada3 100644 --- a/packages/ng-datasource/src/progress.data.ng.ds.ts +++ b/packages/ng-datasource/src/progress.data.ng.ds.ts @@ -1,5 +1,5 @@ /* -Progress Progress Data Source for Angular: 5.0.0 +Progress Progress Data Source for Angular: 6.0.0 Copyright 2017-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -progress.data.ng.ds.ts Version: v5.0.0 +progress.data.ng.ds.ts Version: v6.0.0 Progress Data Source class for NativeScript, Angular. This will provide a seamless integration between OpenEdge (Progress Data Object) with NativeScript. diff --git a/readme.md b/readme.md index e21d7e2..953af28 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ Progress® Data Objects, which include the JSDO on the client, represent the Pro ### JSDO and OpenEdge compatibility | JSDO version | OpenEdge version | |----|----| -| 5.0.0 | 11.6.3, 11.7.x | +| 6.0.0, 5.0.0 | 11.6.3, 11.7.x | ### Download You can download a copy of the full JSDO to a zip file or the individual files below. diff --git a/src/auth/progress.auth.basic.js b/src/auth/progress.auth.basic.js index 43900ef..eb1fe80 100644 --- a/src/auth/progress.auth.basic.js +++ b/src/auth/progress.auth.basic.js @@ -1,5 +1,5 @@ /* -progress.auth.basic.js Version: 4.4.0-3 +progress.auth.basic.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/auth/progress.auth.form.js b/src/auth/progress.auth.form.js index 24cc1d9..f429258 100644 --- a/src/auth/progress.auth.form.js +++ b/src/auth/progress.auth.form.js @@ -1,5 +1,5 @@ /* -progress.auth.form.js Version: 5.0.0 +progress.auth.form.js Version: 6.0.0 Copyright (c) 2016-2018 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/auth/progress.auth.js b/src/auth/progress.auth.js index 03f71a4..0c4b4e4 100644 --- a/src/auth/progress.auth.js +++ b/src/auth/progress.auth.js @@ -1,5 +1,5 @@ /* -progress.auth.js Version: 4.4.0-3 +progress.auth.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/auth/progress.auth.sso.js b/src/auth/progress.auth.sso.js index ff9bbee..80d1485 100644 --- a/src/auth/progress.auth.sso.js +++ b/src/auth/progress.auth.sso.js @@ -1,5 +1,5 @@ /* -progress.auth.sso.js Version: 4.4.0-3 +progress.auth.sso.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/progress.data.kendo.js b/src/progress.data.kendo.js index f2c84c5..58c2845 100644 --- a/src/progress.data.kendo.js +++ b/src/progress.data.kendo.js @@ -1,6 +1,6 @@ /* -progress.data.kendo.js Version: 5.0.0 +progress.data.kendo.js Version: 6.0.0 Copyright (c) 2015-2018 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/progress.js b/src/progress.js index 40dd8d3..bedf69f 100644 --- a/src/progress.js +++ b/src/progress.js @@ -1,5 +1,5 @@ /* -progress.js Version: 5.0.0 +progress.js Version: 6.0.0 Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/progress.session.js b/src/progress.session.js index f7efc13..2582a54 100644 --- a/src/progress.session.js +++ b/src/progress.session.js @@ -1,5 +1,5 @@ /* -progress.session.js Version: 5.0.0 +progress.session.js Version: 6.0.0 Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. diff --git a/src/progress.util.js b/src/progress.util.js index 948bb55..9936f9e 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -1,7 +1,7 @@ /*eslint no-global-assign: ["error", {"exceptions": ["localStorage"]}]*/ /*global XMLHttpRequest:true, require, console, localStorage:true, sessionStorage:true, $:true, Promise, setTimeout */ /* -progress.util.js Version: 5.0.0 +progress.util.js Version: 6.0.0 Copyright (c) 2014-2018 Progress Software Corporation and/or its subsidiaries or affiliates. From a364c66ce55849cf3d522c4e15fd80beec305c2f Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 25 Sep 2018 15:15:42 -0400 Subject: [PATCH 64/84] Update progress.all.d.ts --- typings/progress.all.d.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/typings/progress.all.d.ts b/typings/progress.all.d.ts index 443f9e4..c46c303 100644 --- a/typings/progress.all.d.ts +++ b/typings/progress.all.d.ts @@ -946,8 +946,7 @@ export module progress { filter?: string | FilterOptions | FilterOption | FilterOption[]; id?: string; skip?: number; - // sort?: SortOption | SortOption[]; - sort?: any; + sort?: SortOption | SortOption[]; top?: number; tableRef?: string; logic?: string; From b621627b10035b49001c55c7aa38ebb4576fc06e Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 25 Sep 2018 16:28:02 -0400 Subject: [PATCH 65/84] Updating gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0b9d2fd..2f350c6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ scratch1/ scratch2/ build/ packages/ng-datasource/package-lock.json + +**/tsFiles \ No newline at end of file From b282236924e4dc20b7f249f29c9880833c3c34b1 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Tue, 25 Sep 2018 17:30:34 -0400 Subject: [PATCH 66/84] Updated pkacage.json --- packages/ng-datasource/package.json | 2 +- packages/ng-datasource/tsconfig.json | 3 ++- packages/node/package.json | 2 +- packages/node/test/smoke.datasource.js | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/ng-datasource/package.json b/packages/ng-datasource/package.json index 06e7499..6e3ea9f 100644 --- a/packages/ng-datasource/package.json +++ b/packages/ng-datasource/package.json @@ -12,7 +12,7 @@ ], "scripts": { "build": "tsc", - "build:ds": "mkdirp build && concat -o build/progress.data.node.js src/progress.data.ng.ds.js", + "build:ds": "tsc --p ../ng-datasource && mkdirp build && concat -o build/progress.data.node.js ../ng-datasource/tsFiles/progress.data.ng.ds.js", "test": "npm run build:ds && mocha --recursive", "test:smokes": "npm run build:ds && mocha test/smoke*.js", "test:tc": "npm run build:ds && mocha --recursive --reporter mocha-teamcity-reporter", diff --git a/packages/ng-datasource/tsconfig.json b/packages/ng-datasource/tsconfig.json index 796ebd1..7cb4bcd 100644 --- a/packages/ng-datasource/tsconfig.json +++ b/packages/ng-datasource/tsconfig.json @@ -24,6 +24,7 @@ "exclude": [ "node_modules", "platforms", - "**/*.aot.ts" + "**/*.aot.ts", + "tsFiles" ] } diff --git a/packages/node/package.json b/packages/node/package.json index b5011aa..0a63870 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -11,7 +11,7 @@ "typings/" ], "scripts": { - "build:ds": "mkdirp build && concat -o build/progress.data.node.js ../ng-datasource/src/progress.data.ng.ds.js", + "build:ds": "tsc --p ../ng-datasource && mkdirp build && concat -o build/progress.data.node.js ../ng-datasource/tsFiles/progress.data.ng.ds.js", "test": "npm run build:ds && mocha --recursive", "test:smokes": "npm run build:ds && mocha test/smoke*.js", "test:tc": "npm run build:ds && mocha --recursive --reporter mocha-teamcity-reporter", diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index f948e04..db7d52e 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -13,7 +13,7 @@ describe('Datasource Smoke Tests', function () { //options all the info required for creating a jsdo session const options = { serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", - catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", + catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/SportsService3.json", resourceName: "Customer", authenticationModel: "anonymous", tableRef: "ttCustomer", @@ -83,7 +83,7 @@ describe('Datasource Smoke Tests', function () { // _id: '1537314778768-1' } let testRec = { - CustNum: '', + CustNum: 100000, Name: options.recName, State: 'MA', Balance: 0 @@ -211,7 +211,7 @@ describe('Datasource Smoke Tests', function () { } }); console.log(found); - }); + }, () => console.log("jsdo remove")); }); setTimeout(() => { From 6853cdb930a0271c5d7fa564c8479b1effe99c2c Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 26 Sep 2018 14:04:42 -0400 Subject: [PATCH 67/84] removed base64 dependency --- packages/angular/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index 2e54d35..fc3976c 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -33,8 +33,7 @@ }, "homepage": "https://github.com/progress/JSDO#readme", "dependencies": { - "@progress/jsdo-core": "^6.0.0", - "base-64": "^0.1.0" + "@progress/jsdo-core": "^6.0.0" }, "peerDependencies": { "@angular/core": "^6.1.0", From 9fae0d1af555cebf72918956be7412c6d7a8c602 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 26 Sep 2018 16:35:01 -0400 Subject: [PATCH 68/84] Changed "base-64" to "" + pkg_base64 in requires --- src/progress.util.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/progress.util.js b/src/progress.util.js index 9936f9e..ffd5de9 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -47,6 +47,7 @@ limitations under the License. pkg_nodeLocalstorage = "node-localstorage", pkg_nativescriptLocalstorage = "nativescript-localstorage", pkg_fileSystemAccess = "file-system/file-system-access" + pkg_base64 = "base-64" ; // If XMLHttpRequest is undefined, enviroment would appear to be Node.js @@ -97,7 +98,7 @@ limitations under the License. // load module base-64 try { if (typeof btoa === "undefined") { - btoa = require("base-64").encode; + btoa = require("" + pkg_base64).encode; } } catch(exception3) { console.error("Error: JSDO library requires btoa() function in NativeScript.\n" @@ -127,7 +128,7 @@ limitations under the License. // load module base-64 try { if (typeof btoa === "undefined") { - btoa = require("base-64").encode; + btoa = require("" + pkg_base64).encode; } } catch(exception3) { console.error("Error: JSDO library requires btoa() function in Node.js.\n" From f17a15013de0d185b653472c5cd0fe96136508bf Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Wed, 26 Sep 2018 16:38:11 -0400 Subject: [PATCH 69/84] Added comma --- src/progress.util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/progress.util.js b/src/progress.util.js index ffd5de9..aa622cb 100644 --- a/src/progress.util.js +++ b/src/progress.util.js @@ -46,7 +46,7 @@ limitations under the License. var pkg_xmlhttprequest = "xmlhttprequest", pkg_nodeLocalstorage = "node-localstorage", pkg_nativescriptLocalstorage = "nativescript-localstorage", - pkg_fileSystemAccess = "file-system/file-system-access" + pkg_fileSystemAccess = "file-system/file-system-access", pkg_base64 = "base-64" ; From 18cb9276693ff14227253ffa3da7bc8b07676519 Mon Sep 17 00:00:00 2001 From: Anil Date: Thu, 27 Sep 2018 12:25:20 -0400 Subject: [PATCH 70/84] Updated service to use PASOE Docker container Updated service to use PASOE Docker container --- packages/node/test/smoke.datasource.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index db7d52e..efec2f5 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -12,8 +12,9 @@ chai.use(chaiAsPromised); describe('Datasource Smoke Tests', function () { //options all the info required for creating a jsdo session const options = { - serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", - catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/SportsService3.json", + // These services are running in Docker + serviceURI: "https://172.29.18.125:8894/OEMobileDemoServices", + catalogURI: "https://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json", resourceName: "Customer", authenticationModel: "anonymous", tableRef: "ttCustomer", From a663e2dfb662354151110cc9a9a1f6176db02f12 Mon Sep 17 00:00:00 2001 From: Anil Date: Thu, 27 Sep 2018 16:38:38 -0400 Subject: [PATCH 71/84] Fixed issues related to Datasource test Fixed issues related to Datasource test --- packages/node/test/smoke.datasource.js | 90 ++++++++++++++------------ 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index efec2f5..26af5ca 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -13,12 +13,12 @@ describe('Datasource Smoke Tests', function () { //options all the info required for creating a jsdo session const options = { // These services are running in Docker - serviceURI: "https://172.29.18.125:8894/OEMobileDemoServices", - catalogURI: "https://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json", + serviceURI: "http://172.29.18.125:8894/OEMobileDemoServices", + catalogURI: "http://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json", resourceName: "Customer", authenticationModel: "anonymous", tableRef: "ttCustomer", - recName: "test9001" //+ (Math.random() * 100) + recName: "test9011" //+ (Math.random() * 100) }; //define your variables required for the tests below @@ -31,7 +31,9 @@ describe('Datasource Smoke Tests', function () { progress.data.getSession(options).then((object) => { session = object.jsdosession; }).then(() => { - jsdo = new progress.data.JSDO({ name: options.resourceName }); + jsdo = new progress.data.JSDO({ + name: options.resourceName + }); }).then(() => done(), () => done()); }); @@ -76,12 +78,6 @@ describe('Datasource Smoke Tests', function () { describe('DataSource Create tests', function () { it('should successfully call create()', function () { - // { CustNum: 1, - // Country: 'Mexico', - // Name: 'NewItem', - // ... - // id: '0x0000000000000062', - // _id: '1537314778768-1' } let testRec = { CustNum: 100000, @@ -113,7 +109,7 @@ describe('Datasource Smoke Tests', function () { if (count === 1) { // Save the element for the update test later - rec = element; + rec = element; } }); @@ -123,9 +119,13 @@ describe('Datasource Smoke Tests', function () { describe('DataSource Update tests', function () { it('should successfully call update()', function () { + // console.log("Before addition", rec); rec.Country = "TestCountry"; - expect(dataSource.update(rec).Country).to.deep.equal(rec.Country); + // console.log("After addition", rec); + + // expect(dataSource.update(rec).Country).to.deep.equal(rec.Country); + expect(dataSource.update(rec)).to.deep.equal(true); }); it('should successfully call saveChanges()', function () { @@ -142,8 +142,8 @@ describe('Datasource Smoke Tests', function () { it('should successfully update a single record in the backend', function () { let count = 0; dataSource.getData().forEach(element => { - if (element.Name === options.recName - && element.Country === "TestCountry") { + if (element.Name === options.recName && + element.Country === "TestCountry") { count += 1; } @@ -182,38 +182,44 @@ describe('Datasource Smoke Tests', function () { return expect(remove).to.eventually.be.true; }); - it('should successfully update a single record in the backend', function () { - let count = 0; - dataSource.getData().forEach(element => { - if (element.Name === options.recName) { - count += 1; - } - }); + setTimeout(() => { + it('should successfully remove record in the backend', function () { + let count = 0; + dataSource.getData().forEach(element => { + if (element.Name === options.recName) { + count += 1; + console.log("Count val: ", count); + console.log("elementName", element.Name); + } + }); - return expect(count).to.equal(0); - }); - }); + return expect(count).to.equal(0); + }); + }, 3000); + }); after(function (done) { this.timeout(5000); - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === options.recName) { - customer.remove(); - } - - jsdo.saveChanges().then((object) => { - return jsdo.fill(); - }).then((object) => { - console.log(object); - let found = 0; - jsdo.ttCustomer.foreach((customer) => { - if (customer.data.Name === options.recName) { - found += 1; - } - }); - console.log(found); - }, () => console.log("jsdo remove")); - }); + // jsdo.ttCustomer.foreach((customer) => { + // if (customer.data.Name === options.recName) { + // customer.remove(); + // } + + // jsdo.saveChanges().then((object) => { + // return jsdo.fill(); + // }).then((object) => { + // console.log(object); + // let found = 0; + // jsdo.ttCustomer.foreach((customer) => { + // if (customer.data.Name === options.recName) { + // found += 1; + // } + // }); + // console.log(found); + // }, () => console.log("jsdo remove")); + // }); + + // session.invalidate(); setTimeout(() => { session.invalidate().then(() => done()); From 7d9f6cc35774106ee9cebad0598fb3737f419788 Mon Sep 17 00:00:00 2001 From: Anil Date: Thu, 27 Sep 2018 16:41:14 -0400 Subject: [PATCH 72/84] Updated service to use Docker container service Instead of using oemobiledemo, now test uses a service running in Docker container --- packages/node/test/regressions/ADAS-7282.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/node/test/regressions/ADAS-7282.js b/packages/node/test/regressions/ADAS-7282.js index 4fca16d..9bd1f04 100755 --- a/packages/node/test/regressions/ADAS-7282.js +++ b/packages/node/test/regressions/ADAS-7282.js @@ -14,8 +14,8 @@ chai.use(chaiAsPromised); describe('ADAS-7282: DataSource invokes count operation bug', function () { //options all the info required for creating a jsdo session const options = { - serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", - catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/SportsService3.json", + serviceURI: "http://172.29.18.125:8894/OEMobileDemoServices", + catalogURI: "http://172.29.18.125:8894/OEMobileDemoServices/static/SportsService.json", resourceName: "SalesRep", authenticationModel: "anonymous", tableRef: "ttSalesRep" From efc174ea68727ae9373c539e3b44a57ce4f5ca9f Mon Sep 17 00:00:00 2001 From: Anil Date: Thu, 27 Sep 2018 17:28:31 -0400 Subject: [PATCH 73/84] Update smoke.datasource.js --- packages/node/test/smoke.datasource.js | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index 26af5ca..f24abc9 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -200,27 +200,7 @@ describe('Datasource Smoke Tests', function () { after(function (done) { this.timeout(5000); - // jsdo.ttCustomer.foreach((customer) => { - // if (customer.data.Name === options.recName) { - // customer.remove(); - // } - - // jsdo.saveChanges().then((object) => { - // return jsdo.fill(); - // }).then((object) => { - // console.log(object); - // let found = 0; - // jsdo.ttCustomer.foreach((customer) => { - // if (customer.data.Name === options.recName) { - // found += 1; - // } - // }); - // console.log(found); - // }, () => console.log("jsdo remove")); - // }); - - // session.invalidate(); - + setTimeout(() => { session.invalidate().then(() => done()); }, 1500); From c9ab72ed81b37f7c24cc128d5da3347c7eb6cc0a Mon Sep 17 00:00:00 2001 From: Nicolette Date: Tue, 2 Oct 2018 17:07:39 -0400 Subject: [PATCH 74/84] fix to handle timeout --- src/progress.session.js | 48 ++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/progress.session.js b/src/progress.session.js index 2582a54..7c29838 100644 --- a/src/progress.session.js +++ b/src/progress.session.js @@ -4763,22 +4763,15 @@ limitations under the License. try { jsdosession = new progress.data.JSDOSession(options); - try { - jsdosession.isAuthorized() - .then(function() { - return jsdosession.addCatalog(options.catalogURI); - }, sessionRejectHandler) - .then(function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); - }, sessionRejectHandler); - } catch (e) { - sessionRejectHandler( - jsdosession, - progress.data.Session.GENERAL_FAILURE, - {errorObject: e} - ); - } + jsdosession.isAuthorized() + .then(function() { + return jsdosession.addCatalog(options.catalogURI); + }, sessionRejectHandler) + .then(function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); + }, sessionRejectHandler); + } catch (ex) { sessionRejectHandler( jsdosession, @@ -4904,7 +4897,28 @@ limitations under the License. options.authProvider = authProvider; if (authProvider.hasClientCredentials()) { - loginHandler(authProvider); + // FAKE SESSION + let jsdosession = new progress.data.JSDOSession(options); + + // This is a band-aid. We need to refactor and re-modularize + // getSession() now that the team has a better understanding + // of async operations --aestrada aka yoloswaggins + jsdosession.isAuthorized().then(() => { + jsdosession.invalidate(); + loginHandler(authProvider); + }, + () => { + return Promise.all([ + jsdosession.invalidate(), + options.authProvider.logout() + ]); + }).then((values) => { + if (values) { + authProvider = new progress.data.AuthenticationProvider(authProviderInitObject); + options.authProvider = authProvider; + callLogin(authProvider); + } + }) } else { // If model is anon, just log in. if (authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { From 5702325c67e15186b5923176ee87f59b22b683ac Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 4 Oct 2018 04:52:46 -0400 Subject: [PATCH 75/84] Add notice.txt file --- packages/core/notice.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 packages/core/notice.txt diff --git a/packages/core/notice.txt b/packages/core/notice.txt new file mode 100644 index 0000000..0f482e4 --- /dev/null +++ b/packages/core/notice.txt @@ -0,0 +1,15 @@ +========================================================================= +== NOTICE file corresponding to section 4 d of == +== the Apache License, Version 2.0, == +== in this case for the Progress Data Source Core v6.0 == +========================================================================= +Progress Data Source Core v6.0 + +Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. + +For license information see the LICENSE file which accompanies this NOTICE.txt file. + +Any open source software that may be delivered by Progress Software Corporation embedded in or in association with Progress Data Source Core v6.0 is provided pursuant to the open source license applicable to the software and subject to the disclaimers and limitations on liability set forth in such license. + + + From de859ab86c2127eb358899014c624ffb05b508d3 Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 4 Oct 2018 04:54:56 -0400 Subject: [PATCH 76/84] Update notice.txt --- packages/core/notice.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/notice.txt b/packages/core/notice.txt index 0f482e4..fd9acf8 100644 --- a/packages/core/notice.txt +++ b/packages/core/notice.txt @@ -1,11 +1,11 @@ ========================================================================= == NOTICE file corresponding to section 4 d of == == the Apache License, Version 2.0, == -== in this case for the Progress Data Source Core v6.0 == +== in this case for the Progress JSDO Core Module v6.0 == ========================================================================= -Progress Data Source Core v6.0 +Progress JSDO Core Module v6.0 -Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. +Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. For license information see the LICENSE file which accompanies this NOTICE.txt file. From d3bd833c9022a7f76369f13770108d8975d4fa14 Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 4 Oct 2018 04:56:02 -0400 Subject: [PATCH 77/84] Add notice.txt --- packages/angular/notice.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 packages/angular/notice.txt diff --git a/packages/angular/notice.txt b/packages/angular/notice.txt new file mode 100644 index 0000000..1d9e2a5 --- /dev/null +++ b/packages/angular/notice.txt @@ -0,0 +1,12 @@ +========================================================================= +== NOTICE file corresponding to section 4 d of == +== the Apache License, Version 2.0, == +== in this case for the Progress Data Source for Angular v6.0 == +========================================================================= +Progress Data Source for Angular v6.0 + +Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. + +For license information see the LICENSE file which accompanies this NOTICE.txt file. + +Any open source software that may be delivered by Progress Software Corporation embedded in or in association with Progress Data Source for Angular v6.0 is provided pursuant to the open source license applicable to the software and subject to the disclaimers and limitations on liability set forth in such license. From 01589c426476d611634e6a0da0f8bb023ee695d4 Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 4 Oct 2018 04:58:13 -0400 Subject: [PATCH 78/84] Add notice.txt --- packages/nativescript/notice.txt | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 packages/nativescript/notice.txt diff --git a/packages/nativescript/notice.txt b/packages/nativescript/notice.txt new file mode 100644 index 0000000..18c6d10 --- /dev/null +++ b/packages/nativescript/notice.txt @@ -0,0 +1,58 @@ +========================================================================= +== NOTICE file corresponding to section 4 d of == +== the Apache License, Version 2.0, == +== in this case for Progress Data Source for NativeScript v6.0 == +========================================================================= + +Progress Data Source for NativeScript v6.0 (the “Product”) + +Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. + +For license information see the LICENSE.md file which accompanies this NOTICE.txt file. + +Portions of the Product include certain non-proprietary open source and commercial third-party components listed below (“Third-Party Components”). The authors of the Third-Party Components require Progress Software Corporation (“Progress”) to include the following notices and additional licensing terms as a condition of Progress’s use of such Third-Party Components. You acknowledge that the authors of the Third-Party Components have no obligation to provide support to you for the Third-Party Components or the Product. You hereby undertake to comply with all licenses related to the applicable Third-Party Components. + +1. Special Notices Regarding Open Source Third-Party Components incorporated in the Product: + +(1) MIT-Style License: + +(a) Progress Data Source for NativeScript v6.0 incorporates zone.js v0.8.26. Such technology is subject to the following terms and conditions: +The MIT License +Copyright (c) 2016-2018 Google, Inc. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(b) Progress Data Source for NativeScript v6.0 incorporates base-64 v0.1.0. Such technology is subject to the following terms and conditions: +Copyright Mathias Bynens +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(c) Progress Data Source for NativeScript v6.0 incorporates nativescript-localstorage v2.0.0. Such technology is subject to the following terms and conditions: +The MIT License (MIT) +localstorage +Copyright (c) 2016, Nathanael Anderson +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +2. Special Notices Regarding Commercially Licensed Third-Party Components incorporated in the Product: None + + +NOTICE FROM PROGRESS SOFTWARE CORPORATION: Additional notices may be included in the release notes or other documentation that accompanies updates received in connection with support of the Product. + +9/25/2018 From 1d1bd09025eff311a7869b38d34a6efafb6c94db Mon Sep 17 00:00:00 2001 From: edselg Date: Thu, 4 Oct 2018 05:00:31 -0400 Subject: [PATCH 79/84] Add notice.txt --- packages/node/notice.txt | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 packages/node/notice.txt diff --git a/packages/node/notice.txt b/packages/node/notice.txt new file mode 100644 index 0000000..410f6d9 --- /dev/null +++ b/packages/node/notice.txt @@ -0,0 +1,71 @@ +========================================================================= +== NOTICE file corresponding to section 4 d of == +== the Apache License, Version 2.0, == +== in this case for Progress Data Source for Node.js v6.0 == +========================================================================= + +Progress Data Source for Node.js v6.0 (the “Product”) + +Copyright © 2018 Progress Software Corporation or one of its subsidiaries or affiliates. All Rights Reserved. + +For license information see the LICENSE.md file which accompanies this NOTICE.txt file. + +Portions of the Product include certain non-proprietary open source and commercial third-party components listed below (“Third-Party Components”). The authors of the Third-Party Components require Progress Software Corporation (“Progress”) to include the following notices and additional licensing terms as a condition of Progress’s use of such Third-Party Components. You acknowledge that the authors of the Third-Party Components have no obligation to provide support to you for the Third-Party Components or the Product. You hereby undertake to comply with all licenses related to the applicable Third-Party Components. + +1. Special Notices Regarding Open Source Third-Party Components incorporated in the Product: + +(1) The Apache Software License, Version 2.0: + +Progress Data Source for Node.js v6.0 incorporates RxJS v6.0. Such technology is subject to the following terms and conditions: +The Apache Software License, Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +------------------------------------------------------------------------- + + + +(2) MIT-Style License: + +(a) Progress Data Source for Node.js v6.0 incorporates Angular Core v6.1.0. Such technology is subject to the following terms and conditions: +The MIT License +Copyright (c) 2014-2018 Google, Inc. http://angular.io +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(b) Progress Data Source for Node.js v6.0 incorporates base-64 v0.1.0. Such technology is subject to the following terms and conditions: +Copyright Mathias Bynens +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(c) Progress Data Source for Node.js v6.0 incorporates node-localstorage v1.3.1. Such technology is subject to the following terms and conditions: +MIT License +Copyright (c) 2011, 2012, Lawrence S. Maccherone, Jr. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(d) Progress Data Source for Node.js v6.0 incorporates xmlhttprequst v1.8.0. Such technology is subject to the following terms and conditions: +Copyright (c) 2010 passive.ly LLC +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +2. Special Notices Regarding Commercially Licensed Third-Party Components incorporated in the Product: None + + +NOTICE FROM PROGRESS SOFTWARE CORPORATION: Additional notices may be included in the release notes or other documentation that accompanies updates received in connection with support of the Product. + +9/25/2018 From de0238eb07cf1b3e98b4ec9af57f02551727f1a5 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Thu, 4 Oct 2018 15:34:34 -0400 Subject: [PATCH 80/84] Fixed some of the tests --- packages/node/test/smoke.datasource.js | 2 +- test/smoke.invoke.js | 6 +++--- test/smoke.jsdo.js | 4 ++-- test/smoke.jsdosession.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/node/test/smoke.datasource.js b/packages/node/test/smoke.datasource.js index f24abc9..b7fa139 100644 --- a/packages/node/test/smoke.datasource.js +++ b/packages/node/test/smoke.datasource.js @@ -13,7 +13,7 @@ describe('Datasource Smoke Tests', function () { //options all the info required for creating a jsdo session const options = { // These services are running in Docker - serviceURI: "http://172.29.18.125:8894/OEMobileDemoServices", + serviceURI: "http://172.29.18.125:8894/OEMobileDemoServices/", catalogURI: "http://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json", resourceName: "Customer", authenticationModel: "anonymous", diff --git a/test/smoke.invoke.js b/test/smoke.invoke.js index 57deefc..3804b0c 100644 --- a/test/smoke.invoke.js +++ b/test/smoke.invoke.js @@ -8,7 +8,7 @@ const progress = require("../build/progress.jsdo").progress; chai.use(chaiAsPromised); -describe('JSDO Smoke Tests', () => { +describe('Invoke Smoke Tests', () => { // INFORMATION YEAH const options = { catalogURI: "https://10.128.57.41:65500/Sports/static/SportsService.json", @@ -36,7 +36,7 @@ describe('JSDO Smoke Tests', () => { session.invalidate().then(() => done()); }); - describe('JSDO Instantiation Tests', function() { + describe('Invoke READ Tests', function() { it('should successfully create a JSDO', function() { jsdo = new progress.data.JSDO({name: options.resourceName}); expect(jsdo).to.be.an.instanceof(progress.data.JSDO); @@ -73,7 +73,7 @@ describe('JSDO Smoke Tests', () => { }); }); - describe('JSDO CUD Tests', function () { + describe('Invoke CUD Tests', function () { // Clean up the backend to make sure that there isn't an customer record with a CustNum of 3000 // already in store function clean(callback) { diff --git a/test/smoke.jsdo.js b/test/smoke.jsdo.js index 99f57b7..6b7adcb 100644 --- a/test/smoke.jsdo.js +++ b/test/smoke.jsdo.js @@ -9,8 +9,8 @@ chai.use(chaiAsPromised); describe('JSDO Smoke Tests', () => { // INFORMATION YEAH const options = { - catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json", - serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices", + catalogURI: "http://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json", + serviceURI: "http://172.29.18.125:8894/OEMobileDemoServices/", resourceName: "Customer", authenticationModel: "anonymous" }; diff --git a/test/smoke.jsdosession.js b/test/smoke.jsdosession.js index c9c1527..e06acb6 100644 --- a/test/smoke.jsdosession.js +++ b/test/smoke.jsdosession.js @@ -9,8 +9,8 @@ chai.use(chaiAsPromised); describe('JSDOSession Smoke Tests', () => { // INFORMATION YEAH const options = { - catalogURI: 'https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json', - serviceURI: 'https://oemobiledemo.progress.com/OEMobileDemoServices', + catalogURI: 'http://172.29.18.125:8894/OEMobileDemoServices/static/CustomerService.json', + serviceURI: 'http://172.29.18.125:8894/OEMobileDemoServices/', authenticationModel: 'anonymous' }; From 9488a8aef86446846f45279e0d24e876e678885f Mon Sep 17 00:00:00 2001 From: Nicolette Date: Fri, 5 Oct 2018 14:40:07 -0400 Subject: [PATCH 81/84] Revert "fix to handle timeout" --- src/progress.session.js | 48 +++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/progress.session.js b/src/progress.session.js index 7c29838..2582a54 100644 --- a/src/progress.session.js +++ b/src/progress.session.js @@ -4763,15 +4763,22 @@ limitations under the License. try { jsdosession = new progress.data.JSDOSession(options); - jsdosession.isAuthorized() - .then(function() { - return jsdosession.addCatalog(options.catalogURI); - }, sessionRejectHandler) - .then(function (object, result, info) { - object = progress.util.Deferred.getParamObject(object, result, info); - deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); - }, sessionRejectHandler); - + try { + jsdosession.isAuthorized() + .then(function() { + return jsdosession.addCatalog(options.catalogURI); + }, sessionRejectHandler) + .then(function (object, result, info) { + object = progress.util.Deferred.getParamObject(object, result, info); + deferred.resolve(object.jsdosession, progress.data.Session.SUCCESS); + }, sessionRejectHandler); + } catch (e) { + sessionRejectHandler( + jsdosession, + progress.data.Session.GENERAL_FAILURE, + {errorObject: e} + ); + } } catch (ex) { sessionRejectHandler( jsdosession, @@ -4897,28 +4904,7 @@ limitations under the License. options.authProvider = authProvider; if (authProvider.hasClientCredentials()) { - // FAKE SESSION - let jsdosession = new progress.data.JSDOSession(options); - - // This is a band-aid. We need to refactor and re-modularize - // getSession() now that the team has a better understanding - // of async operations --aestrada aka yoloswaggins - jsdosession.isAuthorized().then(() => { - jsdosession.invalidate(); - loginHandler(authProvider); - }, - () => { - return Promise.all([ - jsdosession.invalidate(), - options.authProvider.logout() - ]); - }).then((values) => { - if (values) { - authProvider = new progress.data.AuthenticationProvider(authProviderInitObject); - options.authProvider = authProvider; - callLogin(authProvider); - } - }) + loginHandler(authProvider); } else { // If model is anon, just log in. if (authProvider.authenticationModel === progress.data.Session.AUTH_TYPE_ANON) { From 502dec60f949909b5291a1ee479d4b759b4f3e7e Mon Sep 17 00:00:00 2001 From: Nicolette Date: Fri, 5 Oct 2018 16:14:19 -0400 Subject: [PATCH 82/84] update lib folder with .js and .map files --- lib/progress.all.js | 106 ++++++++++++++++++++++++----------- lib/progress.all.min.js | 4 +- lib/progress.all.min.js.map | 2 +- lib/progress.jsdo.js | 57 ++++++++++--------- lib/progress.jsdo.min.js | 4 +- lib/progress.jsdo.min.js.map | 2 +- 6 files changed, 110 insertions(+), 65 deletions(-) diff --git a/lib/progress.all.js b/lib/progress.all.js index 8ed4175..9723ab0 100644 --- a/lib/progress.all.js +++ b/lib/progress.all.js @@ -1,5 +1,5 @@ /* -Progress JSDO Version: 5.0.0 +Progress JSDO Version: 6.0.0 Copyright 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -18,7 +18,7 @@ limitations under the License. /*eslint no-global-assign: ["error", {"exceptions": ["localStorage"]}]*/ /*global XMLHttpRequest:true, require, console, localStorage:true, sessionStorage:true, $:true, Promise, setTimeout */ /* -progress.util.js Version: 5.0.0 +progress.util.js Version: 6.0.0 Copyright (c) 2014-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -63,7 +63,8 @@ limitations under the License. var pkg_xmlhttprequest = "xmlhttprequest", pkg_nodeLocalstorage = "node-localstorage", pkg_nativescriptLocalstorage = "nativescript-localstorage", - pkg_fileSystemAccess = "file-system/file-system-access" + pkg_fileSystemAccess = "file-system/file-system-access", + pkg_base64 = "base-64" ; // If XMLHttpRequest is undefined, enviroment would appear to be Node.js @@ -114,7 +115,7 @@ limitations under the License. // load module base-64 try { if (typeof btoa === "undefined") { - btoa = require("base-64").encode; + btoa = require("" + pkg_base64).encode; } } catch(exception3) { console.error("Error: JSDO library requires btoa() function in NativeScript.\n" @@ -144,7 +145,7 @@ limitations under the License. // load module base-64 try { if (typeof btoa === "undefined") { - btoa = require("base-64").encode; + btoa = require("" + pkg_base64).encode; } } catch(exception3) { console.error("Error: JSDO library requires btoa() function in Node.js.\n" @@ -276,27 +277,28 @@ limitations under the License. object.result = arg2; object.info = arg3; } else { - objectName = arg1.constructor.name.toLowerCase(); - if (!objectName) { + // Map some object name to use a particular property name + // We should probably spend some time down the line to truly use + // ES6 promises. + if (arg1 instanceof progress.data.JSDOSession) { + objectName = "jsdosession"; + } else if (arg1 instanceof progress.data.AuthenticationProvider) { + objectName = "provider"; + } else if (arg1 instanceof progress.data.JSDO) { + objectName = "jsdo"; + } else if (typeof(arg1) === "number") { + objectName = "result"; + } else { objectName = typeof(arg1); } - // Map some object name to use a particular property name - switch (objectName) { - case "authenticationprovider": - objectName = "provider" - break; - case "number": - objectName = "result" - break; - default: - break; - } object[objectName] = arg1; if (objectName === "jsdo") { object.success = arg2; if (arg3 && arg3.xhr) { object.request = arg3; + } else if (arg3 && arg3.batch) { + object.request = arg3; } else { object.info = arg3; } @@ -719,7 +721,7 @@ limitations under the License. format = "'{1}'"; value = value.replace(/'/g, "~'"); } else if (type === DATE_OBJECT_TYPE) { - ablType = tableRef._getABLType(field); + ablType = tableRef._getABLType(filter.field); if (ablType === "DATE") { format = "DATE({1:MM, dd, yyyy})"; } else if (ablType === "DATETIME-TZ") { @@ -1093,7 +1095,7 @@ limitations under the License. }()); //# sourceURL=progress.jsdo.js /* -progress.js Version: 5.0.0 +progress.js Version: 6.0.0 Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -3319,6 +3321,11 @@ limitations under the License. this._resource.idProperty = properties[tableName].idProperty; } } + } else if (this._resource.schema + && this._resource.schema.properties + && this._resource.schema.properties[tableName] + && this._resource.schema.properties[tableName].idProperty) { + this._resource.idProperty = this._resource.schema.properties[tableName].idProperty; } // Add functions for operations to JSDO object @@ -8720,7 +8727,7 @@ limitations under the License. //this is so that we can see the code in Chrome's Source tab when script is loaded via XHR //# sourceURL=progress.jsdo.js /* -progress.session.js Version: 5.0.0 +progress.session.js Version: 6.0.0 Copyright (c) 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -13695,7 +13702,7 @@ if (typeof exports !== "undefined") { //# sourceURL=progress.jsdo.js /* -progress.auth.js Version: 4.4.0-3 +progress.auth.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -14166,7 +14173,7 @@ limitations under the License. //# sourceURL=progress.jsdo.js /* -progress.auth.basic.js Version: 4.4.0-3 +progress.auth.basic.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -14325,7 +14332,7 @@ limitations under the License. }()); //# sourceURL=progress.jsdo.js /* -progress.auth.form.js Version: 5.0.0 +progress.auth.form.js Version: 6.0.0 Copyright (c) 2016-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -14537,7 +14544,7 @@ limitations under the License. }()); //# sourceURL=progress.jsdo.js /* -progress.auth.sso.js Version: 4.4.0-3 +progress.auth.sso.js Version: 6.0.0 Copyright (c) 2016-2017 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -15031,7 +15038,7 @@ limitations under the License. /* -progress.data.kendo.js Version: 5.0.0 +progress.data.kendo.js Version: 6.0.0 Copyright (c) 2015-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -15286,6 +15293,8 @@ if (typeof (kendo) !== "undefined") { elementName, copy; + // Remove prods:rowState property from data object + delete data["prods:rowState"]; if (!transport.useArrays && transport._convertTypes && (transport._convertFields._arrayFields.length > 0)) { copy = {}; transport.jsdo._copyRecord(transport.jsdo._buffers[transport.tableRef], data, copy); @@ -15387,6 +15396,10 @@ if (typeof (kendo) !== "undefined") { } } } + + if (transport.jsdo._resource.idProperty) { + fields[transport.jsdo._resource.idProperty].editable = false; + } return fields; }, _getInitialValues: function () { @@ -15615,14 +15628,17 @@ if (typeof (kendo) !== "undefined") { if (options.batch) { array = []; if (options.data.created instanceof Array) { - for (i = 0; i < options.data.created.length; i += 1) { - jsrecord = jsdo[transport.tableRef].findById( - options.data.created[i]._id - ); - if (jsrecord) { - record = transport._convertDataTypes(jsrecord.data); - array.push(record); - } else if (jsdo.autoApplyChanges) { + // Process changes for idProperty case + if (jsdo._resource.idProperty) { + if (request.jsrecords) { + for (i = 0; i < request.jsrecords.length; i += 1) { + if (request.jsrecords[i].data["prods:rowState"] === "created") { + record = transport._convertDataTypes(request.jsrecords[i].data); + array.push(record); + } + } + } + if (options.data.created.length !== array.length) { options.error( null, null, @@ -15630,6 +15646,23 @@ if (typeof (kendo) !== "undefined") { ); return; } + } else { + for (i = 0; i < options.data.created.length; i += 1) { + jsrecord = jsdo[transport.tableRef].findById( + options.data.created[i]._id + ); + if (jsrecord) { + record = transport._convertDataTypes(jsrecord.data); + array.push(record); + } else if (jsdo.autoApplyChanges) { + options.error( + null, + null, + new Error("Created record was not found in memory.") + ); + return; + } + } } } options.success(array, "create"); @@ -15679,6 +15712,10 @@ if (typeof (kendo) !== "undefined") { && request.batch.operations instanceof Array && request.batch.operations.length === 1) { id = request.batch.operations[0].jsrecord.data._id; + } else if (request + && request.jsrecords instanceof Array + && request.jsrecords.length === 1) { + id = request.jsrecords[0].data._id; } } else { id = options.data._id; @@ -15690,6 +15727,7 @@ if (typeof (kendo) !== "undefined") { } else { options.success({}); } + } }, _saveChanges: function (options) { diff --git a/lib/progress.all.min.js b/lib/progress.all.min.js index 3b3691b..d37749a 100644 --- a/lib/progress.all.min.js +++ b/lib/progress.all.min.js @@ -1,5 +1,5 @@ /* -Progress JSDO Version: 5.0.0 +Progress JSDO Version: 6.0.0 Copyright 2012-2018 Progress Software Corporation and/or its subsidiaries or affiliates. @@ -15,5 +15,5 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -(function(){var isNativeScript=false,isNodeJS=false;var pkg_xmlhttprequest="xmlhttprequest",pkg_nodeLocalstorage="node-localstorage",pkg_nativescriptLocalstorage="nativescript-localstorage",pkg_fileSystemAccess="file-system/file-system-access";if(typeof XMLHttpRequest==="undefined"){isNodeJS=true;try{XMLHttpRequest=require(""+pkg_xmlhttprequest).XMLHttpRequest}catch(e){console.error("Error: JSDO library requires XMLHttpRequest object in Node.js.\n"+"Please install xmlhttprequest package.")}}if(!isNodeJS&&(typeof localStorage==="undefined"||typeof sessionStorage==="undefined")){try{require(""+pkg_fileSystemAccess);isNativeScript=true}catch(exception1){isNativeScript=false}}if(isNativeScript){try{if(typeof sessionStorage==="undefined"){sessionStorage=require(""+pkg_nativescriptLocalstorage)}if(typeof localStorage==="undefined"){localStorage=require(""+pkg_nativescriptLocalstorage)}}catch(exception2){console.error("Error: JSDO library requires localStorage and sessionStorage objects in NativeScript.\n"+"Please install nativescript-localstorage package.")}try{if(typeof btoa==="undefined"){btoa=require("base-64").encode}}catch(exception3){console.error("Error: JSDO library requires btoa() function in NativeScript.\n"+"Please install base-64 package.")}}if(isNodeJS){var LocalStorage;if(typeof localStorage==="undefined"){try{var module=require(""+pkg_nodeLocalstorage);LocalStorage=module.LocalStorage;localStorage=new LocalStorage("./scratch1")}catch(e){console.error("Error: JSDO library requires localStorage and sessionStorage objects in Node.js.\n"+"Please install node-localstorage package.")}}if(typeof sessionStorage==="undefined"&&typeof LocalStorage!=="undefined"){sessionStorage=new LocalStorage("./scratch2")}try{if(typeof btoa==="undefined"){btoa=require("base-64").encode}}catch(exception3){console.error("Error: JSDO library requires btoa() function in Node.js.\n"+"Please install base-64 package.")}}})();(function(){if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.util={};var STRING_OBJECT_TYPE="String",DATE_OBJECT_TYPE="Date",CHARACTER_ABL_TYPE="CHARACTER";progress.util.Deferred=function(){function Deferred(){this._deferred={}}Deferred.prototype.promise=function(){var that=this;if(progress.util.Deferred.useJQueryPromises){if(typeof $!=="undefined"&&typeof $.Deferred==="function"){this._deferred._jQuerydeferred=$.Deferred();this._promise=this._deferred._jQuerydeferred.promise()}else{throw new Error("JQuery Promises not found in environment.")}}else{this._promise=new Promise(function(resolve,reject){that._deferred.resolve=resolve;that._deferred.reject=reject})}if(this._resolveArguments||this._rejectArguments){setTimeout(function(){if(that._resolveArguments){that.resolve.apply(that,that._resolveArguments)}else if(that._rejectArguments){that.reject.apply(that,that._rejectArguments)}},500)}return this._promise};Deferred.prototype.resolve=function(arg1,arg2,arg3){if(this._promise){if(this._deferred._jQuerydeferred){this._deferred._jQuerydeferred.resolve.apply(this,arguments)}else{var object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3);this._deferred.resolve(object)}}else{this._resolveArguments=arguments}};Deferred.prototype.reject=function(arg1,arg2,arg3){if(this._promise){if(this._deferred._jQuerydeferred){this._deferred._jQuerydeferred.reject.apply(this,arguments)}else{var object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3);this._deferred.reject(object)}}else{this._rejectArguments=arguments}};Deferred.useJQueryPromises=false;Deferred.when=function(deferreds){if(progress.util.Deferred.useJQueryPromises){return $.when.apply($,deferreds)}else{return Promise.all(deferreds)}};Deferred.getParamObject1=function(arg1,arg2,arg3){var object={},objectName;try{if(typeof arg1==="undefined"||arg1===null){object.result=arg2;object.info=arg3}else{objectName=arg1.constructor.name.toLowerCase();if(!objectName){objectName=typeof arg1}switch(objectName){case"authenticationprovider":objectName="provider";break;case"number":objectName="result";break;default:break}object[objectName]=arg1;if(objectName==="jsdo"){object.success=arg2;if(arg3&&arg3.xhr){object.request=arg3}else{object.info=arg3}}else{if(objectName==="result"){object.info=arg2;if(arg3){object.info2=arg3}}else{object.result=arg2;object.info=arg3}}}}catch(e){console.log("Error: Undetermined argument in getParamObject() call.")}return object};Deferred.getParamObject=function(arg1,arg2,arg3){var object={};if(progress.util.Deferred.useJQueryPromises){object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3)}else{if(typeof arg1==="undefined"){object.result=arg2;object.info=arg3;arg1=object}return arg1}return object};return Deferred}();progress.util.Observable=function(){function _filterObservers(observers,fn,scope,operation){return observers.filter(function(el){if(el.fn!==fn||el.scope!==scope||el.operation!==operation){return el}},this)}this.validateSubscribe=function(args,evt,listenerData){if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="string"){listenerData.operation=args[1];listenerData.fn=args[2];listenerData.scope=args[3]}else if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="function"){listenerData.operation=undefined;listenerData.scope=args[2];listenerData.fn=args[1]}else{throw new Error}};this.subscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"subscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",progress.data._getMsgText("jsdoMSG039")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",e.message))}observers=this._events[evt]||[];observers=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation);observers.push(listenerData);this._events[evt]=observers;return this};this.unsubscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"unsubscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",progress.data._getMsgText("jsdoMSG037")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",e.message))}observers=this._events[evt]||[];if(observers.length>0){this._events[evt]=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation)}return this};this.trigger=function(evt,operation,args){var observers,op;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"trigger"))}this._events=this._events||{};evt=evt.toLowerCase();observers=this._events[evt]||[];if(observers.length>0){args=Array.prototype.slice.call(arguments);if(arguments.length>=2&&typeof evt==="string"&&typeof operation==="string"){op=operation;args=args.length>2?args.slice(2):[]}else if(arguments.length>=1&&typeof evt==="string"){op=undefined;args=args.length>1?args.slice(1):[]}else{throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"trigger"))}observers.forEach(function(el){if(el.operation===op){el.fn.apply(el.scope,args)}})}return this};this.unsubscribeAll=function(evt,operation){var observers;if(evt){this._events=this._events||{};if(typeof evt==="string"){evt=evt.toLowerCase();observers=this._events[evt]||[];observers.forEach(function(el){if(el.operation){this.unsubscribe(evt,el.operation,el.fn,el.scope)}else{this.unsubscribe(evt,el.fn,el.scope)}},this)}}else{this._events={}}return this}};progress.data.LocalStorage=function LocalStorage(){if(typeof localStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","progress.data.LocalStorage","localStorage"))}this.saveToLocalStorage=function(name,dataObj){localStorage.setItem(name,JSON.stringify(dataObj))};this.readFromLocalStorage=function(name){var jsonStr=localStorage.getItem(name),dataObj=null;if(jsonStr!==null){try{dataObj=JSON.parse(jsonStr)}catch(e){dataObj=null}}return dataObj};this.clearLocalStorage=function(name){localStorage.removeItem(name)}};progress.util._convertToABLWhereString=function(tableRef,filter){var result=[],logic=filter.logic||"and",idx,length,field,fieldInfo,type,format,operator,value,ablType,filters=filter.filters||[filter],whereOperators={eq:"=",neq:"<>",gt:">",gte:">=",lt:"<",lte:"<=",contains:"INDEX",doesnotcontain:"INDEX",endswith:"R-INDEX",startswith:"BEGINS",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};for(idx=0,length=filters.length;idx 0"}else{format="{2} MATCHES '*{1}'"}}else{format="{2} {0} "+format}filter=progress.util._format(format,operator,value,field)}else if(operator&&value===undefined){if(filter.operator==="isempty"||filter.operator==="isnotempty"){ablType=tableRef._getABLType(field);if(ablType!==CHARACTER_ABL_TYPE){throw new Error("Error parsing filter object. The operator "+filter.operator+" requires a CHARACTER field")}if(filter.operator==="isempty"){format="{2} = ''"}else if(filter.operator==="isnotempty"){format="{2} <> ''"}}else{if(filter.operator==="isnull"){format="{2} = ?"}else if(filter.operator==="isnotnull"){format="{2} <> ?"}else{format="{2} {0} ?"}}filter=progress.util._format(format,operator,value,field)}}result.push(filter)}filter=result.join(" "+logic+" ");if(result.length>1){filter="("+filter+")"}return filter};progress.util._convertToSQLQueryString=function(tableRef,filter,addSelect){var result=[],logic=filter.logic||"and",idx,length,field,type,format,operator,value,fieldFormat,filters=filter.filters||[filter],filterStr,usingLike=true,whereOperators={eq:"=",neq:"!=",gt:">",gte:">=",lt:"<",lte:"<=",contains:"LIKE",doesnotcontain:"NOT LIKE",endswith:"LIKE",startswith:"LIKE",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};if(typeof addSelect==="undefined"){addSelect=false}for(idx=0,length=filters.length;idx1){filterStr="("+filterStr+")"}if(addSelect===true){filterStr="SELECT * FROM "+tableRef._name+" WHERE "+filterStr}return filterStr};progress.util._getObjectType=function(value){return Object.prototype.toString.call(value).slice(8,-1)};progress.util._format=function(fmt){var values=arguments,formatRegExp=/\{(\d+)(:[^\}]+)?\}/g;return fmt.replace(formatRegExp,function(match,index,placeholderFormat){var value=values[parseInt(index,10)+1];return progress.util._toString(value,placeholderFormat?placeholderFormat.substring(1):"")})};progress.util._toString=function(value,fmt){var str;if(fmt){if(progress.util._getObjectType(value)==="Date"){return progress.util._formatDate(value,fmt)}}if(typeof value==="number"){str=value.toString()}else{str=value!==undefined?value:""}return str};progress.util._pad=function(number,digits){var zeros=["","0","00","000","0000"],end;number=String(number);digits=digits||2;end=digits-number.length;if(end){return zeros[digits].substring(0,end)+number}return number};progress.util._formatDate=function(date,format){var dateFormatRegExp=/dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g;return format.replace(dateFormatRegExp,function(match){var minutes,result,sign;if(match==="dd"){result=progress.util._pad(date.getDate())}else if(match==="MM"){result=progress.util._pad(date.getMonth()+1)}else if(match==="yyyy"){result=progress.util._pad(date.getFullYear(),4)}else if(match==="hh"){result=progress.util._pad(date.getHours())}else if(match==="mm"){result=progress.util._pad(date.getMinutes())}else if(match==="ss"){result=progress.util._pad(date.getSeconds())}else if(match==="fff"){result=progress.util._pad(date.getMilliseconds(),3)}else if(match==="FFF"){result=String(date.getTime())}else if(match==="zzz"){minutes=date.getTimezoneOffset();sign=minutes<0;result=(sign?"+":"-")+minutes}else if(match==="iso"){result=date.toISOString()}return result!==undefined?result:match.slice(1,match.length-1)})};progress.util.jsdoSettingsProcessor=function jsdoSettingsProcessor(jsdoSettings){if(typeof jsdoSettings==="object"){if(jsdoSettings.authenticationModel===undefined||jsdoSettings.authenticationModel===""){jsdoSettings.authenticationModel="ANONYMOUS"}}}})();(function(){var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS=20,PROGRESS_JSDO_OP_STRING=["none","create","read","update","delete","submit"],PROGRESS_JSDO_ROW_STATE_STRING=["","created","","modified","deleted"];if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data._nextid=0;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime());var UID_MAX_VALUE=999999999999999;progress.data._getNextId=function(){var uid=++progress.data._nextid;if(uid>=UID_MAX_VALUE){progress.data._nextid=uid=1;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime())}return progress.data._uidprefix+"-"+uid};var msg={};msg.msgs={};msg.msgs.jsdoMSG000="JSDO, Internal Error: {1}";msg.msgs.jsdoMSG001="JSDO: JSDO has multiple tables. Please use {1} at the table reference level.";msg.msgs.jsdoMSG002="JSDO: Working record for '{1}' is undefined.";msg.msgs.jsdoMSG003="JSDO: {1} function requires a function as a parameter.";msg.msgs.jsdoMSG004="JSDO: Unable to find resource '{1}' in the catalog.";msg.msgs.jsdoMSG005="JSDO: Data for table '{1}' was not specified in addRecords() call.";msg.msgs.jsdoMSG006="JSDO: Data for JSDO was not specified in addRecords() call.";msg.msgs.jsdoMSG007="JSDO: Test function in {1} must return a boolean.";msg.msgs.jsdoMSG008="JSDO: Invalid keyFields parameter in addRecords() call.";msg.msgs.jsdoMSG009="JSDO: KeyField '{1}' in addRecords() call was not found in the schema.";msg.msgs.jsdoMSG010="JSDO: Field '{1}' in relationship was not found in the schema.";msg.msgs.jsdoMSG011="UIHelper: JSDO has multiple tables. "+"Please use {1} at the table reference level.";msg.msgs.jsdoMSG012="UIHelper: Invalid {2} parameter in {1} call.";msg.msgs.jsdoMSG020="JSDO: tableName parameter must be a string in addRecords() call.";msg.msgs.jsdoMSG021="JSDO: addMode parameter must be specified in addRecords() call.";msg.msgs.jsdoMSG022="JSDO: Invalid addMode specified in addRecords() call.";msg.msgs.jsdoMSG023="JSDO: Duplicate found in addRecords() call using APPEND mode.";msg.msgs.jsdoMSG024="{1}: Unexpected signature in call to {2} function.";msg.msgs.jsdoMSG025="{1}: Invalid parameters in call to {2} function.";msg.msgs.jsdoMSG026="JSDO: saveChanges requires a "+"CREATE, UPDATE, DELETE or SUBMIT operation to be defined.";msg.msgs.jsdoMSG030="JSDO: Invalid {1}, expected {2}.";msg.msgs.jsdoMSG031="JSDO: Specified sort field name '{1}' was not found in the schema.";msg.msgs.jsdoMSG032="JSDO: Before-image data already exists for record in addRecords() call.";msg.msgs.jsdoMSG033="{1}: Invalid signature for {2}. {3}";msg.msgs.jsdoMSG034="JSDO: In '{1}' function, JSON data is missing _id";msg.msgs.jsdoMSG035="JSDO: In '{1}' function, before-image JSON data is missing prods:clientId";msg.msgs.jsdoMSG036="JSDO: '{1}' can only be called for a dataset";msg.msgs.jsdoMSG037="{1}: Event name must be provided for {2}.";msg.msgs.jsdoMSG038="Too few arguments. There must be at least {1}.";msg.msgs.jsdoMSG039="The name of the event is not a string.";msg.msgs.jsdoMSG040="The event listener is not a function.";msg.msgs.jsdoMSG041="The event listener scope is not an object.";msg.msgs.jsdoMSG042="'{1}' is not a defined event for this object.";msg.msgs.jsdoMSG043="{1}: A session object was requested to check the status of a Mobile "+"Service named '{2}', but it has not loaded the definition of that service.";msg.msgs.jsdoMSG044="JSDO: In '{1}' function, {2} is missing {3} property.";msg.msgs.jsdoMSG045="JSDO: {1} function: {2} is missing {3} property.";msg.msgs.jsdoMSG046="JSDO: {1} operation is not defined.";msg.msgs.jsdoMSG047="{1} timeout expired.";msg.msgs.jsdoMSG048="{1}: {2} method has argument '{3}' that is missing property '{4}'.";msg.msgs.jsdoMSG049="{1}: Unexpected error calling {2}: {3}";msg.msgs.jsdoMSG050="No token returned from server";msg.msgs.jsdoMSG051="{1} The login method was not executed because the AuthenticationProvider is already logged in.";msg.msgs.jsdoMSG052="{1}: The login method was not executed because no credentials were supplied.";msg.msgs.jsdoMSG053="{1}: {2} was not executed because the AuthenticationProvider is not logged in.";msg.msgs.jsdoMSG054="{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token.";msg.msgs.jsdoMSG055="{1}: Token refresh was not executed because the authentication model is not sso.";msg.msgs.jsdoMSG056="{1}: Already logged in.";msg.msgs.jsdoMSG057="{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead.";msg.msgs.jsdoMSG058="{1}: Cannot pass username and password to addCatalog when authenticationModel "+"is sso. Pass an AuthenticationProvider instead.";msg.msgs.jsdoMSG059="{1}: Error in constructor. The authenticationModels of the "+"AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible.";msg.msgs.jsdoMSG060="AuthenticationProvider: AuthenticationProvider is no longer logged in. "+"Tried to refresh SSO token but failed due to authentication error at token server.";msg.msgs.jsdoMSG061="{1}: Attempted to set {2} property to an invalid value.";msg.msgs.jsdoMSG062="{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in.";msg.msgs.jsdoMSG100="JSDO: Unexpected HTTP response. Too many records.";msg.msgs.jsdoMSG101="Network error while executing HTTP request.";msg.msgs.jsdoMSG110="Catalog error: idProperty not specified for resource '{1}'. "+"idProperty is required {2}.";msg.msgs.jsdoMSG111="Catalog error: Schema '{1}' was not found in catalog.";msg.msgs.jsdoMSG112="Catalog error: Output parameter '{1}' was not found for operation '{2}'.";msg.msgs.jsdoMSG113="Catalog error: Found xType '{1}' for output parameter '{2}' "+"for operation '{3}' but xType DATASET, TABLE or ARRAY was expected.";msg.msgs.jsdoMSG114="JSDO: idProperty '{1}' is missing from '{2}' record.";msg.msgs.jsdoMSG115="JSDO: Invalid option specified in {1}() call.";msg.msgs.jsdoMSG116="JSDO: {1} parameter must be a string in {2} call.";msg.msgs.jsdoMSG117="JSDO: Schema from storage area '{1}' does not match JSDO schema";msg.msgs.jsdoMSG118="JSDO: Plugin '{1}' was not found.";msg.msgs.jsdoMSG119="JSDO: A mappingType is expected when 'capabilities' is set."+" Please specify a plugin (ex: JFP).";msg.msgs.jsdoMSG120="JSDO: Parameter '{2}' requires capability '{1}' in the catalog.";msg.msgs.jsdoMSG121="{1}: Argument {2} must be of type {3} in {4} call.";msg.msgs.jsdoMSG122="{1}: Incorrect number of arguments in {2} call. There should be {3}.";msg.msgs.jsdoMSG123="{1}: A server response included an invalid '{2}' header.";msg.msgs.jsdoMSG124="JSDO: autoApplyChanges is not supported for saveChanges(true) "+"with a temp-table. Use jsdo.autoApplyChanges = false.";msg.msgs.jsdoMSG125="{1}: The AuthenticationProvider is not managing valid credentials.";msg.msgs.jsdoMSG126="{1}: No support for {2}.";msg.msgs.jsdoMSG127="JSDO: acceptRowChanges() cannot be called for record with _rejected === true.";msg.msgs.jsdoMSG500="{1}: '{2}' objects must contain a '{3}' property.";msg.msgs.jsdoMSG501="{1}: '{2}' in '{3}' function cannot be an empty string.";msg.msgs.jsdoMSG502="{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for "+"its '{4}' property.";msg.msgs.jsdoMSG503="{1}: '{2}' must be of type '{3}'.";msg.msgs.jsdoMSG504="{1}: {2} has an invalid value for the '{3}' property.";msg.msgs.jsdoMSG505="{1}: '{2}' objects must have a '{3}' method.";msg.msgs.jsdoMSG506="{1}: Invalid argument for the {2} parameter in {3} call.";msg.msgs.jsdoMSG507="{1}: '{2}' is an invalid value for the {3} parameter in {4} call.";msg.msgs.jsdoMSG508="JSDOSession: If a JSDOSession object is using the SSO authentication model, "+"the options object passed to its constructor must include an authProvider property.";msg.msgs.jsdoMSG509="progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, "+"authenticationURI and authProviderAuthenticationModel are required parameters.";msg.msgs.jsdoMSG510="{1}: This session has been invalidated and cannot be used.";msg.msgs.jsdoMSG511="JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or "+"connect() has been successfully called.";msg.msgs.jsdoMSG512="JSDOSession: Error while loading multiple catalogs.";msg.msgs.jsdoMSG998="JSDO: JSON object in addRecords() must be DataSet or Temp-Table data.";msg.getMsgText=function(n,args){var text=msg.msgs[n],i;if(!text){throw new Error("Message text was not found by getMsgText()")}for(i=1;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true;data=newDataArray}else{if(params&&(params.sort||params.top)){newDataArray=[];for(i=0;i0){sortObject.tableRef=this;data.sort(this._getCompareFn(sortObject))}}if(params.top){if(typeof params.skip=="undefined"){params.skip=0}data=data.splice(params.skip,params.top)}}return data};this._recToDataObject=function(record,includeChildren){var array=[record];var dataObject=array;if(typeof includeChildren=="undefined"){includeChildren=false}if(this._jsdo._dataSetName){dataObject={};dataObject[this._jsdo._dataSetName]={};dataObject[this._jsdo._dataSetName][this._name]=array;if(includeChildren&&this._children.length>0){var jsrecord=this._findById(record._id,false);if(jsrecord){for(var i=0;i0){for(var j=0;j0){for(var i=0;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true};this._equalRecord=function(rec1,rec2,keyFields){var field;var match=true;for(var i=0;ivalue2||(value1===undefined||value1===null))return sortAscending[i]?1:-1;else if(value10)this._sort(sortObject)}else{this._sort(arg1)}this._createIndex()};this._sort=function(arg1){if(arguments.length===0&&(!this.autoSort||this._sortFn===undefined&&this._sortObject.sortFields===undefined))return;if(arguments.length===0){if(this._sortFn){this._data.sort(this._sortFn)}else{this._data.sort(this._compareFields)}this._needsAutoSorting=false}else{if(typeof arg1=="function"){this._data.sort(this._getCompareFn(arg1))}else{arg1.tableRef=this;this._data.sort(this._getCompareFn(arg1))}if(this.autoSort)this._needsAutoSorting=true}};this.addRecords=function(jsonObject,addMode,keyFields,trackChanges,isInvoke){this._jsdo._addRecords(this._name,jsonObject,addMode,keyFields,trackChanges,isInvoke)};this.acceptChanges=function(){var tableRef=this;for(var id in tableRef._beforeImage){if(tableRef._beforeImage[id]===null){var jsrecord=tableRef._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}else if(this._changed[id]!==undefined){var jsrecord=this._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}}tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[];tableRef._beforeImage={}};this.rejectChanges=function(){for(var id in this._beforeImage){if(this._beforeImage[id]===null){this._jsdo._undoCreate(this,id)}else if(this._changed[id]!==undefined){this._jsdo._undoUpdate(this,id,true)}else{this._jsdo._undoDelete(this,id,true)}}var tableRef=this;tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[]};this.hasChanges=function(){return Object.keys(this._beforeImage).length!==0};this.getChanges=function(){var result=[];for(var id in this._beforeImage){var item={rowState:"",record:null};if(this._beforeImage[id]===null){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE];item.record=this._findById(id,false)}else if(this._changed[id]!==undefined){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE];item.record=this._findById(id,false)}else{item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE];item.record=new progress.data.JSRecord(this,this._beforeImage[id])}result.push(item)}return result};this._clearErrorStrings=function(){var record=null;for(var id in this._beforeImage){if(this._beforeImage[id]===null){record=this._findById(id,false);if(record){delete record.data._errorString}}else{record=this._findById(id,false);if(record){delete record.data._errorString}else{delete this._beforeImage[id]._errorString}}}};this._applyChanges=function(){var i;for(var id in this._beforeImage){if(this._beforeImage[id]===null){var jsrecord=this._findById(id,false);if(jsrecord===null&&this._jsdo._resource.idProperty!==undefined){if(this._tmpIndex[id]){var record=this._data[this._tmpIndex[id].index];jsrecord=record?new progress.data.JSRecord(this,record):null;delete this._tmpIndex[id]}}if(jsrecord!==null){if(jsrecord.data._rejected||jsrecord.data._errorString!==undefined){this._jsdo._undoCreate(this,id)}else{jsrecord.acceptRowChanges()}}else{var found=false;for(var i=0;i0){for(var i=0;iindex){i--}if(i!=index){this._tableRef._data.splice(index,1);this._tableRef._data.splice(i,0,record);this._tableRef._createIndex()}}}};this.assign=function(record){if(record===undefined)throw new Error(msg.getMsgText("jsdoMSG024","JSDO","assign() or update()"));this._saveBeforeImageUpdate();var fieldName,i,j,value,schema=this._tableRef.getSchema(),prefixElement,name;if(record){for(i=0;i0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){return this.record.data[name][element-1]}}return this.record.data[fieldName]}else return null},set:function(value){var name=fieldName,index,element,fieldInfo;if(this.record){this.record._saveBeforeImageUpdate();try{index=fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR);if(index>0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){this.record.data[name][element-1]=value;return}}this.record.data[fieldName]=value}finally{this.record._sortRecord(name)}}},enumerable:true,writeable:true})};Object.defineProperty(this,"hasSubmitOperation",{get:function(){return this._hasSubmitOperation},enumerable:true});Object.defineProperty(this,"hasCUDOperations",{get:function(){return this._hasCUDOperations},enumerable:true});Object.defineProperty(this,"defaultTableRef",{get:function(){return this._defaultTableRef},enumerable:true});this._buffers={};this._numBuffers=0;this._defaultTableRef=null;this._async=true;this._dataProperty=null;this._dataSetName=null;this.operations=[];this.useRelationships=true;this._session=null;this._needCompaction=false;this._hasCUDOperations=false;this._hasSubmitOperation=false;this._useSubmit=false;this.autoApplyChanges=true;this._lastErrors=[];this._localStorage=null;this._convertForServer;this._fillMergeMode;var autoFill=false;if(!arguments[0]){throw new Error("JSDO: Parameters are required in constructor.")}if(typeof arguments[0]=="string"){this.name=arguments[0]}else if(typeof arguments[0]=="object"){var args=arguments[0];for(var v in args){switch(v){case"autoFill":autoFill=args[v];break;case"events":this._events={};for(var eventName in args[v]){this._events[eventName.toLowerCase()]=args[v][eventName]}break;case"dataProperty":this._dataProperty=args[v];break;default:this[v]=args[v]}}}if(!this.name){throw new Error("JSDO: JSDO constructor is missing the value for 'name'")}if(this._events){if(typeof this._events!=="object"){throw new Error("JSDO: JSDO constructor event object is not defined as an object")}for(var prop in this._events){var evt=this._events[prop];if(!(evt instanceof Array)){throw new Error("JSDO: JSDO constructor event object for "+prop+" must be an array")}evt.forEach(function(el){if(typeof el!=="object"){throw new Error("JSDO: JSDO constuctor event object for "+prop+" is not defined as an object")}if(typeof el.fn!=="function"){throw new Error("JSDO: JSDO event listener for "+prop+" is not a function.")}if(el.scope&&typeof el.scope!=="object"){throw new Error("JSDO: JSDO event listener scope for "+prop+" is not an object.")}})}}if(this.name){this._resource=progress.data.ServicesManager.getResource(this.name);if(this._resource){if(!this.url)this.url=this._resource.url;if(!this._dataSetName&&this._resource._dataSetName){this._dataSetName=this._resource._dataSetName;if(this._resource.dataProperty){var buffer=this[this._resource.dataProperty]=new progress.data.JSTableRef(this,this._resource.dataProperty);this._buffers[this._resource.dataProperty]=buffer}else{for(var tableName in this._resource.fields){var buffer=this[tableName]=new progress.data.JSTableRef(this,tableName);this._buffers[tableName]=buffer}}}if(!this._dataProperty&&this._resource.dataProperty)this._dataProperty=this._resource.dataProperty;if(!this._dataSetName){var tableName=this._dataProperty?this._dataProperty:"";this._buffers[tableName]=new progress.data.JSTableRef(this,tableName);if(tableName)this[tableName]=this._buffers[tableName]}var properties,tableName;if(this._dataSetName&&this._resource.schema&&this._resource.schema.properties[this._dataSetName]){properties=this._resource.schema.properties[this._dataSetName].properties;if(Object.keys(properties).length===1){tableName=Object.keys(properties)[0];if(properties[tableName].idProperty){this._resource.idProperty=properties[tableName].idProperty}}}for(var fnName in this._resource.fn){this[fnName]=this._resource.fn[fnName]["function"]}this._hasCUDOperations=this._resource.generic["create"]!==undefined||this._resource.generic["update"]!==undefined||this._resource.generic["delete"]!==undefined;this._hasSubmitOperation=this._resource.generic["submit"]!==undefined;if(!this._session){var myservice=progress.data.ServicesManager.getService(this._resource.service.name);this._session=myservice._session;this._session._pushJSDOs(this)}}else{throw new Error(msg.getMsgText("jsdoMSG004",this.name))}}else{this._buffers[""]=new progress.data.JSTableRef(this,"")}if(!this._session){throw new Error("JSDO: Unable to get user session for resource '"+this.name+"'")}for(var buf in this._buffers){this._buffers[buf]._parent=null;this._buffers[buf]._children=[];this._buffers[buf]._relationship=null;this._buffers[buf]._isNested=false;if(!this._defaultTableRef)this._defaultTableRef=this._buffers[buf];this._numBuffers++}if(this._numBuffers!=1)this._defaultTableRef=null;else{this.record=null}if(typeof Object.defineProperty=="function"){this._caseSensitive=false;Object.defineProperty(this,"caseSensitive",{get:function(){return this._caseSensitive},set:function(value){this._caseSensitive=value?true:false;for(var buf in this._buffers){this._buffers[buf].caseSensitive=this._caseSensitive}},enumerable:true,writeable:true});this._autoSort=true;Object.defineProperty(this,"autoSort",{get:function(){return this._autoSort},set:function(value){this._autoSort=value?true:false;for(var buf in this._buffers){this._buffers[buf].autoSort=this._autoSort}},enumerable:true,writeable:true})}this._properties={};if(typeof Object.defineProperty=="function"){Object.defineProperty(this,"this._properties",{get:function(){return this._properties},enumerable:false})}if(this._resource&&this._resource.fields){for(var buf in this._buffers){this._buffers[buf]._schema=this._resource.fields[buf];this._buffers[buf]._primaryKeys=this._resource.primaryKeys[buf];this._buffers[buf]._fields={};var fields=this._buffers[buf]._schema;for(var i=0;i1){for(var buf in this._buffers){var fields=[];var found=false;for(var i=0;i=0?index+1:"");element.value=value?value[index]:undefined;return element};this.isDataSet=function(){return this._dataSetName?true:false};this._invokeComplete=function(jsdo,success,request){if(request.async&&request.fnName){jsdo.trigger("afterInvoke",request.fnName,jsdo,success,request)}if(request.deferred){if(success){request.deferred.resolve(jsdo,success,request)}else{request.deferred.reject(jsdo,success,request)}}};this._invokeSuccess=function(){};this._invokeError=function(){};this._httpRequest=function(xhr,method,url,reqBody,request){function afterOpenRequest(){var input=null;if(reqBody){xhr.setRequestHeader("Content-Type","application/json; charset=utf-8");input=JSON.stringify(reqBody)}try{xhr.send(input)}catch(e){request.success=false;request.exception=e;xhr.jsdo._session._checkServiceResponse(xhr,request.success,request)}}if(!xhr){xhr=new XMLHttpRequest;xhr.onCompleteFn=this._invokeComplete;xhr.onSuccessFn=this._invokeSuccess;xhr.onErrorFn=this._invokeError;xhr.onreadystatechange=this.onReadyStateChangeGeneric;if(request.async&&request.fnName){this.trigger("beforeInvoke",request.fnName,this,request)}if(reqBody){if(this._resource&&this._resource.service){var useRequest=this._resource.service.useRequest;if(this._resource.service.settings&&this._resource.service.settings.useRequest!==undefined){useRequest=this._resource.service.settings.useRequest}if(useRequest){reqBody={request:reqBody}}}}}xhr.request=request;xhr.jsdo=this;request.jsdo=this;request.xhr=xhr;this._session._openRequest(xhr,method,url,request.async,afterOpenRequest);return request};this._getDataObject=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};var oldUseRelationships=this.useRelationships;try{this.useRelationships=false;for(var buf in this._buffers){dataObject[this._dataSetName][buf]=this._buffers[buf].getData()}}finally{this.useRelationships=oldUseRelationships}}else{if(this._dataProperty){dataObject[this._dataProperty]=this.getData()}else return this.getData()}return dataObject};this._getDataObjectAsNested=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};try{for(var buf in this._buffers){var bufObj=this._buffers[buf];if(bufObj._isNested)continue;this._nestChildren=false;if(bufObj._children.length>0){for(var i=0;i0){hasErrors=true}}if(hasErrors){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._allRecordsRejected=true;this._someRecordsRejected=false;hasCommittedRecords=false;for(i=0;i0&&!param.operations[0].success){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._convertForServer=true;this._buffers[buf]._convertForServer=true}}};this._convertRequestData=function(objParam){var buf,beforeData;if(this._convertForServer===false){return}for(buf in this._buffers){if(this._buffers[buf]._convertForServer){if(objParam[this._dataSetName]){if(objParam[this._dataSetName][buf]){this._convertTableData(this._buffers[buf],objParam[this._dataSetName][buf])}beforeData=objParam[this._dataSetName]["prods:before"];if(beforeData&&beforeData[buf]){this._convertTableData(this._buffers[buf],beforeData[buf])}}else if(objParam[buf]){this._convertTableData(this._buffers[buf],objParam[buf])}}}};this._convertTableData=function(tableRef,tableData){var i;for(i=0;i0){this._confirmOperationExists(progress.data.JSDO._OP_DELETE);checkedDelete=true}if(!checkedCreate&&tableRef._added.length>0){this._confirmOperationExists(progress.data.JSDO._OP_CREATE);checkedCreate=true}if(!checkedUpdate&&Object.keys(tableRef._changed).length>0){this._confirmOperationExists(progress.data.JSDO._OP_UPDATE);checkedUpdate=true}if(checkedDelete&&checkedCreate&&checkedUpdate){break}}};this._confirmOperationExists=function(operation){var operationStr=PROGRESS_JSDO_OP_STRING[operation];if(typeof this._resource.generic[operationStr]!=="function"){throw new Error(msg.getMsgText("jsdoMSG046",operationStr.toUpperCase()))}};this.invoke=function(name,object){var deferred,promise;try{var request=this[name](object);if(request.deferred){deferred=request.deferred;promise=request.deferred.promise()}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{if(!deferred){deferred=new progress.util.Deferred;promise=deferred.promise()}deferred.reject(this,false,{errorObject:error})}}return promise};this._syncTableRef=function(operation,tableRef,batch){var rowData,requestData,jsonObject,dataSetObject;if(tableRef._visited)return;tableRef._visited=true;if(!batch){batch={operations:[]}}else if(!batch.operations){batch.operations=[]}switch(operation){case progress.data.JSDO._OP_CREATE:for(var i=0;i0&&!dataSetJsonObject[tableRef._name])dataSetJsonObject[tableRef._name]=[];for(var i=0;i0||tableRef._added.length>0||hasUpdates){hasChanges=true;break}}return hasChanges};this._addDeletesToChangeSet=function(tableRef,dataSetJsonObject,request){for(var i=0;i=10){tmpIndex={};for(var i=0;ivalue2||value1===null)return false;else if(value11){for(var buf in this._buffers){if(this._buffers[buf]._isNested&&this._buffers[buf]._parent&&this._buffers[this._buffers[buf]._parent]){var srcData=this._buffers[this._buffers[buf]._parent]._data;var data=[];for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}var recordId=beforeTableJsonObject[0]["prods:clientId"];if(!recordId){throw new Error(msg.getMsgText("jsdoMSG035","_checkForDeleteError()"))}if(beforeTableJsonObject[0]["prods:hasErrors"]){var prods_id=beforeTableJsonObject[0]["prods:id"];var errorString=this._getErrorStringFromJsonObject(dataSetJsonObject,tableRef,prods_id);this._setErrorString(tableRef,recordId,errorString,true);hasError=true}}return hasError};this._mergeUpdateForSubmit=function(jsonObject,xhr){var errorString;if(!this._dataSetName){throw new Error(msg.getMsgText("jsdoMSG036","_mergeUpdateForSubmit()"))}var dataSetJsonObject=jsonObject[this._dataSetName];if(dataSetJsonObject[this._dataSetName])dataSetJsonObject=dataSetJsonObject[this._dataSetName];var beforeJsonObject=dataSetJsonObject["prods:before"];for(var buf in this._buffers){var tableRef=this._buffers[buf];var tableJsonObject=dataSetJsonObject[tableRef._name];if(tableJsonObject instanceof Array){for(var i=0;i1){request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}}if(beforeJsonObject){hasError=jsdo._checkForDeleteError(dataSetJsonObject,xhr)}if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._deleteError(jsdo,success,request)}}};this._deleteError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoDelete(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._createComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterCreate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterCreate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._createSuccess=function(jsdo,success,request){var xhr=request.xhr;var record=request.response;var hasError=jsdo._mergeUpdateForCUD(record,xhr);if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._createError(jsdo,success,request)}}};this._createError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoCreate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._updateComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterUpdate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterUpdate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._updateSuccess=function(jsdo,success,request){var xhr=request.xhr;var hasError=jsdo._mergeUpdateForCUD(request.response,xhr);if(hasError){request.success=false}if(jsdo.autoApplyChanges){if(!hasError){request.success=true;delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._updateError(jsdo,success,request)}}};this._updateError=function(jsdo,success,request){if(jsdo.autoApplyChanges){request.success=false;jsdo._undoUpdate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._saveChangesSuccess=function(jsdo,success,request){var records=request.response;jsdo._mergeUpdateForSubmit(records,request.xhr);jsdo._clearErrors();var changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(changes);if(jsdo.autoApplyChanges){jsdo._applyChanges()}};this._saveChangesError=function(jsdo,success,request){jsdo._setAllRecordsRejected(true);if(jsdo.autoApplyChanges){jsdo.rejectChanges()}jsdo._updateLastErrors(jsdo,null,null,request)};this._saveChangesSuccessTT=function(jsdo,success,request){var changes;jsdo._clearErrors();changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(false)};this._saveChangesComplete=function(jsdo,success,request){if(request.xhr.status>=200&&request.xhr.status<300&&(jsdo._lastErrors.length>0||jsdo._someRecordsRejected)){request.success=false}if(jsdo._useSubmit===true){jsdo._fireCUDTriggersForSubmit(request)}jsdo._undefWorkingRecord();jsdo._fireAfterSaveChanges(request.success,request)};this._fireAfterSaveChanges=function(success,request){this.trigger("afterSaveChanges",this,success,request);if(request.jsrecords){if(request.deferred){if(success){request.deferred.resolve(this,success,request)}else{request.deferred.reject(this,success,request)}}}else if(request.batch&&request.batch.deferred){if(success){request.batch.deferred.resolve(this,success,request)}else{request.batch.deferred.reject(this,success,request)}}var clearErrorString=this.autoApplyChanges;if(request.jsrecords){for(var idx=0;idx=400&&request.xhr.status<600){try{var responseObject=JSON.parse(request.xhr.responseText);if(responseObject instanceof Array){errorArray=responseObject}else if(responseObject instanceof Object){errorArray.push(responseObject)}for(i=0;i=400&&request.xhr.status<600)){errors.push({type:progress.data.JSDO.ERROR,error:"Error: HTTP Status "+request.xhr.status+" "+request.xhr.statusText,responseText:request.xhr.responseText})}}return errors};this._updateLastErrors=function(jsdo,batch,changes,request){var errors,errorText,responseObject,i,j,buf;if(batch){if(batch.operations===undefined)return;for(i=0;i=200&&request.xhr.status<300){jsdo._lastErrors.push({errorString:request.jsrecord.data._errorString});jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({type:progress.data.JSDO.DATA_ERROR,id:request.jsrecord.data._id,error:request.jsrecord.data._errorString})}else{errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}if(request.jsrecord&&(errors[j].type===progress.data.JSDO.APP_ERROR||errors[j].type===progress.data.JSDO.RETVAL)){errors[j].id=request.jsrecord.data._id;request.jsrecord._tableRef._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}}}}else if(changes instanceof Array){for(i=0;i=400&&request.xhr.status<600||request.xhr.status===0)){errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}for(buf in this._buffers){this._buffers[buf]._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}};this._checkSaveComplete=function(xhr){if(xhr.request){var jsdo=xhr.request.jsdo;var batch=xhr.request.batch;if(jsdo&&batch&&jsdo._async){if(jsdo._isBatchComplete(batch)){var success=jsdo._isBatchSuccess(batch);var request={batch:batch,success:success};jsdo._undefWorkingRecord();jsdo._lastErrors=[];if(!success&&batch.operations){jsdo._updateLastErrors(jsdo,batch,null)}this._setAllRecordsRejected(batch);jsdo._fireAfterSaveChanges(success,request)}}}};this._isBatchSuccess=function(batch){if(batch.operations){for(var i=0;i=200&&xhr.status<300||xhr.status===0&&xhr.responseText!==""){request.success=true;xhr.jsdo._session._saveClientContextId(xhr);if(typeof xhr.onSuccessFn=="function"){var operation;if(xhr.request.fnName!==undefined&&xhr.jsdo._resource.fn[xhr.request.fnName]!==undefined){operation=xhr.jsdo._resource.fn[xhr.request.fnName].operation}else operation=null;if(operation===undefined||operation!==null&&operation.mergeMode)xhr.jsdo._mergeInvoke(request.response,xhr);if(request.success)xhr.onSuccessFn(xhr.jsdo,request.success,request);else if(typeof xhr.onErrorFn=="function")xhr.onErrorFn(xhr.jsdo,request.success,request)}}else{request.success=false;if(xhr.status===0){request.exception=new Error(msg.getMsgText("jsdoMSG101"))}if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}}catch(e){request.success=false;request.exception=e;if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}xhr.jsdo._session._checkServiceResponse(xhr,request.success,request);if(typeof xhr.onCompleteFn=="function"){xhr.onCompleteFn(xhr.jsdo,request.success,request)}}};this.acceptChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].acceptChanges()}};this.rejectChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].rejectChanges()}};this.getChanges=function(){var result=[];for(var buf in this._buffers){var changes=this._buffers[this._buffers[buf]._name].getChanges();result=result.concat(changes)}return result};this.hasChanges=function(){for(var buf in this._buffers){if(this._buffers[this._buffers[buf]._name].hasChanges())return true}return false};this._applyChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name]._applyChanges()}};this.acceptRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.acceptRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","acceptRowChanges()"))};this.rejectRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.rejectRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","rejectRowChanges()"))};this.setProperties=function(propertiesObject){var prop;if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(typeof propertiesObject=="object"){this._properties={};for(prop in propertiesObject){if(propertiesObject.hasOwnProperty(prop)){if(typeof propertiesObject[prop]!=="function"){this._properties[prop]=propertiesObject[prop]}}}}else if(propertiesObject===undefined||propertiesObject===null){this._properties={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"Object","setProperties"))}};this.setProperty=function(propertyName,propertyValue){if(arguments.length<2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(arguments.length!==2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(typeof propertyName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"string","setProperty"))}if(propertyValue===undefined){delete this._properties[propertyName]}else{this._properties[propertyName]=propertyValue}};this.getProperties=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperties",0))}return this._properties};this.getProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}return this._properties[propertyName]};this.saveLocal=function saveLocal(arg1,arg2){var name;var dataMode;if(arguments.length>2){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"||arg1===null||arg1===undefined){name=arg1;dataMode=arg2}else{name=null;dataMode=arg1}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}if(typeof dataMode=="undefined"){dataMode=progress.data.JSDO.ALL_DATA}else{switch(dataMode){case progress.data.JSDO.ALL_DATA:case progress.data.JSDO.CHANGES_ONLY:break;default:throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var dataObj=this._prepareDataObjectForLocalStorage(dataMode);this._localStorage.saveToLocalStorage(name,dataObj)};this.readLocal=function readLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));this._restoreFromLocalStorage(object,progress.data.JSDO.MODE_EMPTY)}return object!==null};this.addLocalRecords=function addLocalRecords(arg1,arg2,arg3){var name;var addMode;var keyFields;if(arguments.length<1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"){name=arg1;addMode=arg2;keyFields=arg3}else{name="jsdo_"+this._resource.service.name+"_"+this._resource.name;addMode=arg1;keyFields=arg2}if(typeof name=="undefined"||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(addMode!=progress.data.JSDO.MODE_REPLACE){throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));try{this._restoreFromLocalStorage(object,addMode,keyFields)}catch(e){var text=e.message;throw new Error(text.replace(new RegExp("addRecords","g"),"addLocalRecords"))}}return object!==null};this._containsPrimaryKeys=function _containsPrimaryKeys(){for(var buf in this._buffers){if(this._buffers[buf]._primaryKeys===null)return false}return true};this._hasMatchingSchema=function _hasMatchingSchema(storageObject){var isValid=true;if(storageObject===null||Object.keys(storageObject).length===0)return true;if(this._dataSetName){if(storageObject[this._dataSetName]){for(var buf in this._buffers)if(storageObject[this._dataSetName][buf]===undefined){isValid=false;break}}else isValid=false}else if(this._dataProperty){storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._dataProperty]===undefined)isValid=false}else{storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._defaultTableRef._name]===undefined)isValid=false}return isValid};this.deleteLocal=function deleteLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}this._localStorage.clearLocalStorage(name)};this._prepareDataObjectForLocalStorage=function(option){var storageObject={};if(this._dataSetName){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet(this._dataSetName);break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet(this._dataSetName,true);break}}else if(this._dataProperty){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}else{switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}return storageObject};this._restoreFromLocalStorage=function(storageObject,addMode,keyFields){if(storageObject&&Object.keys(storageObject).length>0){if(this._dataSetName){for(var buf in this._buffers)this._restoreDataForTable(this._buffers[buf],storageObject,addMode,keyFields)}else this._restoreDataForTable(this._defaultTableRef,storageObject,addMode,keyFields)}else if(addMode===progress.data.JSDO.MODE_EMPTY)this._clearData()};this._restoreDataForTable=function(tableRef,jsonObject,addMode,keyFields){keyFields=keyFields!==undefined?keyFields:tableRef._primaryKeys;if(keyFields===undefined&&this._resource.idProperty){keyFields=[];keyFields[0]=this._resource.idProperty}if(this._dataSetName){var oldUseRelationships=this.useRelationships;this.useRelationships=false;try{tableRef.addRecords(jsonObject,addMode,keyFields)}finally{this.useRelationships=oldUseRelationships}}else{this._dataSetName="_localStorage";tableRef.addRecords(jsonObject,addMode,keyFields);this._dataSetName=null}};this.getMethodProperties=function(operation,name){var idx;if(this._resource._operations){if(this._resource._operations[operation]){return this._resource._operations[operation]}}else{this._resource._operations={}}for(var idx=0;idx1?[params.sort]:[]}sortFields="";for(index=0;index=1?params.filter:undefined}if(params.filter){if(typeof params.filter==="string"){doConversion=false}params.tableRef=tableName;if(doConversion&¶ms.tableRef===undefined){throw new Error(msg.getMsgText("jsdoMSG045","fill() or read()","params","tableRef"))}if(reqCapabilities["filter"].mapping==="ablFilter"){if(doConversion){ablFilter=progress.util._convertToABLWhereString(jsdo._buffers[params.tableRef],params.filter)}else{ablFilter=params.filter}}else if(reqCapabilities["filter"].mapping==="sqlQuery"){if(doConversion){sqlQuery=progress.util._convertToSQLQueryString(jsdo._buffers[params.tableRef],params.filter,true)}else{sqlQuery=params.filter}}}filter=JSON.stringify({ablFilter:ablFilter,sqlQuery:sqlQuery,orderBy:sortFields,skip:params.skip,top:params.top,id:params.id});params={filter:filter}}return params}});if(typeof progress.ui=="undefined")progress.ui={};progress.ui.UITableRef=function UITableRef(tableRef){this._tableRef=tableRef;this._listview=null;this._detailPage=null;this._listviewContent=undefined;this.addItem=function(format){var detailForm;if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._name));if(!this._listview)return;format=format?format:this._listview.format;detailForm=this._detailPage&&this._detailPage.name?this._detailPage.name:"";if(this._listviewContent===undefined){this.clearItems()}var text=this._listview.itemTemplate?this._listview.itemTemplate:progress.ui.UIHelper._itemTemplate;text=text.replace(new RegExp("{__format__}","g"),format);text=text.replace(new RegExp("{__id__}","g"),this._tableRef.record.data._id);text=text.replace(new RegExp("{__page__}","g"),detailForm);for(var field in this._tableRef.record.data){var value=this._tableRef.record.data[field];text=text.replace(new RegExp("{"+field+"}","g"),value!==undefined&&value!==null?value:"")}this._listviewContent+=text};this.clearItems=function(){if(this._listview){this._listviewContent="";var listviewElement=document.getElementById(this._listview.name);if(listviewElement){listviewElement.innerHTML=""}}};this._getFormFieldValue=function(fieldName,detailPageName){var value=null,field;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)value=field.val()}else{field=document.getElementById(fieldName);if(field){value=field.value}}return value};this._setFormField=function(fieldName,value,detailPageName){var field=null;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)field.val(value)}else{field=document.getElementById(fieldName);if(field){field.value=value}}};this.assign=function(detailPageName){if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._tableRef._name));if(arguments.length!==0&&typeof detailPageName!="string")throw new Error(msg.getMsgText("jsdoMSG024","UIHelper","assign()"));this._tableRef.record.assign(null);var fieldName;var schema=this._tableRef.getSchema();for(var i=0;i0){for(var i=0;i0&&fieldName.charAt(0)=="_")continue;if(fields&&fields[fieldName]===undefined)continue;var fieldLabel=this._tableRef._schema[i].title?this._tableRef._schema[i].title:this._tableRef._schema[i].name;var text=this._detailPage&&this._detailPage.fieldTemplate?this._detailPage.fieldTemplate:progress.ui.UIHelper._fieldTemplate;text=text.replace(new RegExp("{__label__}","g"),fieldLabel);text=text.replace(new RegExp("{__name__}","g"),this._tableRef._schema[i].name);htmltext+=text}htmltext+="";fields=null;return htmltext};this.getListViewRecord=function(htmlIElement){var id=htmlIElement.getAttribute("data-id");return this._tableRef.findById(id)};this.getFormRecord=function(detailPageName){var id=this._getFormFieldValue("_id",detailPageName);return this._tableRef.findById(id)};this._getIdOfElement=function(name){if(typeof $=="function"){var element=$("#"+name);if(!element||element.length===0){element=$('[dsid="'+name+'"]');if(element&&element.length==1){var id=element.attr("id");if(id)return id}}}return name};this.setDetailPage=function setDetailPage(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));this._detailPage=obj;this._detailPage.name=this._getIdOfElement(this._detailPage.name)};this.setListView=function setListView(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));if(obj.format&&typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"format"));this._listview=obj;this._listview.name=this._getIdOfElement(this._listview.name);if(!this._listview.format){if(typeof $=="function"){for(var i=0;i{__format__}';progress.ui.UIHelper._defaultFieldTemplate='
    '+''+'
    ';progress.ui.UIHelper._itemTemplate=progress.ui.UIHelper._defaultItemTemplate;progress.ui.UIHelper._fieldTemplate=progress.ui.UIHelper._defaultFieldTemplate;progress.ui.UIHelper.setItemTemplate=function(template){progress.ui.UIHelper._itemTemplate=template?template:progress.ui.UIHelper._defaultItemTemplate};progress.ui.UIHelper.setFieldTemplate=function(template){progress.ui.UIHelper._fieldTemplate=template?template:progress.ui.UIHelper._defaultFieldTemplate}})();(function(){if(progress===undefined){progress={}}if(progress.data===undefined){progress.data={}}progress.data.ServicesManager={};progress.data.ServicesManager._services=[];progress.data.ServicesManager._resources=[];progress.data.ServicesManager._data=[];progress.data.ServicesManager._sessions=[];progress.data.ServicesManager._jsdosessions=[];progress.data.ServicesManager.addResource=function(id,resource){if(progress.data.ServicesManager._resources[id]===undefined){progress.data.ServicesManager._resources[id]=resource}else{throw new Error("A resource named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getResource=function(id){return progress.data.ServicesManager._resources[id]};progress.data.ServicesManager.addService=function(id,service){if(progress.data.ServicesManager._services[id]===undefined){progress.data.ServicesManager._services[id]=service}else{throw new Error("A service named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getService=function(id){return progress.data.ServicesManager._services[id]};progress.data.ServicesManager.addSession=function(catalogURI,session){if(progress.data.ServicesManager._sessions[catalogURI]===undefined){progress.data.ServicesManager._sessions[catalogURI]=session}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.addJSDOSession=function(catalogURI,jsdosession){if(progress.data.ServicesManager._jsdosessions[catalogURI]===undefined){progress.data.ServicesManager._jsdosessions[catalogURI]=jsdosession}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.getSession=function(catalogURI){try{return progress.data.ServicesManager._sessions[catalogURI]}catch(e){return null}};progress.data.ServicesManager.cleanSession=function(session){var servicesKey,resourcesKey,sessionsKey,service,services=progress.data.ServicesManager._services,resources=progress.data.ServicesManager._resources,sessions=progress.data.ServicesManager._sessions,jsdosessions=progress.data.ServicesManager._jsdosessions;for(servicesKey in services){service=null;if(services[servicesKey]._session===session){service=services[servicesKey];delete services[servicesKey]}if(!service){continue}for(resourcesKey in resources){if(resources[resourcesKey].service===service){delete resources[resourcesKey]}}}for(sessionsKey in sessions){if(sessions[sessionsKey]===session){delete sessions[sessionsKey];if(jsdosessions[sessionsKey]){delete jsdosessions[sessionsKey]}}}};function extractParamsFromURL(url){var urlParams=[],paramName=null;if(typeof url==="string"){url.split("").forEach(function(c){if(c==="{"){paramName=""}else if(c==="}"){if(paramName){urlParams.push(paramName)}paramName=null}else if(paramName!==null){paramName+=c}})}return urlParams}progress.data.ServicesManager.addCatalog=function(services,session){var name,value;if(!services){throw new Error("Cannot find 'services' property in catalog file.")}if(services instanceof Array){services.forEach(function(service){if(progress.data.ServicesManager.getService(service.name)!==undefined){throw new Error("A service named '"+service.name+"' was already loaded.")}if(service.resources instanceof Array){service.resources.forEach(function(resource){if(progress.data.ServicesManager.getResource(resource.name)!==undefined){throw new Error("A resource named '"+resource.name+"' was already loaded.")}})}else{throw new Error("Missing 'resources' array in catalog.")}});for(var j=0;j1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","setContext",1))}if(typeof context==="object"){contextObject={};for(prop in context){if(context.hasOwnProperty(prop)){if(typeof context[prop]!=="function"){contextObject[prop]=context[prop]}}}}else if(context===undefined||context===null){contextObject={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","Session",1,"Object","setContextProperty"))}contextString=null};this.getContext=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContext",0))}return contextObject};this.getContextProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}return contextObject[propertyName]}};progress.data.Session=function Session(options){var defPropSupported=false;if(typeof Object.defineProperty==="function"){defPropSupported=true}var that=this,jsdosession,isUserAgentiOS=false,isFirefox=false,isEdge=false,isIE=false,canPassCredentialsToOpenWithCORS=false,defaultiOSBasicAuthTimeout=4e3,deviceIsOnline=true,restApplicationIsOnline=false,oepingAvailable=false,defaultPartialPingURI="/rest/_oeping",partialPingURI=defaultPartialPingURI,_storageKey,_authProvider=null,customCredentials=false,storedAuthModel,storedURI,newURI,stateWasReadFromStorage=false;if(!options||options._silent!==true){console.warn("Session: As of JSDO 4.4, the Session object has been deprecated. "+"Please use the JSDOSession object instead.")}if(typeof navigator!=="undefined"){if(typeof navigator.userAgent!=="undefined"){isUserAgentiOS=navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i);isFirefox=navigator.userAgent.toLowerCase().indexOf("firefox")>-1;isEdge=navigator.userAgent.indexOf("Edge/")>-1;isIE=navigator.userAgent.indexOf("Trident/")>-1||navigator.userAgent.indexOf("MSIE 10")>-1}}canPassCredentialsToOpenWithCORS=!(isFirefox||isEdge||isIE);function canPassCredentialsToOpen(){return canPassCredentialsToOpenWithCORS}this._onlineHandler=function(){setDeviceIsOnline(true);that.trigger("online",that,null)};this._offlineHandler=function(){setDeviceIsOnline(false);that.trigger("offline",that,progress.data.Session.DEVICE_OFFLINE,null)};if(typeof window!=="undefined"&&window.addEventListener){window.addEventListener("online",this._onlineHandler,false);window.addEventListener("offline",this._offlineHandler,false)}var _catalogURIs=[];var _services=[];var _jsdos=[];this.onOpenRequest=null;var _password=null;if(defPropSupported){var _userName=null;Object.defineProperty(this,"userName",{get:function(){return _userName},enumerable:true});var _loginTarget="/static/home.html";Object.defineProperty(this,"loginTarget",{get:function(){return _loginTarget},enumerable:true});var _serviceURI=null;Object.defineProperty(this,"serviceURI",{get:function(){return _serviceURI},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _catalogURIs},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _services},enumerable:true});var _loginResult=null;Object.defineProperty(this,"loginResult",{get:function(){return _loginResult},enumerable:true});var _loginHttpStatus=null;Object.defineProperty(this,"loginHttpStatus",{get:function(){return _loginHttpStatus},enumerable:true});var _clientContextId=null;Object.defineProperty(this,"clientContextId",{get:function(){return _clientContextId},enumerable:true});var _authenticationModel=progress.data.Session.AUTH_TYPE_ANON;Object.defineProperty(this,"authenticationModel",{get:function(){return _authenticationModel},set:function(newval){if(newval){newval=newval.toLowerCase()}switch(newval){case progress.data.Session.AUTH_TYPE_FORM:case progress.data.Session.AUTH_TYPE_BASIC:case progress.data.Session.AUTH_TYPE_ANON:case progress.data.Session.AUTH_TYPE_SSO:case null:_authenticationModel=newval;storeSessionInfo("authenticationModel",newval);break;default:throw new Error("Error setting Session.authenticationModel. '"+newval+"' is an invalid value.")}},enumerable:true});var _lastSessionXHR=null;Object.defineProperty(this,"lastSessionXHR",{get:function(){return _lastSessionXHR},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return this.loginResult===progress.data.Session.LOGIN_SUCCESS&&restApplicationIsOnline&&deviceIsOnline},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _jsdos},enumerable:true});var _pingInterval=0;var _timeoutID=null;Object.defineProperty(this,"pingInterval",{get:function(){return _pingInterval},set:function(newval){if(typeof newval==="number"&&newval>=0){_pingInterval=newval;storeSessionInfo("pingInterval",newval);if(newval>0){if(this.loginResult===progress.data.Session.LOGIN_SUCCESS){_timeoutID=setTimeout(this._autoping,newval)}}else if(newval===0){clearTimeout(_timeoutID);_pingInterval=0}}else{throw new Error("Error setting Session.pingInterval. '"+newval+"' is an invalid value.")}},enumerable:true});var _contextProperties=new progress.data.ContextProperties;Object.defineProperty(this,"_contextProperties",{get:function(){return _contextProperties},enumerable:false});var isInvalidated=false;Object.defineProperty(this,"_isInvalidated",{get:function(){return isInvalidated},enumerable:false});Object.defineProperty(this,"_authProvider",{get:function(){return _authProvider},set:function(newval){if(_authProvider){throw new Error("Internal Error setting Session._authProvider. '"+"The property has already been set.")}setAuthProvider(newval)},enumerable:false})}else{this.userName=null;this.loginTarget="/static/home.html";this.serviceURI=null;this.catalogURIs=[];this.services=[];this.loginResult=null;this.loginHttpStatus=null;this.clientContextId=null;this.authenticationModel=progress.data.Session.AUTH_TYPE_ANON;this.lastSessionXHR=null}function storeSessionInfo(infoName,value){var key;if(that.loginResult===progress.data.Session.LOGIN_SUCCESS&&typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}if(typeof value!=="undefined"){sessionStorage.setItem(key,JSON.stringify(value))}}}function retrieveSessionInfo(infoName){var key,jsonStr,value=null;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}jsonStr=sessionStorage.getItem(key);if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}}function clearSessionInfo(infoName){var key;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName;sessionStorage.removeItem(key)}}}function storeAllSessionInfo(){if(_storageKey){storeSessionInfo("loginResult",that.loginResult);storeSessionInfo("userName",that.userName);storeSessionInfo("serviceURI",that.serviceURI);storeSessionInfo("loginHttpStatus",that.loginHttpStatus);storeSessionInfo("authenticationModel",that.authenticationModel);storeSessionInfo("pingInterval",that.pingInterval);storeSessionInfo("oepingAvailable",oepingAvailable);storeSessionInfo("partialPingURI",partialPingURI);storeSessionInfo("clientContextId",that.clientContextId);storeSessionInfo("deviceIsOnline",deviceIsOnline);storeSessionInfo("restApplicationIsOnline",restApplicationIsOnline);if(that._authProvider){storeSessionInfo("_authProvider.init",{uri:that._authProvider.uri,authenticationModel:that._authProvider.authenticationModel})}storeSessionInfo(_storageKey,true)}}function clearAllSessionInfo(){if(_storageKey){if(retrieveSessionInfo(_storageKey)){clearSessionInfo("loginResult");clearSessionInfo("userName");clearSessionInfo("serviceURI");clearSessionInfo("loginHttpStatus");clearSessionInfo("clientContextId");clearSessionInfo("deviceIsOnline");clearSessionInfo("restApplicationIsOnline");clearSessionInfo("authenticationModel");clearSessionInfo("pingInterval");clearSessionInfo("oepingAvailable");clearSessionInfo("partialPingURI");clearSessionInfo("_authProvider.init");clearSessionInfo(_storageKey)}}}function setSessionInfoFromStorage(key){var authproviderInitObject;if(retrieveSessionInfo(key)){setLoginResult(retrieveSessionInfo("loginResult"),this);setUserName(retrieveSessionInfo("userName"),this);setServiceURI(retrieveSessionInfo("serviceURI"),this);setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"),this);setClientContextID(retrieveSessionInfo("clientContextId"),this);setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline"));setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline"));that.authenticationModel=retrieveSessionInfo("authenticationModel");that.pingInterval=retrieveSessionInfo("pingInterval");setOepingAvailable(retrieveSessionInfo("oepingAvailable"));setPartialPingURI(retrieveSessionInfo("partialPingURI"));if(!that._authProvider){authproviderInitObject=retrieveSessionInfo("_authProvider.init");if(authproviderInitObject){setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject))}}}}function setUserName(newname,sessionObject){if(defPropSupported){_userName=newname}else{sessionObject.userName=newname}storeSessionInfo("userName",newname)}function setLoginTarget(target,sessionObject){if(defPropSupported){_loginTarget=target}else{sessionObject.loginTarget=target}}function setServiceURI(url,sessionObject){if(defPropSupported){_serviceURI=url}else{sessionObject.serviceURI=url}storeSessionInfo("serviceURI",url)}function pushCatalogURIs(url,sessionObject){if(defPropSupported){_catalogURIs.push(url)}else{sessionObject.catalogURIs.push(url)}}function pushService(serviceObject,sessionObject){if(defPropSupported){_services.push(serviceObject)}else{sessionObject.services.push(serviceObject)}}function findService(serviceName){_services.forEach(function(service){if(service.name===serviceName){return service}});return null}function setLoginResult(result,sessionObject){if(defPropSupported){_loginResult=result}else{sessionObject.loginResult=result}if(result===progress.data.Session.LOGIN_SUCCESS){storeSessionInfo("loginResult",result)}else{clearAllSessionInfo()}}function setLoginHttpStatus(status,sessionObject){if(defPropSupported){_loginHttpStatus=status}else{sessionObject.loginHttpStatus=status}storeSessionInfo("loginHttpStatus",status)}function setClientContextIDfromXHR(xhr,sessionObject){if(xhr){setClientContextID(getResponseHeaderNoError(xhr,"X-CLIENT-CONTEXT-ID"),sessionObject)}}function setClientContextID(ccid,sessionObject){if(defPropSupported){_clientContextId=ccid}else{sessionObject.clientContextId=ccid}storeSessionInfo("clientContextId",ccid)}function setLastSessionXHR(xhr,sessionObject){if(defPropSupported){_lastSessionXHR=xhr}else{sessionObject.lastSessionXHR=xhr}}function setDeviceIsOnline(value){deviceIsOnline=value;storeSessionInfo("deviceIsOnline",value)}function setAuthProvider(value){_authProvider=value?value:null}function setRestApplicationIsOnline(value){restApplicationIsOnline=value;storeSessionInfo("restApplicationIsOnline",value)}function setOepingAvailable(value){oepingAvailable=value;storeSessionInfo("oepingAvailable",value)}function setPartialPingURI(value){partialPingURI=value;storeSessionInfo("partialPingURI",value)}function getResponseHeaderNoError(xhr,headerName){var allHeaders=xhr._pdsResponseHeaders,regExp;if(allHeaders===undefined){allHeaders=xhr.getAllResponseHeaders();if(allHeaders){xhr._pdsResponseHeaders=allHeaders}else{xhr._pdsResponseHeaders=null}}if(allHeaders){regExp=new RegExp("^"+headerName+":","mi");if(allHeaders.match(regExp)){return xhr.getResponseHeader(headerName)}}return null}this._pushJSDOs=function(jsdo){_jsdos.push(jsdo)};this._openRequest=function(xhr,verb,url,async,callback){var urlPlusCCID,that=this;function afterOpenAndAuthorize(arg){if(arg instanceof Error){throw arg}else{if(that.clientContextId&&that.clientContextId!=="0"){xhr.setRequestHeader("X-CLIENT-CONTEXT-ID",that.clientContextId)}setRequestHeaderFromContextProps(that,xhr);if(typeof that.onOpenRequest==="function"){var params={xhr:xhr,verb:verb,uri:urlPlusCCID,async:async,formPreTest:false,session:that};that.onOpenRequest(params)}if(callback){callback()}}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to make server request when there is no active session.")}urlPlusCCID=this._prependAppURL(url);urlPlusCCID=this._addCCIDtoURL(urlPlusCCID);if(progress.data.Session._useTimeStamp){urlPlusCCID=progress.data.Session._addTimeStampToURL(urlPlusCCID)}if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,verb,urlPlusCCID,async,afterOpenAndAuthorize)}else{this._setXHRCredentials(xhr,verb,urlPlusCCID,this.userName,_password,async);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json")}afterOpenAndAuthorize(xhr)}};this.pingTestCallback=function(cbArgs){var foundOeping=cbArgs.pingResult?true:false;setOepingAvailable(foundOeping)};this._onReadyStateChangeGeneric=function(){var xhr=this;var result;var errorObject;clearTimeout(xhr._requestTimeout);if(xhr.readyState===4){result=null;errorObject=null;if(typeof xhr.onResponseFn==="function"){try{result=xhr.onResponseFn(xhr)}catch(e){errorObject=e}}if(typeof xhr.onResponseProcessedFn==="function"){if(!result){result=progress.data.Session.GENERAL_FAILURE}xhr.onResponseProcessedFn(xhr.pdsession,result,errorObject,xhr)}}};this._disconnect=function(deferred){this._processDisconnectResult(null,deferred)};this._processDisconnectResult=function(xhr,deferred){this._reinitializeAfterLogout(this,progress.data.Session.SUCCESS);this._disconnectComplete(this,progress.data.Session.SUCCESS,null,null,deferred)};this._disconnectComplete=function(pdsession,result,errObj,xhr,deferred){pdsession.trigger("afterDisconnect",pdsession,result,errObj,xhr,deferred)};var pwSave=null;var unameSave=null;this.login=function(serviceURI,loginUserName,loginPassword,loginTarget){var uname,pw,isAsync=false,args=[],deferred,iOSBasicAuthTimeout,uriForRequest;pwSave=null;unameSave=null;if(!defPropSupported){this.authenticationModel=this.authenticationModel.toLowerCase()}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","login()"))}if(this.loginResult===progress.data.Session.LOGIN_SUCCESS||this._authProvider){throw new Error("Attempted to call login() on a Session object that is already logged in.")}if(arguments.length>0){if(arguments[0]&&typeof arguments[0]==="object"){args[0]=arguments[0].serviceURI;args[1]=arguments[0].userName;args[2]=arguments[0].password;args[3]=arguments[0].loginTarget;args[4]=arguments[0].async;deferred=arguments[0].deferred;iOSBasicAuthTimeout=arguments[0].iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","login","The iOSBasicAuthTimeout argument was invalid."))}}else{args=arguments}}if(args.length>0){if(args[0]){var restURLtemp=args[0];if(restURLtemp[restURLtemp.length-1]==="/"){restURLtemp=restURLtemp.substring(0,restURLtemp.length-1)}setServiceURI(restURLtemp,this)}else if(!this.serviceURI){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}if(args[1]){uname=args[1]}if(args[2]){pw=args[2]}if(args[3]){setLoginTarget(args[3],this)}if(args[4]){if(typeof args[4]==="boolean"){isAsync=args[4]}else{throw new Error("Session.login() was passed an async setting that is not a boolean.")}}}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}unameSave=uname;pwSave=pw;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON||this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){uname=null;pw=null}var xhr=new XMLHttpRequest;xhr.pdsession=this;try{uriForRequest=this.serviceURI+this.loginTarget;if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(uriForRequest)}this._setXHRCredentials(xhr,"GET",uriForRequest,uname,pw,isAsync);progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(this,xhr);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr._isAsync=isAsync;if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){xhr.onResponseFn=this._afterFormPretestLogin}else{xhr.onResponseFn=this._processLoginResult;xhr.onResponseProcessedFn=this._loginComplete}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout>0){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred}if(typeof this.onOpenRequest==="function"){var isFormPreTest=false;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){isFormPreTest=true}setLastSessionXHR(xhr,this);var params={xhr:xhr,verb:"GET",uri:this.serviceURI+this.loginTarget,async:false,formPreTest:isFormPreTest,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send(null)}catch(e){clearTimeout(xhr._requestTimeout);setLoginHttpStatus(xhr.status,this);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);unameSave=null;pwSave=null;throw e}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{setLoginHttpStatus(xhr.status,this);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){return this._afterFormPretestLogin(xhr)}else{return this._processLoginResult(xhr)}}};this._afterFormPretestLogin=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);var formLoginParams={xhr:xhr,pw:pwSave,uname:unameSave,theSession:pdsession};try{return doFormLogin(formLoginParams)}catch(e){pwSave=null;unameSave=null;throw e}};function doFormLogin(args){var xhr=args.xhr;var theSession=args.theSession;var oldXHR;var contentType=null;var needAuth=false;var params={session:theSession,xhr:xhr,statusFromjson:null};contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson||params.statusFromjson>=400&¶ms.statusFromjson<500){needAuth=true}else{setLoginHttpStatus(params.statusFromjson,theSession)}}else{if(theSession.loginHttpStatus===200){if(_gotLoginForm(xhr)){needAuth=true}}}if(needAuth){oldXHR=xhr;xhr=new XMLHttpRequest;args.xhr=xhr;params.xhr=xhr;xhr.pdsession=oldXHR.pdsession;xhr._isAsync=oldXHR._isAsync;xhr._deferred=oldXHR._deferred;xhr._jsdosession=oldXHR._jsdosession;xhr.open("POST",theSession.serviceURI+"/static/auth/j_spring_security_check",xhr._isAsync);xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.setRequestHeader("Cache-Control","max-age=0");setRequestHeaderFromContextProps(theSession,xhr);_addWithCredentialsAndAccept(xhr,"application/json");try{if(typeof theSession.onOpenRequest==="function"){var cbparams={xhr:xhr,verb:"POST",uri:theSession.serviceURI+"/static/auth/j_spring_security_check",async:xhr._isAsync,formPreTest:false,session:theSession};theSession.onOpenRequest(cbparams);xhr=cbparams.xhr}if(xhr._isAsync){xhr.onreadystatechange=theSession._onReadyStateChangeGeneric;xhr.onResponseFn=theSession._afterFormLogin;xhr.onResponseProcessedFn=theSession._loginComplete}xhr.send("j_username="+encodeURIComponent(args.uname)+"&j_password="+encodeURIComponent(args.pw)+"&submit=Submit")}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,theSession);setLoginHttpStatus(xhr.status,theSession);unameSave=null;pwSave=null;throw e}}if(xhr._isAsync&&!needAuth){xhr.onResponseProcessedFn=theSession._loginComplete;return theSession._afterFormLogin(xhr)}if(!xhr._isAsync){return theSession._afterFormLogin(xhr)}}this._afterFormLogin=function(xhr){var theSession=xhr.pdsession;var params={session:theSession,xhr:xhr,statusFromjson:null};var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson){throw new Error("Internal OpenEdge Mobile client error handling login response. HTTP status: "+xhr.status+".")}setLoginHttpStatus(params.statusFromjson,theSession)}else{if(xhr.status===200){if(_gotLoginFailure(xhr)||_gotLoginForm(xhr)){setLoginHttpStatus(401,theSession)}else{setLoginHttpStatus(xhr.status,theSession)}}}return theSession._processLoginResult(xhr)};this._processLoginResult=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);if(pdsession.loginHttpStatus===200){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);setUserName(unameSave,pdsession);_password=pwSave;pdsession._saveClientContextId(xhr);storeAllSessionInfo();var pingTestArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:pdsession._pingtestOnReadyStateChange};pingTestArgs.pingURI=pdsession._makePingURI();pdsession._sendPing(pingTestArgs)}else{if(pdsession.loginHttpStatus===401){setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE,pdsession)}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);unameSave=null;pwSave=null;if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","login"))}return pdsession.loginResult};this._loginComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterLogin",pdsession,result,errObj,xhr)};this.logout=function(args){var isAsync=false,errorObject=null,xhr,deferred,params;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","logout()"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&this.authenticationModel){throw new Error("Attempted to call logout when there is no active session.")}if(typeof args==="object"){isAsync=args.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","logout","The async argument was invalid."))}deferred=args.deferred}xhr=new XMLHttpRequest;xhr.pdsession=this;try{xhr._jsdosession=jsdosession;xhr._deferred=deferred;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM||this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;xhr.onResponseFn=this._processLogoutResult;xhr.onResponseProcessedFn=this._logoutComplete}xhr.open("GET",this.serviceURI+"/static/auth/j_spring_security_logout",isAsync);try{xhr.withCredentials=true}catch(e){}xhr.setRequestHeader("Accept","application/json");setRequestHeaderFromContextProps(this,xhr);if(typeof this.onOpenRequest==="function"){setLastSessionXHR(xhr,this);params={xhr:xhr,verb:"GET",uri:this.serviceURI+"/static/auth/j_spring_security_logout",async:false,formPreTest:false,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send()}else{xhr._anonymousLogoutOK=true}}catch(e){this._reinitializeAfterLogout(this,false);throw e}if(!isAsync){try{this._processLogoutResult(xhr)}catch(e){throw e}}if(isAsync&&this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){try{this._processLogoutResult(xhr)}catch(e){errorObject=e}this._logoutComplete(this,null,errorObject,xhr)}};this.invalidate=function(){isInvalidated=true;cleanServicesManager()};this._logoutComplete=function(pdsession,result,errorObject,xhr){pdsession.trigger("afterLogout",pdsession,errorObject,xhr)};this._processLogoutResult=function(xhr){var logoutSucceeded;var pdsession=xhr.pdsession;var basicStatusOK=false;if(xhr._anonymousLogoutOK){logoutSucceeded=true}else if(xhr.status!==200){if(pdsession.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(xhr.status===404){logoutSucceeded=true}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=true}updateContextPropsFromResponse(pdsession,xhr);pdsession._reinitializeAfterLogout(pdsession,logoutSucceeded)};this._reinitializeAfterLogout=function(pdsession,success){setLoginResult(null,pdsession);setLoginHttpStatus(null,pdsession);setClientContextID(null,pdsession);setUserName(null,pdsession);setAuthProvider(null);_password=null;if(success){setRestApplicationIsOnline(false);setOepingAvailable(false);setPartialPingURI(defaultPartialPingURI);setLastSessionXHR(null,pdsession);clearTimeout(_timeoutID)}};this.addCatalog=function(arg1,arg2,arg3,arg4){var catalogURI,catalogUserName,catalogPassword,isAsync=false,xhr,deferred,iOSBasicAuthTimeout,catalogIndex,authProvider,that=this;function addCatalogAfterOpen(){progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(isAsync){xhr.onreadystatechange=that._onReadyStateChangeGeneric;xhr.onResponseFn=that._processAddCatalogResult;xhr.onResponseProcessedFn=that._addCatalogComplete;if(that.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex}try{if(typeof that.onOpenRequest==="function"){setLastSessionXHR(xhr,that);var params={xhr:xhr,verb:"GET",uri:catalogURI,async:false,formPreTest:false,session:that};that.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,that);xhr.send(null)}catch(e){throw new Error("Error retrieving catalog '"+catalogURI+"'.\n"+e.message)}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{return that._processAddCatalogResult(xhr)}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}customCredentials=true;if(arguments.length>0){if(typeof arg1==="object"){if(!arguments[0].offlineAddCatalog){if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to call addCatalog when there is no active session.")}}catalogURI=arg1.catalogURI;if(!catalogURI||typeof catalogURI!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogURI argument was missing or invalid."))}catalogUserName=arg1.userName;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogUserName argument was invalid."))}catalogPassword=arg1.password;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogPassword argument was invalid."))}isAsync=arg1.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The async argument was invalid."))}iOSBasicAuthTimeout=arg1.iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The iOSBasicAuthTimeout argument was invalid."))}authProvider=arg1.authProvider;deferred=arg1.deferred;catalogIndex=arg1.catalogIndex}else{catalogURI=arg1;if(typeof catalogURI!=="string"){throw new Error("First argument to Session.addCatalog must be the URL of the catalog.")}catalogUserName=arg2;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error("Second argument to Session.addCatalog must be a user name string.")}catalogPassword=arg3;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error("Third argument to Session.addCatalog must be a password string.")}}}else{throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog.")}if(!authProvider){authProvider=this._authProvider;customCredentials=false}if(!catalogUserName){catalogUserName=this.userName}if(!catalogPassword){catalogPassword=_password}xhr=new XMLHttpRequest;xhr.pdsession=this;xhr._catalogURI=catalogURI;if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){if(isAsync){xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex;setTimeout(this._addCatalogComplete,10,this,progress.data.Session.CATALOG_ALREADY_LOADED,null,xhr);return progress.data.Session.ASYNC_PENDING}return progress.data.Session.CATALOG_ALREADY_LOADED}if(authProvider){authProvider._openRequestAndAuthorize(xhr,"GET",catalogURI,isAsync,addCatalogAfterOpen);return progress.data.Session.ASYNC_PENDING}else{this._setXHRCredentials(xhr,"GET",catalogURI,catalogUserName,catalogPassword,isAsync);return addCatalogAfterOpen()}};this._processAddCatalogResult=function(xhr){var _catalogHttpStatus=xhr.status;var theSession=xhr.pdsession;var servicedata;var catalogURI=xhr._catalogURI,serviceURL,theJSDOSession=jsdosession;if(!customCredentials){toggleOnlineState(xhr)}if((_catalogHttpStatus===200||_catalogHttpStatus===0)&&xhr.responseText){servicedata=theSession._parseCatalog(xhr);try{progress.data.ServicesManager.addCatalog(servicedata,theSession)}catch(e){if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){return progress.data.Session.CATALOG_ALREADY_LOADED}throw new Error("Error processing catalog '"+catalogURI+"'. \n"+e.message)}servicedata.forEach(function(service){serviceURL=theSession._prependAppURL(service.address);pushService(new progress.data.MobileServiceObject({name:service.name,uri:serviceURL}),theSession);if(service.settings&&service.settings.useXClientProps&&!theSession.xClientProps){console.warn("Catalog warning: Service settings property 'useXClientProps' "+"is true but 'xClientProps' property has not been set.")}});pushCatalogURIs(catalogURI,theSession);progress.data.ServicesManager.addSession(catalogURI,theSession);if(theJSDOSession){progress.data.ServicesManager.addJSDOSession(catalogURI,theJSDOSession)}}else if(_catalogHttpStatus===401){return progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","addCatalog"))}else{throw new Error("Error retrieving catalog '"+catalogURI+"'. Http status: "+_catalogHttpStatus+".")}return progress.data.Session.SUCCESS};this._addCatalogComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterAddCatalog",pdsession,result,errObj,xhr)};this.ping=function(args){var pingResult=false,pingArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:this._onReadyStateChangePing,offlineReason:null};if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(!this._authProvider&&this.loginResult!==progress.data.Session.LOGIN_SUCCESS){throw new Error("Attempted to call ping when not logged in.")}if(args){if(args.async!==undefined){pingArgs.async=args.async}if(args.doNotFireEvent!==undefined){pingArgs.fireEventIfOfflineChange=!args.doNotFireEvent}if(args.onCompleteFn&&typeof args.onCompleteFn==="function"){pingArgs.onCompleteFn=args.onCompleteFn}pingArgs.deferred=args.deferred;pingArgs.jsdosession=args.jsdosession}pingArgs.pingURI=that._makePingURI();that._sendPing(pingArgs);if(!pingArgs.async){if(pingArgs.xhr){pingResult=that._processPingResult(pingArgs);if(args.offlineReason!==undefined){args.offlineReason=pingArgs.offlineReason}}else{pingResult=false}if(args.xhr!==undefined){args.xhr=pingArgs.xhr}}return pingResult};this._isOnlineStateChange=function(isOnline){var stateChanged=false;if(isOnline&&!this.connected){stateChanged=true}else if(!isOnline&&this.connected){stateChanged=true}return stateChanged};this._checkServiceResponse=function(xhr,success,request){var offlineReason=null,wasOnline=this.connected;updateContextPropsFromResponse(this,xhr);if(!this._events){return}var offlineObservers=this._events.offline||[];var onlineObservers=this._events.online||[];if(offlineObservers.length===0&&onlineObservers.length===0){return}if(success){setRestApplicationIsOnline(true);setDeviceIsOnline(true)}else{if(deviceIsOnline){var localPingArgs={doNotFireEvent:true,offlineReason:null,async:false};if(!that.ping(localPingArgs)){offlineReason=localPingArgs.offlineReason;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}}if(wasOnline&&!this.connected){this.trigger("offline",this,offlineReason,request)}else if(!wasOnline&&this.connected){this.trigger("online",this,request)}};this._processPingResult=function(args){var xhr=args.xhr,pingResponseJSON,appServerStatus=null,wasOnline=this.connected,connectedBeforeCallback,assumeOepingFormat;if(args.hasOwnProperty("usingOepingFormat")){assumeOepingFormat=args.usingOepingFormat}else{assumeOepingFormat=oepingAvailable}if(xhr.status>=200&&xhr.status<300){updateContextPropsFromResponse(this,xhr);if(assumeOepingFormat){try{pingResponseJSON=JSON.parse(xhr.responseText);appServerStatus=pingResponseJSON.AppServerStatus}catch(e){console.error("Unable to parse ping response.")}}toggleOnlineState(xhr)}else{if(deviceIsOnline){if(xhr.status===0){args.offlineReason=progress.data.Session.SERVER_OFFLINE;setRestApplicationIsOnline(false)}else if(xhr.status===404||xhr.status===410){args.offlineReason=progress.data.Session.WEB_APPLICATION_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}else{args.offlineReason=progress.data.Session.DEVICE_OFFLINE}}if(appServerStatus){if(appServerStatus.PingStatus==="false"){args.offlineReason=progress.data.Session.APPSERVER_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}connectedBeforeCallback=this.connected;if(typeof xhr.onCompleteFn==="function"){xhr.onCompleteFn({pingResult:this.connected,xhr:xhr,offlineReason:args.offlineReason})}if(args.fireEventIfOfflineChange){if(wasOnline&&!connectedBeforeCallback){that.trigger("offline",that,args.offlineReason,null)}else if(!wasOnline&&connectedBeforeCallback){that.trigger("online",that,null)}}return this.connected};this._onReadyStateChangePing=function(){var xhr=this;var args;if(xhr.readyState===4){args={xhr:xhr,fireEventIfOfflineChange:true,offlineReason:null};that._processPingResult(args);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._pingtestOnReadyStateChange=function(){var xhr=this;if(xhr.readyState===4){var foundOeping=false;if(xhr.status>=200&&xhr.status<300){foundOeping=true}else{setPartialPingURI(that.loginTarget);console.warn("Default ping target not available, will use loginTarget instead.")}setOepingAvailable(foundOeping);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._sendPing=function(args){var xhr=new XMLHttpRequest,that=this;function sendPingAfterOpen(){if(args.async){xhr.onreadystatechange=args.onReadyStateFn;xhr.onCompleteFn=args.onCompleteFn;xhr._jsdosession=jsdosession;xhr._deferred=args.deferred}progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(that.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr.send(null)}try{if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,"GET",args.pingURI,args.async,sendPingAfterOpen)}else{this._setXHRCredentials(xhr,"GET",args.pingURI,this.userName,_password,args.async);if(xhr.readyState===1){sendPingAfterOpen()}}}catch(e){args.error=e}args.xhr=xhr};this._makePingURI=function(){var pingURI=this.serviceURI+partialPingURI;if(progress.data.Session._useTimeStamp){pingURI=progress.data.Session._addTimeStampToURL(pingURI)}return pingURI};this._autoping=function(){that.ping({async:true})};this._setXHRCredentials=function(xhr,verb,uri,userName,password,async){if(userName&&this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(canPassCredentialsToOpen()){xhr.open(verb,uri,async,userName,password)}else{xhr.open(verb,uri,async)}var auth=_make_basic_auth(userName,password);xhr.setRequestHeader("Authorization",auth)}else{xhr.open(verb,uri,async)}};this._addCCIDtoURL=function(url){var urlPart1,urlPart2,jsessionidStr,index;if(this.clientContextId&&this.clientContextId!=="0"){if(url.substring(0,this.serviceURI.length)===this.serviceURI){jsessionidStr=";"+"JSESSIONID="+this.clientContextId;index=url.indexOf("?");if(index===-1){url+=jsessionidStr}else{urlPart1=url.substring(0,index);urlPart2=url.substring(index);url=urlPart1+jsessionidStr+urlPart2}}}return url};this._saveClientContextId=function(xhr){setClientContextIDfromXHR(xhr,this)};this._parseCatalog=function(xhr){var jsonObject;var catalogdata;try{jsonObject=JSON.parse(xhr.responseText);catalogdata=jsonObject.services}catch(e){console.error("Unable to parse response. Make sure catalog has correct format.");catalogdata=null}return catalogdata};this._prependAppURL=function(oldURL){if(!oldURL){return this.serviceURI}var newURL=oldURL;var pat=/^https?:\/\//i;if(!pat.test(newURL)){if(newURL.indexOf("/")!==0){newURL="/"+newURL}newURL=this.serviceURI+newURL}return newURL};function _addWithCredentialsAndAccept(xhr,acceptString){try{xhr.withCredentials=true;xhr.setRequestHeader("Accept",acceptString)}catch(e){}}function _make_basic_auth(user,pw){var tok=user+":"+pw;var hash=btoa(tok);return"Basic "+hash}var loginFormIDString="j_spring_security_check";function _gotLoginForm(xhr){return _findStringInResponseHTML(xhr,loginFormIDString)}var loginFailureIdentificationString="login failed";function _gotLoginFailure(xhr){return _findStringInResponseHTML(xhr,loginFailureIdentificationString)}function _findStringInResponseHTML(xhr,searchString){if(!xhr.responseText){return false}var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("text/html")>=0&&xhr.responseText.indexOf(searchString)>=0){return true}return false}function handleJSONLoginResponse(params){var jsonObject;params.statusFromjson=null;try{jsonObject=JSON.parse(params.xhr.responseText);if(jsonObject.status_code!==undefined&&jsonObject.status_txt!==undefined){params.statusFromjson=jsonObject.status_code}}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,params.session);setLoginHttpStatus(params.xhr.status,params.session);throw new Error("Unable to parse login response from server.")}}function setRequestHeaderFromContextProps(session,xhr){if(session.xClientProps){xhr.setRequestHeader("X-CLIENT-PROPS",session.xClientProps)}else if(session._contextProperties.contextHeader!==undefined){xhr.setRequestHeader("X-CLIENT-PROPS",session._contextProperties.contextHeader)}}function toggleOnlineState(xhr){var pdsession=that;setLoginHttpStatus(xhr.status,pdsession);if(pdsession.loginHttpStatus>=200&&pdsession.loginHttpStatus<400){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);pdsession._saveClientContextId(xhr);storeAllSessionInfo()}else{if(pdsession.loginHttpStatus===0||pdsession.loginHttpStatus===400||pdsession.loginHttpStatus===410){setRestApplicationIsOnline(false);setLoginResult(progress.data.AuthenticationProvider._getAuthFailureReason(xhr),pdsession)}else{setRestApplicationIsOnline(true);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);return pdsession.loginResult}function updateContextPropsFromResponse(session,xhr){var contextString,context;if(xhr){contextString=getResponseHeaderNoError(xhr,"X-CLIENT-PROPS");if(contextString){try{context=JSON.parse(contextString)}catch(e){}if(typeof context==="object"){session._contextProperties.setContext(context)}else{throw new Error(progress.data._getMsgText("jsdoMSG123","Session","X-CLIENT-PROPS"))}}else if(contextString===""){session._contextProperties.setContext({})}}}function cleanServicesManager(){progress.data.ServicesManager.cleanSession(that)}if(typeof options==="object"){jsdosession=options.jsdosession;newURI=options.serviceURI;setAuthProvider(options.authProvider);if(options.authProvider&&options.authProvider.hasClientCredentials()){_loginResult=progress.data.Session.LOGIN_SUCCESS}if(newURI&&newURI[newURI.length-1]==="/"){newURI=newURI.substring(0,newURI.length-1)}_storageKey=options._storageKey;if(_storageKey){if(retrieveSessionInfo(_storageKey)){storedAuthModel=retrieveSessionInfo("authenticationModel");storedURI=retrieveSessionInfo("serviceURI");if(storedAuthModel!==options.authenticationModel||storedURI!==newURI){clearAllSessionInfo()}else{setSessionInfoFromStorage(_storageKey);stateWasReadFromStorage=true}}if(options.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){_storageKey=undefined}}if(!stateWasReadFromStorage){if(newURI){setServiceURI(newURI,this)}if(options.authenticationModel){this.authenticationModel=options.authenticationModel}}}};progress.data.Session._useTimeStamp=true;var SEQ_MAX_VALUE=999999999999999;var _tsseq=SEQ_MAX_VALUE;var _tsprefix1=0;var _tsprefix2=0;progress.data.Session._getNextTimeStamp=function(){var seq;_tsseq+=1;seq=_tsseq;if(seq>=SEQ_MAX_VALUE){_tsseq=1;seq=1;var t=Math.floor((Date.now?Date.now():(new Date).getTime())/1e4);if(_tsprefix1===t){_tsprefix2+=1;if(_tsprefix2>=SEQ_MAX_VALUE){_tsprefix2=1}}else{_tsprefix1=t;Math.random();_tsprefix2=Math.round(Math.random()*1e10)}}return _tsprefix1+"-"+_tsprefix2+"-"+seq};progress.data.Session._addTimeStampToURL=function(url){var timeStamp="_ts="+progress.data.Session._getNextTimeStamp();url+=(url.indexOf("?")===-1?"?":"&")+timeStamp;return url};progress.data.Session._setNoCacheHeaders=function(xhr){xhr.setRequestHeader("Cache-Control","no-cache");xhr.setRequestHeader("Pragma","no-cache")};if(typeof Object.defineProperty==="function"){Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_REQUIRED",{value:0,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"CATALOG_ALREADY_LOADED",{value:4,enumerable:true});Object.defineProperty(progress.data.Session,"ASYNC_PENDING",{value:5,enumerable:true});Object.defineProperty(progress.data.Session,"EXPIRED_TOKEN",{value:6,enumerable:true});Object.defineProperty(progress.data.Session,"SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_ANON",{value:"anonymous",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_BASIC",{value:"basic",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM",{value:"form",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_SSO",{value:"sso",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM_SSO",{value:"form_sso",enumerable:true});Object.defineProperty(progress.data.Session,"DEVICE_OFFLINE",{value:"Device is offline",enumerable:true});Object.defineProperty(progress.data.Session,"SERVER_OFFLINE",{value:"Cannot contact server",enumerable:true});Object.defineProperty(progress.data.Session,"WEB_APPLICATION_OFFLINE",{value:"Mobile Web Application is not available",enumerable:true});Object.defineProperty(progress.data.Session,"SERVICE_OFFLINE",{value:"REST web Service is not available",enumerable:true});Object.defineProperty(progress.data.Session,"APPSERVER_OFFLINE",{value:"AppServer is not available",enumerable:true})}else{progress.data.Session.LOGIN_SUCCESS=1;progress.data.Session.LOGIN_AUTHENTICATION_FAILURE=2;progress.data.Session.LOGIN_GENERAL_FAILURE=3;progress.data.Session.CATALOG_ALREADY_LOADED=4;progress.data.Session.SUCCESS=1;progress.data.Session.AUTHENTICATION_FAILURE=2;progress.data.Session.GENERAL_FAILURE=3;progress.data.Session.AUTH_TYPE_ANON="anonymous";progress.data.Session.AUTH_TYPE_BASIC="basic";progress.data.Session.AUTH_TYPE_FORM="form";progress.data.Session.AUTH_TYPE_SSO="sso"}progress.data.Session.prototype=new progress.util.Observable;progress.data.Session.prototype.constructor=progress.data.Session;function validateSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}else{listenerData.scope=args[2]}}}progress.data.Session.prototype._eventNames=["offline","online","afterLogin","afterAddCatalog","afterLogout","afterDisconnect"];progress.data.Session.prototype.validateSubscribe=validateSessionSubscribe;progress.data.Session.prototype.toString=function(radix){return"progress.data.Session"};progress.data.JSDOSession=function JSDOSession(options){var _pdsession,_serviceURI,that=this,_name;Object.defineProperty(this,"authenticationModel",{get:function(){return _pdsession?_pdsession.authenticationModel:undefined},enumerable:true});Object.defineProperty(this,"authProvider",{get:function(){return _pdsession?_pdsession._authProvider:null},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _pdsession?_pdsession.catalogURIs:undefined},enumerable:true});Object.defineProperty(this,"clientContextId",{get:function(){return _pdsession?_pdsession.clientContextId:undefined},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return _pdsession?_pdsession.connected:undefined},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _pdsession?_pdsession.JSDOs:undefined},enumerable:true});Object.defineProperty(this,"loginResult",{get:function(){return _pdsession?_pdsession.loginResult:undefined},enumerable:true});Object.defineProperty(this,"loginHttpStatus",{get:function(){return _pdsession?_pdsession.loginHttpStatus:undefined},enumerable:true});Object.defineProperty(this,"onOpenRequest",{get:function(){return _pdsession?_pdsession.onOpenRequest:undefined},set:function(newval){if(_pdsession){_pdsession.onOpenRequest=newval}},enumerable:true});Object.defineProperty(this,"pingInterval",{get:function(){return _pdsession?_pdsession.pingInterval:undefined},set:function(newval){if(_pdsession){_pdsession.pingInterval=newval}},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _pdsession?_pdsession.services:undefined},enumerable:true});Object.defineProperty(this,"serviceURI",{get:function(){if(_pdsession&&_pdsession.serviceURI){return _pdsession.serviceURI}else{return _serviceURI}},enumerable:true});Object.defineProperty(this,"userName",{get:function(){return _pdsession?_pdsession.userName:undefined},enumerable:true});Object.defineProperty(this,"name",{get:function(){return _name},enumerable:true});Object.defineProperty(this,"_isInvalidated",{get:function(){return _pdsession._isInvalidated},enumerable:false});function settlePromise(promise,fulfill,result,info){if(fulfill){promise.resolve(that,result,info)}else{promise.reject(that,result,info)}}function genericSessionEventHandler(pdsession,result,errorObject,xhr,deferred){var myDeferred;if(xhr){myDeferred=xhr._deferred}else{myDeferred=deferred}settlePromise(myDeferred,result===progress.data.Session.SUCCESS?true:false,result,{errorObject:errorObject,xhr:xhr})}function onAfterAddCatalog(pdsession,result,errorObject,xhr){var deferred,fulfill=false,settleResult,info;if(result===progress.data.Session.EXPIRED_TOKEN){settleResult=progress.data.Session.EXPIRED_TOKEN}else if(result===progress.data.Session.LOGIN_AUTHENTICATION_FAILURE){settleResult=progress.data.Session.LOGIN_AUTHENTICATION_FAILURE}else{settleResult=progress.data.Session.GENERAL_FAILURE}if(xhr&&xhr._deferred){deferred=xhr._deferred;if(result!==progress.data.Session.SUCCESS&&result!==progress.data.Session.CATALOG_ALREADY_LOADED){result=result||progress.data.Session.GENERAL_FAILURE;deferred._overallCatalogResult=progress.data.Session.GENERAL_FAILURE}deferred._results[xhr._catalogIndex]={catalogURI:xhr._catalogURI,result:result,errorObject:errorObject,xhr:xhr};deferred._numCatalogsProcessed+=1;if(deferred._numCatalogsProcessed===deferred._numCatalogs){deferred._processedPromise=true;if(!deferred._overallCatalogResult){fulfill=true;settleResult=progress.data.Session.SUCCESS}if(settleResult===progress.data.Session.SUCCESS){if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,details:xhr._deferred._results}}}else{if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,errorObject:new Error(progress.data._getMsgText("jsdoMSG512")),details:xhr._deferred._results}}}settlePromise(xhr._deferred,fulfill,settleResult,info)}}}function onAfterLogout(pdsession,errorObject,xhr){var result=progress.data.Session.GENERAL_FAILURE,fulfill=false;if(xhr&&xhr._deferred){if(!errorObject&&!pdsession.loginResult){result=progress.data.Session.SUCCESS;fulfill=true}settlePromise(xhr._deferred,fulfill,result,{errorObject:errorObject,xhr:xhr})}}function onPingComplete(args){var xhr=args.xhr;if(xhr&&xhr._deferred){settlePromise(xhr._deferred,args.pingResult,args.pingResult,{offlineReason:args.offlineReason,xhr:xhr})}}this.login=function(username,password,options){var deferred=new progress.util.Deferred,iOSBasicAuthTimeout;function callIsAuthorized(){that.isAuthorized().then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(that,object.result,object.info)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","JSDOSession","login()"))}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout}if(!_pdsession._authProvider){_pdsession._authProvider=new progress.data.AuthenticationProvider({uri:this.serviceURI,authenticationModel:this.authenticationModel});_pdsession._authProvider.logout().then(function(){return _pdsession._authProvider.login(username,password)}).then(function(){callIsAuthorized()},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}else{throw new Error(progress.data._getMsgText("jsdoMSG062","JSDOSession","login()"))}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.disconnect=function(){var deferred=new progress.util.Deferred,errorObject;try{_pdsession.subscribe("afterDisconnect",genericSessionEventHandler,this);_pdsession._disconnect(deferred)}catch(e){errorObject=new Error(progress.data._getMsgText("jsdoMSG049","JSDOSession","disconnect",e.message))}if(errorObject){if(progress.util.Deferred.useJQueryPromises){throw errorObject}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:errorObject})}}else{return deferred.promise()}};this.addCatalog=function(catalogURI,unameOrOpts,password,opts){var deferred=new progress.util.Deferred,catalogURIs,numCatalogs,catalogIndex,addResult,errorObject,iOSBasicAuthTimeout,username,options,authProvider;try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(typeof catalogURI==="string"){catalogURIs=[catalogURI]}else if(catalogURI instanceof Array){catalogURIs=catalogURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","addCatalog","The first argument must be a string or an array of strings specifying the URI of the catalog."))}if(unameOrOpts){if(typeof unameOrOpts==="string"){if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG058","Session"))}username=unameOrOpts;if(opts){options=opts;options.authProvider=undefined}}else if(typeof unameOrOpts==="object"){options=unameOrOpts}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDOSession","2","object","addCatalog"))}}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout;if(options.authProvider){authProvider=options.authProvider}else if(this.authProvider){authProvider=this.authProvider}}if(!authProvider&&!this.authProvider&&!username){throw new Error(progress.data._getMsgText("jsdoMSG511"))}_pdsession.subscribe("afterAddCatalog",onAfterAddCatalog,this);numCatalogs=catalogURIs.length;deferred._numCatalogs=numCatalogs;deferred._numCatalogsProcessed=0;deferred._results=[];deferred._results.length=numCatalogs;for(catalogIndex=0;catalogIndex=200&&xhr.status<300){deferred.resolve(that,progress.data.Session.SUCCESS,info)}else{if(xhr.status===401){cbresult=progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else{cbresult=progress.data.Session.GENERAL_FAILURE}deferred.reject(that,cbresult,info)}}};try{xhr.send()}catch(e){throw new Error("JSDOSession: Unable to validate authorization. "+e.message)}})}else{result=progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED;deferred.reject(that,result,{xhr:xhr})}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(that,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.setContext=function(context){_pdsession._contextProperties.setContext(context)};this.setContextProperty=function(propertyName,propertyValue){_pdsession._contextProperties.setContextProperty(propertyName,propertyValue)};this.getContext=function(){return _pdsession._contextProperties.getContext()};this.getContextProperty=function(propertyName){return _pdsession._contextProperties.getContextProperty(propertyName)};this._onlineHandler=function(session,request){that.trigger("online",that,request)};this._offlineHandler=function(session,offlineReason,request){that.trigger("offline",that,offlineReason,request)};if(arguments.length>0&&typeof arguments[0]==="object"){if(options.serviceURI&&typeof options.serviceURI==="string"){_serviceURI=options.serviceURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options parameter must include a 'serviceURI' property that is a string."))}if(options.authenticationModel){if(typeof options.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The authenticationModel property of the options parameter must be a string."))}options.authenticationModel=options.authenticationModel.toLowerCase()}else{options.authenticationModel=progress.data.Session.AUTH_TYPE_ANON}if(options.authProvider){if(typeof options.authProvider!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG502","JSDOSession","options","constructor","authProvider"))}if(options.authProvider.authenticationModel!==progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authProvider.authenticationModel!==options.authenticationModel||options.authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authenticationModel!==progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG059","JSDOSession",options.authProvider.authenticationModel,options.authenticationModel))}if(typeof options.authProvider.hasClientCredentials==="function"){if(!options.authProvider.hasClientCredentials()){throw new Error(progress.data._getMsgText("jsdoMSG125","JSDOSession"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG505","JSDOSession","AuthenticationProvider","hasClientCredentials"))}}else if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG508"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options argument was missing or invalid."))}_name=options.name;_pdsession=new progress.data.Session({_storageKey:_name,_silent:true,authenticationModel:options.authenticationModel,serviceURI:options.serviceURI,jsdosession:this,authProvider:options.authProvider});try{if(options.context){this.setContext(options.context)}_pdsession.subscribe("online",this._onlineHandler,this);_pdsession.subscribe("offline",this._offlineHandler,this)}catch(err){_pdsession=undefined;throw err}};progress.data.JSDOSession.prototype=new progress.util.Observable;progress.data.JSDOSession.prototype.constructor=progress.data.JSDOSession;function validateJSDOSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}listenerData.scope=args[2]}}progress.data.JSDOSession.prototype._eventNames=["offline","online"];progress.data.JSDOSession.prototype.validateSubscribe=validateJSDOSessionSubscribe;progress.data.JSDOSession.prototype.toString=function(radix){return"progress.data.JSDOSession"};progress.data.getSession=function(options){var deferred=new progress.util.Deferred,authProvider,promise,authProviderInitObject={};function sessionRejectHandler(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);if(authProvider&&authProvider.hasClientCredentials()){var callback=function(){deferred.reject(object.result,object.info)};authProvider.logout().then(callback,callback)}else{deferred.reject(object.result,object.info)}}function callbackRejectHandler(reason){deferred.reject(progress.data.Session.GENERAL_FAILURE,{reason:reason})}function loginHandler(object){var jsdosession;try{jsdosession=new progress.data.JSDOSession(options);try{jsdosession.isAuthorized().then(function(){return jsdosession.addCatalog(options.catalogURI)},sessionRejectHandler).then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(object.jsdosession,progress.data.Session.SUCCESS)},sessionRejectHandler)}catch(e){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}catch(ex){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:ex})}}function callLogin(provider){var errorObject;if(typeof options.loginCallback!=="undefined"){options.loginCallback().then(function(result){try{provider.login(result.username,result.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}},callbackRejectHandler)}else if(options.username&&options.password){try{provider.login(options.username,options.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG052","getSession()"));sessionRejectHandler(provider,progress.data.Session.AUTHENTICATION_FAILURE,{errorObject:errorObject})}}if(typeof options!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options","object"))}if(typeof options.loginCallback!=="undefined"&&typeof options.loginCallback!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options.loginCallback","function"))}try{if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){if(!options.authenticationURI||!options.authProviderAuthenticationModel){throw new Error(progress.data._getMsgText("jsdoMSG509"))}}if(options.authenticationURI){authProviderInitObject.uri=options.authenticationURI;authProviderInitObject.authenticationModel=options.authProviderAuthenticationModel;if(typeof authProviderInitObject.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG502","progress.data.getSession","object","getSession","authProviderAuthenticationModel"))}}else{authProviderInitObject.uri=options.serviceURI;authProviderInitObject.authenticationModel=options.authenticationModel}authProvider=new progress.data.AuthenticationProvider(authProviderInitObject);options.authProvider=authProvider;if(authProvider.hasClientCredentials()){loginHandler(authProvider)}else{if(authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){authProvider.login().then(loginHandler,sessionRejectHandler)}else{callLogin(authProvider)}}}catch(error){sessionRejectHandler(null,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}return deferred.promise()};progress.data.invalidateAllSessions=function(){var jsdosession,key,deferred=new progress.util.Deferred,jsdosessions=progress.data.ServicesManager._jsdosessions,invalidatePromises=[];try{for(key in jsdosessions){if(jsdosessions.hasOwnProperty(key)){jsdosession=jsdosessions[key];invalidatePromises.push(jsdosession.invalidate())}}progress.util.Deferred.when(invalidatePromises).then(function(){deferred.resolve(progress.data.Session.SUCCESS)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(progress.data.Session.GENERAL_FAILURE,info)})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()}})();if(typeof exports!=="undefined"){exports.progress=progress}(function(){"use strict";if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data.AuthenticationProvider=function AuthenticationProvider(initObject){var authProv,authModel,uri;if(typeof initObject==="object"){this._checkStringArg("constructor",initObject.authenticationModel,"initObject.authenticationModel","initObject.authenticationModel");this._checkStringArg("constructor",initObject.uri,"init-object.uri","init-object.uri")}else{throw new Error(progress.data._getMsgText("jsdoMSG033","AuthenticationProvider","the constructor","The init-object argument was missing or invalid."))}authModel=initObject.authenticationModel.toLowerCase();switch(authModel){case progress.data.Session.AUTH_TYPE_ANON:this._initialize(initObject.uri,progress.data.Session.AUTH_TYPE_ANON,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});authProv=this;break;case progress.data.Session.AUTH_TYPE_BASIC:authProv=new progress.data.AuthenticationProviderBasic(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM:authProv=new progress.data.AuthenticationProviderForm(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM_SSO:authProv=new progress.data.AuthenticationProviderSSO(initObject.uri);break;default:throw new Error(progress.data._getMsgText("jsdoMSG502","AuthenticationProvider","init-object","constructor","authenticationModel"))}return authProv};progress.data.AuthenticationProvider.prototype._loginProto=function(sendParam){var deferred=new progress.util.Deferred,xhr,uriForRequest,header,that=this;try{if(this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG051","AuthenticationProvider"))}xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLoginResult(xhr,deferred)}};if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(this._loginURI)}else{uriForRequest=this._loginURI}this._openLoginRequest(xhr,uriForRequest);xhr.setRequestHeader("Accept","application/json");xhr.send(sendParam)}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.login=function(){return this._loginProto()};progress.data.AuthenticationProvider.prototype._openLoginRequest=function(xhr,uri){xhr.open("GET",uri,true);progress.data.Session._setNoCacheHeaders(xhr)};progress.data.AuthenticationProvider.prototype._processLoginResult=function(xhr,deferred){var result;if(xhr.status===200){this._loggedIn=true;this._storeInfo();result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};progress.data.AuthenticationProvider.prototype.logout=function(){var deferred=new progress.util.Deferred;try{this._reset();deferred.resolve(this,progress.data.Session.SUCCESS,{})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.hasClientCredentials=function(){return this._loggedIn};progress.data.AuthenticationProvider.prototype.hasRefreshToken=function(){return false};progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);xhr.setRequestHeader("Accept","application/json");callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};progress.data.AuthenticationProvider.prototype._initialize=function(uriParam,authModel,targetURIs){var tempURI,target;Object.defineProperty(this,"uri",{get:function(){return this._uri},enumerable:true});Object.defineProperty(this,"authenticationModel",{get:function(){return this._authenticationModel},enumerable:true});if(uriParam[uriParam.length-1]==="/"){tempURI=uriParam.substring(0,uriParam.length-1)}else{tempURI=uriParam}for(target in targetURIs){if(targetURIs.hasOwnProperty(target)){this[target]=tempURI+targetURIs[target]}}this._authenticationModel=authModel;this._uri=uriParam;this._loggedIn=false;this._dataKeys={uri:".uri",loggedIn:".loggedIn"};if(typeof sessionStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","AuthenticationProvider","sessionStorage"))}this._storage=sessionStorage;this._storageKey=this._uri;this._dataKeys.uri=this._storageKey+this._dataKeys.uri;this._dataKeys.loggedIn=this._storageKey+this._dataKeys.loggedIn;if(this._retrieveLoggedIn()){this._loggedIn=true}};progress.data.AuthenticationProvider.prototype._storeInfo=function(){this._storage.setItem(this._dataKeys.uri,JSON.stringify(this._uri));this._storage.setItem(this._dataKeys.loggedIn,JSON.stringify(this._loggedIn))};progress.data.AuthenticationProvider.prototype._retrieveInfoItem=function(propName){var jsonStr=this._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value};progress.data.AuthenticationProvider.prototype._retrieveURI=function(){return this._retrieveInfoItem(this._dataKeys.uri)};progress.data.AuthenticationProvider.prototype._retrieveLoggedIn=function(){return this._retrieveInfoItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._clearInfo=function(info){this._storage.removeItem(this._dataKeys.uri);this._storage.removeItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._reset=function(){this._clearInfo();this._loggedIn=false};progress.data.AuthenticationProvider.prototype._settlePromise=function(deferred,result,info){if(result===progress.data.Session.SUCCESS){deferred.resolve(this,result,info)}else{deferred.reject(this,result,info)}};progress.data.AuthenticationProvider.prototype._checkStringArg=function(fnName,argToCheck,argPosition,argName){if(typeof argToCheck!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","AuthenticationProvider",argPosition,"string",fnName))}else if(argToCheck.length===0){throw new Error(progress.data._getMsgText("jsdoMSG501","AuthenticationProvider",argName,fnName))}};progress.data.AuthenticationProvider._getAuthFailureReason=function(xhr){var contentType,jsonObject,result=progress.data.Session.AUTHENTICATION_FAILURE;if(xhr.status===401){contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>-1&&xhr.responseText){jsonObject=JSON.parse(xhr.responseText);if(jsonObject.error==="sso.token.expired_token"){result=progress.data.Session.EXPIRED_TOKEN}}}else{result=null}return result};Object.defineProperty(progress.data.AuthenticationProvider,"_homeLoginURIBase",{value:"/static/home.html",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLoginURIBase",{value:"/static/auth/j_spring_security_check",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLogoutURIBase",{value:"/static/auth/j_spring_security_logout",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenLoginURIBase",{value:progress.data.AuthenticationProvider._springLoginURIBase+"?OECP=yes",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenRefreshURIBase",{value:"/static/auth/token?op=refresh",enumerable:true})})();(function(){"use strict";progress.data.AuthenticationProviderBasic=function(uri){var defaultiOSBasicAuthTimeout,userName=null,password=null,fn;this._initialize(uri,progress.data.Session.AUTH_TYPE_BASIC,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});this._reset();function make_basic_auth_header(user,pw){var tok=user+":"+pw,hash=btoa(tok);return"Basic "+hash}this._reset=function(){userName=null;password=null;progress.data.AuthenticationProviderBasic.prototype._reset.apply(this)};this._openLoginRequest=function(xhr,uri){var auth;xhr.open("GET",uri,true);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr)};this._processLoginResult=function _basic_processLoginResult(xhr,deferred){progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply(this,[xhr,deferred]);if(!this._loggedIn){userName=null;password=null}};this.login=function(userNameParam,passwordParam){this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");userName=userNameParam;password=passwordParam;return this._loginProto()};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var auth,errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr);callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}}};function BasicProxy(){}BasicProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderBasic.prototype=new BasicProxy;progress.data.AuthenticationProviderBasic.prototype.constructor=progress.data.AuthenticationProviderBasic})();(function(){"use strict";var fn;progress.data.AuthenticationProviderForm=function(uri){this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM,{_loginURI:progress.data.AuthenticationProvider._springLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase})};function FormProxy(){}FormProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderForm.prototype=new FormProxy;progress.data.AuthenticationProviderForm.prototype.constructor=progress.data.AuthenticationProviderForm;progress.data.AuthenticationProviderForm.prototype.login=function(userNameParam,passwordParam){var deferred=new progress.util.Deferred,xhr,that=this;this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");return this._loginProto("j_username="+encodeURIComponent(userNameParam)+"&j_password="+encodeURIComponent(passwordParam)+"&submit=Submit")};progress.data.AuthenticationProviderForm.prototype._openLoginRequest=function(xhr,uri){xhr.open("POST",uri,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.setRequestHeader("Pragma","no-cache");xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.withCredentials=true};progress.data.AuthenticationProviderForm.prototype.logout=function(){var deferred=new progress.util.Deferred,xhr,that=this;try{if(!this._loggedIn){deferred.resolve(this,progress.data.Session.SUCCESS,{})}else{xhr=new XMLHttpRequest;this._openLogoutRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLogoutResult(xhr,deferred)}};xhr.send()}this._reset()}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProviderForm.prototype._openLogoutRequest=function(xhr){xhr.open("GET",this._logoutURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Accept","application/json")};progress.data.AuthenticationProviderForm.prototype._processLogoutResult=function(xhr,deferred){var result;if(xhr.status===200){result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};fn=progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize;progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){function afterSuper(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.withCredentials=true;callback(xhr)}}try{progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply(this,[xhr,verb,uri,async,afterSuper])}catch(e){callback(e)}};progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super=fn})();(function(){"use strict";var fn;progress.data.AuthenticationProviderSSO=function(uri){var that=this,_automaticTokenRefresh,temp,ssoTokenInfo=null,tokenDataKeys={token:".access_token",refreshToken:".refresh_token",tokenType:".token_type",expiration:".expires_in",accessTokenExpiration:".accessTokenExpiration"};function storeTokenInfo(info){var date,accessTokenExpiration;if(info.access_token.length){that._storage.setItem(tokenDataKeys.token,JSON.stringify(info.access_token))}if(info.refresh_token.length){that._storage.setItem(tokenDataKeys.refreshToken,JSON.stringify(info.refresh_token));date=new Date;accessTokenExpiration=date.getTime()+info.expires_in*1e3*.75;that._storage.setItem(tokenDataKeys.accessTokenExpiration,JSON.stringify(accessTokenExpiration))}else{that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}that._storage.setItem(tokenDataKeys.tokenType,JSON.stringify(info.token_type));that._storage.setItem(tokenDataKeys.expiration,JSON.stringify(info.expires_in))}function retrieveTokenProperty(propName){var jsonStr=that._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}function retrieveToken(){return retrieveTokenProperty(tokenDataKeys.token)}function retrieveRefreshToken(){return retrieveTokenProperty(tokenDataKeys.refreshToken)}function retrieveAccessTokenExpiration(){return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration)}function retrieveTokenType(){return retrieveTokenProperty(tokenDataKeys.tokenType)}function getToken(){return retrieveToken()}function retrieveExpiration(){return retrieveTokenProperty(tokenDataKeys.expiration)}function clearTokenInfo(info){that._storage.removeItem(tokenDataKeys.token);that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.tokenType);that._storage.removeItem(tokenDataKeys.expiration);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}function openRefreshRequest(xhr){xhr.open("POST",that._refreshURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Content-Type","application/json");xhr.setRequestHeader("Accept","application/json")}function processRefreshResult(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",ex.message))}}else if(xhr.status===401){that._reset();result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}that._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})}this._processLoginResult=function(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){this._loggedIn=true;try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",ex.message))}if(result!==progress.data.Session.SUCCESS){var callback=function(params){params=progress.util.Deferred.getParamObject(params);params.provider._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})};this.logout().then(callback,callback);return}}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};this._reset=function(){progress.data.AuthenticationProviderSSO.prototype._reset.apply(this);clearTokenInfo();ssoTokenInfo=null};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var that=this,date,errorObject;function afterRefreshCheck(provider,result,info){if(result===progress.data.Session.AUTHENTICATION_FAILURE){callback(new Error(progress.data._getMsgText("jsdoMSG060")))}else{progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply(that,[xhr,verb,uri,async,function(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.setRequestHeader("Authorization","oecp "+getToken());callback(xhr)}}])}}if(this.hasClientCredentials()){date=new Date;if(this.automaticTokenRefresh&&this.hasRefreshToken()&&date.getTime()>retrieveAccessTokenExpiration()){try{var callback=function(params,result,info){params=progress.util.Deferred.getParamObject(params,result,info);afterRefreshCheck(params.provider,params.result,params.info)};this.refresh().then(callback,callback)}catch(e){callback(e)}}else{afterRefreshCheck(this,progress.data.Session.SUCCESS,null)}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};this.hasClientCredentials=function(){return retrieveToken()===null?false:true};this.refresh=function(){var deferred=new progress.util.Deferred,xhr;try{if(!this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG053","AuthenticationProvider","refresh"))}if(!this.hasRefreshToken()){throw new Error(progress.data._getMsgText("jsdoMSG054","AuthenticationProvider"))}xhr=new XMLHttpRequest;openRefreshRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){processRefreshResult(xhr,deferred)}};xhr.send('{"token_type":"'+retrieveTokenType()+'","refresh_token":"'+retrieveRefreshToken()+'"}')}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.hasRefreshToken=function(){return retrieveRefreshToken()===null?false:true};this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM_SSO,{_loginURI:progress.data.AuthenticationProvider._springFormTokenLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase,_refreshURI:progress.data.AuthenticationProvider._springFormTokenRefreshURIBase});_automaticTokenRefresh=true;Object.defineProperty(this,"automaticTokenRefresh",{get:function(){return _automaticTokenRefresh},set:function(value){if(value===true||value===false){_automaticTokenRefresh=value}else{throw new Error(progress.data._getMsgText("jsdoMSG061","AuthenticationProvider","automaticTokenRefresh"))}},enumerable:true});this._dataKeys.automaticTokenRefresh=this._storageKey+".automaticTokenRefresh";temp=this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh);if(temp===false){_automaticTokenRefresh=false}tokenDataKeys.token=this._storageKey+tokenDataKeys.token;tokenDataKeys.refreshToken=this._storageKey+tokenDataKeys.refreshToken;tokenDataKeys.tokenType=this._storageKey+tokenDataKeys.tokenType;tokenDataKeys.expiration=this._storageKey+tokenDataKeys.expiration;tokenDataKeys.accessTokenExpiration=this._storageKey+tokenDataKeys.accessTokenExpiration;if(retrieveToken()){this._loggedIn=true}};function SSOProxy(){}SSOProxy.prototype=progress.data.AuthenticationProviderForm.prototype;progress.data.AuthenticationProviderSSO.prototype=new SSOProxy;progress.data.AuthenticationProviderSSO.prototype.constructor=progress.data.AuthenticationProviderSSO;fn=progress.data.AuthenticationProviderSSO.prototype._storeInfo;progress.data.AuthenticationProviderSSO.prototype._storeInfo=function(){progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this);this._storage.setItem(this._dataKeys.automaticTokenRefresh,JSON.stringify(this._automaticTokenRefresh))};progress.data.AuthenticationProviderSSO.prototype._storeInfo._super=fn;fn=progress.data.AuthenticationProviderSSO.prototype._clearInfo;progress.data.AuthenticationProviderSSO.prototype._clearInfo=function(){progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this);this._storage.removeItem(this._dataKeys.automaticTokenRefresh)};progress.data.AuthenticationProviderSSO.prototype._clearInfo._super=fn})();if(typeof kendo!=="undefined"){(function(){var JSDODataReader,JSDOTransport,JSDOObservable=new kendo.Observable;function initializeJSDO(transport,options){var jsdo,resourceName;if(options.jsdo instanceof progress.data.JSDO){jsdo=options.jsdo}else if(typeof options.jsdo==="string"){resourceName=options.jsdo;jsdo=new progress.data.JSDO({name:resourceName})}else{throw new Error("JSDO: jsdo property must be either a JSDO instance or a string.")}if(transport.tableRef===undefined&&jsdo._defaultTableRef){transport.tableRef=jsdo._defaultTableRef._name}if(transport.tableRef===undefined){throw new Error("JSDO: A tableRef must be specified when using a multi-table DataSet.")}else if(jsdo[transport.tableRef]===undefined){throw new Error("JSDO: tableRef '"+transport.tableRef+"' is not present in JSDO definition.")}return jsdo}JSDODataReader=kendo.data.readers.json.extend({init:function(arg1){var event={},transport;JSDOObservable.trigger("info",event);transport=this.transport=event.sender._events.info.transport;kendo.data.readers.json.fn.init.call(this,arg1);this.model=kendo.data.Model.define({init:function(data){var record;if(!data||jQuery.isEmptyObject(data)){data=transport._getInitialValues()}record=transport._convertDataTypes(data);transport.jsdo._deleteProdsProperties(record,true);kendo.data.Model.fn.init.call(this,record)},id:"_id",fields:transport._getModel()})},total:function(data){return data.total||(data.data?data.data.length:data.length)},data:function(data){return data.data||data}});JSDOTransport=kendo.data.RemoteTransport.extend({init:function(options){var transport=this,fnName;if(options.tableRef!==undefined){transport.tableRef=options.tableRef}transport.jsdo=initializeJSDO(transport,options);transport._initFromServer=false;transport.autoSave=options.autoSave!==undefined?options.autoSave:true;transport.readLocal=options.readLocal!==undefined?options.readLocal:false;transport.countFnName=options.countFnName;transport.useArrays=options.useArrays!==undefined?options.useArrays:false;if(transport.countFnName!==undefined){if(typeof transport.jsdo[transport.countFnName]!=="function"){throw new Error("Invoke operation '"+transport.countFnName+"' for countFnName is not defined.")}}else if(transport.jsdo._resource.generic.count!==undefined){for(fnName in transport.jsdo._resource.fn){if(transport.jsdo._resource.fn.hasOwnProperty(fnName)){if(transport.jsdo._resource.generic.count===transport.jsdo._resource.fn[fnName]["function"]){transport.countFnName=fnName;break}}}}JSDOObservable.one("info",function(e){e.sender._events.info.transport=transport});transport._initConvertTypes();kendo.data.RemoteTransport.fn.init.call(this,options)},_initConvertTypes:function(){var transport=this,i,schema,fieldName,dateFields=[],arrayFields=[],convertDateFields=false;transport._convertTypes=false;schema=transport.jsdo[transport.tableRef].getSchema();for(i=0;i0&&fieldName.charAt(0)!=="_"){if(schema[i].type==="string"&&schema[i].format&&schema[i].format.indexOf("date")!==-1){dateFields.push(fieldName);if(!convertDateFields){convertDateFields=true}}else if(!transport.useArrays&&schema[i].type==="array"){arrayFields.push(fieldName);if(!convertDateFields&&schema[i].ablType&&schema[i].ablType.indexOf("DATE")===0){convertDateFields=true}}}}if(dateFields.length>0||arrayFields.length>0){transport._convertTypes=true;transport._convertFields={};transport._convertFields._arrayFields=[];transport._convertFields._dateFields=[]}if(dateFields.length>0){transport._convertFields._dateFields=dateFields}if(convertDateFields){transport._convertFields._datePattern=new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?$");transport._convertFields._dateTimePattern=new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?"+"T([0-9]{2})?:([0-9]{2})?:([0-9]{2})?.([0-9]{3})?$")}if(arrayFields.length>0){transport._convertFields._arrayFields=arrayFields}},_convertStringToDate:function(data,fieldName,targetFieldName){var transport=this,array,ablType,orig;if(!targetFieldName){targetFieldName=fieldName}array=transport._convertFields._datePattern.exec(data[targetFieldName])||[];if(array.length>0){data[targetFieldName]=new Date(parseInt(array[1],10),parseInt(array[2],10)-1,parseInt(array[3],10))}else{ablType=transport.jsdo[transport.tableRef]._fields[fieldName.toLowerCase()].ablType;if(ablType==="DATETIME"){array=transport._convertFields._dateTimePattern.exec(data[targetFieldName])||[];if(array.length>0){data[targetFieldName]=new Date(parseInt(array[1],10),parseInt(array[2],10)-1,parseInt(array[3],10),parseInt(array[4],10),parseInt(array[5],10),parseInt(array[6],10),parseInt(array[7],10))}}if(typeof data[targetFieldName]==="string"){orig=data[targetFieldName];try{data[targetFieldName]=new Date(data[targetFieldName])}catch(e){data[targetFieldName]=orig;console.log(progress.data._getMsgText("jsdoMSG000","_convertStringToDate() could not convert to date object: "+orig))}}}},_convertDataTypes:function(data){var transport=this,i,k,fieldName,schemaInfo,prefixElement,elementName,copy;if(!transport.useArrays&&transport._convertTypes&&transport._convertFields._arrayFields.length>0){copy={};transport.jsdo._copyRecord(transport.jsdo._buffers[transport.tableRef],data,copy);data=copy}if(!transport._convertTypes){return data}for(k=0;k0&&schema[i].name.charAt(0)!=="_"){type=schema[i].type;if(type==="integer"){type="number"}else if(type==="string"&&schema[i].format&&schema[i].format.indexOf("date")!==-1){type="date"}if(type==="array"){for(j=0;j0&&schema[i].name.charAt(0)!=="_"){defaultValue=transport.jsdo._getDefaultValue(schema[i]);if(schema[i].type==="array"){data[schema[i].name]=[];for(j=0;j0||jsdo[this.tableRef]._data instanceof Array&&jsdo[this.tableRef]._data.length>0}else{this._initFromServer=jsdo[this.tableRef]._data instanceof Array&&jsdo[this.tableRef]._data.length>0}}data.data=[];if(this.readLocal&&this._initFromServer){saveUseRelationships=jsdo.useRelationships;jsdo.useRelationships=false;data=this._getData(options);jsdo.useRelationships=saveUseRelationships;options.success(data);return}if(!this.readLocal){if(options.data){for(property in options.data){if(options.data.hasOwnProperty(property)){if(options.data[property]!==undefined&&optionsMapping[property]){if(filter===undefined){filter={}}filter[optionsMapping[property]]=options.data[property]}}}if(filter){filter.tableRef=this.tableRef}}}callback=function onAfterFillJSDO(object,success,request){var data={},saveUseRelationships,promise,total,exception,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;if(success){saveUseRelationships=jsdo.useRelationships;jsdo.useRelationships=false;if(transport.readLocal){data=transport._getData(options)}else{data.data=jsdo[transport.tableRef].getData();total=jsdo.getProperty("server.count");if(total){data.total=total}}jsdo.useRelationships=saveUseRelationships;transport._initFromServer=true;if(options.data&&options.data.take){if(!transport.readLocal&&transport.countFnName!==undefined&&typeof jsdo[transport.countFnName]==="function"){if(options.data.skip===0&&options.data.take>data.data.length){options.success(data);return}promise=jsdo.invoke(transport.countFnName,{filter:request.objParam.filter});promise.then(function(object,success,request){var exception,total,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;try{if(typeof request.response==="object"&&Object.keys(request.response).length===1){total=request.response[Object.keys(request.response)];if(typeof total!=="number"){total=undefined}}}catch(e){}if(total!==undefined){if(total){data.total=total}options.success(data)}else{exception=new Error("Unexpected response from '"+transport.countFnName+"' operation.");options.error(request.xhr,request.xhr.status,exception)}},function(object,success,request){var exception,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;exception=new Error("Error invoking '"+transport.countFnName+"' operation.");options.error(request.xhr,request.xhr.status,exception)})}else{options.success(data)}}else{options.success(data)}}else{exception=new Error("Error while reading records.");options.error(request.xhr,request.xhr.status,exception)}};jsdo.fill(filter).then(callback,callback)}catch(e){options.error(null,null,e)}},_processChanges:function(options,request){var jsdo=this.jsdo,transport=this,array,i,jsrecord,id,record;if(options.batch){array=[];if(options.data.created instanceof Array){for(i=0;i=2&&typeof args[0]==="string"&&typeof args[1]==="string"){listenerData.operation=args[1];listenerData.fn=args[2];listenerData.scope=args[3]}else if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="function"){listenerData.operation=undefined;listenerData.scope=args[2];listenerData.fn=args[1]}else{throw new Error}};this.subscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"subscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",progress.data._getMsgText("jsdoMSG039")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",e.message))}observers=this._events[evt]||[];observers=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation);observers.push(listenerData);this._events[evt]=observers;return this};this.unsubscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"unsubscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",progress.data._getMsgText("jsdoMSG037")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",e.message))}observers=this._events[evt]||[];if(observers.length>0){this._events[evt]=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation)}return this};this.trigger=function(evt,operation,args){var observers,op;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"trigger"))}this._events=this._events||{};evt=evt.toLowerCase();observers=this._events[evt]||[];if(observers.length>0){args=Array.prototype.slice.call(arguments);if(arguments.length>=2&&typeof evt==="string"&&typeof operation==="string"){op=operation;args=args.length>2?args.slice(2):[]}else if(arguments.length>=1&&typeof evt==="string"){op=undefined;args=args.length>1?args.slice(1):[]}else{throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"trigger"))}observers.forEach(function(el){if(el.operation===op){el.fn.apply(el.scope,args)}})}return this};this.unsubscribeAll=function(evt,operation){var observers;if(evt){this._events=this._events||{};if(typeof evt==="string"){evt=evt.toLowerCase();observers=this._events[evt]||[];observers.forEach(function(el){if(el.operation){this.unsubscribe(evt,el.operation,el.fn,el.scope)}else{this.unsubscribe(evt,el.fn,el.scope)}},this)}}else{this._events={}}return this}};progress.data.LocalStorage=function LocalStorage(){if(typeof localStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","progress.data.LocalStorage","localStorage"))}this.saveToLocalStorage=function(name,dataObj){localStorage.setItem(name,JSON.stringify(dataObj))};this.readFromLocalStorage=function(name){var jsonStr=localStorage.getItem(name),dataObj=null;if(jsonStr!==null){try{dataObj=JSON.parse(jsonStr)}catch(e){dataObj=null}}return dataObj};this.clearLocalStorage=function(name){localStorage.removeItem(name)}};progress.util._convertToABLWhereString=function(tableRef,filter){var result=[],logic=filter.logic||"and",idx,length,field,fieldInfo,type,format,operator,value,ablType,filters=filter.filters||[filter],whereOperators={eq:"=",neq:"<>",gt:">",gte:">=",lt:"<",lte:"<=",contains:"INDEX",doesnotcontain:"INDEX",endswith:"R-INDEX",startswith:"BEGINS",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};for(idx=0,length=filters.length;idx 0"}else{format="{2} MATCHES '*{1}'"}}else{format="{2} {0} "+format}filter=progress.util._format(format,operator,value,field)}else if(operator&&value===undefined){if(filter.operator==="isempty"||filter.operator==="isnotempty"){ablType=tableRef._getABLType(field);if(ablType!==CHARACTER_ABL_TYPE){throw new Error("Error parsing filter object. The operator "+filter.operator+" requires a CHARACTER field")}if(filter.operator==="isempty"){format="{2} = ''"}else if(filter.operator==="isnotempty"){format="{2} <> ''"}}else{if(filter.operator==="isnull"){format="{2} = ?"}else if(filter.operator==="isnotnull"){format="{2} <> ?"}else{format="{2} {0} ?"}}filter=progress.util._format(format,operator,value,field)}}result.push(filter)}filter=result.join(" "+logic+" ");if(result.length>1){filter="("+filter+")"}return filter};progress.util._convertToSQLQueryString=function(tableRef,filter,addSelect){var result=[],logic=filter.logic||"and",idx,length,field,type,format,operator,value,fieldFormat,filters=filter.filters||[filter],filterStr,usingLike=true,whereOperators={eq:"=",neq:"!=",gt:">",gte:">=",lt:"<",lte:"<=",contains:"LIKE",doesnotcontain:"NOT LIKE",endswith:"LIKE",startswith:"LIKE",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};if(typeof addSelect==="undefined"){addSelect=false}for(idx=0,length=filters.length;idx1){filterStr="("+filterStr+")"}if(addSelect===true){filterStr="SELECT * FROM "+tableRef._name+" WHERE "+filterStr}return filterStr};progress.util._getObjectType=function(value){return Object.prototype.toString.call(value).slice(8,-1)};progress.util._format=function(fmt){var values=arguments,formatRegExp=/\{(\d+)(:[^\}]+)?\}/g;return fmt.replace(formatRegExp,function(match,index,placeholderFormat){var value=values[parseInt(index,10)+1];return progress.util._toString(value,placeholderFormat?placeholderFormat.substring(1):"")})};progress.util._toString=function(value,fmt){var str;if(fmt){if(progress.util._getObjectType(value)==="Date"){return progress.util._formatDate(value,fmt)}}if(typeof value==="number"){str=value.toString()}else{str=value!==undefined?value:""}return str};progress.util._pad=function(number,digits){var zeros=["","0","00","000","0000"],end;number=String(number);digits=digits||2;end=digits-number.length;if(end){return zeros[digits].substring(0,end)+number}return number};progress.util._formatDate=function(date,format){var dateFormatRegExp=/dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g;return format.replace(dateFormatRegExp,function(match){var minutes,result,sign;if(match==="dd"){result=progress.util._pad(date.getDate())}else if(match==="MM"){result=progress.util._pad(date.getMonth()+1)}else if(match==="yyyy"){result=progress.util._pad(date.getFullYear(),4)}else if(match==="hh"){result=progress.util._pad(date.getHours())}else if(match==="mm"){result=progress.util._pad(date.getMinutes())}else if(match==="ss"){result=progress.util._pad(date.getSeconds())}else if(match==="fff"){result=progress.util._pad(date.getMilliseconds(),3)}else if(match==="FFF"){result=String(date.getTime())}else if(match==="zzz"){minutes=date.getTimezoneOffset();sign=minutes<0;result=(sign?"+":"-")+minutes}else if(match==="iso"){result=date.toISOString()}return result!==undefined?result:match.slice(1,match.length-1)})};progress.util.jsdoSettingsProcessor=function jsdoSettingsProcessor(jsdoSettings){if(typeof jsdoSettings==="object"){if(jsdoSettings.authenticationModel===undefined||jsdoSettings.authenticationModel===""){jsdoSettings.authenticationModel="ANONYMOUS"}}}})();(function(){var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS=20,PROGRESS_JSDO_OP_STRING=["none","create","read","update","delete","submit"],PROGRESS_JSDO_ROW_STATE_STRING=["","created","","modified","deleted"];if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data._nextid=0;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime());var UID_MAX_VALUE=999999999999999;progress.data._getNextId=function(){var uid=++progress.data._nextid;if(uid>=UID_MAX_VALUE){progress.data._nextid=uid=1;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime())}return progress.data._uidprefix+"-"+uid};var msg={};msg.msgs={};msg.msgs.jsdoMSG000="JSDO, Internal Error: {1}";msg.msgs.jsdoMSG001="JSDO: JSDO has multiple tables. Please use {1} at the table reference level.";msg.msgs.jsdoMSG002="JSDO: Working record for '{1}' is undefined.";msg.msgs.jsdoMSG003="JSDO: {1} function requires a function as a parameter.";msg.msgs.jsdoMSG004="JSDO: Unable to find resource '{1}' in the catalog.";msg.msgs.jsdoMSG005="JSDO: Data for table '{1}' was not specified in addRecords() call.";msg.msgs.jsdoMSG006="JSDO: Data for JSDO was not specified in addRecords() call.";msg.msgs.jsdoMSG007="JSDO: Test function in {1} must return a boolean.";msg.msgs.jsdoMSG008="JSDO: Invalid keyFields parameter in addRecords() call.";msg.msgs.jsdoMSG009="JSDO: KeyField '{1}' in addRecords() call was not found in the schema.";msg.msgs.jsdoMSG010="JSDO: Field '{1}' in relationship was not found in the schema.";msg.msgs.jsdoMSG011="UIHelper: JSDO has multiple tables. "+"Please use {1} at the table reference level.";msg.msgs.jsdoMSG012="UIHelper: Invalid {2} parameter in {1} call.";msg.msgs.jsdoMSG020="JSDO: tableName parameter must be a string in addRecords() call.";msg.msgs.jsdoMSG021="JSDO: addMode parameter must be specified in addRecords() call.";msg.msgs.jsdoMSG022="JSDO: Invalid addMode specified in addRecords() call.";msg.msgs.jsdoMSG023="JSDO: Duplicate found in addRecords() call using APPEND mode.";msg.msgs.jsdoMSG024="{1}: Unexpected signature in call to {2} function.";msg.msgs.jsdoMSG025="{1}: Invalid parameters in call to {2} function.";msg.msgs.jsdoMSG026="JSDO: saveChanges requires a "+"CREATE, UPDATE, DELETE or SUBMIT operation to be defined.";msg.msgs.jsdoMSG030="JSDO: Invalid {1}, expected {2}.";msg.msgs.jsdoMSG031="JSDO: Specified sort field name '{1}' was not found in the schema.";msg.msgs.jsdoMSG032="JSDO: Before-image data already exists for record in addRecords() call.";msg.msgs.jsdoMSG033="{1}: Invalid signature for {2}. {3}";msg.msgs.jsdoMSG034="JSDO: In '{1}' function, JSON data is missing _id";msg.msgs.jsdoMSG035="JSDO: In '{1}' function, before-image JSON data is missing prods:clientId";msg.msgs.jsdoMSG036="JSDO: '{1}' can only be called for a dataset";msg.msgs.jsdoMSG037="{1}: Event name must be provided for {2}.";msg.msgs.jsdoMSG038="Too few arguments. There must be at least {1}.";msg.msgs.jsdoMSG039="The name of the event is not a string.";msg.msgs.jsdoMSG040="The event listener is not a function.";msg.msgs.jsdoMSG041="The event listener scope is not an object.";msg.msgs.jsdoMSG042="'{1}' is not a defined event for this object.";msg.msgs.jsdoMSG043="{1}: A session object was requested to check the status of a Mobile "+"Service named '{2}', but it has not loaded the definition of that service.";msg.msgs.jsdoMSG044="JSDO: In '{1}' function, {2} is missing {3} property.";msg.msgs.jsdoMSG045="JSDO: {1} function: {2} is missing {3} property.";msg.msgs.jsdoMSG046="JSDO: {1} operation is not defined.";msg.msgs.jsdoMSG047="{1} timeout expired.";msg.msgs.jsdoMSG048="{1}: {2} method has argument '{3}' that is missing property '{4}'.";msg.msgs.jsdoMSG049="{1}: Unexpected error calling {2}: {3}";msg.msgs.jsdoMSG050="No token returned from server";msg.msgs.jsdoMSG051="{1} The login method was not executed because the AuthenticationProvider is already logged in.";msg.msgs.jsdoMSG052="{1}: The login method was not executed because no credentials were supplied.";msg.msgs.jsdoMSG053="{1}: {2} was not executed because the AuthenticationProvider is not logged in.";msg.msgs.jsdoMSG054="{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token.";msg.msgs.jsdoMSG055="{1}: Token refresh was not executed because the authentication model is not sso.";msg.msgs.jsdoMSG056="{1}: Already logged in.";msg.msgs.jsdoMSG057="{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead.";msg.msgs.jsdoMSG058="{1}: Cannot pass username and password to addCatalog when authenticationModel "+"is sso. Pass an AuthenticationProvider instead.";msg.msgs.jsdoMSG059="{1}: Error in constructor. The authenticationModels of the "+"AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible.";msg.msgs.jsdoMSG060="AuthenticationProvider: AuthenticationProvider is no longer logged in. "+"Tried to refresh SSO token but failed due to authentication error at token server.";msg.msgs.jsdoMSG061="{1}: Attempted to set {2} property to an invalid value.";msg.msgs.jsdoMSG062="{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in.";msg.msgs.jsdoMSG100="JSDO: Unexpected HTTP response. Too many records.";msg.msgs.jsdoMSG101="Network error while executing HTTP request.";msg.msgs.jsdoMSG110="Catalog error: idProperty not specified for resource '{1}'. "+"idProperty is required {2}.";msg.msgs.jsdoMSG111="Catalog error: Schema '{1}' was not found in catalog.";msg.msgs.jsdoMSG112="Catalog error: Output parameter '{1}' was not found for operation '{2}'.";msg.msgs.jsdoMSG113="Catalog error: Found xType '{1}' for output parameter '{2}' "+"for operation '{3}' but xType DATASET, TABLE or ARRAY was expected.";msg.msgs.jsdoMSG114="JSDO: idProperty '{1}' is missing from '{2}' record.";msg.msgs.jsdoMSG115="JSDO: Invalid option specified in {1}() call.";msg.msgs.jsdoMSG116="JSDO: {1} parameter must be a string in {2} call.";msg.msgs.jsdoMSG117="JSDO: Schema from storage area '{1}' does not match JSDO schema";msg.msgs.jsdoMSG118="JSDO: Plugin '{1}' was not found.";msg.msgs.jsdoMSG119="JSDO: A mappingType is expected when 'capabilities' is set."+" Please specify a plugin (ex: JFP).";msg.msgs.jsdoMSG120="JSDO: Parameter '{2}' requires capability '{1}' in the catalog.";msg.msgs.jsdoMSG121="{1}: Argument {2} must be of type {3} in {4} call.";msg.msgs.jsdoMSG122="{1}: Incorrect number of arguments in {2} call. There should be {3}.";msg.msgs.jsdoMSG123="{1}: A server response included an invalid '{2}' header.";msg.msgs.jsdoMSG124="JSDO: autoApplyChanges is not supported for saveChanges(true) "+"with a temp-table. Use jsdo.autoApplyChanges = false.";msg.msgs.jsdoMSG125="{1}: The AuthenticationProvider is not managing valid credentials.";msg.msgs.jsdoMSG126="{1}: No support for {2}.";msg.msgs.jsdoMSG127="JSDO: acceptRowChanges() cannot be called for record with _rejected === true.";msg.msgs.jsdoMSG500="{1}: '{2}' objects must contain a '{3}' property.";msg.msgs.jsdoMSG501="{1}: '{2}' in '{3}' function cannot be an empty string.";msg.msgs.jsdoMSG502="{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for "+"its '{4}' property.";msg.msgs.jsdoMSG503="{1}: '{2}' must be of type '{3}'.";msg.msgs.jsdoMSG504="{1}: {2} has an invalid value for the '{3}' property.";msg.msgs.jsdoMSG505="{1}: '{2}' objects must have a '{3}' method.";msg.msgs.jsdoMSG506="{1}: Invalid argument for the {2} parameter in {3} call.";msg.msgs.jsdoMSG507="{1}: '{2}' is an invalid value for the {3} parameter in {4} call.";msg.msgs.jsdoMSG508="JSDOSession: If a JSDOSession object is using the SSO authentication model, "+"the options object passed to its constructor must include an authProvider property.";msg.msgs.jsdoMSG509="progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, "+"authenticationURI and authProviderAuthenticationModel are required parameters.";msg.msgs.jsdoMSG510="{1}: This session has been invalidated and cannot be used.";msg.msgs.jsdoMSG511="JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or "+"connect() has been successfully called.";msg.msgs.jsdoMSG512="JSDOSession: Error while loading multiple catalogs.";msg.msgs.jsdoMSG998="JSDO: JSON object in addRecords() must be DataSet or Temp-Table data.";msg.getMsgText=function(n,args){var text=msg.msgs[n],i;if(!text){throw new Error("Message text was not found by getMsgText()")}for(i=1;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true;data=newDataArray}else{if(params&&(params.sort||params.top)){newDataArray=[];for(i=0;i0){sortObject.tableRef=this;data.sort(this._getCompareFn(sortObject))}}if(params.top){if(typeof params.skip=="undefined"){params.skip=0}data=data.splice(params.skip,params.top)}}return data};this._recToDataObject=function(record,includeChildren){var array=[record];var dataObject=array;if(typeof includeChildren=="undefined"){includeChildren=false}if(this._jsdo._dataSetName){dataObject={};dataObject[this._jsdo._dataSetName]={};dataObject[this._jsdo._dataSetName][this._name]=array;if(includeChildren&&this._children.length>0){var jsrecord=this._findById(record._id,false);if(jsrecord){for(var i=0;i0){for(var j=0;j0){for(var i=0;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true};this._equalRecord=function(rec1,rec2,keyFields){var field;var match=true;for(var i=0;ivalue2||(value1===undefined||value1===null))return sortAscending[i]?1:-1;else if(value10)this._sort(sortObject)}else{this._sort(arg1)}this._createIndex()};this._sort=function(arg1){if(arguments.length===0&&(!this.autoSort||this._sortFn===undefined&&this._sortObject.sortFields===undefined))return;if(arguments.length===0){if(this._sortFn){this._data.sort(this._sortFn)}else{this._data.sort(this._compareFields)}this._needsAutoSorting=false}else{if(typeof arg1=="function"){this._data.sort(this._getCompareFn(arg1))}else{arg1.tableRef=this;this._data.sort(this._getCompareFn(arg1))}if(this.autoSort)this._needsAutoSorting=true}};this.addRecords=function(jsonObject,addMode,keyFields,trackChanges,isInvoke){this._jsdo._addRecords(this._name,jsonObject,addMode,keyFields,trackChanges,isInvoke)};this.acceptChanges=function(){var tableRef=this;for(var id in tableRef._beforeImage){if(tableRef._beforeImage[id]===null){var jsrecord=tableRef._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}else if(this._changed[id]!==undefined){var jsrecord=this._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}}tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[];tableRef._beforeImage={}};this.rejectChanges=function(){for(var id in this._beforeImage){if(this._beforeImage[id]===null){this._jsdo._undoCreate(this,id)}else if(this._changed[id]!==undefined){this._jsdo._undoUpdate(this,id,true)}else{this._jsdo._undoDelete(this,id,true)}}var tableRef=this;tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[]};this.hasChanges=function(){return Object.keys(this._beforeImage).length!==0};this.getChanges=function(){var result=[];for(var id in this._beforeImage){var item={rowState:"",record:null};if(this._beforeImage[id]===null){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE];item.record=this._findById(id,false)}else if(this._changed[id]!==undefined){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE];item.record=this._findById(id,false)}else{item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE];item.record=new progress.data.JSRecord(this,this._beforeImage[id])}result.push(item)}return result};this._clearErrorStrings=function(){var record=null;for(var id in this._beforeImage){if(this._beforeImage[id]===null){record=this._findById(id,false);if(record){delete record.data._errorString}}else{record=this._findById(id,false);if(record){delete record.data._errorString}else{delete this._beforeImage[id]._errorString}}}};this._applyChanges=function(){var i;for(var id in this._beforeImage){if(this._beforeImage[id]===null){var jsrecord=this._findById(id,false);if(jsrecord===null&&this._jsdo._resource.idProperty!==undefined){if(this._tmpIndex[id]){var record=this._data[this._tmpIndex[id].index];jsrecord=record?new progress.data.JSRecord(this,record):null;delete this._tmpIndex[id]}}if(jsrecord!==null){if(jsrecord.data._rejected||jsrecord.data._errorString!==undefined){this._jsdo._undoCreate(this,id)}else{jsrecord.acceptRowChanges()}}else{var found=false;for(var i=0;i0){for(var i=0;iindex){i--}if(i!=index){this._tableRef._data.splice(index,1);this._tableRef._data.splice(i,0,record);this._tableRef._createIndex()}}}};this.assign=function(record){if(record===undefined)throw new Error(msg.getMsgText("jsdoMSG024","JSDO","assign() or update()"));this._saveBeforeImageUpdate();var fieldName,i,j,value,schema=this._tableRef.getSchema(),prefixElement,name;if(record){for(i=0;i0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){return this.record.data[name][element-1]}}return this.record.data[fieldName]}else return null},set:function(value){var name=fieldName,index,element,fieldInfo;if(this.record){this.record._saveBeforeImageUpdate();try{index=fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR);if(index>0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){this.record.data[name][element-1]=value;return}}this.record.data[fieldName]=value}finally{this.record._sortRecord(name)}}},enumerable:true,writeable:true})};Object.defineProperty(this,"hasSubmitOperation",{get:function(){return this._hasSubmitOperation},enumerable:true});Object.defineProperty(this,"hasCUDOperations",{get:function(){return this._hasCUDOperations},enumerable:true});Object.defineProperty(this,"defaultTableRef",{get:function(){return this._defaultTableRef},enumerable:true});this._buffers={};this._numBuffers=0;this._defaultTableRef=null;this._async=true;this._dataProperty=null;this._dataSetName=null;this.operations=[];this.useRelationships=true;this._session=null;this._needCompaction=false;this._hasCUDOperations=false;this._hasSubmitOperation=false;this._useSubmit=false;this.autoApplyChanges=true;this._lastErrors=[];this._localStorage=null;this._convertForServer;this._fillMergeMode;var autoFill=false;if(!arguments[0]){throw new Error("JSDO: Parameters are required in constructor.")}if(typeof arguments[0]=="string"){this.name=arguments[0]}else if(typeof arguments[0]=="object"){var args=arguments[0];for(var v in args){switch(v){case"autoFill":autoFill=args[v];break;case"events":this._events={};for(var eventName in args[v]){this._events[eventName.toLowerCase()]=args[v][eventName]}break;case"dataProperty":this._dataProperty=args[v];break;default:this[v]=args[v]}}}if(!this.name){throw new Error("JSDO: JSDO constructor is missing the value for 'name'")}if(this._events){if(typeof this._events!=="object"){throw new Error("JSDO: JSDO constructor event object is not defined as an object")}for(var prop in this._events){var evt=this._events[prop];if(!(evt instanceof Array)){throw new Error("JSDO: JSDO constructor event object for "+prop+" must be an array")}evt.forEach(function(el){if(typeof el!=="object"){throw new Error("JSDO: JSDO constuctor event object for "+prop+" is not defined as an object")}if(typeof el.fn!=="function"){throw new Error("JSDO: JSDO event listener for "+prop+" is not a function.")}if(el.scope&&typeof el.scope!=="object"){throw new Error("JSDO: JSDO event listener scope for "+prop+" is not an object.")}})}}if(this.name){this._resource=progress.data.ServicesManager.getResource(this.name);if(this._resource){if(!this.url)this.url=this._resource.url;if(!this._dataSetName&&this._resource._dataSetName){this._dataSetName=this._resource._dataSetName;if(this._resource.dataProperty){var buffer=this[this._resource.dataProperty]=new progress.data.JSTableRef(this,this._resource.dataProperty);this._buffers[this._resource.dataProperty]=buffer}else{for(var tableName in this._resource.fields){var buffer=this[tableName]=new progress.data.JSTableRef(this,tableName);this._buffers[tableName]=buffer}}}if(!this._dataProperty&&this._resource.dataProperty)this._dataProperty=this._resource.dataProperty;if(!this._dataSetName){var tableName=this._dataProperty?this._dataProperty:"";this._buffers[tableName]=new progress.data.JSTableRef(this,tableName);if(tableName)this[tableName]=this._buffers[tableName]}var properties,tableName;if(this._dataSetName&&this._resource.schema&&this._resource.schema.properties[this._dataSetName]){properties=this._resource.schema.properties[this._dataSetName].properties;if(Object.keys(properties).length===1){tableName=Object.keys(properties)[0];if(properties[tableName].idProperty){this._resource.idProperty=properties[tableName].idProperty}}}else if(this._resource.schema&&this._resource.schema.properties&&this._resource.schema.properties[tableName]&&this._resource.schema.properties[tableName].idProperty){this._resource.idProperty=this._resource.schema.properties[tableName].idProperty}for(var fnName in this._resource.fn){this[fnName]=this._resource.fn[fnName]["function"]}this._hasCUDOperations=this._resource.generic["create"]!==undefined||this._resource.generic["update"]!==undefined||this._resource.generic["delete"]!==undefined;this._hasSubmitOperation=this._resource.generic["submit"]!==undefined;if(!this._session){var myservice=progress.data.ServicesManager.getService(this._resource.service.name);this._session=myservice._session;this._session._pushJSDOs(this)}}else{throw new Error(msg.getMsgText("jsdoMSG004",this.name))}}else{this._buffers[""]=new progress.data.JSTableRef(this,"")}if(!this._session){throw new Error("JSDO: Unable to get user session for resource '"+this.name+"'")}for(var buf in this._buffers){this._buffers[buf]._parent=null;this._buffers[buf]._children=[];this._buffers[buf]._relationship=null;this._buffers[buf]._isNested=false;if(!this._defaultTableRef)this._defaultTableRef=this._buffers[buf];this._numBuffers++}if(this._numBuffers!=1)this._defaultTableRef=null;else{this.record=null}if(typeof Object.defineProperty=="function"){this._caseSensitive=false;Object.defineProperty(this,"caseSensitive",{get:function(){return this._caseSensitive},set:function(value){this._caseSensitive=value?true:false;for(var buf in this._buffers){this._buffers[buf].caseSensitive=this._caseSensitive}},enumerable:true,writeable:true});this._autoSort=true;Object.defineProperty(this,"autoSort",{get:function(){return this._autoSort},set:function(value){this._autoSort=value?true:false;for(var buf in this._buffers){this._buffers[buf].autoSort=this._autoSort}},enumerable:true,writeable:true})}this._properties={};if(typeof Object.defineProperty=="function"){Object.defineProperty(this,"this._properties",{get:function(){return this._properties},enumerable:false})}if(this._resource&&this._resource.fields){for(var buf in this._buffers){this._buffers[buf]._schema=this._resource.fields[buf];this._buffers[buf]._primaryKeys=this._resource.primaryKeys[buf];this._buffers[buf]._fields={};var fields=this._buffers[buf]._schema;for(var i=0;i1){for(var buf in this._buffers){var fields=[];var found=false;for(var i=0;i=0?index+1:"");element.value=value?value[index]:undefined;return element};this.isDataSet=function(){return this._dataSetName?true:false};this._invokeComplete=function(jsdo,success,request){if(request.async&&request.fnName){jsdo.trigger("afterInvoke",request.fnName,jsdo,success,request)}if(request.deferred){if(success){request.deferred.resolve(jsdo,success,request)}else{request.deferred.reject(jsdo,success,request)}}};this._invokeSuccess=function(){};this._invokeError=function(){};this._httpRequest=function(xhr,method,url,reqBody,request){function afterOpenRequest(){var input=null;if(reqBody){xhr.setRequestHeader("Content-Type","application/json; charset=utf-8");input=JSON.stringify(reqBody)}try{xhr.send(input)}catch(e){request.success=false;request.exception=e;xhr.jsdo._session._checkServiceResponse(xhr,request.success,request)}}if(!xhr){xhr=new XMLHttpRequest;xhr.onCompleteFn=this._invokeComplete;xhr.onSuccessFn=this._invokeSuccess;xhr.onErrorFn=this._invokeError;xhr.onreadystatechange=this.onReadyStateChangeGeneric;if(request.async&&request.fnName){this.trigger("beforeInvoke",request.fnName,this,request)}if(reqBody){if(this._resource&&this._resource.service){var useRequest=this._resource.service.useRequest;if(this._resource.service.settings&&this._resource.service.settings.useRequest!==undefined){useRequest=this._resource.service.settings.useRequest}if(useRequest){reqBody={request:reqBody}}}}}xhr.request=request;xhr.jsdo=this;request.jsdo=this;request.xhr=xhr;this._session._openRequest(xhr,method,url,request.async,afterOpenRequest);return request};this._getDataObject=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};var oldUseRelationships=this.useRelationships;try{this.useRelationships=false;for(var buf in this._buffers){dataObject[this._dataSetName][buf]=this._buffers[buf].getData()}}finally{this.useRelationships=oldUseRelationships}}else{if(this._dataProperty){dataObject[this._dataProperty]=this.getData()}else return this.getData()}return dataObject};this._getDataObjectAsNested=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};try{for(var buf in this._buffers){var bufObj=this._buffers[buf];if(bufObj._isNested)continue;this._nestChildren=false;if(bufObj._children.length>0){for(var i=0;i0){hasErrors=true}}if(hasErrors){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._allRecordsRejected=true;this._someRecordsRejected=false;hasCommittedRecords=false;for(i=0;i0&&!param.operations[0].success){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._convertForServer=true;this._buffers[buf]._convertForServer=true}}};this._convertRequestData=function(objParam){var buf,beforeData;if(this._convertForServer===false){return}for(buf in this._buffers){if(this._buffers[buf]._convertForServer){if(objParam[this._dataSetName]){if(objParam[this._dataSetName][buf]){this._convertTableData(this._buffers[buf],objParam[this._dataSetName][buf])}beforeData=objParam[this._dataSetName]["prods:before"];if(beforeData&&beforeData[buf]){this._convertTableData(this._buffers[buf],beforeData[buf])}}else if(objParam[buf]){this._convertTableData(this._buffers[buf],objParam[buf])}}}};this._convertTableData=function(tableRef,tableData){var i;for(i=0;i0){this._confirmOperationExists(progress.data.JSDO._OP_DELETE);checkedDelete=true}if(!checkedCreate&&tableRef._added.length>0){this._confirmOperationExists(progress.data.JSDO._OP_CREATE);checkedCreate=true}if(!checkedUpdate&&Object.keys(tableRef._changed).length>0){this._confirmOperationExists(progress.data.JSDO._OP_UPDATE);checkedUpdate=true}if(checkedDelete&&checkedCreate&&checkedUpdate){break}}};this._confirmOperationExists=function(operation){var operationStr=PROGRESS_JSDO_OP_STRING[operation];if(typeof this._resource.generic[operationStr]!=="function"){throw new Error(msg.getMsgText("jsdoMSG046",operationStr.toUpperCase()))}};this.invoke=function(name,object){var deferred,promise;try{var request=this[name](object);if(request.deferred){deferred=request.deferred;promise=request.deferred.promise()}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{if(!deferred){deferred=new progress.util.Deferred;promise=deferred.promise()}deferred.reject(this,false,{errorObject:error})}}return promise};this._syncTableRef=function(operation,tableRef,batch){var rowData,requestData,jsonObject,dataSetObject;if(tableRef._visited)return;tableRef._visited=true;if(!batch){batch={operations:[]}}else if(!batch.operations){batch.operations=[]}switch(operation){case progress.data.JSDO._OP_CREATE:for(var i=0;i0&&!dataSetJsonObject[tableRef._name])dataSetJsonObject[tableRef._name]=[];for(var i=0;i0||tableRef._added.length>0||hasUpdates){hasChanges=true;break}}return hasChanges};this._addDeletesToChangeSet=function(tableRef,dataSetJsonObject,request){for(var i=0;i=10){tmpIndex={};for(var i=0;ivalue2||value1===null)return false;else if(value11){for(var buf in this._buffers){if(this._buffers[buf]._isNested&&this._buffers[buf]._parent&&this._buffers[this._buffers[buf]._parent]){var srcData=this._buffers[this._buffers[buf]._parent]._data;var data=[];for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}var recordId=beforeTableJsonObject[0]["prods:clientId"];if(!recordId){throw new Error(msg.getMsgText("jsdoMSG035","_checkForDeleteError()"))}if(beforeTableJsonObject[0]["prods:hasErrors"]){var prods_id=beforeTableJsonObject[0]["prods:id"];var errorString=this._getErrorStringFromJsonObject(dataSetJsonObject,tableRef,prods_id);this._setErrorString(tableRef,recordId,errorString,true);hasError=true}}return hasError};this._mergeUpdateForSubmit=function(jsonObject,xhr){var errorString;if(!this._dataSetName){throw new Error(msg.getMsgText("jsdoMSG036","_mergeUpdateForSubmit()"))}var dataSetJsonObject=jsonObject[this._dataSetName];if(dataSetJsonObject[this._dataSetName])dataSetJsonObject=dataSetJsonObject[this._dataSetName];var beforeJsonObject=dataSetJsonObject["prods:before"];for(var buf in this._buffers){var tableRef=this._buffers[buf];var tableJsonObject=dataSetJsonObject[tableRef._name];if(tableJsonObject instanceof Array){for(var i=0;i1){request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}}if(beforeJsonObject){hasError=jsdo._checkForDeleteError(dataSetJsonObject,xhr)}if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._deleteError(jsdo,success,request)}}};this._deleteError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoDelete(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._createComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterCreate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterCreate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._createSuccess=function(jsdo,success,request){var xhr=request.xhr;var record=request.response;var hasError=jsdo._mergeUpdateForCUD(record,xhr);if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._createError(jsdo,success,request)}}};this._createError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoCreate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._updateComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterUpdate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterUpdate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._updateSuccess=function(jsdo,success,request){var xhr=request.xhr;var hasError=jsdo._mergeUpdateForCUD(request.response,xhr);if(hasError){request.success=false}if(jsdo.autoApplyChanges){if(!hasError){request.success=true;delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._updateError(jsdo,success,request)}}};this._updateError=function(jsdo,success,request){if(jsdo.autoApplyChanges){request.success=false;jsdo._undoUpdate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._saveChangesSuccess=function(jsdo,success,request){var records=request.response;jsdo._mergeUpdateForSubmit(records,request.xhr);jsdo._clearErrors();var changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(changes);if(jsdo.autoApplyChanges){jsdo._applyChanges()}};this._saveChangesError=function(jsdo,success,request){jsdo._setAllRecordsRejected(true);if(jsdo.autoApplyChanges){jsdo.rejectChanges()}jsdo._updateLastErrors(jsdo,null,null,request)};this._saveChangesSuccessTT=function(jsdo,success,request){var changes;jsdo._clearErrors();changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(false)};this._saveChangesComplete=function(jsdo,success,request){if(request.xhr.status>=200&&request.xhr.status<300&&(jsdo._lastErrors.length>0||jsdo._someRecordsRejected)){request.success=false}if(jsdo._useSubmit===true){jsdo._fireCUDTriggersForSubmit(request)}jsdo._undefWorkingRecord();jsdo._fireAfterSaveChanges(request.success,request)};this._fireAfterSaveChanges=function(success,request){this.trigger("afterSaveChanges",this,success,request);if(request.jsrecords){if(request.deferred){if(success){request.deferred.resolve(this,success,request)}else{request.deferred.reject(this,success,request)}}}else if(request.batch&&request.batch.deferred){if(success){request.batch.deferred.resolve(this,success,request)}else{request.batch.deferred.reject(this,success,request)}}var clearErrorString=this.autoApplyChanges;if(request.jsrecords){for(var idx=0;idx=400&&request.xhr.status<600){try{var responseObject=JSON.parse(request.xhr.responseText);if(responseObject instanceof Array){errorArray=responseObject}else if(responseObject instanceof Object){errorArray.push(responseObject)}for(i=0;i=400&&request.xhr.status<600)){errors.push({type:progress.data.JSDO.ERROR,error:"Error: HTTP Status "+request.xhr.status+" "+request.xhr.statusText,responseText:request.xhr.responseText})}}return errors};this._updateLastErrors=function(jsdo,batch,changes,request){var errors,errorText,responseObject,i,j,buf;if(batch){if(batch.operations===undefined)return;for(i=0;i=200&&request.xhr.status<300){jsdo._lastErrors.push({errorString:request.jsrecord.data._errorString});jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({type:progress.data.JSDO.DATA_ERROR,id:request.jsrecord.data._id,error:request.jsrecord.data._errorString})}else{errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}if(request.jsrecord&&(errors[j].type===progress.data.JSDO.APP_ERROR||errors[j].type===progress.data.JSDO.RETVAL)){errors[j].id=request.jsrecord.data._id;request.jsrecord._tableRef._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}}}}else if(changes instanceof Array){for(i=0;i=400&&request.xhr.status<600||request.xhr.status===0)){errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}for(buf in this._buffers){this._buffers[buf]._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}};this._checkSaveComplete=function(xhr){if(xhr.request){var jsdo=xhr.request.jsdo;var batch=xhr.request.batch;if(jsdo&&batch&&jsdo._async){if(jsdo._isBatchComplete(batch)){var success=jsdo._isBatchSuccess(batch);var request={batch:batch,success:success};jsdo._undefWorkingRecord();jsdo._lastErrors=[];if(!success&&batch.operations){jsdo._updateLastErrors(jsdo,batch,null)}this._setAllRecordsRejected(batch);jsdo._fireAfterSaveChanges(success,request)}}}};this._isBatchSuccess=function(batch){if(batch.operations){for(var i=0;i=200&&xhr.status<300||xhr.status===0&&xhr.responseText!==""){request.success=true;xhr.jsdo._session._saveClientContextId(xhr);if(typeof xhr.onSuccessFn=="function"){var operation;if(xhr.request.fnName!==undefined&&xhr.jsdo._resource.fn[xhr.request.fnName]!==undefined){operation=xhr.jsdo._resource.fn[xhr.request.fnName].operation}else operation=null;if(operation===undefined||operation!==null&&operation.mergeMode)xhr.jsdo._mergeInvoke(request.response,xhr);if(request.success)xhr.onSuccessFn(xhr.jsdo,request.success,request);else if(typeof xhr.onErrorFn=="function")xhr.onErrorFn(xhr.jsdo,request.success,request)}}else{request.success=false;if(xhr.status===0){request.exception=new Error(msg.getMsgText("jsdoMSG101"))}if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}}catch(e){request.success=false;request.exception=e;if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}xhr.jsdo._session._checkServiceResponse(xhr,request.success,request);if(typeof xhr.onCompleteFn=="function"){xhr.onCompleteFn(xhr.jsdo,request.success,request)}}};this.acceptChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].acceptChanges()}};this.rejectChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].rejectChanges()}};this.getChanges=function(){var result=[];for(var buf in this._buffers){var changes=this._buffers[this._buffers[buf]._name].getChanges();result=result.concat(changes)}return result};this.hasChanges=function(){for(var buf in this._buffers){if(this._buffers[this._buffers[buf]._name].hasChanges())return true}return false};this._applyChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name]._applyChanges()}};this.acceptRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.acceptRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","acceptRowChanges()"))};this.rejectRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.rejectRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","rejectRowChanges()"))};this.setProperties=function(propertiesObject){var prop;if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(typeof propertiesObject=="object"){this._properties={};for(prop in propertiesObject){if(propertiesObject.hasOwnProperty(prop)){if(typeof propertiesObject[prop]!=="function"){this._properties[prop]=propertiesObject[prop]}}}}else if(propertiesObject===undefined||propertiesObject===null){this._properties={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"Object","setProperties"))}};this.setProperty=function(propertyName,propertyValue){if(arguments.length<2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(arguments.length!==2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(typeof propertyName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"string","setProperty"))}if(propertyValue===undefined){delete this._properties[propertyName]}else{this._properties[propertyName]=propertyValue}};this.getProperties=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperties",0))}return this._properties};this.getProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}return this._properties[propertyName]};this.saveLocal=function saveLocal(arg1,arg2){var name;var dataMode;if(arguments.length>2){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"||arg1===null||arg1===undefined){name=arg1;dataMode=arg2}else{name=null;dataMode=arg1}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}if(typeof dataMode=="undefined"){dataMode=progress.data.JSDO.ALL_DATA}else{switch(dataMode){case progress.data.JSDO.ALL_DATA:case progress.data.JSDO.CHANGES_ONLY:break;default:throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var dataObj=this._prepareDataObjectForLocalStorage(dataMode);this._localStorage.saveToLocalStorage(name,dataObj)};this.readLocal=function readLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));this._restoreFromLocalStorage(object,progress.data.JSDO.MODE_EMPTY)}return object!==null};this.addLocalRecords=function addLocalRecords(arg1,arg2,arg3){var name;var addMode;var keyFields;if(arguments.length<1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"){name=arg1;addMode=arg2;keyFields=arg3}else{name="jsdo_"+this._resource.service.name+"_"+this._resource.name;addMode=arg1;keyFields=arg2}if(typeof name=="undefined"||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(addMode!=progress.data.JSDO.MODE_REPLACE){throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));try{this._restoreFromLocalStorage(object,addMode,keyFields)}catch(e){var text=e.message;throw new Error(text.replace(new RegExp("addRecords","g"),"addLocalRecords"))}}return object!==null};this._containsPrimaryKeys=function _containsPrimaryKeys(){for(var buf in this._buffers){if(this._buffers[buf]._primaryKeys===null)return false}return true};this._hasMatchingSchema=function _hasMatchingSchema(storageObject){var isValid=true;if(storageObject===null||Object.keys(storageObject).length===0)return true;if(this._dataSetName){if(storageObject[this._dataSetName]){for(var buf in this._buffers)if(storageObject[this._dataSetName][buf]===undefined){isValid=false;break}}else isValid=false}else if(this._dataProperty){storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._dataProperty]===undefined)isValid=false}else{storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._defaultTableRef._name]===undefined)isValid=false}return isValid};this.deleteLocal=function deleteLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}this._localStorage.clearLocalStorage(name)};this._prepareDataObjectForLocalStorage=function(option){var storageObject={};if(this._dataSetName){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet(this._dataSetName);break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet(this._dataSetName,true);break}}else if(this._dataProperty){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}else{switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}return storageObject};this._restoreFromLocalStorage=function(storageObject,addMode,keyFields){if(storageObject&&Object.keys(storageObject).length>0){if(this._dataSetName){for(var buf in this._buffers)this._restoreDataForTable(this._buffers[buf],storageObject,addMode,keyFields)}else this._restoreDataForTable(this._defaultTableRef,storageObject,addMode,keyFields)}else if(addMode===progress.data.JSDO.MODE_EMPTY)this._clearData()};this._restoreDataForTable=function(tableRef,jsonObject,addMode,keyFields){keyFields=keyFields!==undefined?keyFields:tableRef._primaryKeys;if(keyFields===undefined&&this._resource.idProperty){keyFields=[];keyFields[0]=this._resource.idProperty}if(this._dataSetName){var oldUseRelationships=this.useRelationships;this.useRelationships=false;try{tableRef.addRecords(jsonObject,addMode,keyFields)}finally{this.useRelationships=oldUseRelationships}}else{this._dataSetName="_localStorage";tableRef.addRecords(jsonObject,addMode,keyFields);this._dataSetName=null}};this.getMethodProperties=function(operation,name){var idx;if(this._resource._operations){if(this._resource._operations[operation]){return this._resource._operations[operation]}}else{this._resource._operations={}}for(var idx=0;idx1?[params.sort]:[]}sortFields="";for(index=0;index=1?params.filter:undefined}if(params.filter){if(typeof params.filter==="string"){doConversion=false}params.tableRef=tableName;if(doConversion&¶ms.tableRef===undefined){throw new Error(msg.getMsgText("jsdoMSG045","fill() or read()","params","tableRef"))}if(reqCapabilities["filter"].mapping==="ablFilter"){if(doConversion){ablFilter=progress.util._convertToABLWhereString(jsdo._buffers[params.tableRef],params.filter)}else{ablFilter=params.filter}}else if(reqCapabilities["filter"].mapping==="sqlQuery"){if(doConversion){sqlQuery=progress.util._convertToSQLQueryString(jsdo._buffers[params.tableRef],params.filter,true)}else{sqlQuery=params.filter}}}filter=JSON.stringify({ablFilter:ablFilter,sqlQuery:sqlQuery,orderBy:sortFields,skip:params.skip,top:params.top,id:params.id});params={filter:filter}}return params}});if(typeof progress.ui=="undefined")progress.ui={};progress.ui.UITableRef=function UITableRef(tableRef){this._tableRef=tableRef;this._listview=null;this._detailPage=null;this._listviewContent=undefined;this.addItem=function(format){var detailForm;if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._name));if(!this._listview)return;format=format?format:this._listview.format;detailForm=this._detailPage&&this._detailPage.name?this._detailPage.name:"";if(this._listviewContent===undefined){this.clearItems()}var text=this._listview.itemTemplate?this._listview.itemTemplate:progress.ui.UIHelper._itemTemplate;text=text.replace(new RegExp("{__format__}","g"),format);text=text.replace(new RegExp("{__id__}","g"),this._tableRef.record.data._id);text=text.replace(new RegExp("{__page__}","g"),detailForm);for(var field in this._tableRef.record.data){var value=this._tableRef.record.data[field];text=text.replace(new RegExp("{"+field+"}","g"),value!==undefined&&value!==null?value:"")}this._listviewContent+=text};this.clearItems=function(){if(this._listview){this._listviewContent="";var listviewElement=document.getElementById(this._listview.name);if(listviewElement){listviewElement.innerHTML=""}}};this._getFormFieldValue=function(fieldName,detailPageName){var value=null,field;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)value=field.val()}else{field=document.getElementById(fieldName);if(field){value=field.value}}return value};this._setFormField=function(fieldName,value,detailPageName){var field=null;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)field.val(value)}else{field=document.getElementById(fieldName);if(field){field.value=value}}};this.assign=function(detailPageName){if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._tableRef._name));if(arguments.length!==0&&typeof detailPageName!="string")throw new Error(msg.getMsgText("jsdoMSG024","UIHelper","assign()"));this._tableRef.record.assign(null);var fieldName;var schema=this._tableRef.getSchema();for(var i=0;i0){for(var i=0;i0&&fieldName.charAt(0)=="_")continue;if(fields&&fields[fieldName]===undefined)continue;var fieldLabel=this._tableRef._schema[i].title?this._tableRef._schema[i].title:this._tableRef._schema[i].name;var text=this._detailPage&&this._detailPage.fieldTemplate?this._detailPage.fieldTemplate:progress.ui.UIHelper._fieldTemplate;text=text.replace(new RegExp("{__label__}","g"),fieldLabel);text=text.replace(new RegExp("{__name__}","g"),this._tableRef._schema[i].name);htmltext+=text}htmltext+="";fields=null;return htmltext};this.getListViewRecord=function(htmlIElement){var id=htmlIElement.getAttribute("data-id");return this._tableRef.findById(id)};this.getFormRecord=function(detailPageName){var id=this._getFormFieldValue("_id",detailPageName);return this._tableRef.findById(id)};this._getIdOfElement=function(name){if(typeof $=="function"){var element=$("#"+name);if(!element||element.length===0){element=$('[dsid="'+name+'"]');if(element&&element.length==1){var id=element.attr("id");if(id)return id}}}return name};this.setDetailPage=function setDetailPage(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));this._detailPage=obj;this._detailPage.name=this._getIdOfElement(this._detailPage.name)};this.setListView=function setListView(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));if(obj.format&&typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"format"));this._listview=obj;this._listview.name=this._getIdOfElement(this._listview.name);if(!this._listview.format){if(typeof $=="function"){for(var i=0;i{__format__}';progress.ui.UIHelper._defaultFieldTemplate='
    '+''+'
    ';progress.ui.UIHelper._itemTemplate=progress.ui.UIHelper._defaultItemTemplate;progress.ui.UIHelper._fieldTemplate=progress.ui.UIHelper._defaultFieldTemplate;progress.ui.UIHelper.setItemTemplate=function(template){progress.ui.UIHelper._itemTemplate=template?template:progress.ui.UIHelper._defaultItemTemplate};progress.ui.UIHelper.setFieldTemplate=function(template){progress.ui.UIHelper._fieldTemplate=template?template:progress.ui.UIHelper._defaultFieldTemplate}})();(function(){if(progress===undefined){progress={}}if(progress.data===undefined){progress.data={}}progress.data.ServicesManager={};progress.data.ServicesManager._services=[];progress.data.ServicesManager._resources=[];progress.data.ServicesManager._data=[];progress.data.ServicesManager._sessions=[];progress.data.ServicesManager._jsdosessions=[];progress.data.ServicesManager.addResource=function(id,resource){if(progress.data.ServicesManager._resources[id]===undefined){progress.data.ServicesManager._resources[id]=resource}else{throw new Error("A resource named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getResource=function(id){return progress.data.ServicesManager._resources[id]};progress.data.ServicesManager.addService=function(id,service){if(progress.data.ServicesManager._services[id]===undefined){progress.data.ServicesManager._services[id]=service}else{throw new Error("A service named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getService=function(id){return progress.data.ServicesManager._services[id]};progress.data.ServicesManager.addSession=function(catalogURI,session){if(progress.data.ServicesManager._sessions[catalogURI]===undefined){progress.data.ServicesManager._sessions[catalogURI]=session}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.addJSDOSession=function(catalogURI,jsdosession){if(progress.data.ServicesManager._jsdosessions[catalogURI]===undefined){progress.data.ServicesManager._jsdosessions[catalogURI]=jsdosession}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.getSession=function(catalogURI){try{return progress.data.ServicesManager._sessions[catalogURI]}catch(e){return null}};progress.data.ServicesManager.cleanSession=function(session){var servicesKey,resourcesKey,sessionsKey,service,services=progress.data.ServicesManager._services,resources=progress.data.ServicesManager._resources,sessions=progress.data.ServicesManager._sessions,jsdosessions=progress.data.ServicesManager._jsdosessions;for(servicesKey in services){service=null;if(services[servicesKey]._session===session){service=services[servicesKey];delete services[servicesKey]}if(!service){continue}for(resourcesKey in resources){if(resources[resourcesKey].service===service){delete resources[resourcesKey]}}}for(sessionsKey in sessions){if(sessions[sessionsKey]===session){delete sessions[sessionsKey];if(jsdosessions[sessionsKey]){delete jsdosessions[sessionsKey]}}}};function extractParamsFromURL(url){var urlParams=[],paramName=null;if(typeof url==="string"){url.split("").forEach(function(c){if(c==="{"){paramName=""}else if(c==="}"){if(paramName){urlParams.push(paramName)}paramName=null}else if(paramName!==null){paramName+=c}})}return urlParams}progress.data.ServicesManager.addCatalog=function(services,session){var name,value;if(!services){throw new Error("Cannot find 'services' property in catalog file.")}if(services instanceof Array){services.forEach(function(service){if(progress.data.ServicesManager.getService(service.name)!==undefined){throw new Error("A service named '"+service.name+"' was already loaded.")}if(service.resources instanceof Array){service.resources.forEach(function(resource){if(progress.data.ServicesManager.getResource(resource.name)!==undefined){throw new Error("A resource named '"+resource.name+"' was already loaded.")}})}else{throw new Error("Missing 'resources' array in catalog.")}});for(var j=0;j1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","setContext",1))}if(typeof context==="object"){contextObject={};for(prop in context){if(context.hasOwnProperty(prop)){if(typeof context[prop]!=="function"){contextObject[prop]=context[prop]}}}}else if(context===undefined||context===null){contextObject={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","Session",1,"Object","setContextProperty"))}contextString=null};this.getContext=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContext",0))}return contextObject};this.getContextProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}return contextObject[propertyName]}};progress.data.Session=function Session(options){var defPropSupported=false;if(typeof Object.defineProperty==="function"){defPropSupported=true}var that=this,jsdosession,isUserAgentiOS=false,isFirefox=false,isEdge=false,isIE=false,canPassCredentialsToOpenWithCORS=false,defaultiOSBasicAuthTimeout=4e3,deviceIsOnline=true,restApplicationIsOnline=false,oepingAvailable=false,defaultPartialPingURI="/rest/_oeping",partialPingURI=defaultPartialPingURI,_storageKey,_authProvider=null,customCredentials=false,storedAuthModel,storedURI,newURI,stateWasReadFromStorage=false;if(!options||options._silent!==true){console.warn("Session: As of JSDO 4.4, the Session object has been deprecated. "+"Please use the JSDOSession object instead.")}if(typeof navigator!=="undefined"){if(typeof navigator.userAgent!=="undefined"){isUserAgentiOS=navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i);isFirefox=navigator.userAgent.toLowerCase().indexOf("firefox")>-1;isEdge=navigator.userAgent.indexOf("Edge/")>-1;isIE=navigator.userAgent.indexOf("Trident/")>-1||navigator.userAgent.indexOf("MSIE 10")>-1}}canPassCredentialsToOpenWithCORS=!(isFirefox||isEdge||isIE);function canPassCredentialsToOpen(){return canPassCredentialsToOpenWithCORS}this._onlineHandler=function(){setDeviceIsOnline(true);that.trigger("online",that,null)};this._offlineHandler=function(){setDeviceIsOnline(false);that.trigger("offline",that,progress.data.Session.DEVICE_OFFLINE,null)};if(typeof window!=="undefined"&&window.addEventListener){window.addEventListener("online",this._onlineHandler,false);window.addEventListener("offline",this._offlineHandler,false)}var _catalogURIs=[];var _services=[];var _jsdos=[];this.onOpenRequest=null;var _password=null;if(defPropSupported){var _userName=null;Object.defineProperty(this,"userName",{get:function(){return _userName},enumerable:true});var _loginTarget="/static/home.html";Object.defineProperty(this,"loginTarget",{get:function(){return _loginTarget},enumerable:true});var _serviceURI=null;Object.defineProperty(this,"serviceURI",{get:function(){return _serviceURI},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _catalogURIs},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _services},enumerable:true});var _loginResult=null;Object.defineProperty(this,"loginResult",{get:function(){return _loginResult},enumerable:true});var _loginHttpStatus=null;Object.defineProperty(this,"loginHttpStatus",{get:function(){return _loginHttpStatus},enumerable:true});var _clientContextId=null;Object.defineProperty(this,"clientContextId",{get:function(){return _clientContextId},enumerable:true});var _authenticationModel=progress.data.Session.AUTH_TYPE_ANON;Object.defineProperty(this,"authenticationModel",{get:function(){return _authenticationModel},set:function(newval){if(newval){newval=newval.toLowerCase()}switch(newval){case progress.data.Session.AUTH_TYPE_FORM:case progress.data.Session.AUTH_TYPE_BASIC:case progress.data.Session.AUTH_TYPE_ANON:case progress.data.Session.AUTH_TYPE_SSO:case null:_authenticationModel=newval;storeSessionInfo("authenticationModel",newval);break;default:throw new Error("Error setting Session.authenticationModel. '"+newval+"' is an invalid value.")}},enumerable:true});var _lastSessionXHR=null;Object.defineProperty(this,"lastSessionXHR",{get:function(){return _lastSessionXHR},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return this.loginResult===progress.data.Session.LOGIN_SUCCESS&&restApplicationIsOnline&&deviceIsOnline},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _jsdos},enumerable:true});var _pingInterval=0;var _timeoutID=null;Object.defineProperty(this,"pingInterval",{get:function(){return _pingInterval},set:function(newval){if(typeof newval==="number"&&newval>=0){_pingInterval=newval;storeSessionInfo("pingInterval",newval);if(newval>0){if(this.loginResult===progress.data.Session.LOGIN_SUCCESS){_timeoutID=setTimeout(this._autoping,newval)}}else if(newval===0){clearTimeout(_timeoutID);_pingInterval=0}}else{throw new Error("Error setting Session.pingInterval. '"+newval+"' is an invalid value.")}},enumerable:true});var _contextProperties=new progress.data.ContextProperties;Object.defineProperty(this,"_contextProperties",{get:function(){return _contextProperties},enumerable:false});var isInvalidated=false;Object.defineProperty(this,"_isInvalidated",{get:function(){return isInvalidated},enumerable:false});Object.defineProperty(this,"_authProvider",{get:function(){return _authProvider},set:function(newval){if(_authProvider){throw new Error("Internal Error setting Session._authProvider. '"+"The property has already been set.")}setAuthProvider(newval)},enumerable:false})}else{this.userName=null;this.loginTarget="/static/home.html";this.serviceURI=null;this.catalogURIs=[];this.services=[];this.loginResult=null;this.loginHttpStatus=null;this.clientContextId=null;this.authenticationModel=progress.data.Session.AUTH_TYPE_ANON;this.lastSessionXHR=null}function storeSessionInfo(infoName,value){var key;if(that.loginResult===progress.data.Session.LOGIN_SUCCESS&&typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}if(typeof value!=="undefined"){sessionStorage.setItem(key,JSON.stringify(value))}}}function retrieveSessionInfo(infoName){var key,jsonStr,value=null;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}jsonStr=sessionStorage.getItem(key);if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}}function clearSessionInfo(infoName){var key;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName;sessionStorage.removeItem(key)}}}function storeAllSessionInfo(){if(_storageKey){storeSessionInfo("loginResult",that.loginResult);storeSessionInfo("userName",that.userName);storeSessionInfo("serviceURI",that.serviceURI);storeSessionInfo("loginHttpStatus",that.loginHttpStatus);storeSessionInfo("authenticationModel",that.authenticationModel);storeSessionInfo("pingInterval",that.pingInterval);storeSessionInfo("oepingAvailable",oepingAvailable);storeSessionInfo("partialPingURI",partialPingURI);storeSessionInfo("clientContextId",that.clientContextId);storeSessionInfo("deviceIsOnline",deviceIsOnline);storeSessionInfo("restApplicationIsOnline",restApplicationIsOnline);if(that._authProvider){storeSessionInfo("_authProvider.init",{uri:that._authProvider.uri,authenticationModel:that._authProvider.authenticationModel})}storeSessionInfo(_storageKey,true)}}function clearAllSessionInfo(){if(_storageKey){if(retrieveSessionInfo(_storageKey)){clearSessionInfo("loginResult");clearSessionInfo("userName");clearSessionInfo("serviceURI");clearSessionInfo("loginHttpStatus");clearSessionInfo("clientContextId");clearSessionInfo("deviceIsOnline");clearSessionInfo("restApplicationIsOnline");clearSessionInfo("authenticationModel");clearSessionInfo("pingInterval");clearSessionInfo("oepingAvailable");clearSessionInfo("partialPingURI");clearSessionInfo("_authProvider.init");clearSessionInfo(_storageKey)}}}function setSessionInfoFromStorage(key){var authproviderInitObject;if(retrieveSessionInfo(key)){setLoginResult(retrieveSessionInfo("loginResult"),this);setUserName(retrieveSessionInfo("userName"),this);setServiceURI(retrieveSessionInfo("serviceURI"),this);setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"),this);setClientContextID(retrieveSessionInfo("clientContextId"),this);setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline"));setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline"));that.authenticationModel=retrieveSessionInfo("authenticationModel");that.pingInterval=retrieveSessionInfo("pingInterval");setOepingAvailable(retrieveSessionInfo("oepingAvailable"));setPartialPingURI(retrieveSessionInfo("partialPingURI"));if(!that._authProvider){authproviderInitObject=retrieveSessionInfo("_authProvider.init");if(authproviderInitObject){setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject))}}}}function setUserName(newname,sessionObject){if(defPropSupported){_userName=newname}else{sessionObject.userName=newname}storeSessionInfo("userName",newname)}function setLoginTarget(target,sessionObject){if(defPropSupported){_loginTarget=target}else{sessionObject.loginTarget=target}}function setServiceURI(url,sessionObject){if(defPropSupported){_serviceURI=url}else{sessionObject.serviceURI=url}storeSessionInfo("serviceURI",url)}function pushCatalogURIs(url,sessionObject){if(defPropSupported){_catalogURIs.push(url)}else{sessionObject.catalogURIs.push(url)}}function pushService(serviceObject,sessionObject){if(defPropSupported){_services.push(serviceObject)}else{sessionObject.services.push(serviceObject)}}function findService(serviceName){_services.forEach(function(service){if(service.name===serviceName){return service}});return null}function setLoginResult(result,sessionObject){if(defPropSupported){_loginResult=result}else{sessionObject.loginResult=result}if(result===progress.data.Session.LOGIN_SUCCESS){storeSessionInfo("loginResult",result)}else{clearAllSessionInfo()}}function setLoginHttpStatus(status,sessionObject){if(defPropSupported){_loginHttpStatus=status}else{sessionObject.loginHttpStatus=status}storeSessionInfo("loginHttpStatus",status)}function setClientContextIDfromXHR(xhr,sessionObject){if(xhr){setClientContextID(getResponseHeaderNoError(xhr,"X-CLIENT-CONTEXT-ID"),sessionObject)}}function setClientContextID(ccid,sessionObject){if(defPropSupported){_clientContextId=ccid}else{sessionObject.clientContextId=ccid}storeSessionInfo("clientContextId",ccid)}function setLastSessionXHR(xhr,sessionObject){if(defPropSupported){_lastSessionXHR=xhr}else{sessionObject.lastSessionXHR=xhr}}function setDeviceIsOnline(value){deviceIsOnline=value;storeSessionInfo("deviceIsOnline",value)}function setAuthProvider(value){_authProvider=value?value:null}function setRestApplicationIsOnline(value){restApplicationIsOnline=value;storeSessionInfo("restApplicationIsOnline",value)}function setOepingAvailable(value){oepingAvailable=value;storeSessionInfo("oepingAvailable",value)}function setPartialPingURI(value){partialPingURI=value;storeSessionInfo("partialPingURI",value)}function getResponseHeaderNoError(xhr,headerName){var allHeaders=xhr._pdsResponseHeaders,regExp;if(allHeaders===undefined){allHeaders=xhr.getAllResponseHeaders();if(allHeaders){xhr._pdsResponseHeaders=allHeaders}else{xhr._pdsResponseHeaders=null}}if(allHeaders){regExp=new RegExp("^"+headerName+":","mi");if(allHeaders.match(regExp)){return xhr.getResponseHeader(headerName)}}return null}this._pushJSDOs=function(jsdo){_jsdos.push(jsdo)};this._openRequest=function(xhr,verb,url,async,callback){var urlPlusCCID,that=this;function afterOpenAndAuthorize(arg){if(arg instanceof Error){throw arg}else{if(that.clientContextId&&that.clientContextId!=="0"){xhr.setRequestHeader("X-CLIENT-CONTEXT-ID",that.clientContextId)}setRequestHeaderFromContextProps(that,xhr);if(typeof that.onOpenRequest==="function"){var params={xhr:xhr,verb:verb,uri:urlPlusCCID,async:async,formPreTest:false,session:that};that.onOpenRequest(params)}if(callback){callback()}}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to make server request when there is no active session.")}urlPlusCCID=this._prependAppURL(url);urlPlusCCID=this._addCCIDtoURL(urlPlusCCID);if(progress.data.Session._useTimeStamp){urlPlusCCID=progress.data.Session._addTimeStampToURL(urlPlusCCID)}if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,verb,urlPlusCCID,async,afterOpenAndAuthorize)}else{this._setXHRCredentials(xhr,verb,urlPlusCCID,this.userName,_password,async);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json")}afterOpenAndAuthorize(xhr)}};this.pingTestCallback=function(cbArgs){var foundOeping=cbArgs.pingResult?true:false;setOepingAvailable(foundOeping)};this._onReadyStateChangeGeneric=function(){var xhr=this;var result;var errorObject;clearTimeout(xhr._requestTimeout);if(xhr.readyState===4){result=null;errorObject=null;if(typeof xhr.onResponseFn==="function"){try{result=xhr.onResponseFn(xhr)}catch(e){errorObject=e}}if(typeof xhr.onResponseProcessedFn==="function"){if(!result){result=progress.data.Session.GENERAL_FAILURE}xhr.onResponseProcessedFn(xhr.pdsession,result,errorObject,xhr)}}};this._disconnect=function(deferred){this._processDisconnectResult(null,deferred)};this._processDisconnectResult=function(xhr,deferred){this._reinitializeAfterLogout(this,progress.data.Session.SUCCESS);this._disconnectComplete(this,progress.data.Session.SUCCESS,null,null,deferred)};this._disconnectComplete=function(pdsession,result,errObj,xhr,deferred){pdsession.trigger("afterDisconnect",pdsession,result,errObj,xhr,deferred)};var pwSave=null;var unameSave=null;this.login=function(serviceURI,loginUserName,loginPassword,loginTarget){var uname,pw,isAsync=false,args=[],deferred,iOSBasicAuthTimeout,uriForRequest;pwSave=null;unameSave=null;if(!defPropSupported){this.authenticationModel=this.authenticationModel.toLowerCase()}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","login()"))}if(this.loginResult===progress.data.Session.LOGIN_SUCCESS||this._authProvider){throw new Error("Attempted to call login() on a Session object that is already logged in.")}if(arguments.length>0){if(arguments[0]&&typeof arguments[0]==="object"){args[0]=arguments[0].serviceURI;args[1]=arguments[0].userName;args[2]=arguments[0].password;args[3]=arguments[0].loginTarget;args[4]=arguments[0].async;deferred=arguments[0].deferred;iOSBasicAuthTimeout=arguments[0].iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","login","The iOSBasicAuthTimeout argument was invalid."))}}else{args=arguments}}if(args.length>0){if(args[0]){var restURLtemp=args[0];if(restURLtemp[restURLtemp.length-1]==="/"){restURLtemp=restURLtemp.substring(0,restURLtemp.length-1)}setServiceURI(restURLtemp,this)}else if(!this.serviceURI){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}if(args[1]){uname=args[1]}if(args[2]){pw=args[2]}if(args[3]){setLoginTarget(args[3],this)}if(args[4]){if(typeof args[4]==="boolean"){isAsync=args[4]}else{throw new Error("Session.login() was passed an async setting that is not a boolean.")}}}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}unameSave=uname;pwSave=pw;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON||this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){uname=null;pw=null}var xhr=new XMLHttpRequest;xhr.pdsession=this;try{uriForRequest=this.serviceURI+this.loginTarget;if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(uriForRequest)}this._setXHRCredentials(xhr,"GET",uriForRequest,uname,pw,isAsync);progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(this,xhr);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr._isAsync=isAsync;if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){xhr.onResponseFn=this._afterFormPretestLogin}else{xhr.onResponseFn=this._processLoginResult;xhr.onResponseProcessedFn=this._loginComplete}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout>0){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred}if(typeof this.onOpenRequest==="function"){var isFormPreTest=false;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){isFormPreTest=true}setLastSessionXHR(xhr,this);var params={xhr:xhr,verb:"GET",uri:this.serviceURI+this.loginTarget,async:false,formPreTest:isFormPreTest,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send(null)}catch(e){clearTimeout(xhr._requestTimeout);setLoginHttpStatus(xhr.status,this);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);unameSave=null;pwSave=null;throw e}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{setLoginHttpStatus(xhr.status,this);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){return this._afterFormPretestLogin(xhr)}else{return this._processLoginResult(xhr)}}};this._afterFormPretestLogin=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);var formLoginParams={xhr:xhr,pw:pwSave,uname:unameSave,theSession:pdsession};try{return doFormLogin(formLoginParams)}catch(e){pwSave=null;unameSave=null;throw e}};function doFormLogin(args){var xhr=args.xhr;var theSession=args.theSession;var oldXHR;var contentType=null;var needAuth=false;var params={session:theSession,xhr:xhr,statusFromjson:null};contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson||params.statusFromjson>=400&¶ms.statusFromjson<500){needAuth=true}else{setLoginHttpStatus(params.statusFromjson,theSession)}}else{if(theSession.loginHttpStatus===200){if(_gotLoginForm(xhr)){needAuth=true}}}if(needAuth){oldXHR=xhr;xhr=new XMLHttpRequest;args.xhr=xhr;params.xhr=xhr;xhr.pdsession=oldXHR.pdsession;xhr._isAsync=oldXHR._isAsync;xhr._deferred=oldXHR._deferred;xhr._jsdosession=oldXHR._jsdosession;xhr.open("POST",theSession.serviceURI+"/static/auth/j_spring_security_check",xhr._isAsync);xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.setRequestHeader("Cache-Control","max-age=0");setRequestHeaderFromContextProps(theSession,xhr);_addWithCredentialsAndAccept(xhr,"application/json");try{if(typeof theSession.onOpenRequest==="function"){var cbparams={xhr:xhr,verb:"POST",uri:theSession.serviceURI+"/static/auth/j_spring_security_check",async:xhr._isAsync,formPreTest:false,session:theSession};theSession.onOpenRequest(cbparams);xhr=cbparams.xhr}if(xhr._isAsync){xhr.onreadystatechange=theSession._onReadyStateChangeGeneric;xhr.onResponseFn=theSession._afterFormLogin;xhr.onResponseProcessedFn=theSession._loginComplete}xhr.send("j_username="+encodeURIComponent(args.uname)+"&j_password="+encodeURIComponent(args.pw)+"&submit=Submit")}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,theSession);setLoginHttpStatus(xhr.status,theSession);unameSave=null;pwSave=null;throw e}}if(xhr._isAsync&&!needAuth){xhr.onResponseProcessedFn=theSession._loginComplete;return theSession._afterFormLogin(xhr)}if(!xhr._isAsync){return theSession._afterFormLogin(xhr)}}this._afterFormLogin=function(xhr){var theSession=xhr.pdsession;var params={session:theSession,xhr:xhr,statusFromjson:null};var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson){throw new Error("Internal OpenEdge Mobile client error handling login response. HTTP status: "+xhr.status+".")}setLoginHttpStatus(params.statusFromjson,theSession)}else{if(xhr.status===200){if(_gotLoginFailure(xhr)||_gotLoginForm(xhr)){setLoginHttpStatus(401,theSession)}else{setLoginHttpStatus(xhr.status,theSession)}}}return theSession._processLoginResult(xhr)};this._processLoginResult=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);if(pdsession.loginHttpStatus===200){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);setUserName(unameSave,pdsession);_password=pwSave;pdsession._saveClientContextId(xhr);storeAllSessionInfo();var pingTestArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:pdsession._pingtestOnReadyStateChange};pingTestArgs.pingURI=pdsession._makePingURI();pdsession._sendPing(pingTestArgs)}else{if(pdsession.loginHttpStatus===401){setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE,pdsession)}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);unameSave=null;pwSave=null;if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","login"))}return pdsession.loginResult};this._loginComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterLogin",pdsession,result,errObj,xhr)};this.logout=function(args){var isAsync=false,errorObject=null,xhr,deferred,params;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","logout()"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&this.authenticationModel){throw new Error("Attempted to call logout when there is no active session.")}if(typeof args==="object"){isAsync=args.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","logout","The async argument was invalid."))}deferred=args.deferred}xhr=new XMLHttpRequest;xhr.pdsession=this;try{xhr._jsdosession=jsdosession;xhr._deferred=deferred;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM||this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;xhr.onResponseFn=this._processLogoutResult;xhr.onResponseProcessedFn=this._logoutComplete}xhr.open("GET",this.serviceURI+"/static/auth/j_spring_security_logout",isAsync);try{xhr.withCredentials=true}catch(e){}xhr.setRequestHeader("Accept","application/json");setRequestHeaderFromContextProps(this,xhr);if(typeof this.onOpenRequest==="function"){setLastSessionXHR(xhr,this);params={xhr:xhr,verb:"GET",uri:this.serviceURI+"/static/auth/j_spring_security_logout",async:false,formPreTest:false,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send()}else{xhr._anonymousLogoutOK=true}}catch(e){this._reinitializeAfterLogout(this,false);throw e}if(!isAsync){try{this._processLogoutResult(xhr)}catch(e){throw e}}if(isAsync&&this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){try{this._processLogoutResult(xhr)}catch(e){errorObject=e}this._logoutComplete(this,null,errorObject,xhr)}};this.invalidate=function(){isInvalidated=true;cleanServicesManager()};this._logoutComplete=function(pdsession,result,errorObject,xhr){pdsession.trigger("afterLogout",pdsession,errorObject,xhr)};this._processLogoutResult=function(xhr){var logoutSucceeded;var pdsession=xhr.pdsession;var basicStatusOK=false;if(xhr._anonymousLogoutOK){logoutSucceeded=true}else if(xhr.status!==200){if(pdsession.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(xhr.status===404){logoutSucceeded=true}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=true}updateContextPropsFromResponse(pdsession,xhr);pdsession._reinitializeAfterLogout(pdsession,logoutSucceeded)};this._reinitializeAfterLogout=function(pdsession,success){setLoginResult(null,pdsession);setLoginHttpStatus(null,pdsession);setClientContextID(null,pdsession);setUserName(null,pdsession);setAuthProvider(null);_password=null;if(success){setRestApplicationIsOnline(false);setOepingAvailable(false);setPartialPingURI(defaultPartialPingURI);setLastSessionXHR(null,pdsession);clearTimeout(_timeoutID)}};this.addCatalog=function(arg1,arg2,arg3,arg4){var catalogURI,catalogUserName,catalogPassword,isAsync=false,xhr,deferred,iOSBasicAuthTimeout,catalogIndex,authProvider,that=this;function addCatalogAfterOpen(){progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(isAsync){xhr.onreadystatechange=that._onReadyStateChangeGeneric;xhr.onResponseFn=that._processAddCatalogResult;xhr.onResponseProcessedFn=that._addCatalogComplete;if(that.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex}try{if(typeof that.onOpenRequest==="function"){setLastSessionXHR(xhr,that);var params={xhr:xhr,verb:"GET",uri:catalogURI,async:false,formPreTest:false,session:that};that.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,that);xhr.send(null)}catch(e){throw new Error("Error retrieving catalog '"+catalogURI+"'.\n"+e.message)}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{return that._processAddCatalogResult(xhr)}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}customCredentials=true;if(arguments.length>0){if(typeof arg1==="object"){if(!arguments[0].offlineAddCatalog){if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to call addCatalog when there is no active session.")}}catalogURI=arg1.catalogURI;if(!catalogURI||typeof catalogURI!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogURI argument was missing or invalid."))}catalogUserName=arg1.userName;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogUserName argument was invalid."))}catalogPassword=arg1.password;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogPassword argument was invalid."))}isAsync=arg1.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The async argument was invalid."))}iOSBasicAuthTimeout=arg1.iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The iOSBasicAuthTimeout argument was invalid."))}authProvider=arg1.authProvider;deferred=arg1.deferred;catalogIndex=arg1.catalogIndex}else{catalogURI=arg1;if(typeof catalogURI!=="string"){throw new Error("First argument to Session.addCatalog must be the URL of the catalog.")}catalogUserName=arg2;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error("Second argument to Session.addCatalog must be a user name string.")}catalogPassword=arg3;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error("Third argument to Session.addCatalog must be a password string.")}}}else{throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog.")}if(!authProvider){authProvider=this._authProvider;customCredentials=false}if(!catalogUserName){catalogUserName=this.userName}if(!catalogPassword){catalogPassword=_password}xhr=new XMLHttpRequest;xhr.pdsession=this;xhr._catalogURI=catalogURI;if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){if(isAsync){xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex;setTimeout(this._addCatalogComplete,10,this,progress.data.Session.CATALOG_ALREADY_LOADED,null,xhr);return progress.data.Session.ASYNC_PENDING}return progress.data.Session.CATALOG_ALREADY_LOADED}if(authProvider){authProvider._openRequestAndAuthorize(xhr,"GET",catalogURI,isAsync,addCatalogAfterOpen);return progress.data.Session.ASYNC_PENDING}else{this._setXHRCredentials(xhr,"GET",catalogURI,catalogUserName,catalogPassword,isAsync);return addCatalogAfterOpen()}};this._processAddCatalogResult=function(xhr){var _catalogHttpStatus=xhr.status;var theSession=xhr.pdsession;var servicedata;var catalogURI=xhr._catalogURI,serviceURL,theJSDOSession=jsdosession;if(!customCredentials){toggleOnlineState(xhr)}if((_catalogHttpStatus===200||_catalogHttpStatus===0)&&xhr.responseText){servicedata=theSession._parseCatalog(xhr);try{progress.data.ServicesManager.addCatalog(servicedata,theSession)}catch(e){if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){return progress.data.Session.CATALOG_ALREADY_LOADED}throw new Error("Error processing catalog '"+catalogURI+"'. \n"+e.message)}servicedata.forEach(function(service){serviceURL=theSession._prependAppURL(service.address);pushService(new progress.data.MobileServiceObject({name:service.name,uri:serviceURL}),theSession);if(service.settings&&service.settings.useXClientProps&&!theSession.xClientProps){console.warn("Catalog warning: Service settings property 'useXClientProps' "+"is true but 'xClientProps' property has not been set.")}});pushCatalogURIs(catalogURI,theSession);progress.data.ServicesManager.addSession(catalogURI,theSession);if(theJSDOSession){progress.data.ServicesManager.addJSDOSession(catalogURI,theJSDOSession)}}else if(_catalogHttpStatus===401){return progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","addCatalog"))}else{throw new Error("Error retrieving catalog '"+catalogURI+"'. Http status: "+_catalogHttpStatus+".")}return progress.data.Session.SUCCESS};this._addCatalogComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterAddCatalog",pdsession,result,errObj,xhr)};this.ping=function(args){var pingResult=false,pingArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:this._onReadyStateChangePing,offlineReason:null};if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(!this._authProvider&&this.loginResult!==progress.data.Session.LOGIN_SUCCESS){throw new Error("Attempted to call ping when not logged in.")}if(args){if(args.async!==undefined){pingArgs.async=args.async}if(args.doNotFireEvent!==undefined){pingArgs.fireEventIfOfflineChange=!args.doNotFireEvent}if(args.onCompleteFn&&typeof args.onCompleteFn==="function"){pingArgs.onCompleteFn=args.onCompleteFn}pingArgs.deferred=args.deferred;pingArgs.jsdosession=args.jsdosession}pingArgs.pingURI=that._makePingURI();that._sendPing(pingArgs);if(!pingArgs.async){if(pingArgs.xhr){pingResult=that._processPingResult(pingArgs);if(args.offlineReason!==undefined){args.offlineReason=pingArgs.offlineReason}}else{pingResult=false}if(args.xhr!==undefined){args.xhr=pingArgs.xhr}}return pingResult};this._isOnlineStateChange=function(isOnline){var stateChanged=false;if(isOnline&&!this.connected){stateChanged=true}else if(!isOnline&&this.connected){stateChanged=true}return stateChanged};this._checkServiceResponse=function(xhr,success,request){var offlineReason=null,wasOnline=this.connected;updateContextPropsFromResponse(this,xhr);if(!this._events){return}var offlineObservers=this._events.offline||[];var onlineObservers=this._events.online||[];if(offlineObservers.length===0&&onlineObservers.length===0){return}if(success){setRestApplicationIsOnline(true);setDeviceIsOnline(true)}else{if(deviceIsOnline){var localPingArgs={doNotFireEvent:true,offlineReason:null,async:false};if(!that.ping(localPingArgs)){offlineReason=localPingArgs.offlineReason;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}}if(wasOnline&&!this.connected){this.trigger("offline",this,offlineReason,request)}else if(!wasOnline&&this.connected){this.trigger("online",this,request)}};this._processPingResult=function(args){var xhr=args.xhr,pingResponseJSON,appServerStatus=null,wasOnline=this.connected,connectedBeforeCallback,assumeOepingFormat;if(args.hasOwnProperty("usingOepingFormat")){assumeOepingFormat=args.usingOepingFormat}else{assumeOepingFormat=oepingAvailable}if(xhr.status>=200&&xhr.status<300){updateContextPropsFromResponse(this,xhr);if(assumeOepingFormat){try{pingResponseJSON=JSON.parse(xhr.responseText);appServerStatus=pingResponseJSON.AppServerStatus}catch(e){console.error("Unable to parse ping response.")}}toggleOnlineState(xhr)}else{if(deviceIsOnline){if(xhr.status===0){args.offlineReason=progress.data.Session.SERVER_OFFLINE;setRestApplicationIsOnline(false)}else if(xhr.status===404||xhr.status===410){args.offlineReason=progress.data.Session.WEB_APPLICATION_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}else{args.offlineReason=progress.data.Session.DEVICE_OFFLINE}}if(appServerStatus){if(appServerStatus.PingStatus==="false"){args.offlineReason=progress.data.Session.APPSERVER_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}connectedBeforeCallback=this.connected;if(typeof xhr.onCompleteFn==="function"){xhr.onCompleteFn({pingResult:this.connected,xhr:xhr,offlineReason:args.offlineReason})}if(args.fireEventIfOfflineChange){if(wasOnline&&!connectedBeforeCallback){that.trigger("offline",that,args.offlineReason,null)}else if(!wasOnline&&connectedBeforeCallback){that.trigger("online",that,null)}}return this.connected};this._onReadyStateChangePing=function(){var xhr=this;var args;if(xhr.readyState===4){args={xhr:xhr,fireEventIfOfflineChange:true,offlineReason:null};that._processPingResult(args);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._pingtestOnReadyStateChange=function(){var xhr=this;if(xhr.readyState===4){var foundOeping=false;if(xhr.status>=200&&xhr.status<300){foundOeping=true}else{setPartialPingURI(that.loginTarget);console.warn("Default ping target not available, will use loginTarget instead.")}setOepingAvailable(foundOeping);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._sendPing=function(args){var xhr=new XMLHttpRequest,that=this;function sendPingAfterOpen(){if(args.async){xhr.onreadystatechange=args.onReadyStateFn;xhr.onCompleteFn=args.onCompleteFn;xhr._jsdosession=jsdosession;xhr._deferred=args.deferred}progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(that.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr.send(null)}try{if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,"GET",args.pingURI,args.async,sendPingAfterOpen)}else{this._setXHRCredentials(xhr,"GET",args.pingURI,this.userName,_password,args.async);if(xhr.readyState===1){sendPingAfterOpen()}}}catch(e){args.error=e}args.xhr=xhr};this._makePingURI=function(){var pingURI=this.serviceURI+partialPingURI;if(progress.data.Session._useTimeStamp){pingURI=progress.data.Session._addTimeStampToURL(pingURI)}return pingURI};this._autoping=function(){that.ping({async:true})};this._setXHRCredentials=function(xhr,verb,uri,userName,password,async){if(userName&&this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(canPassCredentialsToOpen()){xhr.open(verb,uri,async,userName,password)}else{xhr.open(verb,uri,async)}var auth=_make_basic_auth(userName,password);xhr.setRequestHeader("Authorization",auth)}else{xhr.open(verb,uri,async)}};this._addCCIDtoURL=function(url){var urlPart1,urlPart2,jsessionidStr,index;if(this.clientContextId&&this.clientContextId!=="0"){if(url.substring(0,this.serviceURI.length)===this.serviceURI){jsessionidStr=";"+"JSESSIONID="+this.clientContextId;index=url.indexOf("?");if(index===-1){url+=jsessionidStr}else{urlPart1=url.substring(0,index);urlPart2=url.substring(index);url=urlPart1+jsessionidStr+urlPart2}}}return url};this._saveClientContextId=function(xhr){setClientContextIDfromXHR(xhr,this)};this._parseCatalog=function(xhr){var jsonObject;var catalogdata;try{jsonObject=JSON.parse(xhr.responseText);catalogdata=jsonObject.services}catch(e){console.error("Unable to parse response. Make sure catalog has correct format.");catalogdata=null}return catalogdata};this._prependAppURL=function(oldURL){if(!oldURL){return this.serviceURI}var newURL=oldURL;var pat=/^https?:\/\//i;if(!pat.test(newURL)){if(newURL.indexOf("/")!==0){newURL="/"+newURL}newURL=this.serviceURI+newURL}return newURL};function _addWithCredentialsAndAccept(xhr,acceptString){try{xhr.withCredentials=true;xhr.setRequestHeader("Accept",acceptString)}catch(e){}}function _make_basic_auth(user,pw){var tok=user+":"+pw;var hash=btoa(tok);return"Basic "+hash}var loginFormIDString="j_spring_security_check";function _gotLoginForm(xhr){return _findStringInResponseHTML(xhr,loginFormIDString)}var loginFailureIdentificationString="login failed";function _gotLoginFailure(xhr){return _findStringInResponseHTML(xhr,loginFailureIdentificationString)}function _findStringInResponseHTML(xhr,searchString){if(!xhr.responseText){return false}var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("text/html")>=0&&xhr.responseText.indexOf(searchString)>=0){return true}return false}function handleJSONLoginResponse(params){var jsonObject;params.statusFromjson=null;try{jsonObject=JSON.parse(params.xhr.responseText);if(jsonObject.status_code!==undefined&&jsonObject.status_txt!==undefined){params.statusFromjson=jsonObject.status_code}}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,params.session);setLoginHttpStatus(params.xhr.status,params.session);throw new Error("Unable to parse login response from server.")}}function setRequestHeaderFromContextProps(session,xhr){if(session.xClientProps){xhr.setRequestHeader("X-CLIENT-PROPS",session.xClientProps)}else if(session._contextProperties.contextHeader!==undefined){xhr.setRequestHeader("X-CLIENT-PROPS",session._contextProperties.contextHeader)}}function toggleOnlineState(xhr){var pdsession=that;setLoginHttpStatus(xhr.status,pdsession);if(pdsession.loginHttpStatus>=200&&pdsession.loginHttpStatus<400){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);pdsession._saveClientContextId(xhr);storeAllSessionInfo()}else{if(pdsession.loginHttpStatus===0||pdsession.loginHttpStatus===400||pdsession.loginHttpStatus===410){setRestApplicationIsOnline(false);setLoginResult(progress.data.AuthenticationProvider._getAuthFailureReason(xhr),pdsession)}else{setRestApplicationIsOnline(true);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);return pdsession.loginResult}function updateContextPropsFromResponse(session,xhr){var contextString,context;if(xhr){contextString=getResponseHeaderNoError(xhr,"X-CLIENT-PROPS");if(contextString){try{context=JSON.parse(contextString)}catch(e){}if(typeof context==="object"){session._contextProperties.setContext(context)}else{throw new Error(progress.data._getMsgText("jsdoMSG123","Session","X-CLIENT-PROPS"))}}else if(contextString===""){session._contextProperties.setContext({})}}}function cleanServicesManager(){progress.data.ServicesManager.cleanSession(that)}if(typeof options==="object"){jsdosession=options.jsdosession;newURI=options.serviceURI;setAuthProvider(options.authProvider);if(options.authProvider&&options.authProvider.hasClientCredentials()){_loginResult=progress.data.Session.LOGIN_SUCCESS}if(newURI&&newURI[newURI.length-1]==="/"){newURI=newURI.substring(0,newURI.length-1)}_storageKey=options._storageKey;if(_storageKey){if(retrieveSessionInfo(_storageKey)){storedAuthModel=retrieveSessionInfo("authenticationModel");storedURI=retrieveSessionInfo("serviceURI");if(storedAuthModel!==options.authenticationModel||storedURI!==newURI){clearAllSessionInfo()}else{setSessionInfoFromStorage(_storageKey);stateWasReadFromStorage=true}}if(options.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){_storageKey=undefined}}if(!stateWasReadFromStorage){if(newURI){setServiceURI(newURI,this)}if(options.authenticationModel){this.authenticationModel=options.authenticationModel}}}};progress.data.Session._useTimeStamp=true;var SEQ_MAX_VALUE=999999999999999;var _tsseq=SEQ_MAX_VALUE;var _tsprefix1=0;var _tsprefix2=0;progress.data.Session._getNextTimeStamp=function(){var seq;_tsseq+=1;seq=_tsseq;if(seq>=SEQ_MAX_VALUE){_tsseq=1;seq=1;var t=Math.floor((Date.now?Date.now():(new Date).getTime())/1e4);if(_tsprefix1===t){_tsprefix2+=1;if(_tsprefix2>=SEQ_MAX_VALUE){_tsprefix2=1}}else{_tsprefix1=t;Math.random();_tsprefix2=Math.round(Math.random()*1e10)}}return _tsprefix1+"-"+_tsprefix2+"-"+seq};progress.data.Session._addTimeStampToURL=function(url){var timeStamp="_ts="+progress.data.Session._getNextTimeStamp();url+=(url.indexOf("?")===-1?"?":"&")+timeStamp;return url};progress.data.Session._setNoCacheHeaders=function(xhr){xhr.setRequestHeader("Cache-Control","no-cache");xhr.setRequestHeader("Pragma","no-cache")};if(typeof Object.defineProperty==="function"){Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_REQUIRED",{value:0,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"CATALOG_ALREADY_LOADED",{value:4,enumerable:true});Object.defineProperty(progress.data.Session,"ASYNC_PENDING",{value:5,enumerable:true});Object.defineProperty(progress.data.Session,"EXPIRED_TOKEN",{value:6,enumerable:true});Object.defineProperty(progress.data.Session,"SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_ANON",{value:"anonymous",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_BASIC",{value:"basic",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM",{value:"form",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_SSO",{value:"sso",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM_SSO",{value:"form_sso",enumerable:true});Object.defineProperty(progress.data.Session,"DEVICE_OFFLINE",{value:"Device is offline",enumerable:true});Object.defineProperty(progress.data.Session,"SERVER_OFFLINE",{value:"Cannot contact server",enumerable:true});Object.defineProperty(progress.data.Session,"WEB_APPLICATION_OFFLINE",{value:"Mobile Web Application is not available",enumerable:true});Object.defineProperty(progress.data.Session,"SERVICE_OFFLINE",{value:"REST web Service is not available",enumerable:true});Object.defineProperty(progress.data.Session,"APPSERVER_OFFLINE",{value:"AppServer is not available",enumerable:true})}else{progress.data.Session.LOGIN_SUCCESS=1;progress.data.Session.LOGIN_AUTHENTICATION_FAILURE=2;progress.data.Session.LOGIN_GENERAL_FAILURE=3;progress.data.Session.CATALOG_ALREADY_LOADED=4;progress.data.Session.SUCCESS=1;progress.data.Session.AUTHENTICATION_FAILURE=2;progress.data.Session.GENERAL_FAILURE=3;progress.data.Session.AUTH_TYPE_ANON="anonymous";progress.data.Session.AUTH_TYPE_BASIC="basic";progress.data.Session.AUTH_TYPE_FORM="form";progress.data.Session.AUTH_TYPE_SSO="sso"}progress.data.Session.prototype=new progress.util.Observable;progress.data.Session.prototype.constructor=progress.data.Session;function validateSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}else{listenerData.scope=args[2]}}}progress.data.Session.prototype._eventNames=["offline","online","afterLogin","afterAddCatalog","afterLogout","afterDisconnect"];progress.data.Session.prototype.validateSubscribe=validateSessionSubscribe;progress.data.Session.prototype.toString=function(radix){return"progress.data.Session"};progress.data.JSDOSession=function JSDOSession(options){var _pdsession,_serviceURI,that=this,_name;Object.defineProperty(this,"authenticationModel",{get:function(){return _pdsession?_pdsession.authenticationModel:undefined},enumerable:true});Object.defineProperty(this,"authProvider",{get:function(){return _pdsession?_pdsession._authProvider:null},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _pdsession?_pdsession.catalogURIs:undefined},enumerable:true});Object.defineProperty(this,"clientContextId",{get:function(){return _pdsession?_pdsession.clientContextId:undefined},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return _pdsession?_pdsession.connected:undefined},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _pdsession?_pdsession.JSDOs:undefined},enumerable:true});Object.defineProperty(this,"loginResult",{get:function(){return _pdsession?_pdsession.loginResult:undefined},enumerable:true});Object.defineProperty(this,"loginHttpStatus",{get:function(){return _pdsession?_pdsession.loginHttpStatus:undefined},enumerable:true});Object.defineProperty(this,"onOpenRequest",{get:function(){return _pdsession?_pdsession.onOpenRequest:undefined},set:function(newval){if(_pdsession){_pdsession.onOpenRequest=newval}},enumerable:true});Object.defineProperty(this,"pingInterval",{get:function(){return _pdsession?_pdsession.pingInterval:undefined},set:function(newval){if(_pdsession){_pdsession.pingInterval=newval}},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _pdsession?_pdsession.services:undefined},enumerable:true});Object.defineProperty(this,"serviceURI",{get:function(){if(_pdsession&&_pdsession.serviceURI){return _pdsession.serviceURI}else{return _serviceURI}},enumerable:true});Object.defineProperty(this,"userName",{get:function(){return _pdsession?_pdsession.userName:undefined},enumerable:true});Object.defineProperty(this,"name",{get:function(){return _name},enumerable:true});Object.defineProperty(this,"_isInvalidated",{get:function(){return _pdsession._isInvalidated},enumerable:false});function settlePromise(promise,fulfill,result,info){if(fulfill){promise.resolve(that,result,info)}else{promise.reject(that,result,info)}}function genericSessionEventHandler(pdsession,result,errorObject,xhr,deferred){var myDeferred;if(xhr){myDeferred=xhr._deferred}else{myDeferred=deferred}settlePromise(myDeferred,result===progress.data.Session.SUCCESS?true:false,result,{errorObject:errorObject,xhr:xhr})}function onAfterAddCatalog(pdsession,result,errorObject,xhr){var deferred,fulfill=false,settleResult,info;if(result===progress.data.Session.EXPIRED_TOKEN){settleResult=progress.data.Session.EXPIRED_TOKEN}else if(result===progress.data.Session.LOGIN_AUTHENTICATION_FAILURE){settleResult=progress.data.Session.LOGIN_AUTHENTICATION_FAILURE}else{settleResult=progress.data.Session.GENERAL_FAILURE}if(xhr&&xhr._deferred){deferred=xhr._deferred;if(result!==progress.data.Session.SUCCESS&&result!==progress.data.Session.CATALOG_ALREADY_LOADED){result=result||progress.data.Session.GENERAL_FAILURE;deferred._overallCatalogResult=progress.data.Session.GENERAL_FAILURE}deferred._results[xhr._catalogIndex]={catalogURI:xhr._catalogURI,result:result,errorObject:errorObject,xhr:xhr};deferred._numCatalogsProcessed+=1;if(deferred._numCatalogsProcessed===deferred._numCatalogs){deferred._processedPromise=true;if(!deferred._overallCatalogResult){fulfill=true;settleResult=progress.data.Session.SUCCESS}if(settleResult===progress.data.Session.SUCCESS){if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,details:xhr._deferred._results}}}else{if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,errorObject:new Error(progress.data._getMsgText("jsdoMSG512")),details:xhr._deferred._results}}}settlePromise(xhr._deferred,fulfill,settleResult,info)}}}function onAfterLogout(pdsession,errorObject,xhr){var result=progress.data.Session.GENERAL_FAILURE,fulfill=false;if(xhr&&xhr._deferred){if(!errorObject&&!pdsession.loginResult){result=progress.data.Session.SUCCESS;fulfill=true}settlePromise(xhr._deferred,fulfill,result,{errorObject:errorObject,xhr:xhr})}}function onPingComplete(args){var xhr=args.xhr;if(xhr&&xhr._deferred){settlePromise(xhr._deferred,args.pingResult,args.pingResult,{offlineReason:args.offlineReason,xhr:xhr})}}this.login=function(username,password,options){var deferred=new progress.util.Deferred,iOSBasicAuthTimeout;function callIsAuthorized(){that.isAuthorized().then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(that,object.result,object.info)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","JSDOSession","login()"))}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout}if(!_pdsession._authProvider){_pdsession._authProvider=new progress.data.AuthenticationProvider({uri:this.serviceURI,authenticationModel:this.authenticationModel});_pdsession._authProvider.logout().then(function(){return _pdsession._authProvider.login(username,password)}).then(function(){callIsAuthorized()},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}else{throw new Error(progress.data._getMsgText("jsdoMSG062","JSDOSession","login()"))}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.disconnect=function(){var deferred=new progress.util.Deferred,errorObject;try{_pdsession.subscribe("afterDisconnect",genericSessionEventHandler,this);_pdsession._disconnect(deferred)}catch(e){errorObject=new Error(progress.data._getMsgText("jsdoMSG049","JSDOSession","disconnect",e.message))}if(errorObject){if(progress.util.Deferred.useJQueryPromises){throw errorObject}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:errorObject})}}else{return deferred.promise()}};this.addCatalog=function(catalogURI,unameOrOpts,password,opts){var deferred=new progress.util.Deferred,catalogURIs,numCatalogs,catalogIndex,addResult,errorObject,iOSBasicAuthTimeout,username,options,authProvider;try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(typeof catalogURI==="string"){catalogURIs=[catalogURI]}else if(catalogURI instanceof Array){catalogURIs=catalogURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","addCatalog","The first argument must be a string or an array of strings specifying the URI of the catalog."))}if(unameOrOpts){if(typeof unameOrOpts==="string"){if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG058","Session"))}username=unameOrOpts;if(opts){options=opts;options.authProvider=undefined}}else if(typeof unameOrOpts==="object"){options=unameOrOpts}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDOSession","2","object","addCatalog"))}}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout;if(options.authProvider){authProvider=options.authProvider}else if(this.authProvider){authProvider=this.authProvider}}if(!authProvider&&!this.authProvider&&!username){throw new Error(progress.data._getMsgText("jsdoMSG511"))}_pdsession.subscribe("afterAddCatalog",onAfterAddCatalog,this);numCatalogs=catalogURIs.length;deferred._numCatalogs=numCatalogs;deferred._numCatalogsProcessed=0;deferred._results=[];deferred._results.length=numCatalogs;for(catalogIndex=0;catalogIndex=200&&xhr.status<300){deferred.resolve(that,progress.data.Session.SUCCESS,info)}else{if(xhr.status===401){cbresult=progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else{cbresult=progress.data.Session.GENERAL_FAILURE}deferred.reject(that,cbresult,info)}}};try{xhr.send()}catch(e){throw new Error("JSDOSession: Unable to validate authorization. "+e.message)}})}else{result=progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED;deferred.reject(that,result,{xhr:xhr})}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(that,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.setContext=function(context){_pdsession._contextProperties.setContext(context)};this.setContextProperty=function(propertyName,propertyValue){_pdsession._contextProperties.setContextProperty(propertyName,propertyValue)};this.getContext=function(){return _pdsession._contextProperties.getContext()};this.getContextProperty=function(propertyName){return _pdsession._contextProperties.getContextProperty(propertyName)};this._onlineHandler=function(session,request){that.trigger("online",that,request)};this._offlineHandler=function(session,offlineReason,request){that.trigger("offline",that,offlineReason,request)};if(arguments.length>0&&typeof arguments[0]==="object"){if(options.serviceURI&&typeof options.serviceURI==="string"){_serviceURI=options.serviceURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options parameter must include a 'serviceURI' property that is a string."))}if(options.authenticationModel){if(typeof options.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The authenticationModel property of the options parameter must be a string."))}options.authenticationModel=options.authenticationModel.toLowerCase()}else{options.authenticationModel=progress.data.Session.AUTH_TYPE_ANON}if(options.authProvider){if(typeof options.authProvider!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG502","JSDOSession","options","constructor","authProvider"))}if(options.authProvider.authenticationModel!==progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authProvider.authenticationModel!==options.authenticationModel||options.authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authenticationModel!==progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG059","JSDOSession",options.authProvider.authenticationModel,options.authenticationModel))}if(typeof options.authProvider.hasClientCredentials==="function"){if(!options.authProvider.hasClientCredentials()){throw new Error(progress.data._getMsgText("jsdoMSG125","JSDOSession"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG505","JSDOSession","AuthenticationProvider","hasClientCredentials"))}}else if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG508"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options argument was missing or invalid."))}_name=options.name;_pdsession=new progress.data.Session({_storageKey:_name,_silent:true,authenticationModel:options.authenticationModel,serviceURI:options.serviceURI,jsdosession:this,authProvider:options.authProvider});try{if(options.context){this.setContext(options.context)}_pdsession.subscribe("online",this._onlineHandler,this);_pdsession.subscribe("offline",this._offlineHandler,this)}catch(err){_pdsession=undefined;throw err}};progress.data.JSDOSession.prototype=new progress.util.Observable;progress.data.JSDOSession.prototype.constructor=progress.data.JSDOSession;function validateJSDOSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}listenerData.scope=args[2]}}progress.data.JSDOSession.prototype._eventNames=["offline","online"];progress.data.JSDOSession.prototype.validateSubscribe=validateJSDOSessionSubscribe;progress.data.JSDOSession.prototype.toString=function(radix){return"progress.data.JSDOSession"};progress.data.getSession=function(options){var deferred=new progress.util.Deferred,authProvider,promise,authProviderInitObject={};function sessionRejectHandler(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);if(authProvider&&authProvider.hasClientCredentials()){var callback=function(){deferred.reject(object.result,object.info)};authProvider.logout().then(callback,callback)}else{deferred.reject(object.result,object.info)}}function callbackRejectHandler(reason){deferred.reject(progress.data.Session.GENERAL_FAILURE,{reason:reason})}function loginHandler(object){var jsdosession;try{jsdosession=new progress.data.JSDOSession(options);try{jsdosession.isAuthorized().then(function(){return jsdosession.addCatalog(options.catalogURI)},sessionRejectHandler).then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(object.jsdosession,progress.data.Session.SUCCESS)},sessionRejectHandler)}catch(e){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}catch(ex){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:ex})}}function callLogin(provider){var errorObject;if(typeof options.loginCallback!=="undefined"){options.loginCallback().then(function(result){try{provider.login(result.username,result.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}},callbackRejectHandler)}else if(options.username&&options.password){try{provider.login(options.username,options.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG052","getSession()"));sessionRejectHandler(provider,progress.data.Session.AUTHENTICATION_FAILURE,{errorObject:errorObject})}}if(typeof options!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options","object"))}if(typeof options.loginCallback!=="undefined"&&typeof options.loginCallback!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options.loginCallback","function"))}try{if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){if(!options.authenticationURI||!options.authProviderAuthenticationModel){throw new Error(progress.data._getMsgText("jsdoMSG509"))}}if(options.authenticationURI){authProviderInitObject.uri=options.authenticationURI;authProviderInitObject.authenticationModel=options.authProviderAuthenticationModel;if(typeof authProviderInitObject.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG502","progress.data.getSession","object","getSession","authProviderAuthenticationModel"))}}else{authProviderInitObject.uri=options.serviceURI;authProviderInitObject.authenticationModel=options.authenticationModel}authProvider=new progress.data.AuthenticationProvider(authProviderInitObject);options.authProvider=authProvider;if(authProvider.hasClientCredentials()){loginHandler(authProvider)}else{if(authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){authProvider.login().then(loginHandler,sessionRejectHandler)}else{callLogin(authProvider)}}}catch(error){sessionRejectHandler(null,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}return deferred.promise()};progress.data.invalidateAllSessions=function(){var jsdosession,key,deferred=new progress.util.Deferred,jsdosessions=progress.data.ServicesManager._jsdosessions,invalidatePromises=[];try{for(key in jsdosessions){if(jsdosessions.hasOwnProperty(key)){jsdosession=jsdosessions[key];invalidatePromises.push(jsdosession.invalidate())}}progress.util.Deferred.when(invalidatePromises).then(function(){deferred.resolve(progress.data.Session.SUCCESS)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(progress.data.Session.GENERAL_FAILURE,info)})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()}})();if(typeof exports!=="undefined"){exports.progress=progress}(function(){"use strict";if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data.AuthenticationProvider=function AuthenticationProvider(initObject){var authProv,authModel,uri;if(typeof initObject==="object"){this._checkStringArg("constructor",initObject.authenticationModel,"initObject.authenticationModel","initObject.authenticationModel");this._checkStringArg("constructor",initObject.uri,"init-object.uri","init-object.uri")}else{throw new Error(progress.data._getMsgText("jsdoMSG033","AuthenticationProvider","the constructor","The init-object argument was missing or invalid."))}authModel=initObject.authenticationModel.toLowerCase();switch(authModel){case progress.data.Session.AUTH_TYPE_ANON:this._initialize(initObject.uri,progress.data.Session.AUTH_TYPE_ANON,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});authProv=this;break;case progress.data.Session.AUTH_TYPE_BASIC:authProv=new progress.data.AuthenticationProviderBasic(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM:authProv=new progress.data.AuthenticationProviderForm(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM_SSO:authProv=new progress.data.AuthenticationProviderSSO(initObject.uri);break;default:throw new Error(progress.data._getMsgText("jsdoMSG502","AuthenticationProvider","init-object","constructor","authenticationModel"))}return authProv};progress.data.AuthenticationProvider.prototype._loginProto=function(sendParam){var deferred=new progress.util.Deferred,xhr,uriForRequest,header,that=this;try{if(this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG051","AuthenticationProvider"))}xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLoginResult(xhr,deferred)}};if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(this._loginURI)}else{uriForRequest=this._loginURI}this._openLoginRequest(xhr,uriForRequest);xhr.setRequestHeader("Accept","application/json");xhr.send(sendParam)}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.login=function(){return this._loginProto()};progress.data.AuthenticationProvider.prototype._openLoginRequest=function(xhr,uri){xhr.open("GET",uri,true);progress.data.Session._setNoCacheHeaders(xhr)};progress.data.AuthenticationProvider.prototype._processLoginResult=function(xhr,deferred){var result;if(xhr.status===200){this._loggedIn=true;this._storeInfo();result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};progress.data.AuthenticationProvider.prototype.logout=function(){var deferred=new progress.util.Deferred;try{this._reset();deferred.resolve(this,progress.data.Session.SUCCESS,{})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.hasClientCredentials=function(){return this._loggedIn};progress.data.AuthenticationProvider.prototype.hasRefreshToken=function(){return false};progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);xhr.setRequestHeader("Accept","application/json");callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};progress.data.AuthenticationProvider.prototype._initialize=function(uriParam,authModel,targetURIs){var tempURI,target;Object.defineProperty(this,"uri",{get:function(){return this._uri},enumerable:true});Object.defineProperty(this,"authenticationModel",{get:function(){return this._authenticationModel},enumerable:true});if(uriParam[uriParam.length-1]==="/"){tempURI=uriParam.substring(0,uriParam.length-1)}else{tempURI=uriParam}for(target in targetURIs){if(targetURIs.hasOwnProperty(target)){this[target]=tempURI+targetURIs[target]}}this._authenticationModel=authModel;this._uri=uriParam;this._loggedIn=false;this._dataKeys={uri:".uri",loggedIn:".loggedIn"};if(typeof sessionStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","AuthenticationProvider","sessionStorage"))}this._storage=sessionStorage;this._storageKey=this._uri;this._dataKeys.uri=this._storageKey+this._dataKeys.uri;this._dataKeys.loggedIn=this._storageKey+this._dataKeys.loggedIn;if(this._retrieveLoggedIn()){this._loggedIn=true}};progress.data.AuthenticationProvider.prototype._storeInfo=function(){this._storage.setItem(this._dataKeys.uri,JSON.stringify(this._uri));this._storage.setItem(this._dataKeys.loggedIn,JSON.stringify(this._loggedIn))};progress.data.AuthenticationProvider.prototype._retrieveInfoItem=function(propName){var jsonStr=this._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value};progress.data.AuthenticationProvider.prototype._retrieveURI=function(){return this._retrieveInfoItem(this._dataKeys.uri)};progress.data.AuthenticationProvider.prototype._retrieveLoggedIn=function(){return this._retrieveInfoItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._clearInfo=function(info){this._storage.removeItem(this._dataKeys.uri);this._storage.removeItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._reset=function(){this._clearInfo();this._loggedIn=false};progress.data.AuthenticationProvider.prototype._settlePromise=function(deferred,result,info){if(result===progress.data.Session.SUCCESS){deferred.resolve(this,result,info)}else{deferred.reject(this,result,info)}};progress.data.AuthenticationProvider.prototype._checkStringArg=function(fnName,argToCheck,argPosition,argName){if(typeof argToCheck!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","AuthenticationProvider",argPosition,"string",fnName))}else if(argToCheck.length===0){throw new Error(progress.data._getMsgText("jsdoMSG501","AuthenticationProvider",argName,fnName))}};progress.data.AuthenticationProvider._getAuthFailureReason=function(xhr){var contentType,jsonObject,result=progress.data.Session.AUTHENTICATION_FAILURE;if(xhr.status===401){contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>-1&&xhr.responseText){jsonObject=JSON.parse(xhr.responseText);if(jsonObject.error==="sso.token.expired_token"){result=progress.data.Session.EXPIRED_TOKEN}}}else{result=null}return result};Object.defineProperty(progress.data.AuthenticationProvider,"_homeLoginURIBase",{value:"/static/home.html",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLoginURIBase",{value:"/static/auth/j_spring_security_check",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLogoutURIBase",{value:"/static/auth/j_spring_security_logout",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenLoginURIBase",{value:progress.data.AuthenticationProvider._springLoginURIBase+"?OECP=yes",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenRefreshURIBase",{value:"/static/auth/token?op=refresh",enumerable:true})})();(function(){"use strict";progress.data.AuthenticationProviderBasic=function(uri){var defaultiOSBasicAuthTimeout,userName=null,password=null,fn;this._initialize(uri,progress.data.Session.AUTH_TYPE_BASIC,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});this._reset();function make_basic_auth_header(user,pw){var tok=user+":"+pw,hash=btoa(tok);return"Basic "+hash}this._reset=function(){userName=null;password=null;progress.data.AuthenticationProviderBasic.prototype._reset.apply(this)};this._openLoginRequest=function(xhr,uri){var auth;xhr.open("GET",uri,true);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr)};this._processLoginResult=function _basic_processLoginResult(xhr,deferred){progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply(this,[xhr,deferred]);if(!this._loggedIn){userName=null;password=null}};this.login=function(userNameParam,passwordParam){this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");userName=userNameParam;password=passwordParam;return this._loginProto()};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var auth,errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr);callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}}};function BasicProxy(){}BasicProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderBasic.prototype=new BasicProxy;progress.data.AuthenticationProviderBasic.prototype.constructor=progress.data.AuthenticationProviderBasic})();(function(){"use strict";var fn;progress.data.AuthenticationProviderForm=function(uri){this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM,{_loginURI:progress.data.AuthenticationProvider._springLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase})};function FormProxy(){}FormProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderForm.prototype=new FormProxy;progress.data.AuthenticationProviderForm.prototype.constructor=progress.data.AuthenticationProviderForm;progress.data.AuthenticationProviderForm.prototype.login=function(userNameParam,passwordParam){var deferred=new progress.util.Deferred,xhr,that=this;this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");return this._loginProto("j_username="+encodeURIComponent(userNameParam)+"&j_password="+encodeURIComponent(passwordParam)+"&submit=Submit")};progress.data.AuthenticationProviderForm.prototype._openLoginRequest=function(xhr,uri){xhr.open("POST",uri,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.setRequestHeader("Pragma","no-cache");xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.withCredentials=true};progress.data.AuthenticationProviderForm.prototype.logout=function(){var deferred=new progress.util.Deferred,xhr,that=this;try{if(!this._loggedIn){deferred.resolve(this,progress.data.Session.SUCCESS,{})}else{xhr=new XMLHttpRequest;this._openLogoutRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLogoutResult(xhr,deferred)}};xhr.send()}this._reset()}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProviderForm.prototype._openLogoutRequest=function(xhr){xhr.open("GET",this._logoutURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Accept","application/json")};progress.data.AuthenticationProviderForm.prototype._processLogoutResult=function(xhr,deferred){var result;if(xhr.status===200){result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};fn=progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize;progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){function afterSuper(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.withCredentials=true;callback(xhr)}}try{progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply(this,[xhr,verb,uri,async,afterSuper])}catch(e){callback(e)}};progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super=fn})();(function(){"use strict";var fn;progress.data.AuthenticationProviderSSO=function(uri){var that=this,_automaticTokenRefresh,temp,ssoTokenInfo=null,tokenDataKeys={token:".access_token",refreshToken:".refresh_token",tokenType:".token_type",expiration:".expires_in",accessTokenExpiration:".accessTokenExpiration"};function storeTokenInfo(info){var date,accessTokenExpiration;if(info.access_token.length){that._storage.setItem(tokenDataKeys.token,JSON.stringify(info.access_token))}if(info.refresh_token.length){that._storage.setItem(tokenDataKeys.refreshToken,JSON.stringify(info.refresh_token));date=new Date;accessTokenExpiration=date.getTime()+info.expires_in*1e3*.75;that._storage.setItem(tokenDataKeys.accessTokenExpiration,JSON.stringify(accessTokenExpiration))}else{that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}that._storage.setItem(tokenDataKeys.tokenType,JSON.stringify(info.token_type));that._storage.setItem(tokenDataKeys.expiration,JSON.stringify(info.expires_in))}function retrieveTokenProperty(propName){var jsonStr=that._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}function retrieveToken(){return retrieveTokenProperty(tokenDataKeys.token)}function retrieveRefreshToken(){return retrieveTokenProperty(tokenDataKeys.refreshToken)}function retrieveAccessTokenExpiration(){return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration)}function retrieveTokenType(){return retrieveTokenProperty(tokenDataKeys.tokenType)}function getToken(){return retrieveToken()}function retrieveExpiration(){return retrieveTokenProperty(tokenDataKeys.expiration)}function clearTokenInfo(info){that._storage.removeItem(tokenDataKeys.token);that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.tokenType);that._storage.removeItem(tokenDataKeys.expiration);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}function openRefreshRequest(xhr){xhr.open("POST",that._refreshURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Content-Type","application/json");xhr.setRequestHeader("Accept","application/json")}function processRefreshResult(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",ex.message))}}else if(xhr.status===401){that._reset();result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}that._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})}this._processLoginResult=function(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){this._loggedIn=true;try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",ex.message))}if(result!==progress.data.Session.SUCCESS){var callback=function(params){params=progress.util.Deferred.getParamObject(params);params.provider._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})};this.logout().then(callback,callback);return}}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};this._reset=function(){progress.data.AuthenticationProviderSSO.prototype._reset.apply(this);clearTokenInfo();ssoTokenInfo=null};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var that=this,date,errorObject;function afterRefreshCheck(provider,result,info){if(result===progress.data.Session.AUTHENTICATION_FAILURE){callback(new Error(progress.data._getMsgText("jsdoMSG060")))}else{progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply(that,[xhr,verb,uri,async,function(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.setRequestHeader("Authorization","oecp "+getToken());callback(xhr)}}])}}if(this.hasClientCredentials()){date=new Date;if(this.automaticTokenRefresh&&this.hasRefreshToken()&&date.getTime()>retrieveAccessTokenExpiration()){try{var callback=function(params,result,info){params=progress.util.Deferred.getParamObject(params,result,info);afterRefreshCheck(params.provider,params.result,params.info)};this.refresh().then(callback,callback)}catch(e){callback(e)}}else{afterRefreshCheck(this,progress.data.Session.SUCCESS,null)}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};this.hasClientCredentials=function(){return retrieveToken()===null?false:true};this.refresh=function(){var deferred=new progress.util.Deferred,xhr;try{if(!this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG053","AuthenticationProvider","refresh"))}if(!this.hasRefreshToken()){throw new Error(progress.data._getMsgText("jsdoMSG054","AuthenticationProvider"))}xhr=new XMLHttpRequest;openRefreshRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){processRefreshResult(xhr,deferred)}};xhr.send('{"token_type":"'+retrieveTokenType()+'","refresh_token":"'+retrieveRefreshToken()+'"}')}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.hasRefreshToken=function(){return retrieveRefreshToken()===null?false:true};this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM_SSO,{_loginURI:progress.data.AuthenticationProvider._springFormTokenLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase,_refreshURI:progress.data.AuthenticationProvider._springFormTokenRefreshURIBase});_automaticTokenRefresh=true;Object.defineProperty(this,"automaticTokenRefresh",{get:function(){return _automaticTokenRefresh},set:function(value){if(value===true||value===false){_automaticTokenRefresh=value}else{throw new Error(progress.data._getMsgText("jsdoMSG061","AuthenticationProvider","automaticTokenRefresh"))}},enumerable:true});this._dataKeys.automaticTokenRefresh=this._storageKey+".automaticTokenRefresh";temp=this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh);if(temp===false){_automaticTokenRefresh=false}tokenDataKeys.token=this._storageKey+tokenDataKeys.token;tokenDataKeys.refreshToken=this._storageKey+tokenDataKeys.refreshToken;tokenDataKeys.tokenType=this._storageKey+tokenDataKeys.tokenType;tokenDataKeys.expiration=this._storageKey+tokenDataKeys.expiration;tokenDataKeys.accessTokenExpiration=this._storageKey+tokenDataKeys.accessTokenExpiration;if(retrieveToken()){this._loggedIn=true}};function SSOProxy(){}SSOProxy.prototype=progress.data.AuthenticationProviderForm.prototype;progress.data.AuthenticationProviderSSO.prototype=new SSOProxy;progress.data.AuthenticationProviderSSO.prototype.constructor=progress.data.AuthenticationProviderSSO;fn=progress.data.AuthenticationProviderSSO.prototype._storeInfo;progress.data.AuthenticationProviderSSO.prototype._storeInfo=function(){progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this);this._storage.setItem(this._dataKeys.automaticTokenRefresh,JSON.stringify(this._automaticTokenRefresh))};progress.data.AuthenticationProviderSSO.prototype._storeInfo._super=fn;fn=progress.data.AuthenticationProviderSSO.prototype._clearInfo;progress.data.AuthenticationProviderSSO.prototype._clearInfo=function(){progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this);this._storage.removeItem(this._dataKeys.automaticTokenRefresh)};progress.data.AuthenticationProviderSSO.prototype._clearInfo._super=fn})();if(typeof kendo!=="undefined"){(function(){var JSDODataReader,JSDOTransport,JSDOObservable=new kendo.Observable;function initializeJSDO(transport,options){var jsdo,resourceName;if(options.jsdo instanceof progress.data.JSDO){jsdo=options.jsdo}else if(typeof options.jsdo==="string"){resourceName=options.jsdo;jsdo=new progress.data.JSDO({name:resourceName})}else{throw new Error("JSDO: jsdo property must be either a JSDO instance or a string.")}if(transport.tableRef===undefined&&jsdo._defaultTableRef){transport.tableRef=jsdo._defaultTableRef._name}if(transport.tableRef===undefined){throw new Error("JSDO: A tableRef must be specified when using a multi-table DataSet.")}else if(jsdo[transport.tableRef]===undefined){throw new Error("JSDO: tableRef '"+transport.tableRef+"' is not present in JSDO definition.")}return jsdo}JSDODataReader=kendo.data.readers.json.extend({init:function(arg1){var event={},transport;JSDOObservable.trigger("info",event);transport=this.transport=event.sender._events.info.transport;kendo.data.readers.json.fn.init.call(this,arg1);this.model=kendo.data.Model.define({init:function(data){var record;if(!data||jQuery.isEmptyObject(data)){data=transport._getInitialValues()}record=transport._convertDataTypes(data);transport.jsdo._deleteProdsProperties(record,true);kendo.data.Model.fn.init.call(this,record)},id:"_id",fields:transport._getModel()})},total:function(data){return data.total||(data.data?data.data.length:data.length)},data:function(data){return data.data||data}});JSDOTransport=kendo.data.RemoteTransport.extend({init:function(options){var transport=this,fnName;if(options.tableRef!==undefined){transport.tableRef=options.tableRef}transport.jsdo=initializeJSDO(transport,options);transport._initFromServer=false;transport.autoSave=options.autoSave!==undefined?options.autoSave:true;transport.readLocal=options.readLocal!==undefined?options.readLocal:false;transport.countFnName=options.countFnName;transport.useArrays=options.useArrays!==undefined?options.useArrays:false;if(transport.countFnName!==undefined){if(typeof transport.jsdo[transport.countFnName]!=="function"){throw new Error("Invoke operation '"+transport.countFnName+"' for countFnName is not defined.")}}else if(transport.jsdo._resource.generic.count!==undefined){for(fnName in transport.jsdo._resource.fn){if(transport.jsdo._resource.fn.hasOwnProperty(fnName)){if(transport.jsdo._resource.generic.count===transport.jsdo._resource.fn[fnName]["function"]){transport.countFnName=fnName;break}}}}JSDOObservable.one("info",function(e){e.sender._events.info.transport=transport});transport._initConvertTypes();kendo.data.RemoteTransport.fn.init.call(this,options)},_initConvertTypes:function(){var transport=this,i,schema,fieldName,dateFields=[],arrayFields=[],convertDateFields=false;transport._convertTypes=false;schema=transport.jsdo[transport.tableRef].getSchema();for(i=0;i0&&fieldName.charAt(0)!=="_"){if(schema[i].type==="string"&&schema[i].format&&schema[i].format.indexOf("date")!==-1){dateFields.push(fieldName);if(!convertDateFields){convertDateFields=true}}else if(!transport.useArrays&&schema[i].type==="array"){arrayFields.push(fieldName);if(!convertDateFields&&schema[i].ablType&&schema[i].ablType.indexOf("DATE")===0){convertDateFields=true}}}}if(dateFields.length>0||arrayFields.length>0){transport._convertTypes=true;transport._convertFields={};transport._convertFields._arrayFields=[];transport._convertFields._dateFields=[]}if(dateFields.length>0){transport._convertFields._dateFields=dateFields}if(convertDateFields){transport._convertFields._datePattern=new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?$");transport._convertFields._dateTimePattern=new RegExp("^([0-9]+)?-([0-9]{2})?-([0-9]{2})?"+"T([0-9]{2})?:([0-9]{2})?:([0-9]{2})?.([0-9]{3})?$")}if(arrayFields.length>0){transport._convertFields._arrayFields=arrayFields}},_convertStringToDate:function(data,fieldName,targetFieldName){var transport=this,array,ablType,orig;if(!targetFieldName){targetFieldName=fieldName}array=transport._convertFields._datePattern.exec(data[targetFieldName])||[];if(array.length>0){data[targetFieldName]=new Date(parseInt(array[1],10),parseInt(array[2],10)-1,parseInt(array[3],10))}else{ablType=transport.jsdo[transport.tableRef]._fields[fieldName.toLowerCase()].ablType;if(ablType==="DATETIME"){array=transport._convertFields._dateTimePattern.exec(data[targetFieldName])||[];if(array.length>0){data[targetFieldName]=new Date(parseInt(array[1],10),parseInt(array[2],10)-1,parseInt(array[3],10),parseInt(array[4],10),parseInt(array[5],10),parseInt(array[6],10),parseInt(array[7],10))}}if(typeof data[targetFieldName]==="string"){orig=data[targetFieldName];try{data[targetFieldName]=new Date(data[targetFieldName])}catch(e){data[targetFieldName]=orig;console.log(progress.data._getMsgText("jsdoMSG000","_convertStringToDate() could not convert to date object: "+orig))}}}},_convertDataTypes:function(data){var transport=this,i,k,fieldName,schemaInfo,prefixElement,elementName,copy;delete data["prods:rowState"];if(!transport.useArrays&&transport._convertTypes&&transport._convertFields._arrayFields.length>0){copy={};transport.jsdo._copyRecord(transport.jsdo._buffers[transport.tableRef],data,copy);data=copy}if(!transport._convertTypes){return data}for(k=0;k0&&schema[i].name.charAt(0)!=="_"){type=schema[i].type;if(type==="integer"){type="number"}else if(type==="string"&&schema[i].format&&schema[i].format.indexOf("date")!==-1){type="date"}if(type==="array"){for(j=0;j0&&schema[i].name.charAt(0)!=="_"){defaultValue=transport.jsdo._getDefaultValue(schema[i]);if(schema[i].type==="array"){data[schema[i].name]=[];for(j=0;j0||jsdo[this.tableRef]._data instanceof Array&&jsdo[this.tableRef]._data.length>0}else{this._initFromServer=jsdo[this.tableRef]._data instanceof Array&&jsdo[this.tableRef]._data.length>0}}data.data=[];if(this.readLocal&&this._initFromServer){saveUseRelationships=jsdo.useRelationships;jsdo.useRelationships=false;data=this._getData(options);jsdo.useRelationships=saveUseRelationships;options.success(data);return}if(!this.readLocal){if(options.data){for(property in options.data){if(options.data.hasOwnProperty(property)){if(options.data[property]!==undefined&&optionsMapping[property]){if(filter===undefined){filter={}}filter[optionsMapping[property]]=options.data[property]}}}if(filter){filter.tableRef=this.tableRef}}}callback=function onAfterFillJSDO(object,success,request){var data={},saveUseRelationships,promise,total,exception,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;if(success){saveUseRelationships=jsdo.useRelationships;jsdo.useRelationships=false;if(transport.readLocal){data=transport._getData(options)}else{data.data=jsdo[transport.tableRef].getData();total=jsdo.getProperty("server.count");if(total){data.total=total}}jsdo.useRelationships=saveUseRelationships;transport._initFromServer=true;if(options.data&&options.data.take){if(!transport.readLocal&&transport.countFnName!==undefined&&typeof jsdo[transport.countFnName]==="function"){if(options.data.skip===0&&options.data.take>data.data.length){options.success(data);return}promise=jsdo.invoke(transport.countFnName,{filter:request.objParam.filter});promise.then(function(object,success,request){var exception,total,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;try{if(typeof request.response==="object"&&Object.keys(request.response).length===1){total=request.response[Object.keys(request.response)];if(typeof total!=="number"){total=undefined}}}catch(e){}if(total!==undefined){if(total){data.total=total}options.success(data)}else{exception=new Error("Unexpected response from '"+transport.countFnName+"' operation.");options.error(request.xhr,request.xhr.status,exception)}},function(object,success,request){var exception,jsdo;object=progress.util.Deferred.getParamObject(object,success,request);jsdo=object.jsdo;success=object.success;request=object.request;exception=new Error("Error invoking '"+transport.countFnName+"' operation.");options.error(request.xhr,request.xhr.status,exception)})}else{options.success(data)}}else{options.success(data)}}else{exception=new Error("Error while reading records.");options.error(request.xhr,request.xhr.status,exception)}};jsdo.fill(filter).then(callback,callback)}catch(e){options.error(null,null,e)}},_processChanges:function(options,request){var jsdo=this.jsdo,transport=this,array,i,jsrecord,id,record;if(options.batch){array=[];if(options.data.created instanceof Array){if(jsdo._resource.idProperty){if(request.jsrecords){for(i=0;i=2&&typeof args[0]==="string"&&typeof args[1]==="string"){listenerData.operation=args[1];listenerData.fn=args[2];listenerData.scope=args[3]}else if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="function"){listenerData.operation=undefined;listenerData.scope=args[2];listenerData.fn=args[1]}else{throw new Error}};this.subscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"subscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",progress.data._getMsgText("jsdoMSG039")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",e.message))}observers=this._events[evt]||[];observers=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation);observers.push(listenerData);this._events[evt]=observers;return this};this.unsubscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"unsubscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",progress.data._getMsgText("jsdoMSG037")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",e.message))}observers=this._events[evt]||[];if(observers.length>0){this._events[evt]=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation)}return this};this.trigger=function(evt,operation,args){var observers,op;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"trigger"))}this._events=this._events||{};evt=evt.toLowerCase();observers=this._events[evt]||[];if(observers.length>0){args=Array.prototype.slice.call(arguments);if(arguments.length>=2&&typeof evt==="string"&&typeof operation==="string"){op=operation;args=args.length>2?args.slice(2):[]}else if(arguments.length>=1&&typeof evt==="string"){op=undefined;args=args.length>1?args.slice(1):[]}else{throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"trigger"))}observers.forEach(function(el){if(el.operation===op){el.fn.apply(el.scope,args)}})}return this};this.unsubscribeAll=function(evt,operation){var observers;if(evt){this._events=this._events||{};if(typeof evt==="string"){evt=evt.toLowerCase();observers=this._events[evt]||[];observers.forEach(function(el){if(el.operation){this.unsubscribe(evt,el.operation,el.fn,el.scope)}else{this.unsubscribe(evt,el.fn,el.scope)}},this)}}else{this._events={}}return this}};progress.data.LocalStorage=function LocalStorage(){if(typeof localStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","progress.data.LocalStorage","localStorage"))}this.saveToLocalStorage=function(name,dataObj){localStorage.setItem(name,JSON.stringify(dataObj))};this.readFromLocalStorage=function(name){var jsonStr=localStorage.getItem(name),dataObj=null;if(jsonStr!==null){try{dataObj=JSON.parse(jsonStr)}catch(e){dataObj=null}}return dataObj};this.clearLocalStorage=function(name){localStorage.removeItem(name)}};progress.util._convertToABLWhereString=function(tableRef,filter){var result=[],logic=filter.logic||"and",idx,length,field,fieldInfo,type,format,operator,value,ablType,filters=filter.filters||[filter],whereOperators={eq:"=",neq:"<>",gt:">",gte:">=",lt:"<",lte:"<=",contains:"INDEX",doesnotcontain:"INDEX",endswith:"R-INDEX",startswith:"BEGINS",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};for(idx=0,length=filters.length;idx 0"}else{format="{2} MATCHES '*{1}'"}}else{format="{2} {0} "+format}filter=progress.util._format(format,operator,value,field)}else if(operator&&value===undefined){if(filter.operator==="isempty"||filter.operator==="isnotempty"){ablType=tableRef._getABLType(field);if(ablType!==CHARACTER_ABL_TYPE){throw new Error("Error parsing filter object. The operator "+filter.operator+" requires a CHARACTER field")}if(filter.operator==="isempty"){format="{2} = ''"}else if(filter.operator==="isnotempty"){format="{2} <> ''"}}else{if(filter.operator==="isnull"){format="{2} = ?"}else if(filter.operator==="isnotnull"){format="{2} <> ?"}else{format="{2} {0} ?"}}filter=progress.util._format(format,operator,value,field)}}result.push(filter)}filter=result.join(" "+logic+" ");if(result.length>1){filter="("+filter+")"}return filter};progress.util._convertToSQLQueryString=function(tableRef,filter,addSelect){var result=[],logic=filter.logic||"and",idx,length,field,type,format,operator,value,fieldFormat,filters=filter.filters||[filter],filterStr,usingLike=true,whereOperators={eq:"=",neq:"!=",gt:">",gte:">=",lt:"<",lte:"<=",contains:"LIKE",doesnotcontain:"NOT LIKE",endswith:"LIKE",startswith:"LIKE",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};if(typeof addSelect==="undefined"){addSelect=false}for(idx=0,length=filters.length;idx1){filterStr="("+filterStr+")"}if(addSelect===true){filterStr="SELECT * FROM "+tableRef._name+" WHERE "+filterStr}return filterStr};progress.util._getObjectType=function(value){return Object.prototype.toString.call(value).slice(8,-1)};progress.util._format=function(fmt){var values=arguments,formatRegExp=/\{(\d+)(:[^\}]+)?\}/g;return fmt.replace(formatRegExp,function(match,index,placeholderFormat){var value=values[parseInt(index,10)+1];return progress.util._toString(value,placeholderFormat?placeholderFormat.substring(1):"")})};progress.util._toString=function(value,fmt){var str;if(fmt){if(progress.util._getObjectType(value)==="Date"){return progress.util._formatDate(value,fmt)}}if(typeof value==="number"){str=value.toString()}else{str=value!==undefined?value:""}return str};progress.util._pad=function(number,digits){var zeros=["","0","00","000","0000"],end;number=String(number);digits=digits||2;end=digits-number.length;if(end){return zeros[digits].substring(0,end)+number}return number};progress.util._formatDate=function(date,format){var dateFormatRegExp=/dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g;return format.replace(dateFormatRegExp,function(match){var minutes,result,sign;if(match==="dd"){result=progress.util._pad(date.getDate())}else if(match==="MM"){result=progress.util._pad(date.getMonth()+1)}else if(match==="yyyy"){result=progress.util._pad(date.getFullYear(),4)}else if(match==="hh"){result=progress.util._pad(date.getHours())}else if(match==="mm"){result=progress.util._pad(date.getMinutes())}else if(match==="ss"){result=progress.util._pad(date.getSeconds())}else if(match==="fff"){result=progress.util._pad(date.getMilliseconds(),3)}else if(match==="FFF"){result=String(date.getTime())}else if(match==="zzz"){minutes=date.getTimezoneOffset();sign=minutes<0;result=(sign?"+":"-")+minutes}else if(match==="iso"){result=date.toISOString()}return result!==undefined?result:match.slice(1,match.length-1)})};progress.util.jsdoSettingsProcessor=function jsdoSettingsProcessor(jsdoSettings){if(typeof jsdoSettings==="object"){if(jsdoSettings.authenticationModel===undefined||jsdoSettings.authenticationModel===""){jsdoSettings.authenticationModel="ANONYMOUS"}}}})();(function(){var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS=20,PROGRESS_JSDO_OP_STRING=["none","create","read","update","delete","submit"],PROGRESS_JSDO_ROW_STATE_STRING=["","created","","modified","deleted"];if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data._nextid=0;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime());var UID_MAX_VALUE=999999999999999;progress.data._getNextId=function(){var uid=++progress.data._nextid;if(uid>=UID_MAX_VALUE){progress.data._nextid=uid=1;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime())}return progress.data._uidprefix+"-"+uid};var msg={};msg.msgs={};msg.msgs.jsdoMSG000="JSDO, Internal Error: {1}";msg.msgs.jsdoMSG001="JSDO: JSDO has multiple tables. Please use {1} at the table reference level.";msg.msgs.jsdoMSG002="JSDO: Working record for '{1}' is undefined.";msg.msgs.jsdoMSG003="JSDO: {1} function requires a function as a parameter.";msg.msgs.jsdoMSG004="JSDO: Unable to find resource '{1}' in the catalog.";msg.msgs.jsdoMSG005="JSDO: Data for table '{1}' was not specified in addRecords() call.";msg.msgs.jsdoMSG006="JSDO: Data for JSDO was not specified in addRecords() call.";msg.msgs.jsdoMSG007="JSDO: Test function in {1} must return a boolean.";msg.msgs.jsdoMSG008="JSDO: Invalid keyFields parameter in addRecords() call.";msg.msgs.jsdoMSG009="JSDO: KeyField '{1}' in addRecords() call was not found in the schema.";msg.msgs.jsdoMSG010="JSDO: Field '{1}' in relationship was not found in the schema.";msg.msgs.jsdoMSG011="UIHelper: JSDO has multiple tables. "+"Please use {1} at the table reference level.";msg.msgs.jsdoMSG012="UIHelper: Invalid {2} parameter in {1} call.";msg.msgs.jsdoMSG020="JSDO: tableName parameter must be a string in addRecords() call.";msg.msgs.jsdoMSG021="JSDO: addMode parameter must be specified in addRecords() call.";msg.msgs.jsdoMSG022="JSDO: Invalid addMode specified in addRecords() call.";msg.msgs.jsdoMSG023="JSDO: Duplicate found in addRecords() call using APPEND mode.";msg.msgs.jsdoMSG024="{1}: Unexpected signature in call to {2} function.";msg.msgs.jsdoMSG025="{1}: Invalid parameters in call to {2} function.";msg.msgs.jsdoMSG026="JSDO: saveChanges requires a "+"CREATE, UPDATE, DELETE or SUBMIT operation to be defined.";msg.msgs.jsdoMSG030="JSDO: Invalid {1}, expected {2}.";msg.msgs.jsdoMSG031="JSDO: Specified sort field name '{1}' was not found in the schema.";msg.msgs.jsdoMSG032="JSDO: Before-image data already exists for record in addRecords() call.";msg.msgs.jsdoMSG033="{1}: Invalid signature for {2}. {3}";msg.msgs.jsdoMSG034="JSDO: In '{1}' function, JSON data is missing _id";msg.msgs.jsdoMSG035="JSDO: In '{1}' function, before-image JSON data is missing prods:clientId";msg.msgs.jsdoMSG036="JSDO: '{1}' can only be called for a dataset";msg.msgs.jsdoMSG037="{1}: Event name must be provided for {2}.";msg.msgs.jsdoMSG038="Too few arguments. There must be at least {1}.";msg.msgs.jsdoMSG039="The name of the event is not a string.";msg.msgs.jsdoMSG040="The event listener is not a function.";msg.msgs.jsdoMSG041="The event listener scope is not an object.";msg.msgs.jsdoMSG042="'{1}' is not a defined event for this object.";msg.msgs.jsdoMSG043="{1}: A session object was requested to check the status of a Mobile "+"Service named '{2}', but it has not loaded the definition of that service.";msg.msgs.jsdoMSG044="JSDO: In '{1}' function, {2} is missing {3} property.";msg.msgs.jsdoMSG045="JSDO: {1} function: {2} is missing {3} property.";msg.msgs.jsdoMSG046="JSDO: {1} operation is not defined.";msg.msgs.jsdoMSG047="{1} timeout expired.";msg.msgs.jsdoMSG048="{1}: {2} method has argument '{3}' that is missing property '{4}'.";msg.msgs.jsdoMSG049="{1}: Unexpected error calling {2}: {3}";msg.msgs.jsdoMSG050="No token returned from server";msg.msgs.jsdoMSG051="{1} The login method was not executed because the AuthenticationProvider is already logged in.";msg.msgs.jsdoMSG052="{1}: The login method was not executed because no credentials were supplied.";msg.msgs.jsdoMSG053="{1}: {2} was not executed because the AuthenticationProvider is not logged in.";msg.msgs.jsdoMSG054="{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token.";msg.msgs.jsdoMSG055="{1}: Token refresh was not executed because the authentication model is not sso.";msg.msgs.jsdoMSG056="{1}: Already logged in.";msg.msgs.jsdoMSG057="{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead.";msg.msgs.jsdoMSG058="{1}: Cannot pass username and password to addCatalog when authenticationModel "+"is sso. Pass an AuthenticationProvider instead.";msg.msgs.jsdoMSG059="{1}: Error in constructor. The authenticationModels of the "+"AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible.";msg.msgs.jsdoMSG060="AuthenticationProvider: AuthenticationProvider is no longer logged in. "+"Tried to refresh SSO token but failed due to authentication error at token server.";msg.msgs.jsdoMSG061="{1}: Attempted to set {2} property to an invalid value.";msg.msgs.jsdoMSG062="{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in.";msg.msgs.jsdoMSG100="JSDO: Unexpected HTTP response. Too many records.";msg.msgs.jsdoMSG101="Network error while executing HTTP request.";msg.msgs.jsdoMSG110="Catalog error: idProperty not specified for resource '{1}'. "+"idProperty is required {2}.";msg.msgs.jsdoMSG111="Catalog error: Schema '{1}' was not found in catalog.";msg.msgs.jsdoMSG112="Catalog error: Output parameter '{1}' was not found for operation '{2}'.";msg.msgs.jsdoMSG113="Catalog error: Found xType '{1}' for output parameter '{2}' "+"for operation '{3}' but xType DATASET, TABLE or ARRAY was expected.";msg.msgs.jsdoMSG114="JSDO: idProperty '{1}' is missing from '{2}' record.";msg.msgs.jsdoMSG115="JSDO: Invalid option specified in {1}() call.";msg.msgs.jsdoMSG116="JSDO: {1} parameter must be a string in {2} call.";msg.msgs.jsdoMSG117="JSDO: Schema from storage area '{1}' does not match JSDO schema";msg.msgs.jsdoMSG118="JSDO: Plugin '{1}' was not found.";msg.msgs.jsdoMSG119="JSDO: A mappingType is expected when 'capabilities' is set."+" Please specify a plugin (ex: JFP).";msg.msgs.jsdoMSG120="JSDO: Parameter '{2}' requires capability '{1}' in the catalog.";msg.msgs.jsdoMSG121="{1}: Argument {2} must be of type {3} in {4} call.";msg.msgs.jsdoMSG122="{1}: Incorrect number of arguments in {2} call. There should be {3}.";msg.msgs.jsdoMSG123="{1}: A server response included an invalid '{2}' header.";msg.msgs.jsdoMSG124="JSDO: autoApplyChanges is not supported for saveChanges(true) "+"with a temp-table. Use jsdo.autoApplyChanges = false.";msg.msgs.jsdoMSG125="{1}: The AuthenticationProvider is not managing valid credentials.";msg.msgs.jsdoMSG126="{1}: No support for {2}.";msg.msgs.jsdoMSG127="JSDO: acceptRowChanges() cannot be called for record with _rejected === true.";msg.msgs.jsdoMSG500="{1}: '{2}' objects must contain a '{3}' property.";msg.msgs.jsdoMSG501="{1}: '{2}' in '{3}' function cannot be an empty string.";msg.msgs.jsdoMSG502="{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for "+"its '{4}' property.";msg.msgs.jsdoMSG503="{1}: '{2}' must be of type '{3}'.";msg.msgs.jsdoMSG504="{1}: {2} has an invalid value for the '{3}' property.";msg.msgs.jsdoMSG505="{1}: '{2}' objects must have a '{3}' method.";msg.msgs.jsdoMSG506="{1}: Invalid argument for the {2} parameter in {3} call.";msg.msgs.jsdoMSG507="{1}: '{2}' is an invalid value for the {3} parameter in {4} call.";msg.msgs.jsdoMSG508="JSDOSession: If a JSDOSession object is using the SSO authentication model, "+"the options object passed to its constructor must include an authProvider property.";msg.msgs.jsdoMSG509="progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, "+"authenticationURI and authProviderAuthenticationModel are required parameters.";msg.msgs.jsdoMSG510="{1}: This session has been invalidated and cannot be used.";msg.msgs.jsdoMSG511="JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or "+"connect() has been successfully called.";msg.msgs.jsdoMSG512="JSDOSession: Error while loading multiple catalogs.";msg.msgs.jsdoMSG998="JSDO: JSON object in addRecords() must be DataSet or Temp-Table data.";msg.getMsgText=function(n,args){var text=msg.msgs[n],i;if(!text){throw new Error("Message text was not found by getMsgText()")}for(i=1;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true;data=newDataArray}else{if(params&&(params.sort||params.top)){newDataArray=[];for(i=0;i0){sortObject.tableRef=this;data.sort(this._getCompareFn(sortObject))}}if(params.top){if(typeof params.skip=="undefined"){params.skip=0}data=data.splice(params.skip,params.top)}}return data};this._recToDataObject=function(record,includeChildren){var array=[record];var dataObject=array;if(typeof includeChildren=="undefined"){includeChildren=false}if(this._jsdo._dataSetName){dataObject={};dataObject[this._jsdo._dataSetName]={};dataObject[this._jsdo._dataSetName][this._name]=array;if(includeChildren&&this._children.length>0){var jsrecord=this._findById(record._id,false);if(jsrecord){for(var i=0;i0){for(var j=0;j0){for(var i=0;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true};this._equalRecord=function(rec1,rec2,keyFields){var field;var match=true;for(var i=0;ivalue2||(value1===undefined||value1===null))return sortAscending[i]?1:-1;else if(value10)this._sort(sortObject)}else{this._sort(arg1)}this._createIndex()};this._sort=function(arg1){if(arguments.length===0&&(!this.autoSort||this._sortFn===undefined&&this._sortObject.sortFields===undefined))return;if(arguments.length===0){if(this._sortFn){this._data.sort(this._sortFn)}else{this._data.sort(this._compareFields)}this._needsAutoSorting=false}else{if(typeof arg1=="function"){this._data.sort(this._getCompareFn(arg1))}else{arg1.tableRef=this;this._data.sort(this._getCompareFn(arg1))}if(this.autoSort)this._needsAutoSorting=true}};this.addRecords=function(jsonObject,addMode,keyFields,trackChanges,isInvoke){this._jsdo._addRecords(this._name,jsonObject,addMode,keyFields,trackChanges,isInvoke)};this.acceptChanges=function(){var tableRef=this;for(var id in tableRef._beforeImage){if(tableRef._beforeImage[id]===null){var jsrecord=tableRef._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}else if(this._changed[id]!==undefined){var jsrecord=this._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}}tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[];tableRef._beforeImage={}};this.rejectChanges=function(){for(var id in this._beforeImage){if(this._beforeImage[id]===null){this._jsdo._undoCreate(this,id)}else if(this._changed[id]!==undefined){this._jsdo._undoUpdate(this,id,true)}else{this._jsdo._undoDelete(this,id,true)}}var tableRef=this;tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[]};this.hasChanges=function(){return Object.keys(this._beforeImage).length!==0};this.getChanges=function(){var result=[];for(var id in this._beforeImage){var item={rowState:"",record:null};if(this._beforeImage[id]===null){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE];item.record=this._findById(id,false)}else if(this._changed[id]!==undefined){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE];item.record=this._findById(id,false)}else{item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE];item.record=new progress.data.JSRecord(this,this._beforeImage[id])}result.push(item)}return result};this._clearErrorStrings=function(){var record=null;for(var id in this._beforeImage){if(this._beforeImage[id]===null){record=this._findById(id,false);if(record){delete record.data._errorString}}else{record=this._findById(id,false);if(record){delete record.data._errorString}else{delete this._beforeImage[id]._errorString}}}};this._applyChanges=function(){var i;for(var id in this._beforeImage){if(this._beforeImage[id]===null){var jsrecord=this._findById(id,false);if(jsrecord===null&&this._jsdo._resource.idProperty!==undefined){if(this._tmpIndex[id]){var record=this._data[this._tmpIndex[id].index];jsrecord=record?new progress.data.JSRecord(this,record):null;delete this._tmpIndex[id]}}if(jsrecord!==null){if(jsrecord.data._rejected||jsrecord.data._errorString!==undefined){this._jsdo._undoCreate(this,id)}else{jsrecord.acceptRowChanges()}}else{var found=false;for(var i=0;i0){for(var i=0;iindex){i--}if(i!=index){this._tableRef._data.splice(index,1);this._tableRef._data.splice(i,0,record);this._tableRef._createIndex()}}}};this.assign=function(record){if(record===undefined)throw new Error(msg.getMsgText("jsdoMSG024","JSDO","assign() or update()"));this._saveBeforeImageUpdate();var fieldName,i,j,value,schema=this._tableRef.getSchema(),prefixElement,name;if(record){for(i=0;i0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){return this.record.data[name][element-1]}}return this.record.data[fieldName]}else return null},set:function(value){var name=fieldName,index,element,fieldInfo;if(this.record){this.record._saveBeforeImageUpdate();try{index=fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR);if(index>0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){this.record.data[name][element-1]=value;return}}this.record.data[fieldName]=value}finally{this.record._sortRecord(name)}}},enumerable:true,writeable:true})};Object.defineProperty(this,"hasSubmitOperation",{get:function(){return this._hasSubmitOperation},enumerable:true});Object.defineProperty(this,"hasCUDOperations",{get:function(){return this._hasCUDOperations},enumerable:true});Object.defineProperty(this,"defaultTableRef",{get:function(){return this._defaultTableRef},enumerable:true});this._buffers={};this._numBuffers=0;this._defaultTableRef=null;this._async=true;this._dataProperty=null;this._dataSetName=null;this.operations=[];this.useRelationships=true;this._session=null;this._needCompaction=false;this._hasCUDOperations=false;this._hasSubmitOperation=false;this._useSubmit=false;this.autoApplyChanges=true;this._lastErrors=[];this._localStorage=null;this._convertForServer;this._fillMergeMode;var autoFill=false;if(!arguments[0]){throw new Error("JSDO: Parameters are required in constructor.")}if(typeof arguments[0]=="string"){this.name=arguments[0]}else if(typeof arguments[0]=="object"){var args=arguments[0];for(var v in args){switch(v){case"autoFill":autoFill=args[v];break;case"events":this._events={};for(var eventName in args[v]){this._events[eventName.toLowerCase()]=args[v][eventName]}break;case"dataProperty":this._dataProperty=args[v];break;default:this[v]=args[v]}}}if(!this.name){throw new Error("JSDO: JSDO constructor is missing the value for 'name'")}if(this._events){if(typeof this._events!=="object"){throw new Error("JSDO: JSDO constructor event object is not defined as an object")}for(var prop in this._events){var evt=this._events[prop];if(!(evt instanceof Array)){throw new Error("JSDO: JSDO constructor event object for "+prop+" must be an array")}evt.forEach(function(el){if(typeof el!=="object"){throw new Error("JSDO: JSDO constuctor event object for "+prop+" is not defined as an object")}if(typeof el.fn!=="function"){throw new Error("JSDO: JSDO event listener for "+prop+" is not a function.")}if(el.scope&&typeof el.scope!=="object"){throw new Error("JSDO: JSDO event listener scope for "+prop+" is not an object.")}})}}if(this.name){this._resource=progress.data.ServicesManager.getResource(this.name);if(this._resource){if(!this.url)this.url=this._resource.url;if(!this._dataSetName&&this._resource._dataSetName){this._dataSetName=this._resource._dataSetName;if(this._resource.dataProperty){var buffer=this[this._resource.dataProperty]=new progress.data.JSTableRef(this,this._resource.dataProperty);this._buffers[this._resource.dataProperty]=buffer}else{for(var tableName in this._resource.fields){var buffer=this[tableName]=new progress.data.JSTableRef(this,tableName);this._buffers[tableName]=buffer}}}if(!this._dataProperty&&this._resource.dataProperty)this._dataProperty=this._resource.dataProperty;if(!this._dataSetName){var tableName=this._dataProperty?this._dataProperty:"";this._buffers[tableName]=new progress.data.JSTableRef(this,tableName);if(tableName)this[tableName]=this._buffers[tableName]}var properties,tableName;if(this._dataSetName&&this._resource.schema&&this._resource.schema.properties[this._dataSetName]){properties=this._resource.schema.properties[this._dataSetName].properties;if(Object.keys(properties).length===1){tableName=Object.keys(properties)[0];if(properties[tableName].idProperty){this._resource.idProperty=properties[tableName].idProperty}}}for(var fnName in this._resource.fn){this[fnName]=this._resource.fn[fnName]["function"]}this._hasCUDOperations=this._resource.generic["create"]!==undefined||this._resource.generic["update"]!==undefined||this._resource.generic["delete"]!==undefined;this._hasSubmitOperation=this._resource.generic["submit"]!==undefined;if(!this._session){var myservice=progress.data.ServicesManager.getService(this._resource.service.name);this._session=myservice._session;this._session._pushJSDOs(this)}}else{throw new Error(msg.getMsgText("jsdoMSG004",this.name))}}else{this._buffers[""]=new progress.data.JSTableRef(this,"")}if(!this._session){throw new Error("JSDO: Unable to get user session for resource '"+this.name+"'")}for(var buf in this._buffers){this._buffers[buf]._parent=null;this._buffers[buf]._children=[];this._buffers[buf]._relationship=null;this._buffers[buf]._isNested=false;if(!this._defaultTableRef)this._defaultTableRef=this._buffers[buf];this._numBuffers++}if(this._numBuffers!=1)this._defaultTableRef=null;else{this.record=null}if(typeof Object.defineProperty=="function"){this._caseSensitive=false;Object.defineProperty(this,"caseSensitive",{get:function(){return this._caseSensitive},set:function(value){this._caseSensitive=value?true:false;for(var buf in this._buffers){this._buffers[buf].caseSensitive=this._caseSensitive}},enumerable:true,writeable:true});this._autoSort=true;Object.defineProperty(this,"autoSort",{get:function(){return this._autoSort},set:function(value){this._autoSort=value?true:false;for(var buf in this._buffers){this._buffers[buf].autoSort=this._autoSort}},enumerable:true,writeable:true})}this._properties={};if(typeof Object.defineProperty=="function"){Object.defineProperty(this,"this._properties",{get:function(){return this._properties},enumerable:false})}if(this._resource&&this._resource.fields){for(var buf in this._buffers){this._buffers[buf]._schema=this._resource.fields[buf];this._buffers[buf]._primaryKeys=this._resource.primaryKeys[buf];this._buffers[buf]._fields={};var fields=this._buffers[buf]._schema;for(var i=0;i1){for(var buf in this._buffers){var fields=[];var found=false;for(var i=0;i=0?index+1:"");element.value=value?value[index]:undefined;return element};this.isDataSet=function(){return this._dataSetName?true:false};this._invokeComplete=function(jsdo,success,request){if(request.async&&request.fnName){jsdo.trigger("afterInvoke",request.fnName,jsdo,success,request)}if(request.deferred){if(success){request.deferred.resolve(jsdo,success,request)}else{request.deferred.reject(jsdo,success,request)}}};this._invokeSuccess=function(){};this._invokeError=function(){};this._httpRequest=function(xhr,method,url,reqBody,request){function afterOpenRequest(){var input=null;if(reqBody){xhr.setRequestHeader("Content-Type","application/json; charset=utf-8");input=JSON.stringify(reqBody)}try{xhr.send(input)}catch(e){request.success=false;request.exception=e;xhr.jsdo._session._checkServiceResponse(xhr,request.success,request)}}if(!xhr){xhr=new XMLHttpRequest;xhr.onCompleteFn=this._invokeComplete;xhr.onSuccessFn=this._invokeSuccess;xhr.onErrorFn=this._invokeError;xhr.onreadystatechange=this.onReadyStateChangeGeneric;if(request.async&&request.fnName){this.trigger("beforeInvoke",request.fnName,this,request)}if(reqBody){if(this._resource&&this._resource.service){var useRequest=this._resource.service.useRequest;if(this._resource.service.settings&&this._resource.service.settings.useRequest!==undefined){useRequest=this._resource.service.settings.useRequest}if(useRequest){reqBody={request:reqBody}}}}}xhr.request=request;xhr.jsdo=this;request.jsdo=this;request.xhr=xhr;this._session._openRequest(xhr,method,url,request.async,afterOpenRequest);return request};this._getDataObject=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};var oldUseRelationships=this.useRelationships;try{this.useRelationships=false;for(var buf in this._buffers){dataObject[this._dataSetName][buf]=this._buffers[buf].getData()}}finally{this.useRelationships=oldUseRelationships}}else{if(this._dataProperty){dataObject[this._dataProperty]=this.getData()}else return this.getData()}return dataObject};this._getDataObjectAsNested=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};try{for(var buf in this._buffers){var bufObj=this._buffers[buf];if(bufObj._isNested)continue;this._nestChildren=false;if(bufObj._children.length>0){for(var i=0;i0){hasErrors=true}}if(hasErrors){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._allRecordsRejected=true;this._someRecordsRejected=false;hasCommittedRecords=false;for(i=0;i0&&!param.operations[0].success){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._convertForServer=true;this._buffers[buf]._convertForServer=true}}};this._convertRequestData=function(objParam){var buf,beforeData;if(this._convertForServer===false){return}for(buf in this._buffers){if(this._buffers[buf]._convertForServer){if(objParam[this._dataSetName]){if(objParam[this._dataSetName][buf]){this._convertTableData(this._buffers[buf],objParam[this._dataSetName][buf])}beforeData=objParam[this._dataSetName]["prods:before"];if(beforeData&&beforeData[buf]){this._convertTableData(this._buffers[buf],beforeData[buf])}}else if(objParam[buf]){this._convertTableData(this._buffers[buf],objParam[buf])}}}};this._convertTableData=function(tableRef,tableData){var i;for(i=0;i0){this._confirmOperationExists(progress.data.JSDO._OP_DELETE);checkedDelete=true}if(!checkedCreate&&tableRef._added.length>0){this._confirmOperationExists(progress.data.JSDO._OP_CREATE);checkedCreate=true}if(!checkedUpdate&&Object.keys(tableRef._changed).length>0){this._confirmOperationExists(progress.data.JSDO._OP_UPDATE);checkedUpdate=true}if(checkedDelete&&checkedCreate&&checkedUpdate){break}}};this._confirmOperationExists=function(operation){var operationStr=PROGRESS_JSDO_OP_STRING[operation];if(typeof this._resource.generic[operationStr]!=="function"){throw new Error(msg.getMsgText("jsdoMSG046",operationStr.toUpperCase()))}};this.invoke=function(name,object){var deferred,promise;try{var request=this[name](object);if(request.deferred){deferred=request.deferred;promise=request.deferred.promise()}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{if(!deferred){deferred=new progress.util.Deferred;promise=deferred.promise()}deferred.reject(this,false,{errorObject:error})}}return promise};this._syncTableRef=function(operation,tableRef,batch){var rowData,requestData,jsonObject,dataSetObject;if(tableRef._visited)return;tableRef._visited=true;if(!batch){batch={operations:[]}}else if(!batch.operations){batch.operations=[]}switch(operation){case progress.data.JSDO._OP_CREATE:for(var i=0;i0&&!dataSetJsonObject[tableRef._name])dataSetJsonObject[tableRef._name]=[];for(var i=0;i0||tableRef._added.length>0||hasUpdates){hasChanges=true;break}}return hasChanges};this._addDeletesToChangeSet=function(tableRef,dataSetJsonObject,request){for(var i=0;i=10){tmpIndex={};for(var i=0;ivalue2||value1===null)return false;else if(value11){for(var buf in this._buffers){if(this._buffers[buf]._isNested&&this._buffers[buf]._parent&&this._buffers[this._buffers[buf]._parent]){var srcData=this._buffers[this._buffers[buf]._parent]._data;var data=[];for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}var recordId=beforeTableJsonObject[0]["prods:clientId"];if(!recordId){throw new Error(msg.getMsgText("jsdoMSG035","_checkForDeleteError()"))}if(beforeTableJsonObject[0]["prods:hasErrors"]){var prods_id=beforeTableJsonObject[0]["prods:id"];var errorString=this._getErrorStringFromJsonObject(dataSetJsonObject,tableRef,prods_id);this._setErrorString(tableRef,recordId,errorString,true);hasError=true}}return hasError};this._mergeUpdateForSubmit=function(jsonObject,xhr){var errorString;if(!this._dataSetName){throw new Error(msg.getMsgText("jsdoMSG036","_mergeUpdateForSubmit()"))}var dataSetJsonObject=jsonObject[this._dataSetName];if(dataSetJsonObject[this._dataSetName])dataSetJsonObject=dataSetJsonObject[this._dataSetName];var beforeJsonObject=dataSetJsonObject["prods:before"];for(var buf in this._buffers){var tableRef=this._buffers[buf];var tableJsonObject=dataSetJsonObject[tableRef._name];if(tableJsonObject instanceof Array){for(var i=0;i1){request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}}if(beforeJsonObject){hasError=jsdo._checkForDeleteError(dataSetJsonObject,xhr)}if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._deleteError(jsdo,success,request)}}};this._deleteError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoDelete(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._createComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterCreate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterCreate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._createSuccess=function(jsdo,success,request){var xhr=request.xhr;var record=request.response;var hasError=jsdo._mergeUpdateForCUD(record,xhr);if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._createError(jsdo,success,request)}}};this._createError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoCreate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._updateComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterUpdate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterUpdate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._updateSuccess=function(jsdo,success,request){var xhr=request.xhr;var hasError=jsdo._mergeUpdateForCUD(request.response,xhr);if(hasError){request.success=false}if(jsdo.autoApplyChanges){if(!hasError){request.success=true;delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._updateError(jsdo,success,request)}}};this._updateError=function(jsdo,success,request){if(jsdo.autoApplyChanges){request.success=false;jsdo._undoUpdate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._saveChangesSuccess=function(jsdo,success,request){var records=request.response;jsdo._mergeUpdateForSubmit(records,request.xhr);jsdo._clearErrors();var changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(changes);if(jsdo.autoApplyChanges){jsdo._applyChanges()}};this._saveChangesError=function(jsdo,success,request){jsdo._setAllRecordsRejected(true);if(jsdo.autoApplyChanges){jsdo.rejectChanges()}jsdo._updateLastErrors(jsdo,null,null,request)};this._saveChangesSuccessTT=function(jsdo,success,request){var changes;jsdo._clearErrors();changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(false)};this._saveChangesComplete=function(jsdo,success,request){if(request.xhr.status>=200&&request.xhr.status<300&&(jsdo._lastErrors.length>0||jsdo._someRecordsRejected)){request.success=false}if(jsdo._useSubmit===true){jsdo._fireCUDTriggersForSubmit(request)}jsdo._undefWorkingRecord();jsdo._fireAfterSaveChanges(request.success,request)};this._fireAfterSaveChanges=function(success,request){this.trigger("afterSaveChanges",this,success,request);if(request.jsrecords){if(request.deferred){if(success){request.deferred.resolve(this,success,request)}else{request.deferred.reject(this,success,request)}}}else if(request.batch&&request.batch.deferred){if(success){request.batch.deferred.resolve(this,success,request)}else{request.batch.deferred.reject(this,success,request)}}var clearErrorString=this.autoApplyChanges;if(request.jsrecords){for(var idx=0;idx=400&&request.xhr.status<600){try{var responseObject=JSON.parse(request.xhr.responseText);if(responseObject instanceof Array){errorArray=responseObject}else if(responseObject instanceof Object){errorArray.push(responseObject)}for(i=0;i=400&&request.xhr.status<600)){errors.push({type:progress.data.JSDO.ERROR,error:"Error: HTTP Status "+request.xhr.status+" "+request.xhr.statusText,responseText:request.xhr.responseText})}}return errors};this._updateLastErrors=function(jsdo,batch,changes,request){var errors,errorText,responseObject,i,j,buf;if(batch){if(batch.operations===undefined)return;for(i=0;i=200&&request.xhr.status<300){jsdo._lastErrors.push({errorString:request.jsrecord.data._errorString});jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({type:progress.data.JSDO.DATA_ERROR,id:request.jsrecord.data._id,error:request.jsrecord.data._errorString})}else{errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}if(request.jsrecord&&(errors[j].type===progress.data.JSDO.APP_ERROR||errors[j].type===progress.data.JSDO.RETVAL)){errors[j].id=request.jsrecord.data._id;request.jsrecord._tableRef._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}}}}else if(changes instanceof Array){for(i=0;i=400&&request.xhr.status<600||request.xhr.status===0)){errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}for(buf in this._buffers){this._buffers[buf]._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}};this._checkSaveComplete=function(xhr){if(xhr.request){var jsdo=xhr.request.jsdo;var batch=xhr.request.batch;if(jsdo&&batch&&jsdo._async){if(jsdo._isBatchComplete(batch)){var success=jsdo._isBatchSuccess(batch);var request={batch:batch,success:success};jsdo._undefWorkingRecord();jsdo._lastErrors=[];if(!success&&batch.operations){jsdo._updateLastErrors(jsdo,batch,null)}this._setAllRecordsRejected(batch);jsdo._fireAfterSaveChanges(success,request)}}}};this._isBatchSuccess=function(batch){if(batch.operations){for(var i=0;i=200&&xhr.status<300||xhr.status===0&&xhr.responseText!==""){request.success=true;xhr.jsdo._session._saveClientContextId(xhr);if(typeof xhr.onSuccessFn=="function"){var operation;if(xhr.request.fnName!==undefined&&xhr.jsdo._resource.fn[xhr.request.fnName]!==undefined){operation=xhr.jsdo._resource.fn[xhr.request.fnName].operation}else operation=null;if(operation===undefined||operation!==null&&operation.mergeMode)xhr.jsdo._mergeInvoke(request.response,xhr);if(request.success)xhr.onSuccessFn(xhr.jsdo,request.success,request);else if(typeof xhr.onErrorFn=="function")xhr.onErrorFn(xhr.jsdo,request.success,request)}}else{request.success=false;if(xhr.status===0){request.exception=new Error(msg.getMsgText("jsdoMSG101"))}if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}}catch(e){request.success=false;request.exception=e;if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}xhr.jsdo._session._checkServiceResponse(xhr,request.success,request);if(typeof xhr.onCompleteFn=="function"){xhr.onCompleteFn(xhr.jsdo,request.success,request)}}};this.acceptChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].acceptChanges()}};this.rejectChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].rejectChanges()}};this.getChanges=function(){var result=[];for(var buf in this._buffers){var changes=this._buffers[this._buffers[buf]._name].getChanges();result=result.concat(changes)}return result};this.hasChanges=function(){for(var buf in this._buffers){if(this._buffers[this._buffers[buf]._name].hasChanges())return true}return false};this._applyChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name]._applyChanges()}};this.acceptRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.acceptRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","acceptRowChanges()"))};this.rejectRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.rejectRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","rejectRowChanges()"))};this.setProperties=function(propertiesObject){var prop;if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(typeof propertiesObject=="object"){this._properties={};for(prop in propertiesObject){if(propertiesObject.hasOwnProperty(prop)){if(typeof propertiesObject[prop]!=="function"){this._properties[prop]=propertiesObject[prop]}}}}else if(propertiesObject===undefined||propertiesObject===null){this._properties={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"Object","setProperties"))}};this.setProperty=function(propertyName,propertyValue){if(arguments.length<2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(arguments.length!==2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(typeof propertyName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"string","setProperty"))}if(propertyValue===undefined){delete this._properties[propertyName]}else{this._properties[propertyName]=propertyValue}};this.getProperties=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperties",0))}return this._properties};this.getProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}return this._properties[propertyName]};this.saveLocal=function saveLocal(arg1,arg2){var name;var dataMode;if(arguments.length>2){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"||arg1===null||arg1===undefined){name=arg1;dataMode=arg2}else{name=null;dataMode=arg1}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}if(typeof dataMode=="undefined"){dataMode=progress.data.JSDO.ALL_DATA}else{switch(dataMode){case progress.data.JSDO.ALL_DATA:case progress.data.JSDO.CHANGES_ONLY:break;default:throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var dataObj=this._prepareDataObjectForLocalStorage(dataMode);this._localStorage.saveToLocalStorage(name,dataObj)};this.readLocal=function readLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));this._restoreFromLocalStorage(object,progress.data.JSDO.MODE_EMPTY)}return object!==null};this.addLocalRecords=function addLocalRecords(arg1,arg2,arg3){var name;var addMode;var keyFields;if(arguments.length<1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"){name=arg1;addMode=arg2;keyFields=arg3}else{name="jsdo_"+this._resource.service.name+"_"+this._resource.name;addMode=arg1;keyFields=arg2}if(typeof name=="undefined"||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(addMode!=progress.data.JSDO.MODE_REPLACE){throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));try{this._restoreFromLocalStorage(object,addMode,keyFields)}catch(e){var text=e.message;throw new Error(text.replace(new RegExp("addRecords","g"),"addLocalRecords"))}}return object!==null};this._containsPrimaryKeys=function _containsPrimaryKeys(){for(var buf in this._buffers){if(this._buffers[buf]._primaryKeys===null)return false}return true};this._hasMatchingSchema=function _hasMatchingSchema(storageObject){var isValid=true;if(storageObject===null||Object.keys(storageObject).length===0)return true;if(this._dataSetName){if(storageObject[this._dataSetName]){for(var buf in this._buffers)if(storageObject[this._dataSetName][buf]===undefined){isValid=false;break}}else isValid=false}else if(this._dataProperty){storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._dataProperty]===undefined)isValid=false}else{storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._defaultTableRef._name]===undefined)isValid=false}return isValid};this.deleteLocal=function deleteLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}this._localStorage.clearLocalStorage(name)};this._prepareDataObjectForLocalStorage=function(option){var storageObject={};if(this._dataSetName){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet(this._dataSetName);break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet(this._dataSetName,true);break}}else if(this._dataProperty){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}else{switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}return storageObject};this._restoreFromLocalStorage=function(storageObject,addMode,keyFields){if(storageObject&&Object.keys(storageObject).length>0){if(this._dataSetName){for(var buf in this._buffers)this._restoreDataForTable(this._buffers[buf],storageObject,addMode,keyFields)}else this._restoreDataForTable(this._defaultTableRef,storageObject,addMode,keyFields)}else if(addMode===progress.data.JSDO.MODE_EMPTY)this._clearData()};this._restoreDataForTable=function(tableRef,jsonObject,addMode,keyFields){keyFields=keyFields!==undefined?keyFields:tableRef._primaryKeys;if(keyFields===undefined&&this._resource.idProperty){keyFields=[];keyFields[0]=this._resource.idProperty}if(this._dataSetName){var oldUseRelationships=this.useRelationships;this.useRelationships=false;try{tableRef.addRecords(jsonObject,addMode,keyFields)}finally{this.useRelationships=oldUseRelationships}}else{this._dataSetName="_localStorage";tableRef.addRecords(jsonObject,addMode,keyFields);this._dataSetName=null}};this.getMethodProperties=function(operation,name){var idx;if(this._resource._operations){if(this._resource._operations[operation]){return this._resource._operations[operation]}}else{this._resource._operations={}}for(var idx=0;idx1?[params.sort]:[]}sortFields="";for(index=0;index=1?params.filter:undefined}if(params.filter){if(typeof params.filter==="string"){doConversion=false}params.tableRef=tableName;if(doConversion&¶ms.tableRef===undefined){throw new Error(msg.getMsgText("jsdoMSG045","fill() or read()","params","tableRef"))}if(reqCapabilities["filter"].mapping==="ablFilter"){if(doConversion){ablFilter=progress.util._convertToABLWhereString(jsdo._buffers[params.tableRef],params.filter)}else{ablFilter=params.filter}}else if(reqCapabilities["filter"].mapping==="sqlQuery"){if(doConversion){sqlQuery=progress.util._convertToSQLQueryString(jsdo._buffers[params.tableRef],params.filter,true)}else{sqlQuery=params.filter}}}filter=JSON.stringify({ablFilter:ablFilter,sqlQuery:sqlQuery,orderBy:sortFields,skip:params.skip,top:params.top,id:params.id});params={filter:filter}}return params}});if(typeof progress.ui=="undefined")progress.ui={};progress.ui.UITableRef=function UITableRef(tableRef){this._tableRef=tableRef;this._listview=null;this._detailPage=null;this._listviewContent=undefined;this.addItem=function(format){var detailForm;if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._name));if(!this._listview)return;format=format?format:this._listview.format;detailForm=this._detailPage&&this._detailPage.name?this._detailPage.name:"";if(this._listviewContent===undefined){this.clearItems()}var text=this._listview.itemTemplate?this._listview.itemTemplate:progress.ui.UIHelper._itemTemplate;text=text.replace(new RegExp("{__format__}","g"),format);text=text.replace(new RegExp("{__id__}","g"),this._tableRef.record.data._id);text=text.replace(new RegExp("{__page__}","g"),detailForm);for(var field in this._tableRef.record.data){var value=this._tableRef.record.data[field];text=text.replace(new RegExp("{"+field+"}","g"),value!==undefined&&value!==null?value:"")}this._listviewContent+=text};this.clearItems=function(){if(this._listview){this._listviewContent="";var listviewElement=document.getElementById(this._listview.name);if(listviewElement){listviewElement.innerHTML=""}}};this._getFormFieldValue=function(fieldName,detailPageName){var value=null,field;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)value=field.val()}else{field=document.getElementById(fieldName);if(field){value=field.value}}return value};this._setFormField=function(fieldName,value,detailPageName){var field=null;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)field.val(value)}else{field=document.getElementById(fieldName);if(field){field.value=value}}};this.assign=function(detailPageName){if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._tableRef._name));if(arguments.length!==0&&typeof detailPageName!="string")throw new Error(msg.getMsgText("jsdoMSG024","UIHelper","assign()"));this._tableRef.record.assign(null);var fieldName;var schema=this._tableRef.getSchema();for(var i=0;i0){for(var i=0;i0&&fieldName.charAt(0)=="_")continue;if(fields&&fields[fieldName]===undefined)continue;var fieldLabel=this._tableRef._schema[i].title?this._tableRef._schema[i].title:this._tableRef._schema[i].name;var text=this._detailPage&&this._detailPage.fieldTemplate?this._detailPage.fieldTemplate:progress.ui.UIHelper._fieldTemplate;text=text.replace(new RegExp("{__label__}","g"),fieldLabel);text=text.replace(new RegExp("{__name__}","g"),this._tableRef._schema[i].name);htmltext+=text}htmltext+="";fields=null;return htmltext};this.getListViewRecord=function(htmlIElement){var id=htmlIElement.getAttribute("data-id");return this._tableRef.findById(id)};this.getFormRecord=function(detailPageName){var id=this._getFormFieldValue("_id",detailPageName);return this._tableRef.findById(id)};this._getIdOfElement=function(name){if(typeof $=="function"){var element=$("#"+name);if(!element||element.length===0){element=$('[dsid="'+name+'"]');if(element&&element.length==1){var id=element.attr("id");if(id)return id}}}return name};this.setDetailPage=function setDetailPage(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));this._detailPage=obj;this._detailPage.name=this._getIdOfElement(this._detailPage.name)};this.setListView=function setListView(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));if(obj.format&&typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"format"));this._listview=obj;this._listview.name=this._getIdOfElement(this._listview.name);if(!this._listview.format){if(typeof $=="function"){for(var i=0;i{__format__}';progress.ui.UIHelper._defaultFieldTemplate='
    '+''+'
    ';progress.ui.UIHelper._itemTemplate=progress.ui.UIHelper._defaultItemTemplate;progress.ui.UIHelper._fieldTemplate=progress.ui.UIHelper._defaultFieldTemplate;progress.ui.UIHelper.setItemTemplate=function(template){progress.ui.UIHelper._itemTemplate=template?template:progress.ui.UIHelper._defaultItemTemplate};progress.ui.UIHelper.setFieldTemplate=function(template){progress.ui.UIHelper._fieldTemplate=template?template:progress.ui.UIHelper._defaultFieldTemplate}})();(function(){if(progress===undefined){progress={}}if(progress.data===undefined){progress.data={}}progress.data.ServicesManager={};progress.data.ServicesManager._services=[];progress.data.ServicesManager._resources=[];progress.data.ServicesManager._data=[];progress.data.ServicesManager._sessions=[];progress.data.ServicesManager._jsdosessions=[];progress.data.ServicesManager.addResource=function(id,resource){if(progress.data.ServicesManager._resources[id]===undefined){progress.data.ServicesManager._resources[id]=resource}else{throw new Error("A resource named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getResource=function(id){return progress.data.ServicesManager._resources[id]};progress.data.ServicesManager.addService=function(id,service){if(progress.data.ServicesManager._services[id]===undefined){progress.data.ServicesManager._services[id]=service}else{throw new Error("A service named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getService=function(id){return progress.data.ServicesManager._services[id]};progress.data.ServicesManager.addSession=function(catalogURI,session){if(progress.data.ServicesManager._sessions[catalogURI]===undefined){progress.data.ServicesManager._sessions[catalogURI]=session}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.addJSDOSession=function(catalogURI,jsdosession){if(progress.data.ServicesManager._jsdosessions[catalogURI]===undefined){progress.data.ServicesManager._jsdosessions[catalogURI]=jsdosession}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.getSession=function(catalogURI){try{return progress.data.ServicesManager._sessions[catalogURI]}catch(e){return null}};progress.data.ServicesManager.cleanSession=function(session){var servicesKey,resourcesKey,sessionsKey,service,services=progress.data.ServicesManager._services,resources=progress.data.ServicesManager._resources,sessions=progress.data.ServicesManager._sessions,jsdosessions=progress.data.ServicesManager._jsdosessions;for(servicesKey in services){service=null;if(services[servicesKey]._session===session){service=services[servicesKey];delete services[servicesKey]}if(!service){continue}for(resourcesKey in resources){if(resources[resourcesKey].service===service){delete resources[resourcesKey]}}}for(sessionsKey in sessions){if(sessions[sessionsKey]===session){delete sessions[sessionsKey];if(jsdosessions[sessionsKey]){delete jsdosessions[sessionsKey]}}}};function extractParamsFromURL(url){var urlParams=[],paramName=null;if(typeof url==="string"){url.split("").forEach(function(c){if(c==="{"){paramName=""}else if(c==="}"){if(paramName){urlParams.push(paramName)}paramName=null}else if(paramName!==null){paramName+=c}})}return urlParams}progress.data.ServicesManager.addCatalog=function(services,session){var name,value;if(!services){throw new Error("Cannot find 'services' property in catalog file.")}if(services instanceof Array){services.forEach(function(service){if(progress.data.ServicesManager.getService(service.name)!==undefined){throw new Error("A service named '"+service.name+"' was already loaded.")}if(service.resources instanceof Array){service.resources.forEach(function(resource){if(progress.data.ServicesManager.getResource(resource.name)!==undefined){throw new Error("A resource named '"+resource.name+"' was already loaded.")}})}else{throw new Error("Missing 'resources' array in catalog.")}});for(var j=0;j1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","setContext",1))}if(typeof context==="object"){contextObject={};for(prop in context){if(context.hasOwnProperty(prop)){if(typeof context[prop]!=="function"){contextObject[prop]=context[prop]}}}}else if(context===undefined||context===null){contextObject={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","Session",1,"Object","setContextProperty"))}contextString=null};this.getContext=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContext",0))}return contextObject};this.getContextProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}return contextObject[propertyName]}};progress.data.Session=function Session(options){var defPropSupported=false;if(typeof Object.defineProperty==="function"){defPropSupported=true}var that=this,jsdosession,isUserAgentiOS=false,isFirefox=false,isEdge=false,isIE=false,canPassCredentialsToOpenWithCORS=false,defaultiOSBasicAuthTimeout=4e3,deviceIsOnline=true,restApplicationIsOnline=false,oepingAvailable=false,defaultPartialPingURI="/rest/_oeping",partialPingURI=defaultPartialPingURI,_storageKey,_authProvider=null,customCredentials=false,storedAuthModel,storedURI,newURI,stateWasReadFromStorage=false;if(!options||options._silent!==true){console.warn("Session: As of JSDO 4.4, the Session object has been deprecated. "+"Please use the JSDOSession object instead.")}if(typeof navigator!=="undefined"){if(typeof navigator.userAgent!=="undefined"){isUserAgentiOS=navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i);isFirefox=navigator.userAgent.toLowerCase().indexOf("firefox")>-1;isEdge=navigator.userAgent.indexOf("Edge/")>-1;isIE=navigator.userAgent.indexOf("Trident/")>-1||navigator.userAgent.indexOf("MSIE 10")>-1}}canPassCredentialsToOpenWithCORS=!(isFirefox||isEdge||isIE);function canPassCredentialsToOpen(){return canPassCredentialsToOpenWithCORS}this._onlineHandler=function(){setDeviceIsOnline(true);that.trigger("online",that,null)};this._offlineHandler=function(){setDeviceIsOnline(false);that.trigger("offline",that,progress.data.Session.DEVICE_OFFLINE,null)};if(typeof window!=="undefined"&&window.addEventListener){window.addEventListener("online",this._onlineHandler,false);window.addEventListener("offline",this._offlineHandler,false)}var _catalogURIs=[];var _services=[];var _jsdos=[];this.onOpenRequest=null;var _password=null;if(defPropSupported){var _userName=null;Object.defineProperty(this,"userName",{get:function(){return _userName},enumerable:true});var _loginTarget="/static/home.html";Object.defineProperty(this,"loginTarget",{get:function(){return _loginTarget},enumerable:true});var _serviceURI=null;Object.defineProperty(this,"serviceURI",{get:function(){return _serviceURI},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _catalogURIs},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _services},enumerable:true});var _loginResult=null;Object.defineProperty(this,"loginResult",{get:function(){return _loginResult},enumerable:true});var _loginHttpStatus=null;Object.defineProperty(this,"loginHttpStatus",{get:function(){return _loginHttpStatus},enumerable:true});var _clientContextId=null;Object.defineProperty(this,"clientContextId",{get:function(){return _clientContextId},enumerable:true});var _authenticationModel=progress.data.Session.AUTH_TYPE_ANON;Object.defineProperty(this,"authenticationModel",{get:function(){return _authenticationModel},set:function(newval){if(newval){newval=newval.toLowerCase()}switch(newval){case progress.data.Session.AUTH_TYPE_FORM:case progress.data.Session.AUTH_TYPE_BASIC:case progress.data.Session.AUTH_TYPE_ANON:case progress.data.Session.AUTH_TYPE_SSO:case null:_authenticationModel=newval;storeSessionInfo("authenticationModel",newval);break;default:throw new Error("Error setting Session.authenticationModel. '"+newval+"' is an invalid value.")}},enumerable:true});var _lastSessionXHR=null;Object.defineProperty(this,"lastSessionXHR",{get:function(){return _lastSessionXHR},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return this.loginResult===progress.data.Session.LOGIN_SUCCESS&&restApplicationIsOnline&&deviceIsOnline},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _jsdos},enumerable:true});var _pingInterval=0;var _timeoutID=null;Object.defineProperty(this,"pingInterval",{get:function(){return _pingInterval},set:function(newval){if(typeof newval==="number"&&newval>=0){_pingInterval=newval;storeSessionInfo("pingInterval",newval);if(newval>0){if(this.loginResult===progress.data.Session.LOGIN_SUCCESS){_timeoutID=setTimeout(this._autoping,newval)}}else if(newval===0){clearTimeout(_timeoutID);_pingInterval=0}}else{throw new Error("Error setting Session.pingInterval. '"+newval+"' is an invalid value.")}},enumerable:true});var _contextProperties=new progress.data.ContextProperties;Object.defineProperty(this,"_contextProperties",{get:function(){return _contextProperties},enumerable:false});var isInvalidated=false;Object.defineProperty(this,"_isInvalidated",{get:function(){return isInvalidated},enumerable:false});Object.defineProperty(this,"_authProvider",{get:function(){return _authProvider},set:function(newval){if(_authProvider){throw new Error("Internal Error setting Session._authProvider. '"+"The property has already been set.")}setAuthProvider(newval)},enumerable:false})}else{this.userName=null;this.loginTarget="/static/home.html";this.serviceURI=null;this.catalogURIs=[];this.services=[];this.loginResult=null;this.loginHttpStatus=null;this.clientContextId=null;this.authenticationModel=progress.data.Session.AUTH_TYPE_ANON;this.lastSessionXHR=null}function storeSessionInfo(infoName,value){var key;if(that.loginResult===progress.data.Session.LOGIN_SUCCESS&&typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}if(typeof value!=="undefined"){sessionStorage.setItem(key,JSON.stringify(value))}}}function retrieveSessionInfo(infoName){var key,jsonStr,value=null;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}jsonStr=sessionStorage.getItem(key);if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}}function clearSessionInfo(infoName){var key;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName;sessionStorage.removeItem(key)}}}function storeAllSessionInfo(){if(_storageKey){storeSessionInfo("loginResult",that.loginResult);storeSessionInfo("userName",that.userName);storeSessionInfo("serviceURI",that.serviceURI);storeSessionInfo("loginHttpStatus",that.loginHttpStatus);storeSessionInfo("authenticationModel",that.authenticationModel);storeSessionInfo("pingInterval",that.pingInterval);storeSessionInfo("oepingAvailable",oepingAvailable);storeSessionInfo("partialPingURI",partialPingURI);storeSessionInfo("clientContextId",that.clientContextId);storeSessionInfo("deviceIsOnline",deviceIsOnline);storeSessionInfo("restApplicationIsOnline",restApplicationIsOnline);if(that._authProvider){storeSessionInfo("_authProvider.init",{uri:that._authProvider.uri,authenticationModel:that._authProvider.authenticationModel})}storeSessionInfo(_storageKey,true)}}function clearAllSessionInfo(){if(_storageKey){if(retrieveSessionInfo(_storageKey)){clearSessionInfo("loginResult");clearSessionInfo("userName");clearSessionInfo("serviceURI");clearSessionInfo("loginHttpStatus");clearSessionInfo("clientContextId");clearSessionInfo("deviceIsOnline");clearSessionInfo("restApplicationIsOnline");clearSessionInfo("authenticationModel");clearSessionInfo("pingInterval");clearSessionInfo("oepingAvailable");clearSessionInfo("partialPingURI");clearSessionInfo("_authProvider.init");clearSessionInfo(_storageKey)}}}function setSessionInfoFromStorage(key){var authproviderInitObject;if(retrieveSessionInfo(key)){setLoginResult(retrieveSessionInfo("loginResult"),this);setUserName(retrieveSessionInfo("userName"),this);setServiceURI(retrieveSessionInfo("serviceURI"),this);setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"),this);setClientContextID(retrieveSessionInfo("clientContextId"),this);setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline"));setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline"));that.authenticationModel=retrieveSessionInfo("authenticationModel");that.pingInterval=retrieveSessionInfo("pingInterval");setOepingAvailable(retrieveSessionInfo("oepingAvailable"));setPartialPingURI(retrieveSessionInfo("partialPingURI"));if(!that._authProvider){authproviderInitObject=retrieveSessionInfo("_authProvider.init");if(authproviderInitObject){setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject))}}}}function setUserName(newname,sessionObject){if(defPropSupported){_userName=newname}else{sessionObject.userName=newname}storeSessionInfo("userName",newname)}function setLoginTarget(target,sessionObject){if(defPropSupported){_loginTarget=target}else{sessionObject.loginTarget=target}}function setServiceURI(url,sessionObject){if(defPropSupported){_serviceURI=url}else{sessionObject.serviceURI=url}storeSessionInfo("serviceURI",url)}function pushCatalogURIs(url,sessionObject){if(defPropSupported){_catalogURIs.push(url)}else{sessionObject.catalogURIs.push(url)}}function pushService(serviceObject,sessionObject){if(defPropSupported){_services.push(serviceObject)}else{sessionObject.services.push(serviceObject)}}function findService(serviceName){_services.forEach(function(service){if(service.name===serviceName){return service}});return null}function setLoginResult(result,sessionObject){if(defPropSupported){_loginResult=result}else{sessionObject.loginResult=result}if(result===progress.data.Session.LOGIN_SUCCESS){storeSessionInfo("loginResult",result)}else{clearAllSessionInfo()}}function setLoginHttpStatus(status,sessionObject){if(defPropSupported){_loginHttpStatus=status}else{sessionObject.loginHttpStatus=status}storeSessionInfo("loginHttpStatus",status)}function setClientContextIDfromXHR(xhr,sessionObject){if(xhr){setClientContextID(getResponseHeaderNoError(xhr,"X-CLIENT-CONTEXT-ID"),sessionObject)}}function setClientContextID(ccid,sessionObject){if(defPropSupported){_clientContextId=ccid}else{sessionObject.clientContextId=ccid}storeSessionInfo("clientContextId",ccid)}function setLastSessionXHR(xhr,sessionObject){if(defPropSupported){_lastSessionXHR=xhr}else{sessionObject.lastSessionXHR=xhr}}function setDeviceIsOnline(value){deviceIsOnline=value;storeSessionInfo("deviceIsOnline",value)}function setAuthProvider(value){_authProvider=value?value:null}function setRestApplicationIsOnline(value){restApplicationIsOnline=value;storeSessionInfo("restApplicationIsOnline",value)}function setOepingAvailable(value){oepingAvailable=value;storeSessionInfo("oepingAvailable",value)}function setPartialPingURI(value){partialPingURI=value;storeSessionInfo("partialPingURI",value)}function getResponseHeaderNoError(xhr,headerName){var allHeaders=xhr._pdsResponseHeaders,regExp;if(allHeaders===undefined){allHeaders=xhr.getAllResponseHeaders();if(allHeaders){xhr._pdsResponseHeaders=allHeaders}else{xhr._pdsResponseHeaders=null}}if(allHeaders){regExp=new RegExp("^"+headerName+":","mi");if(allHeaders.match(regExp)){return xhr.getResponseHeader(headerName)}}return null}this._pushJSDOs=function(jsdo){_jsdos.push(jsdo)};this._openRequest=function(xhr,verb,url,async,callback){var urlPlusCCID,that=this;function afterOpenAndAuthorize(arg){if(arg instanceof Error){throw arg}else{if(that.clientContextId&&that.clientContextId!=="0"){xhr.setRequestHeader("X-CLIENT-CONTEXT-ID",that.clientContextId)}setRequestHeaderFromContextProps(that,xhr);if(typeof that.onOpenRequest==="function"){var params={xhr:xhr,verb:verb,uri:urlPlusCCID,async:async,formPreTest:false,session:that};that.onOpenRequest(params)}if(callback){callback()}}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to make server request when there is no active session.")}urlPlusCCID=this._prependAppURL(url);urlPlusCCID=this._addCCIDtoURL(urlPlusCCID);if(progress.data.Session._useTimeStamp){urlPlusCCID=progress.data.Session._addTimeStampToURL(urlPlusCCID)}if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,verb,urlPlusCCID,async,afterOpenAndAuthorize)}else{this._setXHRCredentials(xhr,verb,urlPlusCCID,this.userName,_password,async);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json")}afterOpenAndAuthorize(xhr)}};this.pingTestCallback=function(cbArgs){var foundOeping=cbArgs.pingResult?true:false;setOepingAvailable(foundOeping)};this._onReadyStateChangeGeneric=function(){var xhr=this;var result;var errorObject;clearTimeout(xhr._requestTimeout);if(xhr.readyState===4){result=null;errorObject=null;if(typeof xhr.onResponseFn==="function"){try{result=xhr.onResponseFn(xhr)}catch(e){errorObject=e}}if(typeof xhr.onResponseProcessedFn==="function"){if(!result){result=progress.data.Session.GENERAL_FAILURE}xhr.onResponseProcessedFn(xhr.pdsession,result,errorObject,xhr)}}};this._disconnect=function(deferred){this._processDisconnectResult(null,deferred)};this._processDisconnectResult=function(xhr,deferred){this._reinitializeAfterLogout(this,progress.data.Session.SUCCESS);this._disconnectComplete(this,progress.data.Session.SUCCESS,null,null,deferred)};this._disconnectComplete=function(pdsession,result,errObj,xhr,deferred){pdsession.trigger("afterDisconnect",pdsession,result,errObj,xhr,deferred)};var pwSave=null;var unameSave=null;this.login=function(serviceURI,loginUserName,loginPassword,loginTarget){var uname,pw,isAsync=false,args=[],deferred,iOSBasicAuthTimeout,uriForRequest;pwSave=null;unameSave=null;if(!defPropSupported){this.authenticationModel=this.authenticationModel.toLowerCase()}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","login()"))}if(this.loginResult===progress.data.Session.LOGIN_SUCCESS||this._authProvider){throw new Error("Attempted to call login() on a Session object that is already logged in.")}if(arguments.length>0){if(arguments[0]&&typeof arguments[0]==="object"){args[0]=arguments[0].serviceURI;args[1]=arguments[0].userName;args[2]=arguments[0].password;args[3]=arguments[0].loginTarget;args[4]=arguments[0].async;deferred=arguments[0].deferred;iOSBasicAuthTimeout=arguments[0].iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","login","The iOSBasicAuthTimeout argument was invalid."))}}else{args=arguments}}if(args.length>0){if(args[0]){var restURLtemp=args[0];if(restURLtemp[restURLtemp.length-1]==="/"){restURLtemp=restURLtemp.substring(0,restURLtemp.length-1)}setServiceURI(restURLtemp,this)}else if(!this.serviceURI){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}if(args[1]){uname=args[1]}if(args[2]){pw=args[2]}if(args[3]){setLoginTarget(args[3],this)}if(args[4]){if(typeof args[4]==="boolean"){isAsync=args[4]}else{throw new Error("Session.login() was passed an async setting that is not a boolean.")}}}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}unameSave=uname;pwSave=pw;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON||this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){uname=null;pw=null}var xhr=new XMLHttpRequest;xhr.pdsession=this;try{uriForRequest=this.serviceURI+this.loginTarget;if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(uriForRequest)}this._setXHRCredentials(xhr,"GET",uriForRequest,uname,pw,isAsync);progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(this,xhr);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr._isAsync=isAsync;if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){xhr.onResponseFn=this._afterFormPretestLogin}else{xhr.onResponseFn=this._processLoginResult;xhr.onResponseProcessedFn=this._loginComplete}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout>0){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred}if(typeof this.onOpenRequest==="function"){var isFormPreTest=false;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){isFormPreTest=true}setLastSessionXHR(xhr,this);var params={xhr:xhr,verb:"GET",uri:this.serviceURI+this.loginTarget,async:false,formPreTest:isFormPreTest,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send(null)}catch(e){clearTimeout(xhr._requestTimeout);setLoginHttpStatus(xhr.status,this);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);unameSave=null;pwSave=null;throw e}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{setLoginHttpStatus(xhr.status,this);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){return this._afterFormPretestLogin(xhr)}else{return this._processLoginResult(xhr)}}};this._afterFormPretestLogin=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);var formLoginParams={xhr:xhr,pw:pwSave,uname:unameSave,theSession:pdsession};try{return doFormLogin(formLoginParams)}catch(e){pwSave=null;unameSave=null;throw e}};function doFormLogin(args){var xhr=args.xhr;var theSession=args.theSession;var oldXHR;var contentType=null;var needAuth=false;var params={session:theSession,xhr:xhr,statusFromjson:null};contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson||params.statusFromjson>=400&¶ms.statusFromjson<500){needAuth=true}else{setLoginHttpStatus(params.statusFromjson,theSession)}}else{if(theSession.loginHttpStatus===200){if(_gotLoginForm(xhr)){needAuth=true}}}if(needAuth){oldXHR=xhr;xhr=new XMLHttpRequest;args.xhr=xhr;params.xhr=xhr;xhr.pdsession=oldXHR.pdsession;xhr._isAsync=oldXHR._isAsync;xhr._deferred=oldXHR._deferred;xhr._jsdosession=oldXHR._jsdosession;xhr.open("POST",theSession.serviceURI+"/static/auth/j_spring_security_check",xhr._isAsync);xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.setRequestHeader("Cache-Control","max-age=0");setRequestHeaderFromContextProps(theSession,xhr);_addWithCredentialsAndAccept(xhr,"application/json");try{if(typeof theSession.onOpenRequest==="function"){var cbparams={xhr:xhr,verb:"POST",uri:theSession.serviceURI+"/static/auth/j_spring_security_check",async:xhr._isAsync,formPreTest:false,session:theSession};theSession.onOpenRequest(cbparams);xhr=cbparams.xhr}if(xhr._isAsync){xhr.onreadystatechange=theSession._onReadyStateChangeGeneric;xhr.onResponseFn=theSession._afterFormLogin;xhr.onResponseProcessedFn=theSession._loginComplete}xhr.send("j_username="+encodeURIComponent(args.uname)+"&j_password="+encodeURIComponent(args.pw)+"&submit=Submit")}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,theSession);setLoginHttpStatus(xhr.status,theSession);unameSave=null;pwSave=null;throw e}}if(xhr._isAsync&&!needAuth){xhr.onResponseProcessedFn=theSession._loginComplete;return theSession._afterFormLogin(xhr)}if(!xhr._isAsync){return theSession._afterFormLogin(xhr)}}this._afterFormLogin=function(xhr){var theSession=xhr.pdsession;var params={session:theSession,xhr:xhr,statusFromjson:null};var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson){throw new Error("Internal OpenEdge Mobile client error handling login response. HTTP status: "+xhr.status+".")}setLoginHttpStatus(params.statusFromjson,theSession)}else{if(xhr.status===200){if(_gotLoginFailure(xhr)||_gotLoginForm(xhr)){setLoginHttpStatus(401,theSession)}else{setLoginHttpStatus(xhr.status,theSession)}}}return theSession._processLoginResult(xhr)};this._processLoginResult=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);if(pdsession.loginHttpStatus===200){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);setUserName(unameSave,pdsession);_password=pwSave;pdsession._saveClientContextId(xhr);storeAllSessionInfo();var pingTestArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:pdsession._pingtestOnReadyStateChange};pingTestArgs.pingURI=pdsession._makePingURI();pdsession._sendPing(pingTestArgs)}else{if(pdsession.loginHttpStatus===401){setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE,pdsession)}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);unameSave=null;pwSave=null;if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","login"))}return pdsession.loginResult};this._loginComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterLogin",pdsession,result,errObj,xhr)};this.logout=function(args){var isAsync=false,errorObject=null,xhr,deferred,params;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","logout()"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&this.authenticationModel){throw new Error("Attempted to call logout when there is no active session.")}if(typeof args==="object"){isAsync=args.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","logout","The async argument was invalid."))}deferred=args.deferred}xhr=new XMLHttpRequest;xhr.pdsession=this;try{xhr._jsdosession=jsdosession;xhr._deferred=deferred;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM||this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;xhr.onResponseFn=this._processLogoutResult;xhr.onResponseProcessedFn=this._logoutComplete}xhr.open("GET",this.serviceURI+"/static/auth/j_spring_security_logout",isAsync);try{xhr.withCredentials=true}catch(e){}xhr.setRequestHeader("Accept","application/json");setRequestHeaderFromContextProps(this,xhr);if(typeof this.onOpenRequest==="function"){setLastSessionXHR(xhr,this);params={xhr:xhr,verb:"GET",uri:this.serviceURI+"/static/auth/j_spring_security_logout",async:false,formPreTest:false,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send()}else{xhr._anonymousLogoutOK=true}}catch(e){this._reinitializeAfterLogout(this,false);throw e}if(!isAsync){try{this._processLogoutResult(xhr)}catch(e){throw e}}if(isAsync&&this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){try{this._processLogoutResult(xhr)}catch(e){errorObject=e}this._logoutComplete(this,null,errorObject,xhr)}};this.invalidate=function(){isInvalidated=true;cleanServicesManager()};this._logoutComplete=function(pdsession,result,errorObject,xhr){pdsession.trigger("afterLogout",pdsession,errorObject,xhr)};this._processLogoutResult=function(xhr){var logoutSucceeded;var pdsession=xhr.pdsession;var basicStatusOK=false;if(xhr._anonymousLogoutOK){logoutSucceeded=true}else if(xhr.status!==200){if(pdsession.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(xhr.status===404){logoutSucceeded=true}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=true}updateContextPropsFromResponse(pdsession,xhr);pdsession._reinitializeAfterLogout(pdsession,logoutSucceeded)};this._reinitializeAfterLogout=function(pdsession,success){setLoginResult(null,pdsession);setLoginHttpStatus(null,pdsession);setClientContextID(null,pdsession);setUserName(null,pdsession);setAuthProvider(null);_password=null;if(success){setRestApplicationIsOnline(false);setOepingAvailable(false);setPartialPingURI(defaultPartialPingURI);setLastSessionXHR(null,pdsession);clearTimeout(_timeoutID)}};this.addCatalog=function(arg1,arg2,arg3,arg4){var catalogURI,catalogUserName,catalogPassword,isAsync=false,xhr,deferred,iOSBasicAuthTimeout,catalogIndex,authProvider,that=this;function addCatalogAfterOpen(){progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(isAsync){xhr.onreadystatechange=that._onReadyStateChangeGeneric;xhr.onResponseFn=that._processAddCatalogResult;xhr.onResponseProcessedFn=that._addCatalogComplete;if(that.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex}try{if(typeof that.onOpenRequest==="function"){setLastSessionXHR(xhr,that);var params={xhr:xhr,verb:"GET",uri:catalogURI,async:false,formPreTest:false,session:that};that.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,that);xhr.send(null)}catch(e){throw new Error("Error retrieving catalog '"+catalogURI+"'.\n"+e.message)}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{return that._processAddCatalogResult(xhr)}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}customCredentials=true;if(arguments.length>0){if(typeof arg1==="object"){if(!arguments[0].offlineAddCatalog){if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to call addCatalog when there is no active session.")}}catalogURI=arg1.catalogURI;if(!catalogURI||typeof catalogURI!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogURI argument was missing or invalid."))}catalogUserName=arg1.userName;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogUserName argument was invalid."))}catalogPassword=arg1.password;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogPassword argument was invalid."))}isAsync=arg1.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The async argument was invalid."))}iOSBasicAuthTimeout=arg1.iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The iOSBasicAuthTimeout argument was invalid."))}authProvider=arg1.authProvider;deferred=arg1.deferred;catalogIndex=arg1.catalogIndex}else{catalogURI=arg1;if(typeof catalogURI!=="string"){throw new Error("First argument to Session.addCatalog must be the URL of the catalog.")}catalogUserName=arg2;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error("Second argument to Session.addCatalog must be a user name string.")}catalogPassword=arg3;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error("Third argument to Session.addCatalog must be a password string.")}}}else{throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog.")}if(!authProvider){authProvider=this._authProvider;customCredentials=false}if(!catalogUserName){catalogUserName=this.userName}if(!catalogPassword){catalogPassword=_password}xhr=new XMLHttpRequest;xhr.pdsession=this;xhr._catalogURI=catalogURI;if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){if(isAsync){xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex;setTimeout(this._addCatalogComplete,10,this,progress.data.Session.CATALOG_ALREADY_LOADED,null,xhr);return progress.data.Session.ASYNC_PENDING}return progress.data.Session.CATALOG_ALREADY_LOADED}if(authProvider){authProvider._openRequestAndAuthorize(xhr,"GET",catalogURI,isAsync,addCatalogAfterOpen);return progress.data.Session.ASYNC_PENDING}else{this._setXHRCredentials(xhr,"GET",catalogURI,catalogUserName,catalogPassword,isAsync);return addCatalogAfterOpen()}};this._processAddCatalogResult=function(xhr){var _catalogHttpStatus=xhr.status;var theSession=xhr.pdsession;var servicedata;var catalogURI=xhr._catalogURI,serviceURL,theJSDOSession=jsdosession;if(!customCredentials){toggleOnlineState(xhr)}if((_catalogHttpStatus===200||_catalogHttpStatus===0)&&xhr.responseText){servicedata=theSession._parseCatalog(xhr);try{progress.data.ServicesManager.addCatalog(servicedata,theSession)}catch(e){if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){return progress.data.Session.CATALOG_ALREADY_LOADED}throw new Error("Error processing catalog '"+catalogURI+"'. \n"+e.message)}servicedata.forEach(function(service){serviceURL=theSession._prependAppURL(service.address);pushService(new progress.data.MobileServiceObject({name:service.name,uri:serviceURL}),theSession);if(service.settings&&service.settings.useXClientProps&&!theSession.xClientProps){console.warn("Catalog warning: Service settings property 'useXClientProps' "+"is true but 'xClientProps' property has not been set.")}});pushCatalogURIs(catalogURI,theSession);progress.data.ServicesManager.addSession(catalogURI,theSession);if(theJSDOSession){progress.data.ServicesManager.addJSDOSession(catalogURI,theJSDOSession)}}else if(_catalogHttpStatus===401){return progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","addCatalog"))}else{throw new Error("Error retrieving catalog '"+catalogURI+"'. Http status: "+_catalogHttpStatus+".")}return progress.data.Session.SUCCESS};this._addCatalogComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterAddCatalog",pdsession,result,errObj,xhr)};this.ping=function(args){var pingResult=false,pingArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:this._onReadyStateChangePing,offlineReason:null};if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(!this._authProvider&&this.loginResult!==progress.data.Session.LOGIN_SUCCESS){throw new Error("Attempted to call ping when not logged in.")}if(args){if(args.async!==undefined){pingArgs.async=args.async}if(args.doNotFireEvent!==undefined){pingArgs.fireEventIfOfflineChange=!args.doNotFireEvent}if(args.onCompleteFn&&typeof args.onCompleteFn==="function"){pingArgs.onCompleteFn=args.onCompleteFn}pingArgs.deferred=args.deferred;pingArgs.jsdosession=args.jsdosession}pingArgs.pingURI=that._makePingURI();that._sendPing(pingArgs);if(!pingArgs.async){if(pingArgs.xhr){pingResult=that._processPingResult(pingArgs);if(args.offlineReason!==undefined){args.offlineReason=pingArgs.offlineReason}}else{pingResult=false}if(args.xhr!==undefined){args.xhr=pingArgs.xhr}}return pingResult};this._isOnlineStateChange=function(isOnline){var stateChanged=false;if(isOnline&&!this.connected){stateChanged=true}else if(!isOnline&&this.connected){stateChanged=true}return stateChanged};this._checkServiceResponse=function(xhr,success,request){var offlineReason=null,wasOnline=this.connected;updateContextPropsFromResponse(this,xhr);if(!this._events){return}var offlineObservers=this._events.offline||[];var onlineObservers=this._events.online||[];if(offlineObservers.length===0&&onlineObservers.length===0){return}if(success){setRestApplicationIsOnline(true);setDeviceIsOnline(true)}else{if(deviceIsOnline){var localPingArgs={doNotFireEvent:true,offlineReason:null,async:false};if(!that.ping(localPingArgs)){offlineReason=localPingArgs.offlineReason;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}}if(wasOnline&&!this.connected){this.trigger("offline",this,offlineReason,request)}else if(!wasOnline&&this.connected){this.trigger("online",this,request)}};this._processPingResult=function(args){var xhr=args.xhr,pingResponseJSON,appServerStatus=null,wasOnline=this.connected,connectedBeforeCallback,assumeOepingFormat;if(args.hasOwnProperty("usingOepingFormat")){assumeOepingFormat=args.usingOepingFormat}else{assumeOepingFormat=oepingAvailable}if(xhr.status>=200&&xhr.status<300){updateContextPropsFromResponse(this,xhr);if(assumeOepingFormat){try{pingResponseJSON=JSON.parse(xhr.responseText);appServerStatus=pingResponseJSON.AppServerStatus}catch(e){console.error("Unable to parse ping response.")}}toggleOnlineState(xhr)}else{if(deviceIsOnline){if(xhr.status===0){args.offlineReason=progress.data.Session.SERVER_OFFLINE;setRestApplicationIsOnline(false)}else if(xhr.status===404||xhr.status===410){args.offlineReason=progress.data.Session.WEB_APPLICATION_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}else{args.offlineReason=progress.data.Session.DEVICE_OFFLINE}}if(appServerStatus){if(appServerStatus.PingStatus==="false"){args.offlineReason=progress.data.Session.APPSERVER_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}connectedBeforeCallback=this.connected;if(typeof xhr.onCompleteFn==="function"){xhr.onCompleteFn({pingResult:this.connected,xhr:xhr,offlineReason:args.offlineReason})}if(args.fireEventIfOfflineChange){if(wasOnline&&!connectedBeforeCallback){that.trigger("offline",that,args.offlineReason,null)}else if(!wasOnline&&connectedBeforeCallback){that.trigger("online",that,null)}}return this.connected};this._onReadyStateChangePing=function(){var xhr=this;var args;if(xhr.readyState===4){args={xhr:xhr,fireEventIfOfflineChange:true,offlineReason:null};that._processPingResult(args);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._pingtestOnReadyStateChange=function(){var xhr=this;if(xhr.readyState===4){var foundOeping=false;if(xhr.status>=200&&xhr.status<300){foundOeping=true}else{setPartialPingURI(that.loginTarget);console.warn("Default ping target not available, will use loginTarget instead.")}setOepingAvailable(foundOeping);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._sendPing=function(args){var xhr=new XMLHttpRequest,that=this;function sendPingAfterOpen(){if(args.async){xhr.onreadystatechange=args.onReadyStateFn;xhr.onCompleteFn=args.onCompleteFn;xhr._jsdosession=jsdosession;xhr._deferred=args.deferred}progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(that.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr.send(null)}try{if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,"GET",args.pingURI,args.async,sendPingAfterOpen)}else{this._setXHRCredentials(xhr,"GET",args.pingURI,this.userName,_password,args.async);if(xhr.readyState===1){sendPingAfterOpen()}}}catch(e){args.error=e}args.xhr=xhr};this._makePingURI=function(){var pingURI=this.serviceURI+partialPingURI;if(progress.data.Session._useTimeStamp){pingURI=progress.data.Session._addTimeStampToURL(pingURI)}return pingURI};this._autoping=function(){that.ping({async:true})};this._setXHRCredentials=function(xhr,verb,uri,userName,password,async){if(userName&&this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(canPassCredentialsToOpen()){xhr.open(verb,uri,async,userName,password)}else{xhr.open(verb,uri,async)}var auth=_make_basic_auth(userName,password);xhr.setRequestHeader("Authorization",auth)}else{xhr.open(verb,uri,async)}};this._addCCIDtoURL=function(url){var urlPart1,urlPart2,jsessionidStr,index;if(this.clientContextId&&this.clientContextId!=="0"){if(url.substring(0,this.serviceURI.length)===this.serviceURI){jsessionidStr=";"+"JSESSIONID="+this.clientContextId;index=url.indexOf("?");if(index===-1){url+=jsessionidStr}else{urlPart1=url.substring(0,index);urlPart2=url.substring(index);url=urlPart1+jsessionidStr+urlPart2}}}return url};this._saveClientContextId=function(xhr){setClientContextIDfromXHR(xhr,this)};this._parseCatalog=function(xhr){var jsonObject;var catalogdata;try{jsonObject=JSON.parse(xhr.responseText);catalogdata=jsonObject.services}catch(e){console.error("Unable to parse response. Make sure catalog has correct format.");catalogdata=null}return catalogdata};this._prependAppURL=function(oldURL){if(!oldURL){return this.serviceURI}var newURL=oldURL;var pat=/^https?:\/\//i;if(!pat.test(newURL)){if(newURL.indexOf("/")!==0){newURL="/"+newURL}newURL=this.serviceURI+newURL}return newURL};function _addWithCredentialsAndAccept(xhr,acceptString){try{xhr.withCredentials=true;xhr.setRequestHeader("Accept",acceptString)}catch(e){}}function _make_basic_auth(user,pw){var tok=user+":"+pw;var hash=btoa(tok);return"Basic "+hash}var loginFormIDString="j_spring_security_check";function _gotLoginForm(xhr){return _findStringInResponseHTML(xhr,loginFormIDString)}var loginFailureIdentificationString="login failed";function _gotLoginFailure(xhr){return _findStringInResponseHTML(xhr,loginFailureIdentificationString)}function _findStringInResponseHTML(xhr,searchString){if(!xhr.responseText){return false}var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("text/html")>=0&&xhr.responseText.indexOf(searchString)>=0){return true}return false}function handleJSONLoginResponse(params){var jsonObject;params.statusFromjson=null;try{jsonObject=JSON.parse(params.xhr.responseText);if(jsonObject.status_code!==undefined&&jsonObject.status_txt!==undefined){params.statusFromjson=jsonObject.status_code}}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,params.session);setLoginHttpStatus(params.xhr.status,params.session);throw new Error("Unable to parse login response from server.")}}function setRequestHeaderFromContextProps(session,xhr){if(session.xClientProps){xhr.setRequestHeader("X-CLIENT-PROPS",session.xClientProps)}else if(session._contextProperties.contextHeader!==undefined){xhr.setRequestHeader("X-CLIENT-PROPS",session._contextProperties.contextHeader)}}function toggleOnlineState(xhr){var pdsession=that;setLoginHttpStatus(xhr.status,pdsession);if(pdsession.loginHttpStatus>=200&&pdsession.loginHttpStatus<400){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);pdsession._saveClientContextId(xhr);storeAllSessionInfo()}else{if(pdsession.loginHttpStatus===0||pdsession.loginHttpStatus===400||pdsession.loginHttpStatus===410){setRestApplicationIsOnline(false);setLoginResult(progress.data.AuthenticationProvider._getAuthFailureReason(xhr),pdsession)}else{setRestApplicationIsOnline(true);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);return pdsession.loginResult}function updateContextPropsFromResponse(session,xhr){var contextString,context;if(xhr){contextString=getResponseHeaderNoError(xhr,"X-CLIENT-PROPS");if(contextString){try{context=JSON.parse(contextString)}catch(e){}if(typeof context==="object"){session._contextProperties.setContext(context)}else{throw new Error(progress.data._getMsgText("jsdoMSG123","Session","X-CLIENT-PROPS"))}}else if(contextString===""){session._contextProperties.setContext({})}}}function cleanServicesManager(){progress.data.ServicesManager.cleanSession(that)}if(typeof options==="object"){jsdosession=options.jsdosession;newURI=options.serviceURI;setAuthProvider(options.authProvider);if(options.authProvider&&options.authProvider.hasClientCredentials()){_loginResult=progress.data.Session.LOGIN_SUCCESS}if(newURI&&newURI[newURI.length-1]==="/"){newURI=newURI.substring(0,newURI.length-1)}_storageKey=options._storageKey;if(_storageKey){if(retrieveSessionInfo(_storageKey)){storedAuthModel=retrieveSessionInfo("authenticationModel");storedURI=retrieveSessionInfo("serviceURI");if(storedAuthModel!==options.authenticationModel||storedURI!==newURI){clearAllSessionInfo()}else{setSessionInfoFromStorage(_storageKey);stateWasReadFromStorage=true}}if(options.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){_storageKey=undefined}}if(!stateWasReadFromStorage){if(newURI){setServiceURI(newURI,this)}if(options.authenticationModel){this.authenticationModel=options.authenticationModel}}}};progress.data.Session._useTimeStamp=true;var SEQ_MAX_VALUE=999999999999999;var _tsseq=SEQ_MAX_VALUE;var _tsprefix1=0;var _tsprefix2=0;progress.data.Session._getNextTimeStamp=function(){var seq;_tsseq+=1;seq=_tsseq;if(seq>=SEQ_MAX_VALUE){_tsseq=1;seq=1;var t=Math.floor((Date.now?Date.now():(new Date).getTime())/1e4);if(_tsprefix1===t){_tsprefix2+=1;if(_tsprefix2>=SEQ_MAX_VALUE){_tsprefix2=1}}else{_tsprefix1=t;Math.random();_tsprefix2=Math.round(Math.random()*1e10)}}return _tsprefix1+"-"+_tsprefix2+"-"+seq};progress.data.Session._addTimeStampToURL=function(url){var timeStamp="_ts="+progress.data.Session._getNextTimeStamp();url+=(url.indexOf("?")===-1?"?":"&")+timeStamp;return url};progress.data.Session._setNoCacheHeaders=function(xhr){xhr.setRequestHeader("Cache-Control","no-cache");xhr.setRequestHeader("Pragma","no-cache")};if(typeof Object.defineProperty==="function"){Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_REQUIRED",{value:0,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"CATALOG_ALREADY_LOADED",{value:4,enumerable:true});Object.defineProperty(progress.data.Session,"ASYNC_PENDING",{value:5,enumerable:true});Object.defineProperty(progress.data.Session,"EXPIRED_TOKEN",{value:6,enumerable:true});Object.defineProperty(progress.data.Session,"SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_ANON",{value:"anonymous",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_BASIC",{value:"basic",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM",{value:"form",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_SSO",{value:"sso",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM_SSO",{value:"form_sso",enumerable:true});Object.defineProperty(progress.data.Session,"DEVICE_OFFLINE",{value:"Device is offline",enumerable:true});Object.defineProperty(progress.data.Session,"SERVER_OFFLINE",{value:"Cannot contact server",enumerable:true});Object.defineProperty(progress.data.Session,"WEB_APPLICATION_OFFLINE",{value:"Mobile Web Application is not available",enumerable:true});Object.defineProperty(progress.data.Session,"SERVICE_OFFLINE",{value:"REST web Service is not available",enumerable:true});Object.defineProperty(progress.data.Session,"APPSERVER_OFFLINE",{value:"AppServer is not available",enumerable:true})}else{progress.data.Session.LOGIN_SUCCESS=1;progress.data.Session.LOGIN_AUTHENTICATION_FAILURE=2;progress.data.Session.LOGIN_GENERAL_FAILURE=3;progress.data.Session.CATALOG_ALREADY_LOADED=4;progress.data.Session.SUCCESS=1;progress.data.Session.AUTHENTICATION_FAILURE=2;progress.data.Session.GENERAL_FAILURE=3;progress.data.Session.AUTH_TYPE_ANON="anonymous";progress.data.Session.AUTH_TYPE_BASIC="basic";progress.data.Session.AUTH_TYPE_FORM="form";progress.data.Session.AUTH_TYPE_SSO="sso"}progress.data.Session.prototype=new progress.util.Observable;progress.data.Session.prototype.constructor=progress.data.Session;function validateSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}else{listenerData.scope=args[2]}}}progress.data.Session.prototype._eventNames=["offline","online","afterLogin","afterAddCatalog","afterLogout","afterDisconnect"];progress.data.Session.prototype.validateSubscribe=validateSessionSubscribe;progress.data.Session.prototype.toString=function(radix){return"progress.data.Session"};progress.data.JSDOSession=function JSDOSession(options){var _pdsession,_serviceURI,that=this,_name;Object.defineProperty(this,"authenticationModel",{get:function(){return _pdsession?_pdsession.authenticationModel:undefined},enumerable:true});Object.defineProperty(this,"authProvider",{get:function(){return _pdsession?_pdsession._authProvider:null},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _pdsession?_pdsession.catalogURIs:undefined},enumerable:true});Object.defineProperty(this,"clientContextId",{get:function(){return _pdsession?_pdsession.clientContextId:undefined},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return _pdsession?_pdsession.connected:undefined},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _pdsession?_pdsession.JSDOs:undefined},enumerable:true});Object.defineProperty(this,"loginResult",{get:function(){return _pdsession?_pdsession.loginResult:undefined},enumerable:true});Object.defineProperty(this,"loginHttpStatus",{get:function(){return _pdsession?_pdsession.loginHttpStatus:undefined},enumerable:true});Object.defineProperty(this,"onOpenRequest",{get:function(){return _pdsession?_pdsession.onOpenRequest:undefined},set:function(newval){if(_pdsession){_pdsession.onOpenRequest=newval}},enumerable:true});Object.defineProperty(this,"pingInterval",{get:function(){return _pdsession?_pdsession.pingInterval:undefined},set:function(newval){if(_pdsession){_pdsession.pingInterval=newval}},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _pdsession?_pdsession.services:undefined},enumerable:true});Object.defineProperty(this,"serviceURI",{get:function(){if(_pdsession&&_pdsession.serviceURI){return _pdsession.serviceURI}else{return _serviceURI}},enumerable:true});Object.defineProperty(this,"userName",{get:function(){return _pdsession?_pdsession.userName:undefined},enumerable:true});Object.defineProperty(this,"name",{get:function(){return _name},enumerable:true});Object.defineProperty(this,"_isInvalidated",{get:function(){return _pdsession._isInvalidated},enumerable:false});function settlePromise(promise,fulfill,result,info){if(fulfill){promise.resolve(that,result,info)}else{promise.reject(that,result,info)}}function genericSessionEventHandler(pdsession,result,errorObject,xhr,deferred){var myDeferred;if(xhr){myDeferred=xhr._deferred}else{myDeferred=deferred}settlePromise(myDeferred,result===progress.data.Session.SUCCESS?true:false,result,{errorObject:errorObject,xhr:xhr})}function onAfterAddCatalog(pdsession,result,errorObject,xhr){var deferred,fulfill=false,settleResult,info;if(result===progress.data.Session.EXPIRED_TOKEN){settleResult=progress.data.Session.EXPIRED_TOKEN}else if(result===progress.data.Session.LOGIN_AUTHENTICATION_FAILURE){settleResult=progress.data.Session.LOGIN_AUTHENTICATION_FAILURE}else{settleResult=progress.data.Session.GENERAL_FAILURE}if(xhr&&xhr._deferred){deferred=xhr._deferred;if(result!==progress.data.Session.SUCCESS&&result!==progress.data.Session.CATALOG_ALREADY_LOADED){result=result||progress.data.Session.GENERAL_FAILURE;deferred._overallCatalogResult=progress.data.Session.GENERAL_FAILURE}deferred._results[xhr._catalogIndex]={catalogURI:xhr._catalogURI,result:result,errorObject:errorObject,xhr:xhr};deferred._numCatalogsProcessed+=1;if(deferred._numCatalogsProcessed===deferred._numCatalogs){deferred._processedPromise=true;if(!deferred._overallCatalogResult){fulfill=true;settleResult=progress.data.Session.SUCCESS}if(settleResult===progress.data.Session.SUCCESS){if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,details:xhr._deferred._results}}}else{if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,errorObject:new Error(progress.data._getMsgText("jsdoMSG512")),details:xhr._deferred._results}}}settlePromise(xhr._deferred,fulfill,settleResult,info)}}}function onAfterLogout(pdsession,errorObject,xhr){var result=progress.data.Session.GENERAL_FAILURE,fulfill=false;if(xhr&&xhr._deferred){if(!errorObject&&!pdsession.loginResult){result=progress.data.Session.SUCCESS;fulfill=true}settlePromise(xhr._deferred,fulfill,result,{errorObject:errorObject,xhr:xhr})}}function onPingComplete(args){var xhr=args.xhr;if(xhr&&xhr._deferred){settlePromise(xhr._deferred,args.pingResult,args.pingResult,{offlineReason:args.offlineReason,xhr:xhr})}}this.login=function(username,password,options){var deferred=new progress.util.Deferred,iOSBasicAuthTimeout;function callIsAuthorized(){that.isAuthorized().then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(that,object.result,object.info)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","JSDOSession","login()"))}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout}if(!_pdsession._authProvider){_pdsession._authProvider=new progress.data.AuthenticationProvider({uri:this.serviceURI,authenticationModel:this.authenticationModel});_pdsession._authProvider.logout().then(function(){return _pdsession._authProvider.login(username,password)}).then(function(){callIsAuthorized()},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}else{throw new Error(progress.data._getMsgText("jsdoMSG062","JSDOSession","login()"))}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.disconnect=function(){var deferred=new progress.util.Deferred,errorObject;try{_pdsession.subscribe("afterDisconnect",genericSessionEventHandler,this);_pdsession._disconnect(deferred)}catch(e){errorObject=new Error(progress.data._getMsgText("jsdoMSG049","JSDOSession","disconnect",e.message))}if(errorObject){if(progress.util.Deferred.useJQueryPromises){throw errorObject}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:errorObject})}}else{return deferred.promise()}};this.addCatalog=function(catalogURI,unameOrOpts,password,opts){var deferred=new progress.util.Deferred,catalogURIs,numCatalogs,catalogIndex,addResult,errorObject,iOSBasicAuthTimeout,username,options,authProvider;try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(typeof catalogURI==="string"){catalogURIs=[catalogURI]}else if(catalogURI instanceof Array){catalogURIs=catalogURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","addCatalog","The first argument must be a string or an array of strings specifying the URI of the catalog."))}if(unameOrOpts){if(typeof unameOrOpts==="string"){if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG058","Session"))}username=unameOrOpts;if(opts){options=opts;options.authProvider=undefined}}else if(typeof unameOrOpts==="object"){options=unameOrOpts}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDOSession","2","object","addCatalog"))}}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout;if(options.authProvider){authProvider=options.authProvider}else if(this.authProvider){authProvider=this.authProvider}}if(!authProvider&&!this.authProvider&&!username){throw new Error(progress.data._getMsgText("jsdoMSG511"))}_pdsession.subscribe("afterAddCatalog",onAfterAddCatalog,this);numCatalogs=catalogURIs.length;deferred._numCatalogs=numCatalogs;deferred._numCatalogsProcessed=0;deferred._results=[];deferred._results.length=numCatalogs;for(catalogIndex=0;catalogIndex=200&&xhr.status<300){deferred.resolve(that,progress.data.Session.SUCCESS,info)}else{if(xhr.status===401){cbresult=progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else{cbresult=progress.data.Session.GENERAL_FAILURE}deferred.reject(that,cbresult,info)}}};try{xhr.send()}catch(e){throw new Error("JSDOSession: Unable to validate authorization. "+e.message)}})}else{result=progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED;deferred.reject(that,result,{xhr:xhr})}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(that,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.setContext=function(context){_pdsession._contextProperties.setContext(context)};this.setContextProperty=function(propertyName,propertyValue){_pdsession._contextProperties.setContextProperty(propertyName,propertyValue)};this.getContext=function(){return _pdsession._contextProperties.getContext()};this.getContextProperty=function(propertyName){return _pdsession._contextProperties.getContextProperty(propertyName)};this._onlineHandler=function(session,request){that.trigger("online",that,request)};this._offlineHandler=function(session,offlineReason,request){that.trigger("offline",that,offlineReason,request)};if(arguments.length>0&&typeof arguments[0]==="object"){if(options.serviceURI&&typeof options.serviceURI==="string"){_serviceURI=options.serviceURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options parameter must include a 'serviceURI' property that is a string."))}if(options.authenticationModel){if(typeof options.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The authenticationModel property of the options parameter must be a string."))}options.authenticationModel=options.authenticationModel.toLowerCase()}else{options.authenticationModel=progress.data.Session.AUTH_TYPE_ANON}if(options.authProvider){if(typeof options.authProvider!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG502","JSDOSession","options","constructor","authProvider"))}if(options.authProvider.authenticationModel!==progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authProvider.authenticationModel!==options.authenticationModel||options.authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authenticationModel!==progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG059","JSDOSession",options.authProvider.authenticationModel,options.authenticationModel))}if(typeof options.authProvider.hasClientCredentials==="function"){if(!options.authProvider.hasClientCredentials()){throw new Error(progress.data._getMsgText("jsdoMSG125","JSDOSession"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG505","JSDOSession","AuthenticationProvider","hasClientCredentials"))}}else if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG508"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options argument was missing or invalid."))}_name=options.name;_pdsession=new progress.data.Session({_storageKey:_name,_silent:true,authenticationModel:options.authenticationModel,serviceURI:options.serviceURI,jsdosession:this,authProvider:options.authProvider});try{if(options.context){this.setContext(options.context)}_pdsession.subscribe("online",this._onlineHandler,this);_pdsession.subscribe("offline",this._offlineHandler,this)}catch(err){_pdsession=undefined;throw err}};progress.data.JSDOSession.prototype=new progress.util.Observable;progress.data.JSDOSession.prototype.constructor=progress.data.JSDOSession;function validateJSDOSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}listenerData.scope=args[2]}}progress.data.JSDOSession.prototype._eventNames=["offline","online"];progress.data.JSDOSession.prototype.validateSubscribe=validateJSDOSessionSubscribe;progress.data.JSDOSession.prototype.toString=function(radix){return"progress.data.JSDOSession"};progress.data.getSession=function(options){var deferred=new progress.util.Deferred,authProvider,promise,authProviderInitObject={};function sessionRejectHandler(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);if(authProvider&&authProvider.hasClientCredentials()){var callback=function(){deferred.reject(object.result,object.info)};authProvider.logout().then(callback,callback)}else{deferred.reject(object.result,object.info)}}function callbackRejectHandler(reason){deferred.reject(progress.data.Session.GENERAL_FAILURE,{reason:reason})}function loginHandler(object){var jsdosession;try{jsdosession=new progress.data.JSDOSession(options);try{jsdosession.isAuthorized().then(function(){return jsdosession.addCatalog(options.catalogURI)},sessionRejectHandler).then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(object.jsdosession,progress.data.Session.SUCCESS)},sessionRejectHandler)}catch(e){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}catch(ex){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:ex})}}function callLogin(provider){var errorObject;if(typeof options.loginCallback!=="undefined"){options.loginCallback().then(function(result){try{provider.login(result.username,result.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}},callbackRejectHandler)}else if(options.username&&options.password){try{provider.login(options.username,options.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG052","getSession()"));sessionRejectHandler(provider,progress.data.Session.AUTHENTICATION_FAILURE,{errorObject:errorObject})}}if(typeof options!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options","object"))}if(typeof options.loginCallback!=="undefined"&&typeof options.loginCallback!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options.loginCallback","function"))}try{if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){if(!options.authenticationURI||!options.authProviderAuthenticationModel){throw new Error(progress.data._getMsgText("jsdoMSG509"))}}if(options.authenticationURI){authProviderInitObject.uri=options.authenticationURI;authProviderInitObject.authenticationModel=options.authProviderAuthenticationModel;if(typeof authProviderInitObject.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG502","progress.data.getSession","object","getSession","authProviderAuthenticationModel"))}}else{authProviderInitObject.uri=options.serviceURI;authProviderInitObject.authenticationModel=options.authenticationModel}authProvider=new progress.data.AuthenticationProvider(authProviderInitObject);options.authProvider=authProvider;if(authProvider.hasClientCredentials()){loginHandler(authProvider)}else{if(authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){authProvider.login().then(loginHandler,sessionRejectHandler)}else{callLogin(authProvider)}}}catch(error){sessionRejectHandler(null,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}return deferred.promise()};progress.data.invalidateAllSessions=function(){var jsdosession,key,deferred=new progress.util.Deferred,jsdosessions=progress.data.ServicesManager._jsdosessions,invalidatePromises=[];try{for(key in jsdosessions){if(jsdosessions.hasOwnProperty(key)){jsdosession=jsdosessions[key];invalidatePromises.push(jsdosession.invalidate())}}progress.util.Deferred.when(invalidatePromises).then(function(){deferred.resolve(progress.data.Session.SUCCESS)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(progress.data.Session.GENERAL_FAILURE,info)})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()}})();if(typeof exports!=="undefined"){exports.progress=progress}(function(){"use strict";if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data.AuthenticationProvider=function AuthenticationProvider(initObject){var authProv,authModel,uri;if(typeof initObject==="object"){this._checkStringArg("constructor",initObject.authenticationModel,"initObject.authenticationModel","initObject.authenticationModel");this._checkStringArg("constructor",initObject.uri,"init-object.uri","init-object.uri")}else{throw new Error(progress.data._getMsgText("jsdoMSG033","AuthenticationProvider","the constructor","The init-object argument was missing or invalid."))}authModel=initObject.authenticationModel.toLowerCase();switch(authModel){case progress.data.Session.AUTH_TYPE_ANON:this._initialize(initObject.uri,progress.data.Session.AUTH_TYPE_ANON,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});authProv=this;break;case progress.data.Session.AUTH_TYPE_BASIC:authProv=new progress.data.AuthenticationProviderBasic(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM:authProv=new progress.data.AuthenticationProviderForm(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM_SSO:authProv=new progress.data.AuthenticationProviderSSO(initObject.uri);break;default:throw new Error(progress.data._getMsgText("jsdoMSG502","AuthenticationProvider","init-object","constructor","authenticationModel"))}return authProv};progress.data.AuthenticationProvider.prototype._loginProto=function(sendParam){var deferred=new progress.util.Deferred,xhr,uriForRequest,header,that=this;try{if(this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG051","AuthenticationProvider"))}xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLoginResult(xhr,deferred)}};if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(this._loginURI)}else{uriForRequest=this._loginURI}this._openLoginRequest(xhr,uriForRequest);xhr.setRequestHeader("Accept","application/json");xhr.send(sendParam)}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.login=function(){return this._loginProto()};progress.data.AuthenticationProvider.prototype._openLoginRequest=function(xhr,uri){xhr.open("GET",uri,true);progress.data.Session._setNoCacheHeaders(xhr)};progress.data.AuthenticationProvider.prototype._processLoginResult=function(xhr,deferred){var result;if(xhr.status===200){this._loggedIn=true;this._storeInfo();result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};progress.data.AuthenticationProvider.prototype.logout=function(){var deferred=new progress.util.Deferred;try{this._reset();deferred.resolve(this,progress.data.Session.SUCCESS,{})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.hasClientCredentials=function(){return this._loggedIn};progress.data.AuthenticationProvider.prototype.hasRefreshToken=function(){return false};progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);xhr.setRequestHeader("Accept","application/json");callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};progress.data.AuthenticationProvider.prototype._initialize=function(uriParam,authModel,targetURIs){var tempURI,target;Object.defineProperty(this,"uri",{get:function(){return this._uri},enumerable:true});Object.defineProperty(this,"authenticationModel",{get:function(){return this._authenticationModel},enumerable:true});if(uriParam[uriParam.length-1]==="/"){tempURI=uriParam.substring(0,uriParam.length-1)}else{tempURI=uriParam}for(target in targetURIs){if(targetURIs.hasOwnProperty(target)){this[target]=tempURI+targetURIs[target]}}this._authenticationModel=authModel;this._uri=uriParam;this._loggedIn=false;this._dataKeys={uri:".uri",loggedIn:".loggedIn"};if(typeof sessionStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","AuthenticationProvider","sessionStorage"))}this._storage=sessionStorage;this._storageKey=this._uri;this._dataKeys.uri=this._storageKey+this._dataKeys.uri;this._dataKeys.loggedIn=this._storageKey+this._dataKeys.loggedIn;if(this._retrieveLoggedIn()){this._loggedIn=true}};progress.data.AuthenticationProvider.prototype._storeInfo=function(){this._storage.setItem(this._dataKeys.uri,JSON.stringify(this._uri));this._storage.setItem(this._dataKeys.loggedIn,JSON.stringify(this._loggedIn))};progress.data.AuthenticationProvider.prototype._retrieveInfoItem=function(propName){var jsonStr=this._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value};progress.data.AuthenticationProvider.prototype._retrieveURI=function(){return this._retrieveInfoItem(this._dataKeys.uri)};progress.data.AuthenticationProvider.prototype._retrieveLoggedIn=function(){return this._retrieveInfoItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._clearInfo=function(info){this._storage.removeItem(this._dataKeys.uri);this._storage.removeItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._reset=function(){this._clearInfo();this._loggedIn=false};progress.data.AuthenticationProvider.prototype._settlePromise=function(deferred,result,info){if(result===progress.data.Session.SUCCESS){deferred.resolve(this,result,info)}else{deferred.reject(this,result,info)}};progress.data.AuthenticationProvider.prototype._checkStringArg=function(fnName,argToCheck,argPosition,argName){if(typeof argToCheck!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","AuthenticationProvider",argPosition,"string",fnName))}else if(argToCheck.length===0){throw new Error(progress.data._getMsgText("jsdoMSG501","AuthenticationProvider",argName,fnName))}};progress.data.AuthenticationProvider._getAuthFailureReason=function(xhr){var contentType,jsonObject,result=progress.data.Session.AUTHENTICATION_FAILURE;if(xhr.status===401){contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>-1&&xhr.responseText){jsonObject=JSON.parse(xhr.responseText);if(jsonObject.error==="sso.token.expired_token"){result=progress.data.Session.EXPIRED_TOKEN}}}else{result=null}return result};Object.defineProperty(progress.data.AuthenticationProvider,"_homeLoginURIBase",{value:"/static/home.html",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLoginURIBase",{value:"/static/auth/j_spring_security_check",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLogoutURIBase",{value:"/static/auth/j_spring_security_logout",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenLoginURIBase",{value:progress.data.AuthenticationProvider._springLoginURIBase+"?OECP=yes",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenRefreshURIBase",{value:"/static/auth/token?op=refresh",enumerable:true})})();(function(){"use strict";progress.data.AuthenticationProviderBasic=function(uri){var defaultiOSBasicAuthTimeout,userName=null,password=null,fn;this._initialize(uri,progress.data.Session.AUTH_TYPE_BASIC,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});this._reset();function make_basic_auth_header(user,pw){var tok=user+":"+pw,hash=btoa(tok);return"Basic "+hash}this._reset=function(){userName=null;password=null;progress.data.AuthenticationProviderBasic.prototype._reset.apply(this)};this._openLoginRequest=function(xhr,uri){var auth;xhr.open("GET",uri,true);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr)};this._processLoginResult=function _basic_processLoginResult(xhr,deferred){progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply(this,[xhr,deferred]);if(!this._loggedIn){userName=null;password=null}};this.login=function(userNameParam,passwordParam){this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");userName=userNameParam;password=passwordParam;return this._loginProto()};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var auth,errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr);callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}}};function BasicProxy(){}BasicProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderBasic.prototype=new BasicProxy;progress.data.AuthenticationProviderBasic.prototype.constructor=progress.data.AuthenticationProviderBasic})();(function(){"use strict";var fn;progress.data.AuthenticationProviderForm=function(uri){this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM,{_loginURI:progress.data.AuthenticationProvider._springLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase})};function FormProxy(){}FormProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderForm.prototype=new FormProxy;progress.data.AuthenticationProviderForm.prototype.constructor=progress.data.AuthenticationProviderForm;progress.data.AuthenticationProviderForm.prototype.login=function(userNameParam,passwordParam){var deferred=new progress.util.Deferred,xhr,that=this;this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");return this._loginProto("j_username="+encodeURIComponent(userNameParam)+"&j_password="+encodeURIComponent(passwordParam)+"&submit=Submit")};progress.data.AuthenticationProviderForm.prototype._openLoginRequest=function(xhr,uri){xhr.open("POST",uri,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.setRequestHeader("Pragma","no-cache");xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.withCredentials=true};progress.data.AuthenticationProviderForm.prototype.logout=function(){var deferred=new progress.util.Deferred,xhr,that=this;try{if(!this._loggedIn){deferred.resolve(this,progress.data.Session.SUCCESS,{})}else{xhr=new XMLHttpRequest;this._openLogoutRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLogoutResult(xhr,deferred)}};xhr.send()}this._reset()}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProviderForm.prototype._openLogoutRequest=function(xhr){xhr.open("GET",this._logoutURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Accept","application/json")};progress.data.AuthenticationProviderForm.prototype._processLogoutResult=function(xhr,deferred){var result;if(xhr.status===200){result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};fn=progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize;progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){function afterSuper(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.withCredentials=true;callback(xhr)}}try{progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply(this,[xhr,verb,uri,async,afterSuper])}catch(e){callback(e)}};progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super=fn})();(function(){"use strict";var fn;progress.data.AuthenticationProviderSSO=function(uri){var that=this,_automaticTokenRefresh,temp,ssoTokenInfo=null,tokenDataKeys={token:".access_token",refreshToken:".refresh_token",tokenType:".token_type",expiration:".expires_in",accessTokenExpiration:".accessTokenExpiration"};function storeTokenInfo(info){var date,accessTokenExpiration;if(info.access_token.length){that._storage.setItem(tokenDataKeys.token,JSON.stringify(info.access_token))}if(info.refresh_token.length){that._storage.setItem(tokenDataKeys.refreshToken,JSON.stringify(info.refresh_token));date=new Date;accessTokenExpiration=date.getTime()+info.expires_in*1e3*.75;that._storage.setItem(tokenDataKeys.accessTokenExpiration,JSON.stringify(accessTokenExpiration))}else{that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}that._storage.setItem(tokenDataKeys.tokenType,JSON.stringify(info.token_type));that._storage.setItem(tokenDataKeys.expiration,JSON.stringify(info.expires_in))}function retrieveTokenProperty(propName){var jsonStr=that._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}function retrieveToken(){return retrieveTokenProperty(tokenDataKeys.token)}function retrieveRefreshToken(){return retrieveTokenProperty(tokenDataKeys.refreshToken)}function retrieveAccessTokenExpiration(){return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration)}function retrieveTokenType(){return retrieveTokenProperty(tokenDataKeys.tokenType)}function getToken(){return retrieveToken()}function retrieveExpiration(){return retrieveTokenProperty(tokenDataKeys.expiration)}function clearTokenInfo(info){that._storage.removeItem(tokenDataKeys.token);that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.tokenType);that._storage.removeItem(tokenDataKeys.expiration);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}function openRefreshRequest(xhr){xhr.open("POST",that._refreshURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Content-Type","application/json");xhr.setRequestHeader("Accept","application/json")}function processRefreshResult(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",ex.message))}}else if(xhr.status===401){that._reset();result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}that._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})}this._processLoginResult=function(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){this._loggedIn=true;try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",ex.message))}if(result!==progress.data.Session.SUCCESS){var callback=function(params){params=progress.util.Deferred.getParamObject(params);params.provider._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})};this.logout().then(callback,callback);return}}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};this._reset=function(){progress.data.AuthenticationProviderSSO.prototype._reset.apply(this);clearTokenInfo();ssoTokenInfo=null};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var that=this,date,errorObject;function afterRefreshCheck(provider,result,info){if(result===progress.data.Session.AUTHENTICATION_FAILURE){callback(new Error(progress.data._getMsgText("jsdoMSG060")))}else{progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply(that,[xhr,verb,uri,async,function(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.setRequestHeader("Authorization","oecp "+getToken());callback(xhr)}}])}}if(this.hasClientCredentials()){date=new Date;if(this.automaticTokenRefresh&&this.hasRefreshToken()&&date.getTime()>retrieveAccessTokenExpiration()){try{var callback=function(params,result,info){params=progress.util.Deferred.getParamObject(params,result,info);afterRefreshCheck(params.provider,params.result,params.info)};this.refresh().then(callback,callback)}catch(e){callback(e)}}else{afterRefreshCheck(this,progress.data.Session.SUCCESS,null)}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};this.hasClientCredentials=function(){return retrieveToken()===null?false:true};this.refresh=function(){var deferred=new progress.util.Deferred,xhr;try{if(!this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG053","AuthenticationProvider","refresh"))}if(!this.hasRefreshToken()){throw new Error(progress.data._getMsgText("jsdoMSG054","AuthenticationProvider"))}xhr=new XMLHttpRequest;openRefreshRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){processRefreshResult(xhr,deferred)}};xhr.send('{"token_type":"'+retrieveTokenType()+'","refresh_token":"'+retrieveRefreshToken()+'"}')}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.hasRefreshToken=function(){return retrieveRefreshToken()===null?false:true};this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM_SSO,{_loginURI:progress.data.AuthenticationProvider._springFormTokenLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase,_refreshURI:progress.data.AuthenticationProvider._springFormTokenRefreshURIBase});_automaticTokenRefresh=true;Object.defineProperty(this,"automaticTokenRefresh",{get:function(){return _automaticTokenRefresh},set:function(value){if(value===true||value===false){_automaticTokenRefresh=value}else{throw new Error(progress.data._getMsgText("jsdoMSG061","AuthenticationProvider","automaticTokenRefresh"))}},enumerable:true});this._dataKeys.automaticTokenRefresh=this._storageKey+".automaticTokenRefresh";temp=this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh);if(temp===false){_automaticTokenRefresh=false}tokenDataKeys.token=this._storageKey+tokenDataKeys.token;tokenDataKeys.refreshToken=this._storageKey+tokenDataKeys.refreshToken;tokenDataKeys.tokenType=this._storageKey+tokenDataKeys.tokenType;tokenDataKeys.expiration=this._storageKey+tokenDataKeys.expiration;tokenDataKeys.accessTokenExpiration=this._storageKey+tokenDataKeys.accessTokenExpiration;if(retrieveToken()){this._loggedIn=true}};function SSOProxy(){}SSOProxy.prototype=progress.data.AuthenticationProviderForm.prototype;progress.data.AuthenticationProviderSSO.prototype=new SSOProxy;progress.data.AuthenticationProviderSSO.prototype.constructor=progress.data.AuthenticationProviderSSO;fn=progress.data.AuthenticationProviderSSO.prototype._storeInfo;progress.data.AuthenticationProviderSSO.prototype._storeInfo=function(){progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this);this._storage.setItem(this._dataKeys.automaticTokenRefresh,JSON.stringify(this._automaticTokenRefresh))};progress.data.AuthenticationProviderSSO.prototype._storeInfo._super=fn;fn=progress.data.AuthenticationProviderSSO.prototype._clearInfo;progress.data.AuthenticationProviderSSO.prototype._clearInfo=function(){progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this);this._storage.removeItem(this._dataKeys.automaticTokenRefresh)};progress.data.AuthenticationProviderSSO.prototype._clearInfo._super=fn})(); +(function(){var isNativeScript=false,isNodeJS=false;var pkg_xmlhttprequest="xmlhttprequest",pkg_nodeLocalstorage="node-localstorage",pkg_nativescriptLocalstorage="nativescript-localstorage",pkg_fileSystemAccess="file-system/file-system-access",pkg_base64="base-64";if(typeof XMLHttpRequest==="undefined"){isNodeJS=true;try{XMLHttpRequest=require(""+pkg_xmlhttprequest).XMLHttpRequest}catch(e){console.error("Error: JSDO library requires XMLHttpRequest object in Node.js.\n"+"Please install xmlhttprequest package.")}}if(!isNodeJS&&(typeof localStorage==="undefined"||typeof sessionStorage==="undefined")){try{require(""+pkg_fileSystemAccess);isNativeScript=true}catch(exception1){isNativeScript=false}}if(isNativeScript){try{if(typeof sessionStorage==="undefined"){sessionStorage=require(""+pkg_nativescriptLocalstorage)}if(typeof localStorage==="undefined"){localStorage=require(""+pkg_nativescriptLocalstorage)}}catch(exception2){console.error("Error: JSDO library requires localStorage and sessionStorage objects in NativeScript.\n"+"Please install nativescript-localstorage package.")}try{if(typeof btoa==="undefined"){btoa=require(""+pkg_base64).encode}}catch(exception3){console.error("Error: JSDO library requires btoa() function in NativeScript.\n"+"Please install base-64 package.")}}if(isNodeJS){var LocalStorage;if(typeof localStorage==="undefined"){try{var module=require(""+pkg_nodeLocalstorage);LocalStorage=module.LocalStorage;localStorage=new LocalStorage("./scratch1")}catch(e){console.error("Error: JSDO library requires localStorage and sessionStorage objects in Node.js.\n"+"Please install node-localstorage package.")}}if(typeof sessionStorage==="undefined"&&typeof LocalStorage!=="undefined"){sessionStorage=new LocalStorage("./scratch2")}try{if(typeof btoa==="undefined"){btoa=require(""+pkg_base64).encode}}catch(exception3){console.error("Error: JSDO library requires btoa() function in Node.js.\n"+"Please install base-64 package.")}}})();(function(){if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.util={};var STRING_OBJECT_TYPE="String",DATE_OBJECT_TYPE="Date",CHARACTER_ABL_TYPE="CHARACTER";progress.util.Deferred=function(){function Deferred(){this._deferred={}}Deferred.prototype.promise=function(){var that=this;if(progress.util.Deferred.useJQueryPromises){if(typeof $!=="undefined"&&typeof $.Deferred==="function"){this._deferred._jQuerydeferred=$.Deferred();this._promise=this._deferred._jQuerydeferred.promise()}else{throw new Error("JQuery Promises not found in environment.")}}else{this._promise=new Promise(function(resolve,reject){that._deferred.resolve=resolve;that._deferred.reject=reject})}if(this._resolveArguments||this._rejectArguments){setTimeout(function(){if(that._resolveArguments){that.resolve.apply(that,that._resolveArguments)}else if(that._rejectArguments){that.reject.apply(that,that._rejectArguments)}},500)}return this._promise};Deferred.prototype.resolve=function(arg1,arg2,arg3){if(this._promise){if(this._deferred._jQuerydeferred){this._deferred._jQuerydeferred.resolve.apply(this,arguments)}else{var object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3);this._deferred.resolve(object)}}else{this._resolveArguments=arguments}};Deferred.prototype.reject=function(arg1,arg2,arg3){if(this._promise){if(this._deferred._jQuerydeferred){this._deferred._jQuerydeferred.reject.apply(this,arguments)}else{var object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3);this._deferred.reject(object)}}else{this._rejectArguments=arguments}};Deferred.useJQueryPromises=false;Deferred.when=function(deferreds){if(progress.util.Deferred.useJQueryPromises){return $.when.apply($,deferreds)}else{return Promise.all(deferreds)}};Deferred.getParamObject1=function(arg1,arg2,arg3){var object={},objectName;try{if(typeof arg1==="undefined"||arg1===null){object.result=arg2;object.info=arg3}else{if(arg1 instanceof progress.data.JSDOSession){objectName="jsdosession"}else if(arg1 instanceof progress.data.AuthenticationProvider){objectName="provider"}else if(arg1 instanceof progress.data.JSDO){objectName="jsdo"}else if(typeof arg1==="number"){objectName="result"}else{objectName=typeof arg1}object[objectName]=arg1;if(objectName==="jsdo"){object.success=arg2;if(arg3&&arg3.xhr){object.request=arg3}else if(arg3&&arg3.batch){object.request=arg3}else{object.info=arg3}}else{if(objectName==="result"){object.info=arg2;if(arg3){object.info2=arg3}}else{object.result=arg2;object.info=arg3}}}}catch(e){console.log("Error: Undetermined argument in getParamObject() call.")}return object};Deferred.getParamObject=function(arg1,arg2,arg3){var object={};if(progress.util.Deferred.useJQueryPromises){object=progress.util.Deferred.getParamObject1(arg1,arg2,arg3)}else{if(typeof arg1==="undefined"){object.result=arg2;object.info=arg3;arg1=object}return arg1}return object};return Deferred}();progress.util.Observable=function(){function _filterObservers(observers,fn,scope,operation){return observers.filter(function(el){if(el.fn!==fn||el.scope!==scope||el.operation!==operation){return el}},this)}this.validateSubscribe=function(args,evt,listenerData){if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="string"){listenerData.operation=args[1];listenerData.fn=args[2];listenerData.scope=args[3]}else if(args.length>=2&&typeof args[0]==="string"&&typeof args[1]==="function"){listenerData.operation=undefined;listenerData.scope=args[2];listenerData.fn=args[1]}else{throw new Error}};this.subscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"subscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",progress.data._getMsgText("jsdoMSG039")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"subscribe",e.message))}observers=this._events[evt]||[];observers=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation);observers.push(listenerData);this._events[evt]=observers;return this};this.unsubscribe=function(evt,operation,fn,scope){var listenerData,observers;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"unsubscribe"))}if(typeof evt!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",progress.data._getMsgText("jsdoMSG037")))}this._events=this._events||{};evt=evt.toLowerCase();listenerData={fn:undefined,scope:undefined,operation:undefined};try{this.validateSubscribe(arguments,evt,listenerData)}catch(e){throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"unsubscribe",e.message))}observers=this._events[evt]||[];if(observers.length>0){this._events[evt]=_filterObservers(observers,listenerData.fn,listenerData.scope,listenerData.operation)}return this};this.trigger=function(evt,operation,args){var observers,op;if(!evt){throw new Error(progress.data._getMsgText("jsdoMSG037",this.toString(),"trigger"))}this._events=this._events||{};evt=evt.toLowerCase();observers=this._events[evt]||[];if(observers.length>0){args=Array.prototype.slice.call(arguments);if(arguments.length>=2&&typeof evt==="string"&&typeof operation==="string"){op=operation;args=args.length>2?args.slice(2):[]}else if(arguments.length>=1&&typeof evt==="string"){op=undefined;args=args.length>1?args.slice(1):[]}else{throw new Error(progress.data._getMsgText("jsdoMSG033",this.toString(),"trigger"))}observers.forEach(function(el){if(el.operation===op){el.fn.apply(el.scope,args)}})}return this};this.unsubscribeAll=function(evt,operation){var observers;if(evt){this._events=this._events||{};if(typeof evt==="string"){evt=evt.toLowerCase();observers=this._events[evt]||[];observers.forEach(function(el){if(el.operation){this.unsubscribe(evt,el.operation,el.fn,el.scope)}else{this.unsubscribe(evt,el.fn,el.scope)}},this)}}else{this._events={}}return this}};progress.data.LocalStorage=function LocalStorage(){if(typeof localStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","progress.data.LocalStorage","localStorage"))}this.saveToLocalStorage=function(name,dataObj){localStorage.setItem(name,JSON.stringify(dataObj))};this.readFromLocalStorage=function(name){var jsonStr=localStorage.getItem(name),dataObj=null;if(jsonStr!==null){try{dataObj=JSON.parse(jsonStr)}catch(e){dataObj=null}}return dataObj};this.clearLocalStorage=function(name){localStorage.removeItem(name)}};progress.util._convertToABLWhereString=function(tableRef,filter){var result=[],logic=filter.logic||"and",idx,length,field,fieldInfo,type,format,operator,value,ablType,filters=filter.filters||[filter],whereOperators={eq:"=",neq:"<>",gt:">",gte:">=",lt:"<",lte:"<=",contains:"INDEX",doesnotcontain:"INDEX",endswith:"R-INDEX",startswith:"BEGINS",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};for(idx=0,length=filters.length;idx 0"}else{format="{2} MATCHES '*{1}'"}}else{format="{2} {0} "+format}filter=progress.util._format(format,operator,value,field)}else if(operator&&value===undefined){if(filter.operator==="isempty"||filter.operator==="isnotempty"){ablType=tableRef._getABLType(field);if(ablType!==CHARACTER_ABL_TYPE){throw new Error("Error parsing filter object. The operator "+filter.operator+" requires a CHARACTER field")}if(filter.operator==="isempty"){format="{2} = ''"}else if(filter.operator==="isnotempty"){format="{2} <> ''"}}else{if(filter.operator==="isnull"){format="{2} = ?"}else if(filter.operator==="isnotnull"){format="{2} <> ?"}else{format="{2} {0} ?"}}filter=progress.util._format(format,operator,value,field)}}result.push(filter)}filter=result.join(" "+logic+" ");if(result.length>1){filter="("+filter+")"}return filter};progress.util._convertToSQLQueryString=function(tableRef,filter,addSelect){var result=[],logic=filter.logic||"and",idx,length,field,type,format,operator,value,fieldFormat,filters=filter.filters||[filter],filterStr,usingLike=true,whereOperators={eq:"=",neq:"!=",gt:">",gte:">=",lt:"<",lte:"<=",contains:"LIKE",doesnotcontain:"NOT LIKE",endswith:"LIKE",startswith:"LIKE",isnull:"ISNULL",isnotnull:"ISNOTNULL",isempty:"ISEMPTY",isnotempty:"ISNOTEMPTY"};if(typeof addSelect==="undefined"){addSelect=false}for(idx=0,length=filters.length;idx1){filterStr="("+filterStr+")"}if(addSelect===true){filterStr="SELECT * FROM "+tableRef._name+" WHERE "+filterStr}return filterStr};progress.util._getObjectType=function(value){return Object.prototype.toString.call(value).slice(8,-1)};progress.util._format=function(fmt){var values=arguments,formatRegExp=/\{(\d+)(:[^\}]+)?\}/g;return fmt.replace(formatRegExp,function(match,index,placeholderFormat){var value=values[parseInt(index,10)+1];return progress.util._toString(value,placeholderFormat?placeholderFormat.substring(1):"")})};progress.util._toString=function(value,fmt){var str;if(fmt){if(progress.util._getObjectType(value)==="Date"){return progress.util._formatDate(value,fmt)}}if(typeof value==="number"){str=value.toString()}else{str=value!==undefined?value:""}return str};progress.util._pad=function(number,digits){var zeros=["","0","00","000","0000"],end;number=String(number);digits=digits||2;end=digits-number.length;if(end){return zeros[digits].substring(0,end)+number}return number};progress.util._formatDate=function(date,format){var dateFormatRegExp=/dd|MM|yyyy|hh|mm|fff|FFF|ss|zzz|iso|"[^"]*"|'[^']*'/g;return format.replace(dateFormatRegExp,function(match){var minutes,result,sign;if(match==="dd"){result=progress.util._pad(date.getDate())}else if(match==="MM"){result=progress.util._pad(date.getMonth()+1)}else if(match==="yyyy"){result=progress.util._pad(date.getFullYear(),4)}else if(match==="hh"){result=progress.util._pad(date.getHours())}else if(match==="mm"){result=progress.util._pad(date.getMinutes())}else if(match==="ss"){result=progress.util._pad(date.getSeconds())}else if(match==="fff"){result=progress.util._pad(date.getMilliseconds(),3)}else if(match==="FFF"){result=String(date.getTime())}else if(match==="zzz"){minutes=date.getTimezoneOffset();sign=minutes<0;result=(sign?"+":"-")+minutes}else if(match==="iso"){result=date.toISOString()}return result!==undefined?result:match.slice(1,match.length-1)})};progress.util.jsdoSettingsProcessor=function jsdoSettingsProcessor(jsdoSettings){if(typeof jsdoSettings==="object"){if(jsdoSettings.authenticationModel===undefined||jsdoSettings.authenticationModel===""){jsdoSettings.authenticationModel="ANONYMOUS"}}}})();(function(){var PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS=20,PROGRESS_JSDO_OP_STRING=["none","create","read","update","delete","submit"],PROGRESS_JSDO_ROW_STATE_STRING=["","created","","modified","deleted"];if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data._nextid=0;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime());var UID_MAX_VALUE=999999999999999;progress.data._getNextId=function(){var uid=++progress.data._nextid;if(uid>=UID_MAX_VALUE){progress.data._nextid=uid=1;progress.data._uidprefix=""+(Date.now?Date.now():(new Date).getTime())}return progress.data._uidprefix+"-"+uid};var msg={};msg.msgs={};msg.msgs.jsdoMSG000="JSDO, Internal Error: {1}";msg.msgs.jsdoMSG001="JSDO: JSDO has multiple tables. Please use {1} at the table reference level.";msg.msgs.jsdoMSG002="JSDO: Working record for '{1}' is undefined.";msg.msgs.jsdoMSG003="JSDO: {1} function requires a function as a parameter.";msg.msgs.jsdoMSG004="JSDO: Unable to find resource '{1}' in the catalog.";msg.msgs.jsdoMSG005="JSDO: Data for table '{1}' was not specified in addRecords() call.";msg.msgs.jsdoMSG006="JSDO: Data for JSDO was not specified in addRecords() call.";msg.msgs.jsdoMSG007="JSDO: Test function in {1} must return a boolean.";msg.msgs.jsdoMSG008="JSDO: Invalid keyFields parameter in addRecords() call.";msg.msgs.jsdoMSG009="JSDO: KeyField '{1}' in addRecords() call was not found in the schema.";msg.msgs.jsdoMSG010="JSDO: Field '{1}' in relationship was not found in the schema.";msg.msgs.jsdoMSG011="UIHelper: JSDO has multiple tables. "+"Please use {1} at the table reference level.";msg.msgs.jsdoMSG012="UIHelper: Invalid {2} parameter in {1} call.";msg.msgs.jsdoMSG020="JSDO: tableName parameter must be a string in addRecords() call.";msg.msgs.jsdoMSG021="JSDO: addMode parameter must be specified in addRecords() call.";msg.msgs.jsdoMSG022="JSDO: Invalid addMode specified in addRecords() call.";msg.msgs.jsdoMSG023="JSDO: Duplicate found in addRecords() call using APPEND mode.";msg.msgs.jsdoMSG024="{1}: Unexpected signature in call to {2} function.";msg.msgs.jsdoMSG025="{1}: Invalid parameters in call to {2} function.";msg.msgs.jsdoMSG026="JSDO: saveChanges requires a "+"CREATE, UPDATE, DELETE or SUBMIT operation to be defined.";msg.msgs.jsdoMSG030="JSDO: Invalid {1}, expected {2}.";msg.msgs.jsdoMSG031="JSDO: Specified sort field name '{1}' was not found in the schema.";msg.msgs.jsdoMSG032="JSDO: Before-image data already exists for record in addRecords() call.";msg.msgs.jsdoMSG033="{1}: Invalid signature for {2}. {3}";msg.msgs.jsdoMSG034="JSDO: In '{1}' function, JSON data is missing _id";msg.msgs.jsdoMSG035="JSDO: In '{1}' function, before-image JSON data is missing prods:clientId";msg.msgs.jsdoMSG036="JSDO: '{1}' can only be called for a dataset";msg.msgs.jsdoMSG037="{1}: Event name must be provided for {2}.";msg.msgs.jsdoMSG038="Too few arguments. There must be at least {1}.";msg.msgs.jsdoMSG039="The name of the event is not a string.";msg.msgs.jsdoMSG040="The event listener is not a function.";msg.msgs.jsdoMSG041="The event listener scope is not an object.";msg.msgs.jsdoMSG042="'{1}' is not a defined event for this object.";msg.msgs.jsdoMSG043="{1}: A session object was requested to check the status of a Mobile "+"Service named '{2}', but it has not loaded the definition of that service.";msg.msgs.jsdoMSG044="JSDO: In '{1}' function, {2} is missing {3} property.";msg.msgs.jsdoMSG045="JSDO: {1} function: {2} is missing {3} property.";msg.msgs.jsdoMSG046="JSDO: {1} operation is not defined.";msg.msgs.jsdoMSG047="{1} timeout expired.";msg.msgs.jsdoMSG048="{1}: {2} method has argument '{3}' that is missing property '{4}'.";msg.msgs.jsdoMSG049="{1}: Unexpected error calling {2}: {3}";msg.msgs.jsdoMSG050="No token returned from server";msg.msgs.jsdoMSG051="{1} The login method was not executed because the AuthenticationProvider is already logged in.";msg.msgs.jsdoMSG052="{1}: The login method was not executed because no credentials were supplied.";msg.msgs.jsdoMSG053="{1}: {2} was not executed because the AuthenticationProvider is not logged in.";msg.msgs.jsdoMSG054="{1}: Token refresh was not executed because the AuthenticationProvider does not have a refresh token.";msg.msgs.jsdoMSG055="{1}: Token refresh was not executed because the authentication model is not sso.";msg.msgs.jsdoMSG056="{1}: Already logged in.";msg.msgs.jsdoMSG057="{1}: Cannot call {2} when authenticationModel is SSO. Please use the AuthenticationProvider object instead.";msg.msgs.jsdoMSG058="{1}: Cannot pass username and password to addCatalog when authenticationModel "+"is sso. Pass an AuthenticationProvider instead.";msg.msgs.jsdoMSG059="{1}: Error in constructor. The authenticationModels of the "+"AuthenticationProvider ({2}) and the JSDOSession ({3}) were not compatible.";msg.msgs.jsdoMSG060="AuthenticationProvider: AuthenticationProvider is no longer logged in. "+"Tried to refresh SSO token but failed due to authentication error at token server.";msg.msgs.jsdoMSG061="{1}: Attempted to set {2} property to an invalid value.";msg.msgs.jsdoMSG062="{1}: Cannot call {2} when an AuthenticationProvider is already available and logged in.";msg.msgs.jsdoMSG100="JSDO: Unexpected HTTP response. Too many records.";msg.msgs.jsdoMSG101="Network error while executing HTTP request.";msg.msgs.jsdoMSG110="Catalog error: idProperty not specified for resource '{1}'. "+"idProperty is required {2}.";msg.msgs.jsdoMSG111="Catalog error: Schema '{1}' was not found in catalog.";msg.msgs.jsdoMSG112="Catalog error: Output parameter '{1}' was not found for operation '{2}'.";msg.msgs.jsdoMSG113="Catalog error: Found xType '{1}' for output parameter '{2}' "+"for operation '{3}' but xType DATASET, TABLE or ARRAY was expected.";msg.msgs.jsdoMSG114="JSDO: idProperty '{1}' is missing from '{2}' record.";msg.msgs.jsdoMSG115="JSDO: Invalid option specified in {1}() call.";msg.msgs.jsdoMSG116="JSDO: {1} parameter must be a string in {2} call.";msg.msgs.jsdoMSG117="JSDO: Schema from storage area '{1}' does not match JSDO schema";msg.msgs.jsdoMSG118="JSDO: Plugin '{1}' was not found.";msg.msgs.jsdoMSG119="JSDO: A mappingType is expected when 'capabilities' is set."+" Please specify a plugin (ex: JFP).";msg.msgs.jsdoMSG120="JSDO: Parameter '{2}' requires capability '{1}' in the catalog.";msg.msgs.jsdoMSG121="{1}: Argument {2} must be of type {3} in {4} call.";msg.msgs.jsdoMSG122="{1}: Incorrect number of arguments in {2} call. There should be {3}.";msg.msgs.jsdoMSG123="{1}: A server response included an invalid '{2}' header.";msg.msgs.jsdoMSG124="JSDO: autoApplyChanges is not supported for saveChanges(true) "+"with a temp-table. Use jsdo.autoApplyChanges = false.";msg.msgs.jsdoMSG125="{1}: The AuthenticationProvider is not managing valid credentials.";msg.msgs.jsdoMSG126="{1}: No support for {2}.";msg.msgs.jsdoMSG127="JSDO: acceptRowChanges() cannot be called for record with _rejected === true.";msg.msgs.jsdoMSG500="{1}: '{2}' objects must contain a '{3}' property.";msg.msgs.jsdoMSG501="{1}: '{2}' in '{3}' function cannot be an empty string.";msg.msgs.jsdoMSG502="{1}: The '{2}' parameter passed to the '{3}' function has an invalid value for "+"its '{4}' property.";msg.msgs.jsdoMSG503="{1}: '{2}' must be of type '{3}'.";msg.msgs.jsdoMSG504="{1}: {2} has an invalid value for the '{3}' property.";msg.msgs.jsdoMSG505="{1}: '{2}' objects must have a '{3}' method.";msg.msgs.jsdoMSG506="{1}: Invalid argument for the {2} parameter in {3} call.";msg.msgs.jsdoMSG507="{1}: '{2}' is an invalid value for the {3} parameter in {4} call.";msg.msgs.jsdoMSG508="JSDOSession: If a JSDOSession object is using the SSO authentication model, "+"the options object passed to its constructor must include an authProvider property.";msg.msgs.jsdoMSG509="progress.data.getSession: If the authenticationModel is AUTH_TYPE_SSO, "+"authenticationURI and authProviderAuthenticationModel are required parameters.";msg.msgs.jsdoMSG510="{1}: This session has been invalidated and cannot be used.";msg.msgs.jsdoMSG511="JSDOSession: addCatalog() can only be called if an AuthenticationProvider was passed as an argument or "+"connect() has been successfully called.";msg.msgs.jsdoMSG512="JSDOSession: Error while loading multiple catalogs.";msg.msgs.jsdoMSG998="JSDO: JSON object in addRecords() must be DataSet or Temp-Table data.";msg.getMsgText=function(n,args){var text=msg.msgs[n],i;if(!text){throw new Error("Message text was not found by getMsgText()")}for(i=1;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true;data=newDataArray}else{if(params&&(params.sort||params.top)){newDataArray=[];for(i=0;i0){sortObject.tableRef=this;data.sort(this._getCompareFn(sortObject))}}if(params.top){if(typeof params.skip=="undefined"){params.skip=0}data=data.splice(params.skip,params.top)}}return data};this._recToDataObject=function(record,includeChildren){var array=[record];var dataObject=array;if(typeof includeChildren=="undefined"){includeChildren=false}if(this._jsdo._dataSetName){dataObject={};dataObject[this._jsdo._dataSetName]={};dataObject[this._jsdo._dataSetName][this._name]=array;if(includeChildren&&this._children.length>0){var jsrecord=this._findById(record._id,false);if(jsrecord){for(var i=0;i0){for(var j=0;j0){for(var i=0;i=PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS)this._needCompaction=true};this._equalRecord=function(rec1,rec2,keyFields){var field;var match=true;for(var i=0;ivalue2||(value1===undefined||value1===null))return sortAscending[i]?1:-1;else if(value10)this._sort(sortObject)}else{this._sort(arg1)}this._createIndex()};this._sort=function(arg1){if(arguments.length===0&&(!this.autoSort||this._sortFn===undefined&&this._sortObject.sortFields===undefined))return;if(arguments.length===0){if(this._sortFn){this._data.sort(this._sortFn)}else{this._data.sort(this._compareFields)}this._needsAutoSorting=false}else{if(typeof arg1=="function"){this._data.sort(this._getCompareFn(arg1))}else{arg1.tableRef=this;this._data.sort(this._getCompareFn(arg1))}if(this.autoSort)this._needsAutoSorting=true}};this.addRecords=function(jsonObject,addMode,keyFields,trackChanges,isInvoke){this._jsdo._addRecords(this._name,jsonObject,addMode,keyFields,trackChanges,isInvoke)};this.acceptChanges=function(){var tableRef=this;for(var id in tableRef._beforeImage){if(tableRef._beforeImage[id]===null){var jsrecord=tableRef._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}else if(this._changed[id]!==undefined){var jsrecord=this._findById(id,false);if(jsrecord!==null){tableRef._jsdo._deleteProdsProperties(jsrecord.data,true)}}}tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[];tableRef._beforeImage={}};this.rejectChanges=function(){for(var id in this._beforeImage){if(this._beforeImage[id]===null){this._jsdo._undoCreate(this,id)}else if(this._changed[id]!==undefined){this._jsdo._undoUpdate(this,id,true)}else{this._jsdo._undoDelete(this,id,true)}}var tableRef=this;tableRef._processed={};tableRef._added=[];tableRef._changed={};tableRef._deleted=[]};this.hasChanges=function(){return Object.keys(this._beforeImage).length!==0};this.getChanges=function(){var result=[];for(var id in this._beforeImage){var item={rowState:"",record:null};if(this._beforeImage[id]===null){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_CREATE];item.record=this._findById(id,false)}else if(this._changed[id]!==undefined){item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_UPDATE];item.record=this._findById(id,false)}else{item.rowState=PROGRESS_JSDO_ROW_STATE_STRING[progress.data.JSDO._OP_DELETE];item.record=new progress.data.JSRecord(this,this._beforeImage[id])}result.push(item)}return result};this._clearErrorStrings=function(){var record=null;for(var id in this._beforeImage){if(this._beforeImage[id]===null){record=this._findById(id,false);if(record){delete record.data._errorString}}else{record=this._findById(id,false);if(record){delete record.data._errorString}else{delete this._beforeImage[id]._errorString}}}};this._applyChanges=function(){var i;for(var id in this._beforeImage){if(this._beforeImage[id]===null){var jsrecord=this._findById(id,false);if(jsrecord===null&&this._jsdo._resource.idProperty!==undefined){if(this._tmpIndex[id]){var record=this._data[this._tmpIndex[id].index];jsrecord=record?new progress.data.JSRecord(this,record):null;delete this._tmpIndex[id]}}if(jsrecord!==null){if(jsrecord.data._rejected||jsrecord.data._errorString!==undefined){this._jsdo._undoCreate(this,id)}else{jsrecord.acceptRowChanges()}}else{var found=false;for(var i=0;i0){for(var i=0;iindex){i--}if(i!=index){this._tableRef._data.splice(index,1);this._tableRef._data.splice(i,0,record);this._tableRef._createIndex()}}}};this.assign=function(record){if(record===undefined)throw new Error(msg.getMsgText("jsdoMSG024","JSDO","assign() or update()"));this._saveBeforeImageUpdate();var fieldName,i,j,value,schema=this._tableRef.getSchema(),prefixElement,name;if(record){for(i=0;i0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){return this.record.data[name][element-1]}}return this.record.data[fieldName]}else return null},set:function(value){var name=fieldName,index,element,fieldInfo;if(this.record){this.record._saveBeforeImageUpdate();try{index=fieldName.indexOf(progress.data.JSDO.ARRAY_INDEX_SEPARATOR);if(index>0&&!this._fields[fieldName.toLowerCase()]){name=fieldName.substring(0,index);element=fieldName.substring(index+progress.data.JSDO.ARRAY_INDEX_SEPARATOR.length);fieldInfo=this._fields[name.toLowerCase()];if(!isNaN(element)&&fieldInfo&&fieldInfo.type==="array"){this.record.data[name][element-1]=value;return}}this.record.data[fieldName]=value}finally{this.record._sortRecord(name)}}},enumerable:true,writeable:true})};Object.defineProperty(this,"hasSubmitOperation",{get:function(){return this._hasSubmitOperation},enumerable:true});Object.defineProperty(this,"hasCUDOperations",{get:function(){return this._hasCUDOperations},enumerable:true});Object.defineProperty(this,"defaultTableRef",{get:function(){return this._defaultTableRef},enumerable:true});this._buffers={};this._numBuffers=0;this._defaultTableRef=null;this._async=true;this._dataProperty=null;this._dataSetName=null;this.operations=[];this.useRelationships=true;this._session=null;this._needCompaction=false;this._hasCUDOperations=false;this._hasSubmitOperation=false;this._useSubmit=false;this.autoApplyChanges=true;this._lastErrors=[];this._localStorage=null;this._convertForServer;this._fillMergeMode;var autoFill=false;if(!arguments[0]){throw new Error("JSDO: Parameters are required in constructor.")}if(typeof arguments[0]=="string"){this.name=arguments[0]}else if(typeof arguments[0]=="object"){var args=arguments[0];for(var v in args){switch(v){case"autoFill":autoFill=args[v];break;case"events":this._events={};for(var eventName in args[v]){this._events[eventName.toLowerCase()]=args[v][eventName]}break;case"dataProperty":this._dataProperty=args[v];break;default:this[v]=args[v]}}}if(!this.name){throw new Error("JSDO: JSDO constructor is missing the value for 'name'")}if(this._events){if(typeof this._events!=="object"){throw new Error("JSDO: JSDO constructor event object is not defined as an object")}for(var prop in this._events){var evt=this._events[prop];if(!(evt instanceof Array)){throw new Error("JSDO: JSDO constructor event object for "+prop+" must be an array")}evt.forEach(function(el){if(typeof el!=="object"){throw new Error("JSDO: JSDO constuctor event object for "+prop+" is not defined as an object")}if(typeof el.fn!=="function"){throw new Error("JSDO: JSDO event listener for "+prop+" is not a function.")}if(el.scope&&typeof el.scope!=="object"){throw new Error("JSDO: JSDO event listener scope for "+prop+" is not an object.")}})}}if(this.name){this._resource=progress.data.ServicesManager.getResource(this.name);if(this._resource){if(!this.url)this.url=this._resource.url;if(!this._dataSetName&&this._resource._dataSetName){this._dataSetName=this._resource._dataSetName;if(this._resource.dataProperty){var buffer=this[this._resource.dataProperty]=new progress.data.JSTableRef(this,this._resource.dataProperty);this._buffers[this._resource.dataProperty]=buffer}else{for(var tableName in this._resource.fields){var buffer=this[tableName]=new progress.data.JSTableRef(this,tableName);this._buffers[tableName]=buffer}}}if(!this._dataProperty&&this._resource.dataProperty)this._dataProperty=this._resource.dataProperty;if(!this._dataSetName){var tableName=this._dataProperty?this._dataProperty:"";this._buffers[tableName]=new progress.data.JSTableRef(this,tableName);if(tableName)this[tableName]=this._buffers[tableName]}var properties,tableName;if(this._dataSetName&&this._resource.schema&&this._resource.schema.properties[this._dataSetName]){properties=this._resource.schema.properties[this._dataSetName].properties;if(Object.keys(properties).length===1){tableName=Object.keys(properties)[0];if(properties[tableName].idProperty){this._resource.idProperty=properties[tableName].idProperty}}}else if(this._resource.schema&&this._resource.schema.properties&&this._resource.schema.properties[tableName]&&this._resource.schema.properties[tableName].idProperty){this._resource.idProperty=this._resource.schema.properties[tableName].idProperty}for(var fnName in this._resource.fn){this[fnName]=this._resource.fn[fnName]["function"]}this._hasCUDOperations=this._resource.generic["create"]!==undefined||this._resource.generic["update"]!==undefined||this._resource.generic["delete"]!==undefined;this._hasSubmitOperation=this._resource.generic["submit"]!==undefined;if(!this._session){var myservice=progress.data.ServicesManager.getService(this._resource.service.name);this._session=myservice._session;this._session._pushJSDOs(this)}}else{throw new Error(msg.getMsgText("jsdoMSG004",this.name))}}else{this._buffers[""]=new progress.data.JSTableRef(this,"")}if(!this._session){throw new Error("JSDO: Unable to get user session for resource '"+this.name+"'")}for(var buf in this._buffers){this._buffers[buf]._parent=null;this._buffers[buf]._children=[];this._buffers[buf]._relationship=null;this._buffers[buf]._isNested=false;if(!this._defaultTableRef)this._defaultTableRef=this._buffers[buf];this._numBuffers++}if(this._numBuffers!=1)this._defaultTableRef=null;else{this.record=null}if(typeof Object.defineProperty=="function"){this._caseSensitive=false;Object.defineProperty(this,"caseSensitive",{get:function(){return this._caseSensitive},set:function(value){this._caseSensitive=value?true:false;for(var buf in this._buffers){this._buffers[buf].caseSensitive=this._caseSensitive}},enumerable:true,writeable:true});this._autoSort=true;Object.defineProperty(this,"autoSort",{get:function(){return this._autoSort},set:function(value){this._autoSort=value?true:false;for(var buf in this._buffers){this._buffers[buf].autoSort=this._autoSort}},enumerable:true,writeable:true})}this._properties={};if(typeof Object.defineProperty=="function"){Object.defineProperty(this,"this._properties",{get:function(){return this._properties},enumerable:false})}if(this._resource&&this._resource.fields){for(var buf in this._buffers){this._buffers[buf]._schema=this._resource.fields[buf];this._buffers[buf]._primaryKeys=this._resource.primaryKeys[buf];this._buffers[buf]._fields={};var fields=this._buffers[buf]._schema;for(var i=0;i1){for(var buf in this._buffers){var fields=[];var found=false;for(var i=0;i=0?index+1:"");element.value=value?value[index]:undefined;return element};this.isDataSet=function(){return this._dataSetName?true:false};this._invokeComplete=function(jsdo,success,request){if(request.async&&request.fnName){jsdo.trigger("afterInvoke",request.fnName,jsdo,success,request)}if(request.deferred){if(success){request.deferred.resolve(jsdo,success,request)}else{request.deferred.reject(jsdo,success,request)}}};this._invokeSuccess=function(){};this._invokeError=function(){};this._httpRequest=function(xhr,method,url,reqBody,request){function afterOpenRequest(){var input=null;if(reqBody){xhr.setRequestHeader("Content-Type","application/json; charset=utf-8");input=JSON.stringify(reqBody)}try{xhr.send(input)}catch(e){request.success=false;request.exception=e;xhr.jsdo._session._checkServiceResponse(xhr,request.success,request)}}if(!xhr){xhr=new XMLHttpRequest;xhr.onCompleteFn=this._invokeComplete;xhr.onSuccessFn=this._invokeSuccess;xhr.onErrorFn=this._invokeError;xhr.onreadystatechange=this.onReadyStateChangeGeneric;if(request.async&&request.fnName){this.trigger("beforeInvoke",request.fnName,this,request)}if(reqBody){if(this._resource&&this._resource.service){var useRequest=this._resource.service.useRequest;if(this._resource.service.settings&&this._resource.service.settings.useRequest!==undefined){useRequest=this._resource.service.settings.useRequest}if(useRequest){reqBody={request:reqBody}}}}}xhr.request=request;xhr.jsdo=this;request.jsdo=this;request.xhr=xhr;this._session._openRequest(xhr,method,url,request.async,afterOpenRequest);return request};this._getDataObject=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};var oldUseRelationships=this.useRelationships;try{this.useRelationships=false;for(var buf in this._buffers){dataObject[this._dataSetName][buf]=this._buffers[buf].getData()}}finally{this.useRelationships=oldUseRelationships}}else{if(this._dataProperty){dataObject[this._dataProperty]=this.getData()}else return this.getData()}return dataObject};this._getDataObjectAsNested=function(){var dataObject={};if(this._dataSetName){dataObject[this._dataSetName]={};try{for(var buf in this._buffers){var bufObj=this._buffers[buf];if(bufObj._isNested)continue;this._nestChildren=false;if(bufObj._children.length>0){for(var i=0;i0){hasErrors=true}}if(hasErrors){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._allRecordsRejected=true;this._someRecordsRejected=false;hasCommittedRecords=false;for(i=0;i0&&!param.operations[0].success){this._allRecordsRejected=true;this._someRecordsRejected=true;for(i=0;i0){this._convertForServer=true;this._buffers[buf]._convertForServer=true}}};this._convertRequestData=function(objParam){var buf,beforeData;if(this._convertForServer===false){return}for(buf in this._buffers){if(this._buffers[buf]._convertForServer){if(objParam[this._dataSetName]){if(objParam[this._dataSetName][buf]){this._convertTableData(this._buffers[buf],objParam[this._dataSetName][buf])}beforeData=objParam[this._dataSetName]["prods:before"];if(beforeData&&beforeData[buf]){this._convertTableData(this._buffers[buf],beforeData[buf])}}else if(objParam[buf]){this._convertTableData(this._buffers[buf],objParam[buf])}}}};this._convertTableData=function(tableRef,tableData){var i;for(i=0;i0){this._confirmOperationExists(progress.data.JSDO._OP_DELETE);checkedDelete=true}if(!checkedCreate&&tableRef._added.length>0){this._confirmOperationExists(progress.data.JSDO._OP_CREATE);checkedCreate=true}if(!checkedUpdate&&Object.keys(tableRef._changed).length>0){this._confirmOperationExists(progress.data.JSDO._OP_UPDATE);checkedUpdate=true}if(checkedDelete&&checkedCreate&&checkedUpdate){break}}};this._confirmOperationExists=function(operation){var operationStr=PROGRESS_JSDO_OP_STRING[operation];if(typeof this._resource.generic[operationStr]!=="function"){throw new Error(msg.getMsgText("jsdoMSG046",operationStr.toUpperCase()))}};this.invoke=function(name,object){var deferred,promise;try{var request=this[name](object);if(request.deferred){deferred=request.deferred;promise=request.deferred.promise()}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{if(!deferred){deferred=new progress.util.Deferred;promise=deferred.promise()}deferred.reject(this,false,{errorObject:error})}}return promise};this._syncTableRef=function(operation,tableRef,batch){var rowData,requestData,jsonObject,dataSetObject;if(tableRef._visited)return;tableRef._visited=true;if(!batch){batch={operations:[]}}else if(!batch.operations){batch.operations=[]}switch(operation){case progress.data.JSDO._OP_CREATE:for(var i=0;i0&&!dataSetJsonObject[tableRef._name])dataSetJsonObject[tableRef._name]=[];for(var i=0;i0||tableRef._added.length>0||hasUpdates){hasChanges=true;break}}return hasChanges};this._addDeletesToChangeSet=function(tableRef,dataSetJsonObject,request){for(var i=0;i=10){tmpIndex={};for(var i=0;ivalue2||value1===null)return false;else if(value11){for(var buf in this._buffers){if(this._buffers[buf]._isNested&&this._buffers[buf]._parent&&this._buffers[this._buffers[buf]._parent]){var srcData=this._buffers[this._buffers[buf]._parent]._data;var data=[];for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}for(var i=0;i1){xhr.request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}var recordId=beforeTableJsonObject[0]["prods:clientId"];if(!recordId){throw new Error(msg.getMsgText("jsdoMSG035","_checkForDeleteError()"))}if(beforeTableJsonObject[0]["prods:hasErrors"]){var prods_id=beforeTableJsonObject[0]["prods:id"];var errorString=this._getErrorStringFromJsonObject(dataSetJsonObject,tableRef,prods_id);this._setErrorString(tableRef,recordId,errorString,true);hasError=true}}return hasError};this._mergeUpdateForSubmit=function(jsonObject,xhr){var errorString;if(!this._dataSetName){throw new Error(msg.getMsgText("jsdoMSG036","_mergeUpdateForSubmit()"))}var dataSetJsonObject=jsonObject[this._dataSetName];if(dataSetJsonObject[this._dataSetName])dataSetJsonObject=dataSetJsonObject[this._dataSetName];var beforeJsonObject=dataSetJsonObject["prods:before"];for(var buf in this._buffers){var tableRef=this._buffers[buf];var tableJsonObject=dataSetJsonObject[tableRef._name];if(tableJsonObject instanceof Array){for(var i=0;i1){request.success=false;throw new Error(msg.getMsgText("jsdoMSG100"))}}if(beforeJsonObject){hasError=jsdo._checkForDeleteError(dataSetJsonObject,xhr)}if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._deleteError(jsdo,success,request)}}};this._deleteError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoDelete(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._createComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterCreate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterCreate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._createSuccess=function(jsdo,success,request){var xhr=request.xhr;var record=request.response;var hasError=jsdo._mergeUpdateForCUD(record,xhr);if(hasError)request.success=false;if(jsdo.autoApplyChanges){if(!hasError){delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._createError(jsdo,success,request)}}};this._createError=function(jsdo,success,request){if(jsdo.autoApplyChanges){jsdo._undoCreate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._updateComplete=function(jsdo,success,request){var xhr=request.xhr;var jsrecord=request.jsrecord;try{jsdo._deleteProdsProperties(jsrecord.data,false);jsrecord._tableRef.trigger("afterUpdate",jsdo,jsrecord,request.success,request);jsdo.trigger("afterUpdate",jsdo,jsrecord,request.success,request)}finally{request.complete=true;jsdo._checkSaveComplete(xhr)}};this._updateSuccess=function(jsdo,success,request){var xhr=request.xhr;var hasError=jsdo._mergeUpdateForCUD(request.response,xhr);if(hasError){request.success=false}if(jsdo.autoApplyChanges){if(!hasError){request.success=true;delete request.jsrecord._tableRef._beforeImage[request.jsrecord.data._id]}else{jsdo._updateError(jsdo,success,request)}}};this._updateError=function(jsdo,success,request){if(jsdo.autoApplyChanges){request.success=false;jsdo._undoUpdate(request.jsrecord._tableRef,request.jsrecord.data._id)}};this._saveChangesSuccess=function(jsdo,success,request){var records=request.response;jsdo._mergeUpdateForSubmit(records,request.xhr);jsdo._clearErrors();var changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(changes);if(jsdo.autoApplyChanges){jsdo._applyChanges()}};this._saveChangesError=function(jsdo,success,request){jsdo._setAllRecordsRejected(true);if(jsdo.autoApplyChanges){jsdo.rejectChanges()}jsdo._updateLastErrors(jsdo,null,null,request)};this._saveChangesSuccessTT=function(jsdo,success,request){var changes;jsdo._clearErrors();changes=jsdo.getChanges();jsdo._updateLastErrors(jsdo,null,changes);jsdo._setAllRecordsRejected(false)};this._saveChangesComplete=function(jsdo,success,request){if(request.xhr.status>=200&&request.xhr.status<300&&(jsdo._lastErrors.length>0||jsdo._someRecordsRejected)){request.success=false}if(jsdo._useSubmit===true){jsdo._fireCUDTriggersForSubmit(request)}jsdo._undefWorkingRecord();jsdo._fireAfterSaveChanges(request.success,request)};this._fireAfterSaveChanges=function(success,request){this.trigger("afterSaveChanges",this,success,request);if(request.jsrecords){if(request.deferred){if(success){request.deferred.resolve(this,success,request)}else{request.deferred.reject(this,success,request)}}}else if(request.batch&&request.batch.deferred){if(success){request.batch.deferred.resolve(this,success,request)}else{request.batch.deferred.reject(this,success,request)}}var clearErrorString=this.autoApplyChanges;if(request.jsrecords){for(var idx=0;idx=400&&request.xhr.status<600){try{var responseObject=JSON.parse(request.xhr.responseText);if(responseObject instanceof Array){errorArray=responseObject}else if(responseObject instanceof Object){errorArray.push(responseObject)}for(i=0;i=400&&request.xhr.status<600)){errors.push({type:progress.data.JSDO.ERROR,error:"Error: HTTP Status "+request.xhr.status+" "+request.xhr.statusText,responseText:request.xhr.responseText})}}return errors};this._updateLastErrors=function(jsdo,batch,changes,request){var errors,errorText,responseObject,i,j,buf;if(batch){if(batch.operations===undefined)return;for(i=0;i=200&&request.xhr.status<300){jsdo._lastErrors.push({errorString:request.jsrecord.data._errorString});jsdo._buffers[request.jsrecord._tableRef._name]._lastErrors.push({type:progress.data.JSDO.DATA_ERROR,id:request.jsrecord.data._id,error:request.jsrecord.data._errorString})}else{errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}if(request.jsrecord&&(errors[j].type===progress.data.JSDO.APP_ERROR||errors[j].type===progress.data.JSDO.RETVAL)){errors[j].id=request.jsrecord.data._id;request.jsrecord._tableRef._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}}}}else if(changes instanceof Array){for(i=0;i=400&&request.xhr.status<600||request.xhr.status===0)){errors=this._getErrorsFromRequest(request);errorText="";for(j=0;j1&&errors[j].error.indexOf("(7243)")!=-1){continue}for(buf in this._buffers){this._buffers[buf]._lastErrors.push(errors[j])}if(errorText.length===0){errorText=errors[j].error}else{errorText+="\n"+errors[j].error}}jsdo._lastErrors.push({errorString:errorText})}};this._checkSaveComplete=function(xhr){if(xhr.request){var jsdo=xhr.request.jsdo;var batch=xhr.request.batch;if(jsdo&&batch&&jsdo._async){if(jsdo._isBatchComplete(batch)){var success=jsdo._isBatchSuccess(batch);var request={batch:batch,success:success};jsdo._undefWorkingRecord();jsdo._lastErrors=[];if(!success&&batch.operations){jsdo._updateLastErrors(jsdo,batch,null)}this._setAllRecordsRejected(batch);jsdo._fireAfterSaveChanges(success,request)}}}};this._isBatchSuccess=function(batch){if(batch.operations){for(var i=0;i=200&&xhr.status<300||xhr.status===0&&xhr.responseText!==""){request.success=true;xhr.jsdo._session._saveClientContextId(xhr);if(typeof xhr.onSuccessFn=="function"){var operation;if(xhr.request.fnName!==undefined&&xhr.jsdo._resource.fn[xhr.request.fnName]!==undefined){operation=xhr.jsdo._resource.fn[xhr.request.fnName].operation}else operation=null;if(operation===undefined||operation!==null&&operation.mergeMode)xhr.jsdo._mergeInvoke(request.response,xhr);if(request.success)xhr.onSuccessFn(xhr.jsdo,request.success,request);else if(typeof xhr.onErrorFn=="function")xhr.onErrorFn(xhr.jsdo,request.success,request)}}else{request.success=false;if(xhr.status===0){request.exception=new Error(msg.getMsgText("jsdoMSG101"))}if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}}catch(e){request.success=false;request.exception=e;if(typeof xhr.onErrorFn=="function"){xhr.onErrorFn(xhr.jsdo,request.success,request)}}xhr.jsdo._session._checkServiceResponse(xhr,request.success,request);if(typeof xhr.onCompleteFn=="function"){xhr.onCompleteFn(xhr.jsdo,request.success,request)}}};this.acceptChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].acceptChanges()}};this.rejectChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name].rejectChanges()}};this.getChanges=function(){var result=[];for(var buf in this._buffers){var changes=this._buffers[this._buffers[buf]._name].getChanges();result=result.concat(changes)}return result};this.hasChanges=function(){for(var buf in this._buffers){if(this._buffers[this._buffers[buf]._name].hasChanges())return true}return false};this._applyChanges=function(){for(var buf in this._buffers){this._buffers[this._buffers[buf]._name]._applyChanges()}};this.acceptRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.acceptRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","acceptRowChanges()"))};this.rejectRowChanges=function(){if(this._defaultTableRef)return this._defaultTableRef.rejectRowChanges();throw new Error(msg.getMsgText("jsdoMSG001","rejectRowChanges()"))};this.setProperties=function(propertiesObject){var prop;if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperties",1))}if(typeof propertiesObject=="object"){this._properties={};for(prop in propertiesObject){if(propertiesObject.hasOwnProperty(prop)){if(typeof propertiesObject[prop]!=="function"){this._properties[prop]=propertiesObject[prop]}}}}else if(propertiesObject===undefined||propertiesObject===null){this._properties={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"Object","setProperties"))}};this.setProperty=function(propertyName,propertyValue){if(arguments.length<2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(arguments.length!==2){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","setProperty",2))}if(typeof propertyName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","JSDO",1,"string","setProperty"))}if(propertyValue===undefined){delete this._properties[propertyName]}else{this._properties[propertyName]=propertyValue}};this.getProperties=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperties",0))}return this._properties};this.getProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","JSDO","getProperty",1))}return this._properties[propertyName]};this.saveLocal=function saveLocal(arg1,arg2){var name;var dataMode;if(arguments.length>2){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"||arg1===null||arg1===undefined){name=arg1;dataMode=arg2}else{name=null;dataMode=arg1}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}if(typeof dataMode=="undefined"){dataMode=progress.data.JSDO.ALL_DATA}else{switch(dataMode){case progress.data.JSDO.ALL_DATA:case progress.data.JSDO.CHANGES_ONLY:break;default:throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var dataObj=this._prepareDataObjectForLocalStorage(dataMode);this._localStorage.saveToLocalStorage(name,dataObj)};this.readLocal=function readLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));this._restoreFromLocalStorage(object,progress.data.JSDO.MODE_EMPTY)}return object!==null};this.addLocalRecords=function addLocalRecords(arg1,arg2,arg3){var name;var addMode;var keyFields;if(arguments.length<1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(typeof arg1=="string"){name=arg1;addMode=arg2;keyFields=arg3}else{name="jsdo_"+this._resource.service.name+"_"+this._resource.name;addMode=arg1;keyFields=arg2}if(typeof name=="undefined"||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(addMode!=progress.data.JSDO.MODE_REPLACE){throw new Error(msg.getMsgText("jsdoMSG115",arguments.callee.name))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}var object=this._localStorage.readFromLocalStorage(name);if(object){if(this._hasMatchingSchema(object)===false)throw new Error(msg.getMsgText("jsdoMSG117",name));try{this._restoreFromLocalStorage(object,addMode,keyFields)}catch(e){var text=e.message;throw new Error(text.replace(new RegExp("addRecords","g"),"addLocalRecords"))}}return object!==null};this._containsPrimaryKeys=function _containsPrimaryKeys(){for(var buf in this._buffers){if(this._buffers[buf]._primaryKeys===null)return false}return true};this._hasMatchingSchema=function _hasMatchingSchema(storageObject){var isValid=true;if(storageObject===null||Object.keys(storageObject).length===0)return true;if(this._dataSetName){if(storageObject[this._dataSetName]){for(var buf in this._buffers)if(storageObject[this._dataSetName][buf]===undefined){isValid=false;break}}else isValid=false}else if(this._dataProperty){storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._dataProperty]===undefined)isValid=false}else{storageObject=storageObject["_localStorage"];if(storageObject===undefined||storageObject[this._defaultTableRef._name]===undefined)isValid=false}return isValid};this.deleteLocal=function deleteLocal(name){if(arguments.length>1){throw new Error(msg.getMsgText("jsdoMSG024","JSDO",arguments.callee.name+"()"))}if(name===undefined||name===null||name===""){name="jsdo_"+this._resource.service.name+"_"+this._resource.name}else if(typeof name!="string"){throw new Error(msg.getMsgText("jsdoMSG116","name",arguments.callee.name+"()"))}if(this._localStorage===null){this._localStorage=new progress.data.LocalStorage}this._localStorage.clearLocalStorage(name)};this._prepareDataObjectForLocalStorage=function(option){var storageObject={};if(this._dataSetName){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet(this._dataSetName);break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet(this._dataSetName,true);break}}else if(this._dataProperty){switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}else{switch(option){case progress.data.JSDO.ALL_DATA:storageObject=this._createDataAndChangeSet("_localStorage");break;case progress.data.JSDO.CHANGES_ONLY:storageObject=this._createChangeSet("_localStorage",true);break}}return storageObject};this._restoreFromLocalStorage=function(storageObject,addMode,keyFields){if(storageObject&&Object.keys(storageObject).length>0){if(this._dataSetName){for(var buf in this._buffers)this._restoreDataForTable(this._buffers[buf],storageObject,addMode,keyFields)}else this._restoreDataForTable(this._defaultTableRef,storageObject,addMode,keyFields)}else if(addMode===progress.data.JSDO.MODE_EMPTY)this._clearData()};this._restoreDataForTable=function(tableRef,jsonObject,addMode,keyFields){keyFields=keyFields!==undefined?keyFields:tableRef._primaryKeys;if(keyFields===undefined&&this._resource.idProperty){keyFields=[];keyFields[0]=this._resource.idProperty}if(this._dataSetName){var oldUseRelationships=this.useRelationships;this.useRelationships=false;try{tableRef.addRecords(jsonObject,addMode,keyFields)}finally{this.useRelationships=oldUseRelationships}}else{this._dataSetName="_localStorage";tableRef.addRecords(jsonObject,addMode,keyFields);this._dataSetName=null}};this.getMethodProperties=function(operation,name){var idx;if(this._resource._operations){if(this._resource._operations[operation]){return this._resource._operations[operation]}}else{this._resource._operations={}}for(var idx=0;idx1?[params.sort]:[]}sortFields="";for(index=0;index=1?params.filter:undefined}if(params.filter){if(typeof params.filter==="string"){doConversion=false}params.tableRef=tableName;if(doConversion&¶ms.tableRef===undefined){throw new Error(msg.getMsgText("jsdoMSG045","fill() or read()","params","tableRef"))}if(reqCapabilities["filter"].mapping==="ablFilter"){if(doConversion){ablFilter=progress.util._convertToABLWhereString(jsdo._buffers[params.tableRef],params.filter)}else{ablFilter=params.filter}}else if(reqCapabilities["filter"].mapping==="sqlQuery"){if(doConversion){sqlQuery=progress.util._convertToSQLQueryString(jsdo._buffers[params.tableRef],params.filter,true)}else{sqlQuery=params.filter}}}filter=JSON.stringify({ablFilter:ablFilter,sqlQuery:sqlQuery,orderBy:sortFields,skip:params.skip,top:params.top,id:params.id});params={filter:filter}}return params}});if(typeof progress.ui=="undefined")progress.ui={};progress.ui.UITableRef=function UITableRef(tableRef){this._tableRef=tableRef;this._listview=null;this._detailPage=null;this._listviewContent=undefined;this.addItem=function(format){var detailForm;if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._name));if(!this._listview)return;format=format?format:this._listview.format;detailForm=this._detailPage&&this._detailPage.name?this._detailPage.name:"";if(this._listviewContent===undefined){this.clearItems()}var text=this._listview.itemTemplate?this._listview.itemTemplate:progress.ui.UIHelper._itemTemplate;text=text.replace(new RegExp("{__format__}","g"),format);text=text.replace(new RegExp("{__id__}","g"),this._tableRef.record.data._id);text=text.replace(new RegExp("{__page__}","g"),detailForm);for(var field in this._tableRef.record.data){var value=this._tableRef.record.data[field];text=text.replace(new RegExp("{"+field+"}","g"),value!==undefined&&value!==null?value:"")}this._listviewContent+=text};this.clearItems=function(){if(this._listview){this._listviewContent="";var listviewElement=document.getElementById(this._listview.name);if(listviewElement){listviewElement.innerHTML=""}}};this._getFormFieldValue=function(fieldName,detailPageName){var value=null,field;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)value=field.val()}else{field=document.getElementById(fieldName);if(field){value=field.value}}return value};this._setFormField=function(fieldName,value,detailPageName){var field=null;if(detailPageName===undefined){if(this._detailPage&&this._detailPage.name)detailPageName=this._detailPage.name}if(typeof $=="function"&&detailPageName){field=$("#"+detailPageName+" #"+fieldName);if(!field||field.length===0)field=$("#"+detailPageName+' [dsid="'+fieldName+'"]');if(field&&field.length==1)field.val(value)}else{field=document.getElementById(fieldName);if(field){field.value=value}}};this.assign=function(detailPageName){if(!this._tableRef.record)throw new Error(msg.getMsgText("jsdoMSG002",this._tableRef._name));if(arguments.length!==0&&typeof detailPageName!="string")throw new Error(msg.getMsgText("jsdoMSG024","UIHelper","assign()"));this._tableRef.record.assign(null);var fieldName;var schema=this._tableRef.getSchema();for(var i=0;i0){for(var i=0;i0&&fieldName.charAt(0)=="_")continue;if(fields&&fields[fieldName]===undefined)continue;var fieldLabel=this._tableRef._schema[i].title?this._tableRef._schema[i].title:this._tableRef._schema[i].name;var text=this._detailPage&&this._detailPage.fieldTemplate?this._detailPage.fieldTemplate:progress.ui.UIHelper._fieldTemplate;text=text.replace(new RegExp("{__label__}","g"),fieldLabel);text=text.replace(new RegExp("{__name__}","g"),this._tableRef._schema[i].name);htmltext+=text}htmltext+="";fields=null;return htmltext};this.getListViewRecord=function(htmlIElement){var id=htmlIElement.getAttribute("data-id");return this._tableRef.findById(id)};this.getFormRecord=function(detailPageName){var id=this._getFormFieldValue("_id",detailPageName);return this._tableRef.findById(id)};this._getIdOfElement=function(name){if(typeof $=="function"){var element=$("#"+name);if(!element||element.length===0){element=$('[dsid="'+name+'"]');if(element&&element.length==1){var id=element.attr("id");if(id)return id}}}return name};this.setDetailPage=function setDetailPage(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));this._detailPage=obj;this._detailPage.name=this._getIdOfElement(this._detailPage.name)};this.setListView=function setListView(obj){if(!obj||typeof obj!="object")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"object"));if(!obj.name||typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"name"));if(obj.format&&typeof obj.name!="string")throw new Error(msg.getMsgText("jsdoMSG012",arguments.callee.name,"format"));this._listview=obj;this._listview.name=this._getIdOfElement(this._listview.name);if(!this._listview.format){if(typeof $=="function"){for(var i=0;i{__format__}';progress.ui.UIHelper._defaultFieldTemplate='
    '+''+'
    ';progress.ui.UIHelper._itemTemplate=progress.ui.UIHelper._defaultItemTemplate;progress.ui.UIHelper._fieldTemplate=progress.ui.UIHelper._defaultFieldTemplate;progress.ui.UIHelper.setItemTemplate=function(template){progress.ui.UIHelper._itemTemplate=template?template:progress.ui.UIHelper._defaultItemTemplate};progress.ui.UIHelper.setFieldTemplate=function(template){progress.ui.UIHelper._fieldTemplate=template?template:progress.ui.UIHelper._defaultFieldTemplate}})();(function(){if(progress===undefined){progress={}}if(progress.data===undefined){progress.data={}}progress.data.ServicesManager={};progress.data.ServicesManager._services=[];progress.data.ServicesManager._resources=[];progress.data.ServicesManager._data=[];progress.data.ServicesManager._sessions=[];progress.data.ServicesManager._jsdosessions=[];progress.data.ServicesManager.addResource=function(id,resource){if(progress.data.ServicesManager._resources[id]===undefined){progress.data.ServicesManager._resources[id]=resource}else{throw new Error("A resource named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getResource=function(id){return progress.data.ServicesManager._resources[id]};progress.data.ServicesManager.addService=function(id,service){if(progress.data.ServicesManager._services[id]===undefined){progress.data.ServicesManager._services[id]=service}else{throw new Error("A service named '"+id+"' was already loaded.")}};progress.data.ServicesManager.getService=function(id){return progress.data.ServicesManager._services[id]};progress.data.ServicesManager.addSession=function(catalogURI,session){if(progress.data.ServicesManager._sessions[catalogURI]===undefined){progress.data.ServicesManager._sessions[catalogURI]=session}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.addJSDOSession=function(catalogURI,jsdosession){if(progress.data.ServicesManager._jsdosessions[catalogURI]===undefined){progress.data.ServicesManager._jsdosessions[catalogURI]=jsdosession}else{throw new Error("Cannot load catalog '"+catalogURI+"' multiple times.")}};progress.data.ServicesManager.getSession=function(catalogURI){try{return progress.data.ServicesManager._sessions[catalogURI]}catch(e){return null}};progress.data.ServicesManager.cleanSession=function(session){var servicesKey,resourcesKey,sessionsKey,service,services=progress.data.ServicesManager._services,resources=progress.data.ServicesManager._resources,sessions=progress.data.ServicesManager._sessions,jsdosessions=progress.data.ServicesManager._jsdosessions;for(servicesKey in services){service=null;if(services[servicesKey]._session===session){service=services[servicesKey];delete services[servicesKey]}if(!service){continue}for(resourcesKey in resources){if(resources[resourcesKey].service===service){delete resources[resourcesKey]}}}for(sessionsKey in sessions){if(sessions[sessionsKey]===session){delete sessions[sessionsKey];if(jsdosessions[sessionsKey]){delete jsdosessions[sessionsKey]}}}};function extractParamsFromURL(url){var urlParams=[],paramName=null;if(typeof url==="string"){url.split("").forEach(function(c){if(c==="{"){paramName=""}else if(c==="}"){if(paramName){urlParams.push(paramName)}paramName=null}else if(paramName!==null){paramName+=c}})}return urlParams}progress.data.ServicesManager.addCatalog=function(services,session){var name,value;if(!services){throw new Error("Cannot find 'services' property in catalog file.")}if(services instanceof Array){services.forEach(function(service){if(progress.data.ServicesManager.getService(service.name)!==undefined){throw new Error("A service named '"+service.name+"' was already loaded.")}if(service.resources instanceof Array){service.resources.forEach(function(resource){if(progress.data.ServicesManager.getResource(resource.name)!==undefined){throw new Error("A resource named '"+resource.name+"' was already loaded.")}})}else{throw new Error("Missing 'resources' array in catalog.")}});for(var j=0;j1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","setContext",1))}if(typeof context==="object"){contextObject={};for(prop in context){if(context.hasOwnProperty(prop)){if(typeof context[prop]!=="function"){contextObject[prop]=context[prop]}}}}else if(context===undefined||context===null){contextObject={}}else{throw new Error(progress.data._getMsgText("jsdoMSG121","Session",1,"Object","setContextProperty"))}contextString=null};this.getContext=function(){if(arguments.length>0){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContext",0))}return contextObject};this.getContextProperty=function(propertyName){if(arguments.length<1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}if(arguments.length>1){throw new Error(progress.data._getMsgText("jsdoMSG122","Session","getContextProperty",1))}return contextObject[propertyName]}};progress.data.Session=function Session(options){var defPropSupported=false;if(typeof Object.defineProperty==="function"){defPropSupported=true}var that=this,jsdosession,isUserAgentiOS=false,isFirefox=false,isEdge=false,isIE=false,canPassCredentialsToOpenWithCORS=false,defaultiOSBasicAuthTimeout=4e3,deviceIsOnline=true,restApplicationIsOnline=false,oepingAvailable=false,defaultPartialPingURI="/rest/_oeping",partialPingURI=defaultPartialPingURI,_storageKey,_authProvider=null,customCredentials=false,storedAuthModel,storedURI,newURI,stateWasReadFromStorage=false;if(!options||options._silent!==true){console.warn("Session: As of JSDO 4.4, the Session object has been deprecated. "+"Please use the JSDOSession object instead.")}if(typeof navigator!=="undefined"){if(typeof navigator.userAgent!=="undefined"){isUserAgentiOS=navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)/i);isFirefox=navigator.userAgent.toLowerCase().indexOf("firefox")>-1;isEdge=navigator.userAgent.indexOf("Edge/")>-1;isIE=navigator.userAgent.indexOf("Trident/")>-1||navigator.userAgent.indexOf("MSIE 10")>-1}}canPassCredentialsToOpenWithCORS=!(isFirefox||isEdge||isIE);function canPassCredentialsToOpen(){return canPassCredentialsToOpenWithCORS}this._onlineHandler=function(){setDeviceIsOnline(true);that.trigger("online",that,null)};this._offlineHandler=function(){setDeviceIsOnline(false);that.trigger("offline",that,progress.data.Session.DEVICE_OFFLINE,null)};if(typeof window!=="undefined"&&window.addEventListener){window.addEventListener("online",this._onlineHandler,false);window.addEventListener("offline",this._offlineHandler,false)}var _catalogURIs=[];var _services=[];var _jsdos=[];this.onOpenRequest=null;var _password=null;if(defPropSupported){var _userName=null;Object.defineProperty(this,"userName",{get:function(){return _userName},enumerable:true});var _loginTarget="/static/home.html";Object.defineProperty(this,"loginTarget",{get:function(){return _loginTarget},enumerable:true});var _serviceURI=null;Object.defineProperty(this,"serviceURI",{get:function(){return _serviceURI},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _catalogURIs},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _services},enumerable:true});var _loginResult=null;Object.defineProperty(this,"loginResult",{get:function(){return _loginResult},enumerable:true});var _loginHttpStatus=null;Object.defineProperty(this,"loginHttpStatus",{get:function(){return _loginHttpStatus},enumerable:true});var _clientContextId=null;Object.defineProperty(this,"clientContextId",{get:function(){return _clientContextId},enumerable:true});var _authenticationModel=progress.data.Session.AUTH_TYPE_ANON;Object.defineProperty(this,"authenticationModel",{get:function(){return _authenticationModel},set:function(newval){if(newval){newval=newval.toLowerCase()}switch(newval){case progress.data.Session.AUTH_TYPE_FORM:case progress.data.Session.AUTH_TYPE_BASIC:case progress.data.Session.AUTH_TYPE_ANON:case progress.data.Session.AUTH_TYPE_SSO:case null:_authenticationModel=newval;storeSessionInfo("authenticationModel",newval);break;default:throw new Error("Error setting Session.authenticationModel. '"+newval+"' is an invalid value.")}},enumerable:true});var _lastSessionXHR=null;Object.defineProperty(this,"lastSessionXHR",{get:function(){return _lastSessionXHR},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return this.loginResult===progress.data.Session.LOGIN_SUCCESS&&restApplicationIsOnline&&deviceIsOnline},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _jsdos},enumerable:true});var _pingInterval=0;var _timeoutID=null;Object.defineProperty(this,"pingInterval",{get:function(){return _pingInterval},set:function(newval){if(typeof newval==="number"&&newval>=0){_pingInterval=newval;storeSessionInfo("pingInterval",newval);if(newval>0){if(this.loginResult===progress.data.Session.LOGIN_SUCCESS){_timeoutID=setTimeout(this._autoping,newval)}}else if(newval===0){clearTimeout(_timeoutID);_pingInterval=0}}else{throw new Error("Error setting Session.pingInterval. '"+newval+"' is an invalid value.")}},enumerable:true});var _contextProperties=new progress.data.ContextProperties;Object.defineProperty(this,"_contextProperties",{get:function(){return _contextProperties},enumerable:false});var isInvalidated=false;Object.defineProperty(this,"_isInvalidated",{get:function(){return isInvalidated},enumerable:false});Object.defineProperty(this,"_authProvider",{get:function(){return _authProvider},set:function(newval){if(_authProvider){throw new Error("Internal Error setting Session._authProvider. '"+"The property has already been set.")}setAuthProvider(newval)},enumerable:false})}else{this.userName=null;this.loginTarget="/static/home.html";this.serviceURI=null;this.catalogURIs=[];this.services=[];this.loginResult=null;this.loginHttpStatus=null;this.clientContextId=null;this.authenticationModel=progress.data.Session.AUTH_TYPE_ANON;this.lastSessionXHR=null}function storeSessionInfo(infoName,value){var key;if(that.loginResult===progress.data.Session.LOGIN_SUCCESS&&typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}if(typeof value!=="undefined"){sessionStorage.setItem(key,JSON.stringify(value))}}}function retrieveSessionInfo(infoName){var key,jsonStr,value=null;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName}jsonStr=sessionStorage.getItem(key);if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}}function clearSessionInfo(infoName){var key;if(typeof sessionStorage==="object"&&_storageKey){key=_storageKey;if(infoName){key=key+"."+infoName;sessionStorage.removeItem(key)}}}function storeAllSessionInfo(){if(_storageKey){storeSessionInfo("loginResult",that.loginResult);storeSessionInfo("userName",that.userName);storeSessionInfo("serviceURI",that.serviceURI);storeSessionInfo("loginHttpStatus",that.loginHttpStatus);storeSessionInfo("authenticationModel",that.authenticationModel);storeSessionInfo("pingInterval",that.pingInterval);storeSessionInfo("oepingAvailable",oepingAvailable);storeSessionInfo("partialPingURI",partialPingURI);storeSessionInfo("clientContextId",that.clientContextId);storeSessionInfo("deviceIsOnline",deviceIsOnline);storeSessionInfo("restApplicationIsOnline",restApplicationIsOnline);if(that._authProvider){storeSessionInfo("_authProvider.init",{uri:that._authProvider.uri,authenticationModel:that._authProvider.authenticationModel})}storeSessionInfo(_storageKey,true)}}function clearAllSessionInfo(){if(_storageKey){if(retrieveSessionInfo(_storageKey)){clearSessionInfo("loginResult");clearSessionInfo("userName");clearSessionInfo("serviceURI");clearSessionInfo("loginHttpStatus");clearSessionInfo("clientContextId");clearSessionInfo("deviceIsOnline");clearSessionInfo("restApplicationIsOnline");clearSessionInfo("authenticationModel");clearSessionInfo("pingInterval");clearSessionInfo("oepingAvailable");clearSessionInfo("partialPingURI");clearSessionInfo("_authProvider.init");clearSessionInfo(_storageKey)}}}function setSessionInfoFromStorage(key){var authproviderInitObject;if(retrieveSessionInfo(key)){setLoginResult(retrieveSessionInfo("loginResult"),this);setUserName(retrieveSessionInfo("userName"),this);setServiceURI(retrieveSessionInfo("serviceURI"),this);setLoginHttpStatus(retrieveSessionInfo("loginHttpStatus"),this);setClientContextID(retrieveSessionInfo("clientContextId"),this);setDeviceIsOnline(retrieveSessionInfo("deviceIsOnline"));setRestApplicationIsOnline(retrieveSessionInfo("restApplicationIsOnline"));that.authenticationModel=retrieveSessionInfo("authenticationModel");that.pingInterval=retrieveSessionInfo("pingInterval");setOepingAvailable(retrieveSessionInfo("oepingAvailable"));setPartialPingURI(retrieveSessionInfo("partialPingURI"));if(!that._authProvider){authproviderInitObject=retrieveSessionInfo("_authProvider.init");if(authproviderInitObject){setAuthProvider(new progress.data.AuthenticationProvider(authproviderInitObject))}}}}function setUserName(newname,sessionObject){if(defPropSupported){_userName=newname}else{sessionObject.userName=newname}storeSessionInfo("userName",newname)}function setLoginTarget(target,sessionObject){if(defPropSupported){_loginTarget=target}else{sessionObject.loginTarget=target}}function setServiceURI(url,sessionObject){if(defPropSupported){_serviceURI=url}else{sessionObject.serviceURI=url}storeSessionInfo("serviceURI",url)}function pushCatalogURIs(url,sessionObject){if(defPropSupported){_catalogURIs.push(url)}else{sessionObject.catalogURIs.push(url)}}function pushService(serviceObject,sessionObject){if(defPropSupported){_services.push(serviceObject)}else{sessionObject.services.push(serviceObject)}}function findService(serviceName){_services.forEach(function(service){if(service.name===serviceName){return service}});return null}function setLoginResult(result,sessionObject){if(defPropSupported){_loginResult=result}else{sessionObject.loginResult=result}if(result===progress.data.Session.LOGIN_SUCCESS){storeSessionInfo("loginResult",result)}else{clearAllSessionInfo()}}function setLoginHttpStatus(status,sessionObject){if(defPropSupported){_loginHttpStatus=status}else{sessionObject.loginHttpStatus=status}storeSessionInfo("loginHttpStatus",status)}function setClientContextIDfromXHR(xhr,sessionObject){if(xhr){setClientContextID(getResponseHeaderNoError(xhr,"X-CLIENT-CONTEXT-ID"),sessionObject)}}function setClientContextID(ccid,sessionObject){if(defPropSupported){_clientContextId=ccid}else{sessionObject.clientContextId=ccid}storeSessionInfo("clientContextId",ccid)}function setLastSessionXHR(xhr,sessionObject){if(defPropSupported){_lastSessionXHR=xhr}else{sessionObject.lastSessionXHR=xhr}}function setDeviceIsOnline(value){deviceIsOnline=value;storeSessionInfo("deviceIsOnline",value)}function setAuthProvider(value){_authProvider=value?value:null}function setRestApplicationIsOnline(value){restApplicationIsOnline=value;storeSessionInfo("restApplicationIsOnline",value)}function setOepingAvailable(value){oepingAvailable=value;storeSessionInfo("oepingAvailable",value)}function setPartialPingURI(value){partialPingURI=value;storeSessionInfo("partialPingURI",value)}function getResponseHeaderNoError(xhr,headerName){var allHeaders=xhr._pdsResponseHeaders,regExp;if(allHeaders===undefined){allHeaders=xhr.getAllResponseHeaders();if(allHeaders){xhr._pdsResponseHeaders=allHeaders}else{xhr._pdsResponseHeaders=null}}if(allHeaders){regExp=new RegExp("^"+headerName+":","mi");if(allHeaders.match(regExp)){return xhr.getResponseHeader(headerName)}}return null}this._pushJSDOs=function(jsdo){_jsdos.push(jsdo)};this._openRequest=function(xhr,verb,url,async,callback){var urlPlusCCID,that=this;function afterOpenAndAuthorize(arg){if(arg instanceof Error){throw arg}else{if(that.clientContextId&&that.clientContextId!=="0"){xhr.setRequestHeader("X-CLIENT-CONTEXT-ID",that.clientContextId)}setRequestHeaderFromContextProps(that,xhr);if(typeof that.onOpenRequest==="function"){var params={xhr:xhr,verb:verb,uri:urlPlusCCID,async:async,formPreTest:false,session:that};that.onOpenRequest(params)}if(callback){callback()}}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to make server request when there is no active session.")}urlPlusCCID=this._prependAppURL(url);urlPlusCCID=this._addCCIDtoURL(urlPlusCCID);if(progress.data.Session._useTimeStamp){urlPlusCCID=progress.data.Session._addTimeStampToURL(urlPlusCCID)}if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,verb,urlPlusCCID,async,afterOpenAndAuthorize)}else{this._setXHRCredentials(xhr,verb,urlPlusCCID,this.userName,_password,async);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json")}afterOpenAndAuthorize(xhr)}};this.pingTestCallback=function(cbArgs){var foundOeping=cbArgs.pingResult?true:false;setOepingAvailable(foundOeping)};this._onReadyStateChangeGeneric=function(){var xhr=this;var result;var errorObject;clearTimeout(xhr._requestTimeout);if(xhr.readyState===4){result=null;errorObject=null;if(typeof xhr.onResponseFn==="function"){try{result=xhr.onResponseFn(xhr)}catch(e){errorObject=e}}if(typeof xhr.onResponseProcessedFn==="function"){if(!result){result=progress.data.Session.GENERAL_FAILURE}xhr.onResponseProcessedFn(xhr.pdsession,result,errorObject,xhr)}}};this._disconnect=function(deferred){this._processDisconnectResult(null,deferred)};this._processDisconnectResult=function(xhr,deferred){this._reinitializeAfterLogout(this,progress.data.Session.SUCCESS);this._disconnectComplete(this,progress.data.Session.SUCCESS,null,null,deferred)};this._disconnectComplete=function(pdsession,result,errObj,xhr,deferred){pdsession.trigger("afterDisconnect",pdsession,result,errObj,xhr,deferred)};var pwSave=null;var unameSave=null;this.login=function(serviceURI,loginUserName,loginPassword,loginTarget){var uname,pw,isAsync=false,args=[],deferred,iOSBasicAuthTimeout,uriForRequest;pwSave=null;unameSave=null;if(!defPropSupported){this.authenticationModel=this.authenticationModel.toLowerCase()}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","login()"))}if(this.loginResult===progress.data.Session.LOGIN_SUCCESS||this._authProvider){throw new Error("Attempted to call login() on a Session object that is already logged in.")}if(arguments.length>0){if(arguments[0]&&typeof arguments[0]==="object"){args[0]=arguments[0].serviceURI;args[1]=arguments[0].userName;args[2]=arguments[0].password;args[3]=arguments[0].loginTarget;args[4]=arguments[0].async;deferred=arguments[0].deferred;iOSBasicAuthTimeout=arguments[0].iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","login","The iOSBasicAuthTimeout argument was invalid."))}}else{args=arguments}}if(args.length>0){if(args[0]){var restURLtemp=args[0];if(restURLtemp[restURLtemp.length-1]==="/"){restURLtemp=restURLtemp.substring(0,restURLtemp.length-1)}setServiceURI(restURLtemp,this)}else if(!this.serviceURI){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}if(args[1]){uname=args[1]}if(args[2]){pw=args[2]}if(args[3]){setLoginTarget(args[3],this)}if(args[4]){if(typeof args[4]==="boolean"){isAsync=args[4]}else{throw new Error("Session.login() was passed an async setting that is not a boolean.")}}}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);throw new Error("Session.login() is missing the serviceURI argument.")}unameSave=uname;pwSave=pw;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON||this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){uname=null;pw=null}var xhr=new XMLHttpRequest;xhr.pdsession=this;try{uriForRequest=this.serviceURI+this.loginTarget;if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(uriForRequest)}this._setXHRCredentials(xhr,"GET",uriForRequest,uname,pw,isAsync);progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(this,xhr);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr._isAsync=isAsync;if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){xhr.onResponseFn=this._afterFormPretestLogin}else{xhr.onResponseFn=this._processLoginResult;xhr.onResponseProcessedFn=this._loginComplete}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout>0){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred}if(typeof this.onOpenRequest==="function"){var isFormPreTest=false;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){isFormPreTest=true}setLastSessionXHR(xhr,this);var params={xhr:xhr,verb:"GET",uri:this.serviceURI+this.loginTarget,async:false,formPreTest:isFormPreTest,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send(null)}catch(e){clearTimeout(xhr._requestTimeout);setLoginHttpStatus(xhr.status,this);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,this);unameSave=null;pwSave=null;throw e}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{setLoginHttpStatus(xhr.status,this);if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){return this._afterFormPretestLogin(xhr)}else{return this._processLoginResult(xhr)}}};this._afterFormPretestLogin=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);var formLoginParams={xhr:xhr,pw:pwSave,uname:unameSave,theSession:pdsession};try{return doFormLogin(formLoginParams)}catch(e){pwSave=null;unameSave=null;throw e}};function doFormLogin(args){var xhr=args.xhr;var theSession=args.theSession;var oldXHR;var contentType=null;var needAuth=false;var params={session:theSession,xhr:xhr,statusFromjson:null};contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson||params.statusFromjson>=400&¶ms.statusFromjson<500){needAuth=true}else{setLoginHttpStatus(params.statusFromjson,theSession)}}else{if(theSession.loginHttpStatus===200){if(_gotLoginForm(xhr)){needAuth=true}}}if(needAuth){oldXHR=xhr;xhr=new XMLHttpRequest;args.xhr=xhr;params.xhr=xhr;xhr.pdsession=oldXHR.pdsession;xhr._isAsync=oldXHR._isAsync;xhr._deferred=oldXHR._deferred;xhr._jsdosession=oldXHR._jsdosession;xhr.open("POST",theSession.serviceURI+"/static/auth/j_spring_security_check",xhr._isAsync);xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.setRequestHeader("Cache-Control","max-age=0");setRequestHeaderFromContextProps(theSession,xhr);_addWithCredentialsAndAccept(xhr,"application/json");try{if(typeof theSession.onOpenRequest==="function"){var cbparams={xhr:xhr,verb:"POST",uri:theSession.serviceURI+"/static/auth/j_spring_security_check",async:xhr._isAsync,formPreTest:false,session:theSession};theSession.onOpenRequest(cbparams);xhr=cbparams.xhr}if(xhr._isAsync){xhr.onreadystatechange=theSession._onReadyStateChangeGeneric;xhr.onResponseFn=theSession._afterFormLogin;xhr.onResponseProcessedFn=theSession._loginComplete}xhr.send("j_username="+encodeURIComponent(args.uname)+"&j_password="+encodeURIComponent(args.pw)+"&submit=Submit")}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,theSession);setLoginHttpStatus(xhr.status,theSession);unameSave=null;pwSave=null;throw e}}if(xhr._isAsync&&!needAuth){xhr.onResponseProcessedFn=theSession._loginComplete;return theSession._afterFormLogin(xhr)}if(!xhr._isAsync){return theSession._afterFormLogin(xhr)}}this._afterFormLogin=function(xhr){var theSession=xhr.pdsession;var params={session:theSession,xhr:xhr,statusFromjson:null};var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>=0){handleJSONLoginResponse(params);if(!params.statusFromjson){throw new Error("Internal OpenEdge Mobile client error handling login response. HTTP status: "+xhr.status+".")}setLoginHttpStatus(params.statusFromjson,theSession)}else{if(xhr.status===200){if(_gotLoginFailure(xhr)||_gotLoginForm(xhr)){setLoginHttpStatus(401,theSession)}else{setLoginHttpStatus(xhr.status,theSession)}}}return theSession._processLoginResult(xhr)};this._processLoginResult=function(xhr){var pdsession=xhr.pdsession;setLoginHttpStatus(xhr.status,xhr.pdsession);if(pdsession.loginHttpStatus===200){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);setUserName(unameSave,pdsession);_password=pwSave;pdsession._saveClientContextId(xhr);storeAllSessionInfo();var pingTestArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:pdsession._pingtestOnReadyStateChange};pingTestArgs.pingURI=pdsession._makePingURI();pdsession._sendPing(pingTestArgs)}else{if(pdsession.loginHttpStatus===401){setLoginResult(progress.data.Session.LOGIN_AUTHENTICATION_FAILURE,pdsession)}else{setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);unameSave=null;pwSave=null;if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","login"))}return pdsession.loginResult};this._loginComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterLogin",pdsession,result,errObj,xhr)};this.logout=function(args){var isAsync=false,errorObject=null,xhr,deferred,params;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","Session","logout()"))}if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&this.authenticationModel){throw new Error("Attempted to call logout when there is no active session.")}if(typeof args==="object"){isAsync=args.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","logout","The async argument was invalid."))}deferred=args.deferred}xhr=new XMLHttpRequest;xhr.pdsession=this;try{xhr._jsdosession=jsdosession;xhr._deferred=deferred;if(this.authenticationModel===progress.data.Session.AUTH_TYPE_FORM||this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(isAsync){xhr.onreadystatechange=this._onReadyStateChangeGeneric;xhr.onResponseFn=this._processLogoutResult;xhr.onResponseProcessedFn=this._logoutComplete}xhr.open("GET",this.serviceURI+"/static/auth/j_spring_security_logout",isAsync);try{xhr.withCredentials=true}catch(e){}xhr.setRequestHeader("Accept","application/json");setRequestHeaderFromContextProps(this,xhr);if(typeof this.onOpenRequest==="function"){setLastSessionXHR(xhr,this);params={xhr:xhr,verb:"GET",uri:this.serviceURI+"/static/auth/j_spring_security_logout",async:false,formPreTest:false,session:this};this.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,this);xhr.send()}else{xhr._anonymousLogoutOK=true}}catch(e){this._reinitializeAfterLogout(this,false);throw e}if(!isAsync){try{this._processLogoutResult(xhr)}catch(e){throw e}}if(isAsync&&this.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){try{this._processLogoutResult(xhr)}catch(e){errorObject=e}this._logoutComplete(this,null,errorObject,xhr)}};this.invalidate=function(){isInvalidated=true;cleanServicesManager()};this._logoutComplete=function(pdsession,result,errorObject,xhr){pdsession.trigger("afterLogout",pdsession,errorObject,xhr)};this._processLogoutResult=function(xhr){var logoutSucceeded;var pdsession=xhr.pdsession;var basicStatusOK=false;if(xhr._anonymousLogoutOK){logoutSucceeded=true}else if(xhr.status!==200){if(pdsession.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(xhr.status===404){logoutSucceeded=true}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=false;throw new Error("Error logging out, HTTP status = "+xhr.status)}}else{logoutSucceeded=true}updateContextPropsFromResponse(pdsession,xhr);pdsession._reinitializeAfterLogout(pdsession,logoutSucceeded)};this._reinitializeAfterLogout=function(pdsession,success){setLoginResult(null,pdsession);setLoginHttpStatus(null,pdsession);setClientContextID(null,pdsession);setUserName(null,pdsession);setAuthProvider(null);_password=null;if(success){setRestApplicationIsOnline(false);setOepingAvailable(false);setPartialPingURI(defaultPartialPingURI);setLastSessionXHR(null,pdsession);clearTimeout(_timeoutID)}};this.addCatalog=function(arg1,arg2,arg3,arg4){var catalogURI,catalogUserName,catalogPassword,isAsync=false,xhr,deferred,iOSBasicAuthTimeout,catalogIndex,authProvider,that=this;function addCatalogAfterOpen(){progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(isAsync){xhr.onreadystatechange=that._onReadyStateChangeGeneric;xhr.onResponseFn=that._processAddCatalogResult;xhr.onResponseProcessedFn=that._addCatalogComplete;if(that.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC&&isUserAgentiOS&&iOSBasicAuthTimeout){xhr._requestTimeout=setTimeout(function(){clearTimeout(xhr._requestTimeout);xhr._iosTimeOutExpired=true;xhr.abort()},iOSBasicAuthTimeout)}xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex}try{if(typeof that.onOpenRequest==="function"){setLastSessionXHR(xhr,that);var params={xhr:xhr,verb:"GET",uri:catalogURI,async:false,formPreTest:false,session:that};that.onOpenRequest(params);xhr=params.xhr}setLastSessionXHR(xhr,that);xhr.send(null)}catch(e){throw new Error("Error retrieving catalog '"+catalogURI+"'.\n"+e.message)}if(isAsync){return progress.data.Session.ASYNC_PENDING}else{return that._processAddCatalogResult(xhr)}}if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}customCredentials=true;if(arguments.length>0){if(typeof arg1==="object"){if(!arguments[0].offlineAddCatalog){if(this.loginResult!==progress.data.Session.LOGIN_SUCCESS&&!this._authProvider&&this.authenticationModel){throw new Error("Attempted to call addCatalog when there is no active session.")}}catalogURI=arg1.catalogURI;if(!catalogURI||typeof catalogURI!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogURI argument was missing or invalid."))}catalogUserName=arg1.userName;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogUserName argument was invalid."))}catalogPassword=arg1.password;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The catalogPassword argument was invalid."))}isAsync=arg1.async;if(isAsync&&typeof isAsync!=="boolean"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The async argument was invalid."))}iOSBasicAuthTimeout=arg1.iOSBasicAuthTimeout;if(typeof iOSBasicAuthTimeout==="undefined"){iOSBasicAuthTimeout=defaultiOSBasicAuthTimeout}else if(iOSBasicAuthTimeout&&typeof iOSBasicAuthTimeout!=="number"){throw new Error(progress.data._getMsgText("jsdoMSG033","Session","addCatalog","The iOSBasicAuthTimeout argument was invalid."))}authProvider=arg1.authProvider;deferred=arg1.deferred;catalogIndex=arg1.catalogIndex}else{catalogURI=arg1;if(typeof catalogURI!=="string"){throw new Error("First argument to Session.addCatalog must be the URL of the catalog.")}catalogUserName=arg2;if(catalogUserName&&typeof catalogUserName!=="string"){throw new Error("Second argument to Session.addCatalog must be a user name string.")}catalogPassword=arg3;if(catalogPassword&&typeof catalogPassword!=="string"){throw new Error("Third argument to Session.addCatalog must be a password string.")}}}else{throw new Error("Session.addCatalog is missing its first argument, the URL of the catalog.")}if(!authProvider){authProvider=this._authProvider;customCredentials=false}if(!catalogUserName){catalogUserName=this.userName}if(!catalogPassword){catalogPassword=_password}xhr=new XMLHttpRequest;xhr.pdsession=this;xhr._catalogURI=catalogURI;if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){if(isAsync){xhr._jsdosession=jsdosession;xhr._deferred=deferred;xhr._catalogIndex=catalogIndex;setTimeout(this._addCatalogComplete,10,this,progress.data.Session.CATALOG_ALREADY_LOADED,null,xhr);return progress.data.Session.ASYNC_PENDING}return progress.data.Session.CATALOG_ALREADY_LOADED}if(authProvider){authProvider._openRequestAndAuthorize(xhr,"GET",catalogURI,isAsync,addCatalogAfterOpen);return progress.data.Session.ASYNC_PENDING}else{this._setXHRCredentials(xhr,"GET",catalogURI,catalogUserName,catalogPassword,isAsync);return addCatalogAfterOpen()}};this._processAddCatalogResult=function(xhr){var _catalogHttpStatus=xhr.status;var theSession=xhr.pdsession;var servicedata;var catalogURI=xhr._catalogURI,serviceURL,theJSDOSession=jsdosession;if(!customCredentials){toggleOnlineState(xhr)}if((_catalogHttpStatus===200||_catalogHttpStatus===0)&&xhr.responseText){servicedata=theSession._parseCatalog(xhr);try{progress.data.ServicesManager.addCatalog(servicedata,theSession)}catch(e){if(progress.data.ServicesManager.getSession(catalogURI)!==undefined){return progress.data.Session.CATALOG_ALREADY_LOADED}throw new Error("Error processing catalog '"+catalogURI+"'. \n"+e.message)}servicedata.forEach(function(service){serviceURL=theSession._prependAppURL(service.address);pushService(new progress.data.MobileServiceObject({name:service.name,uri:serviceURL}),theSession);if(service.settings&&service.settings.useXClientProps&&!theSession.xClientProps){console.warn("Catalog warning: Service settings property 'useXClientProps' "+"is true but 'xClientProps' property has not been set.")}});pushCatalogURIs(catalogURI,theSession);progress.data.ServicesManager.addSession(catalogURI,theSession);if(theJSDOSession){progress.data.ServicesManager.addJSDOSession(catalogURI,theJSDOSession)}}else if(_catalogHttpStatus===401){return progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else if(xhr._iosTimeOutExpired){throw new Error(progress.data._getMsgText("jsdoMSG047","addCatalog"))}else{throw new Error("Error retrieving catalog '"+catalogURI+"'. Http status: "+_catalogHttpStatus+".")}return progress.data.Session.SUCCESS};this._addCatalogComplete=function(pdsession,result,errObj,xhr){pdsession.trigger("afterAddCatalog",pdsession,result,errObj,xhr)};this.ping=function(args){var pingResult=false,pingArgs={pingURI:null,async:true,onCompleteFn:null,fireEventIfOfflineChange:true,onReadyStateFn:this._onReadyStateChangePing,offlineReason:null};if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","Session"))}if(!this._authProvider&&this.loginResult!==progress.data.Session.LOGIN_SUCCESS){throw new Error("Attempted to call ping when not logged in.")}if(args){if(args.async!==undefined){pingArgs.async=args.async}if(args.doNotFireEvent!==undefined){pingArgs.fireEventIfOfflineChange=!args.doNotFireEvent}if(args.onCompleteFn&&typeof args.onCompleteFn==="function"){pingArgs.onCompleteFn=args.onCompleteFn}pingArgs.deferred=args.deferred;pingArgs.jsdosession=args.jsdosession}pingArgs.pingURI=that._makePingURI();that._sendPing(pingArgs);if(!pingArgs.async){if(pingArgs.xhr){pingResult=that._processPingResult(pingArgs);if(args.offlineReason!==undefined){args.offlineReason=pingArgs.offlineReason}}else{pingResult=false}if(args.xhr!==undefined){args.xhr=pingArgs.xhr}}return pingResult};this._isOnlineStateChange=function(isOnline){var stateChanged=false;if(isOnline&&!this.connected){stateChanged=true}else if(!isOnline&&this.connected){stateChanged=true}return stateChanged};this._checkServiceResponse=function(xhr,success,request){var offlineReason=null,wasOnline=this.connected;updateContextPropsFromResponse(this,xhr);if(!this._events){return}var offlineObservers=this._events.offline||[];var onlineObservers=this._events.online||[];if(offlineObservers.length===0&&onlineObservers.length===0){return}if(success){setRestApplicationIsOnline(true);setDeviceIsOnline(true)}else{if(deviceIsOnline){var localPingArgs={doNotFireEvent:true,offlineReason:null,async:false};if(!that.ping(localPingArgs)){offlineReason=localPingArgs.offlineReason;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}}if(wasOnline&&!this.connected){this.trigger("offline",this,offlineReason,request)}else if(!wasOnline&&this.connected){this.trigger("online",this,request)}};this._processPingResult=function(args){var xhr=args.xhr,pingResponseJSON,appServerStatus=null,wasOnline=this.connected,connectedBeforeCallback,assumeOepingFormat;if(args.hasOwnProperty("usingOepingFormat")){assumeOepingFormat=args.usingOepingFormat}else{assumeOepingFormat=oepingAvailable}if(xhr.status>=200&&xhr.status<300){updateContextPropsFromResponse(this,xhr);if(assumeOepingFormat){try{pingResponseJSON=JSON.parse(xhr.responseText);appServerStatus=pingResponseJSON.AppServerStatus}catch(e){console.error("Unable to parse ping response.")}}toggleOnlineState(xhr)}else{if(deviceIsOnline){if(xhr.status===0){args.offlineReason=progress.data.Session.SERVER_OFFLINE;setRestApplicationIsOnline(false)}else if(xhr.status===404||xhr.status===410){args.offlineReason=progress.data.Session.WEB_APPLICATION_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}else{args.offlineReason=progress.data.Session.DEVICE_OFFLINE}}if(appServerStatus){if(appServerStatus.PingStatus==="false"){args.offlineReason=progress.data.Session.APPSERVER_OFFLINE;setRestApplicationIsOnline(false)}else{setRestApplicationIsOnline(true)}}connectedBeforeCallback=this.connected;if(typeof xhr.onCompleteFn==="function"){xhr.onCompleteFn({pingResult:this.connected,xhr:xhr,offlineReason:args.offlineReason})}if(args.fireEventIfOfflineChange){if(wasOnline&&!connectedBeforeCallback){that.trigger("offline",that,args.offlineReason,null)}else if(!wasOnline&&connectedBeforeCallback){that.trigger("online",that,null)}}return this.connected};this._onReadyStateChangePing=function(){var xhr=this;var args;if(xhr.readyState===4){args={xhr:xhr,fireEventIfOfflineChange:true,offlineReason:null};that._processPingResult(args);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._pingtestOnReadyStateChange=function(){var xhr=this;if(xhr.readyState===4){var foundOeping=false;if(xhr.status>=200&&xhr.status<300){foundOeping=true}else{setPartialPingURI(that.loginTarget);console.warn("Default ping target not available, will use loginTarget instead.")}setOepingAvailable(foundOeping);if(_pingInterval>0){_timeoutID=setTimeout(that._autoping,_pingInterval)}}};this._sendPing=function(args){var xhr=new XMLHttpRequest,that=this;function sendPingAfterOpen(){if(args.async){xhr.onreadystatechange=args.onReadyStateFn;xhr.onCompleteFn=args.onCompleteFn;xhr._jsdosession=jsdosession;xhr._deferred=args.deferred}progress.data.Session._setNoCacheHeaders(xhr);setRequestHeaderFromContextProps(that,xhr);if(that.authenticationModel===progress.data.Session.AUTH_TYPE_FORM){_addWithCredentialsAndAccept(xhr,"application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")}xhr.send(null)}try{if(this._authProvider){this._authProvider._openRequestAndAuthorize(xhr,"GET",args.pingURI,args.async,sendPingAfterOpen)}else{this._setXHRCredentials(xhr,"GET",args.pingURI,this.userName,_password,args.async);if(xhr.readyState===1){sendPingAfterOpen()}}}catch(e){args.error=e}args.xhr=xhr};this._makePingURI=function(){var pingURI=this.serviceURI+partialPingURI;if(progress.data.Session._useTimeStamp){pingURI=progress.data.Session._addTimeStampToURL(pingURI)}return pingURI};this._autoping=function(){that.ping({async:true})};this._setXHRCredentials=function(xhr,verb,uri,userName,password,async){if(userName&&this.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){if(canPassCredentialsToOpen()){xhr.open(verb,uri,async,userName,password)}else{xhr.open(verb,uri,async)}var auth=_make_basic_auth(userName,password);xhr.setRequestHeader("Authorization",auth)}else{xhr.open(verb,uri,async)}};this._addCCIDtoURL=function(url){var urlPart1,urlPart2,jsessionidStr,index;if(this.clientContextId&&this.clientContextId!=="0"){if(url.substring(0,this.serviceURI.length)===this.serviceURI){jsessionidStr=";"+"JSESSIONID="+this.clientContextId;index=url.indexOf("?");if(index===-1){url+=jsessionidStr}else{urlPart1=url.substring(0,index);urlPart2=url.substring(index);url=urlPart1+jsessionidStr+urlPart2}}}return url};this._saveClientContextId=function(xhr){setClientContextIDfromXHR(xhr,this)};this._parseCatalog=function(xhr){var jsonObject;var catalogdata;try{jsonObject=JSON.parse(xhr.responseText);catalogdata=jsonObject.services}catch(e){console.error("Unable to parse response. Make sure catalog has correct format.");catalogdata=null}return catalogdata};this._prependAppURL=function(oldURL){if(!oldURL){return this.serviceURI}var newURL=oldURL;var pat=/^https?:\/\//i;if(!pat.test(newURL)){if(newURL.indexOf("/")!==0){newURL="/"+newURL}newURL=this.serviceURI+newURL}return newURL};function _addWithCredentialsAndAccept(xhr,acceptString){try{xhr.withCredentials=true;xhr.setRequestHeader("Accept",acceptString)}catch(e){}}function _make_basic_auth(user,pw){var tok=user+":"+pw;var hash=btoa(tok);return"Basic "+hash}var loginFormIDString="j_spring_security_check";function _gotLoginForm(xhr){return _findStringInResponseHTML(xhr,loginFormIDString)}var loginFailureIdentificationString="login failed";function _gotLoginFailure(xhr){return _findStringInResponseHTML(xhr,loginFailureIdentificationString)}function _findStringInResponseHTML(xhr,searchString){if(!xhr.responseText){return false}var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("text/html")>=0&&xhr.responseText.indexOf(searchString)>=0){return true}return false}function handleJSONLoginResponse(params){var jsonObject;params.statusFromjson=null;try{jsonObject=JSON.parse(params.xhr.responseText);if(jsonObject.status_code!==undefined&&jsonObject.status_txt!==undefined){params.statusFromjson=jsonObject.status_code}}catch(e){setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,params.session);setLoginHttpStatus(params.xhr.status,params.session);throw new Error("Unable to parse login response from server.")}}function setRequestHeaderFromContextProps(session,xhr){if(session.xClientProps){xhr.setRequestHeader("X-CLIENT-PROPS",session.xClientProps)}else if(session._contextProperties.contextHeader!==undefined){xhr.setRequestHeader("X-CLIENT-PROPS",session._contextProperties.contextHeader)}}function toggleOnlineState(xhr){var pdsession=that;setLoginHttpStatus(xhr.status,pdsession);if(pdsession.loginHttpStatus>=200&&pdsession.loginHttpStatus<400){setLoginResult(progress.data.Session.LOGIN_SUCCESS,pdsession);setRestApplicationIsOnline(true);pdsession._saveClientContextId(xhr);storeAllSessionInfo()}else{if(pdsession.loginHttpStatus===0||pdsession.loginHttpStatus===400||pdsession.loginHttpStatus===410){setRestApplicationIsOnline(false);setLoginResult(progress.data.AuthenticationProvider._getAuthFailureReason(xhr),pdsession)}else{setRestApplicationIsOnline(true);setLoginResult(progress.data.Session.LOGIN_GENERAL_FAILURE,pdsession)}}setLastSessionXHR(xhr,pdsession);updateContextPropsFromResponse(pdsession,xhr);return pdsession.loginResult}function updateContextPropsFromResponse(session,xhr){var contextString,context;if(xhr){contextString=getResponseHeaderNoError(xhr,"X-CLIENT-PROPS");if(contextString){try{context=JSON.parse(contextString)}catch(e){}if(typeof context==="object"){session._contextProperties.setContext(context)}else{throw new Error(progress.data._getMsgText("jsdoMSG123","Session","X-CLIENT-PROPS"))}}else if(contextString===""){session._contextProperties.setContext({})}}}function cleanServicesManager(){progress.data.ServicesManager.cleanSession(that)}if(typeof options==="object"){jsdosession=options.jsdosession;newURI=options.serviceURI;setAuthProvider(options.authProvider);if(options.authProvider&&options.authProvider.hasClientCredentials()){_loginResult=progress.data.Session.LOGIN_SUCCESS}if(newURI&&newURI[newURI.length-1]==="/"){newURI=newURI.substring(0,newURI.length-1)}_storageKey=options._storageKey;if(_storageKey){if(retrieveSessionInfo(_storageKey)){storedAuthModel=retrieveSessionInfo("authenticationModel");storedURI=retrieveSessionInfo("serviceURI");if(storedAuthModel!==options.authenticationModel||storedURI!==newURI){clearAllSessionInfo()}else{setSessionInfoFromStorage(_storageKey);stateWasReadFromStorage=true}}if(options.authenticationModel===progress.data.Session.AUTH_TYPE_BASIC){_storageKey=undefined}}if(!stateWasReadFromStorage){if(newURI){setServiceURI(newURI,this)}if(options.authenticationModel){this.authenticationModel=options.authenticationModel}}}};progress.data.Session._useTimeStamp=true;var SEQ_MAX_VALUE=999999999999999;var _tsseq=SEQ_MAX_VALUE;var _tsprefix1=0;var _tsprefix2=0;progress.data.Session._getNextTimeStamp=function(){var seq;_tsseq+=1;seq=_tsseq;if(seq>=SEQ_MAX_VALUE){_tsseq=1;seq=1;var t=Math.floor((Date.now?Date.now():(new Date).getTime())/1e4);if(_tsprefix1===t){_tsprefix2+=1;if(_tsprefix2>=SEQ_MAX_VALUE){_tsprefix2=1}}else{_tsprefix1=t;Math.random();_tsprefix2=Math.round(Math.random()*1e10)}}return _tsprefix1+"-"+_tsprefix2+"-"+seq};progress.data.Session._addTimeStampToURL=function(url){var timeStamp="_ts="+progress.data.Session._getNextTimeStamp();url+=(url.indexOf("?")===-1?"?":"&")+timeStamp;return url};progress.data.Session._setNoCacheHeaders=function(xhr){xhr.setRequestHeader("Cache-Control","no-cache");xhr.setRequestHeader("Pragma","no-cache")};if(typeof Object.defineProperty==="function"){Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_REQUIRED",{value:0,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"LOGIN_GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"CATALOG_ALREADY_LOADED",{value:4,enumerable:true});Object.defineProperty(progress.data.Session,"ASYNC_PENDING",{value:5,enumerable:true});Object.defineProperty(progress.data.Session,"EXPIRED_TOKEN",{value:6,enumerable:true});Object.defineProperty(progress.data.Session,"SUCCESS",{value:1,enumerable:true});Object.defineProperty(progress.data.Session,"AUTHENTICATION_FAILURE",{value:2,enumerable:true});Object.defineProperty(progress.data.Session,"GENERAL_FAILURE",{value:3,enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_ANON",{value:"anonymous",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_BASIC",{value:"basic",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM",{value:"form",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_SSO",{value:"sso",enumerable:true});Object.defineProperty(progress.data.Session,"AUTH_TYPE_FORM_SSO",{value:"form_sso",enumerable:true});Object.defineProperty(progress.data.Session,"DEVICE_OFFLINE",{value:"Device is offline",enumerable:true});Object.defineProperty(progress.data.Session,"SERVER_OFFLINE",{value:"Cannot contact server",enumerable:true});Object.defineProperty(progress.data.Session,"WEB_APPLICATION_OFFLINE",{value:"Mobile Web Application is not available",enumerable:true});Object.defineProperty(progress.data.Session,"SERVICE_OFFLINE",{value:"REST web Service is not available",enumerable:true});Object.defineProperty(progress.data.Session,"APPSERVER_OFFLINE",{value:"AppServer is not available",enumerable:true})}else{progress.data.Session.LOGIN_SUCCESS=1;progress.data.Session.LOGIN_AUTHENTICATION_FAILURE=2;progress.data.Session.LOGIN_GENERAL_FAILURE=3;progress.data.Session.CATALOG_ALREADY_LOADED=4;progress.data.Session.SUCCESS=1;progress.data.Session.AUTHENTICATION_FAILURE=2;progress.data.Session.GENERAL_FAILURE=3;progress.data.Session.AUTH_TYPE_ANON="anonymous";progress.data.Session.AUTH_TYPE_BASIC="basic";progress.data.Session.AUTH_TYPE_FORM="form";progress.data.Session.AUTH_TYPE_SSO="sso"}progress.data.Session.prototype=new progress.util.Observable;progress.data.Session.prototype.constructor=progress.data.Session;function validateSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}else{listenerData.scope=args[2]}}}progress.data.Session.prototype._eventNames=["offline","online","afterLogin","afterAddCatalog","afterLogout","afterDisconnect"];progress.data.Session.prototype.validateSubscribe=validateSessionSubscribe;progress.data.Session.prototype.toString=function(radix){return"progress.data.Session"};progress.data.JSDOSession=function JSDOSession(options){var _pdsession,_serviceURI,that=this,_name;Object.defineProperty(this,"authenticationModel",{get:function(){return _pdsession?_pdsession.authenticationModel:undefined},enumerable:true});Object.defineProperty(this,"authProvider",{get:function(){return _pdsession?_pdsession._authProvider:null},enumerable:true});Object.defineProperty(this,"catalogURIs",{get:function(){return _pdsession?_pdsession.catalogURIs:undefined},enumerable:true});Object.defineProperty(this,"clientContextId",{get:function(){return _pdsession?_pdsession.clientContextId:undefined},enumerable:true});Object.defineProperty(this,"connected",{get:function(){return _pdsession?_pdsession.connected:undefined},enumerable:true});Object.defineProperty(this,"JSDOs",{get:function(){return _pdsession?_pdsession.JSDOs:undefined},enumerable:true});Object.defineProperty(this,"loginResult",{get:function(){return _pdsession?_pdsession.loginResult:undefined},enumerable:true});Object.defineProperty(this,"loginHttpStatus",{get:function(){return _pdsession?_pdsession.loginHttpStatus:undefined},enumerable:true});Object.defineProperty(this,"onOpenRequest",{get:function(){return _pdsession?_pdsession.onOpenRequest:undefined},set:function(newval){if(_pdsession){_pdsession.onOpenRequest=newval}},enumerable:true});Object.defineProperty(this,"pingInterval",{get:function(){return _pdsession?_pdsession.pingInterval:undefined},set:function(newval){if(_pdsession){_pdsession.pingInterval=newval}},enumerable:true});Object.defineProperty(this,"services",{get:function(){return _pdsession?_pdsession.services:undefined},enumerable:true});Object.defineProperty(this,"serviceURI",{get:function(){if(_pdsession&&_pdsession.serviceURI){return _pdsession.serviceURI}else{return _serviceURI}},enumerable:true});Object.defineProperty(this,"userName",{get:function(){return _pdsession?_pdsession.userName:undefined},enumerable:true});Object.defineProperty(this,"name",{get:function(){return _name},enumerable:true});Object.defineProperty(this,"_isInvalidated",{get:function(){return _pdsession._isInvalidated},enumerable:false});function settlePromise(promise,fulfill,result,info){if(fulfill){promise.resolve(that,result,info)}else{promise.reject(that,result,info)}}function genericSessionEventHandler(pdsession,result,errorObject,xhr,deferred){var myDeferred;if(xhr){myDeferred=xhr._deferred}else{myDeferred=deferred}settlePromise(myDeferred,result===progress.data.Session.SUCCESS?true:false,result,{errorObject:errorObject,xhr:xhr})}function onAfterAddCatalog(pdsession,result,errorObject,xhr){var deferred,fulfill=false,settleResult,info;if(result===progress.data.Session.EXPIRED_TOKEN){settleResult=progress.data.Session.EXPIRED_TOKEN}else if(result===progress.data.Session.LOGIN_AUTHENTICATION_FAILURE){settleResult=progress.data.Session.LOGIN_AUTHENTICATION_FAILURE}else{settleResult=progress.data.Session.GENERAL_FAILURE}if(xhr&&xhr._deferred){deferred=xhr._deferred;if(result!==progress.data.Session.SUCCESS&&result!==progress.data.Session.CATALOG_ALREADY_LOADED){result=result||progress.data.Session.GENERAL_FAILURE;deferred._overallCatalogResult=progress.data.Session.GENERAL_FAILURE}deferred._results[xhr._catalogIndex]={catalogURI:xhr._catalogURI,result:result,errorObject:errorObject,xhr:xhr};deferred._numCatalogsProcessed+=1;if(deferred._numCatalogsProcessed===deferred._numCatalogs){deferred._processedPromise=true;if(!deferred._overallCatalogResult){fulfill=true;settleResult=progress.data.Session.SUCCESS}if(settleResult===progress.data.Session.SUCCESS){if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,details:xhr._deferred._results}}}else{if(xhr._deferred._results.length===1){info=xhr._deferred._results[0]}else{info={xhr:xhr,result:settleResult,errorObject:new Error(progress.data._getMsgText("jsdoMSG512")),details:xhr._deferred._results}}}settlePromise(xhr._deferred,fulfill,settleResult,info)}}}function onAfterLogout(pdsession,errorObject,xhr){var result=progress.data.Session.GENERAL_FAILURE,fulfill=false;if(xhr&&xhr._deferred){if(!errorObject&&!pdsession.loginResult){result=progress.data.Session.SUCCESS;fulfill=true}settlePromise(xhr._deferred,fulfill,result,{errorObject:errorObject,xhr:xhr})}}function onPingComplete(args){var xhr=args.xhr;if(xhr&&xhr._deferred){settlePromise(xhr._deferred,args.pingResult,args.pingResult,{offlineReason:args.offlineReason,xhr:xhr})}}this.login=function(username,password,options){var deferred=new progress.util.Deferred,iOSBasicAuthTimeout;function callIsAuthorized(){that.isAuthorized().then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(that,object.result,object.info)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG057","JSDOSession","login()"))}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout}if(!_pdsession._authProvider){_pdsession._authProvider=new progress.data.AuthenticationProvider({uri:this.serviceURI,authenticationModel:this.authenticationModel});_pdsession._authProvider.logout().then(function(){return _pdsession._authProvider.login(username,password)}).then(function(){callIsAuthorized()},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(that,object.result,object.info)})}else{throw new Error(progress.data._getMsgText("jsdoMSG062","JSDOSession","login()"))}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.disconnect=function(){var deferred=new progress.util.Deferred,errorObject;try{_pdsession.subscribe("afterDisconnect",genericSessionEventHandler,this);_pdsession._disconnect(deferred)}catch(e){errorObject=new Error(progress.data._getMsgText("jsdoMSG049","JSDOSession","disconnect",e.message))}if(errorObject){if(progress.util.Deferred.useJQueryPromises){throw errorObject}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:errorObject})}}else{return deferred.promise()}};this.addCatalog=function(catalogURI,unameOrOpts,password,opts){var deferred=new progress.util.Deferred,catalogURIs,numCatalogs,catalogIndex,addResult,errorObject,iOSBasicAuthTimeout,username,options,authProvider;try{if(this._isInvalidated){throw new Error(progress.data._getMsgText("jsdoMSG510","JSDOSession"))}if(typeof catalogURI==="string"){catalogURIs=[catalogURI]}else if(catalogURI instanceof Array){catalogURIs=catalogURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","addCatalog","The first argument must be a string or an array of strings specifying the URI of the catalog."))}if(unameOrOpts){if(typeof unameOrOpts==="string"){if(this.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG058","Session"))}username=unameOrOpts;if(opts){options=opts;options.authProvider=undefined}}else if(typeof unameOrOpts==="object"){options=unameOrOpts}else{throw new Error(progress.data._getMsgText("jsdoMSG121","JSDOSession","2","object","addCatalog"))}}if(typeof options==="object"){iOSBasicAuthTimeout=options.iOSBasicAuthTimeout;if(options.authProvider){authProvider=options.authProvider}else if(this.authProvider){authProvider=this.authProvider}}if(!authProvider&&!this.authProvider&&!username){throw new Error(progress.data._getMsgText("jsdoMSG511"))}_pdsession.subscribe("afterAddCatalog",onAfterAddCatalog,this);numCatalogs=catalogURIs.length;deferred._numCatalogs=numCatalogs;deferred._numCatalogsProcessed=0;deferred._results=[];deferred._results.length=numCatalogs;for(catalogIndex=0;catalogIndex=200&&xhr.status<300){deferred.resolve(that,progress.data.Session.SUCCESS,info)}else{if(xhr.status===401){cbresult=progress.data.AuthenticationProvider._getAuthFailureReason(xhr)}else{cbresult=progress.data.Session.GENERAL_FAILURE}deferred.reject(that,cbresult,info)}}};try{xhr.send()}catch(e){throw new Error("JSDOSession: Unable to validate authorization. "+e.message)}})}else{result=progress.data.Session.LOGIN_AUTHENTICATION_REQUIRED;deferred.reject(that,result,{xhr:xhr})}}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(that,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.setContext=function(context){_pdsession._contextProperties.setContext(context)};this.setContextProperty=function(propertyName,propertyValue){_pdsession._contextProperties.setContextProperty(propertyName,propertyValue)};this.getContext=function(){return _pdsession._contextProperties.getContext()};this.getContextProperty=function(propertyName){return _pdsession._contextProperties.getContextProperty(propertyName)};this._onlineHandler=function(session,request){that.trigger("online",that,request)};this._offlineHandler=function(session,offlineReason,request){that.trigger("offline",that,offlineReason,request)};if(arguments.length>0&&typeof arguments[0]==="object"){if(options.serviceURI&&typeof options.serviceURI==="string"){_serviceURI=options.serviceURI}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options parameter must include a 'serviceURI' property that is a string."))}if(options.authenticationModel){if(typeof options.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The authenticationModel property of the options parameter must be a string."))}options.authenticationModel=options.authenticationModel.toLowerCase()}else{options.authenticationModel=progress.data.Session.AUTH_TYPE_ANON}if(options.authProvider){if(typeof options.authProvider!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG502","JSDOSession","options","constructor","authProvider"))}if(options.authProvider.authenticationModel!==progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authProvider.authenticationModel!==options.authenticationModel||options.authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_FORM_SSO&&options.authenticationModel!==progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG059","JSDOSession",options.authProvider.authenticationModel,options.authenticationModel))}if(typeof options.authProvider.hasClientCredentials==="function"){if(!options.authProvider.hasClientCredentials()){throw new Error(progress.data._getMsgText("jsdoMSG125","JSDOSession"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG505","JSDOSession","AuthenticationProvider","hasClientCredentials"))}}else if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){throw new Error(progress.data._getMsgText("jsdoMSG508"))}}else{throw new Error(progress.data._getMsgText("jsdoMSG033","JSDOSession","the constructor","The options argument was missing or invalid."))}_name=options.name;_pdsession=new progress.data.Session({_storageKey:_name,_silent:true,authenticationModel:options.authenticationModel,serviceURI:options.serviceURI,jsdosession:this,authProvider:options.authProvider});try{if(options.context){this.setContext(options.context)}_pdsession.subscribe("online",this._onlineHandler,this);_pdsession.subscribe("offline",this._offlineHandler,this)}catch(err){_pdsession=undefined;throw err}};progress.data.JSDOSession.prototype=new progress.util.Observable;progress.data.JSDOSession.prototype.constructor=progress.data.JSDOSession;function validateJSDOSessionSubscribe(args,evt,listenerData){listenerData.operation=undefined;var found=false;this._eventNames.forEach(function(eventName){if(evt===eventName.toLowerCase()){found=true}});if(!found){throw new Error(progress.data._getMsgText("jsdoMSG042",evt))}if(args.length<2){throw new Error(progress.data._getMsgText("jsdoMSG038",2))}if(typeof args[0]!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG039"))}if(typeof args[1]!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG040"))}listenerData.fn=args[1];if(args.length>2){if(typeof args[2]!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG041",evt))}listenerData.scope=args[2]}}progress.data.JSDOSession.prototype._eventNames=["offline","online"];progress.data.JSDOSession.prototype.validateSubscribe=validateJSDOSessionSubscribe;progress.data.JSDOSession.prototype.toString=function(radix){return"progress.data.JSDOSession"};progress.data.getSession=function(options){var deferred=new progress.util.Deferred,authProvider,promise,authProviderInitObject={};function sessionRejectHandler(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);if(authProvider&&authProvider.hasClientCredentials()){var callback=function(){deferred.reject(object.result,object.info)};authProvider.logout().then(callback,callback)}else{deferred.reject(object.result,object.info)}}function callbackRejectHandler(reason){deferred.reject(progress.data.Session.GENERAL_FAILURE,{reason:reason})}function loginHandler(object){var jsdosession;try{jsdosession=new progress.data.JSDOSession(options);try{jsdosession.isAuthorized().then(function(){return jsdosession.addCatalog(options.catalogURI)},sessionRejectHandler).then(function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.resolve(object.jsdosession,progress.data.Session.SUCCESS)},sessionRejectHandler)}catch(e){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}catch(ex){sessionRejectHandler(jsdosession,progress.data.Session.GENERAL_FAILURE,{errorObject:ex})}}function callLogin(provider){var errorObject;if(typeof options.loginCallback!=="undefined"){options.loginCallback().then(function(result){try{provider.login(result.username,result.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}},callbackRejectHandler)}else if(options.username&&options.password){try{provider.login(options.username,options.password).then(loginHandler,sessionRejectHandler)}catch(e){sessionRejectHandler(provider,progress.data.Session.GENERAL_FAILURE,{errorObject:e})}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG052","getSession()"));sessionRejectHandler(provider,progress.data.Session.AUTHENTICATION_FAILURE,{errorObject:errorObject})}}if(typeof options!=="object"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options","object"))}if(typeof options.loginCallback!=="undefined"&&typeof options.loginCallback!=="function"){throw new Error(progress.data._getMsgText("jsdoMSG503","getSession()","options.loginCallback","function"))}try{if(options.authenticationModel===progress.data.Session.AUTH_TYPE_SSO){if(!options.authenticationURI||!options.authProviderAuthenticationModel){throw new Error(progress.data._getMsgText("jsdoMSG509"))}}if(options.authenticationURI){authProviderInitObject.uri=options.authenticationURI;authProviderInitObject.authenticationModel=options.authProviderAuthenticationModel;if(typeof authProviderInitObject.authenticationModel!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG502","progress.data.getSession","object","getSession","authProviderAuthenticationModel"))}}else{authProviderInitObject.uri=options.serviceURI;authProviderInitObject.authenticationModel=options.authenticationModel}authProvider=new progress.data.AuthenticationProvider(authProviderInitObject);options.authProvider=authProvider;if(authProvider.hasClientCredentials()){loginHandler(authProvider)}else{if(authProvider.authenticationModel===progress.data.Session.AUTH_TYPE_ANON){authProvider.login().then(loginHandler,sessionRejectHandler)}else{callLogin(authProvider)}}}catch(error){sessionRejectHandler(null,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}return deferred.promise()};progress.data.invalidateAllSessions=function(){var jsdosession,key,deferred=new progress.util.Deferred,jsdosessions=progress.data.ServicesManager._jsdosessions,invalidatePromises=[];try{for(key in jsdosessions){if(jsdosessions.hasOwnProperty(key)){jsdosession=jsdosessions[key];invalidatePromises.push(jsdosession.invalidate())}}progress.util.Deferred.when(invalidatePromises).then(function(){deferred.resolve(progress.data.Session.SUCCESS)},function(object,result,info){object=progress.util.Deferred.getParamObject(object,result,info);deferred.reject(progress.data.Session.GENERAL_FAILURE,info)})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()}})();if(typeof exports!=="undefined"){exports.progress=progress}(function(){"use strict";if(typeof progress==="undefined"){progress={}}if(typeof progress.data==="undefined"){progress.data={}}progress.data.AuthenticationProvider=function AuthenticationProvider(initObject){var authProv,authModel,uri;if(typeof initObject==="object"){this._checkStringArg("constructor",initObject.authenticationModel,"initObject.authenticationModel","initObject.authenticationModel");this._checkStringArg("constructor",initObject.uri,"init-object.uri","init-object.uri")}else{throw new Error(progress.data._getMsgText("jsdoMSG033","AuthenticationProvider","the constructor","The init-object argument was missing or invalid."))}authModel=initObject.authenticationModel.toLowerCase();switch(authModel){case progress.data.Session.AUTH_TYPE_ANON:this._initialize(initObject.uri,progress.data.Session.AUTH_TYPE_ANON,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});authProv=this;break;case progress.data.Session.AUTH_TYPE_BASIC:authProv=new progress.data.AuthenticationProviderBasic(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM:authProv=new progress.data.AuthenticationProviderForm(initObject.uri);break;case progress.data.Session.AUTH_TYPE_FORM_SSO:authProv=new progress.data.AuthenticationProviderSSO(initObject.uri);break;default:throw new Error(progress.data._getMsgText("jsdoMSG502","AuthenticationProvider","init-object","constructor","authenticationModel"))}return authProv};progress.data.AuthenticationProvider.prototype._loginProto=function(sendParam){var deferred=new progress.util.Deferred,xhr,uriForRequest,header,that=this;try{if(this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG051","AuthenticationProvider"))}xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLoginResult(xhr,deferred)}};if(progress.data.Session._useTimeStamp){uriForRequest=progress.data.Session._addTimeStampToURL(this._loginURI)}else{uriForRequest=this._loginURI}this._openLoginRequest(xhr,uriForRequest);xhr.setRequestHeader("Accept","application/json");xhr.send(sendParam)}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.login=function(){return this._loginProto()};progress.data.AuthenticationProvider.prototype._openLoginRequest=function(xhr,uri){xhr.open("GET",uri,true);progress.data.Session._setNoCacheHeaders(xhr)};progress.data.AuthenticationProvider.prototype._processLoginResult=function(xhr,deferred){var result;if(xhr.status===200){this._loggedIn=true;this._storeInfo();result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};progress.data.AuthenticationProvider.prototype.logout=function(){var deferred=new progress.util.Deferred;try{this._reset();deferred.resolve(this,progress.data.Session.SUCCESS,{})}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProvider.prototype.hasClientCredentials=function(){return this._loggedIn};progress.data.AuthenticationProvider.prototype.hasRefreshToken=function(){return false};progress.data.AuthenticationProvider.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);xhr.setRequestHeader("Accept","application/json");callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};progress.data.AuthenticationProvider.prototype._initialize=function(uriParam,authModel,targetURIs){var tempURI,target;Object.defineProperty(this,"uri",{get:function(){return this._uri},enumerable:true});Object.defineProperty(this,"authenticationModel",{get:function(){return this._authenticationModel},enumerable:true});if(uriParam[uriParam.length-1]==="/"){tempURI=uriParam.substring(0,uriParam.length-1)}else{tempURI=uriParam}for(target in targetURIs){if(targetURIs.hasOwnProperty(target)){this[target]=tempURI+targetURIs[target]}}this._authenticationModel=authModel;this._uri=uriParam;this._loggedIn=false;this._dataKeys={uri:".uri",loggedIn:".loggedIn"};if(typeof sessionStorage==="undefined"){throw new Error(progress.data._getMsgText("jsdoMSG126","AuthenticationProvider","sessionStorage"))}this._storage=sessionStorage;this._storageKey=this._uri;this._dataKeys.uri=this._storageKey+this._dataKeys.uri;this._dataKeys.loggedIn=this._storageKey+this._dataKeys.loggedIn;if(this._retrieveLoggedIn()){this._loggedIn=true}};progress.data.AuthenticationProvider.prototype._storeInfo=function(){this._storage.setItem(this._dataKeys.uri,JSON.stringify(this._uri));this._storage.setItem(this._dataKeys.loggedIn,JSON.stringify(this._loggedIn))};progress.data.AuthenticationProvider.prototype._retrieveInfoItem=function(propName){var jsonStr=this._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value};progress.data.AuthenticationProvider.prototype._retrieveURI=function(){return this._retrieveInfoItem(this._dataKeys.uri)};progress.data.AuthenticationProvider.prototype._retrieveLoggedIn=function(){return this._retrieveInfoItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._clearInfo=function(info){this._storage.removeItem(this._dataKeys.uri);this._storage.removeItem(this._dataKeys.loggedIn)};progress.data.AuthenticationProvider.prototype._reset=function(){this._clearInfo();this._loggedIn=false};progress.data.AuthenticationProvider.prototype._settlePromise=function(deferred,result,info){if(result===progress.data.Session.SUCCESS){deferred.resolve(this,result,info)}else{deferred.reject(this,result,info)}};progress.data.AuthenticationProvider.prototype._checkStringArg=function(fnName,argToCheck,argPosition,argName){if(typeof argToCheck!=="string"){throw new Error(progress.data._getMsgText("jsdoMSG121","AuthenticationProvider",argPosition,"string",fnName))}else if(argToCheck.length===0){throw new Error(progress.data._getMsgText("jsdoMSG501","AuthenticationProvider",argName,fnName))}};progress.data.AuthenticationProvider._getAuthFailureReason=function(xhr){var contentType,jsonObject,result=progress.data.Session.AUTHENTICATION_FAILURE;if(xhr.status===401){contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("application/json")>-1&&xhr.responseText){jsonObject=JSON.parse(xhr.responseText);if(jsonObject.error==="sso.token.expired_token"){result=progress.data.Session.EXPIRED_TOKEN}}}else{result=null}return result};Object.defineProperty(progress.data.AuthenticationProvider,"_homeLoginURIBase",{value:"/static/home.html",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLoginURIBase",{value:"/static/auth/j_spring_security_check",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springLogoutURIBase",{value:"/static/auth/j_spring_security_logout",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenLoginURIBase",{value:progress.data.AuthenticationProvider._springLoginURIBase+"?OECP=yes",enumerable:true});Object.defineProperty(progress.data.AuthenticationProvider,"_springFormTokenRefreshURIBase",{value:"/static/auth/token?op=refresh",enumerable:true})})();(function(){"use strict";progress.data.AuthenticationProviderBasic=function(uri){var defaultiOSBasicAuthTimeout,userName=null,password=null,fn;this._initialize(uri,progress.data.Session.AUTH_TYPE_BASIC,{_loginURI:progress.data.AuthenticationProvider._homeLoginURIBase});this._reset();function make_basic_auth_header(user,pw){var tok=user+":"+pw,hash=btoa(tok);return"Basic "+hash}this._reset=function(){userName=null;password=null;progress.data.AuthenticationProviderBasic.prototype._reset.apply(this)};this._openLoginRequest=function(xhr,uri){var auth;xhr.open("GET",uri,true);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr)};this._processLoginResult=function _basic_processLoginResult(xhr,deferred){progress.data.AuthenticationProviderBasic.prototype._processLoginResult.apply(this,[xhr,deferred]);if(!this._loggedIn){userName=null;password=null}};this.login=function(userNameParam,passwordParam){this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");userName=userNameParam;password=passwordParam;return this._loginProto()};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var auth,errorObject;if(this.hasClientCredentials()){xhr.open(verb,uri,async);if(userName){auth=make_basic_auth_header(userName,password);xhr.setRequestHeader("Authorization",auth)}progress.data.Session._setNoCacheHeaders(xhr);callback(xhr)}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}}};function BasicProxy(){}BasicProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderBasic.prototype=new BasicProxy;progress.data.AuthenticationProviderBasic.prototype.constructor=progress.data.AuthenticationProviderBasic})();(function(){"use strict";var fn;progress.data.AuthenticationProviderForm=function(uri){this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM,{_loginURI:progress.data.AuthenticationProvider._springLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase})};function FormProxy(){}FormProxy.prototype=progress.data.AuthenticationProvider.prototype;progress.data.AuthenticationProviderForm.prototype=new FormProxy;progress.data.AuthenticationProviderForm.prototype.constructor=progress.data.AuthenticationProviderForm;progress.data.AuthenticationProviderForm.prototype.login=function(userNameParam,passwordParam){var deferred=new progress.util.Deferred,xhr,that=this;this._checkStringArg("login",userNameParam,1,"userName");this._checkStringArg("login",passwordParam,2,"password");return this._loginProto("j_username="+encodeURIComponent(userNameParam)+"&j_password="+encodeURIComponent(passwordParam)+"&submit=Submit")};progress.data.AuthenticationProviderForm.prototype._openLoginRequest=function(xhr,uri){xhr.open("POST",uri,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.setRequestHeader("Pragma","no-cache");xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xhr.withCredentials=true};progress.data.AuthenticationProviderForm.prototype.logout=function(){var deferred=new progress.util.Deferred,xhr,that=this;try{if(!this._loggedIn){deferred.resolve(this,progress.data.Session.SUCCESS,{})}else{xhr=new XMLHttpRequest;this._openLogoutRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){that._processLogoutResult(xhr,deferred)}};xhr.send()}this._reset()}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};progress.data.AuthenticationProviderForm.prototype._openLogoutRequest=function(xhr){xhr.open("GET",this._logoutURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Accept","application/json")};progress.data.AuthenticationProviderForm.prototype._processLogoutResult=function(xhr,deferred){var result;if(xhr.status===200){result=progress.data.Session.SUCCESS}else if(xhr.status===401){result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};fn=progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize;progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){function afterSuper(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.withCredentials=true;callback(xhr)}}try{progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super.apply(this,[xhr,verb,uri,async,afterSuper])}catch(e){callback(e)}};progress.data.AuthenticationProviderForm.prototype._openRequestAndAuthorize._super=fn})();(function(){"use strict";var fn;progress.data.AuthenticationProviderSSO=function(uri){var that=this,_automaticTokenRefresh,temp,ssoTokenInfo=null,tokenDataKeys={token:".access_token",refreshToken:".refresh_token",tokenType:".token_type",expiration:".expires_in",accessTokenExpiration:".accessTokenExpiration"};function storeTokenInfo(info){var date,accessTokenExpiration;if(info.access_token.length){that._storage.setItem(tokenDataKeys.token,JSON.stringify(info.access_token))}if(info.refresh_token.length){that._storage.setItem(tokenDataKeys.refreshToken,JSON.stringify(info.refresh_token));date=new Date;accessTokenExpiration=date.getTime()+info.expires_in*1e3*.75;that._storage.setItem(tokenDataKeys.accessTokenExpiration,JSON.stringify(accessTokenExpiration))}else{that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}that._storage.setItem(tokenDataKeys.tokenType,JSON.stringify(info.token_type));that._storage.setItem(tokenDataKeys.expiration,JSON.stringify(info.expires_in))}function retrieveTokenProperty(propName){var jsonStr=that._storage.getItem(propName),value=null;if(jsonStr!==null){try{value=JSON.parse(jsonStr)}catch(e){value=null}}return value}function retrieveToken(){return retrieveTokenProperty(tokenDataKeys.token)}function retrieveRefreshToken(){return retrieveTokenProperty(tokenDataKeys.refreshToken)}function retrieveAccessTokenExpiration(){return retrieveTokenProperty(tokenDataKeys.accessTokenExpiration)}function retrieveTokenType(){return retrieveTokenProperty(tokenDataKeys.tokenType)}function getToken(){return retrieveToken()}function retrieveExpiration(){return retrieveTokenProperty(tokenDataKeys.expiration)}function clearTokenInfo(info){that._storage.removeItem(tokenDataKeys.token);that._storage.removeItem(tokenDataKeys.refreshToken);that._storage.removeItem(tokenDataKeys.tokenType);that._storage.removeItem(tokenDataKeys.expiration);that._storage.removeItem(tokenDataKeys.accessTokenExpiration)}function openRefreshRequest(xhr){xhr.open("POST",that._refreshURI,true);xhr.setRequestHeader("Cache-Control","max-age=0");xhr.withCredentials=true;xhr.setRequestHeader("Content-Type","application/json");xhr.setRequestHeader("Accept","application/json")}function processRefreshResult(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","refresh",ex.message))}}else if(xhr.status===401){that._reset();result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}that._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})}this._processLoginResult=function(xhr,deferred){var errorObject,result,ssoTokenJSON;if(xhr.status===200){this._loggedIn=true;try{ssoTokenInfo=JSON.parse(xhr.responseText);if(ssoTokenInfo.access_token){storeTokenInfo(ssoTokenInfo);result=progress.data.Session.SUCCESS}else{result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",progress.data._getMsgText("jsdoMSG050")))}}catch(ex){result=progress.data.Session.GENERAL_FAILURE;errorObject=new Error(progress.data._getMsgText("jsdoMSG049","AuthenticationProvider","login",ex.message))}if(result!==progress.data.Session.SUCCESS){var callback=function(params){params=progress.util.Deferred.getParamObject(params);params.provider._settlePromise(deferred,result,{xhr:xhr,errorObject:errorObject})};this.logout().then(callback,callback);return}}else if(xhr.status===401){result=progress.data.Session.AUTHENTICATION_FAILURE}else{result=progress.data.Session.GENERAL_FAILURE}this._settlePromise(deferred,result,{xhr:xhr})};this._reset=function(){progress.data.AuthenticationProviderSSO.prototype._reset.apply(this);clearTokenInfo();ssoTokenInfo=null};this._openRequestAndAuthorize=function(xhr,verb,uri,async,callback){var that=this,date,errorObject;function afterRefreshCheck(provider,result,info){if(result===progress.data.Session.AUTHENTICATION_FAILURE){callback(new Error(progress.data._getMsgText("jsdoMSG060")))}else{progress.data.AuthenticationProviderSSO.prototype._openRequestAndAuthorize.apply(that,[xhr,verb,uri,async,function(errorObject){if(errorObject instanceof Error){callback(errorObject)}else{xhr.setRequestHeader("Authorization","oecp "+getToken());callback(xhr)}}])}}if(this.hasClientCredentials()){date=new Date;if(this.automaticTokenRefresh&&this.hasRefreshToken()&&date.getTime()>retrieveAccessTokenExpiration()){try{var callback=function(params,result,info){params=progress.util.Deferred.getParamObject(params,result,info);afterRefreshCheck(params.provider,params.result,params.info)};this.refresh().then(callback,callback)}catch(e){callback(e)}}else{afterRefreshCheck(this,progress.data.Session.SUCCESS,null)}}else{errorObject=new Error(progress.data._getMsgText("jsdoMSG125","AuthenticationProvider"));callback(errorObject)}};this.hasClientCredentials=function(){return retrieveToken()===null?false:true};this.refresh=function(){var deferred=new progress.util.Deferred,xhr;try{if(!this._loggedIn){throw new Error(progress.data._getMsgText("jsdoMSG053","AuthenticationProvider","refresh"))}if(!this.hasRefreshToken()){throw new Error(progress.data._getMsgText("jsdoMSG054","AuthenticationProvider"))}xhr=new XMLHttpRequest;openRefreshRequest(xhr);xhr.onreadystatechange=function(){if(xhr.readyState===4){processRefreshResult(xhr,deferred)}};xhr.send('{"token_type":"'+retrieveTokenType()+'","refresh_token":"'+retrieveRefreshToken()+'"}')}catch(error){if(progress.util.Deferred.useJQueryPromises){throw error}else{deferred.reject(this,progress.data.Session.GENERAL_FAILURE,{errorObject:error})}}return deferred.promise()};this.hasRefreshToken=function(){return retrieveRefreshToken()===null?false:true};this._initialize(uri,progress.data.Session.AUTH_TYPE_FORM_SSO,{_loginURI:progress.data.AuthenticationProvider._springFormTokenLoginURIBase,_logoutURI:progress.data.AuthenticationProvider._springLogoutURIBase,_refreshURI:progress.data.AuthenticationProvider._springFormTokenRefreshURIBase});_automaticTokenRefresh=true;Object.defineProperty(this,"automaticTokenRefresh",{get:function(){return _automaticTokenRefresh},set:function(value){if(value===true||value===false){_automaticTokenRefresh=value}else{throw new Error(progress.data._getMsgText("jsdoMSG061","AuthenticationProvider","automaticTokenRefresh"))}},enumerable:true});this._dataKeys.automaticTokenRefresh=this._storageKey+".automaticTokenRefresh";temp=this._retrieveInfoItem(this._dataKeys.automaticTokenRefresh);if(temp===false){_automaticTokenRefresh=false}tokenDataKeys.token=this._storageKey+tokenDataKeys.token;tokenDataKeys.refreshToken=this._storageKey+tokenDataKeys.refreshToken;tokenDataKeys.tokenType=this._storageKey+tokenDataKeys.tokenType;tokenDataKeys.expiration=this._storageKey+tokenDataKeys.expiration;tokenDataKeys.accessTokenExpiration=this._storageKey+tokenDataKeys.accessTokenExpiration;if(retrieveToken()){this._loggedIn=true}};function SSOProxy(){}SSOProxy.prototype=progress.data.AuthenticationProviderForm.prototype;progress.data.AuthenticationProviderSSO.prototype=new SSOProxy;progress.data.AuthenticationProviderSSO.prototype.constructor=progress.data.AuthenticationProviderSSO;fn=progress.data.AuthenticationProviderSSO.prototype._storeInfo;progress.data.AuthenticationProviderSSO.prototype._storeInfo=function(){progress.data.AuthenticationProviderSSO.prototype._storeInfo._super.apply(this);this._storage.setItem(this._dataKeys.automaticTokenRefresh,JSON.stringify(this._automaticTokenRefresh))};progress.data.AuthenticationProviderSSO.prototype._storeInfo._super=fn;fn=progress.data.AuthenticationProviderSSO.prototype._clearInfo;progress.data.AuthenticationProviderSSO.prototype._clearInfo=function(){progress.data.AuthenticationProviderSSO.prototype._clearInfo._super.apply(this);this._storage.removeItem(this._dataKeys.automaticTokenRefresh)};progress.data.AuthenticationProviderSSO.prototype._clearInfo._super=fn})(); //# sourceMappingURL=progress.jsdo.min.js.map \ No newline at end of file diff --git a/lib/progress.jsdo.min.js.map b/lib/progress.jsdo.min.js.map index 94645db..3e8b590 100644 --- a/lib/progress.jsdo.min.js.map +++ b/lib/progress.jsdo.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["progress.jsdo.js"],"names":["isNativeScript","isNodeJS","pkg_xmlhttprequest","pkg_nodeLocalstorage","pkg_nativescriptLocalstorage","pkg_fileSystemAccess","XMLHttpRequest","require","e","console","error","localStorage","sessionStorage","exception1","exception2","btoa","encode","exception3","LocalStorage","module","progress","data","util","STRING_OBJECT_TYPE","DATE_OBJECT_TYPE","CHARACTER_ABL_TYPE","Deferred","this","_deferred","prototype","promise","that","useJQueryPromises","$","_jQuerydeferred","_promise","Error","Promise","resolve","reject","_resolveArguments","_rejectArguments","setTimeout","apply","arg1","arg2","arg3","arguments","object","getParamObject1","when","deferreds","all","objectName","result","info","constructor","name","toLowerCase","success","xhr","request","info2","log","getParamObject","Observable","_filterObservers","observers","fn","scope","operation","filter","el","validateSubscribe","args","evt","listenerData","length","undefined","subscribe","_getMsgText","toString","_events","message","push","unsubscribe","trigger","op","Array","slice","call","forEach","unsubscribeAll","saveToLocalStorage","dataObj","setItem","JSON","stringify","readFromLocalStorage","jsonStr","getItem","parse","clearLocalStorage","removeItem","_convertToABLWhereString","tableRef","logic","idx","field","fieldInfo","type","format","operator","value","ablType","filters","whereOperators","eq","neq","gt","gte","lt","lte","contains","doesnotcontain","endswith","startswith","isnull","isnotnull","isempty","isnotempty","_name","_jsdo","_fields","origName","_getObjectType","replace","_getABLType","_format","join","_convertToSQLQueryString","addSelect","fieldFormat","filterStr","usingLike","_getFormat","Object","fmt","values","formatRegExp","match","index","placeholderFormat","parseInt","_toString","substring","str","_formatDate","_pad","number","digits","zeros","end","String","date","dateFormatRegExp","minutes","sign","getDate","getMonth","getFullYear","getHours","getMinutes","getSeconds","getMilliseconds","getTime","getTimezoneOffset","toISOString","jsdoSettingsProcessor","jsdoSettings","authenticationModel","PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS","PROGRESS_JSDO_OP_STRING","PROGRESS_JSDO_ROW_STATE_STRING","_nextid","_uidprefix","Date","now","UID_MAX_VALUE","_getNextId","uid","msg","msgs","jsdoMSG000","jsdoMSG001","jsdoMSG002","jsdoMSG003","jsdoMSG004","jsdoMSG005","jsdoMSG006","jsdoMSG007","jsdoMSG008","jsdoMSG009","jsdoMSG010","jsdoMSG011","jsdoMSG012","jsdoMSG020","jsdoMSG021","jsdoMSG022","jsdoMSG023","jsdoMSG024","jsdoMSG025","jsdoMSG026","jsdoMSG030","jsdoMSG031","jsdoMSG032","jsdoMSG033","jsdoMSG034","jsdoMSG035","jsdoMSG036","jsdoMSG037","jsdoMSG038","jsdoMSG039","jsdoMSG040","jsdoMSG041","jsdoMSG042","jsdoMSG043","jsdoMSG044","jsdoMSG045","jsdoMSG046","jsdoMSG047","jsdoMSG048","jsdoMSG049","jsdoMSG050","jsdoMSG051","jsdoMSG052","jsdoMSG053","jsdoMSG054","jsdoMSG055","jsdoMSG056","jsdoMSG057","jsdoMSG058","jsdoMSG059","jsdoMSG060","jsdoMSG061","jsdoMSG062","jsdoMSG100","jsdoMSG101","jsdoMSG110","jsdoMSG111","jsdoMSG112","jsdoMSG113","jsdoMSG114","jsdoMSG115","jsdoMSG116","jsdoMSG117","jsdoMSG118","jsdoMSG119","jsdoMSG120","jsdoMSG121","jsdoMSG122","jsdoMSG123","jsdoMSG124","jsdoMSG125","jsdoMSG126","jsdoMSG127","jsdoMSG500","jsdoMSG501","jsdoMSG502","jsdoMSG503","jsdoMSG504","jsdoMSG505","jsdoMSG506","jsdoMSG507","jsdoMSG508","jsdoMSG509","jsdoMSG510","jsdoMSG511","jsdoMSG512","jsdoMSG998","getMsgText","n","text","i","RegExp","PluginManager","_plugins","addPlugin","plugin","getPlugin","JSIndexEntry","JSTableRef","jsdo","tableName","_schema","_primaryKeys","_processed","_visited","record","_data","_index","_tmpIndex","_hasEmptyBlocks","_beforeImage","_added","_changed","_deleted","_lastErrors","_convertForServer","_createIndex","block","id","idProperty","_id","_resource","_needCompaction","_compact","newDataArray","_loadBeforeImageData","jsonObject","beforeImageJsonIndex","keyFields","prodsBeforeData","_dataSetName","tmpIndex","record2","recordId","key","tmpKeyIndex","jsrecord","tmpDataIndex","tmpDeletedIndex","j","keys","_findById","_getKey","key2","_remove","copy","_copyRecord","_tableRef","_deleteProdsProperties","JSRecord","tableObject","beforeRecord","prodsErrors","item","_errorString","_clearData","_setRecord","hasData","_nestChildren","_getDataWithNestedChildren","_getRelatedData","getData","params","_getData","numEmptyBlocks","sort","top","sortFields","dir","sortObject","_processSortFields","_getCompareFn","skip","splice","_recToDataObject","includeChildren","array","dataObject","_children","_buffers","_dataProperty","_recFromDataObject","getSchema","setSchema","schema","fieldName","add","_add","create","trackChanges","setWorkingRecord","prefixElement","maxItems","_getDefaultValue","_getArrayField","items","_convertType","useRelationships","_relationship","_parent","childFieldName","parentFieldName","v","autoSort","_sortRecords","_sortFn","_sortObject","_needsAutoSorting","_sort","ret","_compareFields","parentRecord","childBuf","_isNested","k","childRecord","m","_hasNestedChild","_findFirst","ignoreRelationships","childTable","_defaultTableRef","assign","update","remove","bTrackChanges","getId","getErrors","getErrorString","findById","find","foreach","_inforeach","_equalRecord","rec1","rec2","value1","value2","caseSensitive","toUpperCase","keyObject","jsrec1","jsrec2","sortAscending","defineProperty","_autoSort","get","set","enumerable","writeable","_caseSensitive","fields","indexOf","sortOrder","setSortFields","setSortFn","addRecords","addMode","isInvoke","_addRecords","acceptChanges","rejectChanges","_undoCreate","_undoUpdate","_undoDelete","hasChanges","getChanges","rowState","JSDO","_OP_CREATE","_OP_UPDATE","_OP_DELETE","_clearErrorStrings","_applyChanges","_rejected","acceptRowChanges","found","rejectRowChanges","hasNestedChild","childBufObj","_saveBeforeImageUpdate","_sortRecord","resNameOrParmObj","serviceName","_super","Session","_defineProperty","fnGet","element","ARRAY_INDEX_SEPARATOR","isNaN","_hasSubmitOperation","_hasCUDOperations","_numBuffers","_async","operations","_session","_useSubmit","autoApplyChanges","_localStorage","_fillMergeMode","autoFill","eventName","prop","ServicesManager","getResource","url","dataProperty","buffer","properties","fnName","generic","myservice","getService","service","_pushJSDOs","buf","_properties","primaryKeys","trim","$ref","relations","relationship","childName","parentName","relationFields","defaultValue","t","d","isDate","arrayFieldName","isDataSet","_invokeComplete","async","deferred","_invokeSuccess","_invokeError","_httpRequest","method","reqBody","afterOpenRequest","input","setRequestHeader","send","exception","_checkServiceResponse","onCompleteFn","onSuccessFn","onErrorFn","onreadystatechange","onReadyStateChangeGeneric","useRequest","settings","_openRequest","_getDataObject","oldUseRelationships","_getDataObjectAsNested","bufObj","_unnestData","obj","itemType","elements","split","convertItem","parseFloat","_clearErrors","clearErrorString","_setAllRecordsRejected","param","changes","hasErrors","hasRejected","hasCommittedRecords","_allRecordsRejected","_someRecordsRejected","fill","objParam","mapping","getMethodProperties","mappingType","mergeMode","MODE_APPEND","MODE_EMPTY","MODE_MERGE","MODE_REPLACE","requestMapping","capabilities","_fillSuccess","_fillError","_fillComplete","read","errorObject","_execGenericOperation","_convertRequestData","operationStr","_OP_READ","_OP_SUBMIT","_initConvertForServer","_convertFieldsForServer","_ablTypeNeedsConversion","beforeData","_convertTableData","tableData","_convertRowData","_convertField","resultArray","_convertDate","needsConversion","_undefWorkingRecord","saveChanges","useSubmit","_checkThatJSDOHasRequiredOperations","_syncDataSetForSubmit","_syncDataSetForCUD","_syncSingleTable","checkedDelete","checkedCreate","checkedUpdate","_confirmOperationExists","invoke","_syncTableRef","batch","rowData","requestData","dataSetObject","_useBeforeImage","_createComplete","_createSuccess","_createError","useBeforeImageFormat","beforeObject","beforeRowData","sendOnlyChanges","_updateComplete","_updateSuccess","_updateError","childTableName","_deleteComplete","_deleteSuccess","_deleteError","opType","useBeforeImage","_isBatchComplete","_isBatchSuccess","_updateLastErrors","_fireAfterSaveChanges","fireAfterSaveChanges","addedRecords","complete","completeFn","_saveChangesComplete","successFn","_saveChangesSuccess","errorFn","_saveChangesError","jsrecords","_createChangeSet","_createTTChangeSet","_saveChangesSuccessTT","dataSetName","alwaysCreateTable","changeSetJsonObject","dataSetJsonObject","_hasChanges","_addDeletesToChangeSet","_addCreatesToChangeSet","_addChangesToChangeSet","tempTableJsonObject","_addRowToTTChangeSet","hasOwnProperty","event","_createDataAndChangeSet","_addRecordsToObject","_doesRecordHaveCreateBIData","_addCreatedRowToChangeSet","_doesRecordHaveUpdateBIData","_addChangedRowToChangeSet","changedId","hasUpdates","_addDeletedRowToChangeSet","beforeTableJsonObject","_getTableInBeforeJsonObject","source","target","onlyChangesRecord","newObject","deleteRowState","beforeImageJsonObject","dataHasBeenProcessed","checkBeforeImage","isAfterSame","_sameData","isBeforeSame","_getBeforeRecordFromObject","afterRecord","tablename","record1","_mergeRead","datasetBuffer","srcData","_mergeUpdateRecord","_setErrorString","errorString","setInBeforeTable","_arrayFromDataObject","_mergeUpdateForCUD","hasError","tableJsonObject","prods_id","_getErrorStringFromJsonObject","_checkForDeleteError","beforeJsonObject","_mergeUpdateForSubmit","_fireCUDTriggersForSubmit","errorsJsonObject","response","responseMapping","entry","deleteProdsProps","_checkSaveComplete","records","status","_getErrorsFromRequest","errors","errorArray","retValString","responseObject","responseText","_retVal","RETVAL","_errors","_errorNum","_errorMsg","APP_ERROR","errorNum","ERROR","statusText","errorText","DATA_ERROR","_mergeInvoke","dataParameterName","_tempTableName","xType","readyState","_saveClientContextId","concat","setProperties","propertiesObject","setProperty","propertyName","propertyValue","getProperties","getProperty","saveLocal","dataMode","callee","ALL_DATA","CHANGES_ONLY","_prepareDataObjectForLocalStorage","readLocal","_hasMatchingSchema","_restoreFromLocalStorage","addLocalRecords","_containsPrimaryKeys","storageObject","isValid","deleteLocal","option","_restoreDataForTable","_operations","radix","sortDir","ablFilter","sqlQuery","methodProperties","position","capabilitiesObject","reqCapabilities","options","doConversion","orderBy","ui","UITableRef","_listview","_detailPage","_listviewContent","addItem","detailForm","clearItems","itemTemplate","UIHelper","_itemTemplate","listviewElement","document","getElementById","innerHTML","_getFormFieldValue","detailPageName","val","_setFormField","display","pageName","showListView","uiTableRef","html","attr","filterable","listview","autoLink","each","bind","getListViewRecord","onSelect","childElementCount","children","onclick","getFormFields","tmpFields","htmltext","charAt","fieldLabel","title","fieldTemplate","_fieldTemplate","htmlIElement","getAttribute","getFormRecord","_getIdOfElement","setDetailPage","setListView","pos","_defaultUITableRef","_uiTableRef","cnt","_defaultItemTemplate","_defaultFieldTemplate","setItemTemplate","template","setFieldTemplate","_services","_resources","_sessions","_jsdosessions","addResource","resource","addService","addSession","catalogURI","session","addJSDOSession","jsdosession","getSession","cleanSession","servicesKey","resourcesKey","sessionsKey","services","resources","sessions","jsdosessions","extractParamsFromURL","urlParams","paramName","c","addCatalog","baseAddress","address","path","primaryKey","tableProperties","RelationName","opname","verb","func","definition","Boolean","encodeURIComponent","reqParam","unwrapped","paramsFromURL","printDebugInfo","resourceName","cSchema","cOperations","MobileServiceObject","_uri","uri","ContextProperties","contextObject","contextString","header","setContextProperty","setContext","context","getContext","getContextProperty","defPropSupported","isUserAgentiOS","isFirefox","isEdge","isIE","canPassCredentialsToOpenWithCORS","defaultiOSBasicAuthTimeout","deviceIsOnline","restApplicationIsOnline","oepingAvailable","defaultPartialPingURI","partialPingURI","_storageKey","_authProvider","customCredentials","storedAuthModel","storedURI","newURI","stateWasReadFromStorage","_silent","warn","navigator","userAgent","canPassCredentialsToOpen","_onlineHandler","setDeviceIsOnline","_offlineHandler","DEVICE_OFFLINE","window","addEventListener","_catalogURIs","_jsdos","onOpenRequest","_password","_userName","_loginTarget","_serviceURI","_loginResult","_loginHttpStatus","_clientContextId","_authenticationModel","AUTH_TYPE_ANON","newval","AUTH_TYPE_FORM","AUTH_TYPE_BASIC","AUTH_TYPE_SSO","storeSessionInfo","_lastSessionXHR","loginResult","LOGIN_SUCCESS","_pingInterval","_timeoutID","_autoping","clearTimeout","_contextProperties","isInvalidated","setAuthProvider","userName","loginTarget","serviceURI","catalogURIs","loginHttpStatus","clientContextId","lastSessionXHR","infoName","retrieveSessionInfo","clearSessionInfo","storeAllSessionInfo","pingInterval","clearAllSessionInfo","setSessionInfoFromStorage","authproviderInitObject","setLoginResult","setUserName","setServiceURI","setLoginHttpStatus","setClientContextID","setRestApplicationIsOnline","setOepingAvailable","setPartialPingURI","AuthenticationProvider","newname","sessionObject","setLoginTarget","pushCatalogURIs","pushService","serviceObject","findService","setClientContextIDfromXHR","getResponseHeaderNoError","ccid","setLastSessionXHR","headerName","allHeaders","_pdsResponseHeaders","regExp","getAllResponseHeaders","getResponseHeader","callback","urlPlusCCID","afterOpenAndAuthorize","arg","setRequestHeaderFromContextProps","formPreTest","_isInvalidated","_prependAppURL","_addCCIDtoURL","_useTimeStamp","_addTimeStampToURL","_openRequestAndAuthorize","_setXHRCredentials","_addWithCredentialsAndAccept","pingTestCallback","cbArgs","foundOeping","pingResult","_onReadyStateChangeGeneric","_requestTimeout","onResponseFn","onResponseProcessedFn","GENERAL_FAILURE","pdsession","_disconnect","_processDisconnectResult","_reinitializeAfterLogout","SUCCESS","_disconnectComplete","errObj","pwSave","unameSave","login","loginUserName","loginPassword","uname","pw","isAsync","iOSBasicAuthTimeout","uriForRequest","password","restURLtemp","LOGIN_GENERAL_FAILURE","_setNoCacheHeaders","_isAsync","_afterFormPretestLogin","_processLoginResult","_loginComplete","_iosTimeOutExpired","abort","_jsdosession","isFormPreTest","ASYNC_PENDING","formLoginParams","theSession","doFormLogin","oldXHR","contentType","needAuth","statusFromjson","handleJSONLoginResponse","_gotLoginForm","open","cbparams","_afterFormLogin","_gotLoginFailure","pingTestArgs","pingURI","fireEventIfOfflineChange","onReadyStateFn","_pingtestOnReadyStateChange","_makePingURI","_sendPing","LOGIN_AUTHENTICATION_FAILURE","updateContextPropsFromResponse","logout","_processLogoutResult","_logoutComplete","withCredentials","_anonymousLogoutOK","invalidate","cleanServicesManager","logoutSucceeded","basicStatusOK","arg4","catalogUserName","catalogPassword","catalogIndex","authProvider","addCatalogAfterOpen","_processAddCatalogResult","_addCatalogComplete","_catalogIndex","offlineAddCatalog","_catalogURI","CATALOG_ALREADY_LOADED","_catalogHttpStatus","servicedata","serviceURL","theJSDOSession","toggleOnlineState","_parseCatalog","useXClientProps","xClientProps","_getAuthFailureReason","ping","pingArgs","_onReadyStateChangePing","offlineReason","doNotFireEvent","_processPingResult","_isOnlineStateChange","isOnline","stateChanged","wasOnline","connected","offlineObservers","offline","onlineObservers","online","localPingArgs","pingResponseJSON","appServerStatus","connectedBeforeCallback","assumeOepingFormat","usingOepingFormat","AppServerStatus","SERVER_OFFLINE","WEB_APPLICATION_OFFLINE","PingStatus","APPSERVER_OFFLINE","sendPingAfterOpen","auth","_make_basic_auth","urlPart1","urlPart2","jsessionidStr","catalogdata","oldURL","newURL","pat","test","acceptString","user","tok","hash","loginFormIDString","_findStringInResponseHTML","loginFailureIdentificationString","searchString","status_code","status_txt","contextHeader","hasClientCredentials","SEQ_MAX_VALUE","_tsseq","_tsprefix1","_tsprefix2","_getNextTimeStamp","seq","Math","floor","random","round","timeStamp","AUTHENTICATION_FAILURE","validateSessionSubscribe","_eventNames","JSDOSession","_pdsession","JSDOs","settlePromise","fulfill","genericSessionEventHandler","myDeferred","onAfterAddCatalog","settleResult","EXPIRED_TOKEN","_overallCatalogResult","_results","_numCatalogsProcessed","_numCatalogs","_processedPromise","details","onAfterLogout","onPingComplete","username","callIsAuthorized","isAuthorized","then","disconnect","unameOrOpts","opts","numCatalogs","addResult","authProv","cbresult","LOGIN_AUTHENTICATION_REQUIRED","AUTH_TYPE_FORM_SSO","err","validateJSDOSessionSubscribe","authProviderInitObject","sessionRejectHandler","callbackRejectHandler","reason","loginHandler","ex","callLogin","provider","loginCallback","authenticationURI","authProviderAuthenticationModel","invalidateAllSessions","invalidatePromises","exports","initObject","authModel","_checkStringArg","_initialize","_loginURI","_homeLoginURIBase","AuthenticationProviderBasic","AuthenticationProviderForm","AuthenticationProviderSSO","_loginProto","sendParam","_loggedIn","_openLoginRequest","_storeInfo","_settlePromise","_reset","hasRefreshToken","uriParam","targetURIs","tempURI","_dataKeys","loggedIn","_storage","_retrieveLoggedIn","_retrieveInfoItem","propName","_retrieveURI","_clearInfo","argToCheck","argPosition","argName","_springLoginURIBase","make_basic_auth_header","_basic_processLoginResult","userNameParam","passwordParam","BasicProxy","_logoutURI","_springLogoutURIBase","FormProxy","_openLogoutRequest","afterSuper","_automaticTokenRefresh","temp","ssoTokenInfo","tokenDataKeys","token","refreshToken","tokenType","expiration","accessTokenExpiration","storeTokenInfo","access_token","refresh_token","expires_in","token_type","retrieveTokenProperty","retrieveToken","retrieveRefreshToken","retrieveAccessTokenExpiration","retrieveTokenType","getToken","retrieveExpiration","clearTokenInfo","openRefreshRequest","_refreshURI","processRefreshResult","ssoTokenJSON","afterRefreshCheck","automaticTokenRefresh","refresh","_springFormTokenLoginURIBase","_springFormTokenRefreshURIBase","SSOProxy"],"mappings":"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"} \ No newline at end of file +{"version":3,"sources":["progress.jsdo.js"],"names":["isNativeScript","isNodeJS","pkg_xmlhttprequest","pkg_nodeLocalstorage","pkg_nativescriptLocalstorage","pkg_fileSystemAccess","pkg_base64","XMLHttpRequest","require","e","console","error","localStorage","sessionStorage","exception1","exception2","btoa","encode","exception3","LocalStorage","module","progress","data","util","STRING_OBJECT_TYPE","DATE_OBJECT_TYPE","CHARACTER_ABL_TYPE","Deferred","this","_deferred","prototype","promise","that","useJQueryPromises","$","_jQuerydeferred","_promise","Error","Promise","resolve","reject","_resolveArguments","_rejectArguments","setTimeout","apply","arg1","arg2","arg3","arguments","object","getParamObject1","when","deferreds","all","objectName","result","info","JSDOSession","AuthenticationProvider","JSDO","success","xhr","request","batch","info2","log","getParamObject","Observable","_filterObservers","observers","fn","scope","operation","filter","el","validateSubscribe","args","evt","listenerData","length","undefined","subscribe","_getMsgText","toString","_events","toLowerCase","message","push","unsubscribe","trigger","op","Array","slice","call","forEach","unsubscribeAll","saveToLocalStorage","name","dataObj","setItem","JSON","stringify","readFromLocalStorage","jsonStr","getItem","parse","clearLocalStorage","removeItem","_convertToABLWhereString","tableRef","logic","idx","field","fieldInfo","type","format","operator","value","ablType","filters","whereOperators","eq","neq","gt","gte","lt","lte","contains","doesnotcontain","endswith","startswith","isnull","isnotnull","isempty","isnotempty","_name","_jsdo","_fields","origName","_getObjectType","replace","_getABLType","_format","join","_convertToSQLQueryString","addSelect","fieldFormat","filterStr","usingLike","_getFormat","Object","fmt","values","formatRegExp","match","index","placeholderFormat","parseInt","_toString","substring","str","_formatDate","_pad","number","digits","zeros","end","String","date","dateFormatRegExp","minutes","sign","getDate","getMonth","getFullYear","getHours","getMinutes","getSeconds","getMilliseconds","getTime","getTimezoneOffset","toISOString","jsdoSettingsProcessor","jsdoSettings","authenticationModel","PROGRESS_JSDO_PCT_MAX_EMPTY_BLOCKS","PROGRESS_JSDO_OP_STRING","PROGRESS_JSDO_ROW_STATE_STRING","_nextid","_uidprefix","Date","now","UID_MAX_VALUE","_getNextId","uid","msg","msgs","jsdoMSG000","jsdoMSG001","jsdoMSG002","jsdoMSG003","jsdoMSG004","jsdoMSG005","jsdoMSG006","jsdoMSG007","jsdoMSG008","jsdoMSG009","jsdoMSG010","jsdoMSG011","jsdoMSG012","jsdoMSG020","jsdoMSG021","jsdoMSG022","jsdoMSG023","jsdoMSG024","jsdoMSG025","jsdoMSG026","jsdoMSG030","jsdoMSG031","jsdoMSG032","jsdoMSG033","jsdoMSG034","jsdoMSG035","jsdoMSG036","jsdoMSG037","jsdoMSG038","jsdoMSG039","jsdoMSG040","jsdoMSG041","jsdoMSG042","jsdoMSG043","jsdoMSG044","jsdoMSG045","jsdoMSG046","jsdoMSG047","jsdoMSG048","jsdoMSG049","jsdoMSG050","jsdoMSG051","jsdoMSG052","jsdoMSG053","jsdoMSG054","jsdoMSG055","jsdoMSG056","jsdoMSG057","jsdoMSG058","jsdoMSG059","jsdoMSG060","jsdoMSG061","jsdoMSG062","jsdoMSG100","jsdoMSG101","jsdoMSG110","jsdoMSG111","jsdoMSG112","jsdoMSG113","jsdoMSG114","jsdoMSG115","jsdoMSG116","jsdoMSG117","jsdoMSG118","jsdoMSG119","jsdoMSG120","jsdoMSG121","jsdoMSG122","jsdoMSG123","jsdoMSG124","jsdoMSG125","jsdoMSG126","jsdoMSG127","jsdoMSG500","jsdoMSG501","jsdoMSG502","jsdoMSG503","jsdoMSG504","jsdoMSG505","jsdoMSG506","jsdoMSG507","jsdoMSG508","jsdoMSG509","jsdoMSG510","jsdoMSG511","jsdoMSG512","jsdoMSG998","getMsgText","n","text","i","RegExp","PluginManager","_plugins","addPlugin","plugin","getPlugin","JSIndexEntry","JSTableRef","jsdo","tableName","_schema","_primaryKeys","_processed","_visited","record","_data","_index","_tmpIndex","_hasEmptyBlocks","_beforeImage","_added","_changed","_deleted","_lastErrors","_convertForServer","_createIndex","block","id","idProperty","_id","_resource","_needCompaction","_compact","newDataArray","_loadBeforeImageData","jsonObject","beforeImageJsonIndex","keyFields","prodsBeforeData","_dataSetName","tmpIndex","record2","recordId","key","tmpKeyIndex","jsrecord","tmpDataIndex","tmpDeletedIndex","j","keys","_findById","_getKey","key2","_remove","copy","_copyRecord","_tableRef","_deleteProdsProperties","JSRecord","tableObject","beforeRecord","prodsErrors","item","_errorString","_clearData","_setRecord","hasData","_nestChildren","_getDataWithNestedChildren","_getRelatedData","getData","params","_getData","numEmptyBlocks","sort","top","sortFields","dir","sortObject","_processSortFields","_getCompareFn","skip","splice","_recToDataObject","includeChildren","array","dataObject","_children","_buffers","_dataProperty","_recFromDataObject","getSchema","setSchema","schema","fieldName","add","_add","create","trackChanges","setWorkingRecord","prefixElement","maxItems","_getDefaultValue","_getArrayField","items","_convertType","useRelationships","_relationship","_parent","childFieldName","parentFieldName","v","autoSort","_sortRecords","_sortFn","_sortObject","_needsAutoSorting","_sort","ret","_compareFields","parentRecord","childBuf","_isNested","k","childRecord","m","_hasNestedChild","_findFirst","ignoreRelationships","childTable","_defaultTableRef","assign","update","remove","bTrackChanges","getId","getErrors","getErrorString","findById","find","foreach","_inforeach","_equalRecord","rec1","rec2","value1","value2","caseSensitive","toUpperCase","keyObject","jsrec1","jsrec2","sortAscending","defineProperty","_autoSort","get","set","enumerable","writeable","_caseSensitive","fields","indexOf","sortOrder","setSortFields","setSortFn","addRecords","addMode","isInvoke","_addRecords","acceptChanges","rejectChanges","_undoCreate","_undoUpdate","_undoDelete","hasChanges","getChanges","rowState","_OP_CREATE","_OP_UPDATE","_OP_DELETE","_clearErrorStrings","_applyChanges","_rejected","acceptRowChanges","found","rejectRowChanges","hasNestedChild","childBufObj","_saveBeforeImageUpdate","_sortRecord","resNameOrParmObj","serviceName","_super","Session","_defineProperty","fnGet","element","ARRAY_INDEX_SEPARATOR","isNaN","_hasSubmitOperation","_hasCUDOperations","_numBuffers","_async","operations","_session","_useSubmit","autoApplyChanges","_localStorage","_fillMergeMode","autoFill","eventName","prop","ServicesManager","getResource","url","dataProperty","buffer","properties","fnName","generic","myservice","getService","service","_pushJSDOs","buf","_properties","primaryKeys","trim","$ref","relations","relationship","childName","parentName","relationFields","defaultValue","t","d","isDate","arrayFieldName","isDataSet","_invokeComplete","async","deferred","_invokeSuccess","_invokeError","_httpRequest","method","reqBody","afterOpenRequest","input","setRequestHeader","send","exception","_checkServiceResponse","onCompleteFn","onSuccessFn","onErrorFn","onreadystatechange","onReadyStateChangeGeneric","useRequest","settings","_openRequest","_getDataObject","oldUseRelationships","_getDataObjectAsNested","bufObj","_unnestData","obj","itemType","elements","split","convertItem","parseFloat","_clearErrors","clearErrorString","_setAllRecordsRejected","param","changes","hasErrors","hasRejected","hasCommittedRecords","_allRecordsRejected","_someRecordsRejected","fill","objParam","mapping","getMethodProperties","mappingType","mergeMode","MODE_APPEND","MODE_EMPTY","MODE_MERGE","MODE_REPLACE","requestMapping","capabilities","_fillSuccess","_fillError","_fillComplete","read","errorObject","_execGenericOperation","_convertRequestData","operationStr","_OP_READ","_OP_SUBMIT","_initConvertForServer","_convertFieldsForServer","_ablTypeNeedsConversion","beforeData","_convertTableData","tableData","_convertRowData","_convertField","resultArray","_convertDate","needsConversion","_undefWorkingRecord","saveChanges","useSubmit","_checkThatJSDOHasRequiredOperations","_syncDataSetForSubmit","_syncDataSetForCUD","_syncSingleTable","checkedDelete","checkedCreate","checkedUpdate","_confirmOperationExists","invoke","_syncTableRef","rowData","requestData","dataSetObject","_useBeforeImage","_createComplete","_createSuccess","_createError","useBeforeImageFormat","beforeObject","beforeRowData","sendOnlyChanges","_updateComplete","_updateSuccess","_updateError","childTableName","_deleteComplete","_deleteSuccess","_deleteError","opType","useBeforeImage","_isBatchComplete","_isBatchSuccess","_updateLastErrors","_fireAfterSaveChanges","fireAfterSaveChanges","addedRecords","complete","completeFn","_saveChangesComplete","successFn","_saveChangesSuccess","errorFn","_saveChangesError","jsrecords","_createChangeSet","_createTTChangeSet","_saveChangesSuccessTT","dataSetName","alwaysCreateTable","changeSetJsonObject","dataSetJsonObject","_hasChanges","_addDeletesToChangeSet","_addCreatesToChangeSet","_addChangesToChangeSet","tempTableJsonObject","_addRowToTTChangeSet","hasOwnProperty","event","_createDataAndChangeSet","_addRecordsToObject","_doesRecordHaveCreateBIData","_addCreatedRowToChangeSet","_doesRecordHaveUpdateBIData","_addChangedRowToChangeSet","changedId","hasUpdates","_addDeletedRowToChangeSet","beforeTableJsonObject","_getTableInBeforeJsonObject","source","target","onlyChangesRecord","newObject","deleteRowState","beforeImageJsonObject","dataHasBeenProcessed","checkBeforeImage","isAfterSame","_sameData","isBeforeSame","_getBeforeRecordFromObject","afterRecord","tablename","record1","_mergeRead","datasetBuffer","srcData","_mergeUpdateRecord","_setErrorString","errorString","setInBeforeTable","_arrayFromDataObject","_mergeUpdateForCUD","hasError","tableJsonObject","prods_id","_getErrorStringFromJsonObject","_checkForDeleteError","beforeJsonObject","_mergeUpdateForSubmit","_fireCUDTriggersForSubmit","errorsJsonObject","response","responseMapping","entry","deleteProdsProps","_checkSaveComplete","records","status","_getErrorsFromRequest","errors","errorArray","retValString","responseObject","responseText","_retVal","RETVAL","_errors","_errorNum","_errorMsg","APP_ERROR","errorNum","ERROR","statusText","errorText","DATA_ERROR","_mergeInvoke","dataParameterName","_tempTableName","xType","readyState","_saveClientContextId","concat","setProperties","propertiesObject","setProperty","propertyName","propertyValue","getProperties","getProperty","saveLocal","dataMode","callee","ALL_DATA","CHANGES_ONLY","_prepareDataObjectForLocalStorage","readLocal","_hasMatchingSchema","_restoreFromLocalStorage","addLocalRecords","_containsPrimaryKeys","storageObject","isValid","deleteLocal","option","_restoreDataForTable","_operations","constructor","radix","sortDir","ablFilter","sqlQuery","methodProperties","position","capabilitiesObject","reqCapabilities","options","doConversion","orderBy","ui","UITableRef","_listview","_detailPage","_listviewContent","addItem","detailForm","clearItems","itemTemplate","UIHelper","_itemTemplate","listviewElement","document","getElementById","innerHTML","_getFormFieldValue","detailPageName","val","_setFormField","display","pageName","showListView","uiTableRef","html","attr","filterable","listview","autoLink","each","bind","getListViewRecord","onSelect","childElementCount","children","onclick","getFormFields","tmpFields","htmltext","charAt","fieldLabel","title","fieldTemplate","_fieldTemplate","htmlIElement","getAttribute","getFormRecord","_getIdOfElement","setDetailPage","setListView","pos","_defaultUITableRef","_uiTableRef","cnt","_defaultItemTemplate","_defaultFieldTemplate","setItemTemplate","template","setFieldTemplate","_services","_resources","_sessions","_jsdosessions","addResource","resource","addService","addSession","catalogURI","session","addJSDOSession","jsdosession","getSession","cleanSession","servicesKey","resourcesKey","sessionsKey","services","resources","sessions","jsdosessions","extractParamsFromURL","urlParams","paramName","c","addCatalog","baseAddress","address","path","primaryKey","tableProperties","RelationName","opname","verb","func","definition","Boolean","encodeURIComponent","reqParam","unwrapped","paramsFromURL","printDebugInfo","resourceName","cSchema","cOperations","MobileServiceObject","_uri","uri","ContextProperties","contextObject","contextString","header","setContextProperty","setContext","context","getContext","getContextProperty","defPropSupported","isUserAgentiOS","isFirefox","isEdge","isIE","canPassCredentialsToOpenWithCORS","defaultiOSBasicAuthTimeout","deviceIsOnline","restApplicationIsOnline","oepingAvailable","defaultPartialPingURI","partialPingURI","_storageKey","_authProvider","customCredentials","storedAuthModel","storedURI","newURI","stateWasReadFromStorage","_silent","warn","navigator","userAgent","canPassCredentialsToOpen","_onlineHandler","setDeviceIsOnline","_offlineHandler","DEVICE_OFFLINE","window","addEventListener","_catalogURIs","_jsdos","onOpenRequest","_password","_userName","_loginTarget","_serviceURI","_loginResult","_loginHttpStatus","_clientContextId","_authenticationModel","AUTH_TYPE_ANON","newval","AUTH_TYPE_FORM","AUTH_TYPE_BASIC","AUTH_TYPE_SSO","storeSessionInfo","_lastSessionXHR","loginResult","LOGIN_SUCCESS","_pingInterval","_timeoutID","_autoping","clearTimeout","_contextProperties","isInvalidated","setAuthProvider","userName","loginTarget","serviceURI","catalogURIs","loginHttpStatus","clientContextId","lastSessionXHR","infoName","retrieveSessionInfo","clearSessionInfo","storeAllSessionInfo","pingInterval","clearAllSessionInfo","setSessionInfoFromStorage","authproviderInitObject","setLoginResult","setUserName","setServiceURI","setLoginHttpStatus","setClientContextID","setRestApplicationIsOnline","setOepingAvailable","setPartialPingURI","newname","sessionObject","setLoginTarget","pushCatalogURIs","pushService","serviceObject","findService","setClientContextIDfromXHR","getResponseHeaderNoError","ccid","setLastSessionXHR","headerName","allHeaders","_pdsResponseHeaders","regExp","getAllResponseHeaders","getResponseHeader","callback","urlPlusCCID","afterOpenAndAuthorize","arg","setRequestHeaderFromContextProps","formPreTest","_isInvalidated","_prependAppURL","_addCCIDtoURL","_useTimeStamp","_addTimeStampToURL","_openRequestAndAuthorize","_setXHRCredentials","_addWithCredentialsAndAccept","pingTestCallback","cbArgs","foundOeping","pingResult","_onReadyStateChangeGeneric","_requestTimeout","onResponseFn","onResponseProcessedFn","GENERAL_FAILURE","pdsession","_disconnect","_processDisconnectResult","_reinitializeAfterLogout","SUCCESS","_disconnectComplete","errObj","pwSave","unameSave","login","loginUserName","loginPassword","uname","pw","isAsync","iOSBasicAuthTimeout","uriForRequest","password","restURLtemp","LOGIN_GENERAL_FAILURE","_setNoCacheHeaders","_isAsync","_afterFormPretestLogin","_processLoginResult","_loginComplete","_iosTimeOutExpired","abort","_jsdosession","isFormPreTest","ASYNC_PENDING","formLoginParams","theSession","doFormLogin","oldXHR","contentType","needAuth","statusFromjson","handleJSONLoginResponse","_gotLoginForm","open","cbparams","_afterFormLogin","_gotLoginFailure","pingTestArgs","pingURI","fireEventIfOfflineChange","onReadyStateFn","_pingtestOnReadyStateChange","_makePingURI","_sendPing","LOGIN_AUTHENTICATION_FAILURE","updateContextPropsFromResponse","logout","_processLogoutResult","_logoutComplete","withCredentials","_anonymousLogoutOK","invalidate","cleanServicesManager","logoutSucceeded","basicStatusOK","arg4","catalogUserName","catalogPassword","catalogIndex","authProvider","addCatalogAfterOpen","_processAddCatalogResult","_addCatalogComplete","_catalogIndex","offlineAddCatalog","_catalogURI","CATALOG_ALREADY_LOADED","_catalogHttpStatus","servicedata","serviceURL","theJSDOSession","toggleOnlineState","_parseCatalog","useXClientProps","xClientProps","_getAuthFailureReason","ping","pingArgs","_onReadyStateChangePing","offlineReason","doNotFireEvent","_processPingResult","_isOnlineStateChange","isOnline","stateChanged","wasOnline","connected","offlineObservers","offline","onlineObservers","online","localPingArgs","pingResponseJSON","appServerStatus","connectedBeforeCallback","assumeOepingFormat","usingOepingFormat","AppServerStatus","SERVER_OFFLINE","WEB_APPLICATION_OFFLINE","PingStatus","APPSERVER_OFFLINE","sendPingAfterOpen","auth","_make_basic_auth","urlPart1","urlPart2","jsessionidStr","catalogdata","oldURL","newURL","pat","test","acceptString","user","tok","hash","loginFormIDString","_findStringInResponseHTML","loginFailureIdentificationString","searchString","status_code","status_txt","contextHeader","hasClientCredentials","SEQ_MAX_VALUE","_tsseq","_tsprefix1","_tsprefix2","_getNextTimeStamp","seq","Math","floor","random","round","timeStamp","AUTHENTICATION_FAILURE","validateSessionSubscribe","_eventNames","_pdsession","JSDOs","settlePromise","fulfill","genericSessionEventHandler","myDeferred","onAfterAddCatalog","settleResult","EXPIRED_TOKEN","_overallCatalogResult","_results","_numCatalogsProcessed","_numCatalogs","_processedPromise","details","onAfterLogout","onPingComplete","username","callIsAuthorized","isAuthorized","then","disconnect","unameOrOpts","opts","numCatalogs","addResult","authProv","cbresult","LOGIN_AUTHENTICATION_REQUIRED","AUTH_TYPE_FORM_SSO","err","validateJSDOSessionSubscribe","authProviderInitObject","sessionRejectHandler","callbackRejectHandler","reason","loginHandler","ex","callLogin","provider","loginCallback","authenticationURI","authProviderAuthenticationModel","invalidateAllSessions","invalidatePromises","exports","initObject","authModel","_checkStringArg","_initialize","_loginURI","_homeLoginURIBase","AuthenticationProviderBasic","AuthenticationProviderForm","AuthenticationProviderSSO","_loginProto","sendParam","_loggedIn","_openLoginRequest","_storeInfo","_settlePromise","_reset","hasRefreshToken","uriParam","targetURIs","tempURI","_dataKeys","loggedIn","_storage","_retrieveLoggedIn","_retrieveInfoItem","propName","_retrieveURI","_clearInfo","argToCheck","argPosition","argName","_springLoginURIBase","make_basic_auth_header","_basic_processLoginResult","userNameParam","passwordParam","BasicProxy","_logoutURI","_springLogoutURIBase","FormProxy","_openLogoutRequest","afterSuper","_automaticTokenRefresh","temp","ssoTokenInfo","tokenDataKeys","token","refreshToken","tokenType","expiration","accessTokenExpiration","storeTokenInfo","access_token","refresh_token","expires_in","token_type","retrieveTokenProperty","retrieveToken","retrieveRefreshToken","retrieveAccessTokenExpiration","retrieveTokenType","getToken","retrieveExpiration","clearTokenInfo","openRefreshRequest","_refreshURI","processRefreshResult","ssoTokenJSON","afterRefreshCheck","automaticTokenRefresh","refresh","_springFormTokenLoginURIBase","_springFormTokenRefreshURIBase","SSOProxy"],"mappings":"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"} \ No newline at end of file From 5fe97bfbdfe986d49e3cedda46a55861054949cc Mon Sep 17 00:00:00 2001 From: edselg Date: Sat, 6 Oct 2018 14:53:34 -0400 Subject: [PATCH 83/84] Add timeout option for npm run test:tc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a037c6..003ac32 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test": "npm run build:jsdo && mocha --recursive", "test:smokes": "npm run build:jsdo && mocha test/smoke*.js", "test:tc-smokes": "npm run build:jsdo && mocha test/smoke*.js --recursive --reporter mocha-teamcity-reporter", - "test:tc": "npm run build:jsdo && mocha --recursive --reporter mocha-teamcity-reporter" + "test:tc": "npm run build:jsdo && mocha --timeout 15000 --recursive --reporter mocha-teamcity-reporter" }, "repository": { "type": "git", From 34629b906ee3846bf763caf5d4f47d95c0e22a11 Mon Sep 17 00:00:00 2001 From: Alan Estrada Date: Mon, 8 Oct 2018 11:02:46 -0400 Subject: [PATCH 84/84] Changed the basic credentials --- test/smoke.jsdosession.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/smoke.jsdosession.js b/test/smoke.jsdosession.js index e06acb6..0c37fdc 100644 --- a/test/smoke.jsdosession.js +++ b/test/smoke.jsdosession.js @@ -38,11 +38,11 @@ describe('JSDOSession Smoke Tests', () => { it('should connect to an existing basic backend', function () { let getSession = progress.data.getSession({ - serviceURI: 'http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/', - catalogURI: 'http://oemobiledemo.progress.com/OEMobileDemoServicesBasic/static/CustomerService.json', + serviceURI: 'http://172.29.18.125:8894/OEMobileDemoServicesBasic', + catalogURI: 'http://172.29.18.125:8894/OEMobileDemoServicesBasic/static/CustomerService.json', authenticationModel: 'basic', - username: 'basicuser', - password: 'basicpassword' + username: 'restuser', + password: 'password' }).then((object) => { object.jsdosession.invalidate(); return object.result;