import("system.neon");
import("system.project");
import("system.logging");
import("system.process");
import("system.db");
import("system.util");
import("system.translate");
import("system.text");
import("system.vars");
import("system.swing");
import("system.question");
import("system.eMath");
import("system.datetime");
import("Offer_lib");
import("Date_lib");
/**
* Class containing utility functions for images
*
* @class
*
*/
function ImageUtils()
{
var that = this;
/**
* reads a picture depending on description and icon_type from ASYS_ICONS
* @param {String} pIconType requ ICON_TYPE of ASYS_ICONS
* @param {String} pDescription requ DESCRIPTION of ASYS_ICONS
* @param {Boolean} pBase64 opt true/undefined: BINDATA (Tables, trees) or false: ID (Icons, XMPP picture)
*
* @return {String} BINDATA of ASYS_ICONS
*
*
*/
this.getIcon = function(pIconType, pDescription, pBase64)
{
var field = pBase64 || pBase64 == undefined ? "BINDATA" : "ID";
return db.cell("select " + field + " from ASYS_ICONS where DESCRIPTION = '" + pDescription + "' and ICON_TYPE = '" + pIconType + "'",
"_____SYSTEMALIAS");
}
/**
* reads frequently used combination of description and bindata/id from ASYS_ICONS
* @param {String} pIconType ICON_TYPE of ASYS_ICONS
* @param {Boolean} pBase64 opt true: BINDATA or false/undefined: ID
*
* @return {String[][]} Key: Description, Value: ID
*
*/
this.getImageObject = function (pIconType, pBase64)
{
var field = pBase64 ? "BINDATA" : "ID";
var icons = {};//kein Array sondern Object, da es sich um ein assoziatives Array handelt
var data = db.table("select " + field + ", DESCRIPTION from ASYS_ICONS where ICON_TYPE = '" + pIconType + "'",
"_____SYSTEMALIAS");
for (var i = 0; i < data.length; i++ )
icons[data[i][1]] = data[i][0];
return icons;
}
}
/**
* class containing utils for URLs
* @class
*/
function UrlUtils()
{
var that = this;
/**
* Extracts a query param from an URL
*
* @param {String} pURL the text from which the parameter should be read
* @param {String} pParameter Name of the parameter
* (Messaging mit Default Trenner:
* - im.internal: "id=", "title_ack=", "title_dcl=", "text_ack=", "text_dcl=", "desc=", "name=", "result=", "decidable=", "icon=", "icon_ack=", "icon_dcl="
* - im.file: "id=", "size=", "result=", "requestor=")
* @param {String} pSplit opt der String, which marks the end of the param value, standard is '&'
*
* @return {String} the extracted value or null if param not existent
*
*
*/
this.extractBlock = function(pURL, pParameter, pSplit)
{
var idLeft = pURL.indexOf(pParameter, 0);
if(idLeft <= -1)
return null; // Kein Block vorhanden
if(pSplit != undefined) var idRight = pURL.indexOf(pSplit, idLeft);
if(pSplit == undefined || idRight <= -1) idRight = pURL.indexOf("&", idLeft);
if(idRight <= -1)
idRight = pURL.length;
return pURL.substring(idLeft + pParameter.length, idRight);
}
/**
* opens the browser
*
* @param {String} pUrl req
* @param {String} pBrowserType opt Browser type 1 = Native (Internet Explorer Rendering Engine)
* ,2 = JavaFX (WebKit Rendering Engine), 3 = Native, if possible.
* default is 2;
*
* @return {void}
*
*
*/
this.openUrl = function(pUrl, pBrowserType)
{
if ( pUrl != "" )
{
if (pUrl.substr(0, 4) != "http"
&& pUrl.substr(0, 4) != "ftp:"
&& pUrl.substr(0, 5) != "file:")
{
pUrl = "http://" + pUrl;
}
var browserType = pBrowserType || 2;
swing.openBrowser(true, false, encodeURI(pUrl), swing.WINDOW_CURRENT, [], browserType);
}
}
}
/**
* Class containing String utility functions
* @class
*
*/
function StringUtils()
{
var that = this;
/**
* validates if a string is a UUID according to versions 1 through 5 of RFC4122
* @param {String} pUUID String to be validated
* @param {bool} pIgnoreCase true if case sensitivty isn't needed
*
* @return {Boolean} ob es sich um eine UUID handelt
*
*
*/
this.isValidUUID = function(pUUID, pIgnoreCase)
{
if (pIgnoreCase)
{
pUUID = pUUID.toLowerCase();
}
return new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/).test(pUUID);
}
/**
* Returns wether a string starts with given string or not.
* @param pString String, which is being searched in
* @param pStringToSearch String, which is being searched
*
* @return {Boolean}
*
*
*/
this.stringStatrsWith = function(pString, pStringToSearch)
{
return pString.indexOf(pStringToSearch) === 0;
}
/**
* Splits street and buildingnumber
*
* @param {String} pAddress req Address
*
* @return {Array} [ Street, BuildingNr ]
*
*
*/
this.splitAddress = function(pAddress)
{
var ret = ["",""];
if(pAddress != "")
{
var arr = pAddress.match( /^[^0-9]+|[0-9]+.*$/g);
ret[0] = arr[0].trim();
if(arr[1])
ret[1] = arr[1].trim();
}
return ret;
}
/**
* Generates the string which shows, who created the dataset and who edited it
*
* @param {String} pDateNew req Date of creation
* @param {String} pUserNew req name of the user, who created the dataset
* @param {String} pDateEdit req date of the last change
* @param {String} pUserEdit req name of last editor
*
* @return {String}
*
*
*/
this.label_new_edit = function(pDateNew, pUserNew, pDateEdit, pUserEdit)
{
var retst = translate.withArguments("created on %0 by %1", [ datetime.toDate(pDateNew, translate.text("yyyy-MM-dd")), pUserNew]);
if (pDateEdit != undefined && pDateEdit != "") retst += " | " + translate.withArguments("changed on %0 by %1", [ datetime.toDate(pDateEdit, translate.text("yyyy-MM-dd")), pUserEdit]);
return(retst)
}
/**
* uses the right translate method, depending on the parameters
*
* @param {String} pText string to be translated
* @param {String} pLocale locale for translating
*
* @return {String}
*
*
*/
this.translateStr = function( pText, pLocale )
{
if ( pLocale == undefined )
return translate.text(pText);
else
return translate.text(pText, pLocale)
}
}
/**
* Class containing utility functions for use with arrays
* @class
*/
function DataUtils()
{
var that = this;
/**
* sorts a two dim array by the given index
*
* @param {Array} pArray req the Array to be sorted
* @param {String} pIndex req the index of the field to sort by
* @param {Boolean} pUp req TRUE sorts ascending, FALSE sorts decending
* @param {Boolean} isNumber TRUE sorts numerical, FALSE or undefined sorts alphanumerical
*
* @return void
*
* @throws {Error} if index is outside pArray.length
*
*
*/
this.array_mDimSort = function(pArray, pIndex, pUp, isNumber)
{
if (pArray.length == 0)
return;
if (pArray[0].length == 0)
return;
if (pIndex >= pArray[0].length)
throw new Error("Index Out Of Bounds: " + pIndex + " >= " + pArray[0].length);
/*
* the sort function
*
* @param {String} x req value 1
* @param {String} y req value 2
*
* @return {Integer}
*
* @memberof array_mDimSort
*/
function array_mDimSorter(x, y)
{
if ( isNumber )
{
xx = Number(x[pIndex]);
yy = Number(y[pIndex]);
}
else
{
xx = x[pIndex];
yy = y[pIndex];
//Umlaute austauschen
xx = xx.toLowerCase();
xx = xx.replace(/ä/g,"ae");
xx = xx.replace(/ö/g,"oe");
xx = xx.replace(/ü/g,"ue");
xx = xx.replace(/ß/g,"ss");
yy = yy.toLowerCase();
yy = yy.replace(/ä/g,"ae");
yy = yy.replace(/ö/g,"oe");
yy = yy.replace(/ü/g,"ue");
yy = yy.replace(/ß/g,"ss");
}
if (xx == yy)
return 0;
if (xx < yy)
return (pUp ? -1 : 1);
return (pUp ? 1 : -1);
}
pArray.sort(array_mDimSorter);
}
/**
* sorts an array up to 6 columns with sortorder
*
* @param {Array} pArray req the array with data
* @param {Integer} us req the Sortorder for Column 1 = Param u (1=asc, -1=desc)
* @param {Integer} u req the 1 Column
* @param {Integer} vs opt the Sortorder for Column 2 = Param v (1=asc, -1=desc)
* @param {Integer} v opt the 2 Column
* @param {Integer} ws opt the Sortorder for Column 3 = Param w (1=asc, -1=desc)
* @param {Integer} w opt the 3 Column
* @param {Integer} xs opt the Sortorder for Column 4 = Param x (1=asc, -1=desc)
* @param {Integer} x opt the 4 Column
* @param {Integer} ys opt the Sortorder for Column 5 = Param y (1=asc, -1=desc)
* @param {Integer} y opt the 5 Column
* @param {Integer} zs opt the Sortorder for Column 6 = Param z (1=asc, -1=desc)
* @param {Integer} z opt the 6 Column
*
* @return {void}
*
*
*/
this.sortArray = function(pArray, us, u, vs, v, ws, w, xs, x, ys, y, zs, z)
{
pArray.sort(_sortmulti);
/*
* sort of a two dim array, up to 6 columns
*
* @param {String} a req value 1, first compared element
* @param {String} b req value 2, sencond compared element
*
* @return {Integer} -1 - set a below b, 0 - equal, 1 - set b below a
*/
function _sortmulti(a, b)
{
var stringComparison = function(a, b)
{
a = a.toLowerCase();
a = a.replace(/ä/g,"ae");
a = a.replace(/ö/g,"oe");
a = a.replace(/ü/g,"ue");
a = a.replace(/ß/g,"ss");
b = b.toLowerCase();
b = b.replace(/ä/g,"ae");
b = b.replace(/ö/g,"oe");
b = b.replace(/ü/g,"ue");
b = b.replace(/ß/g,"ss");
return( a == b ) ? 0 : ( a > b ) ? 1 : -1;
}
var swap=0;
if (isNaN(a[u] - b[u])) // if there is a string in the first compared element
if( isNaN(a[u]) && isNaN(b[u]) ) // if both are strings,
swap = stringComparison(a[u], b[u]); // then: true - false = 1; false - true = -1
else
swap = (isNaN(a[u]) ? 1 : -1);
else
swap = (a[u] - b[u]);
if ((v == undefined) || (swap != 0))
return swap * us;
else
if (isNaN(a[v] - b[v]))
if ((isNaN(a[v])) && (isNaN(b[v])))
swap = stringComparison(a[v], b[v]);
else
swap = (isNaN(a[v]) ? 1 : -1);
else
swap = (a[v] - b[v]);
if ((w == undefined) || (swap != 0))
return swap * vs;
else
if (isNaN(a[w] - b[w]))
if ((isNaN(a[w])) && (isNaN(b[w])))
swap = stringComparison(a[w], b[w]);
else
swap = (isNaN(a[w]) ? 1 : -1);
else
swap = (a[w] - b[w]);
if ((x == undefined) || (swap != 0))
return swap * ws;
else
if (isNaN(a[x] - b[x]))
if ((isNaN(a[x])) && (isNaN(b[x])))
swap = stringComparison(a[x], b[x]);
else
swap = (isNaN(a[x]) ? 1 : -1);
else
swap = (a[x] - b[x]);
if ((y == undefined) || (swap != 0))
return swap * xs;
else
if (isNaN(a[y] - b[y]))
if ((isNaN(a[y])) && (isNaN(b[y])))
swap = stringComparison(a[y], b[y]);
else
swap = (isNaN(a[y]) ? 1 : -1);
else
swap = (a[y] - b[y]);
if ((z == undefined) || (swap != 0))
return swap * ys;
else
if(isNaN(a[z] - b[z]))
if((isNaN(a[z])) && (isNaN(b[z])))
swap = stringComparison(a[z], b[z]);
else
swap = (isNaN(a[z]) ? 1 : -1);
else
swap = (a[z] - b[z]);
return swap * zs;
}
}
/**
* removes an element from an array
*
* @param {Array} pArray req Array from which the element should be removed
* @param {String} pElement req index of the element which should be removed
*
* @return {Array} array without the removed element
*
*
*/
this.removeElement = function(pArray, pElement)
{
return pArray.splice(pElement, 1);
}
/**
* returns all elemtens not in pSource
*
* @param {Array} pSource req this elements are being searched
* @param {Array} pReference req in this array the search is done
* @param {Boolean} pIgnoreCase opt
*
* @return {Array[]} resultIn
*
*
*/
this.notIn = function(pSource, pReference, pIgnoreCase)
{
var resultIn = new Array();
for (var i = 0; i < pSource.length; i++)
{
if (!that.hasElement(pReference, pSource[i], pIgnoreCase))
resultIn.push(pSource[i]);
}
return resultIn;
}
/**
* returns if an element is in an array.
*
* @param {Array} pArray req array which should be searched in
* @param {String} pElement req Element which should looked for
* @param {Boolean} pIgnoreCase opt
*
* @return {Boolean} true if it has the element
*
*
*/
this.hasElement = function(pArray, pElement, pIgnoreCase)
{
for (var i = 0; i < pArray.length; i++)
{
if ( pIgnoreCase != undefined && pIgnoreCase )
{
if (pArray[i].toLowerCase() == pElement.toLowerCase())
return true;
}
else
if (pArray[i] == pElement)
return true;
}
return false;
}
/**
* concats arrays column by column
* see example for more details
* logging.show(JSON.stringify(concatArrayColumns(a, b)));
* //[["a","A"],["b","B"],["c","C"]]
*
* logging.show(JSON.stringify(a.concat(b)));
* //["a","b","c","A","B","C"]
* @param {Array} pArray1 req you have to pass at least 2 Arrays that shall be concated but you can pass as many as you want
* @param {Array} pArrayN req you have to pass at least 2 Arrays that shall be concated but you can pass as many as you want
*
*
*
* @return {Array} Beschreibung
*
*
*/
this.concatArrayColumns = function(pArray1, pArrayN)
{
var res = [];
for (var i = 0, l = arguments.length; i < l; i++)//this function can handle an "unlimited" amount of functionparams
{
var inpArr = arguments[i];
for (var ii = 0, ll = inpArr.length; ii < ll; ii++)
{
if (res[ii] == undefined)
res[ii] = [];
res[ii] = res[ii].concat(inpArr[ii]);
}
}
return res;
}
/**
* function to determine, if an object is truly an Array
* @param {Object} pArray
* @return {Boolean} returns wether an Object is an Array (true) or not (false)
*
*
*/
this.isArray = function(pArray)
{
return (pArray && typeof pArray === "object" && typeof pArray.length === "number" && !(pArray.propertyIsEnumerable('length')))
}
}
/**
* Class containing utility functions for table components
* @class
*/
function TableUtils()
{
var that = this;
/**
* Moving Tablerows Sort field up or down a step
*
* @param {String} pTable req Table
* @param {String} pTableComp req name of the table comp
* @param {String} pCountField req sort field name z.B. 'SORT'
* @param {String} pDirection req 'up' oder 'down'
* @param {String} pCondition opt
*
* @return {void}
*
*
*/
this.moveRow = function(pTable, pTableComp, pCountField, pDirection, pCondition)
{
that.sortRow(pTable, pCountField, pCondition);
if (pCondition == undefined || pCondition == "")
pCondition = "";
else
pCondition = " and " + pCondition;
var id = text.decodeFirst(vars.getString(pTableComp));
var col = [pCountField];
var nextval;
var typ = db.getColumnTypes( pTable, col);
var oldval = db.cell("select " + pCountField + " from " + pTable + " where " + pTable + "ID = '" + id + "'");
if (pDirection == "up")
{
nextval = db.cell("select max(" + pCountField + ") from " + pTable
+ " where " + pCountField + " < " + oldval + pCondition);
}
else
{
nextval = db.cell("select min(" + pCountField + ") from " + pTable
+ " where " + pCountField + " > " + oldval + pCondition);
}
if ( nextval == "" )
nextval = 0;
var nextID = db.cell("select " + pTable + "ID from " + pTable + " where " + pCountField + " = " + nextval + pCondition);
db.updateData(pTable, col, typ, [oldval], pTable + "ID = '" + nextID + "'")
db.updateData(pTable, col, typ, [nextval], pTable + "ID = '" + id + "'")
}
/**
* activates Up/Down buttons
*
* @param {String} pTable req Table
* @param {String} pTableComp req name of the table comp
* @param {String} pSortfield req sort field name z.B. 'SORT'
* @param {String} pDirection req 'up' or 'down'
* @param {String} pCondition opt
*
* @return {Boolean} true if active
*
*
*/
this.moveActive = function(pTable, pTableComp, pSortfield, pDirection, pCondition)
{
var oldval = "min";
var minmax = "min";
var id = text.decodeFirst(vars.getString(pTableComp));
if (pCondition == undefined || pCondition == "")
pCondition = "";
else
pCondition = " where " + pCondition;
if (id != "" && swing.getTableDataByAttribute(pTableComp, swing.INSERTED ).length == 0 && vars.getString("$sys.workingmode") == swing.FRAMEMODE_EDIT )
{
oldval = db.cell("select " + pSortfield + " from " + pTable + " where " + pTable + "ID = '" + id + "'");
if(pDirection == "down")
minmax = "max";
minmax = db.cell("select " + minmax + "(" + pSortfield + ") from " + pTable + pCondition);
}
return (oldval != minmax || oldval == "" || minmax == "" )
}
}
/**
* Class containing utility functions for use with base64 and binaries
* @class
*/
function BinaryUtils()
{
var that = this;
/**
* decodes 64Based String
*
* @param {String} input req the string
*
* @return {String} decoded String
*
*
*/
this.decode64 = function(input)
{
var charset = new Configuration().getOption("Base64Charset");
if ( charset == "" )
charset = "ISO-8859-15";
return util.decodeBase64String(input, charset);
}
/**
* returns the original size of a B64 coded String in bytes
*
* @param {String} pBase64str req base64 encoded string
*
* @return {Number} size of the string in bytes
*
*
*/
this.getBase64lengthBytes = function(pBase64str)
{
var res = pBase64str.length;
res = eMath.divDec(res, 4);
res = Math.ceil(res);
res = eMath.mulInt(3, res);
return +res;//cast und return
}
/**
* sanitizes the filelist gotten from Drag&Drop and returns it.
*
* @param {String[]} pFilelist req Die Filelist als Stringarray.
*
*
*/
this.sanitizeFilelist = function(pFilelist)
{
var sanitized = [];
if(pFilelist != undefined && pFilelist.length > 0)
{
for(let i = 0; i < pFilelist.length; i++)
{
if(swing.doClientIntermediate(swing.CLIENTCMD_FILEIO_ISDIRECTORY, [pFilelist[i]]) == "false")
sanitized.push(pFilelist[i]);
}
}
return sanitized;
}
/**
* reads the folders in a filelist and returns their contained files
*
* @param {String[]} pFilelist req Die Filelist als Stringarray.
*
*
*/
this.resolveSubfolders = function(pFilelist)
{
//read systemconfig for D&D
var cfg = new Configuration();
var filesize = (cfg.getOption("dnd.maxFileSize") *1000 *1000 );
var fileamount = 30;
var files = [];
var folders = [];
if(pFilelist != undefined && pFilelist.length > 0)
{
//separate files and folders
for (let i = 0; i < pFilelist.length; i++)
{
if(swing.doClientIntermediate(swing.CLIENTCMD_FILEIO_ISDIRECTORY, [pFilelist[i]]) == "false")
files.push(pFilelist[i]);
else
folders.push(pFilelist[i]);
}
//resovle Files in Folders
if(folders.length > 0)
{
for (let j = 0; j < folders.length; j++)
{
var resolvedFiles = swing.doClientIntermediate(swing.CLIENTCMD_FILEIO_LISTFILES, [folders[j]]);
if(resolvedFiles.length > 0)
{
for (let k = 0; k < resolvedFiles.length; k++) resolvedFiles[k] = folders[j] + "\\" + resolvedFiles[k];
files = files.concat(resolvedFiles);
}
}
}
//recursive call, cause more subfolders may be present
if( that.hasSubfolders(files) )
files = that.resolveSubfolders(files);
}
//filter out files, that exceed the size limit
var retfiles = [];
for (let m = 0; m < files.length; m++)
{
if(retfiles.length == fileamount)
break;
if(swing.doClientIntermediate(swing.CLIENTCMD_FILEIO_GETLENGTH, [files[m]]) <= filesize)
retfiles.push(files[m]);
}
logging.log(retfiles)
return retfiles;
}
/**
* Checks if subfolders are present in a filelist
*
* @param {String[]} pFilelist req the file list as string array
*
*
*/
this.hasSubfolder = function(pFilelist)
{
var ret = false;
if(pFilelist != undefined && pFilelist.length > 0)
{
for (let i = pFilelist.length; i >= 0; i--)
{
if(swing.doClientIntermediate(swing.CLIENTCMD_FILEIO_ISDIRECTORY, [pFilelist[i]]) == "true")
{
ret = true;
break;
}
}
}
return ret;
}
}
/**
* Class containing miscellaneous utiltiy function extending JDito
* @class
*/
function JDitoUtils()
{
var that = this;
/**
* A wrapper for process.executeScript
*
* @param {String} pIdentifier req The identifier for the script (for better error logging)
* @param {String} pScript req The script to execute
* @param {Object} pLocalVariables opt The local variables which can be accessed within the script
* @param {Array} pImports opt To add additional imports which will be prepended to the script
* @param {Boolean} pWrapIntoResult opt To wrap pScript into 'result.string("***")'
* @param {String} pAlias opt The alias to use within the script
*
* @return {Object} The result of the script
*
*/
this.evalScript = function(pIdentifier, pScript, pLocalVariables, pImports, pWrapIntoResult, pAlias)
{
var defaultImports = ["system.result", "system.vars"];
var importsToPrepend = [];
// add pImports to to defaultImports
if (pImports != undefined) defaultImports = defaultImports.concat(pImports);
// go trough all defaultImports an check if they already exists
for (var i = 0; i < defaultImports.length; i++ )
{
var cImport = "import(\"" + defaultImports[i] + "\");";
if (pScript.indexOf(cImport) == -1)
{
// If the current default import was not found within the script it will be prepended
importsToPrepend.push(cImport);
}
}
// join the imports to prepend and place them in front of a new variable
var script2Execute = importsToPrepend.join("\r\n") + (importsToPrepend.length > 0 ? "\r\n" : "");
// Check if the script needs to be wrapped into result.string() (e.g. (function(){return "result";})())
if (pWrapIntoResult)
script2Execute += "\r\nresult.string(" + pScript + ");\r\n"; // Wrap into 'result.string("***")'
else
script2Execute += pScript; // Just add the script after the prepended imports
return process.executeScript("[evalScript]" + pIdentifier, script2Execute, (pLocalVariables != undefined && pLocalVariables != null ? pLocalVariables : {}), (pAlias != undefined && pAlias != null ? pAlias : null));
}
/**
* Returns a list of aliasNames with a given type
* ignores errors when an alias is not confgiured (empty)
*
* @param {project.DATASOURCE_} pAliasType opt the type of the aliases to load
*
* @return {String[]} Array of aliasNames
*/
this.getAliasListByType = function(pAliasType)
{
pAliasType = pAliasType || project.DATASOURCE_DB;
var allDbAliases = project.getDataModels(project.DATAMODEL_KIND_ALIAS);
var dbAliases = [];
for (var i = 0, j = allDbAliases.length; i < j; i++)
{
var aliasName = allDbAliases[i][0];
var alias = null;
try
{
alias = project.getAliasModel(aliasName);
}
catch(ex)
{
logging.log(translate.withArguments("Der Alias \"%0\" konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert", [aliasName]));
logging.log(ex);
}
if (alias != null && alias[project.ALIAS_DATASOURCETYPE] == pAliasType)
dbAliases.push(aliasName);
}
return dbAliases;
}
/**
* returns a sorted and translated list of countries ;
* DE, AT and CH are at the beginning of the list, if pData is undefined
*
* @param {String} pLanguage opt Sprache
* @param {String[][]} pData opt if the data should not be gathered automatically
* it can be given to this parameter.
* with this, the function can be used to translate country names
*
* @return {String[][]} consisting of ISO2 and Name
*
*
*/
this.getCountries = function(pLanguage, pData)
{
var data, temp;
if(pData == undefined)
{
data = [ ["DE", "Deutschland"], ["AT", "Österreich"], ["CH", "Schweiz"] ];
temp = db.table("select COUNTRYINFO.ISO2, COUNTRYINFO.NAME_DE "
+ "from COUNTRYINFO "
+ "where COUNTRYINFO.ISO2 not in ('DE', 'AT', 'CH')");
}
else
{
data = [];
temp = pData;
}
for(var i = 0; i < data.length; i++)
data[i][1] = translateStr(data[i][1], pLanguage);
for(let i = 0; i < temp.length; i++)
temp[i][1] = translateStr(temp[i][1], pLanguage).trim();
//Sortierung nach der Übersetzung
array_mDimSort(temp, 1, true, false);
return data.concat(temp);
}
/**
* Delivers the next unique number
*
* @param {String} pColumn req database column that contains unique numbers
* @param {String} pTable req database table
* @param {Number} pStartNumber opt number to start numeration
*
* @result {String} next valid number
*/
this.getNextUniqueNumber = function(pColumn, pTable, pStartNumber){
var maxNum = that.getMaxUniqueNumber(pColumn, pTable);
if(maxNum == "0")
{
if(pStartNumber == undefined) pStartNumber = 1000;
return pStartNumber;
}
return eMath.addInt(maxNum, "1");//increment currently highest number
}
/**
* Checks if the passed number is valid (has to be unique)
*
* @param {String} pNumber number to check
* @param {String} pColumn req database column that contains unique numbers
* @param {String} pTable req database table
*
* @result {boolean} passed number is valid
*/
this.validateUniqueNumber = function(pNumber, pColumn, pTable){
var maxNum = that.getMaxUniqueNumber(pColumn, pTable);
return Number(pNumber) > Number(maxNum);
}
/**
* Delivers the hightest number currently stored in database
*
* @param {String} pColumn req database column that contains unique numbers
* @param {String} pTable req database table
*
* @result {String} hightest number
*/
this.getMaxUniqueNumber = function(pColumn, pTable){
var maxNum = db.cell("select max(" + pColumn + ") from " + pTable);
return maxNum == "" ? "0" : maxNum;
}
}
/**
* Class containing utility functions for use with JSON
* @class
*/
function JSONUtils()
{
/**
* A custom JSON.stringify() to
* - keep the functions as string
* - stringify JavaArrays
* - stringify undefined as undefined and not as null
*
* @param {Object} pObj req The object to stringify
*
* @return {String} The stringified string
*
*
*/
this.stringifyJSON = function(pObj)
{
//stringify part from JSON polyfill: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
var toString = Object.prototype.toString;
var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
var stringify = function (value){
//because: "undefined == null" is true
if (value === undefined) {
return 'undefined';
} else if (value == null) {
return 'null';
} else if (typeof value === 'number') {
return isFinite(value) ? value.toString() : 'null';
} else if (typeof value === 'boolean') {
return value.toString();
} else if (typeof value === 'object')
{
//check with "hasOwnProperty" because in JavaArrays using value.toJSON would cause an exception
if (toString.call(value) != '[object Map]' && value.hasOwnProperty("toJSON") && typeof value.toJSON === 'function') {
return value.toString();
} else if (toString.call(value) === '[object Array]') {
var res = '[';
for (var i = 0; i < value.length; i++)
res += (i ? ', ' : '') + stringify(value[i]);
return res + ']';
} else if (toString.call(value) === '[object Object]' || toString.call(value) === '[object Map]') {
var tmp = [];
for (var k in value) {
if (hasOwnProperty.call(value, k))
tmp.push(stringify(k) + ': ' + stringify(value[k]));
}
return '{' + tmp.join(', ') + '}';
//custom addition to stringify Rhino JavaArrays
} else if (toString.call(value) === '[object JavaArray]') {
return value.toSource().toString();
}
}
//custom addition for function transform
//JSON.stringify returns null on functions (default)
//instead return source code of funciton for callback-functions
else if (typeof value === 'function')
{
return value.toString();
}
return '"' + value.toString().replace(escRE, escFunc) + '"';
}
return stringify(pObj);
}
/**
* checks if pStr is JSON
*
* @param {pStr}
*
* @return false or parsed JSON
*
*
*/
this.isJSON = function(pStr)
{
if (typeof(pStr) != "string")
return false;
if (pStr[0] != "{")
return false;
if (pStr[pStr.length-1] != "}")
return false;
try
{
var parse = JSON.parse(pStr);
return parse;
}
catch (ex)
{
return false;
}
return parse;
}
}
/**
* Class containing utility functions for copying modules
* @class
*/
function CopyModuleUtils()
{
var that = this;
/**
* opens the new created modules in neonClient
*
* @param {String} pNeonContext req Name of the neon context that should be opened
* @param {Object} pModulesMapping req ModulesMapping object created by method copyModule
*
* @example var ModulesMapping = CMUtils.copyModule(InputMapping);
*
* CMUtils.openNewModules("Offer_context", ModulesMapping);
*/
this.openNewModules = function(pNeonContext, pModulesMapping)
{
if(pModulesMapping != undefined)
{
var rootModule = Object.keys(pModulesMapping)[0];
if(pModulesMapping[rootModule].DataRows != undefined)
{
var newids = [];
for(var row in pModulesMapping[rootModule].DataRows)
{
newids.push(pModulesMapping[rootModule].DataRows[row].newPrimaryKey);
}
if(newids.length > 0)
neon.openContext(pNeonContext, newids, neon.OPERATINGSTATE_VIEW, null);
}
}
}
/**
* Creates a copy of a specified module together with specified subordinated modules. <br>
* The structure of the input mapping object is the following: <br>
* pInputMapping {
* (only one rootModule allowed)
* $rootModule$: {
* condition: "sqlWhereCondition"
* , ValueMapping: {$colName$: "value"}
* , destinationModuleName: "destinationModuleName"
* , DestinationColumnMapping: { $sourceColName$ : "destinationColName" }
* , SubModules: {
* $Module$:{
* condition: "sqlWhereCondition"
* , ValueMapping: {$colName$: "value"}
* , destinationModuleName: "destinationModuleName"
* , DestinationColumnMapping: { $sourceColName$ : "destinationColName" }
* , SubModules: {...}
* }
* }
* }
* }
*
* @param {Object} pInputMapping
*
* @example var CMUtils = new CopyModuleUtils();
*
* var InputMapping = {
*
* "OFFER": {
* condition: "OFFERID = '" + vars.get("$field.OFFERID") + "'"
* ,SubModules:{
* "OFFERITEM": {
* condition: "OFFER_ID = '" + vars.get("$field.OFFERID") + "' order by ITEMSORT"
* }
* }
* }
* }
*
* CMUtils.copyModule(InputMapping);
*/
this.copyModule = function(pInputMapping)
{
var AliasDefinitionStructure = project.getAliasDefinitionStructure("Data_alias", null);
var ModulesMapping = {};
var statements = [];
buildMapping( pInputMapping );
buildStatements( ModulesMapping );
if(statements.length > 0)
db.inserts( statements );
return ModulesMapping;
/**
* Builds a mapping Object for the copyModule Method. <br>
* The structure of the Object is the following: <br>
* ModulesMapping = {
*
* $rootModule$: { ($$ marks an object property)
*
* (ModuleMapping)
* name: "moduleName"
* , destinationModuleName: "destinationModuleName"
* , DestinationColumnMapping: { $sourceColName$ : "destinationColName" }
* , ValueMapping: {$colName$: "value"}
* , dataRows:{
* (ModuleRowMapping)
* $rowid$: {
* name: "moduleName"
* , oldPrimaryKey: "oldPrimaryKeyValue"
* , newPrimaryKey: "newPrimaryKeyValue"
* , ColumnMapping: { $colName$: { newValue: "newValue", oldValue: "oldValue", destinationColumn: "destinationColumn" } }
* , ModuleMapping: object reference to ModuleMapping object that contains ModuleRowMapping objects
* , ParentModuleMapping: object reference to supervised ModuleMapping object (at this point "null" because there is no supervised object)
* }
* }
* , SubModules: {
* (ModuleMapping)
* $moduleName$: {
* name: "moduleName"
* , destinationModuleName: "destinationModuleName"
* , DestinationColumnMapping: { $sourceColName$ : "destinationColName" }
* , ValueMapping: {$colName$: "value"}
* , dataRows:{
* (ModuleRowMapping)
* $rowid$: {
* name: "moduleName"
* , oldPrimaryKey: "oldPrimaryKeyValue"
* , newPrimaryKey: "newPrimaryKeyValue"
* , ColumnMapping: { $colName$: { newValue: "newValue", oldValue: "oldValue", destinationColumn: "destinationColumn" } }
* , ModuleMapping:
* , ParentModuleMapping: object reference to supervised ModuleMapping object (at this point "null" because there is no supervised object)
* }
* }
* , SubModules: {...}
* }
* }
*
* }
*
*}
*
* @param {Object} pInputMapping InputMapping
*/
function buildMapping(pInputMapping)
{
//root mapping
var rootModule = Object.keys(pInputMapping)[0];
var ModuleMapping = _ModuleMapping(rootModule, pInputMapping[rootModule]);
var ModuleData = _getModuleData(rootModule, pInputMapping[rootModule].condition);
for(var row in ModuleData)
{
var ModuleRowMapping = _ModuleRowMapping(ModuleMapping, null, ModuleData[row]);
ModuleMapping.DataRows[ModuleRowMapping.oldPrimaryKey] = ModuleRowMapping;
}
ModulesMapping[rootModule] = ModuleMapping;
//recursive subordinated modules mapping
_buildSubordinatedMapping(pInputMapping, ModuleMapping);
//delivers stored data for module in Database with condition
function _getModuleData(pModule, pCondition)
{
if(pModule == undefined) return {};
var ModuleColumnsStructure = AliasDefinitionStructure.tables[pModule].columns;
var cols = Object.keys(ModuleColumnsStructure);
var condition = "1=1";
if(pCondition != undefined)
condition = pCondition;
var dbData = db.table("select " + cols.join(", ") + " from " + pModule + " where " + condition);
//map 2d-Array to Object { $rowNumber$: { $columnName$: { value: "valueInDB" } } }
var DataObj = {};
for(var row = 0; row < dbData.length; row++)
{
DataObj[row] = {};
for(var col = 0; col < dbData[row].length; col++)
{
DataObj[row][cols[col]] = {
value: dbData[row][col]
};
}
}
return DataObj;
}
//recursive: ModuleMapping and ModuleRowMapping for subordinated modules
function _buildSubordinatedMapping(pInputMapping, pParentModuleMapping)
{
var SubModules = pInputMapping[pParentModuleMapping.name].SubModules;
if(SubModules == undefined)
return;
for(var subModuleName in SubModules)
{
var ModuleMapping = _ModuleMapping(subModuleName, SubModules[subModuleName]);
ModuleData = _getModuleData(subModuleName, SubModules[subModuleName].condition);
for(var row in ModuleData)
{
ModuleRowMapping = _ModuleRowMapping(ModuleMapping, pParentModuleMapping, ModuleData[row]);
ModuleMapping.DataRows[ModuleRowMapping.oldPrimaryKey] = ModuleRowMapping;
}
ModulesMapping[pParentModuleMapping.name].SubModules[subModuleName] = ModuleMapping;
_buildSubordinatedMapping(SubModules, ModuleMapping);
}
}
function _ModuleMapping( pModuleName, pInputModuleMapping )
{
return {
name: pModuleName,
destinationModuleName: pInputModuleMapping.destinationModuleName == undefined ? pModuleName : pInputModuleMapping.destinationModuleName,
DestinationColumnMapping: pInputModuleMapping.DestinationColumnMapping == undefined ? {} : pInputModuleMapping.DestinationColumnMapping,
ValueMapping: pInputModuleMapping.ValueMapping == undefined ? {} : pInputModuleMapping.ValueMapping,
DataRows:{},
SubModules: {}
};
}
function _ModuleRowMapping(pModuleMapping, pParentModuleMapping, pDataRow)
{
var ModuleRowMapping = {
name: pModuleMapping.name,
oldPrimaryKey: null,
newPrimaryKey: null,
ColumnMapping: {},
ModuleMapping: pModuleMapping,
ParentModuleMapping: pParentModuleMapping
};
var ModuleColumnsStructure = AliasDefinitionStructure.tables[ModuleRowMapping.name].columns;
//build ColumnMapping
for(var col in ModuleColumnsStructure)
{
//set defined columns from InputMapping -> if not defined, use the same column
var destinationColumn = ModuleRowMapping.ModuleMapping.DestinationColumnMapping[col];
if(destinationColumn == undefined)
destinationColumn = col;
//set defined values from InputMapping -> if not defined, use the value from DB
var oldValue = pDataRow[col].value;
var newValue = newValue = ModuleRowMapping.ModuleMapping.ValueMapping[col];
if(newValue == undefined)
newValue = oldValue;
//set new primary key
if(ModuleColumnsStructure[col].primaryKey)
{
ModuleRowMapping.oldPrimaryKey = ModuleRowMapping.ColumnMapping[col] = oldValue;
newValue = util.getNewUUID();
ModuleRowMapping.newPrimaryKey = newValue;
}
ModuleRowMapping.ColumnMapping[col] = _columnMapping(newValue, oldValue, destinationColumn);
}
switch(ModuleRowMapping.name)
{
case "OFFER":
{
//andere Values setzen
var offUtils = new OfferUtils();
var dtUtils = new DateUtils();
ModuleRowMapping.ColumnMapping["OFFERCODE"].newValue = offUtils.getNextOfferNumber();
ModuleRowMapping.ColumnMapping["OFFERDATE"].newValue = dtUtils.getTodayUTC();
}
break;
case "OFFERITEM":
{
//OFFER_ID mappen
if(ModuleRowMapping.ParentModuleMapping.name == "OFFER")
{
ModuleRowMapping.ColumnMapping["OFFER_ID"].newValue = ModulesMapping[ModuleRowMapping.ParentModuleMapping.name].DataRows[ModuleRowMapping.ColumnMapping["OFFER_ID"].oldValue].newPrimaryKey;
}
//ASSIGNEDTO mappen
if(ModuleRowMapping.ColumnMapping["ASSIGNEDTO"].oldValue != "")
{
if(ModuleRowMapping.ParentModuleMapping == null)
{
ModuleRowMapping.ColumnMapping["ASSIGNEDTO"].newValue = ModulesMapping["OFFERITEM"].DataRows[ModuleRowMapping.ColumnMapping["ASSIGNEDTO"].oldValue].newPrimaryKey;
}
else
{
ModuleRowMapping.ColumnMapping["ASSIGNEDTO"].newValue = ModuleRowMapping.ModuleMapping.DataRows[ModuleRowMapping.ColumnMapping["ASSIGNEDTO"].oldValue].newPrimaryKey;
}
}
}
break;
case "OFFERLINK":
{
}
default:
{
}
}
//Spezialbehandlung USER_NEW DATENEW....
if(ModuleRowMapping.ColumnMapping["DATE_NEW"] != undefined) ModuleRowMapping.ColumnMapping["DATE_NEW"].newValue = datetime.date();
if(ModuleRowMapping.ColumnMapping["USER_NEW"] != undefined) ModuleRowMapping.ColumnMapping["USER_NEW"].newValue = vars.get("$sys.user");
if(ModuleRowMapping.ColumnMapping["DATE_EDIT"] != undefined) ModuleRowMapping.ColumnMapping["DATE_EDIT"].newValue = "";
if(ModuleRowMapping.ColumnMapping["USER_EDIT"] != undefined) ModuleRowMapping.ColumnMapping["USER_EDIT"].newValue = "";
return ModuleRowMapping;
}
function _columnMapping(pNewValue, pOldValue, pDestinationColumn)
{
return {
newValue: pNewValue,
oldValue: pOldValue,
destinationColumn: pDestinationColumn
};
}
}
/**
* Builds the insert statements for passed ModulesMapping
*
* @param {Object} pModulesMapping ModulesMapping from buildMapping()
*/
function buildStatements(pModulesMapping)
{
var rootModule = Object.keys(pModulesMapping)[0];
for(var row in pModulesMapping[rootModule].DataRows)
{
//buildInsertStatement
statements.push(_statement(pModulesMapping[rootModule].DataRows[row]));
}
_subordinatedStatements(pModulesMapping[rootModule]);
function _subordinatedStatements(pMapping)
{
if(pMapping.SubModules == undefined)
return;
for(var subModule in pMapping.SubModules)
{
for(var row in pMapping.SubModules[subModule].DataRows)
{
statements.push(_statement(pMapping.SubModules[subModule].DataRows[row]));
}
_subordinatedStatements(pMapping.SubModules[subModule]);
}
}
function _statement(pRowMapping)
{
var cols = [];
var vals = [];
var destTable = pRowMapping.ModuleMapping.destinationModuleName;
var colMapping = pRowMapping.ColumnMapping;
for(var col in colMapping)
{
cols.push(colMapping[col].destinationColumn);
vals.push(colMapping[col].newValue.toString());
}
var colTypes = db.getColumnTypes(destTable, cols)
return [destTable, cols, colTypes, vals];
}
}
}
}
/**
* provides somehow static methods for special handling in JDito-Processes
* do not create an instance of this
*/
function ProcessHandlingUtil()
{
}
/**
* In onValidation-Process a local variable called "$local.value" is made available from kernel.
* It contains the entered value - the field contains the value only after successfull validation (vars.get("$field.Fieldname")).
* The onValidation-Process is running again before saving the entity, at this point there's "$local.value" varialbe no longer available,
* but the entered value now is the present one because the field has already been validated before.
* Otherwise a "variable not found" error would occur.
*
* @param {String} pFieldValue req value of the field onValidation-Process is executed ( e.g. vars.get("$field.Fieldname") )
* @return {String} Field value for onValidation-Process
*/
ProcessHandlingUtil.getOnValidationValue = function(pFieldValue)
{
return vars.exists("$local.value") ? vars.get("$local.value") : pFieldValue;
}