Skip to content
Snippets Groups Projects
process.js 42.58 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("KeywordRegistry_basic");
import("Sql_lib");
import("Importer_lib");

// TODO: use SqlBuilder

/*
+---------------------------------------------------------------+
� 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);
    }
    if (pObject.Target) // no target specified? just try to create a new keyword entry if necessary 
        this.setOutput(pObject, id);
    return true;
}

/*
 * Values of the mapping line:
 * attribute (required): The new attribute name.
 * attributeType (required): The type of the attribute e.g 'GROUP'.
 * objectType (optional): The type of the object (AB_ATTRIBUTEUSAGE).
 * objectId (optional): The OBJECT_ROWID for the object instance (AB_ATTRIBUTERELATION).
 * value (optional): 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];
    var attributeType = this.InputRecord[pObject.attributeType];
    var objectType = this.InputRecord[pObject.objectType];
    var objectId = this.InputRecord[pObject.objectId];
    var value = this.InputRecord[pObject.value];
    
    var alias = this.Config.AliasTo;
    var funcBuffer = this.FuncBuffer.iAttribute;
    var ab_attribute = this.getTableCase("ab_attribute");
    var ab_attributeId = this.getColumnCase("ab_attribute.ab_attributeid");
    var attribute_parent_id = this.getColumnCase("ab_attribute.attribute_parent_id");
    var attribute_name = this.getColumnCase("ab_attribute.attribute_name");
    var attribute_type = this.getColumnCase("ab_attribute.attribute_type");
    var attribute_active = this.getColumnCase("ab_attribute.attribute_active");
    var ab_attributeUsage = this.getTableCase("ab_attributeusage");
    var ab_attributeUsageId = this.getColumnCase("ab_attributeusage.ab_attributeusageid");
    var attrU_ab_attribute_id = this.getColumnCase("ab_attributeusage.ab_attribute_id");
    var attrU_object_type = this.getColumnCase("ab_attributeusage.object_type");
    var ab_attributeRelation = this.getTableCase("ab_attributerelation");
    var attrRel_ab_attribute_id = this.getColumnCase("ab_attributerelation.ab_attribute_id"); 
    var ab_attributeRelationId = this.getColumnCase("ab_attributerelation.ab_attributerelationid");
    var object_rowId = this.getColumnCase("ab_attributerelation.object_rowid");
    var attrRel_object_type = this.getColumnCase("ab_attributerelation.object_type")
    
    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.attribute);
    if(attributeType == undefined) attributeType = this.resolveSymbol(pObject, pObject.attributeType);
    if(objectType == undefined) objectType = this.resolveSymbol(pObject, pObject.objectType);
    if(objectId == undefined) objectId = this.resolveSymbol(pObject, pObject.objectId);
    if(value == undefined) value = this.resolveSymbol(pObject, pObject.value);
    
    if (!attribute || !attributeType) return true;
    attributeType = attributeType.toUpperCase();

    var valueColumn = "";
    var attributes = attribute.split(".");   
    var columns = [ab_attributeId, attribute_parent_id, attribute_name, attribute_type, attribute_active];
    var type = $AttributeTypes.GROUP.toString();

    if ($AttributeTypes[attributeType] == undefined) 
    {
        this.writeLog(this.LogLevels.Error, "iAttribute: " + attributeType + " isn't a valid attribute type.");
        return false;
    }

    switch (attributeType) 
    {
        case $AttributeTypes.COMBO.toString():
            valueColumn = $AttributeTypes[attributeType].databaseField;
            type = $AttributeTypes.COMBO.toString();
            break;
        default:
            valueColumn = $AttributeTypes[attributeType].databaseField;
    }

    if (funcBuffer == undefined) funcBuffer = {childs: {}};
    var pathToFollow = funcBuffer;

    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";
                // select ab_attributeid from AB_ATTRIBUTE where ATTRIBUTE_NAME = 'Subordinate campaign of' and attribute_parent_id is null
                id = newSelect(ab_attributeId, alias).from(ab_attribute).where(attribute_name, attributes[i])
                        .and(attribute_parent_id + "is null").cell();
            } 
            else 
            {
                parent = pathToFollow["id"];
                id = newSelect(ab_attributeId, alias).from(ab_attribute).where(attribute_name, attributes[i])
                        .and(attribute_parent_id, parent).cell();
            }
            
            if (id == "" || id == null) 
            {
                id = util.getNewUUID();
                if (attributes.length == i+1) type = attributeType;
                //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?
                var values = [id, parent, attributes[i], type, "1"];
                this.insertData(ab_attribute, columns, null, values, alias);
            }   
            pathToFollow["childs"][attributes[i]]["id"] = id;   
        }
        pathToFollow = pathToFollow["childs"][attributes[i]];
    }
    
    if (objectType) 
    {
        var attributeId = id;
        id = newSelect(ab_attributeUsageId, alias).from(ab_attributeUsage).where(attrU_ab_attribute_id, attributeId)
                .and(attrU_object_type, objectType).cell();
        
        if (id == "" || id == null) 
        {
            columns = [ab_attributeUsageId, attrU_ab_attribute_id, attrU_object_type];
            values = [util.getNewUUID(), attributeId, objectType];
            this.insertData(ab_attributeUsage, columns, null, values, alias);
        } 
        
        if (value && objectId) 
        {
            id = newSelect(ab_attributeRelationId, alias).from(ab_attributeRelation).where(attrRel_ab_attribute_id, attributeId)
                    .and(object_rowId, objectId).and(attrRel_object_type, objectType).cell();
            
            if (id == "" || id == null) 
            {
                columns = [ab_attributeRelationId, attrRel_ab_attribute_id, attrRel_object_type, object_rowId, valueColumn];
                values = [util.getNewUUID(), attributeId, objectType, objectId, value];
                this.insertData(ab_attributeRelation, columns, null, values, alias);
            } 
            else if (this.Config.ImportCommand.indexOf("update") != -1)
            {
                cond = ab_attributeRelationId + " = '" + id + "'";
                this.updateData(ab_attributeRelation, [valueColumn], null, [value], cond, alias);
            }
        }
    }    
    return true;
}

/*
 * Values of the mapping line:
 * - attribute (required): The column index with the new attribute value.
 * - attributeType (required): The type of the attribute.
 * - keywordContainer (required): The container name of the keyword.
 * - keyword (optional): A new keyword name or an existing KeyId (AB_KEYWORD_ATTRIBUTERELATION).
 * - value (optional): The value of the relation (AB_KEYWORD_ATTRIBUTERELATION).
 *
 * @name iKeywordAttribute
 * @param {Object} pObject (required) the mapping line.
 * @return {Boolean} true
 * */

