Skip to content
Snippets Groups Projects
process.js 17.10 KiB
import("system.entities");
import("system.db");
import("system.neon");
import("system.SQLTYPES");
import("system.translate");
import("system.vars");
import("KeywordData_lib");
import("KeywordRegistry_basic");
import("Sql_lib");

/**
 * provides methods for interactions with keywords
 * 
 * @class
 */
function KeywordUtils() {}

/**
* resolves KEYIDs of a KeywordEntry into the specific title
* 
* @param {String} pContainerName name of the keyword container that shall be resolved
* @param {String} pDbFieldName name fo the database field where the KEYID-value is stored
* @param {String} [pLocale=current client language] specifies the locale for translating the title; can be false if nothing shall be translated
* 
* @return {String} a SQL-expression (case-when-statement) that resolves the KEYID into the title
*/
KeywordUtils.getResolvedTitleSqlPart = function(pContainerName, pDbFieldName, pLocale)
{
    var keywordData = KeywordData.getSimpleData(pContainerName, pLocale);
    var resSql = SqlUtils.getResolvingCaseWhen(keywordData, pDbFieldName, false);

    return SqlUtils.translateStatementWithQuotes(resSql);
};

/**
 * returns a specific name (translated) - this is normally the view-value - of a given keyword;
 * <br/>if the key could not be found an empty string "" is returned*
 * @param {String} keywordContainer specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY"
 * @param {String} key id value of the keyword where the view-value shall be searched
 * @param {String} [locale=locale depending on current client/servercontext] Language-value for translations
 *
 * @return {String} representation of the translated name of the keyword-key
 *
 * @example
 * var histMedium;
 * histMedium = vars.get("$field.MEDIUM");
 * if (histMedium) {
 *     result.string(vars.get("$field.SUBJECT") + " (" + LegacyKeywordUtils.getViewValue("ACTIVITY.MEDIUM", histMedium) + ")");
 * }
 */
KeywordUtils.getViewValue = function(keywordContainer, key, locale)
{
    if (!key)
        return "";

    var data = KeywordData.getKeyIdMap(keywordContainer, locale);

    return data[key] == undefined ? "" : data[key];
};

/**
 * collects possible and defined keyword-attributes per keyword entry and returns them
 * 
 * @param {String} pKeyId the key of an element within a containerName - this is the value that is stored in the reference-table (e.g. "DE")
 * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
 *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
 * @return {Object} key-value-pair of the keyword-attributes; contains all attribute-keys for the keywords-entries container; 
 *                                  if there is no value set for a key the null-value is given
 */
KeywordUtils.getAttributeRelationsByKey = function(pKeyId, pContainerName)
{
    if (!pKeyId)
        return "";

    var data = KeywordData.getKeywordAttributeRelations(pContainerName);

    return data[pKeyId] == undefined ? {} : data[pKeyId];
};

/**
 * return a specific attribute. Only call if you need only one. If you need more than one use getAttributeRelationsByKey()
 * 
 * @param {String} pKeyId the key of an element within a containerName - this is the value that is stored in the reference-table (e.g. "DE")
 * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
 *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
 * @param {String} pAttrName The Attribute name you need
 * @param {String} [pDefault=null] the default value, if the attribute doesn't exist. If not specified, null will be used.
 * 
 * @return {Object} the value or pDefault
 */
KeywordUtils.getAttributeRelation = function(pKeyId, pContainerName, pAttrName, pDefault)
{
    var attributes = KeywordUtils.getAttributeRelationsByKey(pKeyId, pContainerName);

    if (attributes && attributes[pAttrName] != null)
    {
        return attributes[pAttrName];
    }

    return pDefault !== undefined ? pDefault : null;
};

/**
* provides a distinctive list of all keyword-container-names in the system
* 
* @return {String[]} containerNames as 1D-Array
*/
KeywordUtils.getContainerNames = function()
{
    //do not cache this list since
    // a) the list can easily change when a new container is created
    // b) where this is called it's not relevant in terms of performance
    return db.array(db.COLUMN, "select AB_KEYWORD_CATEGORY.NAME from AB_KEYWORD_CATEGORY order by AB_KEYWORD_CATEGORY.NAME asc");
};

/**
 * returns the category name (former "keyword container") of a KeywordCategory by the given UUID or an empty string if it does not exist
 *
 * @param {String} pCategoryId UUID of the KeywordCategory
 *
 * @return {String} category name as string
 */
KeywordUtils.getCategoryNameById = function(pCategoryId)
{
    let categoryName = "";

    if(pCategoryId) {
        let resultValue = newSelect("AB_KEYWORD_CATEGORY.NAME")
                            .from("AB_KEYWORD_CATEGORY")
                            .where("AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID", pCategoryId)
                            .cell();

        if(resultValue) 
            categoryName = resultValue;
    }

    return categoryName;
};

/**
 * returns the  UUID of a KeywordCategory by the category name (fromer keyword container) or an empty string "" if it does not exist
 *
 * @param {String} pName name of the Keyword category (former "keyword container")
 *
 * @return {String} category UUID as string
 */
