diff --git a/entity/Activity_entity/Activity_entity.aod b/entity/Activity_entity/Activity_entity.aod
index 2111de3c013aa4290d97e6981ab24f909e5e57c2..fdb6fb795564c093ceb8b381a8792986cb822700 100644
--- a/entity/Activity_entity/Activity_entity.aod
+++ b/entity/Activity_entity/Activity_entity.aod
@@ -4,6 +4,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Activity_entity/documentation.adoc</documentation>
   <title>Activity</title>
+  <grantDeleteProcess>%aditoprj%/entity/Activity_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Activity_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Activity_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:HOURGLASS_END</iconId>
@@ -114,6 +115,10 @@
           <name>AssignmentTable_param</name>
           <valueProcess>%aditoprj%/entity/Activity_entity/entityfields/documents/children/assignmenttable_param/valueProcess.js</valueProcess>
         </entityParameter>
+        <entityParameter>
+          <name>AssignmentName_param</name>
+          <valueProcess>%aditoprj%/entity/Activity_entity/entityfields/documents/children/assignmentname_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
     <entityConsumer>
diff --git a/entity/Activity_entity/grantDeleteProcess.js b/entity/Activity_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b8b033f79ad04aedecbc9ae7384b631d32c70c24
--- /dev/null
+++ b/entity/Activity_entity/grantDeleteProcess.js
@@ -0,0 +1,5 @@
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("ACTIVITY", null, vars.get("$field.ACTIVITYID")));
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js b/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js
index 23c8a16fb6f2382bdb1dd18ae57bb794268d6ae9..2ac4fdfe746f195614b2929afe827b16af8a8609 100644
--- a/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js
+++ b/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js
@@ -1,13 +1,13 @@
-import("system.translate");
-import("Context_lib");
-import("system.vars");
-import("system.result");
-import("Keyword_lib");
-import("Attribute_lib");
-
-var res = [];
-var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
-var getDropDownFn = type && $AttributeTypes[type] && $AttributeTypes[type].getDropDownDefinitions;
-if (getDropDownFn instanceof Function)
-    res = getDropDownFn.call();
-result.object(res);
+import("system.translate");
+import("Context_lib");
+import("system.vars");
+import("system.result");
+import("Keyword_lib");
+import("Attribute_lib");
+
+var res = [];
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+var getDropDownFn = type && $AttributeTypes[type] && $AttributeTypes[type].getDropDownDefinitions;
+if (getDropDownFn instanceof Function)
+    res = getDropDownFn.call();
+result.object(res);
diff --git a/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js b/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js
index f00cbd82e67e091c167605b83a160416e4b83853..7ef97b2dfac662713a40a02d0974ef2494ae311f 100644
--- a/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js
+++ b/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js
@@ -1,11 +1,11 @@
-import("system.translate");
-import("system.neon");
-import("system.vars");
-import("system.result");
-import("Attribute_lib");
-
-var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
-if (type == $AttributeTypes.KEYWORD)
-    result.string(translate.text("Keyword"));
-else if (type == $AttributeTypes.OBJECTSELECTION)
-    result.string(translate.text("Module"));
+import("system.translate");
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+if (type == $AttributeTypes.KEYWORD)
+    result.string(translate.text("Keyword"));
+else if (type == $AttributeTypes.OBJECTSELECTION)
+    result.string(translate.text("Module"));
diff --git a/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js b/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js
index f00cbd82e67e091c167605b83a160416e4b83853..7ef97b2dfac662713a40a02d0974ef2494ae311f 100644
--- a/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js
+++ b/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js
@@ -1,11 +1,11 @@
-import("system.translate");
-import("system.neon");
-import("system.vars");
-import("system.result");
-import("Attribute_lib");
-
-var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
-if (type == $AttributeTypes.KEYWORD)
-    result.string(translate.text("Keyword"));
-else if (type == $AttributeTypes.OBJECTSELECTION)
-    result.string(translate.text("Module"));
+import("system.translate");
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+if (type == $AttributeTypes.KEYWORD)
+    result.string(translate.text("Keyword"));
+else if (type == $AttributeTypes.OBJECTSELECTION)
+    result.string(translate.text("Module"));
diff --git a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
index 4cd396cf5193d5e94c80d43250d22d0f8eeab41e..e4fd9e63f9acbce13f072c6c5e3be46ed3285263 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
@@ -1,209 +1,209 @@
-import("system.translate");
-import("Util_lib");
-import("JditoFilter_lib");
-import("KeywordRegistry_basic");
-import("Keyword_lib");
-import("system.db");
-import("system.vars");
-import("system.result");
-import("Sql_lib");
-import("Attribute_lib");
-
-var getGroups = vars.exists("$param.GetGroups_param") && vars.get("$param.GetGroups_param");
-var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
-var parentType = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");
-var fetchUsages = true;
-var translateName = false;
-
-var sqlSelect = "select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME, ATTRIBUTE_ACTIVE, DROPDOWNDEFINITION, DROPDOWNFILTER, SORTING, ATTRIBUTE_TYPE, " 
-    + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "ATTRIBUTE_TYPE") //3
-    + ", '', '', '' from AB_ATTRIBUTE"; 
-
-var sqlOrder = " order by ATTRIBUTE_PARENT_ID asc, SORTING asc";
-
-var condition = SqlCondition.begin();
-
-if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
-{
-    condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", vars.get("$local.idvalues"));
-}
-else if (getGroups) //if getGroups == true, it is the lookup for selecting the superordinate attribute
-{
-    //this condition filters out the own id and the children to prevent loops
-    
-    var isGroupCondition = SqlCondition.begin();
-    for (let type in $AttributeTypes)
-        if ($AttributeTypes[type].isGroup)
-        {
-            isGroupCondition.orPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes[type]);
-        }
-    
-    condition.andSqlCondition(SqlCondition.begin()
-        .andSqlCondition(isGroupCondition)
-        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$param.AttrParentId_param", "# != ?")
-        .andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")), null, true)
-    );
-}
-else if (objectType)  //if there's an objectType, it comes from the AttributeRelation entity (lookup for the attribute selection)
-{
-    var filteredAttributes = null;
-    
-    if (vars.exists("$param.AttributeTypes_param") && vars.getString("$param.AttributeTypes_param"))
-        condition.andIn("AB_ATTRIBUTE.ATTRIBUTE_TYPE", JSON.parse(vars.getString("$param.AttributeTypes_param")));
-    
-    if (vars.exists("$param.FilteredAttributeIds_param") && vars.getString("$param.FilteredAttributeIds_param"))
-        filteredAttributes = JSON.parse(vars.getString("$param.FilteredAttributeIds_param"));
-    
-    var attributeCount;
-    if (vars.exists("$param.AttributeCount_param") && vars.get("$param.AttributeCount_param"))
-        attributeCount = JSON.parse(vars.getString("$param.AttributeCount_param"));
-    var ids = AttributeUtil.getPossibleAttributes(objectType, false, filteredAttributes, attributeCount);
-
-    if (ids.length > 0)
-        condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", ids);
-    else  // do not return anything, if parameter is there but an empty array
-        condition.and("1=2");
-
-     fetchUsages = false;
-     translateName = true;
-}
-else if (parentType) //condition for all subordinate attributes of an attribute (for the tree of subordinate attributes in an attribute)
-{
-    if (AttributeTypeUtil.isGroupType(parentType))
-    {
-        var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
-        if (parentId)
-            condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")));
-    }
-    else
-        condition.and("1=2");
-    
-    translateName = true;
-}
-
-//when there are filters selected, add them to the conditon
-if (vars.exists("$local.filter") && vars.get("$local.filter"))
-{
-    var filter = vars.get("$local.filter");
-    if (filter.filter)
-        condition.andSqlCondition(JditoFilterUtils.getSqlCondition(filter.filter, "AB_ATTRIBUTE"));
-}
-
-var usages;
-if (fetchUsages) //this query is only necessary in Attribute, not in AttributeRelation
-{
-    var usagesSelect = "select AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE \n\
-                        join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID";
-    var usageTbl = db.table(condition.buildSql(usagesSelect, "1=1"));
-    usages = {};
-    for (let i = 0, l = usageTbl.length; i < l; i++)
-    {
-        let attrId = usageTbl[i][0];
-        if (attrId in usages)
-            usages[attrId].push(usageTbl[i][1]);
-        else
-            usages[attrId] = [usageTbl[i][1]];
-    }
-}
-
-var attributes = db.table(condition.buildSql(sqlSelect, "1=1", sqlOrder));
-
-var allNames = db.table("select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME from AB_ATTRIBUTE");
-var attrNameData = {};
-for (let i = 0, l = allNames.length; i < l; i++)
-{
-    attrNameData[allNames[i][0]] = [
-        allNames[i][1], 
-        translateName 
-            ? translate.text(allNames[i][2])
-            : allNames[i][2]
-    ];
-}
-var nameCache = {};
-
-result.object(_buildAttributeTable(attributes, usages));
-
-//sorts the records in a way that a tree can be built and adds values
-function _buildAttributeTable (pAttributes, pUsages) 
-{
-    var rows = {};
-    var allIds = {};
-    
-    //fills the allIds object, the object is used for checking if a parent exists in the array
-    for (let i = 0, l = pAttributes.length; i < l; i++)
-        allIds[pAttributes[i][0]] = true;
-    
-    var arrayIndex = 0;
-    
-    do {
-        var oldIndex = arrayIndex;
-        pAttributes.forEach(function (row)
-        {   
-            //item will be added if the id is not already in the object and
-            //the parent is already added (or the parent is not in the array)
-            if (!(row[0] in this) && (row[1] in this || !allIds[row[1]]))
-                this[row[0]] = {
-                    data : row,
-                    index : arrayIndex++
-                };
-        }, rows);
-    } while (oldIndex != arrayIndex); //stops the loop when no new items were added so that recursive relations between attributes don't cause an infinite loop
-    
-    var displaySimpleName = vars.exists("$param.DisplaySimpleName_param") && vars.get("$param.DisplaySimpleName_param");
-    var sortedArray = new Array(Object.keys(rows).length);
-    for (let i in rows)
-    {
-        let rowData = rows[i].data;
-        if (pUsages && rowData[7].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
-        {
-            rowData[9] = pUsages[i].map(function (usage)
-            {
-                return translate.text(usage);
-            }).join(", ");
-        }
-        rowData[10] = _getFullName(rowData[1]); //parent full name
-        rowData[11] = _getFullName(rowData[0], displaySimpleName);
-        sortedArray[rows[i].index] = rowData;
-    }
-    
-    return sortedArray;
-    
-
-    /**
-     * builds the full attribute name from the pre-loaded parent names and adds all parent names
-     * if required
-     */
-    function _getFullName (pAttributeId, pSimpleName)
-    {
-        if (!pAttributeId)
-            return "";
-        var attrId = pAttributeId;
-        var fullName = [];
-        
-        while (attrId)
-        {
-            let name = null;
-            if (attrId in nameCache)
-            {
-                name = nameCache[attrId];
-                attrId = null;
-            }
-            else if (attrId in attrNameData)
-            {
-                name = attrNameData[attrId][1]; 
-                attrId = attrNameData[attrId][0]; //next parent
-            }
-            else
-                attrId = null;
-            if (name)
-                fullName.unshift(name);
-            if (pSimpleName)
-                break;
-        }
-        
-        fullName = fullName.join(" / ");
-        nameCache[pAttributeId] = fullName;
-
-        return fullName;
-    }
-}
+import("system.translate");
+import("Util_lib");
+import("JditoFilter_lib");
+import("KeywordRegistry_basic");
+import("Keyword_lib");
+import("system.db");
+import("system.vars");
+import("system.result");
+import("Sql_lib");
+import("Attribute_lib");
+
+var getGroups = vars.exists("$param.GetGroups_param") && vars.get("$param.GetGroups_param");
+var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
+var parentType = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");
+var fetchUsages = true;
+var translateName = false;
+
+var sqlSelect = "select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME, ATTRIBUTE_ACTIVE, DROPDOWNDEFINITION, DROPDOWNFILTER, SORTING, ATTRIBUTE_TYPE, " 
+    + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "ATTRIBUTE_TYPE") //3
+    + ", '', '', '' from AB_ATTRIBUTE"; 
+
+var sqlOrder = " order by ATTRIBUTE_PARENT_ID asc, SORTING asc";
+
+var condition = SqlCondition.begin();
+
+if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
+{
+    condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", vars.get("$local.idvalues"));
+}
+else if (getGroups) //if getGroups == true, it is the lookup for selecting the superordinate attribute
+{
+    //this condition filters out the own id and the children to prevent loops
+    
+    var isGroupCondition = SqlCondition.begin();
+    for (let type in $AttributeTypes)
+        if ($AttributeTypes[type].isGroup)
+        {
+            isGroupCondition.orPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes[type]);
+        }
+    
+    condition.andSqlCondition(SqlCondition.begin()
+        .andSqlCondition(isGroupCondition)
+        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$param.AttrParentId_param", "# != ?")
+        .andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")), null, true)
+    );
+}
+else if (objectType)  //if there's an objectType, it comes from the AttributeRelation entity (lookup for the attribute selection)
+{
+    var filteredAttributes = null;
+    
+    if (vars.exists("$param.AttributeTypes_param") && vars.getString("$param.AttributeTypes_param"))
+        condition.andIn("AB_ATTRIBUTE.ATTRIBUTE_TYPE", JSON.parse(vars.getString("$param.AttributeTypes_param")));
+    
+    if (vars.exists("$param.FilteredAttributeIds_param") && vars.getString("$param.FilteredAttributeIds_param"))
+        filteredAttributes = JSON.parse(vars.getString("$param.FilteredAttributeIds_param"));
+    
+    var attributeCount;
+    if (vars.exists("$param.AttributeCount_param") && vars.get("$param.AttributeCount_param"))
+        attributeCount = JSON.parse(vars.getString("$param.AttributeCount_param"));
+    var ids = AttributeUtil.getPossibleAttributes(objectType, false, filteredAttributes, attributeCount);
+
+    if (ids.length > 0)
+        condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", ids);
+    else  // do not return anything, if parameter is there but an empty array
+        condition.and("1=2");
+
+     fetchUsages = false;
+     translateName = true;
+}
+else if (parentType) //condition for all subordinate attributes of an attribute (for the tree of subordinate attributes in an attribute)
+{
+    if (AttributeTypeUtil.isGroupType(parentType))
+    {
+        var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
+        if (parentId)
+            condition.andIn("AB_ATTRIBUTE.AB_ATTRIBUTEID", AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")));
+    }
+    else
+        condition.and("1=2");
+    
+    translateName = true;
+}
+
+//when there are filters selected, add them to the conditon
+if (vars.exists("$local.filter") && vars.get("$local.filter"))
+{
+    var filter = vars.get("$local.filter");
+    if (filter.filter)
+        condition.andSqlCondition(JditoFilterUtils.getSqlCondition(filter.filter, "AB_ATTRIBUTE"));
+}
+
+var usages;
+if (fetchUsages) //this query is only necessary in Attribute, not in AttributeRelation
+{
+    var usagesSelect = "select AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE \n\
+                        join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID";
+    var usageTbl = db.table(condition.buildSql(usagesSelect, "1=1"));
+    usages = {};
+    for (let i = 0, l = usageTbl.length; i < l; i++)
+    {
+        let attrId = usageTbl[i][0];
+        if (attrId in usages)
+            usages[attrId].push(usageTbl[i][1]);
+        else
+            usages[attrId] = [usageTbl[i][1]];
+    }
+}
+
+var attributes = db.table(condition.buildSql(sqlSelect, "1=1", sqlOrder));
+
+var allNames = db.table("select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME from AB_ATTRIBUTE");
+var attrNameData = {};
+for (let i = 0, l = allNames.length; i < l; i++)
+{
+    attrNameData[allNames[i][0]] = [
+        allNames[i][1], 
+        translateName 
+            ? translate.text(allNames[i][2])
+            : allNames[i][2]
+    ];
+}
+var nameCache = {};
+
+result.object(_buildAttributeTable(attributes, usages));
+
+//sorts the records in a way that a tree can be built and adds values
+function _buildAttributeTable (pAttributes, pUsages) 
+{
+    var rows = {};
+    var allIds = {};
+    
+    //fills the allIds object, the object is used for checking if a parent exists in the array
+    for (let i = 0, l = pAttributes.length; i < l; i++)
+        allIds[pAttributes[i][0]] = true;
+    
+    var arrayIndex = 0;
+    
+    do {
+        var oldIndex = arrayIndex;
+        pAttributes.forEach(function (row)
+        {   
+            //item will be added if the id is not already in the object and
+            //the parent is already added (or the parent is not in the array)
+            if (!(row[0] in this) && (row[1] in this || !allIds[row[1]]))
+                this[row[0]] = {
+                    data : row,
+                    index : arrayIndex++
+                };
+        }, rows);
+    } while (oldIndex != arrayIndex); //stops the loop when no new items were added so that recursive relations between attributes don't cause an infinite loop
+    
+    var displaySimpleName = vars.exists("$param.DisplaySimpleName_param") && vars.get("$param.DisplaySimpleName_param");
+    var sortedArray = new Array(Object.keys(rows).length);
+    for (let i in rows)
+    {
+        let rowData = rows[i].data;
+        if (pUsages && rowData[7].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
+        {
+            rowData[9] = pUsages[i].map(function (usage)
+            {
+                return translate.text(usage);
+            }).join(", ");
+        }
+        rowData[10] = _getFullName(rowData[1]); //parent full name
+        rowData[11] = _getFullName(rowData[0], displaySimpleName);
+        sortedArray[rows[i].index] = rowData;
+    }
+    
+    return sortedArray;
+    
+
+    /**
+     * builds the full attribute name from the pre-loaded parent names and adds all parent names
+     * if required
+     */
+    function _getFullName (pAttributeId, pSimpleName)
+    {
+        if (!pAttributeId)
+            return "";
+        var attrId = pAttributeId;
+        var fullName = [];
+        
+        while (attrId)
+        {
+            let name = null;
+            if (attrId in nameCache)
+            {
+                name = nameCache[attrId];
+                attrId = null;
+            }
+            else if (attrId in attrNameData)
+            {
+                name = attrNameData[attrId][1]; 
+                attrId = attrNameData[attrId][0]; //next parent
+            }
+            else
+                attrId = null;
+            if (name)
+                fullName.unshift(name);
+            if (pSimpleName)
+                break;
+        }
+        
+        fullName = fullName.join(" / ");
+        nameCache[pAttributeId] = fullName;
+
+        return fullName;
+    }
+}
diff --git a/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js b/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
index 12ab6ce802c360e2ca62e9ce4ac7f26e6f6e2b74..cc709a73a6100b8a5d991061e5d1119aa18f4092 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
@@ -1,26 +1,27 @@
-import("Sql_lib");
-import("system.db");
-import("system.vars");
-
-var rowdata = vars.get("$local.rowdata");
-var columns = [
-    "ATTRIBUTE_ACTIVE",
-    "ATTRIBUTE_NAME",
-    "ATTRIBUTE_PARENT_ID",
-    "ATTRIBUTE_TYPE",
-    "DROPDOWNDEFINITION",
-    "DROPDOWNFILTER",
-    "SORTING"
-];
-var values = [
-    rowdata["ATTRIBUTE_ACTIVE.value"] || "",
-    rowdata["ATTRIBUTE_NAME.value"] || "",
-    rowdata["ATTRIBUTE_PARENT_ID.value"] || "",
-    rowdata["ATTRIBUTE_TYPE.value"] || "",
-    rowdata["DROPDOWNDEFINITION.value"] || "",
-    rowdata["DROPDOWNFILTER.value"] || "",
-    rowdata["SORTING.value"] || ""
-];
-
-db.updateData("AB_ATTRIBUTE", columns, null, values, 
+import("system.logging");
+import("Sql_lib");
+import("system.db");
+import("system.vars");
+
+var rowdata = vars.get("$local.rowdata");
+var columns = [
+    "ATTRIBUTE_ACTIVE",
+    "ATTRIBUTE_NAME",
+    "ATTRIBUTE_PARENT_ID",
+    "ATTRIBUTE_TYPE",
+    "DROPDOWNDEFINITION",
+    "DROPDOWNFILTER",
+    "SORTING"
+];
+var values = [
+    rowdata["ATTRIBUTE_ACTIVE.value"] || "",
+    rowdata["ATTRIBUTE_NAME.value"] || "",
+    rowdata["ATTRIBUTE_PARENT_ID.value"] || "",
+    rowdata["ATTRIBUTE_TYPE.value"] || "",
+    rowdata["DROPDOWNDEFINITION.value"] || "",
+    rowdata["DROPDOWNFILTER.value"] || "",
+    rowdata["SORTING.value"] || ""
+];
+logging.log(JSON.stringify(values, null, "\t"))
+db.updateData("AB_ATTRIBUTE", columns, null, values, 
     SqlCondition.equals("AB_ATTRIBUTE.AB_ATTRIBUTEID", vars.get("$field.UID"), "1=2"));
\ No newline at end of file
diff --git a/entity/CampaignAddParticipants_entity/recordcontainers/jdito/onInsert.js b/entity/CampaignAddParticipants_entity/recordcontainers/jdito/onInsert.js
index 12f66113e1ae398eec2ebdb19e6f337bbee03500..81aeb47b23e5a0d9fe087f701064397826b41c3a 100644
--- a/entity/CampaignAddParticipants_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/CampaignAddParticipants_entity/recordcontainers/jdito/onInsert.js
@@ -1,3 +1,4 @@
+import("system.neon");
 import("Sql_lib");
 import("system.vars");
 import("system.db");
@@ -31,7 +32,8 @@ else
     _handleCondition(campaignId, conditionSourceTableName, participantCondition);
 }
 
-
+if (!vars.exists("$param.currentCampaignId_param") || !vars.get("$param.currentCampaignId_param"))
+    neon.openContext("Campaign", "CampaignMain_view", [campaignId], neon.OPERATINGSTATE_VIEW, null);
 
 function _handleCondition(pCampaignId, pTargetTableName, pCondition)
 {
diff --git a/entity/CampaignStep_entity/CampaignStep_entity.aod b/entity/CampaignStep_entity/CampaignStep_entity.aod
index 76a4c4cdb8f82ae577c0bce945d3914c644f1427..8a985edb72bae272bec080a875477ba4926e44fb 100644
--- a/entity/CampaignStep_entity/CampaignStep_entity.aod
+++ b/entity/CampaignStep_entity/CampaignStep_entity.aod
@@ -1,485 +1,486 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
-  <name>CampaignStep_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <icon>NEON:GROUP_APPOINTMENT</icon>
-  <title>Campaign Step</title>
-  <siblings>
-    <element>CampaignPlanning_entity</element>
-    <element>Campaign_entity</element>
-  </siblings>
-  <contentTitleProcess>%aditoprj%/entity/CampaignStep_entity/contentTitleProcess.js</contentTitleProcess>
-  <onValidation>%aditoprj%/entity/CampaignStep_entity/onValidation.js</onValidation>
-  <imageProcess>%aditoprj%/entity/CampaignStep_entity/imageProcess.js</imageProcess>
-  <titlePlural>Steps</titlePlural>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-      <dependencies>
-        <entityDependency>
-          <name>13f82959-7e04-449f-a657-c34f6b97f3be</name>
-          <entityName>Object_entity</entityName>
-          <fieldName>CampaignSteps</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-    </entityProvider>
-    <entityField>
-      <name>CAMPAIGNSTEPID</name>
-      <mandatory v="true" />
-    </entityField>
-    <entityField>
-      <name>CAMPAIGN_ID</name>
-      <title>Campaign</title>
-      <consumer>CampaignConsumer</consumer>
-      <linkedContext>Campaign</linkedContext>
-      <mandatory v="true" />
-      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-        <element>PROCESS_SETVALUE</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityField>
-      <name>EMPLOYEE_CONTACT_ID</name>
-      <title>Responsible</title>
-      <consumer>Employees</consumer>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/employee_contact_id/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/employee_contact_id/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityField>
-      <name>NAME</name>
-      <title>Name</title>
-      <mandatory v="true" />
-    </entityField>
-    <entityField>
-      <name>DATE_START</name>
-      <title>Begin</title>
-      <contentType>DATE</contentType>
-      <resolution>DAY</resolution>
-      <outputFormat>dd.MM.yyyy</outputFormat>
-      <inputFormat>dd.MM.yyyy</inputFormat>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_start/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DATE_END</name>
-      <title>End</title>
-      <contentType>DATE</contentType>
-      <resolution>DAY</resolution>
-      <outputFormat>dd.MM.yyyy</outputFormat>
-      <inputFormat>dd.MM.yyyy</inputFormat>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_end/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>STATUS</name>
-      <title>Status</title>
-      <consumer>KeywordStates</consumer>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/status/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/status/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityField>
-      <name>SORTING</name>
-      <title>Sorting</title>
-      <contentType>NUMBER</contentType>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/sorting/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>USER_NEW</name>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/user_new/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DATE_NEW</name>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_new/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>USER_EDIT</name>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/user_edit/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DATE_EDIT</name>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_edit/valueProcess.js</valueProcess>
-    </entityField>
-    <entityProvider>
-      <name>CampaignSteps</name>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>421e6cc2-f874-4834-b022-fe1b253d50af</name>
-          <entityName>Campaign_entity</entityName>
-          <fieldName>CampaignSteps</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>7f1c046b-0e8f-429e-a0a6-3322382c61d4</name>
-          <entityName>CampaignParticipant_entity</entityName>
-          <fieldName>CampaignSteps</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>eedc7b17-af98-4ffb-b527-97835cf8f903</name>
-          <entityName>CampaignAddParticipants_entity</entityName>
-          <fieldName>CampaignStepConsumer</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>ad4ee503-95b9-4add-a0ef-e833db008349</name>
-          <entityName>CampaignCost_entity</entityName>
-          <fieldName>CampaignSteps</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>3fde1e51-cc4c-4727-b4e7-fd30bed1ee04</name>
-          <entityName>Campaign_entity</entityName>
-          <fieldName>CampaignStepsReadonly</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>db1a63f3-753b-423d-9ab9-db3d03315dc6</name>
-          <entityName>CampaignStep_entity</entityName>
-          <fieldName>CampaignStepsConsumer</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>campaignId_param</name>
-          <expose v="true" />
-          <mandatory v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>campaignId_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>KeywordStates</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/keywordstates/children/containername_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>MAXPARTICIPANTS</name>
-      <title>Max participants</title>
-      <contentType>NUMBER</contentType>
-      <mandatory v="true" />
-      <onValidation>%aditoprj%/entity/CampaignStep_entity/entityfields/maxparticipants/onValidation.js</onValidation>
-    </entityField>
-    <entityConsumer>
-      <name>CampaignParticipantsConsumer</name>
-      <selectionMode>MULTI</selectionMode>
-      <dependency>
-        <name>dependency</name>
-        <entityName>CampaignParticipant_entity</entityName>
-        <fieldName>CampaignParticipantsProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>CampaignId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignparticipantsconsumer/children/campaignid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>CampaignStepId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignparticipantsconsumer/children/campaignstepid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>CurrentMaxParticipantsInfo</name>
-      <title>Participants</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/currentmaxparticipantsinfo/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>CampaignStatus</name>
-      <title>Campaign status</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstatus/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DESCRIPTION</name>
-      <title>Description</title>
-      <contentType>LONG_TEXT</contentType>
-    </entityField>
-    <entityConsumer>
-      <name>Employees</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Employee_entity</entityName>
-        <fieldName>Employees</fieldName>
-      </dependency>
-    </entityConsumer>
-    <entityConsumer>
-      <name>CampaignStepCosts</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>CampaignCost_entity</entityName>
-        <fieldName>StepCosts</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>CampaignId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepcosts/children/campaignid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>CampaignStepId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepcosts/children/campaignstepid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>COST</name>
-      <title>Cost</title>
-      <contentType>NUMBER</contentType>
-      <outputFormat>#,##0.00</outputFormat>
-      <inputFormat>#,##0.00</inputFormat>
-    </entityField>
-    <entityConsumer>
-      <name>CampaignConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Campaign_entity</entityName>
-        <fieldName>Campaigns</fieldName>
-      </dependency>
-    </entityConsumer>
-    <entityConsumer>
-      <name>Activities</name>
-      <title>Activities</title>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Activity_entity</entityName>
-        <fieldName>LinkedObjects</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>RowId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/activities/children/rowid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ObjectId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/activities/children/objectid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityConsumer>
-      <name>Tasks</name>
-      <title>Tasks</title>
-      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/stateProcess.js</stateProcess>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Task_entity</entityName>
-        <fieldName>Tasks</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>RowId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/children/rowid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ObjectId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/children/objectid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityActionField>
-      <name>newActivity</name>
-      <title>New activity</title>
-      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newactivity/onActionProcess.js</onActionProcess>
-      <iconId>VAADIN:HOURGLASS</iconId>
-      <tooltip>New activity</tooltip>
-      <tooltipProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newactivity/tooltipProcess.js</tooltipProcess>
-    </entityActionField>
-    <entityActionField>
-      <name>newTask</name>
-      <title>New task</title>
-      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newtask/onActionProcess.js</onActionProcess>
-      <iconId>VAADIN:TASKS</iconId>
-    </entityActionField>
-    <entityField>
-      <name>PREDECESSORSTEP_ID</name>
-      <title>Predecessor</title>
-      <color></color>
-      <consumer>CampaignStepsConsumer</consumer>
-      <textInputAllowed v="true" />
-      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/predecessorstep_id/stateProcess.js</stateProcess>
-      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/predecessorstep_id/displayValueProcess.js</displayValueProcess>
-      <onValueChangeTypes>
-        <element>MASK</element>
-        <element>PROCESS</element>
-        <element>PROCESS_SETVALUE</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityConsumer>
-      <name>CampaignStepsConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>CampaignStep_entity</entityName>
-        <fieldName>CampaignSteps</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>campaignId_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepsconsumer/children/campaignid_param/valueProcess.js</valueProcess>
-          <mandatory v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>maxSort_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepsconsumer/children/maxsort_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>CampaignName</name>
-      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignname/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>campaignSelectionVisible_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>CampaignStepMedium</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepmedium/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>STEPMEDIUM</name>
-      <title>Medium</title>
-      <consumer>CampaignStepMedium</consumer>
-      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/stepmedium/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityActionField>
-      <name>newBulkMail</name>
-      <title>Write bulk mail</title>
-      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newbulkmail/onActionProcess.js</onActionProcess>
-      <iconId>VAADIN:AT</iconId>
-    </entityActionField>
-    <entityParameter>
-      <name>maxSort_param</name>
-      <expose v="true" />
-    </entityParameter>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <conditionProcess>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <orderClauseProcess>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <linkInformation>
-        <linkInformation>
-          <name>b039db2c-3988-42a0-9257-9689b1eb4e58</name>
-          <tableName>CAMPAIGNSTEP</tableName>
-          <primaryKey>CAMPAIGNSTEPID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>CAMPAIGN_ID.value</name>
-          <recordfield>CAMPAIGNSTEP.CAMPAIGN_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_EDIT.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_EDIT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_END.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_END</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_NEW.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_NEW</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_START.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_START</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>EMPLOYEE_CONTACT_ID.value</name>
-          <recordfield>CAMPAIGNSTEP.EMPLOYEE_CONTACT_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>NAME.value</name>
-          <recordfield>CAMPAIGNSTEP.NAME</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>SORTING.value</name>
-          <recordfield>CAMPAIGNSTEP.SORTING</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>STATUS.value</name>
-          <recordfield>CAMPAIGNSTEP.STATUS</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>USER_EDIT.value</name>
-          <recordfield>CAMPAIGNSTEP.USER_EDIT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>USER_NEW.value</name>
-          <recordfield>CAMPAIGNSTEP.USER_NEW</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>STATUS.displayValue</name>
-          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>MAXPARTICIPANTS.value</name>
-          <recordfield>CAMPAIGNSTEP.MAXPARTICIPANTS</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CAMPAIGNSTEPID.value</name>
-          <recordfield>CAMPAIGNSTEP.CAMPAIGNSTEPID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DESCRIPTION.value</name>
-          <recordfield>CAMPAIGNSTEP.DESCRIPTION</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>COST.value</name>
-          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/cost.value/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CAMPAIGN_ID.displayValue</name>
-          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/campaign_id.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PREDECESSORSTEP_ID.value</name>
-          <recordfield>CAMPAIGNSTEP.PREDECESSORSTEP_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>STEPMEDIUM.value</name>
-          <recordfield>CAMPAIGNSTEP.STEPMEDIUM</recordfield>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
+  <name>CampaignStep_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <icon>NEON:GROUP_APPOINTMENT</icon>
+  <title>Campaign Step</title>
+  <siblings>
+    <element>CampaignPlanning_entity</element>
+    <element>Campaign_entity</element>
+  </siblings>
+  <grantDeleteProcess>%aditoprj%/entity/CampaignStep_entity/grantDeleteProcess.js</grantDeleteProcess>
+  <contentTitleProcess>%aditoprj%/entity/CampaignStep_entity/contentTitleProcess.js</contentTitleProcess>
+  <onValidation>%aditoprj%/entity/CampaignStep_entity/onValidation.js</onValidation>
+  <imageProcess>%aditoprj%/entity/CampaignStep_entity/imageProcess.js</imageProcess>
+  <titlePlural>Steps</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <dependencies>
+        <entityDependency>
+          <name>13f82959-7e04-449f-a657-c34f6b97f3be</name>
+          <entityName>Object_entity</entityName>
+          <fieldName>CampaignSteps</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityField>
+      <name>CAMPAIGNSTEPID</name>
+      <mandatory v="true" />
+    </entityField>
+    <entityField>
+      <name>CAMPAIGN_ID</name>
+      <title>Campaign</title>
+      <consumer>CampaignConsumer</consumer>
+      <linkedContext>Campaign</linkedContext>
+      <mandatory v="true" />
+      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/CampaignStep_entity/entityfields/campaign_id/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS_SETVALUE</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>EMPLOYEE_CONTACT_ID</name>
+      <title>Responsible</title>
+      <consumer>Employees</consumer>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/employee_contact_id/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/employee_contact_id/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>NAME</name>
+      <title>Name</title>
+      <mandatory v="true" />
+    </entityField>
+    <entityField>
+      <name>DATE_START</name>
+      <title>Begin</title>
+      <contentType>DATE</contentType>
+      <resolution>DAY</resolution>
+      <outputFormat>dd.MM.yyyy</outputFormat>
+      <inputFormat>dd.MM.yyyy</inputFormat>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_start/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DATE_END</name>
+      <title>End</title>
+      <contentType>DATE</contentType>
+      <resolution>DAY</resolution>
+      <outputFormat>dd.MM.yyyy</outputFormat>
+      <inputFormat>dd.MM.yyyy</inputFormat>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_end/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>STATUS</name>
+      <title>Status</title>
+      <consumer>KeywordStates</consumer>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/status/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/status/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>SORTING</name>
+      <title>Sorting</title>
+      <contentType>NUMBER</contentType>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/sorting/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>USER_NEW</name>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/user_new/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DATE_NEW</name>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_new/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>USER_EDIT</name>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/user_edit/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DATE_EDIT</name>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/date_edit/valueProcess.js</valueProcess>
+    </entityField>
+    <entityProvider>
+      <name>CampaignSteps</name>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>421e6cc2-f874-4834-b022-fe1b253d50af</name>
+          <entityName>Campaign_entity</entityName>
+          <fieldName>CampaignSteps</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>7f1c046b-0e8f-429e-a0a6-3322382c61d4</name>
+          <entityName>CampaignParticipant_entity</entityName>
+          <fieldName>CampaignSteps</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>eedc7b17-af98-4ffb-b527-97835cf8f903</name>
+          <entityName>CampaignAddParticipants_entity</entityName>
+          <fieldName>CampaignStepConsumer</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>ad4ee503-95b9-4add-a0ef-e833db008349</name>
+          <entityName>CampaignCost_entity</entityName>
+          <fieldName>CampaignSteps</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>3fde1e51-cc4c-4727-b4e7-fd30bed1ee04</name>
+          <entityName>Campaign_entity</entityName>
+          <fieldName>CampaignStepsReadonly</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>db1a63f3-753b-423d-9ab9-db3d03315dc6</name>
+          <entityName>CampaignStep_entity</entityName>
+          <fieldName>CampaignStepsConsumer</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>campaignId_param</name>
+          <expose v="true" />
+          <mandatory v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>campaignId_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>KeywordStates</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/keywordstates/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>MAXPARTICIPANTS</name>
+      <title>Max participants</title>
+      <contentType>NUMBER</contentType>
+      <mandatory v="true" />
+      <onValidation>%aditoprj%/entity/CampaignStep_entity/entityfields/maxparticipants/onValidation.js</onValidation>
+    </entityField>
+    <entityConsumer>
+      <name>CampaignParticipantsConsumer</name>
+      <selectionMode>MULTI</selectionMode>
+      <dependency>
+        <name>dependency</name>
+        <entityName>CampaignParticipant_entity</entityName>
+        <fieldName>CampaignParticipantsProvider</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>CampaignId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignparticipantsconsumer/children/campaignid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>CampaignStepId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignparticipantsconsumer/children/campaignstepid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>CurrentMaxParticipantsInfo</name>
+      <title>Participants</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/currentmaxparticipantsinfo/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>CampaignStatus</name>
+      <title>Campaign status</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstatus/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DESCRIPTION</name>
+      <title>Description</title>
+      <contentType>LONG_TEXT</contentType>
+    </entityField>
+    <entityConsumer>
+      <name>Employees</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Employee_entity</entityName>
+        <fieldName>Employees</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>CampaignStepCosts</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>CampaignCost_entity</entityName>
+        <fieldName>StepCosts</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>CampaignId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepcosts/children/campaignid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>CampaignStepId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepcosts/children/campaignstepid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>COST</name>
+      <title>Cost</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>#,##0.00</outputFormat>
+      <inputFormat>#,##0.00</inputFormat>
+    </entityField>
+    <entityConsumer>
+      <name>CampaignConsumer</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Campaign_entity</entityName>
+        <fieldName>Campaigns</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Activities</name>
+      <title>Activities</title>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Activity_entity</entityName>
+        <fieldName>LinkedObjects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>RowId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/activities/children/rowid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>ObjectId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/activities/children/objectid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Tasks</name>
+      <title>Tasks</title>
+      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/stateProcess.js</stateProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Task_entity</entityName>
+        <fieldName>Tasks</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>RowId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/children/rowid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>ObjectId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/tasks/children/objectid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityActionField>
+      <name>newActivity</name>
+      <title>New activity</title>
+      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newactivity/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:HOURGLASS</iconId>
+      <tooltip>New activity</tooltip>
+      <tooltipProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newactivity/tooltipProcess.js</tooltipProcess>
+    </entityActionField>
+    <entityActionField>
+      <name>newTask</name>
+      <title>New task</title>
+      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newtask/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:TASKS</iconId>
+    </entityActionField>
+    <entityField>
+      <name>PREDECESSORSTEP_ID</name>
+      <title>Predecessor</title>
+      <color></color>
+      <consumer>CampaignStepsConsumer</consumer>
+      <textInputAllowed v="true" />
+      <stateProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/predecessorstep_id/stateProcess.js</stateProcess>
+      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/predecessorstep_id/displayValueProcess.js</displayValueProcess>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+        <element>PROCESS_SETVALUE</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityConsumer>
+      <name>CampaignStepsConsumer</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>CampaignStep_entity</entityName>
+        <fieldName>CampaignSteps</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>campaignId_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepsconsumer/children/campaignid_param/valueProcess.js</valueProcess>
+          <mandatory v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>maxSort_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepsconsumer/children/maxsort_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>CampaignName</name>
+      <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignname/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>campaignSelectionVisible_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>CampaignStepMedium</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/campaignstepmedium/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>STEPMEDIUM</name>
+      <title>Medium</title>
+      <consumer>CampaignStepMedium</consumer>
+      <displayValueProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/stepmedium/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityActionField>
+      <name>newBulkMail</name>
+      <title>Write bulk mail</title>
+      <onActionProcess>%aditoprj%/entity/CampaignStep_entity/entityfields/newbulkmail/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:AT</iconId>
+    </entityActionField>
+    <entityParameter>
+      <name>maxSort_param</name>
+      <expose v="true" />
+    </entityParameter>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
+      <linkInformation>
+        <linkInformation>
+          <name>b039db2c-3988-42a0-9257-9689b1eb4e58</name>
+          <tableName>CAMPAIGNSTEP</tableName>
+          <primaryKey>CAMPAIGNSTEPID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>CAMPAIGN_ID.value</name>
+          <recordfield>CAMPAIGNSTEP.CAMPAIGN_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DATE_EDIT.value</name>
+          <recordfield>CAMPAIGNSTEP.DATE_EDIT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DATE_END.value</name>
+          <recordfield>CAMPAIGNSTEP.DATE_END</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DATE_NEW.value</name>
+          <recordfield>CAMPAIGNSTEP.DATE_NEW</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DATE_START.value</name>
+          <recordfield>CAMPAIGNSTEP.DATE_START</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>EMPLOYEE_CONTACT_ID.value</name>
+          <recordfield>CAMPAIGNSTEP.EMPLOYEE_CONTACT_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>NAME.value</name>
+          <recordfield>CAMPAIGNSTEP.NAME</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SORTING.value</name>
+          <recordfield>CAMPAIGNSTEP.SORTING</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.value</name>
+          <recordfield>CAMPAIGNSTEP.STATUS</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>USER_EDIT.value</name>
+          <recordfield>CAMPAIGNSTEP.USER_EDIT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>USER_NEW.value</name>
+          <recordfield>CAMPAIGNSTEP.USER_NEW</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.displayValue</name>
+          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>MAXPARTICIPANTS.value</name>
+          <recordfield>CAMPAIGNSTEP.MAXPARTICIPANTS</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CAMPAIGNSTEPID.value</name>
+          <recordfield>CAMPAIGNSTEP.CAMPAIGNSTEPID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DESCRIPTION.value</name>
+          <recordfield>CAMPAIGNSTEP.DESCRIPTION</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>COST.value</name>
+          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/cost.value/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CAMPAIGN_ID.displayValue</name>
+          <expression>%aditoprj%/entity/CampaignStep_entity/recordcontainers/db/recordfieldmappings/campaign_id.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PREDECESSORSTEP_ID.value</name>
+          <recordfield>CAMPAIGNSTEP.PREDECESSORSTEP_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STEPMEDIUM.value</name>
+          <recordfield>CAMPAIGNSTEP.STEPMEDIUM</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/CampaignStep_entity/grantDeleteProcess.js b/entity/CampaignStep_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..87f22c8c68e951b1986bc106010ce589753244be
--- /dev/null
+++ b/entity/CampaignStep_entity/grantDeleteProcess.js
@@ -0,0 +1,7 @@
+import("Context_lib");
+import("system.vars");
+import("ActivityTask_lib");
+import("system.result");
+
+result.string(!TaskUtils.hasTasks(vars.get("$field.CAMPAIGNSTEPID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.CAMPAIGNSTEPID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Campaign_entity/Campaign_entity.aod b/entity/Campaign_entity/Campaign_entity.aod
index 1b3a4609cc16c2e524dd3299e527af15c60096b7..6fdce8ab9b250b8e55c297bbf290d7a81654cb2c 100644
--- a/entity/Campaign_entity/Campaign_entity.aod
+++ b/entity/Campaign_entity/Campaign_entity.aod
@@ -10,6 +10,7 @@
     <element>CampaignCostChart_entity</element>
     <element>CampaignStep_entity</element>
   </siblings>
+  <grantDeleteProcess>%aditoprj%/entity/Campaign_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Campaign_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Campaign_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:GROUP</iconId>
diff --git a/entity/Campaign_entity/grantDeleteProcess.js b/entity/Campaign_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8f6dbd3f5f48448ca0c78b7240fbbd715828a6bd
--- /dev/null
+++ b/entity/Campaign_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("CAMPAIGN", null, vars.get("$field.CAMPAIGNID"))
+    && !TaskUtils.hasTasks(vars.get("$field.CAMPAIGNID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.CAMPAIGNID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Contract_entity/Contract_entity.aod b/entity/Contract_entity/Contract_entity.aod
index d8e64f5aacd76dce17ca86d5cafe8414cde1308f..52283a9db64a6e7fb6d341afbd64cd2076ce3bf8 100644
--- a/entity/Contract_entity/Contract_entity.aod
+++ b/entity/Contract_entity/Contract_entity.aod
@@ -4,6 +4,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Contract_entity/documentation.adoc</documentation>
   <title>Contract</title>
+  <grantDeleteProcess>%aditoprj%/entity/Contract_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Contract_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Contract_entity/afterUiInit.js</afterUiInit>
   <onValidation>%aditoprj%/entity/Contract_entity/onValidation.js</onValidation>
diff --git a/entity/Contract_entity/grantDeleteProcess.js b/entity/Contract_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..36b39de07882145d3528ad277b799a36d79c4a6e
--- /dev/null
+++ b/entity/Contract_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("CONTRACT", null, vars.get("$field.CONTRACTID"))
+    && !TaskUtils.hasTasks(vars.get("$field.CONTRACTID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.CONTRACTID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Employee_entity/Employee_entity.aod b/entity/Employee_entity/Employee_entity.aod
index fa2500aaca97890966d3dc7ff913a04b4f892a96..48596c9e3a434b7102b63019862647e6cf67b042 100644
--- a/entity/Employee_entity/Employee_entity.aod
+++ b/entity/Employee_entity/Employee_entity.aod
@@ -3,6 +3,7 @@
   <name>Employee_entity</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <title>Employee</title>
+  <grantDeleteProcess>%aditoprj%/entity/Employee_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Employee_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Employee_entity/afterUiInit.js</afterUiInit>
   <onValidation>%aditoprj%/entity/Employee_entity/onValidation.js</onValidation>
diff --git a/entity/Employee_entity/grantDeleteProcess.js b/entity/Employee_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b60872d672ceaa4a6670cf90bc7c25fabc3e3fb2
--- /dev/null
+++ b/entity/Employee_entity/grantDeleteProcess.js
@@ -0,0 +1,6 @@
+import("Employee_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("EMPLOYEE", null, EmployeeUtils.sliceUserId(vars.get("$field.UID"))));
\ No newline at end of file
diff --git a/entity/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod b/entity/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod
index 4078a79be269559d5cecb18c579432400c64b629..7874f23b68bb2d007282f29ff3e607c266132325 100644
--- a/entity/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod
+++ b/entity/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod
@@ -1,174 +1,169 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
-  <name>KeywordAttributeRelation_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/KeywordAttributeRelation_entity/documentation.adoc</documentation>
-  <title>Keyword Attribute Values</title>
-  <titlePlural>Keyword Attribute Values</titlePlural>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>AB_KEYWORD_ATTRIBUTERELATIONID</name>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attributerelationid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>CHAR_VALUE</name>
-      <title>CHAR_VALUE</title>
-    </entityField>
-    <entityField>
-      <name>NUMBER_VALUE</name>
-      <contentType>NUMBER</contentType>
-    </entityField>
-    <entityField>
-      <name>BOOL_VALUE</name>
-      <contentType>BOOLEAN</contentType>
-    </entityField>
-    <entityField>
-      <name>AB_KEYWORD_ATTRIBUTE_ID</name>
-      <title>Keyword Attribute</title>
-      <consumer>KeywordAttributes</consumer>
-      <mandatory v="true" />
-      <displayValueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attribute_id/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attribute_id/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-        <element>PROCESS_SETVALUE</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityField>
-      <name>AB_KEYWORD_ENTRY_ID</name>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_entry_id/valueProcess.js</valueProcess>
-    </entityField>
-    <entityProvider>
-      <name>AttributesForKeywordEntry</name>
-      <titlePlural></titlePlural>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>490d12c0-6ace-42e5-89e1-d40b25322161</name>
-          <entityName>KeywordEntry_entity</entityName>
-          <fieldName>KeywordAttributeRelations</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>53b35858-7c81-429c-9e06-0362f567ad42</name>
-          <entityName>KeywordEntry_entity</entityName>
-          <fieldName>KeywordAttributeRelationsReadOnly</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>KeywordEntryId_param</name>
-          <expose v="true" />
-          <mandatory v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>ContainerName_param</name>
-      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/containername_param/valueProcess.js</valueProcess>
-      <mandatory v="false" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>KeywordAttributes</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordAttribute_entity</entityName>
-        <fieldName>SpecificContainerKeyword</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>FilterAlreadyUsedByEntryId_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityParameter>
-      <name>KeywordEntryId_param</name>
-      <expose v="true" />
-      <mandatory v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>valueProxy</name>
-      <documentation>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/documentation.adoc</documentation>
-      <title>Value</title>
-      <contentTypeProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js</contentTypeProcess>
-      <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/valueProcess.js</valueProcess>
-      <onValueChange>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/onValueChange.js</onValueChange>
-    </entityField>
-    <entityField>
-      <name>attributeType</name>
-      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/attributetype/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>LONG_CHAR_VALUE</name>
-    </entityField>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <isPageable v="false" />
-      <isRequireContainerFiltering v="false" />
-      <conditionProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <linkInformation>
-        <linkInformation>
-          <name>8e2938d2-e14b-403b-8ae5-875f70bc3f85</name>
-          <tableName>AB_KEYWORD_ATTRIBUTERELATION</tableName>
-          <primaryKey>AB_KEYWORD_ATTRIBUTERELATIONID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ATTRIBUTERELATIONID.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTERELATIONID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>BOOL_VALUE.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.BOOL_VALUE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CHAR_VALUE.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.CHAR_VALUE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>NUMBER_VALUE.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.NUMBER_VALUE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ATTRIBUTE_ID.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ENTRY_ID.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ATTRIBUTE_ID.displayValue</name>
-          <expression>%aditoprj%/entity/KeywordAttributeRelation_entity/recordcontainers/db/recordfieldmappings/ab_keyword_attribute_id.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>LONG_CHAR_VALUE.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.LONG_CHAR_VALUE</recordfield>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
+  <name>KeywordAttributeRelation_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/KeywordAttributeRelation_entity/documentation.adoc</documentation>
+  <title>Keyword Attribute Values</title>
+  <titlePlural>Keyword Attribute Values</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>AB_KEYWORD_ATTRIBUTERELATIONID</name>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attributerelationid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>CHAR_VALUE</name>
+      <title>CHAR_VALUE</title>
+    </entityField>
+    <entityField>
+      <name>NUMBER_VALUE</name>
+      <contentType>NUMBER</contentType>
+    </entityField>
+    <entityField>
+      <name>BOOL_VALUE</name>
+      <contentType>BOOLEAN</contentType>
+    </entityField>
+    <entityField>
+      <name>AB_KEYWORD_ATTRIBUTE_ID</name>
+      <title>Keyword Attribute</title>
+      <consumer>KeywordAttributes</consumer>
+      <mandatory v="true" />
+      <displayValueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attribute_id/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_attribute_id/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS_SETVALUE</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>AB_KEYWORD_ENTRY_ID</name>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/ab_keyword_entry_id/valueProcess.js</valueProcess>
+    </entityField>
+    <entityProvider>
+      <name>AttributesForKeywordEntry</name>
+      <titlePlural></titlePlural>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>490d12c0-6ace-42e5-89e1-d40b25322161</name>
+          <entityName>KeywordEntry_entity</entityName>
+          <fieldName>KeywordAttributeRelations</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>KeywordEntryId_param</name>
+          <expose v="true" />
+          <mandatory v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>ContainerName_param</name>
+      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/containername_param/valueProcess.js</valueProcess>
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>KeywordAttributes</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordAttribute_entity</entityName>
+        <fieldName>SpecificContainerKeyword</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>FilterAlreadyUsedByEntryId_param</name>
+          <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+          <documentation>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/documentation.adoc</documentation>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityParameter>
+      <name>KeywordEntryId_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>valueProxy</name>
+      <documentation>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/documentation.adoc</documentation>
+      <title>Value</title>
+      <contentTypeProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js</contentTypeProcess>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/valueProcess.js</valueProcess>
+      <onValueChange>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/valueproxy/onValueChange.js</onValueChange>
+    </entityField>
+    <entityField>
+      <name>attributeType</name>
+      <valueProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/entityfields/attributetype/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>LONG_CHAR_VALUE</name>
+    </entityField>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <isPageable v="false" />
+      <isRequireContainerFiltering v="false" />
+      <conditionProcess>%aditoprj%/entity/KeywordAttributeRelation_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <linkInformation>
+        <linkInformation>
+          <name>8e2938d2-e14b-403b-8ae5-875f70bc3f85</name>
+          <tableName>AB_KEYWORD_ATTRIBUTERELATION</tableName>
+          <primaryKey>AB_KEYWORD_ATTRIBUTERELATIONID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ATTRIBUTERELATIONID.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTERELATIONID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>BOOL_VALUE.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.BOOL_VALUE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CHAR_VALUE.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.CHAR_VALUE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>NUMBER_VALUE.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.NUMBER_VALUE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ATTRIBUTE_ID.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ENTRY_ID.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ATTRIBUTE_ID.displayValue</name>
+          <expression>%aditoprj%/entity/KeywordAttributeRelation_entity/recordcontainers/db/recordfieldmappings/ab_keyword_attribute_id.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LONG_CHAR_VALUE.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTERELATION.LONG_CHAR_VALUE</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/documentation.adoc b/entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod b/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
index 51527c153e05af4fd0f766560af876d11a62d49d..6fee4eb699fae7b44bcc8745589305903ea98e10 100644
--- a/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
+++ b/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
@@ -1,128 +1,128 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
-  <name>KeywordAttribute_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/KeywordAttribute_entity/documentation.adoc</documentation>
-  <title>Keyword Attribute</title>
-  <contentTitleProcess>%aditoprj%/entity/KeywordAttribute_entity/contentTitleProcess.js</contentTitleProcess>
-  <iconId>VAADIN:KEY_O</iconId>
-  <iconIdProcess>%aditoprj%/entity/KeywordAttribute_entity/iconIdProcess.js</iconIdProcess>
-  <titlePlural>Keyword Attributes</titlePlural>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>AB_KEYWORD_ATTRIBUTEID</name>
-      <valueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/ab_keyword_attributeid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>CONTAINER</name>
-      <title>Container</title>
-      <mandatory v="true" />
-      <dropDownProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/container/dropDownProcess.js</dropDownProcess>
-    </entityField>
-    <entityField>
-      <name>NAME</name>
-      <title>Name</title>
-      <mandatory v="true" />
-      <onValidation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/name/onValidation.js</onValidation>
-    </entityField>
-    <entityField>
-      <name>TYPE</name>
-      <title>Type</title>
-      <consumer>KeywordAttributeTypes</consumer>
-      <mandatory v="true" />
-      <displayValueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/type/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityProvider>
-      <name>SpecificContainerKeyword</name>
-      <documentation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/specificcontainerkeyword/documentation.adoc</documentation>
-      <dependencies>
-        <entityDependency>
-          <name>1d11c064-1cf2-4f08-b842-9fa941ad3157</name>
-          <entityName>KeywordAttributeRelation_entity</entityName>
-          <fieldName>KeywordAttributes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>684a3e60-00ad-4d46-8c98-6559e485a729</name>
-          <entityName>CommRestriction_Entity</entityName>
-          <fieldName>MediumKeywordAttribute</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-    </entityProvider>
-    <entityParameter>
-      <name>ContainerName_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>FilterAlreadyUsedByEntryId_param</name>
-      <expose v="true" />
-      <mandatory v="false" />
-      <documentation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/filteralreadyusedbyentryid_param/documentation.adoc</documentation>
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>KeywordAttributeTypes</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <isPageable v="false" />
-      <conditionProcess>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <onDBDelete>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
-      <linkInformation>
-        <linkInformation>
-          <name>bd113d67-34ab-4708-b0e5-60a44332e6b8</name>
-          <tableName>AB_KEYWORD_ATTRIBUTE</tableName>
-          <primaryKey>AB_KEYWORD_ATTRIBUTEID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ATTRIBUTEID.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CONTAINER.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTE.CONTAINER</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>NAME.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTE.NAME</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>TYPE.value</name>
-          <recordfield>AB_KEYWORD_ATTRIBUTE.KIND</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>TYPE.displayValue</name>
-          <expression>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
+  <name>KeywordAttribute_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/KeywordAttribute_entity/documentation.adoc</documentation>
+  <title>Keyword Attribute</title>
+  <contentTitleProcess>%aditoprj%/entity/KeywordAttribute_entity/contentTitleProcess.js</contentTitleProcess>
+  <iconId>VAADIN:KEY_O</iconId>
+  <iconIdProcess>%aditoprj%/entity/KeywordAttribute_entity/iconIdProcess.js</iconIdProcess>
+  <titlePlural>Keyword Attributes</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>AB_KEYWORD_ATTRIBUTEID</name>
+      <valueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/ab_keyword_attributeid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>CONTAINER</name>
+      <title>Container</title>
+      <mandatory v="true" />
+      <dropDownProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/container/dropDownProcess.js</dropDownProcess>
+    </entityField>
+    <entityField>
+      <name>NAME</name>
+      <title>Name</title>
+      <mandatory v="true" />
+      <onValidation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/name/onValidation.js</onValidation>
+    </entityField>
+    <entityField>
+      <name>TYPE</name>
+      <title>Type</title>
+      <consumer>KeywordAttributeTypes</consumer>
+      <mandatory v="true" />
+      <displayValueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/type/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityProvider>
+      <name>SpecificContainerKeyword</name>
+      <documentation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/specificcontainerkeyword/documentation.adoc</documentation>
+      <dependencies>
+        <entityDependency>
+          <name>1d11c064-1cf2-4f08-b842-9fa941ad3157</name>
+          <entityName>KeywordAttributeRelation_entity</entityName>
+          <fieldName>KeywordAttributes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>684a3e60-00ad-4d46-8c98-6559e485a729</name>
+          <entityName>CommRestriction_Entity</entityName>
+          <fieldName>MediumKeywordAttribute</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityParameter>
+      <name>ContainerName_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>FilterAlreadyUsedByEntryId_param</name>
+      <expose v="true" />
+      <mandatory v="false" />
+      <documentation>%aditoprj%/entity/KeywordAttribute_entity/entityfields/filteralreadyusedbyentryid_param/documentation.adoc</documentation>
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>KeywordAttributeTypes</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/KeywordAttribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <isPageable v="false" />
+      <conditionProcess>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <onDBDelete>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
+      <linkInformation>
+        <linkInformation>
+          <name>bd113d67-34ab-4708-b0e5-60a44332e6b8</name>
+          <tableName>AB_KEYWORD_ATTRIBUTE</tableName>
+          <primaryKey>AB_KEYWORD_ATTRIBUTEID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ATTRIBUTEID.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CONTAINER.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTE.CONTAINER</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>NAME.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTE.NAME</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TYPE.value</name>
+          <recordfield>AB_KEYWORD_ATTRIBUTE.KIND</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TYPE.displayValue</name>
+          <expression>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js b/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js
index 02735856728916d8c1030268da36120a4b8c16c3..5df041cf417a065651c61f11c8296636328e2462 100644
--- a/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js
@@ -1,21 +1,21 @@
-import("system.vars");
-import("system.db");
-import("system.result");
-import("Sql_lib");
-
-var cond = SqlCondition.begin().andPrepareVars("AB_KEYWORD_ATTRIBUTE.CONTAINER", "$param.ContainerName_param");
-
-//filter for entries that are already used by entry_id
-var entryIdForFilter = vars.get("$param.FilterAlreadyUsedByEntryId_param");
-if (entryIdForFilter)
-{
-    var exclusiveFilterCondition = SqlCondition.begin()
-        .andPrepare("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID", entryIdForFilter)
-        .buildSql("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID not in (\n\
-            select AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID \n\
-            from AB_KEYWORD_ATTRIBUTERELATION ", null, ")");
-    cond.andAttachPrepared(exclusiveFilterCondition);
-}
-
-var condStr = db.translateCondition(cond.build("1 = 1"));
+import("system.vars");
+import("system.db");
+import("system.result");
+import("Sql_lib");
+
+var cond = SqlCondition.begin().andPrepareVars("AB_KEYWORD_ATTRIBUTE.CONTAINER", "$param.ContainerName_param");
+
+//filter for entries that are already used by entry_id
+var entryIdForFilter = vars.get("$param.FilterAlreadyUsedByEntryId_param");
+if (entryIdForFilter)
+{
+    var exclusiveFilterCondition = SqlCondition.begin()
+        .andPrepare("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID", entryIdForFilter)
+        .buildSql("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID not in (\n\
+            select AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID \n\
+            from AB_KEYWORD_ATTRIBUTERELATION ", null, ")");
+    cond.andAttachPrepared(exclusiveFilterCondition);
+}
+
+var condStr = db.translateCondition(cond.build("1 = 1"));
 result.string(condStr);
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 3576059f49386e02336b4dbf1371f02dba5f7130..cfd5ab3025745be89f24fe3c8b89458f58d884b7 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -1,608 +1,593 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
-  <name>KeywordEntry_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/KeywordEntry_entity/documentation.adoc</documentation>
-  <title>Keyword</title>
-  <siblings />
-  <grantDelete v="false" />
-  <grantDeleteProcess>%aditoprj%/entity/KeywordEntry_entity/grantDeleteProcess.js</grantDeleteProcess>
-  <contentTitleProcess>%aditoprj%/entity/KeywordEntry_entity/contentTitleProcess.js</contentTitleProcess>
-  <onValidation>%aditoprj%/entity/KeywordEntry_entity/onValidation.js</onValidation>
-  <iconId>VAADIN:KEY</iconId>
-  <iconIdProcess>%aditoprj%/entity/KeywordEntry_entity/iconIdProcess.js</iconIdProcess>
-  <titlePlural>Keywords</titlePlural>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-      <lookupIdfield>KEYID</lookupIdfield>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>ce10e4d3-7799-4473-a681-a3c6d9f93b02</name>
-          <entityName>Notification_entity</entityName>
-          <fieldName>StateKeywords</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>0015f4fa-9f54-4d99-8e23-92e36a614d7a</name>
-          <entityName>Notification_entity</entityName>
-          <fieldName>PrioKeywords</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-    </entityProvider>
-    <entityField>
-      <name>CONTAINER</name>
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/documentation.adoc</documentation>
-      <title>Container</title>
-      <groupable v="true" />
-      <mandatory v="true" />
-      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/dropDownProcess.js</dropDownProcess>
-      <textInputAllowed v="true" />
-      <state>READONLY</state>
-      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/stateProcess.js</stateProcess>
-    </entityField>
-    <entityField>
-      <name>AB_KEYWORD_ENTRYID</name>
-      <title>AB_KEYWORD_ENTRYID (UID)</title>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/ab_keyword_entryid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>KEYID</name>
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc</documentation>
-      <title>Key</title>
-      <mandatory v="true" />
-      <state>READONLY</state>
-      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js</valueProcess>
-      <onValidation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js</onValidation>
-    </entityField>
-    <entityField>
-      <name>TITLE</name>
-      <title>Title (original language)</title>
-      <mandatory v="true" />
-    </entityField>
-    <entityField>
-      <name>SORTING</name>
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/sorting/documentation.adoc</documentation>
-      <title>Sorting</title>
-      <mandatory v="false" />
-      <state>AUTO</state>
-    </entityField>
-    <entityField>
-      <name>ISACTIVE</name>
-      <title>Active</title>
-      <contentType>BOOLEAN</contentType>
-      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isactive/dropDownProcess.js</dropDownProcess>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isactive/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>ISESSENTIAL</name>
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/documentation.adoc</documentation>
-      <title>Relational</title>
-      <contentType>BOOLEAN</contentType>
-      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/dropDownProcess.js</dropDownProcess>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>ContainerName_param</name>
-      <expose v="true" />
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/containername_param/documentation.adoc</documentation>
-    </entityParameter>
-    <entityProvider>
-      <name>SpecificContainerKeywords</name>
-      <lookupIdfield>KEYID</lookupIdfield>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>bb48a3ee-f340-4fd4-8c80-ef73b765ab58</name>
-          <entityName>Organisation_entity</entityName>
-          <fieldName>KeywordContactStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>4b1d1def-36d3-45e9-9ed5-eaef12d1ec82</name>
-          <entityName>Activity_entity</entityName>
-          <fieldName>KeywordDirections</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>42219987-4eff-4429-a22c-93e8a9c55c45</name>
-          <entityName>Contract_entity</entityName>
-          <fieldName>ContractPayments</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>2712e2b3-f17f-4a9c-9752-2383f62eb2b8</name>
-          <entityName>Contract_entity</entityName>
-          <fieldName>ContractStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>bd68f269-457c-487d-a1b2-e045d98f74b7</name>
-          <entityName>Contract_entity</entityName>
-          <fieldName>ContractTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>b88b5cc8-c29e-4110-b86e-d1d0050460e5</name>
-          <entityName>Offer_entity</entityName>
-          <fieldName>KeywordCurrencies</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>57c746ee-a8c0-484a-8c73-6301609b76b1</name>
-          <entityName>Order_entity</entityName>
-          <fieldName>KeywordCurrencies</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>bf014596-954b-4c7d-9304-8283c9bcc7ae</name>
-          <entityName>Productprice_entity</entityName>
-          <fieldName>KeywordCurrencies</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>f5dcbf08-3765-4a9d-8b42-cb1219c87f57</name>
-          <entityName>Offeritem_entity</entityName>
-          <fieldName>KeywordProductGroupcodes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>53bcaa07-94eb-4e81-9e9e-c5748156dad5</name>
-          <entityName>Orderitem_entity</entityName>
-          <fieldName>KeywordProductGroupcodes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>c404b010-1634-4160-adca-7edf1535ee26</name>
-          <entityName>Product_entity</entityName>
-          <fieldName>KeywordProductGroupcodes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>3575fdd7-3dd6-4318-b0d2-32d1df821076</name>
-          <entityName>Forecast_entity</entityName>
-          <fieldName>KeywordProductGroupcodes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>5a21cbe2-4eb0-4968-80fa-b98a64599230</name>
-          <entityName>Offer_entity</entityName>
-          <fieldName>KeywordOfferStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>8696e561-b263-4c7c-b753-c5da44b48055</name>
-          <entityName>Organisation_entity</entityName>
-          <fieldName>KeywordOrganisationTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>0d54d283-f158-4b91-8f6d-026954ed9c50</name>
-          <entityName>Person_entity</entityName>
-          <fieldName>KeywordGenders</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>8d28f08b-675d-4bcf-9318-a508d45ca69e</name>
-          <entityName>Task_entity</entityName>
-          <fieldName>KeywordStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>b069ef7d-07a0-460c-a8e7-cde5861c96c2</name>
-          <entityName>Productprice_entity</entityName>
-          <fieldName>KeywordPricelists</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>7f134ef1-cff5-4cf4-9d2a-e288c7904c28</name>
-          <entityName>Offeritem_entity</entityName>
-          <fieldName>KeywordQuantityUnits</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>c3c3b430-a14f-46b4-909a-9b53cef35413</name>
-          <entityName>Orderitem_entity</entityName>
-          <fieldName>KeywordQuantityUnits</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>a1983efd-92f9-4a6b-8805-d2977fcde0c8</name>
-          <entityName>Product_entity</entityName>
-          <fieldName>KeywordQuantityUnits</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>026021cd-cd64-400d-8bd5-f6d044af1ad8</name>
-          <entityName>Member_entity</entityName>
-          <fieldName>KeywordMemberRoles</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>356e23f9-eb05-4e18-b0b5-cbc7c8716dba</name>
-          <entityName>SalesprojectSource_entity</entityName>
-          <fieldName>KeywordSources</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>36a72192-902f-431b-8f43-0bef311678f7</name>
-          <entityName>Order_entity</entityName>
-          <fieldName>KeywordStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>e2041dea-8647-49e9-aacf-4481b75b76ff</name>
-          <entityName>Stock_entity</entityName>
-          <fieldName>KeywordWarehouses</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>403c40a4-f747-4e47-ad60-07334724d6fb</name>
-          <entityName>KeywordAttribute_entity</entityName>
-          <fieldName>KeywordAttributeTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>078bbd52-87fa-44cc-9902-04af935b5fbc</name>
-          <entityName>Attribute_entity</entityName>
-          <fieldName>KeywordAttributeTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>718fe5a2-c75f-49ed-b67e-fc4fbf63ff1d</name>
-          <entityName>Salesproject_entity</entityName>
-          <fieldName>KeywordProbabilties</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>a44375e9-917c-4db8-9aa8-de0625caf78f</name>
-          <entityName>Activity_entity</entityName>
-          <fieldName>KeywordCategories</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>f442a641-4dff-4860-bf4c-cfddc054e075</name>
-          <entityName>Offer_entity</entityName>
-          <fieldName>KeywordProbabilities</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>fa831dac-3287-422a-8f28-504fc525876a</name>
-          <entityName>Communication_entity</entityName>
-          <fieldName>KeywordMediums</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>04b28ce6-a144-4c19-ac2d-4cfbc3568700</name>
-          <entityName>Organisation_entity</entityName>
-          <fieldName>KeywordPricePolitics</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>f024df05-2faf-4447-9eed-ae31b329d542</name>
-          <entityName>Competition_entity</entityName>
-          <fieldName>KeywordPricePolitics</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>60840c28-9875-4e3e-8099-5ca208d58bbe</name>
-          <entityName>Organisation_entity</entityName>
-          <fieldName>KeywordWeaknesses</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>854148e2-2532-4562-b393-832819e8d462</name>
-          <entityName>Organisation_entity</entityName>
-          <fieldName>KeywordStrenghts</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>613d5861-0494-45f9-a839-a705347a68da</name>
-          <entityName>Competition_entity</entityName>
-          <fieldName>KeywordWeaknesses</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>119d79d0-9e04-4dd0-80bb-0bc32eaae775</name>
-          <entityName>Competition_entity</entityName>
-          <fieldName>KeywordStrenghts</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>6e2d164c-1ac7-4ed0-ad8f-7bfda1328493</name>
-          <entityName>Salesproject_entity</entityName>
-          <fieldName>KeywordStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>3ca6d3c7-83d2-4761-bab4-50d2baecdbd6</name>
-          <entityName>Competition_entity</entityName>
-          <fieldName>KeywordPhases</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>1053a90d-574a-4ca2-b41d-42b513db0fd2</name>
-          <entityName>Task_entity</entityName>
-          <fieldName>KeywordPriorities</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>bf9f7a07-dfb9-44d0-8f9b-d3814053683e</name>
-          <entityName>Competition_entity</entityName>
-          <fieldName>KeywordStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>ef8b9397-6292-42de-806e-5aaf3e3db5f3</name>
-          <entityName>Salesproject_entity</entityName>
-          <fieldName>KeywordWonLost</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>5d9e0e48-ece8-4b8e-ab72-beef77b5dcc3</name>
-          <entityName>Task_entity</entityName>
-          <fieldName>KeywordProgress</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>36aa04c1-5361-4e40-a036-0546db596973</name>
-          <entityName>Offer_entity</entityName>
-          <fieldName>KeywordDeliveryTerm</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>7e12cbd6-3a2c-4bd8-bc66-5001c282b690</name>
-          <entityName>Offer_entity</entityName>
-          <fieldName>KeywordPaymentTerm</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>77be3cca-8b50-4810-9549-3fd3e6fdf220</name>
-          <entityName>Person_entity</entityName>
-          <fieldName>KeywordContactStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>7945545b-f1e6-446d-84c3-ef68486652f4</name>
-          <entityName>Contact_entity</entityName>
-          <fieldName>KeywordContactStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>740a9696-d394-48ea-bcbf-a5484a093bde</name>
-          <entityName>SalesprojectMilestone_entity</entityName>
-          <fieldName>Keywords</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>b5c39776-509e-4758-8d05-a64eac4e7f38</name>
-          <entityName>CampaignStep_entity</entityName>
-          <fieldName>KeywordStates</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>13d739cb-2b97-44a0-bed0-b6868b0e579e</name>
-          <entityName>CampaignCost_entity</entityName>
-          <fieldName>KeywordCampaignManagementCostCategory</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>63bd7284-e9a0-4576-afe8-299d412e8def</name>
-          <entityName>ClassificationAdmin_entity</entityName>
-          <fieldName>KeywordClassificationTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>3a81e886-0d83-47f0-9ec7-c864ffc57cda</name>
-          <entityName>Classification_entity</entityName>
-          <fieldName>KeywordClassificationTypes</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>995646a8-ccec-4962-8c81-05a54903c433</name>
-          <entityName>CommRestriction_Entity</entityName>
-          <fieldName>CommRestrictionMedium</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>eb7c17de-3057-45c5-96c0-f863551cc049</name>
-          <entityName>BulkMailRecipient_entity</entityName>
-          <fieldName>StatusKeyword</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>3ab18dc8-b702-49d9-9cbc-4b8d8ffaea2e</name>
-          <entityName>DSGVO_entity</entityName>
-          <fieldName>KeywordDSGVOPurpose</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>86501073-4e62-42ef-ba15-e9f6a2eb3495</name>
-          <entityName>DSGVO_entity</entityName>
-          <fieldName>KeywordDSGVOStatuoritysource</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>ae2c4712-5513-4c0d-911a-532f50483c76</name>
-          <entityName>DSGVO_entity</entityName>
-          <fieldName>KeywordDSGVOType</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>44f84932-2a27-4e11-833b-def950c064d9</name>
-          <entityName>SupportTicket_entity</entityName>
-          <fieldName>KeywordTickettype</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>10ba6c44-779c-4ba8-9277-e9583af03ed5</name>
-          <entityName>SupportTicket_entity</entityName>
-          <fieldName>KeywordTaskState</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>e1b87370-aa15-4540-99c1-7bd63f0f3263</name>
-          <entityName>SupportTicket_entity</entityName>
-          <fieldName>KeywordTaskPriority</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>d8c587cc-47db-4e08-a6ac-92ec1d91acb5</name>
-          <entityName>BulkMail_entity</entityName>
-          <fieldName>StatusKeyword</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>41fd8fd4-7285-4493-9a56-cc0c44353057</name>
-          <entityName>DSGVOInfo_entity</entityName>
-          <fieldName>KeywordDeadline</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>1cbfe51f-43c3-4e99-895f-673097915249</name>
-          <entityName>DSGVOInfo_entity</entityName>
-          <fieldName>KeywordTransmission</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>718da6a7-229b-4075-a8ff-b0458c770e7b</name>
-          <entityName>DSGVOInfo_entity</entityName>
-          <fieldName>KeywordGuarantee</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>OnlyActives_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/specificcontainerkeywords/children/onlyactives_param/valueProcess.js</valueProcess>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>TITLE_TRANSLATED</name>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/title_translated/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>OnlyActives_param</name>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/onlyactives_param/valueProcess.js</valueProcess>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>KeywordAttributeRelations</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordAttributeRelation_entity</entityName>
-        <fieldName>AttributesForKeywordEntry</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>KeywordEntryId_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keywordattributerelations/children/keywordentryid_param/valueProcess.js</valueProcess>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityConsumer>
-      <name>KeywordAttributeRelationsReadOnly</name>
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/documentation.adoc</documentation>
-      <state>READONLY</state>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordAttributeRelation_entity</entityName>
-        <fieldName>AttributesForKeywordEntry</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>KeywordEntryId_param</name>
-          <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/children/keywordentryid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityParameter>
-      <name>ExcludedKeyIdsSubquery_param</name>
-      <expose v="true" />
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc</documentation>
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>WhitelistIds_param</name>
-      <expose v="true" />
-      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/whitelistids_param/documentation.adoc</documentation>
-    </entityParameter>
-    <entityField>
-      <name>expanded</name>
-      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/expanded/valueProcess.js</valueProcess>
-    </entityField>
-    <entityActionField>
-      <name>openAdminView</name>
-      <title>Open admin view</title>
-      <onActionProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/openadminview/onActionProcess.js</onActionProcess>
-      <iconId>VAADIN:CURLY_BRACKETS</iconId>
-      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/openadminview/stateProcess.js</stateProcess>
-    </entityActionField>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <isPageable v="false" />
-      <conditionProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <orderClauseProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <onDBDelete>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
-      <linkInformation>
-        <linkInformation>
-          <name>52acbfe0-57f4-4614-83af-9882e168f431</name>
-          <tableName>AB_KEYWORD_ENTRY</tableName>
-          <primaryKey>AB_KEYWORD_ENTRYID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>TITLE.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.TITLE</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>SORTING.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.SORTING</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ISESSENTIAL.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.ISESSENTIAL</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ISACTIVE.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.ISACTIVE</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>AB_KEYWORD_ENTRYID.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>KEYID.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.KEYID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CONTAINER.value</name>
-          <recordfield>AB_KEYWORD_ENTRY.CONTAINER</recordfield>
-          <isFilterable v="true" />
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.11" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.11">
+  <name>KeywordEntry_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/KeywordEntry_entity/documentation.adoc</documentation>
+  <title>Keyword</title>
+  <siblings />
+  <grantDelete v="false" />
+  <grantDeleteProcess>%aditoprj%/entity/KeywordEntry_entity/grantDeleteProcess.js</grantDeleteProcess>
+  <contentTitleProcess>%aditoprj%/entity/KeywordEntry_entity/contentTitleProcess.js</contentTitleProcess>
+  <onValidation>%aditoprj%/entity/KeywordEntry_entity/onValidation.js</onValidation>
+  <iconId>VAADIN:KEY</iconId>
+  <iconIdProcess>%aditoprj%/entity/KeywordEntry_entity/iconIdProcess.js</iconIdProcess>
+  <titlePlural>Keywords</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <lookupIdfield>KEYID</lookupIdfield>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>ce10e4d3-7799-4473-a681-a3c6d9f93b02</name>
+          <entityName>Notification_entity</entityName>
+          <fieldName>StateKeywords</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>0015f4fa-9f54-4d99-8e23-92e36a614d7a</name>
+          <entityName>Notification_entity</entityName>
+          <fieldName>PrioKeywords</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityField>
+      <name>CONTAINER</name>
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/documentation.adoc</documentation>
+      <title>Container</title>
+      <groupable v="true" />
+      <mandatory v="true" />
+      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/dropDownProcess.js</dropDownProcess>
+      <textInputAllowed v="true" />
+      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/stateProcess.js</stateProcess>
+    </entityField>
+    <entityField>
+      <name>AB_KEYWORD_ENTRYID</name>
+      <title>AB_KEYWORD_ENTRYID (UID)</title>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/ab_keyword_entryid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>KEYID</name>
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc</documentation>
+      <title>Key</title>
+      <mandatory v="true" />
+      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js</valueProcess>
+      <onValidation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js</onValidation>
+    </entityField>
+    <entityField>
+      <name>TITLE</name>
+      <title>Title (original language)</title>
+      <mandatory v="true" />
+    </entityField>
+    <entityField>
+      <name>SORTING</name>
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/sorting/documentation.adoc</documentation>
+      <title>Sorting</title>
+      <mandatory v="false" />
+      <state>AUTO</state>
+    </entityField>
+    <entityField>
+      <name>ISACTIVE</name>
+      <title>Active</title>
+      <contentType>BOOLEAN</contentType>
+      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isactive/dropDownProcess.js</dropDownProcess>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isactive/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>ISESSENTIAL</name>
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/documentation.adoc</documentation>
+      <title>Relational</title>
+      <contentType>BOOLEAN</contentType>
+      <dropDownProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/dropDownProcess.js</dropDownProcess>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/isessential/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>ContainerName_param</name>
+      <expose v="true" />
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/containername_param/documentation.adoc</documentation>
+    </entityParameter>
+    <entityProvider>
+      <name>SpecificContainerKeywords</name>
+      <lookupIdfield>KEYID</lookupIdfield>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>bb48a3ee-f340-4fd4-8c80-ef73b765ab58</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>KeywordContactStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>4b1d1def-36d3-45e9-9ed5-eaef12d1ec82</name>
+          <entityName>Activity_entity</entityName>
+          <fieldName>KeywordDirections</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>42219987-4eff-4429-a22c-93e8a9c55c45</name>
+          <entityName>Contract_entity</entityName>
+          <fieldName>ContractPayments</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>2712e2b3-f17f-4a9c-9752-2383f62eb2b8</name>
+          <entityName>Contract_entity</entityName>
+          <fieldName>ContractStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>bd68f269-457c-487d-a1b2-e045d98f74b7</name>
+          <entityName>Contract_entity</entityName>
+          <fieldName>ContractTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>b88b5cc8-c29e-4110-b86e-d1d0050460e5</name>
+          <entityName>Offer_entity</entityName>
+          <fieldName>KeywordCurrencies</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>57c746ee-a8c0-484a-8c73-6301609b76b1</name>
+          <entityName>Order_entity</entityName>
+          <fieldName>KeywordCurrencies</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>bf014596-954b-4c7d-9304-8283c9bcc7ae</name>
+          <entityName>Productprice_entity</entityName>
+          <fieldName>KeywordCurrencies</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>f5dcbf08-3765-4a9d-8b42-cb1219c87f57</name>
+          <entityName>Offeritem_entity</entityName>
+          <fieldName>KeywordProductGroupcodes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>53bcaa07-94eb-4e81-9e9e-c5748156dad5</name>
+          <entityName>Orderitem_entity</entityName>
+          <fieldName>KeywordProductGroupcodes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>c404b010-1634-4160-adca-7edf1535ee26</name>
+          <entityName>Product_entity</entityName>
+          <fieldName>KeywordProductGroupcodes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>3575fdd7-3dd6-4318-b0d2-32d1df821076</name>
+          <entityName>Forecast_entity</entityName>
+          <fieldName>KeywordProductGroupcodes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>5a21cbe2-4eb0-4968-80fa-b98a64599230</name>
+          <entityName>Offer_entity</entityName>
+          <fieldName>KeywordOfferStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>8696e561-b263-4c7c-b753-c5da44b48055</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>KeywordOrganisationTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>0d54d283-f158-4b91-8f6d-026954ed9c50</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>KeywordGenders</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>8d28f08b-675d-4bcf-9318-a508d45ca69e</name>
+          <entityName>Task_entity</entityName>
+          <fieldName>KeywordStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>b069ef7d-07a0-460c-a8e7-cde5861c96c2</name>
+          <entityName>Productprice_entity</entityName>
+          <fieldName>KeywordPricelists</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>7f134ef1-cff5-4cf4-9d2a-e288c7904c28</name>
+          <entityName>Offeritem_entity</entityName>
+          <fieldName>KeywordQuantityUnits</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>c3c3b430-a14f-46b4-909a-9b53cef35413</name>
+          <entityName>Orderitem_entity</entityName>
+          <fieldName>KeywordQuantityUnits</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>a1983efd-92f9-4a6b-8805-d2977fcde0c8</name>
+          <entityName>Product_entity</entityName>
+          <fieldName>KeywordQuantityUnits</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>026021cd-cd64-400d-8bd5-f6d044af1ad8</name>
+          <entityName>Member_entity</entityName>
+          <fieldName>KeywordMemberRoles</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>356e23f9-eb05-4e18-b0b5-cbc7c8716dba</name>
+          <entityName>SalesprojectSource_entity</entityName>
+          <fieldName>KeywordSources</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>36a72192-902f-431b-8f43-0bef311678f7</name>
+          <entityName>Order_entity</entityName>
+          <fieldName>KeywordStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>e2041dea-8647-49e9-aacf-4481b75b76ff</name>
+          <entityName>Stock_entity</entityName>
+          <fieldName>KeywordWarehouses</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>403c40a4-f747-4e47-ad60-07334724d6fb</name>
+          <entityName>KeywordAttribute_entity</entityName>
+          <fieldName>KeywordAttributeTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>078bbd52-87fa-44cc-9902-04af935b5fbc</name>
+          <entityName>Attribute_entity</entityName>
+          <fieldName>KeywordAttributeTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>718fe5a2-c75f-49ed-b67e-fc4fbf63ff1d</name>
+          <entityName>Salesproject_entity</entityName>
+          <fieldName>KeywordProbabilties</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>a44375e9-917c-4db8-9aa8-de0625caf78f</name>
+          <entityName>Activity_entity</entityName>
+          <fieldName>KeywordCategories</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>f442a641-4dff-4860-bf4c-cfddc054e075</name>
+          <entityName>Offer_entity</entityName>
+          <fieldName>KeywordProbabilities</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>fa831dac-3287-422a-8f28-504fc525876a</name>
+          <entityName>Communication_entity</entityName>
+          <fieldName>KeywordMediums</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>04b28ce6-a144-4c19-ac2d-4cfbc3568700</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>KeywordPricePolitics</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>f024df05-2faf-4447-9eed-ae31b329d542</name>
+          <entityName>Competition_entity</entityName>
+          <fieldName>KeywordPricePolitics</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>60840c28-9875-4e3e-8099-5ca208d58bbe</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>KeywordWeaknesses</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>854148e2-2532-4562-b393-832819e8d462</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>KeywordStrenghts</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>613d5861-0494-45f9-a839-a705347a68da</name>
+          <entityName>Competition_entity</entityName>
+          <fieldName>KeywordWeaknesses</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>119d79d0-9e04-4dd0-80bb-0bc32eaae775</name>
+          <entityName>Competition_entity</entityName>
+          <fieldName>KeywordStrenghts</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>6e2d164c-1ac7-4ed0-ad8f-7bfda1328493</name>
+          <entityName>Salesproject_entity</entityName>
+          <fieldName>KeywordStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>3ca6d3c7-83d2-4761-bab4-50d2baecdbd6</name>
+          <entityName>Competition_entity</entityName>
+          <fieldName>KeywordPhases</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>1053a90d-574a-4ca2-b41d-42b513db0fd2</name>
+          <entityName>Task_entity</entityName>
+          <fieldName>KeywordPriorities</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>bf9f7a07-dfb9-44d0-8f9b-d3814053683e</name>
+          <entityName>Competition_entity</entityName>
+          <fieldName>KeywordStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>ef8b9397-6292-42de-806e-5aaf3e3db5f3</name>
+          <entityName>Salesproject_entity</entityName>
+          <fieldName>KeywordWonLost</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>5d9e0e48-ece8-4b8e-ab72-beef77b5dcc3</name>
+          <entityName>Task_entity</entityName>
+          <fieldName>KeywordProgress</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>36aa04c1-5361-4e40-a036-0546db596973</name>
+          <entityName>Offer_entity</entityName>
+          <fieldName>KeywordDeliveryTerm</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>7e12cbd6-3a2c-4bd8-bc66-5001c282b690</name>
+          <entityName>Offer_entity</entityName>
+          <fieldName>KeywordPaymentTerm</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>77be3cca-8b50-4810-9549-3fd3e6fdf220</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>KeywordContactStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>7945545b-f1e6-446d-84c3-ef68486652f4</name>
+          <entityName>Contact_entity</entityName>
+          <fieldName>KeywordContactStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>740a9696-d394-48ea-bcbf-a5484a093bde</name>
+          <entityName>SalesprojectMilestone_entity</entityName>
+          <fieldName>Keywords</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>b5c39776-509e-4758-8d05-a64eac4e7f38</name>
+          <entityName>CampaignStep_entity</entityName>
+          <fieldName>KeywordStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>13d739cb-2b97-44a0-bed0-b6868b0e579e</name>
+          <entityName>CampaignCost_entity</entityName>
+          <fieldName>KeywordCampaignManagementCostCategory</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>63bd7284-e9a0-4576-afe8-299d412e8def</name>
+          <entityName>ClassificationAdmin_entity</entityName>
+          <fieldName>KeywordClassificationTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>3a81e886-0d83-47f0-9ec7-c864ffc57cda</name>
+          <entityName>Classification_entity</entityName>
+          <fieldName>KeywordClassificationTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>995646a8-ccec-4962-8c81-05a54903c433</name>
+          <entityName>CommRestriction_Entity</entityName>
+          <fieldName>CommRestrictionMedium</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>eb7c17de-3057-45c5-96c0-f863551cc049</name>
+          <entityName>BulkMailRecipient_entity</entityName>
+          <fieldName>StatusKeyword</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>3ab18dc8-b702-49d9-9cbc-4b8d8ffaea2e</name>
+          <entityName>DSGVO_entity</entityName>
+          <fieldName>KeywordDSGVOPurpose</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>86501073-4e62-42ef-ba15-e9f6a2eb3495</name>
+          <entityName>DSGVO_entity</entityName>
+          <fieldName>KeywordDSGVOStatuoritysource</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>ae2c4712-5513-4c0d-911a-532f50483c76</name>
+          <entityName>DSGVO_entity</entityName>
+          <fieldName>KeywordDSGVOType</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>44f84932-2a27-4e11-833b-def950c064d9</name>
+          <entityName>SupportTicket_entity</entityName>
+          <fieldName>KeywordTickettype</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>10ba6c44-779c-4ba8-9277-e9583af03ed5</name>
+          <entityName>SupportTicket_entity</entityName>
+          <fieldName>KeywordTaskState</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>e1b87370-aa15-4540-99c1-7bd63f0f3263</name>
+          <entityName>SupportTicket_entity</entityName>
+          <fieldName>KeywordTaskPriority</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>d8c587cc-47db-4e08-a6ac-92ec1d91acb5</name>
+          <entityName>BulkMail_entity</entityName>
+          <fieldName>StatusKeyword</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>41fd8fd4-7285-4493-9a56-cc0c44353057</name>
+          <entityName>DSGVOInfo_entity</entityName>
+          <fieldName>KeywordDeadline</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>1cbfe51f-43c3-4e99-895f-673097915249</name>
+          <entityName>DSGVOInfo_entity</entityName>
+          <fieldName>KeywordTransmission</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>718da6a7-229b-4075-a8ff-b0458c770e7b</name>
+          <entityName>DSGVOInfo_entity</entityName>
+          <fieldName>KeywordGuarantee</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>OnlyActives_param</name>
+          <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/specificcontainerkeywords/children/onlyactives_param/valueProcess.js</valueProcess>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>TITLE_TRANSLATED</name>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/title_translated/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>OnlyActives_param</name>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/onlyactives_param/valueProcess.js</valueProcess>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>KeywordAttributeRelations</name>
+      <onValidation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keywordattributerelations/onValidation.js</onValidation>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordAttributeRelation_entity</entityName>
+        <fieldName>AttributesForKeywordEntry</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>KeywordEntryId_param</name>
+          <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keywordattributerelations/children/keywordentryid_param/valueProcess.js</valueProcess>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityParameter>
+      <name>ExcludedKeyIdsSubquery_param</name>
+      <expose v="true" />
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc</documentation>
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>WhitelistIds_param</name>
+      <expose v="true" />
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/whitelistids_param/documentation.adoc</documentation>
+    </entityParameter>
+    <entityField>
+      <name>expanded</name>
+      <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/expanded/valueProcess.js</valueProcess>
+    </entityField>
+    <entityActionField>
+      <name>openAdminView</name>
+      <title>Open admin view</title>
+      <onActionProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/openadminview/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:CURLY_BRACKETS</iconId>
+      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/openadminview/stateProcess.js</stateProcess>
+    </entityActionField>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <isPageable v="false" />
+      <conditionProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
+      <onDBDelete>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
+      <linkInformation>
+        <linkInformation>
+          <name>52acbfe0-57f4-4614-83af-9882e168f431</name>
+          <tableName>AB_KEYWORD_ENTRY</tableName>
+          <primaryKey>AB_KEYWORD_ENTRYID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>TITLE.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.TITLE</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SORTING.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.SORTING</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ISESSENTIAL.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.ISESSENTIAL</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ISACTIVE.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.ISACTIVE</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>AB_KEYWORD_ENTRYID.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>KEYID.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.KEYID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CONTAINER.value</name>
+          <recordfield>AB_KEYWORD_ENTRY.CONTAINER</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/KeywordEntry_entity/entityfields/keywordattributerelations/onValidation.js b/entity/KeywordEntry_entity/entityfields/keywordattributerelations/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..e2a0b150abda4a70271483b6b64fcb4d937511bc
--- /dev/null
+++ b/entity/KeywordEntry_entity/entityfields/keywordattributerelations/onValidation.js
@@ -0,0 +1,82 @@
+import("system.translate");
+import("system.result");
+import("system.vars");
+import("Sql_lib");
+import("system.db");
+
+if (!_areUnique())
+    result.string(translate.text("Attributes must be unique!"));
+
+function _areUnique ()
+{
+    var insertedRows = vars.get("$field.KeywordAttributeRelations.insertedRows");
+    var changedRows = vars.get("$field.KeywordAttributeRelations.changedRows");
+    var deletedRows = vars.get("$field.KeywordAttributeRelations.deletedRows");
+
+    var storedRows = db.table(SqlCondition.begin()
+        .andPrepare("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID", vars.get("$field.AB_KEYWORD_ENTRYID"))
+        .buildSql("select AB_KEYWORD_ATTRIBUTERELATIONID, AB_KEYWORD_ATTRIBUTE_ID from AB_KEYWORD_ATTRIBUTERELATION"));
+    
+    var attributeChanges = {};
+
+    if (deletedRows)
+        deletedRows.forEach(function (row)
+        {
+            this[row.AB_KEYWORD_ATTRIBUTERELATIONID] = "";
+        }, attributeChanges);
+    
+    if (changedRows)
+        changedRows.forEach(function (row)
+        {
+            this[row.AB_KEYWORD_ATTRIBUTERELATIONID] = row.AB_KEYWORD_ATTRIBUTE_ID;
+        }, attributeChanges);
+    
+    var countObj = {};
+
+    storedRows.forEach(function ([storedAttrRelationId, storedAttributeId]) {
+        var currentAttributeId = storedAttributeId;
+        //merging the data that is stored in the DB and the provided changes
+        if (attributeChanges && storedAttrRelationId in attributeChanges)
+            currentAttributeId = attributeChanges[storedAttrRelationId];
+        
+        // it doesn't matter if a row has been deleted or if the attribute has been set to "nothing"
+        if (currentAttributeId == "")
+            _decrCount(storedAttributeId);
+        else
+        {
+            _incrCount(currentAttributeId);
+            if (currentAttributeId != storedAttributeId)
+                _decrCount(storedAttributeId);
+        }
+    });
+    
+    if (insertedRows) //append the new rows
+    {
+        insertedRows.forEach(function (row)
+        {
+            this[row.AB_KEYWORD_ATTRIBUTE_ID] = (this[row.AB_KEYWORD_ATTRIBUTE_ID] || 0) + 1;
+        }, countObj);
+    }
+    
+    for (let id in countObj)
+        if (countObj[id] > 1)
+            return false;
+    
+    return true;
+
+    function _incrCount (pAttributeId)
+    {
+        if (countObj[pAttributeId])
+            countObj[pAttributeId]++;
+        else
+            countObj[pAttributeId] = 1;
+    }
+    
+    function _decrCount (pAttributeId)
+    {
+        if (countObj[pAttributeId])
+            countObj[pAttributeId]--;
+        else
+            countObj[pAttributeId] = 0;
+    }
+}
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/children/keywordentryid_param/valueProcess.js b/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/children/keywordentryid_param/valueProcess.js
deleted file mode 100644
index 53afbdfbbfe9044ca0a5af0984365d6b2ee5bdba..0000000000000000000000000000000000000000
--- a/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/children/keywordentryid_param/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.AB_KEYWORD_ENTRYID"));
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/documentation.adoc b/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/documentation.adoc
deleted file mode 100644
index 99874edc30d1b8340662c802a9b2b4ef1da0fcdd..0000000000000000000000000000000000000000
--- a/entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/documentation.adoc
+++ /dev/null
@@ -1,2 +0,0 @@
-Since it's not possible to limit the keywordAttributeRelation to a distinctive list (use a KeywordAttributeRelation "category" only once per keyowrd-entry) within the generic-multiple-template / titledList-template use this readonly consumer there.
-For editing use the not-read-only consumer in a list-template. In a list-template only one row can be changed (and stored) which means we can exlucde already stored entries.
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/onValidation.js b/entity/KeywordEntry_entity/onValidation.js
index f1f568a35c02d5f14032daa227f765538d92b5a1..c2eb1f2b7173988bef7fb4997a2853cfe5f2514b 100644
--- a/entity/KeywordEntry_entity/onValidation.js
+++ b/entity/KeywordEntry_entity/onValidation.js
@@ -1,22 +1,22 @@
-import("system.translate");
-import("system.db");
-import("system.vars");
-import("system.text");
-import("system.neon");
-import("Sql_lib");
-
-//TODO: this should no happen in onValidation; waiting for #1032668
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-{
-    var keyContainer = vars.get("$field.CONTAINER");
-    if (keyContainer)
-    {
-        var cond = SqlCondition.begin().andPrepare("AB_KEYWORD_ENTRY.CONTAINER", keyContainer);
-        var maskingHelper = new SqlMaskingUtils();
-        var newCodeNumber = db.cell(cond.buildSql("select " + maskingHelper.max("AB_KEYWORD_ENTRY.SORTING") + " from AB_KEYWORD_ENTRY", "1 = 2"));
-        newCodeNumber = Number(newCodeNumber);//if no number exists till no, start value will be 1 (due to: ++0)
-        if (isNaN(newCodeNumber))
-            throw new TypeError(translate.text("The code number is not a valid number."));
-        neon.setFieldValue("$field.SORTING", ++newCodeNumber);
-    }
-}
\ No newline at end of file
+import("system.translate");
+import("system.db");
+import("system.vars");
+import("system.text");
+import("system.neon");
+import("Sql_lib");
+
+//TODO: this should no happen in onValidation; waiting for #1032668
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+{
+    var keyContainer = vars.get("$field.CONTAINER");
+    if (keyContainer)
+    {
+        var cond = SqlCondition.begin().andPrepare("AB_KEYWORD_ENTRY.CONTAINER", keyContainer);
+        var maskingHelper = new SqlMaskingUtils();
+        var newCodeNumber = db.cell(cond.buildSql("select " + maskingHelper.max("AB_KEYWORD_ENTRY.SORTING") + " from AB_KEYWORD_ENTRY", "1 = 2"));
+        newCodeNumber = Number(newCodeNumber);//if no number exists till no, start value will be 1 (due to: ++0)
+        if (isNaN(newCodeNumber))
+            throw new TypeError(translate.text("The code number is not a valid number."));
+        neon.setFieldValue("$field.SORTING", ++newCodeNumber);
+    }
+}
diff --git a/entity/Offer_entity/grantDeleteProcess.js b/entity/Offer_entity/grantDeleteProcess.js
index f95c719463a913f0dfef05cfee0712e084c530ce..287fe5261292fbc1d33f3a86cd673877ff688166 100644
--- a/entity/Offer_entity/grantDeleteProcess.js
+++ b/entity/Offer_entity/grantDeleteProcess.js
@@ -1,5 +1,11 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
 import("system.vars");
 import("system.result");
 import("Offer_lib");
 
-result.string(OfferUtils.isDeletable(vars.get("$field.STATUS")));
\ No newline at end of file
+result.string(OfferUtils.isDeletable(vars.get("$field.STATUS")) 
+    && !DocumentUtil.hasDocuments("OFFER", null, vars.get("$field.OFFERID"))
+    && !TaskUtils.hasTasks(vars.get("$field.OFFERID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.OFFERID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Order_entity/Order_entity.aod b/entity/Order_entity/Order_entity.aod
index b27c96486412e7b1d1c0452ff86f503639a96f91..cd7a58cb1a019442e35c2aed261a556f8679a47f 100644
--- a/entity/Order_entity/Order_entity.aod
+++ b/entity/Order_entity/Order_entity.aod
@@ -4,6 +4,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Order_entity/documentation.adoc</documentation>
   <title>Receipt</title>
+  <grantDeleteProcess>%aditoprj%/entity/Order_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Order_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Order_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:DOLLAR</iconId>
diff --git a/entity/Order_entity/grantDeleteProcess.js b/entity/Order_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c869b71df47f48eb14648ab83bf80b4f2f507da9
--- /dev/null
+++ b/entity/Order_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("SALESORDER", null, vars.get("$field.SALESORDERID"))
+    && !TaskUtils.hasTasks(vars.get("$field.SALESORDERID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.SALESORDERID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 57236fe7a5073a4254134c34ffaf37dd373baa4e..9c6be4d360b55f49070409d68eccf69635b04f1e 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -5,6 +5,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Organisation_entity/documentation.adoc</documentation>
   <title>Company</title>
+  <grantDeleteProcess>%aditoprj%/entity/Organisation_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Organisation_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Organisation_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:BUILDING</iconId>
diff --git a/entity/Organisation_entity/grantDeleteProcess.js b/entity/Organisation_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c4ebf40c41f7ba44d1ff79e91b77b0487c59475f
--- /dev/null
+++ b/entity/Organisation_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("CONTACT", null, vars.get("$field.CONTACTID"))
+    && !TaskUtils.hasTasks(vars.get("$field.CONTACTID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.CONTACTID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 173c4ae05abc00a61d9958578128942a1e0b80f0..01df9b5d5527da847f9cbf781a4bca691c827317 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -5,6 +5,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Person_entity/documentation.adoc</documentation>
   <title>Contact</title>
+  <grantDeleteProcess>%aditoprj%/entity/Person_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Person_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Person_entity/afterUiInit.js</afterUiInit>
   <onValidation>%aditoprj%/entity/Person_entity/onValidation.js</onValidation>
diff --git a/entity/Person_entity/grantDeleteProcess.js b/entity/Person_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c4ebf40c41f7ba44d1ff79e91b77b0487c59475f
--- /dev/null
+++ b/entity/Person_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("CONTACT", null, vars.get("$field.CONTACTID"))
+    && !TaskUtils.hasTasks(vars.get("$field.CONTACTID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.CONTACTID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Product_entity/Product_entity.aod b/entity/Product_entity/Product_entity.aod
index 75d32f10f632ee2e1e66618a76b20692e3bfcae6..4c47769977d0edd85bf5c1e491118a45d3ccaf64 100644
--- a/entity/Product_entity/Product_entity.aod
+++ b/entity/Product_entity/Product_entity.aod
@@ -7,6 +7,7 @@
   <siblings>
     <element>Productprice_entity</element>
   </siblings>
+  <grantDeleteProcess>%aditoprj%/entity/Product_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Product_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Product_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:HAMMER</iconId>
diff --git a/entity/Product_entity/grantDeleteProcess.js b/entity/Product_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e60a76ed2f3b62ed97948d8cf55819dc835f59fa
--- /dev/null
+++ b/entity/Product_entity/grantDeleteProcess.js
@@ -0,0 +1,8 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("PRODUCT", null, vars.get("$field.PRODUCTID"))
+    && !ActivityUtils.hasActivities(vars.get("$field.PRODUCTID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/SalesprojectSource_entity/SalesprojectSource_entity.aod b/entity/SalesprojectSource_entity/SalesprojectSource_entity.aod
index 6df54dec07218ba41a79471d288814b7d7ce7b26..82112726caff98dcb9d251b1e3a99453c5a885e9 100644
--- a/entity/SalesprojectSource_entity/SalesprojectSource_entity.aod
+++ b/entity/SalesprojectSource_entity/SalesprojectSource_entity.aod
@@ -91,7 +91,7 @@
       <conditionProcess>%aditoprj%/entity/SalesprojectSource_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
       <linkInformation>
         <linkInformation>
-          <name>d0f986d3-dae8-4266-b3e1-1e006d0367c7</name>
+          <name>fa43b303-700e-43ea-a755-7db8aceffa0f</name>
           <tableName>SALESPROJECT_TOUCHPOINT</tableName>
           <primaryKey>SALESPROJECT_TOUCHPOINTID</primaryKey>
           <isUIDTable v="true" />
@@ -101,12 +101,12 @@
       <recordFieldMappings>
         <dbRecordFieldMapping>
           <name>ENTRYDATE.value</name>
-          <recordfield>SALESPROJECT_SOURCE.ENTRYDATE</recordfield>
+          <recordfield>SALESPROJECT_TOUCHPOINT.ENTRYDATE</recordfield>
           <isFilterable v="true" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>SALESPROJECT_ID.value</name>
-          <recordfield>SALESPROJECT_SOURCE.SALESPROJECT_ID</recordfield>
+          <recordfield>SALESPROJECT_TOUCHPOINT.SALESPROJECT_ID</recordfield>
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>SOURCE.displayValue</name>
@@ -114,7 +114,7 @@
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>INFO.value</name>
-          <recordfield>SALESPROJECT_SOURCE.INFO</recordfield>
+          <recordfield>SALESPROJECT_TOUCHPOINT.INFO</recordfield>
           <isFilterable v="true" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index 2fb1017c7040e26e37cac7b6c1a88b15e02a85d3..636e3b0f6667ff0075e04312724cfd6c58661b48 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -6,6 +6,7 @@
   <siblings>
     <element>SalesprojectMilestone_entity</element>
   </siblings>
+  <grantDeleteProcess>%aditoprj%/entity/Salesproject_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Salesproject_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Salesproject_entity/afterUiInit.js</afterUiInit>
   <onValidation>%aditoprj%/entity/Salesproject_entity/onValidation.js</onValidation>
diff --git a/entity/Salesproject_entity/grantDeleteProcess.js b/entity/Salesproject_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..66d8dcc67dbfa7addfbe250d3e1c6a074bb84a3a
--- /dev/null
+++ b/entity/Salesproject_entity/grantDeleteProcess.js
@@ -0,0 +1,9 @@
+import("Context_lib");
+import("ActivityTask_lib");
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("SALESPROJECT", null, vars.get("$field.SALESPROJECTID"))
+    && !TaskUtils.hasTasks(vars.get("$field.SALESPROJECTID"), ContextUtils.getCurrentContextId())
+    && !ActivityUtils.hasActivities(vars.get("$field.SALESPROJECTID"), ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/recordcontainers/db/onDBDelete.js b/entity/Salesproject_entity/recordcontainers/db/onDBDelete.js
index 1012ac8639bb3c66676962031a57ad95056b2102..805d98d50d962a373d80080c279a10a9a2b34938 100644
--- a/entity/Salesproject_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Salesproject_entity/recordcontainers/db/onDBDelete.js
@@ -9,7 +9,7 @@ if (currentId)
 {
     var toDelete = [
     "SALESPROJECT_MILESTONE",
-    "SALESPROJECT_SOURCE"
+    "SALESPROJECT_TOUCHPOINT"
     ];
     
         
diff --git a/entity/Task_entity/Task_entity.aod b/entity/Task_entity/Task_entity.aod
index e86a9791de5f7858bcf746cf246ee58dd36db2c1..701cceee3729ed3762d8666867f38c0de2365dcc 100644
--- a/entity/Task_entity/Task_entity.aod
+++ b/entity/Task_entity/Task_entity.aod
@@ -4,6 +4,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Task_entity/documentation.adoc</documentation>
   <title>Task</title>
+  <grantDeleteProcess>%aditoprj%/entity/Task_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Task_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Task_entity/afterUiInit.js</afterUiInit>
   <onValidation>%aditoprj%/entity/Task_entity/onValidation.js</onValidation>
@@ -54,6 +55,7 @@
       <consumer>ContactEditors</consumer>
       <linkedContext>Person</linkedContext>
       <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Task_entity/entityfields/editor_contact_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Task_entity/entityfields/editor_contact_id/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
diff --git a/entity/Task_entity/entityfields/editor_contact_id/valueProcess.js b/entity/Task_entity/entityfields/editor_contact_id/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4cc8f2bb8a1e0399e937fc1ad3db093f4c0c590c
--- /dev/null
+++ b/entity/Task_entity/entityfields/editor_contact_id/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("Employee_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null)
+    result.string(EmployeeUtils.getCurrentContactId());
\ No newline at end of file
diff --git a/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js b/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js
index 1e62e7551ccb20b0b0d7aca34f64b6e448b5dda7..4cc8f2bb8a1e0399e937fc1ad3db093f4c0c590c 100644
--- a/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js
+++ b/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js
@@ -1,7 +1,7 @@
-import("system.result");
-import("system.neon");
-import("system.vars");
-import("Employee_lib");
-
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("Employee_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null)
     result.string(EmployeeUtils.getCurrentContactId());
\ No newline at end of file
diff --git a/entity/Task_entity/grantDeleteProcess.js b/entity/Task_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..33915f18594e33e4aa413f9e737dd36158c312f3
--- /dev/null
+++ b/entity/Task_entity/grantDeleteProcess.js
@@ -0,0 +1,5 @@
+import("Document_lib");
+import("system.vars");
+import("system.result");
+
+result.string(!DocumentUtil.hasDocuments("TASK", null, vars.get("$field.TASKID")));
\ No newline at end of file
diff --git a/neonContext/KeywordEntry/KeywordEntry.aod b/neonContext/KeywordEntry/KeywordEntry.aod
index 9c8eee02ee349531f5f2bb4cf2bdcfcdb084fc5d..a42880585c7a8d5b9a2eaccd30fa44fbf0e38a33 100644
--- a/neonContext/KeywordEntry/KeywordEntry.aod
+++ b/neonContext/KeywordEntry/KeywordEntry.aod
@@ -4,7 +4,6 @@
   <title>Keyword</title>
   <description>&lt;null value&gt;</description>
   <majorModelMode>DISTRIBUTED</majorModelMode>
-  <mainview>KeywordEntryMain_view</mainview>
   <filterview>KeywordEntryFilter_view</filterview>
   <editview>KeywordEntryEdit_view</editview>
   <preview>KeywordEntryPreview_view</preview>
@@ -22,13 +21,5 @@
       <name>9bb352b9-5a8c-41ac-9c42-7f4f7f4827f3</name>
       <view>KeywordEntryPreview_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>bba3520e-3e12-44e9-89dc-b42183e332ec</name>
-      <view>KeywordEntryMain_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>fb697cca-5e7d-4814-a6ed-09f32f9f60fd</name>
-      <view>KeywordEntryMainSide_view</view>
-    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonView/AppointmentFilter_view/AppointmentFilter_view.aod b/neonView/AppointmentFilter_view/AppointmentFilter_view.aod
index 5556dfaab0549b3edf2d36b9c2a8261d4edd8955..25b8a93be92ab8f05e1972fdb958af5c5bddde70 100644
--- a/neonView/AppointmentFilter_view/AppointmentFilter_view.aod
+++ b/neonView/AppointmentFilter_view/AppointmentFilter_view.aod
@@ -1,38 +1,38 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
-  <name>AppointmentFilter_view</name>
-  <title>Linked Appointments</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <filterable v="false" />
-  <layout>
-    <drawerLayout>
-      <name>layout</name>
-      <layoutCaption>Linked Appointments</layoutCaption>
-    </drawerLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>Table</name>
-      <hideActions v="true" />
-      <entityField>#ENTITY</entityField>
-      <columns>
-        <neonTableColumn>
-          <name>dfc5cdb0-6ff6-4089-b0e7-6ebcab5061e6</name>
-          <entityField>SUMMARY</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>65d462d0-e685-4493-bb73-c32c7ffe393b</name>
-          <entityField>BEGIN</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>ba6f5f7a-7ae4-41cb-940b-c115561c0a71</name>
-          <entityField>END</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>0a591a05-1efe-4e33-9a59-363a5e423802</name>
-          <entityField>LOCATION</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
+  <name>AppointmentFilter_view</name>
+  <title>Linked Appointments</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="false" />
+  <layout>
+    <drawerLayout>
+      <name>layout</name>
+      <layoutCaption>Linked Appointments</layoutCaption>
+    </drawerLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>Table</name>
+      <hideActions v="true" />
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>dfc5cdb0-6ff6-4089-b0e7-6ebcab5061e6</name>
+          <entityField>SUMMARY</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>65d462d0-e685-4493-bb73-c32c7ffe393b</name>
+          <entityField>BEGIN</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>ba6f5f7a-7ae4-41cb-940b-c115561c0a71</name>
+          <entityField>END</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>0a591a05-1efe-4e33-9a59-363a5e423802</name>
+          <entityField>LOCATION</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod b/neonView/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod
deleted file mode 100644
index ba521d29a3bd0a5fd1c27d972ffa3e69c0095ad9..0000000000000000000000000000000000000000
--- a/neonView/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
-  <name>KeywordEntryMainSide_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <cardViewTemplate>
-      <name>Header</name>
-      <titleField>TITLE</titleField>
-      <subtitleField>CONTAINER</subtitleField>
-      <descriptionField>KEYID</descriptionField>
-      <entityField>#ENTITY</entityField>
-    </cardViewTemplate>
-    <genericViewTemplate>
-      <name>Info</name>
-      <entityField>#ENTITY</entityField>
-      <fields>
-        <entityFieldLink>
-          <name>12e16874-32ee-47d7-b9d7-acaa32ca0402</name>
-          <entityField>ISACTIVE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>74f8f491-43e2-4de5-b1c6-c83055b4ffa1</name>
-          <entityField>ISESSENTIAL</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>5608493f-90b5-4baf-9114-63cb6a2e85bf</name>
-          <entityField>SORTING</entityField>
-        </entityFieldLink>
-      </fields>
-    </genericViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/KeywordEntryMain_view/KeywordEntryMain_view.aod b/neonView/KeywordEntryMain_view/KeywordEntryMain_view.aod
deleted file mode 100644
index b69aaabd14c5ec792cc4d698b6f2413432182448..0000000000000000000000000000000000000000
--- a/neonView/KeywordEntryMain_view/KeywordEntryMain_view.aod
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
-  <name>KeywordEntryMain_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <masterSlaveLayout>
-      <name>layout</name>
-      <master>267eb426-08d6-4699-9b9f-743c9c071463</master>
-    </masterSlaveLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>267eb426-08d6-4699-9b9f-743c9c071463</name>
-      <entityField>#ENTITY</entityField>
-      <view>KeywordEntryMainSide_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>e722eb4b-5737-4801-b6e4-550fca43963a</name>
-      <entityField>KeywordAttributeRelations</entityField>
-      <view>KeywordAttributeRelationRows_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod b/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
index d37f7f0daca3b999173c7031e7da6278adb5d688..c169f74709810b2d1f0caabe23b1c1e075f67722 100644
--- a/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
+++ b/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
@@ -1,45 +1,45 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
-  <name>KeywordEntryPreview_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <headerFooterLayout>
-      <name>layout</name>
-      <header>Header</header>
-    </headerFooterLayout>
-  </layout>
-  <children>
-    <cardViewTemplate>
-      <name>Header</name>
-      <titleField>TITLE</titleField>
-      <subtitleField>CONTAINER</subtitleField>
-      <descriptionField>KEYID</descriptionField>
-      <entityField>#ENTITY</entityField>
-    </cardViewTemplate>
-    <genericViewTemplate>
-      <name>Info</name>
-      <showDrawer v="true" />
-      <entityField>#ENTITY</entityField>
-      <title></title>
-      <fields>
-        <entityFieldLink>
-          <name>8455ebce-3bc2-4b0c-8e80-ec3795202d0e</name>
-          <entityField>ISACTIVE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>4b0bb3a6-5457-4eee-b0d8-6ec4b23c0aa7</name>
-          <entityField>ISESSENTIAL</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>30d80ba1-235e-4b4a-9e9c-2b63f70f87b5</name>
-          <entityField>SORTING</entityField>
-        </entityFieldLink>
-      </fields>
-    </genericViewTemplate>
-    <neonViewReference>
-      <name>31f3e341-19b3-452e-a381-942c9860f696</name>
-      <entityField>KeywordAttributeRelationsReadOnly</entityField>
-      <view>KeywordAttriubteRelationTitled_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.2">
+  <name>KeywordEntryPreview_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <headerFooterLayout>
+      <name>layout</name>
+      <header>Header</header>
+    </headerFooterLayout>
+  </layout>
+  <children>
+    <cardViewTemplate>
+      <name>Header</name>
+      <titleField>TITLE</titleField>
+      <subtitleField>CONTAINER</subtitleField>
+      <descriptionField>KEYID</descriptionField>
+      <entityField>#ENTITY</entityField>
+    </cardViewTemplate>
+    <genericViewTemplate>
+      <name>Info</name>
+      <showDrawer v="true" />
+      <entityField>#ENTITY</entityField>
+      <title></title>
+      <fields>
+        <entityFieldLink>
+          <name>8455ebce-3bc2-4b0c-8e80-ec3795202d0e</name>
+          <entityField>ISACTIVE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>4b0bb3a6-5457-4eee-b0d8-6ec4b23c0aa7</name>
+          <entityField>ISESSENTIAL</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>30d80ba1-235e-4b4a-9e9c-2b63f70f87b5</name>
+          <entityField>SORTING</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <neonViewReference>
+      <name>31f3e341-19b3-452e-a381-942c9860f696</name>
+      <entityField>KeywordAttributeRelations</entityField>
+      <view>KeywordAttriubteRelationTitled_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/process/ActivityTask_lib/process.js b/process/ActivityTask_lib/process.js
index 56174a6a884885858ea8cdf9f3d28c6f4169c9ed..3987c9533e07e9ca7a30e8f5bf68e0035a4900b9 100644
--- a/process/ActivityTask_lib/process.js
+++ b/process/ActivityTask_lib/process.js
@@ -1,339 +1,353 @@
-import("system.logging");
-import("Binary_lib");
-import("system.vars");
-import("system.util");
-import("system.datetime");
-import("system.text");
-import("system.neon");
-import("system.db");
-import("system.translate");
-import("system.eMath");
-import("Util_lib");
-import("Sql_lib");
-import("Keyword_lib");
-import("KeywordRegistry_basic");
-import("Product_lib");
-import("Report_lib");
-import("Context_lib");
-
-/**
- * Methods used by for activities (former history).
- * Do not create an instance of this!
- * 
- * @class
- */
-function ActivityUtils() {}
-
-/**
- * Create a new activity within the database-scope.
- * This funciton will insert a complete new activity into the Database
- * 
- * @param {Object} [pDataPreset={}] an object that contains the data for the activity, you do not need to specify any preset data at all,
- *                                  but you CAN define the following properties: 
- *                                  <ul>
- *                                  <li>activityId</li>
- *                                  <li>responsibleContactId</li>
- *                                  <li>categoryKeywordId</li>
- *                                  <li>directionKeywordId</li>
- *                                  <li>subject</li>
- *                                  <li>content</li>
- *                                  </ul>
- * @param {Array} [pActivityLinks] 2D array where each element is an array of Contextname and objectid, for example:
- *                                 <pre>[["Organisation", "2d1e505c-a75a-4fa6-826b-7224a97d5b51"]]</pre>
-  * @param {Array} [pDocuments] 2D array where each element is an array of:
-   *                                <ul>
- *                                  <li>document-name</li>
- *                                  <li>document-content(base64-string)</li>
- *                                  <li>true/false if it's mainDocument or not</li>
- *                                  </ul>
- *                                  for example:
- *                                  <pre>[["number.txt", "MDExOCA5OTkgODgxIDk5OSAxMTkgNzI1IDM", true]]</pre>
- * @param {String} [pDbAlias=current db alias] database alias where the activity shall be inserted
- * 
- * @return {Object} js object where the following are filled:
- *                                  <ul>
- *                                  <li>activityId</li>
- *                                  </ul>
- */
-ActivityUtils.insertNewActivity = function(pDataPreset, pActivityLinks, pDocuments, pDbAlias)
-{
-    var dataPreset = pDataPreset || {};
-    var dbAlias = pDbAlias || db.getCurrentAlias();
-    var insertStatements = [];
-    
-    var creationUser = vars.get("$sys.user");
-    var creationDate = datetime.date();
-    
-    var activityId = dataPreset.activityId || util.getNewUUID();
-    var entrydate = pDataPreset.entrydate || creationDate;
-
-    var activityColumns = ["ACTIVITYID", "DATE_NEW", "USER_NEW", "ENTRYDATE"];
-    var activityValues = [activityId, creationDate, creationUser, entrydate];
-    
-    _addActivityCol("CATEGORY", dataPreset.categoryKeywordId);
-    _addActivityCol("DIRECTION", dataPreset.directionKeywordId);
-    _addActivityCol("INFO", dataPreset.content);
-    _addActivityCol("RESPONSIBLE", dataPreset.responsibleContactId);
-    _addActivityCol("SUBJECT", dataPreset.subject);
-    
-    insertStatements.push(["ACTIVITY", activityColumns, db.getColumnTypes("ACTIVITY", activityColumns, dbAlias), activityValues]);
-
-    if (pActivityLinks)
-    {
-        var activityLinkColumns = ["ACTIVITYLINKID", "ACTIVITY_ID", "DATE_NEW", "USER_NEW", "OBJECT_TYPE", "OBJECT_ROWID"];
-        var activityLinkColumnTypes = db.getColumnTypes("ACTIVITYLINK", activityLinkColumns, dbAlias);
-        var activityLinkValues;
-        for (var i = 0, l = pActivityLinks.length; i < l; i++)
-        {
-            activityLinkValues = [util.getNewUUID(), activityId, creationDate, creationUser, pActivityLinks[i][0], pActivityLinks[i][1]];
-            insertStatements.push(["ACTIVITYLINK", activityLinkColumns, activityLinkColumnTypes, activityLinkValues]);
-        }
-    }
-    
-    db.inserts(insertStatements, dbAlias);
-    
-    if (pDocuments)
-        ActivityUtils.insertDocuments(activityId, pDocuments);
-
-    return {
-        activityId: activityId
-    };
-
-    function _addActivityCol(pColumn, pValue, pDefaultValue)
-    {
-        if (pValue || pDefaultValue)
-        {
-            activityColumns.push(pColumn);
-            activityValues.push(pValue || pDefaultValue);
-        }
-    }
-};
-
-/**
- * inserts documents for an activity
- * 
- * @param {String} pActivityId activity id
- * @param {Array} pDocuments 2D array where each element is an array of:
- *                                  <ul>
- *                                  <li>document-name</li>
- *                                  <li>document-content(base64-string)</li>
- *                                  <li>true/false if it's mainDocument or not</li>
- *                                  </ul>
- *                                  for example:
- *                                  <pre>[["number.txt", "MDExOCA5OTkgODgxIDk5OSAxMTkgNzI1IDM", true]]</pre>
- */
-ActivityUtils.insertDocuments = function (pActivityId, pDocuments)
-{
-    pDocuments.forEach(function (document)
-    {
-        var filename, b64Content, isMainDocument;
-        [filename, b64Content, isMainDocument] = document;
-        if (isMainDocument)
-            SingleBinaryUtils.insertMainDocument("ACTIVITY", "DOCUMENT", pActivityId, b64Content, filename);
-        else
-            SingleBinaryUtils.insert("ACTIVITY", "DOCUMENT", pActivityId, b64Content, filename);
-    });
-}
-
-/**
- * Create a new activity
- */
-ActivityUtils.createNewActivity = function(pRowId, pAdditionalLinks, pParentContext, pParentId, pSubject, pInfo, pDirection, pDocuments)
-{
-    var params = {};
-    if (pDocuments)
-        params["PresetDocuments_param"] = JSON.stringify(pDocuments);
-    if (pSubject)
-        params["Subject_param"] = pSubject;
-    if (pInfo)
-        params["Info_param"] = text.text2html(pInfo.trim(), false);
-    if (pDirection)
-        params["Direction_param"] = pDirection;
-    
-    _ActivityTaskUtils._createNew("Activity", pRowId, pAdditionalLinks, pParentContext, pParentId, params)
-}
-
-/*
- * Gets the date of the last activity
- * 
- * @param {String} pRowId the rowid of the dataset
- * 
- * @return {number|null} the date of the last actvity as long
- */
-ActivityUtils.getLastActivityDate = function(pRowId)
-{
-    var context = ContextUtils.getCurrentContextId();
-    var sqlUtil = new SqlMaskingUtils();
-    var activitySql = "select " + sqlUtil.max("ENTRYDATE") + " from ACTIVITY "
-        + " join ACTIVITYLINK on ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID";
-    activitySql = SqlCondition.begin()
-        .andPrepare("ACTIVITYLINK.OBJECT_TYPE", context)
-        .andPrepare("ACTIVITYLINK.OBJECT_ROWID", pRowId)
-        .buildSql(activitySql);
-    
-    var entryDate = db.cell(activitySql);
-    if (entryDate != "")
-        return parseInt(entryDate);
-    return null;
-}
-
-/**
- * add the links to the link-table in new mode
- * 
- * @return {String} pObjectIdField jdito Field for the objectId
- * @return {String} pRowIdField jdito Field for the rowId
- * @return {String} pAdditionalLinksField jdito Field for additional links
- */
-ActivityUtils.addLinkRecords= function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField)
-{
-    _ActivityTaskUtils._addLinkRecords(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, "Links");
-}
-
-/**
- * Methods used by for tasks.
- * Do not create an instance of this!
- * 
- * @class
- */
-function TaskUtils () {}
-   
-
-/**
- * Create a new task
- */
-TaskUtils.createNewTask = function(pRowId, pAdditionalLinks, pParentContext, pParentId, pParams, pDocuments)
-{
-    _ActivityTaskUtils._createNew("Task", pRowId, pAdditionalLinks, pParentContext, pParentId, pParams, pDocuments)
-}
-
-/**
- * Create a new task
- */
-TaskUtils.hasTasks = function(pRowId, pObjectType)
-{
-    if (pRowId != "" && pObjectType != "")
-    {
-        var cond = SqlCondition.begin().andPrepare("TASKLINK.OBJECT_TYPE", pObjectType)
-                                       .andPrepare("TASKLINK.OBJECT_ROWID", pRowId);
-        var taskCount = db.cell(cond.buildSql("select count(*) from TASKLINK"));
-        if (taskCount != "0")
-            return true;
-        else 
-            return false;
-    }
-    else
-        return true;
-}
-
-TaskUtils.getStatusIcon = function(pStatus)
-{
-    return KeywordUtils.getAttributeRelation(pStatus, $KeywordRegistry.taskStatus(), "icon", "NEON:STATUS_NOT_STARTED");
-}
-
-/**
- * add the links to the link-table in new mode
- * 
- * @return {String} pObjectIdField jdito Field for the objectId
- * @return {String} pRowIdField jdito Field for the rowId
- * @return {String} pAdditionalLinksField jdito Field for additional links
- */
-TaskUtils.addLinkRecords= function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField)
-{
-    _ActivityTaskUtils._addLinkRecords(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, "Links");
-}
-
-/**
- * Methods used by for tasks.
- * Do not create an instance of this!
- * 
- * @ignore
- * @class
- */
-function _ActivityTaskUtils() {}
-   
-
-/**
- * Create a new task
- * @ignore
- */
-_ActivityTaskUtils._createNew = function(pContext, pRowId, pAdditionalLinks, pParentContext, pParentId, pParams)
-{
-    if (pAdditionalLinks == undefined)
-        pAdditionalLinks = [];
-       
-    var params = {};
-    
-    if (pParams)
-        params = pParams
-     
-    if (pRowId)
-    {
-        params["ObjectId_param"] = ContextUtils.getCurrentContextId();
-        params["RowId_param"] = pRowId;
-    }
-        
-    params["PresetLinks_param"] = JSON.stringify(pAdditionalLinks);
-    
-    if (pParentContext && pParentId)
-    {
-        
-        
-        params["ParentContext_param"] = pParentContext;
-        params["ParentId_param"] = pParentId;
-    }
-    
-    neon.openContext(pContext, null, null, neon.OPERATINGSTATE_NEW, params);
-}
-
-/**
- * add the links to the link-table in new mode
- * 
- * @return {String} pObjectIdField jdito Field for the objectId
- * @return {String} pRowIdField jdito Field for the rowId
- * @return {String} pAdditionalLinksField jdito Field for additional links
- * 
- * @ignore
- */
-_ActivityTaskUtils._addLinkRecords = function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, pConsumerName)
-{
-    if (vars.exists(pAdditionalLinksField))
-        presetLinks = JSON.parse(vars.getString(pAdditionalLinksField));
-
-    if (!presetLinks)
-        presetLinks = [];
-    
-    if (vars.exists(pRowIdField) && vars.get(pRowIdField)
-        && vars.exists(pObjectIdField) && vars.get(pObjectIdField))
-        presetLinks.push([vars.get(pObjectIdField), vars.get(pRowIdField)]);
-
-    if (vars.exists(pParentContextField) && vars.exists(pParentIdField))
-    {
-        switch (vars.get(pParentContextField))
-        {
-            case "Activity":
-                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
-                             .andPrepare("ACTIVITYLINK.ACTIVITY_ID", vars.get(pParentIdField))
-                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from ACTIVITYLINK", "1=2")));
-                break;
-            case "Task":
-                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
-                             .andPrepare("TASKLINK.TASK_ID", vars.get(pParentIdField))
-                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from TASKLINK", "1=2")));
-                break;
-            case "SupportTicket":
-                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
-                             .andPrepare("TICKET.TICKETID", vars.get(pParentIdField))
-                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from TICKET join TASKLINK on TASKLINK.TASK_ID = TICKET.TASK_ID", "1=2")));
-                break;
-        }
-        
-    }
-
-    presetLinks.forEach(function(link) {
-        neon.addRecord(pConsumerName, {
-            "OBJECT_TYPE" : link[0], 
-            "OBJECT_ROWID" : link[1]
-        });
-    });
-}
-
+import("system.logging");
+import("Binary_lib");
+import("system.vars");
+import("system.util");
+import("system.datetime");
+import("system.text");
+import("system.neon");
+import("system.db");
+import("system.translate");
+import("system.eMath");
+import("Util_lib");
+import("Sql_lib");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+import("Product_lib");
+import("Report_lib");
+import("Context_lib");
+
+/**
+ * Methods used by for activities (former history).
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function ActivityUtils() {}
+
+/**
+ * Create a new activity within the database-scope.
+ * This funciton will insert a complete new activity into the Database
+ * 
+ * @param {Object} [pDataPreset={}] an object that contains the data for the activity, you do not need to specify any preset data at all,
+ *                                  but you CAN define the following properties: 
+ *                                  <ul>
+ *                                  <li>activityId</li>
+ *                                  <li>responsibleContactId</li>
+ *                                  <li>categoryKeywordId</li>
+ *                                  <li>directionKeywordId</li>
+ *                                  <li>subject</li>
+ *                                  <li>content</li>
+ *                                  </ul>
+ * @param {Array} [pActivityLinks] 2D array where each element is an array of Contextname and objectid, for example:
+ *                                 <pre>[["Organisation", "2d1e505c-a75a-4fa6-826b-7224a97d5b51"]]</pre>
+  * @param {Array} [pDocuments] 2D array where each element is an array of:
+   *                                <ul>
+ *                                  <li>document-name</li>
+ *                                  <li>document-content(base64-string)</li>
+ *                                  <li>true/false if it's mainDocument or not</li>
+ *                                  </ul>
+ *                                  for example:
+ *                                  <pre>[["number.txt", "MDExOCA5OTkgODgxIDk5OSAxMTkgNzI1IDM", true]]</pre>
+ * @param {String} [pDbAlias=current db alias] database alias where the activity shall be inserted
+ * 
+ * @return {Object} js object where the following are filled:
+ *                                  <ul>
+ *                                  <li>activityId</li>
+ *                                  </ul>
+ */
+ActivityUtils.insertNewActivity = function(pDataPreset, pActivityLinks, pDocuments, pDbAlias)
+{
+    var dataPreset = pDataPreset || {};
+    var dbAlias = pDbAlias || db.getCurrentAlias();
+    var insertStatements = [];
+    
+    var creationUser = vars.get("$sys.user");
+    var creationDate = datetime.date();
+    
+    var activityId = dataPreset.activityId || util.getNewUUID();
+    var entrydate = pDataPreset.entrydate || creationDate;
+
+    var activityColumns = ["ACTIVITYID", "DATE_NEW", "USER_NEW", "ENTRYDATE"];
+    var activityValues = [activityId, creationDate, creationUser, entrydate];
+    
+    _addActivityCol("CATEGORY", dataPreset.categoryKeywordId);
+    _addActivityCol("DIRECTION", dataPreset.directionKeywordId);
+    _addActivityCol("INFO", dataPreset.content);
+    _addActivityCol("RESPONSIBLE", dataPreset.responsibleContactId);
+    _addActivityCol("SUBJECT", dataPreset.subject);
+    
+    insertStatements.push(["ACTIVITY", activityColumns, db.getColumnTypes("ACTIVITY", activityColumns, dbAlias), activityValues]);
+
+    if (pActivityLinks)
+    {
+        var activityLinkColumns = ["ACTIVITYLINKID", "ACTIVITY_ID", "DATE_NEW", "USER_NEW", "OBJECT_TYPE", "OBJECT_ROWID"];
+        var activityLinkColumnTypes = db.getColumnTypes("ACTIVITYLINK", activityLinkColumns, dbAlias);
+        var activityLinkValues;
+        for (var i = 0, l = pActivityLinks.length; i < l; i++)
+        {
+            activityLinkValues = [util.getNewUUID(), activityId, creationDate, creationUser, pActivityLinks[i][0], pActivityLinks[i][1]];
+            insertStatements.push(["ACTIVITYLINK", activityLinkColumns, activityLinkColumnTypes, activityLinkValues]);
+        }
+    }
+    
+    db.inserts(insertStatements, dbAlias);
+    
+    if (pDocuments)
+        ActivityUtils.insertDocuments(activityId, pDocuments);
+
+    return {
+        activityId: activityId
+    };
+
+    function _addActivityCol(pColumn, pValue, pDefaultValue)
+    {
+        if (pValue || pDefaultValue)
+        {
+            activityColumns.push(pColumn);
+            activityValues.push(pValue || pDefaultValue);
+        }
+    }
+};
+
+/**
+ * inserts documents for an activity
+ * 
+ * @param {String} pActivityId activity id
+ * @param {Array} pDocuments 2D array where each element is an array of:
+ *                                  <ul>
+ *                                  <li>document-name</li>
+ *                                  <li>document-content(base64-string)</li>
+ *                                  <li>true/false if it's mainDocument or not</li>
+ *                                  </ul>
+ *                                  for example:
+ *                                  <pre>[["number.txt", "MDExOCA5OTkgODgxIDk5OSAxMTkgNzI1IDM", true]]</pre>
+ */
+ActivityUtils.insertDocuments = function (pActivityId, pDocuments)
+{
+    pDocuments.forEach(function (document)
+    {
+        var filename, b64Content, isMainDocument;
+        [filename, b64Content, isMainDocument] = document;
+        if (isMainDocument)
+            SingleBinaryUtils.insertMainDocument("ACTIVITY", "DOCUMENT", pActivityId, b64Content, filename);
+        else
+            SingleBinaryUtils.insert("ACTIVITY", "DOCUMENT", pActivityId, b64Content, filename);
+    });
+}
+
+/**
+ * Create a new activity
+ */
+ActivityUtils.createNewActivity = function(pRowId, pAdditionalLinks, pParentContext, pParentId, pSubject, pInfo, pDirection, pDocuments)
+{
+    var params = {};
+    if (pDocuments)
+        params["PresetDocuments_param"] = JSON.stringify(pDocuments);
+    if (pSubject)
+        params["Subject_param"] = pSubject;
+    if (pInfo)
+        params["Info_param"] = text.text2html(pInfo.trim(), false);
+    if (pDirection)
+        params["Direction_param"] = pDirection;
+    
+    _ActivityTaskUtils._createNew("Activity", pRowId, pAdditionalLinks, pParentContext, pParentId, params)
+}
+
+/*
+ * Gets the date of the last activity
+ * 
+ * @param {String} pRowId the rowid of the dataset
+ * 
+ * @return {number|null} the date of the last actvity as long
+ */
+ActivityUtils.getLastActivityDate = function(pRowId)
+{
+    var context = ContextUtils.getCurrentContextId();
+    var sqlUtil = new SqlMaskingUtils();
+    var activitySql = "select " + sqlUtil.max("ENTRYDATE") + " from ACTIVITY "
+        + " join ACTIVITYLINK on ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID";
+    activitySql = SqlCondition.begin()
+        .andPrepare("ACTIVITYLINK.OBJECT_TYPE", context)
+        .andPrepare("ACTIVITYLINK.OBJECT_ROWID", pRowId)
+        .buildSql(activitySql);
+    
+    var entryDate = db.cell(activitySql);
+    if (entryDate != "")
+        return parseInt(entryDate);
+    return null;
+}
+
+/**
+ * add the links to the link-table in new mode
+ * 
+ * @return {String} pObjectIdField jdito Field for the objectId
+ * @return {String} pRowIdField jdito Field for the rowId
+ * @return {String} pAdditionalLinksField jdito Field for additional links
+ */
+ActivityUtils.addLinkRecords= function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField)
+{
+    _ActivityTaskUtils._addLinkRecords(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, "Links");
+}
+
+ActivityUtils.hasActivities = function (pRowId, pObjectType)
+{
+    if (pRowId && pObjectType)
+    {
+        var cond = SqlCondition.begin().andPrepare("ACTIVITYLINK.OBJECT_TYPE", pObjectType)
+                                       .andPrepare("ACTIVITYLINK.OBJECT_ROWID", pRowId);
+        var taskCount = db.cell(cond.buildSql("select count(*) from ACTIVITYLINK"));
+        if (taskCount != "0")
+            return true;
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Methods used by for tasks.
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function TaskUtils () {}
+   
+
+/**
+ * Create a new task
+ */
+TaskUtils.createNewTask = function(pRowId, pAdditionalLinks, pParentContext, pParentId, pParams, pDocuments)
+{
+    _ActivityTaskUtils._createNew("Task", pRowId, pAdditionalLinks, pParentContext, pParentId, pParams, pDocuments)
+}
+
+/**
+ * Create a new task
+ */
+TaskUtils.hasTasks = function(pRowId, pObjectType)
+{
+    if (pRowId != "" && pObjectType != "")
+    {
+        var cond = SqlCondition.begin().andPrepare("TASKLINK.OBJECT_TYPE", pObjectType)
+                                       .andPrepare("TASKLINK.OBJECT_ROWID", pRowId);
+        var taskCount = db.cell(cond.buildSql("select count(*) from TASKLINK"));
+        if (taskCount != "0")
+            return true;
+        else 
+            return false;
+    }
+    else
+        return true;
+}
+
+TaskUtils.getStatusIcon = function(pStatus)
+{
+    return KeywordUtils.getAttributeRelation(pStatus, $KeywordRegistry.taskStatus(), "icon", "NEON:STATUS_NOT_STARTED");
+}
+
+/**
+ * add the links to the link-table in new mode
+ * 
+ * @return {String} pObjectIdField jdito Field for the objectId
+ * @return {String} pRowIdField jdito Field for the rowId
+ * @return {String} pAdditionalLinksField jdito Field for additional links
+ */
+TaskUtils.addLinkRecords= function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField)
+{
+    _ActivityTaskUtils._addLinkRecords(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, "Links");
+}
+
+/**
+ * Methods used by for tasks.
+ * Do not create an instance of this!
+ * 
+ * @ignore
+ * @class
+ */
+function _ActivityTaskUtils() {}
+   
+
+/**
+ * Create a new task
+ * @ignore
+ */
+_ActivityTaskUtils._createNew = function(pContext, pRowId, pAdditionalLinks, pParentContext, pParentId, pParams)
+{
+    if (pAdditionalLinks == undefined)
+        pAdditionalLinks = [];
+       
+    var params = {};
+    
+    if (pParams)
+        params = pParams
+     
+    if (pRowId)
+    {
+        params["ObjectId_param"] = ContextUtils.getCurrentContextId();
+        params["RowId_param"] = pRowId;
+    }
+        
+    params["PresetLinks_param"] = JSON.stringify(pAdditionalLinks);
+    
+    if (pParentContext && pParentId)
+    {
+        
+        
+        params["ParentContext_param"] = pParentContext;
+        params["ParentId_param"] = pParentId;
+    }
+    
+    neon.openContext(pContext, null, null, neon.OPERATINGSTATE_NEW, params);
+}
+
+/**
+ * add the links to the link-table in new mode
+ * 
+ * @return {String} pObjectIdField jdito Field for the objectId
+ * @return {String} pRowIdField jdito Field for the rowId
+ * @return {String} pAdditionalLinksField jdito Field for additional links
+ * 
+ * @ignore
+ */
+_ActivityTaskUtils._addLinkRecords = function(pObjectIdField, pRowIdField, pAdditionalLinksField, pParentContextField, pParentIdField, pConsumerName)
+{
+    if (vars.exists(pAdditionalLinksField))
+        presetLinks = JSON.parse(vars.getString(pAdditionalLinksField));
+
+    if (!presetLinks)
+        presetLinks = [];
+    
+    if (vars.exists(pRowIdField) && vars.get(pRowIdField)
+        && vars.exists(pObjectIdField) && vars.get(pObjectIdField))
+        presetLinks.push([vars.get(pObjectIdField), vars.get(pRowIdField)]);
+
+    if (vars.exists(pParentContextField) && vars.exists(pParentIdField))
+    {
+        switch (vars.get(pParentContextField))
+        {
+            case "Activity":
+                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
+                             .andPrepare("ACTIVITYLINK.ACTIVITY_ID", vars.get(pParentIdField))
+                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from ACTIVITYLINK", "1=2")));
+                break;
+            case "Task":
+                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
+                             .andPrepare("TASKLINK.TASK_ID", vars.get(pParentIdField))
+                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from TASKLINK", "1=2")));
+                break;
+            case "SupportTicket":
+                presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
+                             .andPrepare("TICKET.TICKETID", vars.get(pParentIdField))
+                             .buildSql("select OBJECT_TYPE, OBJECT_ROWID from TICKET join TASKLINK on TASKLINK.TASK_ID = TICKET.TASK_ID", "1=2")));
+                break;
+        }
+        
+    }
+
+    presetLinks.forEach(function(link) {
+        neon.addRecord(pConsumerName, {
+            "OBJECT_TYPE" : link[0], 
+            "OBJECT_ROWID" : link[1]
+        });
+    });
+}
+
diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js
index bf397d874cb4a77486935932f978e110f3f2eac3..0a3b7af1fccdeaca0ea0a10463317ac6c9ce7b80 100644
--- a/process/Attribute_lib/process.js
+++ b/process/Attribute_lib/process.js
@@ -1,1086 +1,1086 @@
-import("KeywordData_lib");
-import("Context_lib");
-import("system.util");
-import("system.datetime");
-import("system.translate");
-import("system.neon");
-import("system.vars");
-import("system.db");
-import("system.project");
-import("system.entities");
-import("Sql_lib");
-import("Keyword_lib");
-
-/**
- * Provides functions for the work with attributes, like
- * listing the available attributes for a context.
- * Don't instanciate this!
- * 
- * @class
- */
-function AttributeUtil () {}
-
-/**
- * Gives an array of all available attributes for a context. This is used in the possibleItems
- * process for the attribute id in AttributeRelation
- * 
- * @param {String} pObjectType the object type (= context)
- * @param {boolean} [pIncludeGroups=false]
- * @param {String[]} [pFilteredAttributeIds=[]] Whitleist of attribute ids
- * @param {Object} [pAttributeCount=null] Object with attribute ids and their count
- * 
- * @return {String[]} array of attributeIds
- */
-AttributeUtil.getPossibleAttributes = function (pObjectType, pIncludeGroups, pFilteredAttributeIds, pAttributeCount)
-{
-    if (pObjectType == null || (pFilteredAttributeIds && pFilteredAttributeIds.length == 0))
-        return [];
-    
-    var attrSql = "select AB_ATTRIBUTEID from AB_ATTRIBUTE"
-        + " join AB_ATTRIBUTEUSAGE  on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID";
-    var attrCond = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
-        .and("ATTRIBUTE_ACTIVE = 1");
-    
-    if (pAttributeCount)
-    {
-        for (let attributeId in pAttributeCount)
-        {
-            attrCond.andSqlCondition(
-                SqlCondition.begin()
-                    .orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", attributeId, "# != ?")
-                    .orPrepare("AB_ATTRIBUTEUSAGE.MAX_COUNT", pAttributeCount[attributeId], "# > ?")
-                    .or("AB_ATTRIBUTEUSAGE.MAX_COUNT is null")
-            );
-        }
-    }
-        
-    if (pFilteredAttributeIds)
-    {
-        var filteredIdsCondition = new SqlCondition();
-        var filteredIdChildren = AttributeUtil.getAllChildren(pFilteredAttributeIds);
-        pFilteredAttributeIds.concat(filteredIdChildren).forEach(function(id) 
-        {
-            this.orPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", id);
-        }, filteredIdsCondition);
-
-        attrCond.andSqlCondition(filteredIdsCondition);
-    }
-
-    if (!pIncludeGroups)
-        attrCond.andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# != ?");
-    
-    var attributes = db.array(db.COLUMN, attrCond.buildSql(attrSql));
-    
-    return attributes;
-}
-
-/**
- * searches for possiblevalues for a atttribute and returns these. The values depend on the attributeType
- * 
- * @param {String} pAttributeId the id of the attribute
- * @param {Boolean} pAttributeType type of the attribute that is specified with pAttributeId;
- *                                 The type needs to be passed to the function for better performance 
- *                                 (loading the type via attribute several times would be too slow)
- * @param {Boolean} [pIncludeInactives=false] specifies if only active attributevalues or actives + inactives shall be returned, 
- *                                            this is important when you want to search for attributevalues 
- * 
- * @return {Array} 2D-array with [ID, value] als elements if the given attributeType has possible items. if not null is returned
- */
-AttributeUtil.getPossibleListValues = function (pAttributeId, pAttributeType, pIncludeInactives)
-{
-    var attributeId = pAttributeId;
-    var attrType = pAttributeType.trim();
-    var onlyActives = (pIncludeInactives == undefined ? false : pIncludeInactives);
-    if (attrType == $AttributeTypes.COMBO.toString())
-    {
-        var valueSql = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", attributeId)
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE);
-        
-        if (onlyActives)
-            valueSql.andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1");
-        
-        valueSql = valueSql.buildSql("select AB_ATTRIBUTEID, ATTRIBUTE_NAME from AB_ATTRIBUTE", "1=2", "order by SORTING asc");
-        var valueList = db.table(valueSql);
-        for (let i = 0; i < valueList.length; i++)
-        {
-            valueList[i][1] = translate.text(valueList[i][1]);
-        }
-        return valueList;
-    }
-    else if (attrType == $AttributeTypes.BOOLEAN.toString())
-    {
-        return [
-            ["1", translate.text("Yes")],
-            ["0", translate.text("No")]
-            ];
-    }
-    else if (attrType == $AttributeTypes.KEYWORD.toString())
-    {
-        var attrKeywordSelect = "select DROPDOWNDEFINITION from AB_ATTRIBUTE";
-        attrKeywordSelect = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeId)
-            .buildSql(attrKeywordSelect);
-        var attrKeyword = db.cell(attrKeywordSelect);
-        var keywords = KeywordData.getSimpleData(attrKeyword, null, onlyActives);
-        return keywords;
-    }
-    else if (attrType == $AttributeTypes.OBJECTSELECTION)
-    {
-        var [module, filter] = db.array(db.ROW, SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeId)
-            .buildSql("select DROPDOWNDEFINITION, DROPDOWNFILTER from AB_ATTRIBUTE")
-            );
-        var objects = [];
-        if (module)
-        {
-            var uid = "#UID";
-            var title = "#CONTENTTITLE";
-            var config = entities.createConfigForLoadingRows()
-                .entity(module)
-                .fields([uid, title]);
-            if (filter)
-                config.filter(filter);
-            var rows = entities.getRows(config);
-            for (let i = 0, l = rows.length; i < l; i++)
-                objects.push([rows[i][uid], rows[i][title]])
-        }
-        return objects;
-    }
-    else
-        return null;
-}
-
-/**
- * returns the name of an attribute with all parent attribute names
- * 
- * @param {String} pAttributeId the id of the attribute
- * @param {Boolean} [pSimpleName=false] Use only the name of the attribute and not the names of the parents.
- * @param {Boolean} [pTranslate=true] translate the name
- * 
- * @return {String} the name of the attribute
- */
-AttributeUtil.getFullAttributeName = function (pAttributeId, pSimpleName, pTranslate) 
-{
-    if (pSimpleName === undefined)
-        pSimpleName = false;
-    if (pTranslate === undefined)
-        pTranslate = true;
-    
-    if (!pAttributeId)
-        return "";
-    if (pSimpleName)
-        return AttributeUtil.getSimpleAttributeName(pAttributeId, pTranslate);
-    var attributeNames = [];
-    var attribute;
-    do {
-        attribute = db.array(db.ROW, SqlCondition.begin()
-            .andPrepare(["AB_ATTRIBUTE", "AB_ATTRIBUTEID", "ATTRIBUTE"], pAttributeId)
-            .buildSql("select ATTRIBUTE.ATTRIBUTE_NAME, PARENT1.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_PARENT_ID \n\
-                from AB_ATTRIBUTE ATTRIBUTE \n\
-                left join AB_ATTRIBUTE PARENT1 on ATTRIBUTE.ATTRIBUTE_PARENT_ID = PARENT1.AB_ATTRIBUTEID \n\
-                left join AB_ATTRIBUTE PARENT2 on PARENT1.ATTRIBUTE_PARENT_ID = PARENT2.AB_ATTRIBUTEID")
-        );
-        if (attribute.length > 0)
-        {
-            attributeNames.push(attribute[0]);
-            if (attribute[1])
-                attributeNames.push(attribute[1]);
-            if (attribute[2])
-                attributeNames.push(attribute[2]);
-            pAttributeId = attribute[3];
-        }
-        else
-            pAttributeId = "";
-    } while (pAttributeId);
-    
-    if (pTranslate)
-    {
-        for (let i = 0; i < attributeNames.length; i++)
-        {
-            attributeNames[i] = translate.text(attributeNames[i]);
-        }
-    }
-    return attributeNames.reverse().join(" / ");
-}
-
-/**
- * returns the name of an attribute
- * 
- * @param {String} pAttributeId the id of the attribute
- * @param {boolean} [pTranslate] if the name should be translated
- * 
- * @return {String} the name of the attribute
- */
-AttributeUtil.getSimpleAttributeName = function (pAttributeId, pTranslate) 
-{
-    var attributeName = db.cell(SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
-        .buildSql("select ATTRIBUTE_NAME from AB_ATTRIBUTE")
-    );
-    if (pTranslate)
-        attributeName = translate.text(attributeName);
-    return attributeName;
-}
-
-/**
- * returns the ids of all subordinated attributes of an attribute
- * 
- * @param {String|Array} pAttributeIds the id(s) of the attribute(s)
- * 
- * @result {String[]} array with the ids of every subordinated attribute
- */
-AttributeUtil.getAllChildren = function (pAttributeIds)
-{
-    var childIds = [];
-    if (typeof(pAttributeIds) == "string")
-        pAttributeIds = [pAttributeIds];
-        
-    while (pAttributeIds.length > 0)
-    {
-        pAttributeIds = db.array(db.COLUMN, SqlCondition.begin()
-            .andIn("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeIds)
-            .buildSql("select AB_ATTRIBUTEID from AB_ATTRIBUTE")
-        );
-        if (pAttributeIds.length > 0)
-            childIds = childIds.concat(pAttributeIds);
-    }
-    return childIds;
-}
-
-/**
- * checks if an attribute has attribute relations
- * 
- * @param {String} pAttributeId the id of the attribute
- * 
- * @result {boolean} true if it has relations
- */
-AttributeUtil.hasRelations = function (pAttributeId)
-{
-    if (!pAttributeId)
-        return false;
-    return db.cell(SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId)
-        .buildSql(
-            "select count(*) from AB_ATTRIBUTERELATION", "1=2" //TODO: is there a way exists could be used?
-        )
-    ) != "0";
-}
-
-/**
- * returns the type of an attribute
- * 
- * @param {String} pAttributeId the id of the attribute
- * 
- * @result {String} attribute type
- */
-AttributeUtil.getAttributeType = function (pAttributeId)
-{
-    if (!pAttributeId)
-        return "";
-    var attrTypeSelect = "select ATTRIBUTE_TYPE from AB_ATTRIBUTE";
-    attrTypeSelect = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
-        .buildSql(attrTypeSelect);
-    return db.cell(attrTypeSelect).trim();
-}
-
-AttributeUtil.hasAttributes = function (pObjectType)
-{
-    if (!pObjectType)
-        return false;
-    return db.cell(SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1")
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# != ?")
-        .buildSql(
-            "select count(*) from AB_ATTRIBUTEUSAGE \n\
-            join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID", "1=2"
-        )
-    ) != "0"; //TODO: is there a way exists could be used?
-}
-
-/*********************************************************************************************************************/
-
-/**
- * Provides functions for the work with attributeRelations, getting the value of an attributeRelation for an object.
- * Don't instanciate this!
- * 
- * @class
- */
-function AttributeRelationUtils () {}
-
-/**
- * gets the value of an attributeRelation for one dataset (e. g. a person)
- * 
- * @param {String} pAttributeId attribute-id
- * @param {String} pObjectRowId row-id of the dataset
- * @param {String} [pObjectType=null] object-type
- * @param {String} [pGetViewValue=false] if true the values are resolved and formatted
- * @param {String} [pGetAttrname=false] if true the attributename is also returned
- * 
- * @return {String|String[]|null} the value of the attribute or an array of attrname and value [attrname, value] (if pGetAttrname is true)
- */
-AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObjectType, pGetViewValue, pGetAttrname)
-{
-    var attrCond = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId)
-        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId);
-    if (pObjectType != null)
-        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
-    
-    var defaultFields = [
-        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
-        "AB_ATTRIBUTE.DROPDOWNDEFINITION", 
-        "COMBOVAL.ATTRIBUTE_NAME"
-    ];
-    
-    if (pGetAttrname)
-        defaultFields.push("AB_ATTRIBUTE.ATTRIBUTE_NAME");    
-    
-    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
-    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
-        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
-        + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
-    
-    var attributeValues = db.array(db.ROW, attributeSql);
-    if (!attributeValues.length)
-        return null;
-    
-    let value = attributeValues[AttributeTypeUtil.getTypeColumnIndex(attributeValues[0]) + defaultFields.length];
-    if (pGetViewValue && attributeValues[1].trim() == $AttributeTypes.COMBO)
-        value = attributeValues[2];
-    else if (pGetViewValue)
-        value = AttributeTypeUtil.getAttributeViewValue(attributeValues[0].trim(), value, attributeValues[1]);
-    
-    if (pGetAttrname)
-        value = [attributeValues[3], value];
-    
-    return value;
-}
-
-/**
- * gets all attributes for a dataset
- * 
- * @param {String} pObjectRowId object rowid
- * @param {String} [pObjectType=null] object-type
- * @param {String} [pUseAttributeIds=0] if 0 the full attribute names are returned
- *                                      if 1 the ids are used instead of the full attribute names
- *                                      if 2 the ids AND the full attribute name is returned
- * @param {String} [pUseIdValues=false] if true the values are not resolved or formatted [attributeId, attributeName, value]
- * 
- * @return {String[][]} two-dimensional array a row is [attributeId|attributeName, value] (or [attributeId, attributeName, value])
- */
-AttributeRelationUtils.getAllAttributes = function (pObjectRowId, pObjectType, pUseAttributeIds, pUseIdValues)
-{
-    var attrCond = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
-    if (pObjectType != null)
-        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
-    
-    var defaultFields = [
-        "AB_ATTRIBUTE_ID", 
-        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
-        "AB_ATTRIBUTE.DROPDOWNDEFINITION", 
-        "COMBOVAL.ATTRIBUTE_NAME"
-    ];
-    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
-    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
-        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
-        + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
-    
-    var attributeNameMap = {};
-    var attributeValues = db.table(attributeSql).map(function (row) 
-    {
-        let attribute = row[0];
-        let attrname;
-        if (pUseAttributeIds == 0 || pUseAttributeIds == 2)
-        {
-            var tmpAttrname = "";
-            if (!(attribute in attributeNameMap))
-                attributeNameMap[attribute] = AttributeUtil.getFullAttributeName(attribute);
-            tmpAttrname = attributeNameMap[attribute];
-            
-            // if mode 0, return only the name
-            if (pUseAttributeIds == 0)
-                attribute = tmpAttrname
-            
-            // if mode 2 return both
-            if (pUseAttributeIds == 2)
-                attrname = tmpAttrname
-        }
-        let value = row[AttributeTypeUtil.getTypeColumnIndex(row[1]) + defaultFields.length];
-        if (!pUseIdValues && row[1].trim() == $AttributeTypes.COMBO)
-            value = row[3];
-        else if (!pUseIdValues)
-            value = AttributeTypeUtil.getAttributeViewValue(row[1].trim(), value, row[2]);
-        
-        // add attrname only if id AND attrname is needed
-        var data = [];
-        
-        data.push(attribute);
-
-        if (attrname)
-            data.push(attrname);
-        
-        data.push(value);
-        return data;
-    });
-    
-    return attributeValues;
-}
-
-/**
- * gets the correct attribute value from a map with values depending on the attribute id
- * 
- * @param {String} pAttributeId the attribute id
- * @param {Object} pValueMap a map with the attribute values and the db fields as keys
- * @param {Boolean} [pGetViewValue=false] if true, get the view value
- * 
- * @return {String|null} the value of the attribute or null if the attribute doesn't exist
- */
-AttributeRelationUtils.selectAttributeValue = function (pAttributeId, pValueMap, pGetViewValue)
-{
-    var sqlSelect = "select ATTRIBUTE_TYPE, DROPDOWNDEFINITION from AB_ATTRIBUTE";
-    var type = db.array(db.ROW, SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
-        .buildSql(sqlSelect)
-    );
-    if (!type.length)
-        return null;
-    
-    type[0] = type[0].trim();
-    var field = AttributeTypeUtil.getDatabaseField(type[0]);
-    var value = pValueMap[field];
-    if (pGetViewValue && type[0] == $AttributeTypes.COMBO)
-    {
-        value = db.cell(SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", value)
-            .buildSql("select ATTRIBUTE_NAME from AB_ATTRIBUTE")
-        );
-    }
-    else if (pGetViewValue)
-        value = AttributeTypeUtil.getAttributeViewValue(type[0], value, type[1]);
-    
-    return value;
-}
-
-AttributeRelationUtils.getAttributes = function ()
-{
-    //TODO: implement maybe
-}
-
-/**
- * sets the value of an attribute for one dataset (e. g. a person)
- */
-AttributeRelationUtils.setAttribute = function ()
-{
-    //TODO: implement
-}
-
-/**
- * adds rows for attributes with min_count > 0
- * 
- * @param {String} pObjectType the object type
- * @param {String} pConsumer the name of the attribute relation consumer
- */
-AttributeRelationUtils.presetMandatoryAttributes = function (pObjectType, pConsumer)
-{
-    var mandatoryAttributes = db.table(
-        SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# <> ?")
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# <> ?")
-            .and("ATTRIBUTE_ACTIVE = 1")
-            .and("MIN_COUNT > 0")
-            .buildSql("select AB_ATTRIBUTE_ID, MIN_COUNT from AB_ATTRIBUTEUSAGE "
-                + "join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTEID")
-    );
-    mandatoryAttributes.forEach(function (usage)
-    {
-        //adding an attribute more than 20 times would be too much (having a min_count > 20 is very unlikely)
-        for (let i = 0; i < usage[1] && i < 20; i++)
-            neon.addRecord(pConsumer, {
-                "AB_ATTRIBUTE_ID" : usage[0]
-            });
-    });
-}
-
-/**
- * Checks if the count of the used attributes is valid and returns a message if it's not.
- * 
- * @param {String} pRowId the row id of the entity
- * @param {String} [pObjectType=null] the object type
- * @param {String} pConsumerField the name of the attribute relation consumer
- * 
- * @return {String} the validation message or an empty string if everything is ok
- */
-AttributeRelationUtils.validateAttributeCount = function (pRowId, pObjectType, pConsumerField)
-{
-    var attributeChanges = {};
-    var deletedRows = vars.get("$field." + pConsumerField + ".deletedRows");
-    var changedRows = vars.get("$field." + pConsumerField + ".changedRows");
-    var insertedRows = vars.get("$field." + pConsumerField + ".insertedRows");
-
-   if (deletedRows)
-    {
-        deletedRows.forEach(function (row)
-        {
-            this[row.UID] = "";
-        }, attributeChanges);
-    }
-    
-    if (changedRows)
-    {
-        changedRows.forEach(function (row)
-        {
-            this[row.UID] = row.AB_ATTRIBUTE_ID;
-        }, attributeChanges);
-    }
-    
-    //get the current count of usages considering the changes
-    //this will merge the counts of attributeChanges and the already stored attributerelations
-    var countObj = AttributeRelationUtils.countAttributeRelations(pRowId, pObjectType, attributeChanges);
-    
-    if (insertedRows) //append the new rows
-    {
-        insertedRows.forEach(function (row)
-        {
-            this[row.AB_ATTRIBUTE_ID] = (this[row.AB_ATTRIBUTE_ID] || 0) + 1;
-        }, countObj);
-    }
-    var attributeCondition = SqlCondition.begin();
-    AttributeUtil.getPossibleAttributes(pObjectType).forEach(function (attributeId)
-    {
-        this.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", attributeId);
-    }, attributeCondition);
-    
-    var usageCondition = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
-        .andSqlCondition(attributeCondition, "1=2");
-    
-    //retrieve all min/max counts of the possible attributes
-    var minMaxCounts = db.table(usageCondition.buildSql(
-          "select AB_ATTRIBUTEID, ATTRIBUTE_NAME, MIN_COUNT, MAX_COUNT from AB_ATTRIBUTEUSAGE \
-           join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID", "1=2"
-    ));
-        
-    var validationMessage = [];
-    minMaxCounts.forEach(function ([attributeId, name, minCount, maxCount])
-    {
-        let count = this[attributeId] || 0;
-        //compares the actual usage with the min and max count and generates a message if the usage is too low or too high
-        if (count < minCount)
-            validationMessage.push(translate.withArguments("Attribute \"%0\" has to be used at least %1.", [name, _getTranslatedCount(minCount)]));
-        if (maxCount && count > maxCount)
-            validationMessage.push(translate.withArguments("Attribute \"%0\" can't be used more than %1.", [name, _getTranslatedCount(maxCount)]));
-    }, countObj);
-    
-    return validationMessage.join("\n");
-    
-    //returns the correct count expression by choosing either singular (1 time) or plural (2 times)
-    function _getTranslatedCount (pCount)
-    {
-        if (pCount == 1)
-            return pCount + " " + translate.text("${COUNT_PREPOSITION_SINGLE}");
-        return pCount + " " + translate.text("${COUNT_PREPOSITION_MULTIPLE}");
-    }
-}
-
-/**
- * counts attribute relations
- * 
- * @param {String} pRowId the row id of the entity
- * @param {String} [pObjectType=null] the object type
- * @param {Object} [pAttributeChanges=null] object containing changes and deletions of attributes
- *                          structure = {attributeRelationId : new attributeId or "" when deleted}
- * 
- * @return {Object} object with attribute ids and the count of the usage (without new rows)
- */
-AttributeRelationUtils.countAttributeRelations = function (pRowId, pObjectType, pAttributeChanges)
-{
-    //use cases:
-    //complete new row ==> increase count by 1 for that attribute [this is done in another function]
-    //row removed ==> decrease count by 1
-    //row edit: replace one attribute by another attribute ==> increase the new attribute count and decrease the old attribute count
-    //row edit: replace attribute with no new value ==> decrease count for the old attribute
-    //unchanged (already stored) row ==> increase count 
-    var countObj = {};
-
-    var condition = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pRowId)
-        .andPrepareIfSet("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
-
-    var storedAttributeRelations = db.table(condition.buildSql(
-        "select AB_ATTRIBUTERELATIONID, AB_ATTRIBUTE_ID from AB_ATTRIBUTERELATION",
-        "1=2"
-    ));
-
-    storedAttributeRelations.forEach(function ([storedAttrRelationId, storedAttributeId]) {
-        var currentAttributeId = storedAttributeId;
-        //merging the data that is stored in the DB and the provided changes
-        if (pAttributeChanges && storedAttrRelationId in pAttributeChanges)
-            currentAttributeId = pAttributeChanges[storedAttrRelationId];
-        
-        // it doesn't matter if a row has been deleted or if the attribute has been set to "nothing"
-        if (currentAttributeId == "")
-            _decrCount(storedAttributeId);
-        else
-        {
-            _incrCount(currentAttributeId);
-            if (currentAttributeId != storedAttributeId)
-                _decrCount(storedAttributeId);
-        }
-    });
-    
-    function _incrCount(pAttributeId)
-    {
-        if (countObj[pAttributeId])
-            countObj[pAttributeId]++;
-        else
-            countObj[pAttributeId] = 1;
-    }
-    
-    function _decrCount(pAttributeId)
-    {
-        if (countObj[pAttributeId])
-            countObj[pAttributeId]--;
-        else
-            countObj[pAttributeId] = 0;
-    }
-    
-    return countObj;
-}
-
-/*********************************************************************************************************************/
-
-
-/**
- * Object for the enumeration and management of all attribute types.
- * This Object is only for the general definition of attribute types and for getting
- * data about every type, anything that has to do with a specific attribute (= the function requires an attribute id)
- * should be done in AttributeUtils.
- * The required values and methods for each type are:
- * 
- * toString = function that should return a unique name
- * contentType = the value that is returned in the contentType process for the attribute
- * databaseField = the database field that holds values of attributes with the type
- * 
- * optional:
- * getViewValue = function that gets the display value for a given value
- * isGroup = if true, the attribute can have children
- * getDropDownDefinitions = function that returns an array of possible values
- *          for DROPDOWNDEFINITION
- * 
- * The display name is controlled by the keyword 'AttributeType'
- */
-function $AttributeTypes () {}
-
-$AttributeTypes.TEXT = { 
-    toString : function () {return "TEXT";},
-    contentType : "TEXT", 
-    databaseField : "CHAR_VALUE"
-};
-$AttributeTypes.DATE = {
-    toString : function () {return "DATE";},
-    contentType : "DATE", 
-    databaseField : "DATE_VALUE",
-    getViewValue : function (pValue)
-        {
-            return datetime.toDate(pValue, translate.text("dd.MM.yyyy"));
-        }
-};
-$AttributeTypes.NUMBER = {
-    toString : function () {return  "NUMBER";},
-    contentType : "NUMBER", 
-    databaseField : "NUMBER_VALUE"
-};
-$AttributeTypes.BOOLEAN = {
-    toString : function () {return "BOOLEAN";},
-    contentType : "BOOLEAN", 
-    databaseField : "INT_VALUE",
-    getViewValue : function (pValue)
-        {
-            return pValue == "1" ? translate.text("Yes") : translate.text("No");
-        }
-};
-$AttributeTypes.COMBO = {
-    toString : function () {return "COMBO";},
-    contentType : "UNKNOWN",
-    databaseField : "ID_VALUE",
-    isGroup : true,
-    possibleChildren : ["COMBOVALUE"]
-};
-$AttributeTypes.COMBOVALUE = {
-    toString : function () {return "COMBOVALUE";},
-    contentType : null, 
-    databaseField : null
-};
-$AttributeTypes.GROUP = {
-    toString : function () {return "GROUP";},
-    contentType : null, 
-    databaseField : null,
-    isGroup : true
-};
-$AttributeTypes.KEYWORD = {
-    toString : function () {return "KEYWORD";},
-    contentType : "UNKNOWN", 
-    databaseField : "ID_VALUE", 
-    getViewValue : function (pValue, pKeyword)
-        {
-            return KeywordUtils.getViewValue(pKeyword, pValue);
-        },
-    getDropDownDefinitions : function ()
-        {
-            return KeywordUtils.getContainerNames().map(function (e)
-            {
-                return [e, e];//currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
-            });
-        }
-};
-$AttributeTypes.VOID = {
-    toString : function () {return "VOID";},
-    contentType : null,
-    databaseField : null,
-    isGroup : true,
-    possibleChildren : ["VOID"]
-};
-$AttributeTypes.MEMO = { 
-    toString : function () {return "MEMO";},
-    contentType : "LONG_TEXT", 
-    databaseField : "CHAR_VALUE"
-};
-$AttributeTypes.OBJECTSELECTION = {
-    toString : function () {return "OBJECTSELECTION";},
-    contentType : "UNKNOWN",
-    databaseField : "ID_VALUE",
-    getViewValue : function (pValue, pModule)
-        {
-            if (pValue)
-            {
-                var title = "#CONTENTTITLE";
-                var config = entities.createConfigForLoadingRows()
-                    .entity(pModule)
-                    .fields([title])
-                    .uid(pValue);
-                var rows = entities.getRow(config);
-                pValue = rows ? rows[title] : pValue;
-            }
-            return pValue;
-        },
-    getDropDownDefinitions : function ()
-        {
-            var dropDownList = [];
-            //TODO filter entities
-            project.getDataModels(project.DATAMODEL_KIND_ENTITY).forEach(
-                function (entity)
-                {
-                    if (entity[1])
-                        dropDownList.push([entity[0], translate.text(entity[1])]);
-                }
-            );
-            return dropDownList;
-        }
-};
-$AttributeTypes.THEME = {
-    toString : function () {return "THEME";},
-    contentType : "LONG_TEXT",
-    databaseField : "CHAR_VALUE",
-    isGroup : true,
-    possibleChildren : ["THEME"]
-};
-
-function AttributeTypeUtil () {}
-
-/**
- * returns the required contentType for the given attribute type
- * 
- * @param {String} pAttributeType the attribute type 
- *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
- * @return {String} the contentType for the attribute
- */
-AttributeTypeUtil.getContentType = function (pAttributeType)
-{
-    if (pAttributeType)
-    {
-        pAttributeType = pAttributeType.trim();
-    
-        if (pAttributeType in $AttributeTypes)
-            return $AttributeTypes[pAttributeType].contentType;
-    }
-    return null;
-}
-
-/**
- * returns if the type is a group type
- * 
- * @param {String} pAttributeType the attribute type 
- *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
- * @return {Boolean} if the type is a group type
- */
-AttributeTypeUtil.isGroupType = function (pAttributeType)
-{
-    if (pAttributeType)
-    {
-        pAttributeType = pAttributeType.trim();
-        if (pAttributeType in $AttributeTypes)
-            return $AttributeTypes[pAttributeType].isGroup || false;
-    }
-    return null;
-}
-
-/**
- * returns the database field for the given attribute type that holds the value of the attribute
- * 
- * @param {String} pAttributeType the attribute type 
- *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
- * @return {String} the database field for the attribute
- */
-AttributeTypeUtil.getDatabaseField = function (pAttributeType)
-{
-    if (pAttributeType)
-    {
-        pAttributeType = pAttributeType.trim();
-        if (pAttributeType in $AttributeTypes)
-            return $AttributeTypes[pAttributeType].databaseField;
-    }
-    return null;
-}
-
-/**
- * returns the possible children types for the given attribute type
- * 
- * @param {String} pAttributeType the attribute type 
- *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
- * @return {String[]} the possible children types
- */
-AttributeTypeUtil.getPossibleChildren = function (pAttributeType)
-{
-    if (pAttributeType)
-    {
-        pAttributeType = pAttributeType.trim();
-        if (pAttributeType in $AttributeTypes)
-            return $AttributeTypes[pAttributeType].possibleChildren;
-    }
-    return null;
-}
-
-AttributeTypeUtil.getAttributeViewValue = function (pAttributeType, pValue, pKeyword)
-{
-    if (pAttributeType in $AttributeTypes && $AttributeTypes[pAttributeType].getViewValue)
-        return $AttributeTypes[pAttributeType].getViewValue(pValue, pKeyword);
-    return pValue;
-}
-
-AttributeTypeUtil._initTypeColumnData = function ()
-{
-    var columns = [];
-    var typeColumnMap = {};
-    for (let type in $AttributeTypes)
-    {
-        type = $AttributeTypes[type];
-        if (type.databaseField)
-        {
-            var typeKey = type.toString();
-            var colIndex = columns.indexOf(type.databaseField);
-            if (colIndex == -1)
-            {
-                colIndex = columns.length;
-                columns.push(type.databaseField);
-            }
-            typeColumnMap[typeKey] = colIndex;
-        }
-    }
-    this._allDBColumns = columns;
-    this._typeColumnMap = typeColumnMap;
-}
-
-AttributeTypeUtil.getAllDatabaseFields = function ()
-{
-    if (this._allDBColumns == undefined)
-        AttributeTypeUtil._initTypeColumnData();
-    return this._allDBColumns;
-}
-
-AttributeTypeUtil.getTypeColumnIndex = function (pAttributeType)
-{
-    if (this._typeColumnMap == undefined)
-        AttributeTypeUtil._initTypeColumnData();
-    return this._typeColumnMap[pAttributeType.trim()];
-}
-
-/*********************************************************************************************************************/
-
-/**
- * Functions for AttributeUsages.
- * Do not instanciate this!
- */
-function AttributeUsageUtil () {}
-
-/**
- * Creates AttributeUsages for all subordinate attributes of an attribute.
- * This is required when an usage is added to a superordinate attribute.
- * 
- * @param {String} pAttributeId the id of the superordinate attribute
- * @param {String} pObjectType the context
- */
-AttributeUsageUtil.insertChildrenUsages = function (pAttributeId, pObjectType)
-{
-    if (!pAttributeId)
-        return;
-    var table = "AB_ATTRIBUTEUSAGE";
-    var columns = ["AB_ATTRIBUTEUSAGEID", "AB_ATTRIBUTE_ID", "OBJECT_TYPE"];
-    var types = db.getColumnTypes(table, columns);
-    
-    var sqlSelect = "select AB_ATTRIBUTEID, "
-            + " (select count(*) from AB_ATTRIBUTEUSAGE where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID and OBJECT_TYPE = '" 
-            + pObjectType + "') = 0 from AB_ATTRIBUTE";
-    
-    var inserts = [];
-    _addInserts(pAttributeId, pObjectType);
-    db.inserts(inserts);
-    
-    function _addInserts (pAttributeId, pObjectType)
-    {
-        var condition = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
-        var attributes = db.table(condition.buildSql(sqlSelect));
-        
-        attributes.forEach(function (row)
-        {
-            if (row[1] == "true")
-            {
-                let values = [util.getNewUUID(), row[0], pObjectType];
-                inserts.push([table, columns, types, values]);
-            }
-            _addInserts(row[0], pObjectType);
-        });
-    }
-}
-
-/**
- * Updates AttributeUsages for all subordinate attributes of an attribute.
- * This is required when an usage of a superordinate attribute is changed.
- * 
- * @param {String} pAttributeId the id of the superordinate attribute
- * @param {String} pOldObjectType ye olde context
- * @param {String} pNewObjectType the new context
- */
-AttributeUsageUtil.updateChildrenUsages = function (pAttributeId, pOldObjectType, pNewObjectType)
-{
-    if (!pNewObjectType || !pAttributeId)
-        return;
-    
-    var table = "AB_ATTRIBUTEUSAGE";
-    
-    var countSubQuery = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pNewObjectType)
-        .and("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID")
-        .buildSql("select count(*) from AB_ATTRIBUTEUSAGE");
-    
-    var sqlSelect = SqlBuilder.begin()
-        .select(["AB_ATTRIBUTEID", "AB_ATTRIBUTEUSAGEID", countSubQuery])
-        .from("AB_ATTRIBUTE")
-        .leftJoin("AB_ATTRIBUTEUSAGE", SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pOldObjectType)
-            .and("AB_ATTRIBUTEID = AB_ATTRIBUTE_ID"));
-    
-    var updateCond = SqlCondition.begin();
-    
-    //it is possible that the new objectType is already in a subordinate attribute 
-    //and an update could cause a duplicate entry so one has to be deleted
-    var deleteCond = SqlCondition.begin();
-    
-    _addUpdateIds(pAttributeId, pOldObjectType);
-        
-    if (updateCond.isSet())
-        db.updateData(table, ["OBJECT_TYPE"], null, [pNewObjectType], updateCond.build("1=2"));
-    if (deleteCond.isSet())
-        db.deleteData(table, deleteCond.build("1=2"));
-    
-    function _addUpdateIds (pAttributeId)
-    {
-        var condition = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
-        var query = sqlSelect.where(condition);
-        var attributes = db.table(query.build());
-        
-        attributes.forEach(function (row)
-        {
-            if (row[1] && row[2] != "0")
-                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
-            else if (row[1])
-                updateCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
-            _addUpdateIds(row[0]);
-        });
-    }
-}
-
-/**
- * Deletes AttributeUsages for all subordinate attributes of an attribute.
- * This is required when an usage is removed from a superordinate attribute.
- * 
- * @param {String} pAttributeId the id of the superordinate attribute
- * @param {String} pObjectType the context
- */
-AttributeUsageUtil.deleteChildrenUsages = function (pAttributeId, pObjectType)
-{
-    var table = "AB_ATTRIBUTEUSAGE";
-    
-    var sqlSelect = "select AB_ATTRIBUTEID, AB_ATTRIBUTEUSAGEID "
-        + " from AB_ATTRIBUTE left join AB_ATTRIBUTEUSAGE on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID and OBJECT_TYPE = '" + pObjectType + "'";
-    
-    var deleteCond = SqlCondition.begin();
-    _addDeleteIds(pAttributeId, pObjectType);
-    if (deleteCond.isSet())
-        db.deleteData(table, deleteCond.build("1=2"));
-    
-    function _addDeleteIds (pAttributeId)
-    {
-        var condition = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
-            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
-        var attributes = db.table(condition.buildSql(sqlSelect));
-        
-        attributes.forEach(function (row)
-        {
-            if (row[1])
-                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1])
-            _addDeleteIds(row[0]);
-        });
-    }
-}
-
-/**
- * Deletes duplicate attribute usages.
- * 
- * @param {String} [pAttributeId=null] attribute id, if omitted, all duplicates will be deleted 
- */
-AttributeUsageUtil.removeDuplicates = function (pAttributeId)
-{
-    var condition = SqlCondition.begin()
-        .and("exists (select AB_ATTRIBUTEUSAGEID from AB_ATTRIBUTEUSAGE AU where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AU.AB_ATTRIBUTE_ID "
-            + "and AB_ATTRIBUTEUSAGE.OBJECT_TYPE = AU.OBJECT_TYPE and AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID != AU.AB_ATTRIBUTEUSAGEID)");
-    if (pAttributeId)
-        condition.andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", pAttributeId);
-    
-    var duplicates = db.table(condition.buildSql("select AB_ATTRIBUTEUSAGEID, AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE"));
-    var usageObj = {};
-    var deleteCond = SqlCondition.begin();
-    
-    duplicates.forEach(function (row)
-    {
-        if (!(row[1] in this))
-            this[row[1]] = {};
-        if (row[2] in this[row[1]])
-            deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[0]);
-        this[row[1]][row[2]] = true;
-    }, usageObj);
-    if (deleteCond.isSet())
-        db.deleteData("AB_ATTRIBUTEUSAGE", deleteCond.build("1=2"));
+import("KeywordData_lib");
+import("Context_lib");
+import("system.util");
+import("system.datetime");
+import("system.translate");
+import("system.neon");
+import("system.vars");
+import("system.db");
+import("system.project");
+import("system.entities");
+import("Sql_lib");
+import("Keyword_lib");
+
+/**
+ * Provides functions for the work with attributes, like
+ * listing the available attributes for a context.
+ * Don't instanciate this!
+ * 
+ * @class
+ */
+function AttributeUtil () {}
+
+/**
+ * Gives an array of all available attributes for a context. This is used in the possibleItems
+ * process for the attribute id in AttributeRelation
+ * 
+ * @param {String} pObjectType the object type (= context)
+ * @param {boolean} [pIncludeGroups=false]
+ * @param {String[]} [pFilteredAttributeIds=[]] Whitleist of attribute ids
+ * @param {Object} [pAttributeCount=null] Object with attribute ids and their count
+ * 
+ * @return {String[]} array of attributeIds
+ */
+AttributeUtil.getPossibleAttributes = function (pObjectType, pIncludeGroups, pFilteredAttributeIds, pAttributeCount)
+{
+    if (pObjectType == null || (pFilteredAttributeIds && pFilteredAttributeIds.length == 0))
+        return [];
+    
+    var attrSql = "select AB_ATTRIBUTEID from AB_ATTRIBUTE"
+        + " join AB_ATTRIBUTEUSAGE  on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID";
+    var attrCond = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+        .and("ATTRIBUTE_ACTIVE = 1");
+    
+    if (pAttributeCount)
+    {
+        for (let attributeId in pAttributeCount)
+        {
+            attrCond.andSqlCondition(
+                SqlCondition.begin()
+                    .orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", attributeId, "# != ?")
+                    .orPrepare("AB_ATTRIBUTEUSAGE.MAX_COUNT", pAttributeCount[attributeId], "# > ?")
+                    .or("AB_ATTRIBUTEUSAGE.MAX_COUNT is null")
+            );
+        }
+    }
+        
+    if (pFilteredAttributeIds)
+    {
+        var filteredIdsCondition = new SqlCondition();
+        var filteredIdChildren = AttributeUtil.getAllChildren(pFilteredAttributeIds);
+        pFilteredAttributeIds.concat(filteredIdChildren).forEach(function(id) 
+        {
+            this.orPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", id);
+        }, filteredIdsCondition);
+
+        attrCond.andSqlCondition(filteredIdsCondition);
+    }
+
+    if (!pIncludeGroups)
+        attrCond.andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# != ?");
+    
+    var attributes = db.array(db.COLUMN, attrCond.buildSql(attrSql));
+    
+    return attributes;
+}
+
+/**
+ * searches for possiblevalues for a atttribute and returns these. The values depend on the attributeType
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * @param {Boolean} pAttributeType type of the attribute that is specified with pAttributeId;
+ *                                 The type needs to be passed to the function for better performance 
+ *                                 (loading the type via attribute several times would be too slow)
+ * @param {Boolean} [pIncludeInactives=false] specifies if only active attributevalues or actives + inactives shall be returned, 
+ *                                            this is important when you want to search for attributevalues 
+ * 
+ * @return {Array} 2D-array with [ID, value] als elements if the given attributeType has possible items. if not null is returned
+ */
+AttributeUtil.getPossibleListValues = function (pAttributeId, pAttributeType, pIncludeInactives)
+{
+    var attributeId = pAttributeId;
+    var attrType = pAttributeType.trim();
+    var onlyActives = (pIncludeInactives == undefined ? false : pIncludeInactives);
+    if (attrType == $AttributeTypes.COMBO.toString())
+    {
+        var valueSql = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", attributeId)
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE);
+        
+        if (onlyActives)
+            valueSql.andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1");
+        
+        valueSql = valueSql.buildSql("select AB_ATTRIBUTEID, ATTRIBUTE_NAME from AB_ATTRIBUTE", "1=2", "order by SORTING asc");
+        var valueList = db.table(valueSql);
+        for (let i = 0; i < valueList.length; i++)
+        {
+            valueList[i][1] = translate.text(valueList[i][1]);
+        }
+        return valueList;
+    }
+    else if (attrType == $AttributeTypes.BOOLEAN.toString())
+    {
+        return [
+            ["1", translate.text("Yes")],
+            ["0", translate.text("No")]
+            ];
+    }
+    else if (attrType == $AttributeTypes.KEYWORD.toString())
+    {
+        var attrKeywordSelect = "select DROPDOWNDEFINITION from AB_ATTRIBUTE";
+        attrKeywordSelect = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeId)
+            .buildSql(attrKeywordSelect);
+        var attrKeyword = db.cell(attrKeywordSelect);
+        var keywords = KeywordData.getSimpleData(attrKeyword, null, onlyActives);
+        return keywords;
+    }
+    else if (attrType == $AttributeTypes.OBJECTSELECTION)
+    {
+        var [module, filter] = db.array(db.ROW, SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", attributeId)
+            .buildSql("select DROPDOWNDEFINITION, DROPDOWNFILTER from AB_ATTRIBUTE")
+            );
+        var objects = [];
+        if (module)
+        {
+            var uid = "#UID";
+            var title = "#CONTENTTITLE";
+            var config = entities.createConfigForLoadingRows()
+                .entity(module)
+                .fields([uid, title]);
+            if (filter)
+                config.filter(filter);
+            var rows = entities.getRows(config);
+            for (let i = 0, l = rows.length; i < l; i++)
+                objects.push([rows[i][uid], rows[i][title]])
+        }
+        return objects;
+    }
+    else
+        return null;
+}
+
+/**
+ * returns the name of an attribute with all parent attribute names
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * @param {Boolean} [pSimpleName=false] Use only the name of the attribute and not the names of the parents.
+ * @param {Boolean} [pTranslate=true] translate the name
+ * 
+ * @return {String} the name of the attribute
+ */
+AttributeUtil.getFullAttributeName = function (pAttributeId, pSimpleName, pTranslate) 
+{
+    if (pSimpleName === undefined)
+        pSimpleName = false;
+    if (pTranslate === undefined)
+        pTranslate = true;
+    
+    if (!pAttributeId)
+        return "";
+    if (pSimpleName)
+        return AttributeUtil.getSimpleAttributeName(pAttributeId, pTranslate);
+    var attributeNames = [];
+    var attribute;
+    do {
+        attribute = db.array(db.ROW, SqlCondition.begin()
+            .andPrepare(["AB_ATTRIBUTE", "AB_ATTRIBUTEID", "ATTRIBUTE"], pAttributeId)
+            .buildSql("select ATTRIBUTE.ATTRIBUTE_NAME, PARENT1.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_PARENT_ID \n\
+                from AB_ATTRIBUTE ATTRIBUTE \n\
+                left join AB_ATTRIBUTE PARENT1 on ATTRIBUTE.ATTRIBUTE_PARENT_ID = PARENT1.AB_ATTRIBUTEID \n\
+                left join AB_ATTRIBUTE PARENT2 on PARENT1.ATTRIBUTE_PARENT_ID = PARENT2.AB_ATTRIBUTEID")
+        );
+        if (attribute.length > 0)
+        {
+            attributeNames.push(attribute[0]);
+            if (attribute[1])
+                attributeNames.push(attribute[1]);
+            if (attribute[2])
+                attributeNames.push(attribute[2]);
+            pAttributeId = attribute[3];
+        }
+        else
+            pAttributeId = "";
+    } while (pAttributeId);
+    
+    if (pTranslate)
+    {
+        for (let i = 0; i < attributeNames.length; i++)
+        {
+            attributeNames[i] = translate.text(attributeNames[i]);
+        }
+    }
+    return attributeNames.reverse().join(" / ");
+}
+
+/**
+ * returns the name of an attribute
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * @param {boolean} [pTranslate] if the name should be translated
+ * 
+ * @return {String} the name of the attribute
+ */
+AttributeUtil.getSimpleAttributeName = function (pAttributeId, pTranslate) 
+{
+    var attributeName = db.cell(SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql("select ATTRIBUTE_NAME from AB_ATTRIBUTE")
+    );
+    if (pTranslate)
+        attributeName = translate.text(attributeName);
+    return attributeName;
+}
+
+/**
+ * returns the ids of all subordinated attributes of an attribute
+ * 
+ * @param {String|Array} pAttributeIds the id(s) of the attribute(s)
+ * 
+ * @result {String[]} array with the ids of every subordinated attribute
+ */
+AttributeUtil.getAllChildren = function (pAttributeIds)
+{
+    var childIds = [];
+    if (typeof(pAttributeIds) == "string")
+        pAttributeIds = [pAttributeIds];
+        
+    while (pAttributeIds.length > 0)
+    {
+        pAttributeIds = db.array(db.COLUMN, SqlCondition.begin()
+            .andIn("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeIds)
+            .buildSql("select AB_ATTRIBUTEID from AB_ATTRIBUTE")
+        );
+        if (pAttributeIds.length > 0)
+            childIds = childIds.concat(pAttributeIds);
+    }
+    return childIds;
+}
+
+/**
+ * checks if an attribute has attribute relations
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * 
+ * @result {boolean} true if it has relations
+ */
+AttributeUtil.hasRelations = function (pAttributeId)
+{
+    if (!pAttributeId)
+        return false;
+    return db.cell(SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId)
+        .buildSql(
+            "select count(*) from AB_ATTRIBUTERELATION", "1=2" //TODO: is there a way exists could be used?
+        )
+    ) != "0";
+}
+
+/**
+ * returns the type of an attribute
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * 
+ * @result {String} attribute type
+ */
+AttributeUtil.getAttributeType = function (pAttributeId)
+{
+    if (!pAttributeId)
+        return "";
+    var attrTypeSelect = "select ATTRIBUTE_TYPE from AB_ATTRIBUTE";
+    attrTypeSelect = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql(attrTypeSelect);
+    return db.cell(attrTypeSelect).trim();
+}
+
+AttributeUtil.hasAttributes = function (pObjectType)
+{
+    if (!pObjectType)
+        return false;
+    return db.cell(SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1")
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# != ?")
+        .buildSql(
+            "select count(*) from AB_ATTRIBUTEUSAGE \n\
+            join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID", "1=2"
+        )
+    ) != "0"; //TODO: is there a way exists could be used?
+}
+
+/*********************************************************************************************************************/
+
+/**
+ * Provides functions for the work with attributeRelations, getting the value of an attributeRelation for an object.
+ * Don't instanciate this!
+ * 
+ * @class
+ */
+function AttributeRelationUtils () {}
+
+/**
+ * gets the value of an attributeRelation for one dataset (e. g. a person)
+ * 
+ * @param {String} pAttributeId attribute-id
+ * @param {String} pObjectRowId row-id of the dataset
+ * @param {String} [pObjectType=null] object-type
+ * @param {String} [pGetViewValue=false] if true the values are resolved and formatted
+ * @param {String} [pGetAttrname=false] if true the attributename is also returned
+ * 
+ * @return {String|String[]|null} the value of the attribute or an array of attrname and value [attrname, value] (if pGetAttrname is true)
+ */
+AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObjectType, pGetViewValue, pGetAttrname)
+{
+    var attrCond = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId)
+        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId);
+    if (pObjectType != null)
+        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
+    
+    var defaultFields = [
+        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
+        "AB_ATTRIBUTE.DROPDOWNDEFINITION", 
+        "COMBOVAL.ATTRIBUTE_NAME"
+    ];
+    
+    if (pGetAttrname)
+        defaultFields.push("AB_ATTRIBUTE.ATTRIBUTE_NAME");    
+    
+    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
+    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
+        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
+        + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
+    
+    var attributeValues = db.array(db.ROW, attributeSql);
+    if (!attributeValues.length)
+        return null;
+    
+    let value = attributeValues[AttributeTypeUtil.getTypeColumnIndex(attributeValues[0]) + defaultFields.length];
+    if (pGetViewValue && attributeValues[1].trim() == $AttributeTypes.COMBO)
+        value = attributeValues[2];
+    else if (pGetViewValue)
+        value = AttributeTypeUtil.getAttributeViewValue(attributeValues[0].trim(), value, attributeValues[1]);
+    
+    if (pGetAttrname)
+        value = [attributeValues[3], value];
+    
+    return value;
+}
+
+/**
+ * gets all attributes for a dataset
+ * 
+ * @param {String} pObjectRowId object rowid
+ * @param {String} [pObjectType=null] object-type
+ * @param {String} [pUseAttributeIds=0] if 0 the full attribute names are returned
+ *                                      if 1 the ids are used instead of the full attribute names
+ *                                      if 2 the ids AND the full attribute name is returned
+ * @param {String} [pUseIdValues=false] if true the values are not resolved or formatted [attributeId, attributeName, value]
+ * 
+ * @return {String[][]} two-dimensional array a row is [attributeId|attributeName, value] (or [attributeId, attributeName, value])
+ */
+AttributeRelationUtils.getAllAttributes = function (pObjectRowId, pObjectType, pUseAttributeIds, pUseIdValues)
+{
+    var attrCond = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
+    if (pObjectType != null)
+        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
+    
+    var defaultFields = [
+        "AB_ATTRIBUTE_ID", 
+        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
+        "AB_ATTRIBUTE.DROPDOWNDEFINITION", 
+        "COMBOVAL.ATTRIBUTE_NAME"
+    ];
+    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
+    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
+        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
+        + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
+    
+    var attributeNameMap = {};
+    var attributeValues = db.table(attributeSql).map(function (row) 
+    {
+        let attribute = row[0];
+        let attrname;
+        if (pUseAttributeIds == 0 || pUseAttributeIds == 2)
+        {
+            var tmpAttrname = "";
+            if (!(attribute in attributeNameMap))
+                attributeNameMap[attribute] = AttributeUtil.getFullAttributeName(attribute);
+            tmpAttrname = attributeNameMap[attribute];
+            
+            // if mode 0, return only the name
+            if (pUseAttributeIds == 0)
+                attribute = tmpAttrname
+            
+            // if mode 2 return both
+            if (pUseAttributeIds == 2)
+                attrname = tmpAttrname
+        }
+        let value = row[AttributeTypeUtil.getTypeColumnIndex(row[1]) + defaultFields.length];
+        if (!pUseIdValues && row[1].trim() == $AttributeTypes.COMBO)
+            value = row[3];
+        else if (!pUseIdValues)
+            value = AttributeTypeUtil.getAttributeViewValue(row[1].trim(), value, row[2]);
+        
+        // add attrname only if id AND attrname is needed
+        var data = [];
+        
+        data.push(attribute);
+
+        if (attrname)
+            data.push(attrname);
+        
+        data.push(value);
+        return data;
+    });
+    
+    return attributeValues;
+}
+
+/**
+ * gets the correct attribute value from a map with values depending on the attribute id
+ * 
+ * @param {String} pAttributeId the attribute id
+ * @param {Object} pValueMap a map with the attribute values and the db fields as keys
+ * @param {Boolean} [pGetViewValue=false] if true, get the view value
+ * 
+ * @return {String|null} the value of the attribute or null if the attribute doesn't exist
+ */
+AttributeRelationUtils.selectAttributeValue = function (pAttributeId, pValueMap, pGetViewValue)
+{
+    var sqlSelect = "select ATTRIBUTE_TYPE, DROPDOWNDEFINITION from AB_ATTRIBUTE";
+    var type = db.array(db.ROW, SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql(sqlSelect)
+    );
+    if (!type.length)
+        return null;
+    
+    type[0] = type[0].trim();
+    var field = AttributeTypeUtil.getDatabaseField(type[0]);
+    var value = pValueMap[field];
+    if (pGetViewValue && type[0] == $AttributeTypes.COMBO)
+    {
+        value = db.cell(SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", value)
+            .buildSql("select ATTRIBUTE_NAME from AB_ATTRIBUTE")
+        );
+    }
+    else if (pGetViewValue)
+        value = AttributeTypeUtil.getAttributeViewValue(type[0], value, type[1]);
+    
+    return value;
+}
+
+AttributeRelationUtils.getAttributes = function ()
+{
+    //TODO: implement maybe
+}
+
+/**
+ * sets the value of an attribute for one dataset (e. g. a person)
+ */
+AttributeRelationUtils.setAttribute = function ()
+{
+    //TODO: implement
+}
+
+/**
+ * adds rows for attributes with min_count > 0
+ * 
+ * @param {String} pObjectType the object type
+ * @param {String} pConsumer the name of the attribute relation consumer
+ */
+AttributeRelationUtils.presetMandatoryAttributes = function (pObjectType, pConsumer)
+{
+    var mandatoryAttributes = db.table(
+        SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# <> ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP, "# <> ?")
+            .and("ATTRIBUTE_ACTIVE = 1")
+            .and("MIN_COUNT > 0")
+            .buildSql("select AB_ATTRIBUTE_ID, MIN_COUNT from AB_ATTRIBUTEUSAGE "
+                + "join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTEID")
+    );
+    mandatoryAttributes.forEach(function (usage)
+    {
+        //adding an attribute more than 20 times would be too much (having a min_count > 20 is very unlikely)
+        for (let i = 0; i < usage[1] && i < 20; i++)
+            neon.addRecord(pConsumer, {
+                "AB_ATTRIBUTE_ID" : usage[0]
+            });
+    });
+}
+
+/**
+ * Checks if the count of the used attributes is valid and returns a message if it's not.
+ * 
+ * @param {String} pRowId the row id of the entity
+ * @param {String} [pObjectType=null] the object type
+ * @param {String} pConsumerField the name of the attribute relation consumer
+ * 
+ * @return {String} the validation message or an empty string if everything is ok
+ */
+AttributeRelationUtils.validateAttributeCount = function (pRowId, pObjectType, pConsumerField)
+{
+    var attributeChanges = {};
+    var deletedRows = vars.get("$field." + pConsumerField + ".deletedRows");
+    var changedRows = vars.get("$field." + pConsumerField + ".changedRows");
+    var insertedRows = vars.get("$field." + pConsumerField + ".insertedRows");
+
+   if (deletedRows)
+    {
+        deletedRows.forEach(function (row)
+        {
+            this[row.UID] = "";
+        }, attributeChanges);
+    }
+    
+    if (changedRows)
+    {
+        changedRows.forEach(function (row)
+        {
+            this[row.UID] = row.AB_ATTRIBUTE_ID;
+        }, attributeChanges);
+    }
+    
+    //get the current count of usages considering the changes
+    //this will merge the counts of attributeChanges and the already stored attributerelations
+    var countObj = AttributeRelationUtils.countAttributeRelations(pRowId, pObjectType, attributeChanges);
+    
+    if (insertedRows) //append the new rows
+    {
+        insertedRows.forEach(function (row)
+        {
+            this[row.AB_ATTRIBUTE_ID] = (this[row.AB_ATTRIBUTE_ID] || 0) + 1;
+        }, countObj);
+    }
+    var attributeCondition = SqlCondition.begin();
+    AttributeUtil.getPossibleAttributes(pObjectType).forEach(function (attributeId)
+    {
+        this.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", attributeId);
+    }, attributeCondition);
+    
+    var usageCondition = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)
+        .andSqlCondition(attributeCondition, "1=2");
+    
+    //retrieve all min/max counts of the possible attributes
+    var minMaxCounts = db.table(usageCondition.buildSql(
+          "select AB_ATTRIBUTEID, ATTRIBUTE_NAME, MIN_COUNT, MAX_COUNT from AB_ATTRIBUTEUSAGE \
+           join AB_ATTRIBUTE on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID", "1=2"
+    ));
+        
+    var validationMessage = [];
+    minMaxCounts.forEach(function ([attributeId, name, minCount, maxCount])
+    {
+        let count = this[attributeId] || 0;
+        //compares the actual usage with the min and max count and generates a message if the usage is too low or too high
+        if (count < minCount)
+            validationMessage.push(translate.withArguments("Attribute \"%0\" has to be used at least %1.", [name, _getTranslatedCount(minCount)]));
+        if (maxCount && count > maxCount)
+            validationMessage.push(translate.withArguments("Attribute \"%0\" can't be used more than %1.", [name, _getTranslatedCount(maxCount)]));
+    }, countObj);
+    
+    return validationMessage.join("\n");
+    
+    //returns the correct count expression by choosing either singular (1 time) or plural (2 times)
+    function _getTranslatedCount (pCount)
+    {
+        if (pCount == 1)
+            return pCount + " " + translate.text("${COUNT_PREPOSITION_SINGLE}");
+        return pCount + " " + translate.text("${COUNT_PREPOSITION_MULTIPLE}");
+    }
+}
+
+/**
+ * counts attribute relations
+ * 
+ * @param {String} pRowId the row id of the entity
+ * @param {String} [pObjectType=null] the object type
+ * @param {Object} [pAttributeChanges=null] object containing changes and deletions of attributes
+ *                          structure = {attributeRelationId : new attributeId or "" when deleted}
+ * 
+ * @return {Object} object with attribute ids and the count of the usage (without new rows)
+ */
+AttributeRelationUtils.countAttributeRelations = function (pRowId, pObjectType, pAttributeChanges)
+{
+    //use cases:
+    //complete new row ==> increase count by 1 for that attribute [this is done in another function]
+    //row removed ==> decrease count by 1
+    //row edit: replace one attribute by another attribute ==> increase the new attribute count and decrease the old attribute count
+    //row edit: replace attribute with no new value ==> decrease count for the old attribute
+    //unchanged (already stored) row ==> increase count 
+    var countObj = {};
+
+    var condition = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pRowId)
+        .andPrepareIfSet("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
+
+    var storedAttributeRelations = db.table(condition.buildSql(
+        "select AB_ATTRIBUTERELATIONID, AB_ATTRIBUTE_ID from AB_ATTRIBUTERELATION",
+        "1=2"
+    ));
+
+    storedAttributeRelations.forEach(function ([storedAttrRelationId, storedAttributeId]) {
+        var currentAttributeId = storedAttributeId;
+        //merging the data that is stored in the DB and the provided changes
+        if (pAttributeChanges && storedAttrRelationId in pAttributeChanges)
+            currentAttributeId = pAttributeChanges[storedAttrRelationId];
+        
+        // it doesn't matter if a row has been deleted or if the attribute has been set to "nothing"
+        if (currentAttributeId == "")
+            _decrCount(storedAttributeId);
+        else
+        {
+            _incrCount(currentAttributeId);
+            if (currentAttributeId != storedAttributeId)
+                _decrCount(storedAttributeId);
+        }
+    });
+    
+    function _incrCount(pAttributeId)
+    {
+        if (countObj[pAttributeId])
+            countObj[pAttributeId]++;
+        else
+            countObj[pAttributeId] = 1;
+    }
+    
+    function _decrCount(pAttributeId)
+    {
+        if (countObj[pAttributeId])
+            countObj[pAttributeId]--;
+        else
+            countObj[pAttributeId] = 0;
+    }
+    
+    return countObj;
+}
+
+/*********************************************************************************************************************/
+
+
+/**
+ * Object for the enumeration and management of all attribute types.
+ * This Object is only for the general definition of attribute types and for getting
+ * data about every type, anything that has to do with a specific attribute (= the function requires an attribute id)
+ * should be done in AttributeUtils.
+ * The required values and methods for each type are:
+ * 
+ * toString = function that should return a unique name
+ * contentType = the value that is returned in the contentType process for the attribute
+ * databaseField = the database field that holds values of attributes with the type
+ * 
+ * optional:
+ * getViewValue = function that gets the display value for a given value
+ * isGroup = if true, the attribute can have children
+ * getDropDownDefinitions = function that returns an array of possible values
+ *          for DROPDOWNDEFINITION
+ * 
+ * The display name is controlled by the keyword 'AttributeType'
+ */
+function $AttributeTypes () {}
+
+$AttributeTypes.TEXT = { 
+    toString : function () {return "TEXT";},
+    contentType : "TEXT", 
+    databaseField : "CHAR_VALUE"
+};
+$AttributeTypes.DATE = {
+    toString : function () {return "DATE";},
+    contentType : "DATE", 
+    databaseField : "DATE_VALUE",
+    getViewValue : function (pValue)
+        {
+            return datetime.toDate(pValue, translate.text("dd.MM.yyyy"));
+        }
+};
+$AttributeTypes.NUMBER = {
+    toString : function () {return  "NUMBER";},
+    contentType : "NUMBER", 
+    databaseField : "NUMBER_VALUE"
+};
+$AttributeTypes.BOOLEAN = {
+    toString : function () {return "BOOLEAN";},
+    contentType : "BOOLEAN", 
+    databaseField : "INT_VALUE",
+    getViewValue : function (pValue)
+        {
+            return pValue == "1" ? translate.text("Yes") : translate.text("No");
+        }
+};
+$AttributeTypes.COMBO = {
+    toString : function () {return "COMBO";},
+    contentType : "UNKNOWN",
+    databaseField : "ID_VALUE",
+    isGroup : true,
+    possibleChildren : ["COMBOVALUE"]
+};
+$AttributeTypes.COMBOVALUE = {
+    toString : function () {return "COMBOVALUE";},
+    contentType : null, 
+    databaseField : null
+};
+$AttributeTypes.GROUP = {
+    toString : function () {return "GROUP";},
+    contentType : null, 
+    databaseField : null,
+    isGroup : true
+};
+$AttributeTypes.KEYWORD = {
+    toString : function () {return "KEYWORD";},
+    contentType : "UNKNOWN", 
+    databaseField : "ID_VALUE", 
+    getViewValue : function (pValue, pKeyword)
+        {
+            return KeywordUtils.getViewValue(pKeyword, pValue);
+        },
+    getDropDownDefinitions : function ()
+        {
+            return KeywordUtils.getContainerNames().map(function (e)
+            {
+                return [e, e];//currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+            });
+        }
+};
+$AttributeTypes.VOID = {
+    toString : function () {return "VOID";},
+    contentType : null,
+    databaseField : null,
+    isGroup : true,
+    possibleChildren : ["VOID"]
+};
+$AttributeTypes.MEMO = { 
+    toString : function () {return "MEMO";},
+    contentType : "LONG_TEXT", 
+    databaseField : "CHAR_VALUE"
+};
+$AttributeTypes.OBJECTSELECTION = {
+    toString : function () {return "OBJECTSELECTION";},
+    contentType : "UNKNOWN",
+    databaseField : "ID_VALUE",
+    getViewValue : function (pValue, pModule)
+        {
+            if (pValue)
+            {
+                var title = "#CONTENTTITLE";
+                var config = entities.createConfigForLoadingRows()
+                    .entity(pModule)
+                    .fields([title])
+                    .uid(pValue);
+                var rows = entities.getRow(config);
+                pValue = rows ? rows[title] : pValue;
+            }
+            return pValue;
+        },
+    getDropDownDefinitions : function ()
+        {
+            var dropDownList = [];
+            //TODO filter entities
+            project.getDataModels(project.DATAMODEL_KIND_ENTITY).forEach(
+                function (entity)
+                {
+                    if (entity[1])
+                        dropDownList.push([entity[0], translate.text(entity[1])]);
+                }
+            );
+            return dropDownList;
+        }
+};
+$AttributeTypes.THEME = {
+    toString : function () {return "THEME";},
+    contentType : "LONG_TEXT",
+    databaseField : "CHAR_VALUE",
+    isGroup : true,
+    possibleChildren : ["THEME"]
+};
+
+function AttributeTypeUtil () {}
+
+/**
+ * returns the required contentType for the given attribute type
+ * 
+ * @param {String} pAttributeType the attribute type 
+ *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
+ * @return {String} the contentType for the attribute
+ */
+AttributeTypeUtil.getContentType = function (pAttributeType)
+{
+    if (pAttributeType)
+    {
+        pAttributeType = pAttributeType.trim();
+    
+        if (pAttributeType in $AttributeTypes)
+            return $AttributeTypes[pAttributeType].contentType;
+    }
+    return null;
+}
+
+/**
+ * returns if the type is a group type
+ * 
+ * @param {String} pAttributeType the attribute type 
+ *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
+ * @return {Boolean} if the type is a group type
+ */
+AttributeTypeUtil.isGroupType = function (pAttributeType)
+{
+    if (pAttributeType)
+    {
+        pAttributeType = pAttributeType.trim();
+        if (pAttributeType in $AttributeTypes)
+            return $AttributeTypes[pAttributeType].isGroup || false;
+    }
+    return null;
+}
+
+/**
+ * returns the database field for the given attribute type that holds the value of the attribute
+ * 
+ * @param {String} pAttributeType the attribute type 
+ *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
+ * @return {String} the database field for the attribute
+ */
+AttributeTypeUtil.getDatabaseField = function (pAttributeType)
+{
+    if (pAttributeType)
+    {
+        pAttributeType = pAttributeType.trim();
+        if (pAttributeType in $AttributeTypes)
+            return $AttributeTypes[pAttributeType].databaseField;
+    }
+    return null;
+}
+
+/**
+ * returns the possible children types for the given attribute type
+ * 
+ * @param {String} pAttributeType the attribute type 
+ *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
+ * @return {String[]} the possible children types
+ */
+AttributeTypeUtil.getPossibleChildren = function (pAttributeType)
+{
+    if (pAttributeType)
+    {
+        pAttributeType = pAttributeType.trim();
+        if (pAttributeType in $AttributeTypes)
+            return $AttributeTypes[pAttributeType].possibleChildren;
+    }
+    return null;
+}
+
+AttributeTypeUtil.getAttributeViewValue = function (pAttributeType, pValue, pKeyword)
+{
+    if (pAttributeType in $AttributeTypes && $AttributeTypes[pAttributeType].getViewValue)
+        return $AttributeTypes[pAttributeType].getViewValue(pValue, pKeyword);
+    return pValue;
+}
+
+AttributeTypeUtil._initTypeColumnData = function ()
+{
+    var columns = [];
+    var typeColumnMap = {};
+    for (let type in $AttributeTypes)
+    {
+        type = $AttributeTypes[type];
+        if (type.databaseField)
+        {
+            var typeKey = type.toString();
+            var colIndex = columns.indexOf(type.databaseField);
+            if (colIndex == -1)
+            {
+                colIndex = columns.length;
+                columns.push(type.databaseField);
+            }
+            typeColumnMap[typeKey] = colIndex;
+        }
+    }
+    this._allDBColumns = columns;
+    this._typeColumnMap = typeColumnMap;
+}
+
+AttributeTypeUtil.getAllDatabaseFields = function ()
+{
+    if (this._allDBColumns == undefined)
+        AttributeTypeUtil._initTypeColumnData();
+    return this._allDBColumns;
+}
+
+AttributeTypeUtil.getTypeColumnIndex = function (pAttributeType)
+{
+    if (this._typeColumnMap == undefined)
+        AttributeTypeUtil._initTypeColumnData();
+    return this._typeColumnMap[pAttributeType.trim()];
+}
+
+/*********************************************************************************************************************/
+
+/**
+ * Functions for AttributeUsages.
+ * Do not instanciate this!
+ */
+function AttributeUsageUtil () {}
+
+/**
+ * Creates AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage is added to a superordinate attribute.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pObjectType the context
+ */
+AttributeUsageUtil.insertChildrenUsages = function (pAttributeId, pObjectType)
+{
+    if (!pAttributeId)
+        return;
+    var table = "AB_ATTRIBUTEUSAGE";
+    var columns = ["AB_ATTRIBUTEUSAGEID", "AB_ATTRIBUTE_ID", "OBJECT_TYPE"];
+    var types = db.getColumnTypes(table, columns);
+    
+    var sqlSelect = "select AB_ATTRIBUTEID, "
+            + " (select count(*) from AB_ATTRIBUTEUSAGE where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID and OBJECT_TYPE = '" 
+            + pObjectType + "') = 0 from AB_ATTRIBUTE";
+    
+    var inserts = [];
+    _addInserts(pAttributeId, pObjectType);
+    db.inserts(inserts);
+    
+    function _addInserts (pAttributeId, pObjectType)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var attributes = db.table(condition.buildSql(sqlSelect));
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1] == "true")
+            {
+                let values = [util.getNewUUID(), row[0], pObjectType];
+                inserts.push([table, columns, types, values]);
+            }
+            _addInserts(row[0], pObjectType);
+        });
+    }
+}
+
+/**
+ * Updates AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage of a superordinate attribute is changed.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pOldObjectType ye olde context
+ * @param {String} pNewObjectType the new context
+ */
+AttributeUsageUtil.updateChildrenUsages = function (pAttributeId, pOldObjectType, pNewObjectType)
+{
+    if (!pNewObjectType || !pAttributeId)
+        return;
+    
+    var table = "AB_ATTRIBUTEUSAGE";
+    
+    var countSubQuery = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pNewObjectType)
+        .and("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID")
+        .buildSql("select count(*) from AB_ATTRIBUTEUSAGE");
+    
+    var sqlSelect = SqlBuilder.begin()
+        .select(["AB_ATTRIBUTEID", "AB_ATTRIBUTEUSAGEID", countSubQuery])
+        .from("AB_ATTRIBUTE")
+        .leftJoin("AB_ATTRIBUTEUSAGE", SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pOldObjectType)
+            .and("AB_ATTRIBUTEID = AB_ATTRIBUTE_ID"));
+    
+    var updateCond = SqlCondition.begin();
+    
+    //it is possible that the new objectType is already in a subordinate attribute 
+    //and an update could cause a duplicate entry so one has to be deleted
+    var deleteCond = SqlCondition.begin();
+    
+    _addUpdateIds(pAttributeId, pOldObjectType);
+        
+    if (updateCond.isSet())
+        db.updateData(table, ["OBJECT_TYPE"], null, [pNewObjectType], updateCond.build("1=2"));
+    if (deleteCond.isSet())
+        db.deleteData(table, deleteCond.build("1=2"));
+    
+    function _addUpdateIds (pAttributeId)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var query = sqlSelect.where(condition);
+        var attributes = db.table(query.build());
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1] && row[2] != "0")
+                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
+            else if (row[1])
+                updateCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
+            _addUpdateIds(row[0]);
+        });
+    }
+}
+
+/**
+ * Deletes AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage is removed from a superordinate attribute.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pObjectType the context
+ */
+AttributeUsageUtil.deleteChildrenUsages = function (pAttributeId, pObjectType)
+{
+    var table = "AB_ATTRIBUTEUSAGE";
+    
+    var sqlSelect = "select AB_ATTRIBUTEID, AB_ATTRIBUTEUSAGEID "
+        + " from AB_ATTRIBUTE left join AB_ATTRIBUTEUSAGE on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID and OBJECT_TYPE = '" + pObjectType + "'";
+    
+    var deleteCond = SqlCondition.begin();
+    _addDeleteIds(pAttributeId, pObjectType);
+    if (deleteCond.isSet())
+        db.deleteData(table, deleteCond.build("1=2"));
+    
+    function _addDeleteIds (pAttributeId)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var attributes = db.table(condition.buildSql(sqlSelect));
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1])
+                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1])
+            _addDeleteIds(row[0]);
+        });
+    }
+}
+
+/**
+ * Deletes duplicate attribute usages.
+ * 
+ * @param {String} [pAttributeId=null] attribute id, if omitted, all duplicates will be deleted 
+ */
+AttributeUsageUtil.removeDuplicates = function (pAttributeId)
+{
+    var condition = SqlCondition.begin()
+        .and("exists (select AB_ATTRIBUTEUSAGEID from AB_ATTRIBUTEUSAGE AU where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AU.AB_ATTRIBUTE_ID "
+            + "and AB_ATTRIBUTEUSAGE.OBJECT_TYPE = AU.OBJECT_TYPE and AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID != AU.AB_ATTRIBUTEUSAGEID)");
+    if (pAttributeId)
+        condition.andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", pAttributeId);
+    
+    var duplicates = db.table(condition.buildSql("select AB_ATTRIBUTEUSAGEID, AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE"));
+    var usageObj = {};
+    var deleteCond = SqlCondition.begin();
+    
+    duplicates.forEach(function (row)
+    {
+        if (!(row[1] in this))
+            this[row[1]] = {};
+        if (row[2] in this[row[1]])
+            deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[0]);
+        this[row[1]][row[2]] = true;
+    }, usageObj);
+    if (deleteCond.isSet())
+        db.deleteData("AB_ATTRIBUTEUSAGE", deleteCond.build("1=2"));
 }
\ No newline at end of file
diff --git a/process/Document_lib/process.js b/process/Document_lib/process.js
index 4d1e6725eb69ff366e0f993b4107981f01903cee..4049cfa963c6a9fcfffec8f70256686731840481 100644
--- a/process/Document_lib/process.js
+++ b/process/Document_lib/process.js
@@ -113,4 +113,9 @@ DocumentUtil.getMimeTypeFromUpload = function(pUploadValue) {
         return res[2];
     else
         return '';
+}
+
+DocumentUtil.hasDocuments = function (pAssignmentTable, pAssignmentName, pAssignmentRowId)
+{
+    return db.getBinaryCount(pAssignmentTable, pAssignmentName, pAssignmentRowId, SqlUtils.getSystemAlias()) > 0;
 }
\ No newline at end of file