function iKeywordAttribute(pObject) {
    if (!this.doIfCheck(pObject)) return true;
    
    var keywordAttribute = this.InputRecord[pObject.attribute];
    if(keywordAttribute == undefined) keywordAttribute = this.resolveSymbol(pObject, pObject.attribute);

    var keywordAttributeType = this.InputRecord[pObject.attributeType];
    if(keywordAttributeType == undefined) keywordAttributeType = this.resolveSymbol(pObject, pObject.attributeType);

    var keywordContainer = this.InputRecord[pObject.keywordContainer];
    if(keywordContainer == undefined) keywordContainer = this.resolveSymbol(pObject, pObject.keywordContainer);
    
    var keyword = this.InputRecord[pObject.keyword];
    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.keyword);
    
    var keywordAttrRelValue = this.InputRecord[pObject.keywordAttrRelValue];
    if(keywordAttrRelValue == undefined) keywordAttrRelValue = this.resolveSymbol(pObject, pObject.keywordAttrRelValue);
    
    if (!keywordAttribute || !keywordContainer || !keywordAttributeType) return true;
    keywordAttributeType = keywordAttributeType.toUpperCase();
    
    var valueColumn = "";
    
    switch (keywordAttributeType) {
        case $KeywordRegistry.keywordAttributeType$char():
            valueColumn = this.getColumnCase("char_value");
            break;
        case $KeywordRegistry.keywordAttributeType$number():
            valueColumn = this.getColumnCase("number_value");           
            break;
        case $KeywordRegistry.keywordAttributeType$bool():
            valueColumn = this.getColumnCase("bool_value");         
            break;
        case $KeywordRegistry.keywordAttributeType$longChar():
            valueColumn = this.getColumnCase("long_char_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 attributeId = db.cell([sql, [[keywordAttribute, SQLTYPES.VARCHAR], [keywordContainer, SQLTYPES.VARCHAR]]], this.Config.AliasTo); 
    
    // Creates the entry in AB_KEYWORD_ATTRIBUTE, case if it not exists.
    if (attributeId == "" || attributeId == null) {
        attributeId = util.getNewUUID();
        var columns = [this.getColumnCase("ab_keyword_attributeid"), 
        this.getColumnCase("name"), 
        this.getColumnCase("container"), 
        this.getColumnCase("kind")];

        this.insertData(this.getTableCase("ab_keyword_attribute"), columns, null, 
            [attributeId, keywordAttribute, keywordContainer, keywordAttributeType], this.Config.AliasTo);
    }
    
    // Creates the entry in AB_KEYWORD_ENTRY and AB_KEYWORD_ATTRIBUTERELATION, case if it not exists.
    if (keyword && keywordAttrRelValue) {   
        sql = "select " + this.getColumnCase("ab_keyword_entryid")
        + " from " + this.getTableCase("ab_keyword_entry")
        + " where " + this.getColumnCase("keyid") + " = ?";
    
        var keywordId = db.cell([sql, [[keyword, SQLTYPES.CHAR]]], this.Config.AliasTo);      
        
        if (keywordId == "" || keywordId == null) {
            
            sql = "select " + this.getColumnCase("keyid") 
            + " from " + this.getTableCase("ab_keyword_entry") 
            + " where " + this.getColumnCase("container") 
            + " = ? and " + this.getColumnCase("title") + " = ?";
            
            keywordId = db.cell([sql, [[keywordContainer, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
            
            if (keywordId == "" || keywordId == 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, [[keywordContainer, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
                
                if(sort == "") sort = "0";
                
                keywordId = util.getNewUUID();
                
                this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, 
                    [keywordId, util.getNewUUID(), keywordContainer, keyword, sort, "1", "0"], this.Config.AliasTo);
            }
        }
        
        // Creates or updates the keyword attributerelation.
        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, [[keywordId, SQLTYPES.CHAR], [attributeId, 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, keywordId, attributeId, keywordAttrRelValue], 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, [keywordAttrRelValue], cond, this.Config.AliasTo);
            }            
        }       
    } 
    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];
    var medium = this.InputRecord[pObject.Medium];
    var contact = this.InputRecord[pObject.ContactID];
    var standard = "0";
    
    if(address == undefined) address = this.resolveSymbol(pObject, pObject.address);
    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.medium);
    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
    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("isstandard") + " = ? and " + this.getColumnCase("addr") + " = ?"
    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.CHAR], //TODO: define types dynamically and not hardcoded
        [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("isstandard")];
        this.insertData(this.getTableCase("communication"), columns, null, [util.getNewUUID(), address, medium, contact, standard], this.Config.AliasTo);       
    }    
    return true;
}

