From cc1b51909615d3bcdf121d6b53cc48b941fecd0f Mon Sep 17 00:00:00 2001
From: Johannes Hoermann <j.hoermann@adito.de>
Date: Wed, 28 Aug 2019 16:27:44 +0200
Subject: [PATCH] WsValidation Documentation, automatic lookup disable,
 refactoring

---
 .../AddressValidation_entity.aod              |   1 +
 .../documentation.adoc                        |   1 +
 .../recordcontainers/jdito/contentProcess.js  |  58 +++--
 entity/Address_entity/Address_entity.aod      |  58 +++--
 entity/Address_entity/documentation.adoc      |   2 +
 .../entityfields/address/mandatoryProcess.js  |   5 +-
 .../entityfields/address/onValueChange.js     |   4 +-
 .../entityfields/address/stateProcess.js      |   4 +
 .../address_ws/displayValueProcess.js         |   3 +
 .../address_ws/mandatoryProcess.js            |   5 +
 .../entityfields/address_ws/onValueChange.js  |   3 +
 .../entityfields/address_ws/stateProcess.js   |   4 +
 .../entityfields/address_ws/valueProcess.js   |   3 +
 .../entityfields/city/displayValueProcess.js  |   6 -
 .../entityfields/city/documentation.adoc      |   2 +
 .../entityfields/city/mandatoryProcess.js     |   5 +-
 .../entityfields/city/onValueChange.js        |   5 -
 .../entityfields/city/stateProcess.js         |   4 +
 .../entityfields/city/valueProcess.js         |   6 -
 .../city_ws/displayValueProcess.js            |   3 +
 .../entityfields/city_ws/mandatoryProcess.js  |   5 +
 .../entityfields/city_ws/onValueChange.js     |   3 +
 .../entityfields/city_ws/stateProcess.js      |   4 +
 .../entityfields/city_ws/valueProcess.js      |   3 +
 .../currentvalue_param/valueProcess.js        |   2 +-
 .../currentvalue_param/valueProcess.js        |   2 +-
 .../entityfields/zip/displayValueProcess.js   |   6 -
 .../entityfields/zip/mandatoryProcess.js      |   6 +-
 .../entityfields/zip/onValidation.js          |  14 +-
 .../entityfields/zip/onValueChange.js         |   5 -
 .../entityfields/zip/stateProcess.js          |   4 +
 .../entityfields/zip/valueProcess.js          |   6 -
 .../zip_ws/displayValueProcess.js             |   3 +
 .../entityfields/zip_ws/mandatoryProcess.js   |   5 +
 .../entityfields/zip_ws/onValidation.js       |  17 ++
 .../entityfields/zip_ws/onValueChange.js      |   3 +
 .../entityfields/zip_ws/stateProcess.js       |   4 +
 .../entityfields/zip_ws/valueProcess.js       |   3 +
 .../currentvalue_param/valueProcess.js        |   2 +-
 .../AddressList_view/AddressList_view.aod     |  13 ++
 .../AdressMultiEdit_view.aod                  |  12 +
 process/AddressEntity_lib/process.js          |  11 +-
 process/PostalAddress_lib/process.js          |  20 +-
 process/WsValidation_lib/WsValidation_lib.aod |   1 +
 process/WsValidation_lib/documentation.adoc   |   1 +
 process/WsValidation_lib/process.js           | 212 ++++++++++++++++--
 46 files changed, 430 insertions(+), 119 deletions(-)
 create mode 100644 entity/AddressValidation_entity/documentation.adoc
 create mode 100644 entity/Address_entity/entityfields/address/stateProcess.js
 create mode 100644 entity/Address_entity/entityfields/address_ws/displayValueProcess.js
 create mode 100644 entity/Address_entity/entityfields/address_ws/mandatoryProcess.js
 create mode 100644 entity/Address_entity/entityfields/address_ws/onValueChange.js
 create mode 100644 entity/Address_entity/entityfields/address_ws/stateProcess.js
 create mode 100644 entity/Address_entity/entityfields/address_ws/valueProcess.js
 delete mode 100644 entity/Address_entity/entityfields/city/displayValueProcess.js
 create mode 100644 entity/Address_entity/entityfields/city/documentation.adoc
 delete mode 100644 entity/Address_entity/entityfields/city/onValueChange.js
 create mode 100644 entity/Address_entity/entityfields/city/stateProcess.js
 delete mode 100644 entity/Address_entity/entityfields/city/valueProcess.js
 create mode 100644 entity/Address_entity/entityfields/city_ws/displayValueProcess.js
 create mode 100644 entity/Address_entity/entityfields/city_ws/mandatoryProcess.js
 create mode 100644 entity/Address_entity/entityfields/city_ws/onValueChange.js
 create mode 100644 entity/Address_entity/entityfields/city_ws/stateProcess.js
 create mode 100644 entity/Address_entity/entityfields/city_ws/valueProcess.js
 delete mode 100644 entity/Address_entity/entityfields/zip/displayValueProcess.js
 delete mode 100644 entity/Address_entity/entityfields/zip/onValueChange.js
 create mode 100644 entity/Address_entity/entityfields/zip/stateProcess.js
 delete mode 100644 entity/Address_entity/entityfields/zip/valueProcess.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/displayValueProcess.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/mandatoryProcess.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/onValidation.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/onValueChange.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/stateProcess.js
 create mode 100644 entity/Address_entity/entityfields/zip_ws/valueProcess.js
 create mode 100644 process/WsValidation_lib/documentation.adoc

