Skip to content
Snippets Groups Projects
contentProcess.js 10.1 KiB
Newer Older
import("system.translate");
import("system.util");
import("Util_lib");
import("system.vars");
import("system.result");
import("system.db");
import("Attribute_lib");
import("Sql_lib");

var idvalues = vars.exists("$local.idvalues") ? vars.get("$local.idvalues") : null;
var getTree = !idvalues && vars.getString("$param.GetTree_param") == "true";
var loadFullAttributeName = vars.getString("$param.DisplaySimpleName_param") != "true";
var typeWhitelist, typeBlacklist;
if (vars.getString("$param.GetTheme_param") == "true")
    typeWhitelist = [$AttributeTypes.THEME.toString()];
else
    typeBlacklist = [$AttributeTypes.THEME.toString()];
    
var loadEmptyAttributes = vars.getString("$param.ShowEmpty_param") == "true";
var filteredAttributeIds = vars.exists("$param.FilteredAttributeIds_param") && vars.get("$param.FilteredAttributeIds_param");
if (filteredAttributeIds)
    filteredAttributeIds = JSON.parse(filteredAttributeIds);
var objectRowId = vars.get("$param.ObjectRowId_param");
var objectType = vars.get("$param.ObjectType_param");
var attributeQueryMaker = {
    defaultQueryFields : [
        "AB_ATTRIBUTERELATIONID",
        "AB_ATTRIBUTE.AB_ATTRIBUTEID", 
        "AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", 
        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
        "AB_ATTRIBUTE.ATTRIBUTE_NAME", 
        "AB_ATTRIBUTE.DROPDOWNDEFINITION", 
        "COMBOVAL.ATTRIBUTE_NAME",
        "AB_ATTRIBUTERELATION.DATE_NEW",
        "AB_ATTRIBUTERELATION.USER_NEW",
        "AB_ATTRIBUTERELATION.DATE_EDIT",
        "AB_ATTRIBUTERELATION.USER_EDIT",
        "AB_ATTRIBUTE.DROPDOWNFILTER"
    ],
    valueQueryFields : AttributeTypeUtil.getAllDatabaseFields(),
    getConditionForIdValues : function (pIdValues, pLoadEmptyAttributes)
        var idCondition = newWhere();
        
        if (pLoadEmptyAttributes)
            pIdValues.forEach(function (id)
            {
                var [attributeRelationId, attributeId] = JSON.parse(id);
                idCondition.or("AB_ATTRIBUTERELATION.AB_ATTRIBUTERELATIONID", attributeRelationId);
                idCondition.or(newWhere("AB_ATTRIBUTERELATION.AB_ATTRIBUTERELATIONID is null")
                    .and("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeId));
            });
        }
        else
            idCondition.andIfSet("AB_ATTRIBUTERELATION.AB_ATTRIBUTERELATIONID", pIdValues, SqlBuilder.IN());
        return idCondition;
    },
    getConditionForLinkedObject : function (pObjectType, pLoadEmptyAttributes, pAttributeIds, pTypeBlacklist, pTypeWhitelist)
        var attributeCondition = newWhereIfSet("AB_ATTRIBUTE.ATTRIBUTE_TYPE", pTypeBlacklist, SqlBuilder.NOT_IN());
        attributeCondition.andIfSet("AB_ATTRIBUTE.ATTRIBUTE_TYPE", pTypeWhitelist, SqlBuilder.IN());
        if (pLoadEmptyAttributes)
            attributeCondition.andIfSet("AB_ATTRIBUTE.AB_ATTRIBUTEID", AttributeUtil.getPossibleAttributes(pObjectType), SqlBuilder.IN());
        if (pAttributeIds)
        {
            let attributeChildren = AttributeUtil.getAllChildren(pAttributeIds);
            let attributeIdCondition = newWhere();

            if (attributeChildren.length > 0)
            {
                attributeIdCondition.and("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeChildren, SqlBuilder.IN())
                attributeIdCondition.and("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, SqlBuilder.NOT_EQUAL());
            }

            // return nothing if filteredAttributeIds is an empty array. (--> and 1=2)
            if (!attributeIdCondition.hasCondition())
                return null;
            attributeCondition.and(attributeIdCondition);
        }
        return attributeCondition;
    },
    
    getAttributeQuery : function (pIdValues, pObjectRowId, pObjectType, pLoadEmptyAttributes, pAttributeIds, pTypeBlacklist, pTypeWhitelist)
    {
        var attributeQuery = newSelect(this.defaultQueryFields.concat(this.valueQueryFields))
            .from("AB_ATTRIBUTE")
            .orderBy("AB_ATTRIBUTE.SORTING asc");
        if (pIdValues)
            attributeQuery.where(this.getConditionForIdValues(pIdValues, pLoadEmptyAttributes));
        else if (pObjectRowId)
            let condition = this.getConditionForLinkedObject(pObjectType, pLoadEmptyAttributes, pAttributeIds, pTypeBlacklist, pTypeWhitelist);
            if (condition === null)
                return null;
            attributeQuery.where(condition);
        var attributeRelationCond = newWhere("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"); //condition for the joined values (for AttributeRelation)
        if (!pIdValues && pObjectRowId)
        {
            attributeRelationCond.and("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
            attributeRelationCond.andIfSet("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
        }
        if (pLoadEmptyAttributes)
            attributeQuery.leftJoin("AB_ATTRIBUTERELATION", attributeRelationCond);
        else
            attributeQuery.join("AB_ATTRIBUTERELATION", attributeRelationCond);
        attributeQuery.leftJoin("AB_ATTRIBUTE", "COMBOVAL.AB_ATTRIBUTEID = " + $AttributeTypes.COMBO.databaseField, "COMBOVAL");
        
        return attributeQuery;
    }
}
var attributeQuery = attributeQueryMaker.getAttributeQuery(idvalues, objectRowId, objectType, loadEmptyAttributes, filteredAttributeIds, typeBlacklist, typeWhitelist);
var attributeRelations = attributeQuery != null ? attributeQuery.table(false) : [];
S.Listl's avatar
S.Listl committed
//Builds an object containing the minimal counts of the attributes, this is required for
//checking if an attribute is used not often enough or just often enough. When this is the case,
//deletion of this attributeRelation will be prohibited.
var minCountInsurance = {
    minCounts : {},
    usageCounts : {},
S.Listl's avatar
S.Listl committed
    
    loadMinCounts : function (pObjectType)
        
        var minUsages = newSelect("AB_ATTRIBUTE_ID, MIN_COUNT")
            .from("AB_ATTRIBUTEUSAGE")
            .whereIfSet("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", Object.keys(this.usageCounts), SqlBuilder.IN())
            .and("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
            .table(true);
        minUsages.forEach(function ([attributeId, minCount])
S.Listl's avatar
S.Listl committed
        {
            this.minCounts[attributeId] = minCount;
        }, this);
    },
    incrUsageCount : function (pAttributeId)
    {
        if (pAttributeId in this.usageCounts)
            this.usageCounts[pAttributeId]++;
        else
            this.usageCounts[pAttributeId] = 1;
    },
    attributeNotDeletable : function (pAttributeId)
    {
        return this.minCounts[pAttributeId] >= this.usageCounts[pAttributeId];
    }
};
S.Listl's avatar
S.Listl committed

attributeRelations = attributeRelations.map(function (row) 
{
    var [attrRelId, attrId, attrParentId, attrType, attrName, dropDownDef, comboViewVal, dateNew, userNew, dateEdit, userEdit, dropDownFilter] = row;
    attrName = translate.text(attrName);
    attrType = attrType.trim();
    if (!getTree && loadFullAttributeName && attrParentId)
    {
        let parentName = AttributeUtil.getFullAttributeName(attrParentId);
        attrName = (parentName ? parentName + " / " : "") + attrName;
    var value = row[AttributeTypeUtil.getTypeColumnIndex(attrType) + attributeQueryMaker.defaultQueryFields.length];
    var viewValue;
    if (attrType == $AttributeTypes.COMBO)
        viewValue = translate.text(comboViewVal);
    else 
        viewValue = AttributeTypeUtil.getAttributeViewValue(attrType, value, dropDownDef);
    minCountInsurance.incrUsageCount(attrId);

    //if loadEmptyAttributes is true, the id is contains the attributeRelation id and the attribute id.
    //in case there is no attributeRelation, a random id is used
    return [
        loadEmptyAttributes ? JSON.stringify([attrRelId || util.getNewUUID(), attrId]) : attrRelId,
        attrRelId,
        attrParentId, 
        value,
        viewValue, 
        attrId, 
        attrName, 
        "", //protected
        attrType.trim(), 
        dateNew, 
        userNew, 
        dateEdit, 
        userEdit,
        value,
        viewValue,
        dropDownDef,
        dropDownFilter
    ];
});

minCountInsurance.loadMinCounts(objectType);
attributeRelations.forEach(function (attributeRelation)
{
    var attrId = attributeRelation[4];
    if (minCountInsurance.attributeNotDeletable(attrId))
        attributeRelation[7] = "true";
});

if (getTree)
    attributeRelations = _buildAttributeTree(attributeRelations);
result.object(attributeRelations);
S.Listl's avatar
S.Listl committed
/*
 * loads the parents for a tree
 */
function _buildAttributeTree (pAttrRelations)
{
    //object of attribute ids to avoid duplicates (more than one attribute can have the same parent)
    var attrCatalog = {}; 
    var parentAttributes = [];
    _fetchParentAttributes(pAttrRelations.map(function (row) {return row[2]}), parentAttributes);
    return TreeUtils.sortArrayForTree(parentAttributes, 0, 2).concat(pAttrRelations);
    /*
     * recursive function that loads all superordinate attributes for the tree
     */
    function _fetchParentAttributes (pAttributeIds, pParentAttributes)
S.Listl's avatar
S.Listl committed
    {
        var attributeCond = newSelect("AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME")
                                .from("AB_ATTRIBUTE")
                                .where()
        var nextIds = [];
        pAttributeIds.forEach(function (id)
        {
            if (!(id in this))
                attributeCond.orIfSet("AB_ATTRIBUTE.AB_ATTRIBUTEID", id);
        }, attrCatalog);

        attributeCond.table(true)
            .forEach(function ([attrId, parentId, attrName])
                {
                    this[attrId] = true; //make entry in attrCatalog to avoid duplicates
                    if (parentId)
                        nextIds.push(parentId);

                    pParentAttributes.push([
                        attrId, "", parentId, "", "", "", //0-5
                        translate.text(attrName),  //translate attribute name
                        "true", //7
                        "", "", "", "", "", "", "", "", "" //8-16
                    ]);
                }, attrCatalog);

        if (nextIds.length)
            _fetchParentAttributes(nextIds, pParentAttributes);
S.Listl's avatar
S.Listl committed
    }