/*
 * Values of the mapping line:
 * contact (required): The id of the entry in the contact table.
 * restrictionMedium (required): The medium id.
 * restrictionReason (optional): The reason.
 * startDate (optional): The date when the restrictions begins.
 * involvedEmployee (optional): The contact which is responsible for the restriction.
 *
 * @name iCommRestriction
 * @param {Object} pObject (required): Associative Array with required informations.
 * @return {Boolean} true
 * */

function iCommRestriction(pObject) 
{
    if (!this.doIfCheck(pObject)) return true;

    var restrictionContact = this.InputRecord[pObject.restrictionContact];
    var restrictionReason = this.InputRecord[pObject.restrictionReason];
    var restrictionMedium = this.InputRecord[pObject.restrictionMedium];
    var restrictionStartDate = this.InputRecord[pObject.restrictionStartDate];
    var restrictionInvolvedEmployee = this.InputRecord[pObject.restrictionInvolvedEmployee];
    
    if(restrictionContact == undefined) restrictionContact = this.resolveSymbol(pObject, pObject.restrictionContact);
    if(restrictionReason == undefined) restrictionReason = this.resolveSymbol(pObject, pObject.restrictionReason);
    if(restrictionReason == undefined || restrictionReason == null) restrictionReason = "NULL";
    if(restrictionMedium == undefined) restrictionMedium = this.resolveSymbol(pObject, pObject.restrictionMedium);
    if(restrictionStartDate == undefined) restrictionStartDate = this.resolveSymbol(pObject.restrictionStartDate);
    if(restrictionStartDate == undefined || restrictionStartDate == null) restrictionStartDate = "NULL";
    if(restrictionInvolvedEmployee == undefined) restrictionInvolvedEmployee = this.resolveSymbol(pObject.restrictionInvolvedEmployee);
    if(restrictionInvolvedEmployee == undefined || restrictionInvolvedEmployee == null) restrictionInvolvedEmployee = "NULL";
    
    if (!restrictionMedium || !restrictionContact) return true;

    var alias = this.Config.AliasTo;
    var commRestriction = this.getTableCase("commrestriction");
    var commRestrictionId = this.getColumnCase("commrestriction.commrestrictionid");
    var contactId = this.getColumnCase("commrestriction.contact_id");
    var medium = this.getColumnCase("commrestriction.medium");
    var reason = this.getColumnCase("commrestriction.reason");
    var startDate = this.getColumnCase("commrestriction.startdate");
    var involvedEmployee = this.getColumnCase("commrestriction.employee_involved");

    var id = newSelect(commRestrictionId, alias).from(commRestriction).where(contactId, restrictionContact).and(medium, restrictionMedium).cell();
    var columns = [commRestrictionId, medium, reason, contactId, startDate, involvedEmployee];
    var values = [id, restrictionMedium, restrictionReason, restrictionContact, restrictionStartDate, restrictionInvolvedEmployee];
    
    if (id == "" || id == null) 
    {
        values[0] = util.getNewUUID();
        this.insertData(commRestriction, columns, null, values, alias);       
    }
    else
    {
        this.updateData(commRestriction, columns, null, values, alias);
    }
    
    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 activityId = this.InputRecord[pObject.ActivityID];
    
    if(activityId == undefined) 
        activityId = this.resolveSymbol(pObject, pObject.ActivityID);
    
    var objectType = this.InputRecord[pObject.OType];
    
    if(objectType == undefined) 
        objectType = this.resolveSymbol(pObject, pObject.OType);
    
    var objectId = this.InputRecord[pObject.OID];
    
    if(objectId == undefined) 
        objectId = this.resolveSymbol(pObject, pObject.OID);
    
    if (!activityId || !objectId || !objectType) 
        return true; 
    
    var columnCaseActivityLinkId = this.getColumnCase("activitylinkid");
    var tableCaseActivityLink = this.getTableCase("activitylink");
    var columnCaseActivityId = this.getColumnCase("activity_id");
    var columnCaseObjectType = this.getColumnCase("object_type");
    var columnCaseObjectRowId = this.getColumnCase("object_rowid");
    var configAliasTo = this.Config.AliasTo;
       
    var sql = "select " + columnCaseActivityLinkId
    +" from " + tableCaseActivityLink
    + " where " + columnCaseActivityId
    + " = ? and " + columnCaseObjectType
    + " = ? and " + columnCaseObjectRowId
    + " = ?";
    
    var id = db.cell([sql, [[activityId, SQLTYPES.VARCHAR], [objectType, SQLTYPES.VARCHAR], [objectId, SQLTYPES.CHAR]]], configAliasTo);
    
    if (id == "" || id == null) {
        var columns = [columnCaseActivityLinkId, columnCaseActivityId, columnCaseObjectType, columnCaseObjectRowId];
        this.insertData(tableCaseActivityLink, columns, null, [util.getNewUUID(), activityId, objectType, objectId], configAliasTo);
    }
    
    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) keyw = 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 {Boolean}
 */
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);
    
    return false;
}



/*
 * 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;
}