Skip to content
Snippets Groups Projects
process.js 39.09 KiB
import("system.fileIO");
import("system.SQLTYPES");
import("system.text");
import("system.db");
import("system.vars");
import("system.eMath");
import("system.util");
import("system.datetime");
import("system.logging");
import("Attribute_lib");
import("Sql_lib");
import("Importer_lib");

/////////////////////////////////////////////////////////////////////
/// toolkit methods for the import handler                      ///
/// DO NOT TOUCH - use lib_importerCustomMappingFunctions       ///
///////////////////////////////////////////////////////////////////

/*
* Values of the mapping line:
* Keyword req -- the column index with the new keyword value
* Container req -- the keyword container for the keyword lookup
*
* @name iKeyword
* @param {Object} pObject req the mapping line
* @return {Boolean} true
**/
function iKeyword(pObject) { 
    if (!this.doIfCheck(pObject)) return true;

    var keyword = this.InputRecord[pObject.Keyword];
    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.Keyword);
    var container = this.InputRecord[pObject.Container];
    if(container == undefined) container = this.resolveSymbol(pObject, pObject.Container);

    if(!keyword || !container)  return true;
    
    var sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
    + this.getColumnCase("container") + " = ? and " + this.getColumnCase("title") + " = ?";
    var id = db.cell([sql, [[container, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
    
    if(id == "" || id == null) {
        id = util.getNewUUID();
        var columns = [this.getColumnCase("ab_keyword_entryid"), this.getColumnCase("keyid"), this.getColumnCase("container"),
            this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"), this.getColumnCase("isessential")]; 
        sql = "select max(coalesce(sorting, 0))+1 from ab_keyword_entry where container = ?";
        var sort = db.cell([sql, [[container, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
        if(sort == "") sort = "0";
        values = [id, util.getNewUUID(), container, keyword, sort, "1", "0"];
        this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, values, this.Config.AliasTo);
    }
    this.setOutput(pObject, id);
    return true;
}

/*
 * Values of the mapping line:
 * Attribute req -- the new attribute name
 * AType req -- the type of the attribute
 * OType opt -- the type of the object (AB_ATTRIBUTEUSAGE)
 * OID opt -- the row id for the object instance (AB_ATTRIBUTERELATION)
 * Value opt -- the value for the object instance (AB_ATTRIBUTERELATION)
 *
 * @name iAttribute
 * @param {Object} pObject req the mapping line
 * @return {Boolean} true
 * */
function iAttribute(pObject) {
    if (!this.doIfCheck(pObject)) return true;
    var attribute = this.InputRecord[pObject.Attribute];
    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
    var atype = this.InputRecord[pObject.AType];
    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
    var otype = this.InputRecord[pObject.OType];
    if(otype == undefined) otype = this.resolveSymbol(pObject, pObject.OType);
    var oid = this.InputRecord[pObject.OID];
    if(oid == undefined) oid = this.resolveSymbol(pObject, pObject.OID);
    var value = this.InputRecord[pObject.Value];
    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
    
    if (!attribute || !atype) return true;
    atype = atype.toUpperCase();

    var valueColumn = "";
    var attributes = attribute.split(".");   
    var columns = [this.getColumnCase("ab_attributeid"), this.getColumnCase("attribute_parent_id"), this.getColumnCase("attribute_name"), 
        this.getColumnCase("attribute_type"), this.getColumnCase("attribute_level"), this.getColumnCase("attribute_active")];
    var type = $AttributeTypes.GROUP.toString();
    switch (atype) {
        case $AttributeTypes.TEXT.toString():
            valueColumn = this.getColumnCase("char_value");
            break;
        case $AttributeTypes.DATE.toString():
            valueColumn = this.getColumnCase("date_value");
            break;
        case $AttributeTypes.NUMBER.toString():
            valueColumn = this.getColumnCase("number_value");
            break;
        case $AttributeTypes.BOOLEAN.toString():
            valueColumn = this.getColumnCase("bool_value");
            break;
        case $AttributeTypes.COMBO.toString():
            valueColumn = this.getColumnCase("id_value");
            type = $AttributeTypes.COMBO.toString();
            break;
        default:
            return true;
    }

    if (this.FuncBuffer.iAttribute == undefined) this.FuncBuffer.iAttribute = {childs: {}};
    var pathToFollow = this.FuncBuffer.iAttribute;
    for (var i = 0; i < attributes.length; i++)  {
        if (pathToFollow["childs"][attributes[i]] != undefined) {
            var id = pathToFollow["childs"][attributes[i]]["id"];            
        } else {
            pathToFollow["childs"][attributes[i]] = {id: id, childs: {}};
            if (i == 0) {
                var parent = "NULL";  
                var sql = "select " + this.getColumnCase("ab_attributeid") + " from  " + this.getTableCase("ab_attribute") + " where " 
                + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_level") + " = 0";
                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR]]], this.Config.AliasTo);                         
            } else {
                parent = pathToFollow["id"];
                sql = "select " + this.getColumnCase("ab_attributeid") + " from " + this.getTableCase("ab_attribute") + " where " 
                    + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_parent_id") + " = ?";
                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR], [parent, SQLTYPES.CHAR]]], this.Config.AliasTo);                         
            }       
            if (id == "" || id == null) {
                id = util.getNewUUID();
                if (attributes.length == i+1) type = atype;
                //TODO: add insertNoWait to instantly add AB_ATTRIBUTE records; this ensures that nothing is in the funcBuffer that does not exist in the database
                //TODO: check: are COMOB-values added automatically?
                this.insertData(this.getTableCase("ab_attribute"), columns, null, [id, parent, attributes[i], type, i.toString(), "1"], this.Config.AliasTo);
            }
            pathToFollow["childs"][attributes[i]]["id"] = id;
        }
        pathToFollow = pathToFollow["childs"][attributes[i]];
    } 
    
    if (otype) {
        var aid = id;
        sql = "select " + this.getColumnCase("ab_attributeusageid") + " from " + this.getTableCase("ab_attributeusage") + " where "
            + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_type") + " = ?";
        id = db.cell([sql, [[aid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);      
        if (id == "" || id == null) {
            columns = [this.getColumnCase("ab_attributeusageid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type")];
            this.insertData(this.getTableCase("ab_attributeusage"), columns, null, [util.getNewUUID(), aid, otype], this.Config.AliasTo);
        } 
        
        if (value && oid) {
            sql = "select " + this.getColumnCase("ab_attributerelationid") + " from " + this.getTableCase("ab_attributerelation") + " where " 
                 + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_rowid") + " = ? and "
                 + this.getColumnCase("object_type") + " = ?";
            id = db.cell([sql, [[aid, SQLTYPES.CHAR], [oid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
            if (id == "" || id == null) {
                columns = [this.getColumnCase("ab_attributerelationid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type"),
                     this.getColumnCase("object_rowid"), valueColumn];
                 this.insertData(this.getTableCase("ab_attributerelation"), columns, null, [util.getNewUUID(), aid, otype, oid, value], this.Config.AliasTo);
            } else if (this.Config.ImportCommand.indexOf("update") != -1) {
                cond = this.getColumnCase("ab_attributerelationid") + " = '" + id + "'";
                this.updateData(this.getTableCase("ab_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
            }
        }
    }    
    return true;
}

/*
 * Values of the mapping line:
 * Attribute req -- the column index with the new attribute value
 * AType req -- the type of the attribute
 * Container req -- the container name of the keyword
 * Keyword opt -- a new keyword name or an existing KeyId (AB_KEYWORD_ATTRIBUTERELATION)
 * Value opt - the value of the relation (AB_KEYWORD_ATTRIBUTERELATION)
 *
 * @name iKeywordAttribute
 * @param {Object} pObject req the mapping line
 * @return {Boolean} true
 * */
function iKeywordAttribute(pObject) {
    if (!this.doIfCheck(pObject)) return true;
    
    var attribute = this.InputRecord[pObject.Attribute];
    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
    var atype = this.InputRecord[pObject.AType];
    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
    var container = this.InputRecord[pObject.Container];
    if(container == undefined) container = this.resolveSymbol(pObject, pObject.Container);
    var keyword = this.InputRecord[pObject.Keyword];
    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.Keyword);
    var value = this.InputRecord[pObject.Value];
    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
    
    if (!attribute || !container || !atype) return true;
    atype = atype.toUpperCase();
    
    var valueColumn = "";
    switch (atype) {
        case $AttributeTypes.TEXT.toString():
            valueColumn = this.getColumnCase("char_value");
            break;
        case $AttributeTypes.NUMBER.toString():
            valueColumn = this.getColumnCase("number_value");           
            break;
        case $AttributeTypes.BOOLEAN.toString():
            valueColumn = this.getColumnCase("bool_value");         
            break;
        default:
            return true;
    }
    
    var sql = "select " + this.getColumnCase("ab_keyword_attributeid") + " from  " + this.getTableCase("ab_keyword_attribute") 
        + " where " + this.getColumnCase("name") + " = ? and " + this.getColumnCase("container") + " = ?";
    var aid = db.cell([sql, [[attribute, SQLTYPES.VARCHAR], [container, SQLTYPES.VARCHAR]]], this.Config.AliasTo); 
    if (aid == "" || aid == null) {
        aid = util.getNewUUID();
        var columns = [this.getColumnCase("ab_keyword_attributeid"), this.getColumnCase("name"), this.getColumnCase("container"), this.getColumnCase("type")];
        this.insertData(this.getTableCase("ab_keyword_attribute"), columns, null, [aid, attribute, container, atype], this.Config.AliasTo);
    }
    
    if (keyword && value) {   
        sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
            + this.getColumnCase("keyid") + " = ?";
        var kid = db.cell([sql, [[keyword, SQLTYPES.CHAR]]], this.Config.AliasTo);      
        
        if (kid == "" || kid == null) {
            sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
                + this.getColumnCase("container") + " = ? and " + this.getColumnCase("title") + " = ?";
            kid = db.cell([sql, [[container, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
            if (kid == "" || kid == null) {
                columns = [this.getColumnCase("ab_keyword_entryid"), this.getColumnCase("keyid"), this.getColumnCase("container"),
                    this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"), this.getColumnCase("isessential")]; 
                sql = "select max(coalesce(sorting, 0))+1 from ab_keyword_entry where container = ?";
                var sort = db.cell([sql, [[container, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
                if(sort == "") sort = "0";
                kid = util.getNewUUID();
                this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, 
                    [kid, util.getNewUUID(), container, keyword, sort, "1", "0"], this.Config.AliasTo);
            }
        }
        
        sql = "select " + this.getColumnCase("ab_keyword_attributerelationid") + " from " + this.getTableCase("ab_keyword_attributerelation") 
            + " where " + this.getColumnCase("ab_keyword_entry_id") + " = ? and " + this.getColumnCase("ab_keyword_attribute_id") + " = ?";
        id = db.cell([sql, [[kid, SQLTYPES.CHAR], [aid, SQLTYPES.CHAR]]], this.Config.AliasTo);
        if (id == "" || id == null) {
            columns = [this.getColumnCase("ab_keyword_attributerelationid"), this.getColumnCase("ab_keyword_entry_id"), 
                this.getColumnCase("ab_keyword_attribute_id"), valueColumn];
            id = util.getNewUUID();
            this.insertData(this.getTableCase("ab_keyword_attributerelation"), columns, null, [id, kid, aid, value], this.Config.AliasTo);
        } else {
            if (this.Config.ImportCommand.indexOf("update") != -1) {
                cond = this.getColumnCase("ab_keyword_attributerelationid") + " = '" + id + "'";
                this.updateData(this.getTableCase("ab_keyword_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
            }            
        }       
        this.setOutput(pObject, id);
    } else {
        this.setOutput(pObject, aid);
    }
    return true;  
}

/*
 * Values of the mapping line:
 * Address req -- the address for the communication entry
 * Medium req -- the medium id
 * ContactID req -- the id of the entry in the contact table
 * Standard opt -- the standard value (boolean)
 *
 * @name iComm
 * @param {Object} pObject req the mapping line
 * @return {Boolean} true
 * */
function iComm(pObject) {
    if (! this.doIfCheck(pObject)) return true;

    var address = this.InputRecord[pObject.Address];
    if(address == undefined) address = this.resolveSymbol(pObject, pObject.Address);
    var medium = this.InputRecord[pObject.Medium];
    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
    var contact = this.InputRecord[pObject.ContactID];
    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
    var standard = "0";
    if(pObject.Standard) standard = "1";
    
    if(!address || !medium || !contact) return true;
    
    var sql = "select " + this.getColumnCase("communicationid") + " from " + this.getTableCase("communication")
        +" where " + this.getColumnCase("contact_id") + " = ? and " + this.getColumnCase("medium_id") + " = ? and "
        + this.getColumnCase("standard") + " = ? and " + this.getColumnCase("addr") + " = ?"
    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.INTEGER], 
            [standard, SQLTYPES.SMALLINT], [address, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
    if (id == "" || id == null) {
        var columns = [this.getColumnCase("communicationid"), this.getColumnCase("addr"), 
            this.getColumnCase("medium_id"), this.getColumnCase("contact_id"), this.getColumnCase("standard")];
        this.insertData(this.getTableCase("communication"), columns, null, [util.getNewUUID(), address, medium, contact, standard], this.Config.AliasTo);       
    }    
    return true;
}

/*
 * Values of the mapping line:
 * Reason opt -- the reason 
 * Medium req -- the medium id
 * ContactID req -- the id of the entry in the contact table
 * Type req -- yes or no to communication
 *
 * @name iCommRestriction
 * @param {Object} pObject req the mapping line
 * @return {Boolean} true
 * */
function iCommRestriction(pObject) {
    if (!this.doIfCheck(pObject)) return true;

    var reason = this.InputRecord[pObject.Reason];
    if(reason == undefined) reason = this.resolveSymbol(pObject, pObject.Reason);
    var medium = this.InputRecord[pObject.Medium];
    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
    var contact = this.InputRecord[pObject.ContactID];
    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
    var type = this.InputRecord[pObject.Type];
    if(type == undefined) type = this.resolveSymbol(pObject, pObject.Type);
    
    if (!medium || !contact || !type) return true;

    var sql = "select top 1 " + this.getColumnCase("type") + " from " + this.getTableCase("commrestriction")
        +" where " + this.getColumnCase("contact_id") + " = ? and " + this.getColumnCase("medium") + " = ? order by " 
        + this.getColumnCase("date_edit") + " desc, " + this.getColumnCase("date_new") + " desc";
    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.CHAR]]], this.Config.AliasTo);
    if (id == "" || id == null || id != type) {
        if(reason == undefined || reason == null) reason = "NULL";
        var columns = [this.getColumnCase("commrestrictionid"), this.getColumnCase("medium"), this.getColumnCase("contact_id"), this.getColumnCase("type"), this.getColumnCase("reason")];
        this.insertData(this.getTableCase("commrestriction"), columns, null, [util.getNewUUID(), medium, contact, type, reason], this.Config.AliasTo);       
    } 
    return true;
}

/*
 * Values of the mapping line:
 * ActivityID req -- the column specifier for the activity table
 * OID req -- the id for a default object for object_rowid
 * OType req -- the context name
 *
 * @name iActivityLink
 * @param {Object} pObject req the mapping line
 * @return {Boolean} true
 * */
function iActivityLink(pObject) {
    if (!this.doIfCheck(pObject)) return true;

    var aid = this.InputRecord[pObject.ActivityID];
    if(aid == undefined) aid = this.resolveSymbol(pObject, pObject.ActivityID);
    var otype = this.InputRecord[pObject.OType];
    if(otype == undefined) otype = this.resolveSymbol(pObject, pObject.OType);
    var oid = this.InputRecord[pObject.OID];
    if(oid == undefined) oid = this.resolveSymbol(pObject, pObject.OID);
    
    if (!aid || !oid || !otype) return true; 
    
    var sql = "select " + this.getColumnCase("activitylinkid") + " from " + this.getTableCase("activitylink") + " where "
        + this.getColumnCase("activity_id") + " = ? and " + this.getColumnCase("object_type") + " = ? and " + this.getColumnCase("object_rowid") + " = ?";
    var id = db.cell([sql, [[aid, SQLTYPES.VARCHAR], [otype, SQLTYPES.VARCHAR], [oid, SQLTYPES.CHAR]]], this.Config.AliasTo);
    if (id == "" || id == null) {
        var columns = [this.getColumnCase("activitylinkid"), this.getColumnCase("activity_id"), this.getColumnCase("object_type"), this.getColumnCase("object_rowid")];
        this.insertData(this.getTableCase("activitylink"), columns, null, [util.getNewUUID(), aid, otype, oid], this.Config.AliasTo);
    }
    return true;
}

/*
* imports an document from a given path
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true, if import of the data was successful, otherwise false
*/
function iDocumentByPath(pObject){
    var resultDocument = true;
    if (! this.doIfCheck(pObject)) return true;

    try {
        if(pObject.Rowid != "" && pObject.Filename != "") {
            if(pObject.Value && pObject.Rowid) {          
                var wert = this.resolveSymbol(pObject, pObject.Value);
                var row = this.resolveSymbol(pObject, pObject.Rowid);
                var dateNew = this.resolveSymbol(pObject, pObject.DateNew);           
                var filename = this.InputRecord[pObject.Filename];
                var data = fileIO.getData(wert, util.DATA_BINARY);
                var length = fileIO.getLength(wert);
                logging.log(filename + " " + dateNew)
            }       
            var sql = "select count(" + this.getColumnCase("row_id") + ") from " + this.getTableCase("asys_binaries") 
                + " where " + this.getColumnCase("row_id") + " = ? and " + this.getColumnCase("filename") + " = ?";
            var count = db.cell([sql, [[row, SQLTYPES.CHAR], [filename, SQLTYPES.VARCHAR]]], this.Config. AliasSys);
            if(count == 0) {            
                var cols = [this.getColumnCase("Id"), this.getColumnCase("Tablename"), this.getColumnCase("Datasize"),
                    this.getColumnCase("date_new"), this.getColumnCase("date_edit"), this.getColumnCase("user_new"),
                    this.getColumnCase("bindata"), this.getColumnCase("containername"), this.getColumnCase("filename"),
                    this.getColumnCase("row_id"), this.getColumnCase("mimetype")];
                var vals = [util.getNewUUID(), "$!GENERIC!$", length, dateNew, dateNew, vars.getString("$sys.user"), data, 
                    "DOCUMENT", filename, row, util.getMimeType(filename)];
                db.insertData(this.getTableCase("asys_binaries"), cols, null, vals, this.Config. AliasSys);
            }
        }
    } catch(ex) {
        logging.log("Datei nicht gefunden!");
        resultDocument = false;
    }
    return resultDocument;
}

/*
* imports an document
* draft: Container: "string", Row: "TBL.COLID", Source: index, Filename: index, Tablename: "string",
* Description: "string", Keywords: "string"
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true, if import of the data was successful, otherwise false
*/
function iDocument(pObject)
{
    var resultDocument = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    // iDocument is insert-only
    this.setDefaultAction(pObject);
    if(pObject.Action != "I") return resultDocument;

    try
    {
        var desc = "";
        if(pObject.Description != undefined) desc = this.InputRecord[pObject.Description];
        var keyw = "";
        if(pObject.Keywords != undefined) desc = this.InputRecord[pObject.Keywords];

        if(pObject.Rowid != "" && pObject.Filename != "")
            db.insertBinary(
                            pObject.Tablename, 
                            pObject.Container, 
                            this.getOutput(pObject, "Rowid"), 
                            null, 
                            this.InputRecord[pObject.Source], 
                            this.InputRecord[pObject.Filename], 
                            desc, 
                            keyw, 
                            this.Config.AliasTo);
    }
    catch(ex)
    {
        logging.log(ex);
        resultDocument = false;
    }

    return resultDocument;
}

/*
* move import data to target
*
* @param {Object} pObject req the mapping line
*
* @example: [iMove, { Source: 3, Target: "RELATION.ADDRESS" } ]
*
* @return {Boolean} false, if the import of the row is not possible. otherwise true
*/
function iMove(pObject)
{
    var resultMove = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    if(pObject.Blobfile != undefined && pObject.Blobfile == true)  // blobfile move
    {
        var pn = pObject.Pathname;
        var fn = this.InputRecord[pObject.Source];

        // s will be NULL is something went wrong (no file, access error, etc)
        var s = this.getFileContent(pn.toString() + fn.toString(), util.DATA_TEXT);

        // if blob file could be read, assign to output buffer,
        // otherweise signal "no import for this row" by returning false as the function value
        if(s != null && s != undefined)
            this.setOutput(pObject, s);
        else
            resultMove = false;
    }
    else  // no blob file handling, just plan old move
    {
        var expr = "";
        if(pObject.Source != undefined) expr = this.InputRecord[pObject.Source];
        if(pObject.Value != undefined) expr = this.resolveSymbol(pObject, pObject.Value, pObject.Eval);
        if(pObject.Map != undefined && pObject.Index) expr = pObject.Map[this.resolveSymbol(pObject, pObject.Index, pObject.Eval)];

        //if expr is undefined, then do no replace
        if(expr != undefined)
        {
            // check for trimming option
            if(pObject.Trim != undefined && typeof(pObject.Trim) == "string")
            {
                switch(pObject.Trim.toLowerCase())
                {
                    case "left":
                        expr = expr.replace(/^\s+/, "");
                        break;
                    case "right":
                        expr = expr.replace(/\s+$/, "");
                        break;
                    case "both":
                        expr = expr.replace(/^\s+|\s+$/g, "");
                        break;
                }
            }

            // chek for replacing option
            if(pObject.Replace != undefined && typeof(pObject.Replace) == "string" && pObject.ReplaceTo != undefined)
                expr = expr.replace(pObject.Replace, pObject.ReplaceTo);

            // check for format conversion
            if(pObject.HTML2Text)
                expr = text.html2text(expr);
            else if (pObject.RTF2Text)
                expr = text.rtf2text(expr);
        }
        else
            expr = "";

        this.setOutput(pObject, expr);
    }

    return resultMove;
}


/*
* Return word number "Index" from source column.
*    Values of the mapping line:
*    String Source the source column index
*    String Regex the regular expression for the split
*    Number Index the word number starting with 0
*    String Substring "right" or "left"
*    String Separator concatenation string, default is blank
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true
*/
function iWord(pObject)
{
    var resultWord = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    var mode = pObject.Substring;
    var sep = pObject.Separator;
    if(sep == undefined) sep = " ";  // default concat with blank

    // split the input string with the regex and get the word number,
    // negative values will count from the end of the string (e.g. -1 for the last word in a string)
    if(pObject.Source != undefined) s = this.InputRecord[pObject.Source];
    if(pObject.Value != undefined) s = this.resolveSymbol(pObject, pObject.Value);

    s = s.split( pObject.Regex );
    var len = s.length;
    var num = Number(pObject.Index);
    if(num < 0) num = len - eMath.absInt(num);

    // just to be sure we are in a valid range
    if((num >= 0) && (num < len))
    {
        if(mode != undefined)
        {
            var part = "";
            // concatenate up the word
            mode = mode.toString().toLowerCase();
            if(mode == "left")
            {
                num++;
                part = s.slice(0,num).join(sep);
            }
            else if(mode == "right")
            {
                part = s.slice(pObject.Index).join(sep);
            }
            this.setOutput(pObject, part);
        }
        else
        {
            // use the single word
            this.setOutput(pObject, s[num]);
        }
    }

    if(resultWord == undefined) resultWord = "";
    return resultWord;
}


/*
* return a new ID for a key field
*			 	Value of the mapping line:
*				String pColumn req the key column
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true
*/
function iNewID(pObject)
{
    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    if (pObject.Action == undefined)
    {
        pObject.Action = "I";
    }

    this.setOutput(pObject, util.getNewUUID());
    return true;
}

/*
* join the list of columns into the specified target column
* Values of the mapping line:
*			Array pList req array containing result set indexes with joinable columns
*			String pDelimiter req the delimiter string
*			String pColumn req target column name
*
* @param {Object} pObject req the mapping line
*
* @example1: [iJoin, {Source: [3, 5], Delimiter: "\n", Target: "RELATION.ADDRESS"}]
* @example2: [iJoin, {Value: ["{3}", "{5}"], Delimiter: "\n", Target: "RELATION.ADDRESS"}]
*
* @return {Boolean} true
*/
function iJoin(pObject)
{
    var s = "";
    var len;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    if(pObject.Source != undefined)
        len = pObject.Source.length;
    if(pObject.Value != undefined)
        len = pObject.Value.length;

    for(var i=0; i < len; i++)
    {
        if (pObject.Source != undefined)
            if(this.InputRecord[pObject.Source[i]] != "")
            {
                if(i > 0 ) s += pObject.Delimiter;
                s += this.InputRecord[pObject.Source[i]];
            }

        if(pObject.Value != undefined)
            if(this.resolveSymbol(pObject, pObject.Value[i]) != "")
            {
                if(i > 0 ) s += pObject.Delimiter;
                s += this.resolveSymbol(pObject, pObject.Value[i]);
            }
    }

    this.setOutput(pObject, s);


    return true;
}

/*
* executes an sql statement with the data from input result set column in pIndex
* Values of the mapping line:
* Number pIndex req the index into the input result set
* String Command req the sql command (use {0}..{n} to specify source indexes)
* String Alias req the alias name
* String Target req the target column
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true
*/
function iSql(pObject)
{
    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;
    var sql = this.resolveSymbol(pObject, pObject.Command);

    if (pObject.Target != undefined)
        this.setOutput(pObject, db.cell(sql, pObject.Alias));
    else
        db.cell(sql, pObject.Alias);


    return true;
}


/*
* inserts or updates an relation entry
*
* @param {Object} pObject req the mapping line
*
* @example: [iInsertUpdate, { Table: "RELATION", Alias: "AO_DATEN",
*                      			Columns: ( {Name: "RELATIONID", Source: 4, Required: true },
*                            			     {Name: "AOTYPE", Value: "2" },
*                                 			 {Name: "PERS_ID", Column: "PERS.PERSID" })  } ]
*
* @return {Boolean} true, if insert and update are successful, otherwise false
*/
function iInsertUpdate(pObject)
{
    var resultUpdate = true;
    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    this.setDefaultAction(pObject);

    try
    {
        var spalten = [];
        var typen = [];
        var werte = [];
        var coldef;
        var data_ok = true; // be optimistic ...
        var alias = this.Config.AliasTo;
        var tableName = this.getTableCase(pObject.Table);
        var condition = this.resolveSymbol(pObject, pObject.Condition);

        if(pObject.Action == undefined)  // set reasonable defaults for Action, if not specified
        {
            if(this.Config.ImportCommand == "insert")
                pObject.Action = "I";
            else if(this.Config.ImportCommand == "update")
                pObject.Action = "U";
            else if(this.Config.ImportCommand == "insert+update")
                pObject.Action = "I+U";
        }

        if(this.Config.ImportCommand == "insert+update")
        {
            if(pObject.Action == "I")
                action = "insert";
            else if (pObject.Action == "U")
                action = "update";
            else if(pObject.Action == "I+U")
            {
                //try to find an existing entry
                var entryid = db.cell("select count(*) from " + tableName + " where " + condition, alias);

                if(Number(entryid) > 0)
                {
                    //exist, do update
                    action = "update";
                }
                else
                {
                    //no entry, do insert
                    action = "insert";
                }
            }
        }
        else if (this.Config.ImportCommand == "update")
        {
            action = "update";
        }
        else
        {
            action = "insert";
        }

        // loop thru the column definitions
        for(var i=0; i < pObject.Columns.length; i++)
        {
            var value = undefined;
            coldef = pObject.Columns[i];

            //be sure, that no keycolumn is pushed in the array, when action like insert
            if(coldef.Key != true || (coldef.Key == true && action == "insert")) spalten.push(this.getColumnCase(coldef.Name));
            if(coldef.Key != true || (coldef.Key == true && action == "insert")) typen.push( this.DataType[tableName][this.getColumnCase(coldef.Name)] );

            if(value == undefined && coldef.Source != undefined) value = this.InputRecord[coldef.Source];
            if(value == undefined && coldef.Value != undefined) value = this.resolveSymbol(coldef, coldef.Value, coldef.Eval);
            if(value == undefined && coldef.Key == true && action == "insert") value = util.getNewUUID();

            //value undefined should not be pushed
            //only add value if column was pushed
            if(value != undefined && (coldef.Key != true || (coldef.Key == true && action == "insert"))) werte.push(value);

            // do not update data if any required field is empty
            if(coldef.Required == true && (value == undefined || value == "")) data_ok = false;
        }

        if(data_ok == true)
        {
            switch(action)
            {
                case "insert":
                    this.insertData(tableName, spalten, typen, werte, alias);
                    break;
                case "update":
                    this.updateData(tableName, spalten, typen, werte, condition, alias);
                    break;
            }
        }
    }
    catch(ex)
    {
        logging.log(ex);
        resultUpdate = false;
    }

    return resultUpdate;
}

/*
* import a timestamp string in a specified format into a date field
*    Values of the mapping line:
*    String Source req the column index for the current record
*    String Target req target column name
*    String Format opt The timestamp format, default is YYYY-MM-DD HH:MI:SS
*    String Timezone opt The timezone string, default is UTC
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true, if the import of the timestamp was successfull, otherwise false
*/
function iTimestamp(pObject)
{
    var resultTimestamp = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    var fmt = pObject.Format;
    var tz = pObject.Timezone;
    if(fmt == undefined || fmt == "") fmt = "yyyy-MM-dd HH:mm:ss";
    if(tz == undefined || tz == "") tz = "UTC";

    var value = "";
    if(pObject.Source != undefined) value = this.InputRecord[pObject.Source];
    if(pObject.Value != undefined) value = this.resolveSymbol(pObject, pObject.Value);
    try
    {
        this.setOutput(pObject, datetime.toLong(value, fmt, tz));
    }
    catch(ex)
    {
        logging.log(ex);
        resultTimestamp = false;
    }

    return resultTimestamp;
}


/*
* decode an input entry by searching thru a translation list
*    Values of the mapping line:
*    String Value -- the input data
*    String Target -- the target column
*    String List -- the decode list, format: data;replacement;data;replacement.....
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean} true, if the the decoding was successfull, otherwise false
*/
function iDecode(pObject)
{
    var resultDecode = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    var wert = "";
    if(pObject.Source != undefined) wert = this.InputRecord[pObject.Source];
    if(pObject.Value != undefined) wert = this.resolveSymbol(pObject, pObject.Value);

    var list = pObject.List;
    var map = new Object();
    if(list != undefined)
    {
        // convert decode list into map
        list = list.split(";");

        //is the list complete?
        if(list.length % 2 == 0)
        {
            for(var i=0; i < list.length; i=i+2)
            {
                map[list[i]] = list[i+1];
            }
            // use map entry to decode
            if(wert != "") wert = map[wert];

            //if not found, set default to empty
            if(wert == undefined) wert = "";
        }
        else
        {
            //list is not correct, so wert = "" and log error message
            wert = "";
            this.writeLog(this.LogLevels.Error, "[iDecode] List is not correct!");
        }

        // write to output buffer
        this.setOutput(pObject, wert);
    }
    else
    {
        resultDecode = false;
    }

    return resultDecode;
}


/*
* save an input in a globalvar
*    Values of the mapping line:
*    String Value -- the input data
*    String Name -- the name for the globalvar
*
* @param {Object} pObject req the mapping line
*
* @example [(iGlobalVar {Value: "{3}", Name: "importLogin"} )     -->  $global.importLogin]
*
* @return {void}
*/
function iGlobalVar(pObject)
{
    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    var value = "";
    var name = "";
    if(pObject.Source != undefined) value = this.InputRecord[pObject.Source];
    if(pObject.Value != undefined) value = this.resolveSymbol(pObject, pObject.Value);
    if(pObject.Name != undefined) name = pObject.Name;
    vars.getString("$global." + name, value);
}



/*
* do character set translation.
* basically works like iMove, but allows to specify a conversion map
* that will be used to process the input data.
* conversion map is a map (directionary, associative array, whatever you call it).
* declare a varaible like theMap = new Array(); theMap("a") = "X"; theMap("b") = "z"; etc. ...
* and specify this a sthe value for the Parameter "Map"
*
* Important! Usage of "Method" parameter value "replaceall" requires ADITO online 3.0.3 or above!
*
* Values of the mapping line:
* String Value -- the input data
* String Target -- the target column
* String Map -- the decode map
* String Method -- which Method to use: "js", "replaceall" (default to "js")]
*
* @param {Object} pObject req the mapping line
*
* @return {Boolean}
*/
function iCharMap(pObject)
{
    var resultMap = true;

    //is any DoIf-condition set?
    if (! this.doIfCheck(pObject))
        return true;

    var wert = "";
    if(pObject.Source != undefined) wert = this.InputRecord[pObject.Source];
    if(pObject.Value != undefined) wert = this.resolveSymbol(pObject, pObject.Value);

    var map = pObject.Map;

    if(map != undefined)
    {
        if(pObject.Method == undefined) pObject.Method = "js";  // default to JavaScript
        this.writeLog(this.LogLevels.Debug, "[iCharMap] Using mapping method '" + pObject.Method + "' for mapping in iCharMap");

        switch(pObject.Method)
        {
            case "js" :
                for (var i in map)
                {
                    wert = wert.replace(new RegExp(i, "gi"), map[i]);
                }
                break;

            case "replaceall" :
                wert = text.replaceAll(wert, map);
                break;
        }

        // write to output buffer
        this.setOutput(pObject, wert);

    }
    else
    {
        this.writeLog(this.LogLevels.Warning, "[iCharMap] Map for iCharMap missing or undefined/empty");
        resultMap = false;
    }

    return resultMap;
}