From 94db6a9e3667b2ae3b84c07cab754a9a85439250 Mon Sep 17 00:00:00 2001
From: "j.goderbauer" <j.goderbauer@adito.de>
Date: Wed, 27 Nov 2019 11:31:41 +0100
Subject: [PATCH] small descriptive changes in JDito documentation

---
 others/guide/how to write JDito code.adoc | 119 +++++++++++++++++-----
 process/Contact_lib/process.js            |   2 +
 2 files changed, 95 insertions(+), 26 deletions(-)

diff --git a/others/guide/how to write JDito code.adoc b/others/guide/how to write JDito code.adoc
index e8ab96aef63..9dbbdb19d29 100644
--- a/others/guide/how to write JDito code.adoc	
+++ b/others/guide/how to write JDito code.adoc	
@@ -1,3 +1,4 @@
+How to wirte JDito code
 =======================
 :toc2: left
 :numbered:
@@ -54,11 +55,13 @@ for (row = 0, row < dataLen; row++)
 ----
 
 
-== defining different types of functions n libraries ==
+== Functions - overview of different "types" ==
+This sections covers how to define different "types" of functions in libraries.
 
 === by using static methods ===
-This will be mostly utility functions and so on, where there is no need to instanciate an object. You'll need this probably the most time.
---> Static object with static functions.
+This will be mostly utility functions where there is no need to instantiate an object. You'll need this probably the most time.
+
+-> Static object with static functions.
 
 
 Definition:
@@ -98,39 +101,103 @@ var additionals = CommValidationUtil.getExtensionsBlueprint();
 
 You may want to hold data and create objects where methods share that data. 
 
-Definition:
+Here is an example for an object that can be created:
 [source,javascript]
 ----
 /**
- * object for easier handling of conditions; <1>
- * With this object you do not have to check if the string is empty or not;
- * you don't need to append a "1=1" condition or similar;
- * this objects gains most benefit if you have a lot of conditions that are added (or not) depending on tons of JDito-conditions
- * @class 
- * @param {String} [alias=the current alias] the database alias where the condition shall be executed later (important for column types of preparedStatements) <2>
- * @example //TODO: add missing example <3>
+ * object that provides featrues for a single keyword attribute; initalizes itself on creation with a specific keyword-attribute
+ * 
+ * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
+ *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
+ * @param {String} pAttributeName the name of the keyword attribute that shall be initalized
+ * @param {String} [pDefault=undefined] the default value -> Does not throw an error, if default value exists.
+ * 
+ * @class
  */
-function SqlCondition(pAlias) <4>
+function KeywordAttribute(pContainerName, pAttributeName, pDefault)
 {
-   //setting null is only needed to provide autocomplete for the ADITO-designer
-    this.preparedValues = null;
-    this._init();//the properties are initialized in an extra function because init is nearly the same as resetting (clearing) the SqlConditions
-    this.alias = alias;
+    this.container = pContainerName;
+    this.attribute = pAttributeName;
+    this.defaultValue = pDefault;
+
+    var keywordAttrData = newSelect("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID, AB_KEYWORD_ATTRIBUTE.KIND")
+        .from("AB_KEYWORD_ATTRIBUTE")
+        .where("AB_KEYWORD_ATTRIBUTE.CONTAINER", pContainerName)
+        .and("AB_KEYWORD_ATTRIBUTE.NAME", pAttributeName)
+        .arrayRow();
+    
+    if (keywordAttrData.length > 0) 
+    {
+        this.id = keywordAttrData[0];
+        this.type = keywordAttrData[1];
+        this.dbField = this.type.trim();
+    }
+    else if(pDefault == undefined)
+    {
+        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword container \"%1\"", [this.attribute, this.container]));
+    }
 }
+
 /**
- * append with SQL-and; no paranthesize of existing conditions is done
- * @param {String} cond the condition string which shall be appended
- * @return {Object} current SqlCondition-object
+ * get the value for a specific keyId.
+ * Error if the keyword container does not have the attribute at all (you can check this with .exists())
+ * Error if the attribute does not exist at the provided keyId and you have not specified a default
+ * 
+ * @param {String} pKeyId the keyId
+ * 
+ * @return {String} the loaded value (or the default)
  */
-SqlCondition.prototype.and = function(pCond) <5>
+KeywordAttribute.prototype.getValue = function(pKeyId)
 {
-    if (!pCond)
-        return this;
-    if (this._sqlStorage)
-        this._sqlStorage += " and ";
-    this._sqlStorage += pCond;
-    return this;
+    if (this.exists()) 
+    {
+        var attrValue = newSelect(this.dbField)
+            .from("AB_KEYWORD_ENTRY")
+            .join("AB_KEYWORD_ATTRIBUTERELATION", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
+            .where("AB_KEYWORD_ENTRY.CONTAINER", this.container)
+            .and("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", this.id)
+            .and("AB_KEYWORD_ENTRY.KEYID", pKeyId)
+            .cell();
+
+        if (attrValue)
+            return attrValue;
+        
+        if (this.defaultValue)
+            return this.defaultValue;
+        
+        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword \"%1\" from container \"%2\"", [this.attribute, pKeyId, this.container]));
+    }
+    else if (this.defaultValue == undefined)
+        throw new Error(translate.withArguments("no keyword attribute \"%0\" found in keyword container \"%1\"", [this.attribute, this.container]));
+    else
+        return this.defaultValue;
 }
+
+/**
+ * get a SqlBuilder object for this keyword attribute. You can easily add additional conditions to it.
+ * 
+ * @return {SqlBuilder} a SqlBuilder which contains a select for the entry-id's, joins to entry and attribute 
+ *                      and conditions for the container and the attribute-name.
+ */
+KeywordAttribute.prototype.getSqlBuilderSelect = function() 
+{
+    return newSelect("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
+        .from("AB_KEYWORD_ATTRIBUTERELATION")
+        .join("AB_KEYWORD_ENTRY", "AB_KEYWORD_ENTRYID = AB_KEYWORD_ENTRY_ID", "attrEntry")
+        .join("AB_KEYWORD_ATTRIBUTE", "AB_KEYWORD_ATTRIBUTEID = AB_KEYWORD_ATTRIBUTE_ID")
+        .where(["AB_KEYWORD_ENTRY", "CONTAINER", "attrEntry"], this.container)
+        .and("AB_KEYWORD_ATTRIBUTE.NAME", this.attribute)
+}
+
+/**
+ * check if the Container can have the attribute.
+ * @return {Boolean} true if it exists, false if not
+ */
+KeywordAttribute.prototype.exists = function()
+{
+    return this.id != undefined && this.type != undefined && this.dbField != undefined;
+}
+
 ----
 
 === private functions ===
diff --git a/process/Contact_lib/process.js b/process/Contact_lib/process.js
index d137cf41a4d..464d8503923 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -611,6 +611,8 @@ Contact.createWithColumnPresetForPrivatePerson = function()
  * 
  * @class
  *
+ * //TODO: far too complex to understand for the very easy job it does. Refactor for better understanding what this (and related) function do, and how.
+ *
  */
 function ContactTitleRenderer(pContact, pOptions)
 {
-- 
GitLab