diff --git a/entity/AddressValidation_entity/AddressValidation_entity.aod b/entity/AddressValidation_entity/AddressValidation_entity.aod
index 3b44b38b5d..6fa4fbffda 100644
--- a/entity/AddressValidation_entity/AddressValidation_entity.aod
+++ b/entity/AddressValidation_entity/AddressValidation_entity.aod
@@ -2,6 +2,7 @@
 <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>AddressValidation_entity</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/AddressValidation_entity/documentation.adoc</documentation>
   <contentTitleProcess>%aditoprj%/entity/AddressValidation_entity/contentTitleProcess.js</contentTitleProcess>
   <recordContainer>jdito</recordContainer>
   <entityFields>
diff --git a/entity/AddressValidation_entity/documentation.adoc b/entity/AddressValidation_entity/documentation.adoc
new file mode 100644
index 0000000000..9b4c189ce8
--- /dev/null
+++ b/entity/AddressValidation_entity/documentation.adoc
@@ -0,0 +1 @@
+See WsValidation_lib
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
index 08e0650767..70adc4396f 100644
--- a/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
@@ -1,31 +1,47 @@
+import("system.logging");
 import("system.result");
 import("WsValidation_lib");
 import("system.vars");
 
-var type = "";
-if (vars.exists("$param.Type_param") && vars.get("$param.Type_param"))
-    type = vars.get("$param.Type_param");
+if (vars.get("$local.idvalues") != null)
+{
+    // extract data from uid as it already contains everything
+    result.object(vars.get("$local.idvalues").map(function(pId)
+    {
+        var data = WsValidationUtils.parseJSONArray(pId)
+        return [
+            pId,
+        ].concat(data.slice(0, -1))
+    }))
+}
+else
+{
+    var type = "";
+    if (vars.exists("$param.Type_param") && vars.get("$param.Type_param"))
+        type = vars.get("$param.Type_param");
 
-var country = "";
-if (vars.exists("$param.Country_param") && vars.get("$param.Country_param"))
-    country = vars.get("$param.Country_param");
+    var country = "";
+    if (vars.exists("$param.Country_param") && vars.get("$param.Country_param"))
+        country = vars.get("$param.Country_param");
 
-var city = "";
-if (vars.exists("$param.City_param") && vars.get("$param.City_param"))
-    city = vars.get("$param.City_param");
+    var city = "";
+    if (vars.exists("$param.City_param") && vars.get("$param.City_param"))
+        city = vars.get("$param.City_param");
 
-// get the value typed by the user
-var filter = "";
-var localFilter = vars.get("$local.filter");
+    // get the value typed by the user
+    var filter = "";
+    var localFilter = vars.get("$local.filter");
 
-if(localFilter.filter != null) {
-    filter = localFilter.filter.childs[0].value;
-}
+    if(localFilter.filter != null) {
+        filter = localFilter.filter.childs[0].value;
+    }
 
-if (!filter && vars.exists("$param.CurrentValue_param") && vars.get("$param.CurrentValue_param"))
-    filter = vars.get("$param.CurrentValue_param");
+    if (!filter && vars.exists("$param.CurrentValue_param") && vars.get("$param.CurrentValue_param"))
+        filter = vars.get("$param.CurrentValue_param");
 
-var foundAddresses = WsValidationUtils.validate(filter, type, country, city);
-result.object(foundAddresses.map(function(row) {
-    return row.concat([filter])
-}));
\ No newline at end of file
+    var foundAddresses = WsValidationUtils.validate(filter, type, country, city);
+
+    result.object(foundAddresses.map(function(row) {
+        return row.concat([filter])
+    }));
+}
diff --git a/entity/Address_entity/Address_entity.aod b/entity/Address_entity/Address_entity.aod
index e7414beda0..6fb61c9765 100644
--- a/entity/Address_entity/Address_entity.aod
+++ b/entity/Address_entity/Address_entity.aod
@@ -14,6 +14,7 @@
       <title>Street</title>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/address/mandatoryProcess.js</mandatoryProcess>
       <textInputAllowed v="true" />
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/address/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/Address_entity/entityfields/address/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/address/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/Address_entity/entityfields/address/onValueChange.js</onValueChange>
@@ -47,15 +48,11 @@
     </entityField>
     <entityField>
       <name>CITY</name>
+      <documentation>%aditoprj%/entity/Address_entity/entityfields/city/documentation.adoc</documentation>
       <title>City</title>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/city/mandatoryProcess.js</mandatoryProcess>
       <textInputAllowed v="true" />
-      <valueProcess>%aditoprj%/entity/Address_entity/entityfields/city/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/city/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/city/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-      </onValueChangeTypes>
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/city/stateProcess.js</stateProcess>
     </entityField>
     <entityField>
       <name>COUNTRY</name>
@@ -86,13 +83,7 @@
       <name>ZIP</name>
       <title>Postcode</title>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/zip/mandatoryProcess.js</mandatoryProcess>
-      <textInputAllowed v="true" />
-      <valueProcess>%aditoprj%/entity/Address_entity/entityfields/zip/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/zip/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/zip/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-      </onValueChangeTypes>
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/zip/stateProcess.js</stateProcess>
       <onValidation>%aditoprj%/entity/Address_entity/entityfields/zip/onValidation.js</onValidation>
     </entityField>
     <entityProvider>
@@ -404,6 +395,47 @@
       <valueProcess>%aditoprj%/entity/Address_entity/entityfields/showdsgvomessage_param/valueProcess.js</valueProcess>
       <expose v="true" />
     </entityParameter>