KeywordUtils.getCategoryIdByName = function(pName)
{
    var res = "";

    if(pName) 
    {
        var nameFilter =  {
                "type":"group",
                "operator":"AND",
                "childs":[{
                    "type":"row",
                    "name":"NAME",
                    "operator":"EQUAL",
                    "value":pName,
                    "key":pName,
                    "contenttype":"TEXT"
                }]
            };
        var entityConfig = entities.createConfigForLoadingRows()
            .entity("KeywordCategory_entity")
            .fields(["#UID"])
            .filter(JSON.stringify(nameFilter));
        var entityRow = entities.getRows(entityConfig);
        if (entityRow.length > 0)
            res = entityRow[0]["#UID"];
    }

    return res;
};

/**
* provides a translated list of keyword-entry-titles in the system filtered by a containerName;
* useful for lists where the key is the name which is then a editable displayValue
* 
* @param {String} pContainerName name of the keyword container for filtering
* @param {String} [pLocale=locale depending on current client/servercontext] Language-value for translations
* 
* @return {String[]} translated titles as 1D-Array
*/
KeywordUtils.getEntryNamesByContainer = function(pContainerName, pLocale)
{
    var data = KeywordData.getSimpleData(pContainerName, pLocale);
    data = data.map(function(v) {
        return v[1];
    });

    return data;
};


/**
* provides a translated list of keyword-entry-titles and its ids in the system filtered by a containerName;
* useful for lists where the key is the name which is then a editable displayValue
* 
* @param {String} pContainerName name of the keyword container for filtering
* @param {String} [pLocale=locale depending on current client/servercontext] Language-value for translations
* @param {boolean=} pOnlyActive if true only active keywords will be returned
* 
* @return {String[]} 2D-Array in the form of [[id1, translatedTitle1], [idN, translatedTitleN]]
*/
KeywordUtils.getEntryNamesAndIdsByContainer = function(pContainerName, pLocale, pOnlyActive)
{
    //TODO: this can be propably removed when the "Salesproject_entity.REASONS.dropDownProcess.js" is replaced by a consumer
    var list = newSelect("AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE")
                    .from("AB_KEYWORD_ENTRY")
                    .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID")
                    .where("AB_KEYWORD_CATEGORY.NAME", pContainerName)
                    .andIfSet("AB_KEYWORD_ENTRY.ISACTIVE", pOnlyActive ? "1" : null)
                    .orderBy("AB_KEYWORD_ENTRY.SORTING asc, AB_KEYWORD_ENTRY.TITLE asc")
                    .table();

    list = list.map(function(elem) {
        elem[1] = pLocale ? translate.text(elem[1], pLocale) : translate.text(elem[1]);
        return elem;
    });

    return list;
};

/**
 * checks, if a specific keyword exists
 * 
 * @param {String} pKeyId the key of an element within a containerName - this is the value that is stored in the reference-table (e.g. "DE")
 * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
 *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
 * 
 * @return {Boolean}
 */
KeywordUtils.exists = function(pKeyId, pContainerName)
{
    //a check if a keyword exists should always be on the origin data and not the cache, so do not cache here
    var countValue = newSelect("count(*)")
                    .from("AB_KEYWORD_ENTRY")
                    .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID")
                    .where("AB_KEYWORD_ENTRY.KEYID", pKeyId)
                    .and("AB_KEYWORD_CATEGORY.NAME", pContainerName)
                    .cell(true, "0")
;

    return parseInt(countValue) > 0;
};

/**
 * Get the first keyword Keyid from a container
 * 
 * @param {String} pContainerName name of the keyword container that shall be resolved
 * @param {String} [pLocale=current client language] specifies the locale for translating the title; can be false if nothing shall be translated
 * 
 * @return {String} the keyid or ""
 */
KeywordUtils.getFirst = function(pContainerName, pLocale)
{
    var keywordData = KeywordData.getSimpleData(pContainerName, pLocale);

    return (keywordData && keywordData.length > 0 ? keywordData[0][0] : "");
};

/**
 * get the translated container name.
 * 
 * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
 *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
 *
 * @return {String} translated name, if it exists in the switch case
 */
KeywordUtils.getTranslatedContainer = function(pContainerName)
{
    switch (pContainerName)
    {
        case "SalesprojectPhase":
            return translate.text("Phase");
        case "SalesprojectState":
            return translate.text("State");
        default:
            return "Please add '" + pContainerName + "' to the switch case in Salesproject_lib";
    }

}

/**
 * object that provides features for a single keyword attribute; initializes itself on creation with a specific keyword-attribute
 * 
 * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
 *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
 * @param {String} pAttributeName the name of the keyword attribute that shall be initialized
 * @param {String} [pDefault=undefined] the default value -> Does not throw an error, if default value exists.
 * 
 * @class
 */
