From 6fa2c0f53101f05feb70c123ba6e148b194f8fdd Mon Sep 17 00:00:00 2001
From: "S.Listl" <S.Listl@SLISTL.aditosoftware.local>
Date: Thu, 8 Aug 2019 18:38:00 +0200
Subject: [PATCH] Keyword main view removed

---
 entity/Attribute_entity/Attribute_entity.aod  |  820 +++----
 .../dropdowndefinition/dropDownProcess.js     |   26 +-
 .../dropdowndefinition/placeholderProcess.js  |   22 +-
 .../dropdowndefinition/titleProcess.js        |   22 +-
 .../recordcontainers/jdito/contentProcess.js  |  418 ++--
 .../recordcontainers/jdito/onUpdate.js        |   51 +-
 .../KeywordAttributeRelation_entity.aod       |  343 ++-
 .../documentation.adoc                        |    0
 .../KeywordAttribute_entity.aod               |  256 +-
 .../recordcontainers/db/conditionProcess.js   |   40 +-
 .../KeywordEntry_entity.aod                   | 1201 +++++----
 .../keywordattributerelations/onValidation.js |   82 +
 .../keywordentryid_param/valueProcess.js      |    4 -
 .../documentation.adoc                        |    2 -
 entity/KeywordEntry_entity/onValidation.js    |   44 +-
 neonContext/KeywordEntry/KeywordEntry.aod     |    9 -
 .../KeywordEntryMainSide_view.aod             |   37 -
 .../KeywordEntryMain_view.aod                 |   23 -
 .../KeywordEntryPreview_view.aod              |   90 +-
 process/Attribute_lib/process.js              | 2170 ++++++++---------
 20 files changed, 2824 insertions(+), 2836 deletions(-)
 create mode 100644 entity/KeywordAttributeRelation_entity/entityfields/keywordattributes/children/filteralreadyusedbyentryid_param/documentation.adoc
 create mode 100644 entity/KeywordEntry_entity/entityfields/keywordattributerelations/onValidation.js
 delete mode 100644 entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/children/keywordentryid_param/valueProcess.js
 delete mode 100644 entity/KeywordEntry_entity/entityfields/keywordattributerelationsreadonly/documentation.adoc
 delete mode 100644 neonView/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod
 delete mode 100644 neonView/KeywordEntryMain_view/KeywordEntryMain_view.aod