+    <entityField>
+      <name>Zip_ws</name>
+      <title>Postcode</title>
+      <consumer>ZipValidation</consumer>
+      <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/zip_ws/mandatoryProcess.js</mandatoryProcess>
+      <textInputAllowed v="true" />
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/zip_ws/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Address_entity/entityfields/zip_ws/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/zip_ws/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/zip_ws/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+      <onValidation>%aditoprj%/entity/Address_entity/entityfields/zip_ws/onValidation.js</onValidation>
+    </entityField>
+    <entityField>
+      <name>City_ws</name>
+      <consumer>CityValidation</consumer>
+      <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/city_ws/mandatoryProcess.js</mandatoryProcess>
+      <textInputAllowed v="true" />
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/city_ws/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Address_entity/entityfields/city_ws/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/city_ws/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/city_ws/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>Address_ws</name>
+      <consumer>StreetValidation</consumer>
+      <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/address_ws/mandatoryProcess.js</mandatoryProcess>
+      <textInputAllowed v="true" />
+      <stateProcess>%aditoprj%/entity/Address_entity/entityfields/address_ws/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Address_entity/entityfields/address_ws/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/address_ws/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/address_ws/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+    </entityField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Address_entity/documentation.adoc b/entity/Address_entity/documentation.adoc
index 220e9378c4..e43e482a61 100644
--- a/entity/Address_entity/documentation.adoc
+++ b/entity/Address_entity/documentation.adoc
@@ -8,3 +8,5 @@ an entity for logic behind a postal address
 The entity manages storing postal addresses and provides features like validation.
 
 Every `CONTACT` has one standard address value that is used by default for some actions. Keep in mind that this standard address has a special status and therefore may cannot be deleted.
+
+Webservice Validation: See WsValidation_lib
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address/mandatoryProcess.js b/entity/Address_entity/entityfields/address/mandatoryProcess.js
index 7c898f0182..ebedecd06a 100644
--- a/entity/Address_entity/entityfields/address/mandatoryProcess.js
+++ b/entity/Address_entity/entityfields/address/mandatoryProcess.js
@@ -1,5 +1,4 @@
-import("Entity_lib");
 import("system.result");
-import("AddressEntity_lib");
+import("WsValidation_lib");
 
