importPackage(Packages.de.elo.ix.client);
importPackage(Packages.de.elo.ix.jscript);
importPackage(Packages.de.elo.ix.scripting);
//@include lib_Class.js
//@include lib_sol.common.StringUtils.js
//@include lib_sol.common.SordUtils.js
//@include lib_sol.common.Template.js
//@include lib_sol.common.Locale.js
//@include lib_sol.common.HttpUtils.js
//@include lib_sol.common.ix.DynKwlUtils.js
/**
* BLP Query Iterator used by dynamic keyword lists. This class provides an abstract layer that simplifies the usage
* of keywording information.
*
* This iterator has to be used in combination with a BLP query. When used in a GenericDynKwl we're extracting
* the correct BLP values (e.g. queryName, addInId, moduleId, ...) within the DynKWL configuration app.
* When implemented via code you'll need to provide the specific properties yourself.
*
* # Example implementation
*
*
* Implementation of an Index Server data iterator that can be used by keywording forms:
*
* sol.define("sol.examples.ix.dynkwl.Customers", {
* extend: "sol.common.ix.DynKwlBLPIterator",
*
* tableTitle: "Customers of a ERP system",
* tableKeyNames: ["CUSTOMER_NO", "CUSTOMER_NAME", "IX_MAP_CUSTOMER_CATEGORY"],
* serverUrl: "http://10.1.2.10:30009",
* appToken: "HThYifwwAsdfYf400XSaiINismui3kTDOPqan8EoyfM=",
* projectId: "603c98f95675da5172eb84cb",
* queryName: "psql.navcustomers",
* queryModule: "OleDb",
* moduleId: "a7f28149-7202-43f2-b3ec-d225743b06ee",
* addInId: "da414d55-45b5-451a-a03a-9517727ae9c7",
* queryConditions: [
* { name: "IDX1", fieldName: "CUSTOMER_NAME" },
* { name: "IDX2", value: "IMPORTANT CUSTOMERS" }
* ]
* });
*
* function getDataIterator() {
* var iterator;
* iterator = sol.create("sol.examples.ix.dynkwl.Customers", { });
* return new DynamicKeywordDataProvider(iterator);
* }
*
* @author ELO Digital Office GmbH
*
* @eloix
* @requires sol.common.StringUtils
* @requires sol.common.SordUtils
* @requires sol.common.Template
* @requires sol.common.Locale
* @requires sol.common.HttpUtils
* @requires sol.common.ix.DynKwlUtils
*/
sol.define("sol.common.ix.DynKwlBLPIterator", {
mixins: ["sol.common.ix.DynKwlMixin"],
/**
* @cfg {string} serverUrl
* URL of BLP server (e.g. http://<IP Adress>:30009)
*/
serverUrl: undefined,
/**
* @cfg {string} appToken
* App token for BLP connection. Needs to be configured in the BLP designer within the Credential Store
* This is the "Secret Key" within the "Access Keys"
* (e.g. HThYifwwAsdfYf400XSaiINismui3kTDOPqan8EoyfM=)
*/
appToken: undefined,
/**
* @cfg {string} projectId
* Project Id for this BLP query. Can be the project name
*/
projectId: undefined,
/**
* @cfg {string} tableTitle
* name of this table. The title is displayed by the client.
*/
tableTitle: undefined,
/**
* @cfg {string} queryName
* Name of the BLP query to be used in this DynKWL
*/
queryName: undefined,
/**
* @cfg {string} queryModule
* Name of the BLP module (e.g.: "OleDb") to be used in this DynKWL
*/
queryModule: undefined,
/**
* @cfg {string} moduleId
* ID of the BLP module (e.g.: "a7f28149-7202-43f2-b3ec-d225743b06ee for the DataConnect module") to be used in this DynKWL
*/
moduleId: undefined,
/**
* @cfg {string} addInId
* ID of the BLP addIn (e.g.: "da414d55-45b5-451a-a03a-9517727ae9c7") to be used in this DynKWL
*/
addInId: undefined,
/**
* @cfg {Array} queryConditions
*
* [{ "name": "IDX1", "value": "20000", message: 'field x missing' }]
*
* Conditions to be passed to the BLP query
* If no name is provied the current focuesd field is used.
*/
queryConditions: [],
/**
* @cfg {Array} tableKeyNames (required)
* mapping between columns and elo group or map fields. if null, value is not transferred.
*
* // GRP field map static field map table field
* ['RECORD_REFERENCE', null];
*
* Map fields must contain IX_MAP as a prefix and can optionally use {i} as a counter value.
*/
tableKeyNames: undefined,
* @cfg {Array} tableHeaders (required)
* column header names. if null column is hidden in the client.
*
* ["Name", "Description"]
*/
tableHeaders: undefined,
/**
* @property
* @private
* Error message that is passed to the client if value is missing.
*/
errorMessage: "",
initialize: function (config) {
var me = this, queryUrl;
me.log = sol.create("sol.Logger", { scope: this.$className || "sol.common.ix.DynKwlBLPIterator" });
me.log.enter("initialize", config);
config = config || {};
if ((!me.serverUrl && !config.serverUrl)
|| (!me.appToken && !config.appToken)
|| (!me.projectId && !config.projectId)
|| (!me.queryName && !config.queryName)
|| (!me.queryModule && !config.queryModule)
|| (!me.moduleId && !config.moduleId)
|| (!me.addInId && !config.addInId)
|| (!me.tableKeyNames && !config.tableKeyNames)
|| (!me.tableHeaders && !config.tableHeaders)) {
me.log.error("Dynamic keyword list: serverUrl, queryName, queryModule, projectId, moduleId, addInId, tableKeyNames and tableHeaders must be set.");
}
// this is the BLP security token to authenticate with the service
me.serverUrl = config.serverUrl || me.serverUrl;
me.appToken = config.appToken || me.appToken;
me.projectId = config.projectId || me.projectId;
me.queryName = config.queryName || me.queryName;
me.queryModule = config.queryModule || me.queryModule;
me.moduleId = config.moduleId || me.moduleId;
me.addInId = config.addInId || me.addInId;
queryUrl = "{{serverUrl}}/api/v1/project/{{projectId}}/dataquery/{{moduleId}}/{{addInId}}/execute";
tpl = sol.create('sol.common.Template', {
source: queryUrl
});
me.blpQueryUrl = tpl.apply({
serverUrl: me.serverUrl,
projectId: me.projectId,
moduleId: me.moduleId,
addInId: me.addInId
});
me.tableTitle = config.tableTitle || me.tableTitle;
me.queryConditions = config.queryConditions || me.queryConditions;
me.tableKeyNames = config.tableKeyNames || me.tableKeyNames;
me.tableHeaders = config.tableHeaders || me.tableHeaders;
me.focusFieldGivesValueForMap = !!config.focusFieldGivesValueForMap;
me.errorMessage = "";
me.log.exit("initialize");
},
/**
* Opens a connection for the elo java client and non map field capable clients.
*
* @param {de.elo.ix.scripting.ScriptExecContext} ec
* @param {de.elo.ix.client.Sord} sord working version of the current sord object
* @param {String} fieldName name of the currently focused field
*/
open: function (ec, sord, fieldName) {
var me = this;
me.log.enter("open", { sord: sord, fieldName: fieldName });
me._keyNames = me.getTableKeyNames(fieldName);
me.index = 0;
me.resultSet = me.getQueryResults(me.createBLPConditionFields(ec, fieldName, null, null, sord));
me.log.exit("open");
},
/**
* Opens a connection for elo wf forms and map field capable components
*
* @param {de.elo.ix.scripting.ScriptExecContext} ec
* @param {Object} map Map of all entries passed by the client
* @param {String} focusName Name of the currently focused field
*/
openMap: function (ec, map, focusName) {
var me = this, fieldIndex;
me.log.enter("openMap", { focusName: focusName, map: map });
fieldIndex = me.getIndexFromName(focusName);
me._keyNames = me.getTableKeyNames(focusName).map(function (keyName) {
return !!keyName ? ((fieldIndex != "") ? keyName.replace("{i}", fieldIndex) : keyName) : null;
});
me.index = 0;
me.resultSet = me.getQueryResults(me.createBLPConditionFields(ec, focusName, fieldIndex, map, null));
me.log.exit("openMap");
},
/**
* Closes the connection for both map and non map capable clients.
*/
close: function () {
this.log.enter("close");
this._findInfo = null;
this.log.exit("close");
},
/**
* Returns the next row of the table.
*
* @return {String[]} Table row
*/
getNextRow: function () {
var row = this.resultSet[this.index++];
if (row) {
row = this.getRowData(row);
this.formatRow(row);
return row;
}
},
/**
* Within BLP we're basically just passing our result row to our DynKwl.
* You may overwrite this function for some fancy row preparation
* @param {String[]} row
* @return {String[]} Table row
*/
getRowData: function (row) {
return row;
},
* Returns the header of this table that can be displayed by the clients.
*
* @return {String[]} Table header
*/
getHeader: function () {
return this.tableHeaders;
},
/**
* Returns the keys of this table that can be used in order to map
* map or group fields with columns.
*
* @return {String[]} Table keys
*/
getKeyNames: function () {
return this._keyNames;
},
/**
* Returns true if table has more rows.
*
* @return {Boolean} Has more rows
*/
hasMoreRows: function () {
return (this.index < (this.resultSet.length));
},
/**
* Returns the error message that should be displayed by the client
* instead of the table data.
*
* @return {String} error message
*/
getMessage: function () {
return this.errorMessage;
},
/**
* Returns a title for this table used by the user interface.
*
* @return {String} Title
*/
getTitle: function () {
return this.tableTitle;
},
/**
* @private
* Retrieves a list of results from a BLP query.
* @return {de.elo.ix.client.Sord[]}
*/
getQueryResults: function (queryConditions) {
var me = this, responseObj, dataObj, results, des, decryptedAppToken;
me.log.enter("getSearchResults", this._findInfo);
dataObj = {
name: me.queryName,
module: me.queryModule
};
if (queryConditions.length > 0) {
dataObj.condition_fields = queryConditions;
}
des = new Packages.de.elo.utils.sec.DesEncryption();
decryptedAppToken = des.decrypt(me.appToken);
requestProperties = {
Authorization: "Bearer " + decryptedAppToken
};
responseObj = sol.common.HttpUtils.sendRequest({
url: me.blpQueryUrl,
method: "post",
connectTimeout: 10000,
readTimeout: 60000,
dataObj: dataObj,
encodeData: false,
requestProperties: requestProperties
});
results = JSON.parse(responseObj.content);
if (!results.result || !results.result.rows) {
throw new Exception("No BLP Query results returned. Content: " + responseObj.content);
}
me.log.exit("getQueryResults");
return results.result.rows;
},
/**
* Internal function that utilizes the creation of condition_fields passed to the BLP query.
*
* @param {de.elo.ix.scripting.ScriptExecContext} ec IX ScriptExecContext
* @param {String} focusField Currently focused field
* @param {String} fieldIndex
* @param {Object} map Map of all entries passed by the client
* @param {de.elo.ix.client.Sord} sord working version of the current sord object
* @returns {String[]} Values for prepared statement
*/
createBLPConditionFields: function (ec, focusField, fieldIndex, map, sord) {
var me = this, queryConditions = [],
i, param, fieldName, value, mapValueField;
me.log.enter("createBLPConditionFields", { focusField: focusField, fieldIndex: fieldIndex, map: map, sord: sord });
me.errorMessage = "";
for (i = 0; i < me.queryConditions.length; i++) {
param = me.queryConditions[i];
if (!param.value) {
fieldName = param.fieldName || focusField;
if (param.valueType) {
switch (param.valueType) {
case "LANGUAGE":
value = ec.ci.language;
break;
default:
value = "";
}
} else if (map) {
// WF currently passes IX_GRP for group fields.
// This must be fixed so SQL-Queries can be used in mixed mode.
mapValueField = this.focusFieldGivesValueForMap ? focusField : fieldName;
if (fieldIndex) {
mapValueField = String(mapValueField).replace("{i}", fieldIndex);
}
param.value = (map[mapValueField] || map["IX_GRP_" + mapValueField]) || "";
} else {
param.value = sol.common.SordUtils.getObjKeyValue(sord, fieldName) || "";
}
}
if (!param.value && param.message) {
me.errorMessage = param.message;
}
if (param.value || ((!param.value || param.value == "") && param.emptyAllowed === true)) {
queryConditions.push(param);
}
}
me.log.exit("createBLPConditionFields");
return queryConditions;
},
getIndexFromName: function (name) {
name = String(name);
if (!name) {
return "";
}
var pos = name.search(/\d+$/);
if (pos > 0) {
return name.substring(pos);
}
return "";
}
});