diff --git a/entity/Attribute_entity/Attribute_entity.aod b/entity/Attribute_entity/Attribute_entity.aod
index 0800311201e..c95832f4435 100644
--- a/entity/Attribute_entity/Attribute_entity.aod
+++ b/entity/Attribute_entity/Attribute_entity.aod
@@ -1,410 +1,410 @@
-<?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>Attribute_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/Attribute_entity/documentation.adoc</documentation>
-  <title>Attribute</title>
-  <contentTitleProcess>%aditoprj%/entity/Attribute_entity/contentTitleProcess.js</contentTitleProcess>
-  <afterUiInit>%aditoprj%/entity/Attribute_entity/afterUiInit.js</afterUiInit>
-  <onValidation>%aditoprj%/entity/Attribute_entity/onValidation.js</onValidation>
-  <iconId>VAADIN:TAG</iconId>
-  <titlePlural>Attributes</titlePlural>
-  <recordContainer>jdito</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>ATTRIBUTE_NAME</name>
-      <title>Title (original language)</title>
-      <mandatory v="true" />
-      <state>EDITABLE</state>
-    </entityField>
-    <entityField>
-      <name>ATTRIBUTE_TYPE</name>
-      <title>Type</title>
-      <consumer>KeywordAttributeTypes</consumer>
-      <mandatory v="true" />
-      <state>READONLY</state>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/onValueChange.js</onValueChange>
-    </entityField>
-    <entityField>
-      <name>ATTRIBUTE_PARENT_ID</name>
-      <title>Superordinate Attribute</title>
-      <consumer>AttributeGroup</consumer>
-      <linkedContext>Attribute</linkedContext>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/displayValueProcess.js</displayValueProcess>
-      <onValueChangeTypes>
-        <element>MASK</element>
-        <element>PROCESS</element>
-        <element>PROCESS_SETVALUE</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityConsumer>
-      <name>AttributeChildren</name>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js</stateProcess>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Attribute_entity</entityName>
-        <fieldName>AttributeParent</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityProvider>
-      <name>AttributeParent</name>
-      <dependencies>
-        <entityDependency>
-          <name>18bd148d-bed3-429f-ba54-c5eac76c5083</name>
-          <entityName>Attribute_entity</entityName>
-          <fieldName>AttributeChildren</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>9fb3569c-7c75-48b1-9dc0-3f707940813a</name>
-          <entityName>Employee_entity</entityName>
-          <fieldName>Departments</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttributeCount_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>ObjectType_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>GetGroups_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttributeTypes_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>AttrParentId_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>AttributeUsages</name>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js</stateProcess>
-      <dependency>
-        <name>dependency</name>
-        <entityName>AttributeUsage_entity</entityName>
-        <fieldName>SpecificAttribute</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttributeId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>SingleSelection_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/singleselection_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>DisableMinCount_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/disablemincount_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>ATTRIBUTE_ACTIVE</name>
-      <title>Active</title>
-      <contentType>BOOLEAN</contentType>
-      <groupable v="true" />
-      <dropDownProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/dropDownProcess.js</dropDownProcess>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/valueProcess.js</valueProcess>
-    </entityField>
-    <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/Attribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>WhitelistIds_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/keywordattributetypes/children/whitelistids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>DROPDOWNDEFINITION</name>
-      <title>Keyword</title>
-      <placeholderProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js</placeholderProcess>
-      <dropDownProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js</dropDownProcess>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/stateProcess.js</stateProcess>
-      <titleProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js</titleProcess>
-    </entityField>
-    <entityParameter>
-      <name>AttrParentType_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>ObjectType_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>SpecificAttribute</name>
-      <lookupIdfield>UID</lookupIdfield>
-      <dependencies>
-        <entityDependency>
-          <name>ba3b4d47-7385-49df-bf61-54c99f5b2c81</name>
-          <entityName>AttributeRelation_entity</entityName>
-          <fieldName>SpecificAttribute</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>ObjectType_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>FilteredAttributeIds_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>DisplaySimpleName_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>GetGroups_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>FULL_ATTRIBUTE_NAME</name>
-      <title>Title</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/full_attribute_name/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>FilteredAttributeIds_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityActionGroup>
-      <name>AttributeActions</name>
-      <children>
-        <entityActionField>
-          <name>newChildAttribute</name>
-          <title>New attribute</title>
-          <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:FILE_TREE_SMALL</iconId>
-          <tooltipProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/tooltipProcess.js</tooltipProcess>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityParameter>
-      <name>GetGroups_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>DisplaySimpleName_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>USAGELIST</name>
-      <title>Usage</title>
-      <state>READONLY</state>
-    </entityField>
-    <entityProvider>
-      <name>AttributeGroups</name>
-      <children>
-        <entityParameter>
-          <name>GetGroups_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroups/children/getgroups_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttributeCount_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>ObjectType_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttributeTypes_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityConsumer>
-      <name>AttributeGroup</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Attribute_entity</entityName>
-        <fieldName>AttributeGroups</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparenttype_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>ICON</name>
-      <colorProcess>%aditoprj%/entity/Attribute_entity/entityfields/icon/colorProcess.js</colorProcess>
-      <contentType>IMAGE</contentType>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/icon/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>UID</name>
-    </entityField>
-    <entityField>
-      <name>SORTING</name>
-      <title>Sorting</title>
-    </entityField>
-    <entityParameter>
-      <name>AttributeCount_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityFieldGroup>
-      <name>attributeName</name>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributename/valueProcess.js</valueProcess>
-      <title>Name</title>
-      <fields>
-        <element>ATTRIBUTE_NAME</element>
-      </fields>
-    </entityFieldGroup>
-    <entityField>
-      <name>expanded</name>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/expanded/valueProcess.js</valueProcess>
-    </entityField>
-    <entityActionField>
-      <name>openAdminView</name>
-      <title>Open admin view</title>
-      <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/openadminview/onActionProcess.js</onActionProcess>
-      <iconId>VAADIN:CURLY_BRACKETS</iconId>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/openadminview/stateProcess.js</stateProcess>
-    </entityActionField>
-    <entityField>
-      <name>DROPDOWNFILTER</name>
-      <title>Filter</title>
-      <contentType>FILTER_TREE</contentType>
-    </entityField>
-    <entityParameter>
-      <name>AttributeTypes_param</name>
-      <expose v="true" />
-    </entityParameter>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>jdito</name>
-      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
-      <isFilterable v="true" />
-      <isSortable v="true" />
-      <contentProcess>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
-      <onInsert>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onInsert.js</onInsert>
-      <onUpdate>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
-      <onDelete>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onDelete.js</onDelete>
-      <recordFieldMappings>
-        <jDitoRecordFieldMapping>
-          <name>UID.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_PARENT_ID.value</name>
-          <isFilterable v="true" />
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_NAME.value</name>
-          <isFilterable v="true" />
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_ACTIVE.value</name>
-          <isFilterable v="true" />
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>DROPDOWNDEFINITION.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>DROPDOWNFILTER.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>SORTING.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_TYPE.value</name>
-          <isFilterable v="true" />
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_TYPE.displayValue</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>USAGELIST.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ATTRIBUTE_PARENT_ID.displayValue</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>FULL_ATTRIBUTE_NAME.value</name>
-        </jDitoRecordFieldMapping>
-      </recordFieldMappings>
-    </jDitoRecordContainer>
-  </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>Attribute_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/Attribute_entity/documentation.adoc</documentation>
+  <title>Attribute</title>
+  <contentTitleProcess>%aditoprj%/entity/Attribute_entity/contentTitleProcess.js</contentTitleProcess>
+  <afterUiInit>%aditoprj%/entity/Attribute_entity/afterUiInit.js</afterUiInit>
+  <onValidation>%aditoprj%/entity/Attribute_entity/onValidation.js</onValidation>
+  <iconId>VAADIN:TAG</iconId>
+  <titlePlural>Attributes</titlePlural>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>ATTRIBUTE_NAME</name>
+      <title>Title (original language)</title>
+      <mandatory v="true" />
+      <state>EDITABLE</state>
+    </entityField>
+    <entityField>
+      <name>ATTRIBUTE_TYPE</name>
+      <title>Type</title>
+      <consumer>KeywordAttributeTypes</consumer>
+      <mandatory v="true" />
+      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/onValueChange.js</onValueChange>
+    </entityField>
+    <entityField>
+      <name>ATTRIBUTE_PARENT_ID</name>
+      <title>Superordinate Attribute</title>
+      <consumer>AttributeGroup</consumer>
+      <linkedContext>Attribute</linkedContext>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/displayValueProcess.js</displayValueProcess>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+        <element>PROCESS_SETVALUE</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityConsumer>
+      <name>AttributeChildren</name>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js</stateProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>AttributeParent</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityProvider>
+      <name>AttributeParent</name>
+      <dependencies>
+        <entityDependency>
+          <name>18bd148d-bed3-429f-ba54-c5eac76c5083</name>
+          <entityName>Attribute_entity</entityName>
+          <fieldName>AttributeChildren</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>9fb3569c-7c75-48b1-9dc0-3f707940813a</name>
+          <entityName>Employee_entity</entityName>
+          <fieldName>Departments</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttributeCount_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>GetGroups_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttributeTypes_param</name>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>AttrParentId_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>AttributeUsages</name>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js</stateProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AttributeUsage_entity</entityName>
+        <fieldName>SpecificAttribute</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttributeId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>SingleSelection_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/singleselection_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>DisableMinCount_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/disablemincount_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>ATTRIBUTE_ACTIVE</name>
+      <title>Active</title>
+      <contentType>BOOLEAN</contentType>
+      <groupable v="true" />
+      <dropDownProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/dropDownProcess.js</dropDownProcess>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/valueProcess.js</valueProcess>
+    </entityField>
+    <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/Attribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>WhitelistIds_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/keywordattributetypes/children/whitelistids_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>DROPDOWNDEFINITION</name>
+      <title>Keyword</title>
+      <placeholderProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/placeholderProcess.js</placeholderProcess>
+      <dropDownProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js</dropDownProcess>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/stateProcess.js</stateProcess>
+      <titleProcess>%aditoprj%/entity/Attribute_entity/entityfields/dropdowndefinition/titleProcess.js</titleProcess>
+    </entityField>
+    <entityParameter>
+      <name>AttrParentType_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>ObjectType_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>SpecificAttribute</name>
+      <lookupIdfield>UID</lookupIdfield>
+      <dependencies>
+        <entityDependency>
+          <name>ba3b4d47-7385-49df-bf61-54c99f5b2c81</name>
+          <entityName>AttributeRelation_entity</entityName>
+          <fieldName>SpecificAttribute</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>FilteredAttributeIds_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>DisplaySimpleName_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>GetGroups_param</name>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>FULL_ATTRIBUTE_NAME</name>
+      <title>Title</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/full_attribute_name/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>FilteredAttributeIds_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityActionGroup>
+      <name>AttributeActions</name>
+      <children>
+        <entityActionField>
+          <name>newChildAttribute</name>
+          <title>New attribute</title>
+          <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js</onActionProcess>
+          <isMenuAction v="true" />
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:FILE_TREE_SMALL</iconId>
+          <tooltipProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/tooltipProcess.js</tooltipProcess>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityParameter>
+      <name>GetGroups_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>DisplaySimpleName_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>USAGELIST</name>
+      <title>Usage</title>
+      <state>READONLY</state>
+    </entityField>
+    <entityProvider>
+      <name>AttributeGroups</name>
+      <children>
+        <entityParameter>
+          <name>GetGroups_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroups/children/getgroups_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttributeCount_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttributeTypes_param</name>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityConsumer>
+      <name>AttributeGroup</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>AttributeGroups</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparenttype_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>ICON</name>
+      <colorProcess>%aditoprj%/entity/Attribute_entity/entityfields/icon/colorProcess.js</colorProcess>
+      <contentType>IMAGE</contentType>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/icon/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>UID</name>
+    </entityField>
+    <entityField>
+      <name>SORTING</name>
+      <title>Sorting</title>
+    </entityField>
+    <entityParameter>
+      <name>AttributeCount_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityFieldGroup>
+      <name>attributeName</name>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributename/valueProcess.js</valueProcess>
+      <title>Name</title>
+      <fields>
+        <element>ATTRIBUTE_NAME</element>
+      </fields>
+    </entityFieldGroup>
+    <entityField>
+      <name>expanded</name>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/expanded/valueProcess.js</valueProcess>
+    </entityField>
+    <entityActionField>
+      <name>openAdminView</name>
+      <title>Open admin view</title>
+      <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/openadminview/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:CURLY_BRACKETS</iconId>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/openadminview/stateProcess.js</stateProcess>
+    </entityActionField>
+    <entityField>
+      <name>DROPDOWNFILTER</name>
+      <title>Filter</title>
+      <contentType>FILTER_TREE</contentType>
+    </entityField>
+    <entityParameter>
+      <name>AttributeTypes_param</name>
+      <expose v="true" />
+    </entityParameter>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+      <isFilterable v="true" />
+      <isSortable v="true" />
+      <contentProcess>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <onInsert>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <onUpdate>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
+      <onDelete>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onDelete.js</onDelete>
+      <recordFieldMappings>
+        <jDitoRecordFieldMapping>
+          <name>UID.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_PARENT_ID.value</name>
+          <isFilterable v="true" />
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_NAME.value</name>
+          <isFilterable v="true" />
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_ACTIVE.value</name>
+          <isFilterable v="true" />
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>DROPDOWNDEFINITION.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>DROPDOWNFILTER.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>SORTING.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_TYPE.value</name>
+          <isFilterable v="true" />
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_TYPE.displayValue</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>USAGELIST.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ATTRIBUTE_PARENT_ID.displayValue</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>FULL_ATTRIBUTE_NAME.value</name>
+        </jDitoRecordFieldMapping>
+      </recordFieldMappings>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js b/entity/Attribute_entity/entityfields/dropdowndefinition/dropDownProcess.js
index 23c8a16fb6f..2ac4fdfe746 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 f00cbd82e67..7ef97b2dfac 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 f00cbd82e67..7ef97b2dfac 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 4cd396cf519..e4fd9e63f9a 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 12ab6ce802c..cc709a73a61 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/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod b/entity/KeywordAttributeRelation_entity/KeywordAttributeRelation_entity.aod
index 4078a79be26..7874f23b68b 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 00000000000..e69de29bb2d
diff --git a/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod b/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
index 51527c153e0..6fee4eb699f 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 02735856728..5df041cf417 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 3576059f493..cfd5ab30257 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 00000000000..e2a0b150abd
--- /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 53afbdfbbfe..00000000000
--- 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 99874edc30d..00000000000
--- 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 f1f568a35c0..c2eb1f2b717 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/neonContext/KeywordEntry/KeywordEntry.aod b/neonContext/KeywordEntry/KeywordEntry.aod
index 9c8eee02ee3..a42880585c7 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/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod b/neonView/KeywordEntryMainSide_view/KeywordEntryMainSide_view.aod
deleted file mode 100644
index ba521d29a3b..00000000000
--- 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 b69aaabd14c..00000000000
--- 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 d37f7f0daca..c169f747098 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/Attribute_lib/process.js b/process/Attribute_lib/process.js
index bf397d874cb..0a3b7af1fcc 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
-- 
GitLab