-result.object(AddressEntityValidation.isMandatoryField());
\ No newline at end of file
+result.string(WsValidationFieldUtils.mainFieldMandatoryProcess(WsValidationType.get().TYPE_STREET_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address/onValueChange.js b/entity/Address_entity/entityfields/address/onValueChange.js
index abec5ca7ea..9ec7eecebe 100644
--- a/entity/Address_entity/entityfields/address/onValueChange.js
+++ b/entity/Address_entity/entityfields/address/onValueChange.js
@@ -1,5 +1,5 @@
 import("system.vars");
 import("WsValidation_lib");
 
-// use the code if address webservice is active
-//WsValidationUtils.setAddressFields(vars.get("$local.value"));
\ No newline at end of file
+if (WsValidationUtils.isWsEnabled(WsValidationType.get().TYPE_STREET_NOMINATIM))
+    WsValidationUtils.setAddressFields(vars.get("$local.value"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address/stateProcess.js b/entity/Address_entity/entityfields/address/stateProcess.js
new file mode 100644
index 0000000000..3644f13c62
--- /dev/null
+++ b/entity/Address_entity/entityfields/address/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.mainFieldStateProcess(WsValidationType.get().TYPE_STREET_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address_ws/displayValueProcess.js b/entity/Address_entity/entityfields/address_ws/displayValueProcess.js
new file mode 100644
index 0000000000..8b35f14226
--- /dev/null
+++ b/entity/Address_entity/entityfields/address_ws/displayValueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsDisplayValueProcess(WsValidationType.get().TYPE_STREET_NOMINATIM, "$field.ADDRESS");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address_ws/mandatoryProcess.js b/entity/Address_entity/entityfields/address_ws/mandatoryProcess.js
new file mode 100644
index 0000000000..3e9f416503
--- /dev/null
+++ b/entity/Address_entity/entityfields/address_ws/mandatoryProcess.js
@@ -0,0 +1,5 @@
+import("AddressEntity_lib");
+import("WsValidation_lib");
+import("system.result");
+
+result.object(WsValidationFieldUtils.wsFieldMandatoryProcess(WsValidationType.get().TYPE_STREET_NOMINATIM, AddressEntityValidation.isMandatoryField("ADDRESS")));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address_ws/onValueChange.js b/entity/Address_entity/entityfields/address_ws/onValueChange.js
new file mode 100644
index 0000000000..02aee85018
--- /dev/null
+++ b/entity/Address_entity/entityfields/address_ws/onValueChange.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsOnValueChangeProcess(WsValidationType.get().TYPE_STREET_NOMINATIM, "$field.ADDRESS");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address_ws/stateProcess.js b/entity/Address_entity/entityfields/address_ws/stateProcess.js
new file mode 100644
index 0000000000..e20c40eb31
--- /dev/null
+++ b/entity/Address_entity/entityfields/address_ws/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.wsFieldStateProcess(WsValidationType.get().TYPE_STREET_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address_ws/valueProcess.js b/entity/Address_entity/entityfields/address_ws/valueProcess.js
new file mode 100644
index 0000000000..5ccdf5a99f
--- /dev/null
+++ b/entity/Address_entity/entityfields/address_ws/valueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsValueProcess(WsValidationType.get().TYPE_STREET_NOMINATIM, "$field.ADDRESS");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/displayValueProcess.js b/entity/Address_entity/entityfields/city/displayValueProcess.js
deleted file mode 100644
index 0738ded179..0000000000
--- a/entity/Address_entity/entityfields/city/displayValueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.vars");
-import("system.result");
-
-// Needed for instant refresh if set by neon.setFieldValue
-// use the code if address webservice is active
-//result.string(vars.get("$field.CITY"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/documentation.adoc b/entity/Address_entity/entityfields/city/documentation.adoc
new file mode 100644
index 0000000000..42b8967311
--- /dev/null
+++ b/entity/Address_entity/entityfields/city/documentation.adoc
@@ -0,0 +1,2 @@
+Address validation
+==
diff --git a/entity/Address_entity/entityfields/city/mandatoryProcess.js b/entity/Address_entity/entityfields/city/mandatoryProcess.js
index 7c898f0182..fe8510d194 100644
--- a/entity/Address_entity/entityfields/city/mandatoryProcess.js
+++ b/entity/Address_entity/entityfields/city/mandatoryProcess.js
@@ -1,5 +1,4 @@
-import("Entity_lib");
 import("system.result");
-import("AddressEntity_lib");
+import("WsValidation_lib");
 
-result.object(AddressEntityValidation.isMandatoryField());
\ No newline at end of file
+result.string(WsValidationFieldUtils.mainFieldMandatoryProcess(WsValidationType.get().TYPE_CITY_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/onValueChange.js b/entity/Address_entity/entityfields/city/onValueChange.js
deleted file mode 100644
index abec5ca7ea..0000000000
--- a/entity/Address_entity/entityfields/city/onValueChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("WsValidation_lib");
-
-// use the code if address webservice is active
-//WsValidationUtils.setAddressFields(vars.get("$local.value"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/stateProcess.js b/entity/Address_entity/entityfields/city/stateProcess.js
new file mode 100644
index 0000000000..e2ef4a95e3
--- /dev/null
+++ b/entity/Address_entity/entityfields/city/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.mainFieldStateProcess(WsValidationType.get().TYPE_CITY_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/valueProcess.js b/entity/Address_entity/entityfields/city/valueProcess.js
deleted file mode 100644
index 2c9d496185..0000000000
--- a/entity/Address_entity/entityfields/city/valueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.result");
-import("WsValidation_lib");
-import("system.vars");
-
-// use the code if address webservice is active
-//result.string(WsValidationUtils.valueFromJSON(vars.get("$this.value")));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city_ws/displayValueProcess.js b/entity/Address_entity/entityfields/city_ws/displayValueProcess.js
new file mode 100644
index 0000000000..7cbee1a42e
--- /dev/null
+++ b/entity/Address_entity/entityfields/city_ws/displayValueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsDisplayValueProcess(WsValidationType.get().TYPE_CITY_NOMINATIM, "$field.CITY");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city_ws/mandatoryProcess.js b/entity/Address_entity/entityfields/city_ws/mandatoryProcess.js
new file mode 100644
index 0000000000..7dba637e9d
--- /dev/null
+++ b/entity/Address_entity/entityfields/city_ws/mandatoryProcess.js
@@ -0,0 +1,5 @@
+import("AddressEntity_lib");
+import("WsValidation_lib");
+import("system.result");
+
+result.object(WsValidationFieldUtils.wsFieldMandatoryProcess(WsValidationType.get().TYPE_CITY_NOMINATIM, AddressEntityValidation.isMandatoryField("CITY")));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city_ws/onValueChange.js b/entity/Address_entity/entityfields/city_ws/onValueChange.js
new file mode 100644
index 0000000000..5938552243
--- /dev/null
+++ b/entity/Address_entity/entityfields/city_ws/onValueChange.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsOnValueChangeProcess(WsValidationType.get().TYPE_CITY_NOMINATIM, "$field.CITY");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city_ws/stateProcess.js b/entity/Address_entity/entityfields/city_ws/stateProcess.js
new file mode 100644
index 0000000000..1017598abb
--- /dev/null
+++ b/entity/Address_entity/entityfields/city_ws/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.wsFieldStateProcess(WsValidationType.get().TYPE_CITY_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city_ws/valueProcess.js b/entity/Address_entity/entityfields/city_ws/valueProcess.js
new file mode 100644
index 0000000000..789a3b3303
--- /dev/null
+++ b/entity/Address_entity/entityfields/city_ws/valueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsValueProcess(WsValidationType.get().TYPE_CITY_NOMINATIM, "$field.CITY");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
index 210aab5135..74c070329c 100644
--- a/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
+++ b/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$this.value"))
\ No newline at end of file
+result.string(vars.get("$field.CITY"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js
index 6cd3c4544e..8e559d5146 100644
--- a/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js
+++ b/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$this.value"));
\ No newline at end of file
+result.string(vars.get("$field.ADDRESS"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/displayValueProcess.js b/entity/Address_entity/entityfields/zip/displayValueProcess.js
deleted file mode 100644
index 219ae2ffc0..0000000000
--- a/entity/Address_entity/entityfields/zip/displayValueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.vars");
-import("system.result");
-
-// Needed for instant refresh if set by neon.setFieldValue
-// use the code if address webservice is active
-//result.string(vars.get("$field.ZIP"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/mandatoryProcess.js b/entity/Address_entity/entityfields/zip/mandatoryProcess.js
index 7c898f0182..981aa78bf8 100644
--- a/entity/Address_entity/entityfields/zip/mandatoryProcess.js
+++ b/entity/Address_entity/entityfields/zip/mandatoryProcess.js
@@ -1,5 +1,5 @@
-import("Entity_lib");
-import("system.result");
 import("AddressEntity_lib");
+import("WsValidation_lib");
+import("system.result");
 
-result.object(AddressEntityValidation.isMandatoryField());
\ No newline at end of file
+result.object(WsValidationFieldUtils.mainFieldMandatoryProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM, AddressEntityValidation.isMandatoryField()));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/onValidation.js b/entity/Address_entity/entityfields/zip/onValidation.js
index d676d5911b..31896dfdfa 100644
--- a/entity/Address_entity/entityfields/zip/onValidation.js
+++ b/entity/Address_entity/entityfields/zip/onValidation.js
@@ -1,15 +1,11 @@
+import("WsValidation_lib");
 import("system.translate");
 import("system.result");
 import("system.vars");
 import("PostalAddress_lib");
 import("Entity_lib");
 
-
-var countryCode = vars.get("$field.COUNTRY");
-var zipCode = vars.get("local.value");
-var message = "";
-var isValid = AddressValidationUtils.isValidZip(countryCode, zipCode);
-if (!isValid)
-    message = translate.text("The ZIP code does not match the format of the country.");
-    
-result.string(message);
\ No newline at end of file
+if (!WsValidationUtils.isWsEnabled(WsValidationType.get().TYPE_ZIP_NOMINATIM))
+{
+    result.string(AddressValidationUtils.validateZipField(vars.get("$field.COUNTRY"), vars.get("$local.value")));
+}
diff --git a/entity/Address_entity/entityfields/zip/onValueChange.js b/entity/Address_entity/entityfields/zip/onValueChange.js
deleted file mode 100644
index abec5ca7ea..0000000000
--- a/entity/Address_entity/entityfields/zip/onValueChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("WsValidation_lib");
-
-// use the code if address webservice is active
-//WsValidationUtils.setAddressFields(vars.get("$local.value"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/stateProcess.js b/entity/Address_entity/entityfields/zip/stateProcess.js
new file mode 100644
index 0000000000..b1f5ba1ac1
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.mainFieldStateProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/valueProcess.js b/entity/Address_entity/entityfields/zip/valueProcess.js
deleted file mode 100644
index 92c7fae75d..0000000000
--- a/entity/Address_entity/entityfields/zip/valueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.vars");
-import("system.result");
-import("WsValidation_lib");
-
-// use the code if address webservice is active
-//result.string(WsValidationUtils.valueFromJSON(vars.get("$this.value")));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/displayValueProcess.js b/entity/Address_entity/entityfields/zip_ws/displayValueProcess.js
new file mode 100644
index 0000000000..72a6e97c0a
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/displayValueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsDisplayValueProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM, "$field.ZIP");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/mandatoryProcess.js b/entity/Address_entity/entityfields/zip_ws/mandatoryProcess.js
new file mode 100644
index 0000000000..a2dfbb85c8
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/mandatoryProcess.js
@@ -0,0 +1,5 @@
+import("AddressEntity_lib");
+import("WsValidation_lib");
+import("system.result");
+
+result.object(WsValidationFieldUtils.wsFieldMandatoryProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM, AddressEntityValidation.isMandatoryField("ZIP")));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/onValidation.js b/entity/Address_entity/entityfields/zip_ws/onValidation.js
new file mode 100644
index 0000000000..bbbf2acbbc
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/onValidation.js
@@ -0,0 +1,17 @@
+import("WsValidation_lib");
+import("system.translate");
+import("system.result");
+import("system.vars");
+import("PostalAddress_lib");
+import("Entity_lib");
+
+if (WsValidationUtils.isWsEnabled(WsValidationType.get().TYPE_ZIP_NOMINATIM))
+{
+    var wsData = WsValidationUtils.parseJSONArray(vars.get("$local.value"));
+    
+    // If it comes from WS (not null as parsing succeeded), assume it's correct. If not: validate.
+    if (wsData == null)
+    {
+        result.string(AddressValidationUtils.validateZipField(vars.get("$field.COUNTRY"), vars.get("$local.value")));
+    }
+}
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/onValueChange.js b/entity/Address_entity/entityfields/zip_ws/onValueChange.js
new file mode 100644
index 0000000000..dfd1bbf97d
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/onValueChange.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsOnValueChangeProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM, "$field.ZIP");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/stateProcess.js b/entity/Address_entity/entityfields/zip_ws/stateProcess.js
new file mode 100644
index 0000000000..3aec65f49c
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/stateProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("WsValidation_lib");
+
+result.string(WsValidationFieldUtils.wsFieldStateProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip_ws/valueProcess.js b/entity/Address_entity/entityfields/zip_ws/valueProcess.js
new file mode 100644
index 0000000000..0ecfd8b06e
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip_ws/valueProcess.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationFieldUtils.wsValueProcess(WsValidationType.get().TYPE_ZIP_NOMINATIM, "$field.ZIP");
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
index 6cd3c4544e..d9e7983e6f 100644
--- a/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
+++ b/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$this.value"));
\ No newline at end of file
+result.string(vars.get("$field.ZIP"))
\ No newline at end of file
diff --git a/neonView/AddressList_view/AddressList_view.aod b/neonView/AddressList_view/AddressList_view.aod
index 10095234b5..32133b6072 100644
--- a/neonView/AddressList_view/AddressList_view.aod
+++ b/neonView/AddressList_view/AddressList_view.aod
@@ -15,6 +15,7 @@
       <highlightingField>IS_STANDARD</highlightingField>
       <entityField>#ENTITY</entityField>
       <title></title>
+      <devices />
       <columns>
         <neonTableColumn>
           <name>dfaa01a1-0b11-4f92-aa18-89f12ebb2db5</name>
@@ -34,14 +35,26 @@
           <name>29dbb3f5-6f80-4100-aed3-334ac0b9cc48</name>
           <entityField>REGION</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>e809ff52-e8f7-443a-bf34-7e36daa2de42</name>
+          <entityField>Zip_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>0336ea99-c4a1-4f39-b5aa-a520a7dcbaab</name>
           <entityField>ZIP</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>69734ec3-b7a6-4efd-8dab-5059975fab70</name>
+          <entityField>City_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>12727b21-0359-4430-a9c2-54eb48e2e864</name>
           <entityField>CITY</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>2e48e6ac-a524-49e7-ad71-a29f1dd68891</name>
+          <entityField>Address_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>4e5e6a4f-f43e-4861-a912-fb05e576f960</name>
           <entityField>ADDRESS</entityField>
diff --git a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
index e7a369269f..90b97f765c 100644
--- a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
+++ b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
@@ -33,15 +33,27 @@
           <name>b62515bf-e89d-44a9-94ff-933766657fe5</name>
           <entityField>REGION</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>b9379fcc-3212-488b-8f90-cade09c00f3c</name>
+          <entityField>Zip_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>c1372a93-cf83-4c55-90e6-3b6b352abebf</name>
           <entityField>ZIP</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>5a0d723a-8531-4330-957b-11a1be9d7eab</name>
+          <entityField>City_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>2e7ba632-36ad-4852-bcca-d75bcf3f7de1</name>
           <entityField>CITY</entityField>
           <width v="75" />
         </neonTableColumn>
+        <neonTableColumn>
+          <name>2c104842-2ca1-408d-81d6-e998c0a562f2</name>
+          <entityField>Address_ws</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>ac71d5eb-7ce7-41a0-91aa-5594f2238788</name>
           <entityField>ADDRESS</entityField>
diff --git a/process/AddressEntity_lib/process.js b/process/AddressEntity_lib/process.js
index 3f13bba906..61b8e5a06f 100644
--- a/process/AddressEntity_lib/process.js
+++ b/process/AddressEntity_lib/process.js
@@ -14,12 +14,17 @@ function AddressEntityValidation(){}
 
 /**
  * check if the field, this function is called in is a mandatory field of the country
- * 
+ * @param {String} [pField=undefined] if provided use this field else use $this.name
  * @return {Boolean}
  */
-AddressEntityValidation.isMandatoryField = function()
+AddressEntityValidation.isMandatoryField = function(pField)
 {
-    var fieldName = vars.get("$this.name").replace(/^\$?field\./, "");
+    var fieldName;
+    
+    if (pField)
+        fieldName = pField;
+    else
+        fieldName = vars.get("$this.name").replace(/^\$?field\./, "");
     var countryCode = vars.get("$field.COUNTRY");
     var fieldCode = this.mapFieldToShorthand(fieldName);
     if (fieldCode == null)
diff --git a/process/PostalAddress_lib/process.js b/process/PostalAddress_lib/process.js
index de5ac3dcd8..9e2a28bb1c 100644
--- a/process/PostalAddress_lib/process.js
+++ b/process/PostalAddress_lib/process.js
@@ -1,3 +1,4 @@
+import("system.translate");
 import("KeywordRegistry_basic");
 import("system.db");
 import("Sql_lib");
@@ -268,4 +269,21 @@ AddressValidationUtils.isValidZip = function(countryCode, zipCode)
     regExpVal = "^" + regExpVal + "$";
     var regExp = new RegExp(regExpVal);
     return regExp.test(zipCode);
-};
\ No newline at end of file
+};
+
+/**
+ * validates a zip field
+ * @param {String} pCountry
+ * @param {String} pZip zip code to validate
+ * 
+ * @return {String} an empty string or an error message if validation failed.
+ */
+AddressValidationUtils.validateZipField = function(pCountry, pZip)
+{
+    var message = "";
+    var isValid = AddressValidationUtils.isValidZip(pCountry, pZip);
+    if (!isValid)
+        message = translate.text("The ZIP code does not match the format of the country.");
+
+    return message;
+}
\ No newline at end of file
diff --git a/process/WsValidation_lib/WsValidation_lib.aod b/process/WsValidation_lib/WsValidation_lib.aod
index 87bb88bd27..7557aa61ac 100644
--- a/process/WsValidation_lib/WsValidation_lib.aod
+++ b/process/WsValidation_lib/WsValidation_lib.aod
@@ -2,6 +2,7 @@
 <process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
   <name>WsValidation_lib</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/process/WsValidation_lib/documentation.adoc</documentation>
   <process>%aditoprj%/process/WsValidation_lib/process.js</process>
   <variants>
     <element>LIBRARY</element>
diff --git a/process/WsValidation_lib/documentation.adoc b/process/WsValidation_lib/documentation.adoc
new file mode 100644
index 0000000000..a47408f2ed
--- /dev/null
+++ b/process/WsValidation_lib/documentation.adoc
@@ -0,0 +1 @@
+See beginning of Lib. (TODO: move here??)
\ No newline at end of file
diff --git a/process/WsValidation_lib/process.js b/process/WsValidation_lib/process.js
index 69379c6adf..ef1bf9a459 100644
--- a/process/WsValidation_lib/process.js
+++ b/process/WsValidation_lib/process.js
@@ -7,6 +7,73 @@ import("system.net");
 import("system.util");
 import("system.auth");
 import("DataCaching_lib");
+import("AddressEntity_lib");
+
+/******************************************************************************/
+/******************************************************************************/
+/********************************DOCUMENTATION*********************************/
+/******************************************************************************/
+/******************************************************************************/
+/*
+1. How to add a new Webservice type
+-----------------------------------
+- Scroll down to WsValidationType.get
+- add a new Type into the cache like the other ones
+- IMPORTANT: use the same name for the key as for the first parameter of the new WsValidationType!
+- the second param, pWebserviceName defines which webservice should be used. This name is used for the custom project preferences
+  e.g. nominatim webservice has the custom preference nominatim.enable which is checked by WsValidationUtils.isWsEnabled
+  all other project preferences can contain the url, useername, password, etc. and are used by the function you create in the next step:
+- WS-Request function: (pProcessRequestCallback)
+  This callback defines a function which is called if a Request is triggered.
+  the following params are available (if you need more you have to add them to WsValidationUtils.validate(...)
+  pValue, pCountry, pCity
+  
+  You can base your callback on the function _nominatimRequest(pValue, pCountry, pCity)
+
+  Your callback has to call the processResultCallback (created as next step) for example like this:
+    return this.processResultCallback.call(this, ret, pValue);
+  
+- WS-Result function: (pProcessResultCallback)
+  This callback defines a function which is called on receiving an answer from the webservice.
+  
+  Base it on function _processNominatimAddressLookup(pWsResult, pValue) below.
+
+- create a new provider, which presets the Type_param with the new Type (you should not expose the parameter on this provider):
+import("WsValidation_lib");
+import("system.result");
+
+result.string(WsValidationType.get().TYPE_ADDRESS_NOMINATIM.key);
+
+
+2. Address_entity-specific! 
+How to add a new lookup using the webservice (like e.g. ZIP)
+------------------------------------------------------------
+
+In the following Text I use "main field" when referencing the field which is directly connected with the db and contains the actual data (e.g. $field.ZIP)
+The main field is only displayed if the webservice is disabled.
+In the following Text I use "ws field" when referencing the new field which is displayed when the webservice is enabled. It "uses" the data provided by the main field.
+
+- create new ws field:
+  e.g. Zip_ws
+- Set the following properties:
+  * textInputAllowed: true
+  * onValueChangeTypes: Mask (only)
+- add the following processes by using the functions from WsValidationFieldUtils (see the already existing Zip_ws field for reference)
+  * valueProcess
+  * displayValueProcess
+  * onValueChange
+  * stateProcess
+  * mandatoryProcess
+- if your main field has a onValidationProcess, copy it from the main field and wrap it with a check for ENABLÖED webservice (see Zip_ws) 
+   and maybe modify it (note that the onValidationProcess may get the Request answer as value. You have to deal with it!
+  Also wrap the onValidationProcess of your main field with a check for DISABLED webservice (see ZIP field)
+- create a new Consumer (e.g. ZipValidation_entity) and point it to the AddressValidation_entity. 
+  Use the corresponding provider which is created for the type you need (see documentation 1. above)
+  You may have to fill the parameters. if they are needed by your webservice
+- You HAVE TO fill the param "currentValueParam" by the value of your main field.
+- set the consumer of your ws field to the newly created consumer
+- Add your new ws field to the views: AddressList_view and AddressMultiEdit_view (right above the mainField)
+*/
 
 /**
  * Class used for the webservice validation types.
@@ -15,15 +82,15 @@ import("DataCaching_lib");
  * 
  * @param {String} pKey the key-name
  * @param {String} pWebserviceName name of the webservice. Used to find the correct webservice configuraation
- * @param {Function} pProcessResultCallback function for processing Webservice-result to the return value
  * @param {Function} pProcessRequestCallback function for processing Webservice-request
+ * @param {Function} pProcessResultCallback function for processing Webservice-result to the return value
  * @param {Object} pAdditionalInfo additional Info. Can be an object or something else. (callback specific)
  */
-function WsValidationType(pKey, pWebserviceName, pProcessResultCallback, pProcessRequestCallback, pAdditionalInfo) 
+function WsValidationType(pKey, pWebserviceName, pProcessRequestCallback, pProcessResultCallback, pAdditionalInfo) 
 {
     this.key = pKey;
-    this.processResultCallback = pProcessResultCallback;
     this.processRequestCallback = pProcessRequestCallback;
+    this.processResultCallback = pProcessResultCallback;
     this.webserviceName = pWebserviceName;
     this.additionalInfo = pAdditionalInfo;
 }
@@ -39,13 +106,13 @@ WsValidationType.get = function(pKey)
     if (!this._cache)
         this._cache = {
             // Address lookups
-            TYPE_ADDRESS_NOMINATIM: new WsValidationType("TYPE_ADDRESS_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "q"),
-            TYPE_ZIP_NOMINATIM: new WsValidationType("TYPE_ZIP_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "postalcode"),
-            TYPE_CITY_NOMINATIM: new WsValidationType("TYPE_CITY_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "city"),
-            TYPE_STREET_NOMINATIM: new WsValidationType("TYPE_STREET_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "street"),
+            TYPE_ADDRESS_NOMINATIM: new WsValidationType("TYPE_ADDRESS_NOMINATIM", "nominatim", _nominatimRequest, _processNominatimAddressLookup, "q"),
+            TYPE_ZIP_NOMINATIM: new WsValidationType("TYPE_ZIP_NOMINATIM", "nominatim", _nominatimRequest, _processNominatimAddressLookup, "postalcode"),
+            TYPE_CITY_NOMINATIM: new WsValidationType("TYPE_CITY_NOMINATIM", "nominatim", _nominatimRequest, _processNominatimAddressLookup, "city"),
+            TYPE_STREET_NOMINATIM: new WsValidationType("TYPE_STREET_NOMINATIM", "nominatim", _nominatimRequest, _processNominatimAddressLookup, "street"),
             
-            // Communication validation
-            TYPE_PHONE: new WsValidationType("TYPE_PHONE", "phoneValidation", _processCommunicationValidation, _customRequest, "Number")
+            // Communication validation (Not used anymore, as it's done via system functions now. Left here for reference.)
+            TYPE_PHONE: new WsValidationType("TYPE_PHONE", "phoneValidation", _customRequest, _processCommunicationValidation, "Number")
         }
     
     if (pKey)
@@ -271,7 +338,7 @@ WsValidationUtils.validate = function(pValue, pType, pCountry, pCity)
  * 
  * @return {Array|null} the parsed data as array or null if it was no array
  */
-WsValidationUtils._parseJSONArray = function(pJSON) {
+WsValidationUtils.parseJSONArray = function(pJSON) {
     try
     {
         var data = JSON.parse(pJSON);
@@ -291,18 +358,17 @@ WsValidationUtils._parseJSONArray = function(pJSON) {
 
 /**
  * set all address-fields by pValue, which should contain an array of all values as JSON
- * Note: it does not set the current field itself as this sould be done by the value process. Use WsValidationUtils.valueFromJSON for this.
  * 
  * @param {String} pJSON the values as json
+ * @return {Boolean} if any fields were set
  */
 WsValidationUtils.setAddressFields = function(pJSON)
 {
-    var data = WsValidationUtils._parseJSONArray(pJSON);
+    var data = WsValidationUtils.parseJSONArray(pJSON);
     if (data == null)
-        return
+        return false;
 
-    var currentField = vars.get("$this.name");
-    var toSet = {
+    var toSet = { 
         "$field.ZIP": data[1],
         "$field.CITY": data[2],
         "$field.COUNTRY": data[4],
@@ -314,15 +380,14 @@ WsValidationUtils.setAddressFields = function(pJSON)
     
     for (field in toSet) 
     {
-        if (field != currentField) 
-        {
-            let value = toSet[field];
-            if (!value)
-            value = ""
-        
-            neon.setFieldValue(field, value);
-        }
+        let value = toSet[field];
+        if (!value)
+        value = ""
+
+        neon.setFieldValue(field, value);
     }
+    
+    return true;
 }
 
 /**
@@ -333,7 +398,7 @@ WsValidationUtils.setAddressFields = function(pJSON)
  */
 WsValidationUtils.valueFromJSON = function(pJSON)
 {
-    var data = WsValidationUtils._parseJSONArray(pJSON);
+    var data = WsValidationUtils.parseJSONArray(pJSON);
     if (data == null)
         return null
 
@@ -364,4 +429,103 @@ WsValidationUtils.isWsEnabled = function(pType)
 WsValidationUtils._isError = function(pWsReturn)
 {
     return pWsReturn == null || !pWsReturn.hasHttpSuccessStatusCode || pWsReturn.httpStatusCode != 200;
+}
+
+/**
+ * Class containing functions for fields validated by the ws (e.g. Address_entity: ZIP, ADDRESS, CITY)
+ * do not create an instance of this
+ * 
+ * @class
+ */
+function WsValidationFieldUtils() {}
+
+/**
+ * @param {WsValidationType} pWsType
+ * @return {String} componentstate
+ */
+WsValidationFieldUtils.mainFieldStateProcess = function(pWsType)
+{
+    if (WsValidationUtils.isWsEnabled(pWsType))
+        return neon.COMPONENTSTATE_INVISIBLE
+    else
+        return neon.COMPONENTSTATE_AUTO
+}
+
+/**
+ * @param {WsValidationType} pWsType
+ * @return {String} componentstate
+ */
+WsValidationFieldUtils.wsFieldStateProcess = function(pWsType)
+{
+    if (!WsValidationUtils.isWsEnabled(pWsType))
+        return neon.COMPONENTSTATE_INVISIBLE
+    else
+        return neon.COMPONENTSTATE_AUTO
+}
+
+/**
+ * @param {WsValidationType} pWsType
+ * @param {Boolean} pMandatory if field is a mandatory field
+ * @return {Boolean} mandatory
+ */
+WsValidationFieldUtils.wsFieldMandatoryProcess = function(pWsType, pMandatory)
+{
+    return (WsValidationUtils.isWsEnabled(pWsType) && pMandatory);
+}
+
+/**
+ * @param {WsValidationType} pWsType
+ * @param {Boolean} pMandatory if field is a mandatory field
+ * @return {Boolean} mandatory
+ */
+WsValidationFieldUtils.mainFieldMandatoryProcess = function(pWsType, pMandatory)
+{
+    return (!WsValidationUtils.isWsEnabled(pWsType) && pMandatory);
+}
+
+/**
+ * Note: may call result.string(...)
+ *
+ * @param {WsValidationType} pWsType
+ * @param {String} field-variable from the main field. e.g. "$field.ZIP"
+ */
+WsValidationFieldUtils.wsValueProcess = function(pWsType, pMainField)
+{
+    if (vars.get("$this.value") == null && WsValidationUtils.isWsEnabled(pWsType))
+    {
+        result.string(vars.get(pMainField));
+    }
+}
+
+/**
+ * Note: may call result.string(...)
+ *
+ * @param {WsValidationType} pWsType
+ * @param {String} field-variable from the main field. e.g. "$field.ZIP"
+ */
+WsValidationFieldUtils.wsDisplayValueProcess = function(pWsType, pMainField)
+{
+    if (WsValidationUtils.isWsEnabled(pWsType))
+    {
+        // use the value from the corresponding field as display value
+        result.string(vars.get(pMainField));
+    }
+}
+
+/**
+ * Note: may call result.string(...)
+ *
+ * @param {WsValidationType} pWsType
+ * @param {String} field-variable from the main field. e.g. "$field.ZIP"
+ */
+WsValidationFieldUtils.wsOnValueChangeProcess = function(pWsType, pMainField)
+{
+    if (WsValidationUtils.isWsEnabled(pWsType))
+    {
+        var newCurrentValue = WsValidationUtils.setAddressFields(vars.get("$local.value"));
+        
+        // Set the corresponding field if it was not set by setAddressFields because the value was not from the WS.
+        if (!newCurrentValue)
+            neon.setFieldValue(pMainField, vars.get("$local.value"));
+    }
 }
\ No newline at end of file
-- 
GitLab