function KeywordAttribute(pContainerName, pAttributeName, pDefault)
{
    this.container = pContainerName;
    this.attribute = pAttributeName;
    this.defaultValue = pDefault;

    var keywordAttrData = newSelect("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID, AB_KEYWORD_ATTRIBUTE.KIND")
                            .from("AB_KEYWORD_ATTRIBUTE")
                            .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID")
                            .where("AB_KEYWORD_ATTRIBUTE.NAME", pAttributeName)
                            .and("AB_KEYWORD_CATEGORY.NAME", pContainerName)
                            .arrayRow();

    if (keywordAttrData.length > 0)
    {
        this.id = keywordAttrData[0];
        this.type = keywordAttrData[1];
        this.dbField = this.type.trim();
    }
    else if(pDefault == undefined)
    {
        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword container \"%1\"", [this.attribute, this.container]));
    }
}

/**
 * get the value for a specific keyId.
 * Error if the keyword container does not have the attribute at all (you can check this with .exists())
 * Error if the attribute does not exist at the provided keyId and you have not specified a default
 * 
 * @param {String} pKeyId the keyId
 * 
 * @return {String} the loaded value (or the default)
 */
KeywordAttribute.prototype.getValue = function(pKeyId)
{
    if (this.exists())
    {
        var attrValue = newSelect(this.dbField)
                        .from("AB_KEYWORD_ENTRY")
                        .join("AB_KEYWORD_ATTRIBUTERELATION", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
                        .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID")
                        .where("AB_KEYWORD_ENTRY.KEYID", pKeyId)
                        .and("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", this.id)
                        .and("AB_KEYWORD_CATEGORY.NAME", this.container)
                        .cell();

        if (attrValue)
            return attrValue;

        if (this.defaultValue)
            return this.defaultValue;

        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword \"%1\" from container \"%2\"", [this.attribute, pKeyId, this.container]));
    }
    else if (this.defaultValue == undefined)
        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword container \"%1\"", [this.attribute, this.container]));
    else
        return this.defaultValue;
}

/**
 * get a SqlBuilder object for this keyword attribute. You can easily add additional conditions to it.
 * 
 * @return {SqlBuilder} a SqlBuilder which contains a select for the entry-id's, joins to entry and attribute and conditions for the container and the attribute-name.
 */
KeywordAttribute.prototype.getSqlBuilderSelect = function()
{
    return newSelect("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
            .from("AB_KEYWORD_ATTRIBUTERELATION")
            .join("AB_KEYWORD_ATTRIBUTE", "AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID")
            .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID = AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID")
            .where("AB_KEYWORD_CATEGORY.NAME", this.container)
            .and("AB_KEYWORD_ATTRIBUTE.NAME", this.attribute)
}

/**
 * check if the Container can have the attribute.
 *
 * @return {Boolean} true if it exists, false if not
 */
KeywordAttribute.prototype.exists = function()
{
    return this.id != undefined && this.type != undefined && this.dbField != undefined;
}


/**
 * provides methods for interactions with the special-keywords "LANGUAGE"
 * 
 * @class
 */
function LanguageKeywordUtils() {}

/**
* resolves LanguageCode into the latin name
* 
* @param {String} pDbFieldName name fo the database field where the ISO3-value is stored
* @param {String} [pLocale=current client language] specifies the locale for translating the title; can be false if nothing shall be translated
* 
* @return {String} a SQL-expression (case-when-statement)
*/
LanguageKeywordUtils.getResolvedTitleSqlPart = function(pDbFieldName, pLocale)
{
    var data = LanguageData.getData();
    var resSql = SqlUtils.getResolvingCaseWhen(data, pDbFieldName, pLocale);
    return SqlUtils.translateStatementWithQuotes(resSql);
};

/**
 * returns a specific name (translated) - this is normally the view-value of a language
 * 
 * @param {String} key id value of the language where the view-value shall be searched
 * @param {String} [locale=locale depending on current client/servercontext] Language-value for translations
 *
 * @return {String} representation of the translated name 
 * 
 */
LanguageKeywordUtils.getViewValue = function(key, locale)
{
    if (!key)
        return "";

    var languageMap = LanguageData.getIso3Map(locale);
    var languageInfo = languageMap[key];

    if (languageInfo == undefined)
        return "";

    var title = languageInfo.name;

    return title == undefined ? "" : title;
};

/**
 * determines on server- and clientside the matching iso2-code to a iso3 by generating a map and then returning the matched result;
 * on clientside the map is cached
 * 
 * @param {String} key id value (iso3) of the language where the value shall be searched
 * @param {String} [pAlias=the current alias] the database alias where the information shall be retrieved
 *
 * @return {String} iso2 or "" when nothing was found
 * 
 */
LanguageKeywordUtils.Iso2FromIso3 = function(key, pAlias)
{
    if (!key)
        return "";

    //maybe this should be retrieved by a simple select on the serverside since LanguageData-methods are only cached on the client side
    var languageMap = LanguageData.getIso3Map(null, pAlias);
    var languageInfo = languageMap[key];

    if (languageInfo == undefined)
        return "";

    var res = languageInfo.iso2;

    return res == undefined ? "" : res;
};