importPackage(Packages.de.elo.ix.client);
//@include lib_Class.js
//@include lib_sol.common.Cache.js
//@include lib_sol.common.StringUtils.js
//@include lib_sol.common.AclUtils.js
//@include lib_sol.common.JsonUtils.js
//@include lib_sol.common.ObjectFormatter.js
/**
* Local definition of the class `sol.common.Cache` for backward compatibility of previous solution packages.
*/
if (!sol.ClassManager.getClass("sol.common.Cache")) {
sol.define("sol.common.Cache", {
initialize: function (config) {
var me = this;
me.cache = new java.util.concurrent.ConcurrentHashMap(8, 0.9, 1);
},
/**
* Inserts the specified key-value pair into the cache.
* @param {String} key
* @param {Object} value
* @return {Object} The previous value associated with the key, or null if there was no mapping before
*/
put: function (key, value) {
var me = this;
return me.cache.put(key, value);
},
/**
* Inserts all key-value pairs specified by an object into the cache. Existing mappings will be replaced.
* @param {Object} data Property names will be used as keys and the associated values as values.
*/
putAll: function (data) {
var me = this;
me.cache.putAll(data);
},
/**
* Tests if the specified object is a key in the cache.
* @param {String} key
* @return {Boolean}
*/
containsKey: function (key) {
var me = this;
return me.cache.containsKey(key);
},
/**
* Returns the value for the specified key from the cache, or null if the chache contains no mapping for the key.
* @param {String} key
* @return {Object}
*/
get: function (key) {
var me = this;
return me.cache.get(key);
},
/**
* Returns an enumeration of all keys in the cache.
* @return {Object} An `java.util.Enumeration` of all keys
*/
keys: function () {
var me = this;
return me.cache.keys();
},
/**
* Returns a collection view of the values contained in the cache.
* @return {Object} An `java.util.Collection` of all values
*/
values: function () {
var me = this;
return me.cache.values();
},
/**
* Returns an enumeration of the values in the cache.
* @return {Object} An `java.util.Enumeration` of all values
*/
elements: function () {
var me = this;
return me.cache.elements();
},
/**
* Removes the key (and its corresponding value) from the cache.
* @param {String} key
* @return {Object} The previous value associated with the key, or null if there was no value for the key
*/
remove: function (key) {
var me = this;
return me.cache.remove(key);
},
/**
* Returns the number of key-value pairs in the cache.
* @return {Number}
*/
size: function () {
var me = this;
return me.cache.size();
},
/**
* Returns `true` if the chache contains no key-value pairs.
* @return {Boolean}
*/
isEmpty: function () {
var me = this;
return me.cache.isEmpty();
},
/**
* Removes all of the mappings from the cache.
*/
clear: function () {
var me = this;
me.cache.clear();
}
});
}
/**
* This class contains convenience methods for working with Sord objects in server scripts.
*
* @author PZ, ELO Digital Office GmbH
* @version 1.03.000
*
* @eloix
* @eloas
* @elojc
*
* @requires sol.common.Cache
* @requires sol.common.StringUtils
* @requires sol.common.ObjectFormatter
*/
sol.define("sol.common.SordUtils", {
singleton: true,
requires: ["sol.common.Cache"],
pilcrow: "\u00b6",
/**
* @private
* @property {sol.common.Cache} docMaskCache Cache for `de.elo.ix.client.DocMask`
*/
initialize: function (config) {
var me = this;
me.$super("sol.Base", "initialize", [config]);
me.docMaskCache = sol.create("sol.common.Cache");
},
/**
* Checks, if an object is a de.elo.ix.client.Sord
* @param {Object} sord
* @return {Boolean}
*/
isSord: function (sord) {
return (sord instanceof Sord);
},
/**
* Checks, if the index data (objKeys) is loaded
* @param {de.elo.ix.client.Sord} sord
* @return {Boolean}
*/
isIndexdataLoaded: function (sord) {
return sord && sord.objKeys && (sord.objKeys.length > 0);
},
/**
* Checks, if a de.elo.ix.client.Sord is from type folder
* @param {de.elo.ix.client.Sord} sord
* @return {Boolean}
*/
isFolder: function (sord) {
return (sord.type < SordC.LBT_DOCUMENT);
},
/**
* Checks, if a de.elo.ix.client.Sord is a dynamic folder.
* @param {de.elo.ix.client.Sord} sord
* @return {Boolean}
*/
isDynamicFolder: function (sord) {
var me = this,
desc;
if (!me.isFolder(sord)) {
return false;
}
desc = sord.desc;
return !sol.common.StringUtils.isBlank(desc) && (desc.matches("^![\+|\?|!].*"));
},
/**
* Checks, if a de.elo.ix.client.Sord is from type document
* @param {de.elo.ix.client.Sord} sord
* @return {Boolean}
*/
isDocument: function (sord) {
return (sord.type >= SordC.LBT_DOCUMENT) && (sord.type <= SordC.LBT_DOCUMENT_MAX);
},
/**
* Updates all of Sord attributes and ObjKeys.
* Map Keys are not updated immediately, instead the function returns an Array with KeyValues, which can be checked in later.
* @param {de.elo.ix.client.Sord} sord
* @param {Object[]} data
*
* {
* key: "name",
* type: "GRP", // SORD|GRP|MAP
* value: "hallo welt"
* }
*
* @param {Object} params Parameters
* @param {Boolean} params.silent Silent
* @returns {de.elo.ix.client.KeyValue[]}
*/
updateSord: function (sord, data, params) {
var me = this,
mapEntries, result, dataString, paramsString;
params = params || {};
me.logger.enter("updateSord");
if (me.logger.debugEnabled) {
dataString = sol.common.JsonUtils.stringifyAll(data);
paramsString = sol.common.JsonUtils.stringifyAll(params);
me.logger.debug(["updateSord: data={0}, params={1}", dataString, paramsString]);
}
mapEntries = [];
if (!me.isSord(sord) || !data) {
me.logger.exit("updateSord");
return;
}
if (!Array.isArray(data)) {
throw "data has to be an Array";
}
data.forEach(function (entry) {
if (!entry || !entry.type || !entry.key || entry.value === undefined || entry.value === null) {
throw "illegal object: " + JSON.stringify(data);
}
switch (entry.type) {
case "SORD":
sord[entry.key] = entry.value;
break;
case "GRP":
me.setObjKeyValue(sord, entry.key, entry.value, params);
break;
case "MAP":
mapEntries.push(new KeyValue(entry.key, entry.value));
break;
default:
throw "unsupported type: " + entry.type;
}
});
result = (mapEntries.length > 0) ? mapEntries : null;
me.logger.exit("updateSord", "mapEntries.length=" + mapEntries.length);
return result;
},
/**
* Updates a bunch of index data at once.
* @param {de.elo.ix.client.Sord} sord
* @param {Object} indexData Key-value-pairs with key=field and value=new value
*/
updateKeywording: function (sord, indexData) {
var me = this,
property;
me.logger.enter("updateKeywording", arguments);
for (property in indexData) {
if (indexData.hasOwnProperty(property)) {
this.setObjKeyValue(sord, property, indexData[property]);
}
}
me.logger.exit("updateKeywording");
},
/**
* Checks if an ObjKey exists
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName
* @returns {Boolean}
*/
objKeyExists: function (sord, keyName) {
return this.getObjKey(sord, keyName) !== null;
},
/**
* Retrieves values from a Sord.
* This could be a Sord property, an objKey, a map field or a form blob field.
*
* This can retrieve lists from `ObjKeys` and multiple map values.
*
* {
* key: "FIELD_NAME",
* type: "GRP", // SORD|GRP|MAP
* }
*
* {
* key: "INDEXED_MAP_FIELD*",
* type: "MAP", // SORD|GRP|MAP
* }
*
* @param {de.elo.ix.client.Sord} sord
* @param {Object} params Parameter
* @param {String} params.key Key
* @param {String} params.type Type
* @param {Number} params.maxLength Max length
* @param {Number} params.fillString Fill string, e.g. `00000000000000`
* @return {String[]} Can be null
*/
getValues: function (sord, params) {
var me = this,
values = null,
tmpValues, i, fieldDefString, value;
if (!sord) {
throw "Sord is empty";
}
if (!params || !params.type || !(params.key || params.value)) {
fieldDefString = JSON.stringify(params);
throw "Field definition is incomplete: fieldDef=" + fieldDefString;
}
switch (params.type) {
case "SORD":
if (sord[params.key]) {
values = [String(sord[params.key])];
}
break;
case "GRP":
tmpValues = me.getObjKeyValues(sord, params.key);
if (tmpValues && (tmpValues.length > 0)) {
values = tmpValues;
}
break;
case "MAP":
tmpValues = ixConnect.ix().checkoutMap(MapDomainC.DOMAIN_SORD, sord.id, [params.key], LockC.NO).items;
if (tmpValues && (tmpValues.length > 0)) {
values = [];
for (i = 0; i < tmpValues.length; i++) {
values.push(String(tmpValues[i].value));
}
}
break;
case "SORDBLOB":
value = me.getStringMapBlob({ mapDomain: MapDomainC.DOMAIN_SORD, mapId: sord.id, key: params.key });
if (value) {
values = [value];
}
break;
case "FORMBLOB":
value = me.getStringMapBlob({ mapDomain: "FORMDATA", mapId: sord.id, key: params.key });
if (value) {
values = [value];
}
break;
case "CONST":
if (params.value) {
values = [String(params.value)];
}
break;
default:
throw "unsupported type: " + params.type;
}
if (values && (values.length > 0)) {
if (params.maxLength) {
for (i = 0; i < values.length; i++) {
value = values[i] + "";
value = (value.length > params.maxLength) ? value.substr(0, params.maxLength) : value;
values[i] = value;
}
}
if (params.fillString) {
for (i = 0; i < values.length; i++) {
value = values[i] + "";
if (value.length < params.fillString.length) {
value += params.fillString.substr(value.length);
}
values[i] = value;
}
}
}
return values;
},
/**
* Returns an object map blob
* @param {Object} params Parameters
* @param {String} [params.mapDomain=MapDomainC.DOMAIN_SORD] Map domain
* @param {String} params.mapId Map ID
* @param {String} params.key Map key
* @return {Object}
*/
getObjectMapBlob: function (params) {
var me = this,
obj, str;
params = params || {};
str = me.getStringMapBlob(params);
obj = JSON.parse(str);
return obj;
},
/**
* Returns a string map blob
* @param {Object} params Parameters
* @param {String} [params.mapDomain=MapDomainC.DOMAIN_SORD] Map domain
* @param {String} params.mapId Map ID
* @param {String} params.key Map key
*/
getStringMapBlob: function (params) {
var me = this,
mapEntries, mapEntry, dataString;
params = params || {};
if (!params.mapId) {
throw "Map ID is missing";
}
if (!params.key) {
throw "Key is missing";
}
params.mapDomain = params.mapDomain || MapDomainC.DOMAIN_SORD;
mapEntries = ixConnect.ix().checkoutMap(params.mapDomain, params.mapId, [params.key], LockC.NO).items;
if (!mapEntries || (mapEntries.length == 0)) {
return;
}
mapEntry = mapEntries[0];
dataString = me.getBlobDataFromMapEntry(mapEntry);
return dataString;
},
/**
* Sets an object map blob
* @param {Object} params Parameters
* @param {String} params.mapId Map ID
* @param {String} params.key Key
* @param {Object} params.value Value
* @param {String} [params.mapDomain=MapDomainC.DOMAIN_SORD] Map domain
* @param {String} params.objId Object ID
*/
setObjectMapBlob: function (params) {
var me = this;
params = params || {};
params.value = JSON.stringify(params.value, 2);
me.setStringMapBlob(params);
},
/**
* Sets a string map blob
* @param {Object} params Parameters
* @param {String} params.mapId Map ID
* @param {String} params.key Key
* @param {String} params.value Value
* @param {String} [params.mapDomain=MapDomainC.DOMAIN_SORD] Map domain
* @param {String} params.objId Object ID
*/
setStringMapBlob: function (params) {
var me = this,
stringMapBlob;
params = params || {};
if (!params.mapId) {
throw "Map ID is missing";
}
if (!params.key) {
throw "Map key is missing";
}
params.mapDomain = params.mapDomain || MapDomainC.DOMAIN_SORD;
stringMapBlob = me.createStringMapBlob(params.key, params.value);
if (!params.objId && (params.mapDomain == MapDomainC.DOMAIN_SORD)) {
params.objId = params.mapId;
}
if (!params.objId) {
throw "Object ID is empty";
}
ixConnect.ix().checkinMap(params.mapDomain, params.mapId, params.objId, [stringMapBlob], LockC.NO);
},
/**
* Creates a string map blob
* @param {String} key Key
* @param {String} value Value
* @return {de.elo.ix.client.MapValue} Map blob
*/
createStringMapBlob: function (key, value) {
var str, bytes, fileData, stringMapBlob;
if (!key) {
throw "Key is empty";
}
value = value || "";
str = new java.lang.String(value);
bytes = str.getBytes("UTF-8");
fileData = new FileData("text/plain", bytes);
stringMapBlob = new MapValue(key, fileData);
return stringMapBlob;
},
/**
* Retrieves a value from a Sord.
* This could be a Sord property, an objKey or a map field.
*
* If there are more than one value, first value will be returned.
*
* Uses {@link #getValues}.
*
* @param {de.elo.ix.client.Sord} sord
* @param {Object} params Parameter
* @param {String} params.key Key
* @param {String} params.type Type
* @param {Number} params.fillString Fill string, e.g. `00000000000000`
* @param {Number} params.maxLength Max length
*
* {
* key: "name",
* type: "GRP", // SORD|GRP|MAP|FORMBLOB
* }
*
* @return {String}
*/
getValue: function (sord, params) {
var me = this,
value = null,
values;
values = me.getValues(sord, params);
if (values && (values.length > 0)) {
value = values[0];
}
return value;
},
/**
* Returns the ObjKey for a field
* @param {de.elo.ix.client.Sord} sord
* @param {string} keyName Name of the index field
* @return {de.elo.ix.client.ObjKey} The ObjKey, or null if none was found
*/
getObjKey: function (sord, keyName) {
var keys, key, i;
if (this.isSord(sord) && this.isIndexdataLoaded(sord) && keyName) {
keys = sord.objKeys;
for (i = 0; i < keys.length; i++) {
key = keys[i];
if (key.name == keyName) {
return key;
}
}
}
return null;
},
/**
* Returns the value of an ObjKey for a field
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @return {String} The field value
*/
getObjKeyValue: function (sord, keyName) {
var values = this.getObjKeyValues(sord, keyName);
if (values) {
return values[0];
}
return null;
},
/**
* Returns the value of an ObjKey for a field as number.
* The method takes care of wrong decimal separators.
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @param {Object} params Parameters
* @param {Boolean} [params.throwException=false] Throw exception
* @return {Number} The field value as number
*/
getObjKeyValueAsNumber: function (sord, keyName, params) {
var me = this,
rawValue, validNumberFormat, message, stringValue, number;
params = params || {};
rawValue = me.getObjKeyValue(sord, keyName);
if (rawValue == null) {
me.logger.debug(["getObjKeyValueAsNumber: No values exist: sord.id={0}, sord.name={1}, keyName={2}", sord.id, sord.name, keyName]);
return null;
}
rawValue += "";
validNumberFormat = me.isValidNumberFormat(rawValue);
if (!validNumberFormat) {
message = me.logger.format(["getObjKeyValueAsNumber: Invalid number format: sord.id={0}, sord.name={1}, keyName={2}, rawValue={3}", sord.id, sord.name, keyName, rawValue]);
if (params.throwException) {
throw message;
} else {
me.logger.warn(message);
}
}
stringValue = rawValue.replace(",", ".");
number = parseFloat(stringValue);
me.logger.debug(["getObjKeyValueAsNumber: sord.id={0}, sord.name={1}, keyName={2}, rawValue={3}, number={5}", sord.id, sord.name, keyName, rawValue, stringValue, number]);
return number;
},
/**
* Checks wether the numberString is a valid number
* @param {String} numberString Number string
* @return {Boolean} True if the string contains a valid number
*/
isValidNumberFormat: function (numberString) {
var valid;
numberString = (numberString || "") + "";
valid = /^-*\d*[.,]{0,1}\d*$/.test(numberString);
return valid;
},
/**
* Sets the value of an ObjKey for a field as number.
* The method takes care of the decimal separator.
*
* Be carefull if using not the users IX connection to checkin the sord after using this method.
* This could cause problems with the separator. Use additional `params.language` parameter where language is the ISO country code of the connection used to checkin the sord afterwards.
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @param {String} value Value
* @param {Object} params (optional)
* @param {String} params.language (optional) ISO language code to determine the decimal separator
* @param {Boolean} [params.throwException=false] Throw exception
* @param {de.elo.ix.client.IXConnection} params.conn IX connection
*/
setObjKeyValueAsNumber: function (sord, keyName, value, params) {
var me = this,
validNumberFormat, stringValue, message, normalizedValue;
params = params || {};
stringValue = value + "";
validNumberFormat = me.isValidNumberFormat(stringValue);
if (!validNumberFormat) {
message = me.logger.format(["setObjKeyValueAsNumber: Invalid number format: sord.id={0}, sord.name={1}, keyName={2}, value={3}, params={4}", sord.id, sord.name, keyName, value, JSON.stringify(params)]);
if (params.throwException) {
throw message;
} else {
me.logger.warn(message);
}
}
normalizedValue = me.normalizeNumber(value, params.lang, params.conn);
me.logger.debug(["setObjKeyValueAsNumber: sord.id={0}, sord.name={1}, keyName={2}, stringValue={3}, normalizedValue={4}", sord.id, sord.name, keyName, stringValue, normalizedValue]);
me.setObjKeyValue(sord, keyName, normalizedValue);
},
/**
* Increments the value of an ObjKey
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @return {Number} The field value as number
*/
incObjKeyValue: function (sord, keyName) {
var me = this,
value;
value = me.getObjKeyValueAsNumber(sord, keyName);
value++;
me.setObjKeyValueAsNumber(sord, keyName, value);
return value;
},
/**
* Decrements the value of an ObjKey
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @return {Number} The field value as number
*/
decObjKeyValue: function (sord, keyName) {
var me = this,
value;
value = me.getObjKeyValueAsNumber(sord, keyName);
value--;
if (value == 0) {
me.setObjKeyValue(sord, keyName, value);
} else {
me.setObjKeyValueAsNumber(sord, keyName, value);
}
return value;
},
/**
* Adjusts the decimal separator of a number
* @param {String} value Value
* @param {String} language ISO country code to determine the decimal separator
* @param {de.elo.ix.client.IXConnection} conn IX connection
* @return {String} normalized Number
*/
normalizeNumber: function (value, language, conn) {
var me = this,
stringValue, groups, decimalSeparator, normalizedValue;
stringValue = (value || "") + "";
stringValue = stringValue.trim();
groups = stringValue.match(/(^-?\d+)[\.|,](\d+$)/);
decimalSeparator = (language) ? me.getDecimalSeparatorForLanguage(language) : me.getDecimalSeparatorForIx(conn);
if (groups && (groups.length == 3)) {
normalizedValue = groups[1] + decimalSeparator + groups[2];
} else {
normalizedValue = stringValue;
}
me.logger.debug(["normalizeNumber: value={0}, normalizedValue={1}", stringValue, normalizedValue]);
return normalizedValue;
},
/**
* Returns the decimal separator for the ELO index server
* @param {de.elo.ix.client.IXConnection} conn IX connection
* @returns {String}
*/
getDecimalSeparatorForIx: function (conn) {
var me = this,
language, country, decimalSeparator, connectionUserName;
conn = conn || ixConnect;
language = conn.loginResult.clientInfo.language;
country = conn.loginResult.clientInfo.country;
decimalSeparator = me.getDecimalSeparatorForLanguage(language, country);
connectionUserName = conn.loginResult.user.name;
me.logger.debug(["getDecimalSeparatorForIX: connectionUserName={0}, language={1}, country={2}, decimalSeparator={3}", connectionUserName, language || "", country || "", decimalSeparator]);
return decimalSeparator;
},
/**
* Returns the decimal separator for a language
* @param {String} language ISO language code to determine the decimal separator
* @param {String} country ISO country code to determine the decimal separator
* @returns {String}
*/
getDecimalSeparatorForLanguage: function (language, country) {
var decimalSeparatorChar, decimalSeparator;
decimalSeparatorChar = new java.text.DecimalFormatSymbols(new java.util.Locale(language, country)).decimalSeparator;
decimalSeparator = String(java.lang.Character.toString(decimalSeparatorChar));
return decimalSeparator;
},
/**
* Returns the values of an ObjKey for a field as array
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @return {String[]} The field values
*/
getObjKeyValues: function (sord, keyName) {
var me = this,
key, values, i, value;
key = me.getObjKey(sord, keyName);
if (key && key.data) {
for (i = 0; i < key.data.length; i++) {
value = key.data[i];
if (typeof value != "undefined") {
values = values || [];
values.push(String(value));
}
}
}
return values;
},
/**
*
* Sets the value of an ObjKey for a field
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @param {String|String[]} value could be a multi index string (e.g. a¶b¶c). In this case the value will convert to an array before each item is set
* @param {Object} params Parameters
* @param {Boolean} params.silent Silent
* @return {de.elo.ix.client.ObjKey} The changed ObjKey
*/
setObjKeyValue: function (sord, keyName, value, params) {
var me = this;
if (!Array.isArray(value)) {
value = (value == undefined)
? [""]
: String(value)
.split(me.pilcrow)
.filter(function (el) {
return el.trim();
});
}
return this.setObjKeyValues(sord, keyName, value, params);
},
/**
* Sets the values of an ObjKey for a field
* @param {de.elo.ix.client.Sord} sord
* @param {String} keyName Name of the index field
* @param {String[]} values
* @param {Object} params Parameters
* @param {Boolean} params.silent Silent
* @return {de.elo.ix.client.ObjKey} The changed ObjKey
*/
setObjKeyValues: function (sord, keyName, values, params) {
var me = this,
newObjKey, objKeys, line, key, i, value;
params = params || {};
if (!sord) {
throw "Sord is missing";
}
if (!keyName) {
throw "Object key name is empty";
}
values = values || [""];
if (params.fillString) {
for (i = 0; i < values.length; i++) {
value = values[i] + "";
if (value.length < params.fillString.length) {
value += params.fillString.substr(value.length);
}
values[i] = value;
}
}
key = this.getObjKey(sord, keyName);
if (key) {
key.data = values;
} else {
// in some cases objKey array doesn't match mask definition.
line = me.getDocMaskLine(sord.mask, keyName) || me.getHiddenLine(keyName);
if (line) {
me.logger.debug("ObjKey '" + keyName + "' does not exist. Adding ObjKey to list.");
newObjKey = new ObjKey();
newObjKey.id = line.id;
newObjKey.name = keyName;
newObjKey.data = values;
objKeys = Array.prototype.slice.call(sord.objKeys);
objKeys.push(newObjKey);
sord.objKeys = objKeys;
key = newObjKey;
} else {
if (!params.silent) {
throw "ObjKey '" + keyName + "' not found.";
}
return;
}
}
return key;
},
/**
* Retrieves (and caches) the definition of document masks by their name
* @param {String} name
* @param {String} language
* @returns {de.elo.ix.client.DocMask} mask
*/
getDocMask: function (name, language) {
var me = this,
languageCache, _result;
me.logger.enter("getDocMask", { name: name, language: language });
if (!name && (name !== 0)) { // Issue BS-799: second check is for the special case if some of our scripts call this function with an integer (which can be zero)
throw "Document mask name is empty";
}
language = language || ixConnect.loginResult.clientInfo.language;
if (!me.docMaskCache.containsKey(language)) {
me.docMaskCache.put(language, sol.create("sol.common.Cache"));
}
languageCache = me.docMaskCache.get(language);
if (!languageCache.containsKey(name)) {
languageCache.put(name, ixConnect.ix().checkoutDocMask(name + "", DocMaskC.mbAll, LockC.NO));
}
_result = languageCache.get(name);
me.logger.exit("getDocMask", _result + "");
return _result;
},
/**
* Reads document mask names
* @param {Object} params Parameters
* @param {Object} params.allMasks if true, return all docmasks
* @param {Object} params.filters Filters
* @param {String} params.filters.nameTranslationKeyPrefix Name translation key prefix filter
* @return {de.elo.ix.client.MaskName[]}
*/
getDocMaskNames: function (params) {
var maskNames = [],
editInfoZ, editInfo, i, maskName;
params = params || {};
editInfoZ = new EditInfoZ(EditInfoC.mbMaskNames, new SordZ());
editInfo = ixConnect.ix().createSord(params.allMasks === true ? null : "1", "", editInfoZ);
for (i = 0; i < editInfo.maskNames.length; i++) {
maskName = editInfo.maskNames[i];
if (params.filters) {
if (params.filters.nameTranslationKeyPrefix) {
if (String(maskName.nameTranslationKey).indexOf(params.filters.nameTranslationKeyPrefix) == 0) {
maskNames.push(maskName);
}
}
} else {
maskNames.push(maskName);
}
}
return maskNames;
},
/**
* Returns the GUID of a doc mask
* @param {String} name Doc mask name
* @returns {String} GUID
*/
getDocMaskGuid: function (name) {
var me = this,
docMask;
docMask = me.getDocMask(name);
return docMask ? String(docMask.guid) : "";
},
/**
* Checks, if a sord has the specified mask
* @param {de.elo.ix.client.Sord} sord
* @param {String} maskName The original mask name
* @return {Boolean}
*/
hasDocMask: function (sord, maskName) {
var me = this,
docMask;
if (!me.isSord(sord) || !maskName) {
return false;
}
docMask = me.getDocMask(maskName);
return sord && (sord.mask === docMask.id);
},
/**
* Gets the field information of a specific mask field
* @param {String} maskName Name of the mask
* @param {String} fieldName Name of the field
* @return {de.elo.ix.client.DocMaskLine}
*/
getDocMaskLine: function (maskName, fieldName) {
var me = this,
docMask, i, line;
docMask = me.getDocMask(maskName);
for (i = 0; i < docMask.lines.length; i++) {
line = docMask.lines[i];
if (line.key == fieldName) {
return line;
}
}
},
/**
* @private
* Returns an hidden line object
* @param {String} keyName Key name
* @return {Objekt} line Line
* @return {String} line.id Line ID
* @return {String} line.name Key name
*/
getHiddenLine: function (keyName) {
var me = this,
hiddenLine;
if (!me.hiddenLines) {
me.hiddenLines = {};
me.hiddenLines[DocMaskLineC.NAME_FILENAME + ""] = { id: DocMaskLineC.ID_FILENAME + "", name: DocMaskLineC.NAME_FILENAME };
me.hiddenLineExists("NAME_LINK") && (me.hiddenLines[DocMaskLineC.NAME_LINK + ""] = { id: DocMaskLineC.ID_LINK + "", name: DocMaskLineC.NAME_LINK });
me.hiddenLineExists("NAME_MAINSCALE") && (me.hiddenLines[DocMaskLineC.NAME_MAINSCALE + ""] = { id: DocMaskLineC.ID_MAINSCALE + "", name: DocMaskLineC.NAME_MAINSCALE });
me.hiddenLineExists("NAME_PERSONALDATA_DELETEAT") && (me.hiddenLines[DocMaskLineC.NAME_PERSONALDATA_DELETEAT + ""] = { id: DocMaskLineC.ID_PERSONALDATA_DELETEAT + "", name: DocMaskLineC.NAME_PERSONALDATA_DELETEAT });
me.hiddenLineExists("NAME_PERSONALDATA_UID") && (me.hiddenLines[DocMaskLineC.NAME_PERSONALDATA_UID + ""] = { id: DocMaskLineC.ID_PERSONALDATA_UID + "", name: DocMaskLineC.NAME_PERSONALDATA_UID });
}
hiddenLine = me.hiddenLines[keyName];
return hiddenLine;
},
/**
* Checks if a hidden line exists
* @param {String} constantName Constant name
*/
hiddenLineExists: function (constantName) {
var docMaskLineC, docMaskLineCClass, fields, i, field;
docMaskLineC = new DocMaskLineC();
docMaskLineCClass = docMaskLineC.getClass();
fields = docMaskLineCClass.getDeclaredFields();
for (i = 0; i < fields.length; i++) {
field = fields[i];
if (field.name == constantName) {
return true;
}
}
return false;
},
/**
* Checks wether a mask exists
* @param {String} maskName
* @return {Boolean}
*/
docMaskExists: function (maskName) {
if (!maskName) {
throw "Mask name is empty";
}
try {
ixConnect.ix().checkoutDocMask(maskName + "", DocMaskC.mbAll, LockC.NO);
return true;
} catch (ex) {
return false;
}
},
/**
* Retrieves values from a dynamic keyword list.
*
* Returns the values from the KWL associated with the REMINDER_PERIOD_UNIT field
*
* sol.common.SordUtils.getDynamicKeywordlistValue("Contract", "REMINDER_PERIOD_UNIT");
*
* Returns the values from the KWL associated with the REMINDER_PERIOD_UNIT field and containing the string 'month'
*
* sol.common.SordUtils.getDynamicKeywordlistValue("Contract", "REMINDER_PERIOD_UNIT", { data: "month" });
*
* Returns the values from the KWL associated with the REMINDER_PERIOD_UNIT field and the data from column 2
*
* sol.common.SordUtils.getDynamicKeywordlistValue("Contract", "REMINDER_PERIOD_UNIT", { returnColumn: 2 });
*
* Returns the values from the KWL associated with the REMINDER_PERIOD_UNIT field and the data from column 2 filtering only thoase containing 'M' in column 1
*
* sol.common.SordUtils.getDynamicKeywordlistValue("Contract", "REMINDER_PERIOD_UNIT", { data: "M", filterColumn: 0, returnColumn: 2 });
*
* @param {String} maskName The mask name used to determine the dynamic keyword list
* @param {String} key The field which has the dynamic keyword list
* @param {Object} params (optional)
* @param {String} params.data (optional) lookup data (used to filter the result on the serverside, if supported by the KWL, or on clientside, if `returnColumn` and `filterColumn` are defined)
* @param {Number} params.returnColumn (optional) If set, the content of this column will be returned
* @param {Number} params.filterColumn (optional) If set (in addition to a return column), the result will be filtered on the clientside on the KWL column with this index (using `params.data`)
* @return {String[]}
*/
getDynamicKeywordlistValue: function (maskName, key, params) {
var me = this,
keywordsDynamicInfo = new KeywordsDynamicInfo(),
sord = new Sord(),
objKey = new ObjKey(), foreignObjKey = new ObjKey(),
result = [], objKeys = [],
columnMode = (params && (typeof params.returnColumn === "number")),
docMaskLine, keywordsResult, i, max, keyIndex;
key = new java.lang.String(key);
objKey.name = key;
objKey.data = (params && params.data && (typeof params.filterColumn !== "number")) ? [params.data] : [];
objKeys.push(objKey);
if (params && params.useForeignKey && (params.useForeignKey.key && params.useForeignKey.value)) {
foreignObjKey.name = params.useForeignKey.key;
foreignObjKey.data = [params.useForeignKey.value];
objKeys.push(foreignObjKey);
}
sord.objKeys = objKeys;
docMaskLine = me.getDocMaskLine(maskName, key);
if (!docMaskLine) {
throw "Can't find document mask line: maskName=" + maskName + ", key=" + key;
}
keywordsDynamicInfo.sord = sord;
keywordsDynamicInfo.maskLineFocus = docMaskLine;
keywordsResult = ixConnect.ix().checkoutKeywordsDynamic(keywordsDynamicInfo);
if (columnMode) {
keyIndex = params.returnColumn;
} else {
for (i = 0, max = keywordsResult.keyNames.size(); i < max; i++) {
if (keywordsResult.keyNames.get(i).equals(key)) {
keyIndex = i;
break;
}
}
}
for (i = 0, max = keywordsResult.table.size(); i < max; i++) {
if (!columnMode || !params.data || (typeof params.filterColumn !== "number") || (sol.common.StringUtils.startsWith(keywordsResult.table.get(i).get(params.filterColumn) + "", params.data))) {
result.push(keywordsResult.table.get(i).get(keyIndex) + "");
}
}
return result;
},
/**
* Returns the key of a localized keyword list entry
* @param {de.elo.ix.client.Sord} sord
* @param {Object} fieldDef Field definition
* @param {Object} config Configuration
* @param {String} config.localizedKwlSeparator Localized keyword list separator
* @return {String}
*/
getLocalizedKwlKey: function (sord, fieldDef, config) {
var me = this,
value, separator, separatorPos;
if (!sord) {
throw "Sord is empty";
}
if (!fieldDef) {
throw "Field definition is empty";
}
config = config || {};
separator = config.localizedKwlSeparator || "-";
value = String(me.getValue(sord, fieldDef));
separatorPos = value.indexOf(separator);
if (separatorPos < 0) {
return value;
}
return value.substring(0, separatorPos).trim();
},
/**
* Returns the localized kwl entry
* @param {String} key Key
* @param {Object} config Configuration
* @param {String} config.scriptName Script name
* @return {String}
*/
getLocalizedKwlEntry: function (key, config) {
var keywordsDynamicInfo, keywordsResult, entry;
if (!key) {
throw "Key is empty";
}
config = config || {};
if (!config.localizedKwlScript) {
throw "Localized keyword list script name is emtpy";
}
keywordsDynamicInfo = new KeywordsDynamicInfo();
keywordsDynamicInfo.mapData = { $KEY: key };
keywordsDynamicInfo.mapLineFocus = "$KEY";
keywordsDynamicInfo.mapScriptName = config.localizedKwlScript;
keywordsResult = ixConnect.ix().checkoutKeywordsDynamic(keywordsDynamicInfo);
if (keywordsResult.table.size() != 1) {
return "";
}
entry = String(keywordsResult.table.get(0).get(2));
return entry;
},
/**
* Creates a template sord from a Sord (see {@link sol.common.ObjectFormatter.TemplateSord TemplateSord}).
* @param {de.elo.ix.client.Sord} sord
* @return {Object}
*/
getTemplateSord: function (sord) {
var me = this,
templateSord;
me.logger.enter("getTemplateSord", arguments);
templateSord = sol.common.ObjectFormatter.format({
sord: {
formatter: "sol.common.ObjectFormatter.TemplateSord",
data: sord,
config: {
sordKeys: ["id", "guid", "maskName", "name", "desc", "IDateIso", "XDateIso", "ownerName"],
allMapFields: true
}
}
});
me.logger.exit("getTemplateSord");
return templateSord;
},
/**
* Creates a statistic sord from a Sord (see {@link sol.common.ObjectFormatter.StatisticSord StatisticSord}).
* @param {de.elo.ix.client.Sord} sord
* @return {Object}
*/
getStatisticSord: function (sord) {
var me = this,
statisticSord;
me.logger.enter("getStatisticSord", arguments);
statisticSord = sol.common.ObjectFormatter.format({
sord: {
formatter: "sol.common.ObjectFormatter.StatisticSord",
data: sord,
config: {
sordKeys: ["id", "guid", "maskName", "name", "desc", "IDateIso", "XDateIso", "ownerName"],
objKeys: ["VENDOR_NAME", "INVOICE_DATE", "INVOICE_CASH_DISCOUNT_AMOUNT"]
}
}
});
me.logger.exit("getStatisticSord");
return statisticSord;
},
/**
* Returns the display repository path
* @param {de.elo.ix.client.Sord} sord
* @param {Object} params Parameters
* @param {String} [params.separator="/"] Separator
* @param {Boolean} [params.withName=true] If true the name of the Sord will be appended
* @return {String}
*/
getDisplayRepoPath: function (sord, params) {
var me = this,
displayRepoPath;
if (!sord) {
throw "Sord is empty";
}
if (!sord.refPaths) {
throw "Property 'sord.refPaths is empty'";
}
params = params || {};
params.separator = params.separator || "/";
params.withName = (typeof params.withName == "undefined") ? true : params.withName;
displayRepoPath = sord.refPaths[0].pathAsString;
displayRepoPath = sol.common.StringUtils.replaceAll(displayRepoPath, me.pilcrow, params.separator);
if (params.withName) {
displayRepoPath += params.separator + sord.name;
}
return displayRepoPath;
},
/**
* Creates a Sord
*
* Backward-comptabilility added for createSord(maskId, params)
*
* @param {Object} params Parameters
* @param {String} params.mask Mask
* @param {String} params.name Name
* @param {String} [params.parentId="1"] Parent ID
* @param {String} params.sortOrder Sort order
* @param {String} params.documentContainer Container document
* @return {de.elo.ix.client.Sord} Sord
*/
createSord: function (params) {
var sord;
params = params || {};
// backward-compatibility
if (arguments.length == 2) {
params = arguments[1];
params.mask = {
mask: arguments[0]
};
}
if (!params.mask) {
throw "Mask ID is empty";
}
params.parentId = params.parentId || "1";
sord = ixConnect.ix().createSord(params.parentId, params.mask, EditInfoC.mbSord).sord;
if (typeof params.name != "undefined") {
sord.name = params.name;
}
if (typeof params.sortOrder != "undefined") {
sord.details.sortOrder = params.sortOrder;
}
if (typeof params.documentContainer != "undefined") {
sord.details.documentContainer = params.documentContainer;
}
return sord;
},
/**
* Clones a sord.
* @param {de.elo.ix.client.Sord} srcSord Source sord
* @param {Object} params (optional) Parameters
* @param {de.elo.ix.client.Sord} params.dstSord (optional) Destination sord
* @param {String} params.dstMask (optional) Destination mask
* @param {de.elo.ix.client.Sord} params.dstParentId (optional) Destination parent ID. Hint: parameter is mandatory if no `dstSord` is configured
* @param {String[]} [params.memberNames=["name"]] (optional) Member names to copy
* @param {String[]} params.detailMemberNames (optional) Detail member names to copy, e.g. `sortOrder`
* @param {String[]} params.objKeyNames (optional) Object key names to copy
* @param {Boolean} [params.inheritDestinationAcl=false] (optional) If `true` (and the target is a sord) the ACL of the target will be inherited to the cloned sord. Hint: to copy the ACL of the source sord use member `aclItems` (but `inheritDestinationAcl` has priority).
* @return {de.elo.ix.client.Sord} Sord
*/
cloneSord: function (srcSord, params) {
var me = this,
dstSord, dstMask, memberName, detailMemberName, now, i, parentSord, objKey, objKeyName, values, conn;
if (!srcSord) {
throw "Source Sord is emtpy";
}
params = params || {};
params.memberNames = params.memberNames || ["name"];
conn = params.conn || ixConnect;
if (params.dstSord) {
dstSord = new Sord(params.dstSord);
dstSord.id = -1;
dstSord.guid = "";
dstSord.ownerId = ixConnect.loginResult.user.id;
dstSord.ownerName = "";
now = me.nowIsoForConnection(conn);
dstSord.IDateIso = now;
dstSord.XDateIso = now;
} else {
dstMask = params.dstMask || srcSord.mask;
dstSord = me.createSord({ mask: dstMask, parentId: params.dstParentId });
}
for (i = 0; i < params.memberNames.length; i++) {
memberName = params.memberNames[i];
dstSord[memberName] = srcSord[memberName];
}
if (params.detailMemberNames) {
for (i = 0; i < params.detailMemberNames.length; i++) {
detailMemberName = params.detailMemberNames[i];
dstSord.details[detailMemberName] = srcSord.details[detailMemberName];
}
}
if (params.dstParentId) {
if (params.dstParentId != "0") {
parentSord = ixConnect.ix().checkoutSord(params.dstParentId, SordC.mbMin, LockC.NO);
if (params.inheritDestinationAcl) {
dstSord.aclItems = parentSord.aclItems;
}
}
dstSord.parentId = (parentSord) ? parentSord.id : "0";
}
if (!params.objKeyNames || (params.objKeyNames.length > 0)) {
for (i = 0; i < dstSord.objKeys.length; i++) {
objKey = dstSord.objKeys[i];
objKeyName = String(objKey.name);
if (objKeyName == "" || (params.objKeyNames && (params.objKeyNames.indexOf(objKeyName) < 0))) {
continue;
}
if (objKeyName != "") {
values = me.getObjKeyValues(srcSord, objKeyName);
me.setObjKeyValues(dstSord, objKeyName, values);
}
}
}
return dstSord;
},
/**
* Adds rights
* @param {de.elo.ix.client.Sord} sord Sord
* @param {Object} params Parameters
* @param {Array} params.users Users
* @param {Object} params.rigths Rights, e.g. { r: true, w: true, d: true, e: true, l: true }
*/
addRights: function (sord, params) {
var accessCode, users, userAcls, newAclItems;
if (!params) {
throw "Rights configuration is empty";
}
if (!params.users) {
throw "Users are empty";
}
params = params || {};
users = params.users.map(function (userName) {
if (userName == "$CURRENTUSER") {
return String(ixConnect.loginResult.user.name);
}
return userName;
});
params.rights = params.rights || { r: true, w: true, d: true, e: true, l: true, p: true };
accessCode = sol.common.AclUtils.createAccessCode(params.rights);
userAcls = sol.common.AclUtils.retrieveUserAcl(users, accessCode);
if (userAcls) {
newAclItems = Array.prototype.slice.call(sord.aclItems);
userAcls.forEach(function (userAcl) {
newAclItems.push(userAcl);
});
}
sord.aclItems = newAclItems;
},
/**
* Changes the sord mask
* @param {de.elo.ix.client.Sord} sord Sord
* @param {Number|String} newMask New mask ID or name
* @param {de.elo.ix.client.IXConnection} ixConnection (optional) contains the given IX-Connection
* @return {de.elo.ix.client.Sord}
*/
changeMask: function (sord, newMask, ixConnection) {
var me = this,
myConnection = ixConnection || ixConnect,
changedSord;
if (!sord) {
throw "Sord is empty";
}
if (typeof newMask == "undefined") {
throw "New mask is empty";
}
changedSord = myConnection.ix().changeSordMask(sord, newMask, EditInfoC.mbSord).sord;
me.logger.debug(["conn.username={0}, changedSord={1}", myConnection.loginResult.user.name, changedSord.name]);
return changedSord;
},
/**
* Get links
* @param {de.elo.ix.client.Sord} sord Sord
* @return {Array} Object IDs
*/
getLinks: function (sord) {
var i,
linksObj = {},
links = [],
objId;
if (!sord) {
throw "Sord is empty";
}
for (i = 0; i < sord.linksComeIn.length; i++) {
linksObj[sord.linksComeIn[i].id + ""] = 1;
}
for (i = 0; i < sord.linksGoOut.length; i++) {
linksObj[sord.linksGoOut[i].id + ""] = 1;
}
for (objId in linksObj) {
links.push(objId);
}
return links;
},
/**
* Returns now as ISO date considering the time zone
* @param {de.elo.ix.client.IXConnection} [conn=ixConnect]
* @param {Object} params Parameters
* @param {Boolean} [params.startOfDay=false] (optional) Start of day
* @return {String} ISO date
*/
nowIsoForConnection: function (conn, params) {
var me = this,
nowIso, timeZone;
conn = conn || ixConnect;
params = params || {};
timeZone = conn.loginResult.clientInfo.timeZone + "";
params.utcOffset = me.getTimeZoneOffset(timeZone);
nowIso = sol.common.DateUtils.nowIso(params);
return nowIso;
},
/**
* @private
* Gets the time zone offset
* @param {String} timeZoneString Time zone string
* @return {String} Offset
*/
getTimeZoneOffset: function (timeZoneString) {
var timeZone, utcOffset, now;
timeZone = java.util.TimeZone.getTimeZone(timeZoneString);
now = new java.util.Date();
utcOffset = timeZone.getOffset(now.time) / 1000 / 60;
return utcOffset;
},
/**
* Returns the field name index
* @param {String} fieldName Field name
* @returns {String}
*/
getFieldNameIndex: function (fieldName) {
if (!fieldName) {
return "";
}
var pos = fieldName.search(/\d+$/);
if (pos > 0) {
return parseInt(fieldName.substring(pos), 10);
}
return "";
},
/**
* Returns the ESW content
* @param {String} objId Object ID
* @param {String} params Parameters
* @param {Object} params.timeZone Timezone, e.g. `GMT`
* @return {String} ESW content
*/
getEsw: function (objId, params) {
var savedTimeZone,
editInfo, eswOptions, fileDataArr, fileData, esw;
if (!objId) {
throw "Object ID is empty";
}
params = params || {};
if (params.timeZone) {
savedTimeZone = ixConnect.loginResult.clientInfo.timeZone;
ixConnect.loginResult.clientInfo.timeZone = params.timeZone;
}
editInfo = ixConnect.ix().checkoutSord(objId, EditInfoC.mbSord, LockC.NO);
eswOptions = new EditInfoEswOptions();
fileDataArr = ixConnect.ix().getESWFromEditInfo([editInfo], eswOptions);
fileData = fileDataArr[0];
esw = new java.lang.String(fileData.data, "UTF-8") + "";
if (savedTimeZone) {
ixConnect.loginResult.clientInfo.timeZone = params.timeZone = savedTimeZone;
}
return esw;
},
/**
* Returns blob data from a map entry
* @param {de.elo.ix.client.KeyValue} mapEntry Map entry
* @param {Object} params Parameters
* @param {String} [params.returnType=String] returnType, e.g. `String`
* @param {String} [params.encoding=UTF-8] encoding, e.g. `UTF-8`
* @return {String}
*/
getBlobDataFromMapEntry: function (mapEntry, params) {
var fileData, stringValue;
if (!mapEntry || !mapEntry.blobValue) {
return;
}
fileData = mapEntry.blobValue;
if (!fileData.stream) {
return;
}
params = params || {};
params.returnType = params.returnType || "String";
params.encoding = params.encoding || "UTF-8";
if (params.returnType == "String") {
stringValue = Packages.org.apache.commons.io.IOUtils.toString(fileData.stream, params.encoding) + "";
fileData.stream.close();
return stringValue;
}
},
/**
* Returns the internal date for `iDate` and `xDate`
* @param {String} isoDate ISO date
* @param {Object} params Parameters
* @param {Object} params.conn Connection
* @param {String} Internal date
*/
getInternalDate: function (isoDate, params) {
var me = this,
ELODATE_1970_01_01_UTC,
conn, timeZone, utcOffset, date, systemMillis, internalDateInteger, internalDateString;
ELODATE_1970_01_01_UTC = 36819360;
params = params || {};
conn = params.conn || ixConnect;
timeZone = conn.loginResult.clientInfo.timeZone + "";
utcOffset = me.getTimeZoneOffset(timeZone);
if (isoDate) {
date = Packages.org.apache.commons.lang3.time.DateUtils.parseDate(isoDate, ["yyyyMMddHHmmss", "yyyyMMdd"]);
} else {
date = new java.util.Date();
}
systemMillis = date.getTime();
internalDateInteger = parseInt((systemMillis / 60 / 1000) + ELODATE_1970_01_01_UTC + utcOffset, 10);
internalDateString = internalDateInteger + "";
return internalDateString;
},
/**
* Reads map entries for the defined `objId` (or `mapId`) and returns them as an object
* @param {Object} config Configuration
* @param {Array} config.keys Map-keys which should be returned
* @param {String} [config.mapId=config.objId] Either `mapId` or `objId` must be passed. The specific map for the `mapId` or `objId` will be read.
* @param {String} config.objId Object ID
* @param {de.elo.ix.client.MapDomainDataC} [config.domain=MapDomainC.DOMAIN_SORD] Map domain
* @param {de.elo.ix.client.IXConnection} [params.connection=ixConnect] Index server connection
*/
getMapEntriesAsObject: function (config) {
var mapId,
mapObj = {},
domain, keys, connection, keyValues, i, entry;
config = config || {};
mapId = config.mapId || config.objId;
domain = config.domain || MapDomainC.DOMAIN_SORD;
if (!mapId) {
throw "Map ID is missing";
}
keys = config.keys || [];
connection = config.connection || ixConnect;
keyValues = connection.ix().checkoutMap(domain, mapId, keys, LockC.NO).items;
for (i = 0; i < keyValues.length; i++) {
entry = keyValues[i];
mapObj[entry.key + ""] = entry.value + "";
}
return mapObj;
}
});