diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java
new file mode 100644
index 0000000..59ac5e1
--- /dev/null
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/InvoicePlugin.java
@@ -0,0 +1,75 @@
+package com.alexanderlogistics;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.imixs.workflow.ItemCollection;
+import org.imixs.workflow.engine.plugins.AbstractPlugin;
+import org.imixs.workflow.exceptions.PluginException;
+
+/**
+ * Das InvoicePlugin prüft die Eingaben auf gültigkeit, so dass diese problemlos
+ * nach Cargosoft expoertier werden können.
+ *
+ * Konkret geht es darum, das in den ChildItems keine leeren Zeilen vorkommen
+ * dürfen.
+ *
+ * @author rsoika
+ * @version 1.0
+ *
+ */
+public class InvoicePlugin extends AbstractPlugin {
+ public static final String CHILD_ITEM_PROPERTY = "_ChildItems";
+ public static final String ERROR_MISSING_DATA = "MISSING_DATA";
+
+ @SuppressWarnings("unused")
+ private static Logger logger = Logger.getLogger(InvoicePlugin.class.getName());
+
+ /**
+ * Test childworkitems for empty lines
+ *
+ * @throws PluginException - if txtCooperateSpace not filled.
+ *
+ **/
+ @Override
+ public ItemCollection run(ItemCollection workitem, ItemCollection documentActivity) throws PluginException {
+
+ List childs = explodeChildList(workitem);
+ for (ItemCollection posItem : childs) {
+ if (posItem.getItemValueString("name").trim().isEmpty()) {
+ // throw a plugin exception - because name is missing!
+ throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA,
+ "Eingabefehler - Die Positionsnummer in Zeile " + posItem.getItemValueString("numpos")
+ + " muss aufgefüllt sein!");
+ }
+
+ if (posItem.getItemValueFloat("amount") == 0) {
+ // throw a plugin exception - because name is missing!
+ throw new PluginException(InvoicePlugin.class.getName(), ERROR_MISSING_DATA,
+ "Eingabefehler - Der Nettobetrag in in Zeile " + posItem.getItemValueString("numpos")
+ + " darf nicht 0 sein!");
+ }
+ }
+ return workitem;
+ }
+
+ /**
+ * converts the Map List of a workitem into a List of ItemCollectons
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected List explodeChildList(ItemCollection workitem) {
+ // convert current list of childItems into ItemCollection elements
+ ArrayList childItems = new ArrayList();
+
+ List mapOrderItems = workitem.getItemValue(CHILD_ITEM_PROPERTY);
+ for (Object mapOderItem : mapOrderItems) {
+ if (mapOderItem instanceof Map) {
+ ItemCollection itemCol = new ItemCollection((Map) mapOderItem);
+ childItems.add(itemCol);
+ }
+ }
+ return childItems;
+ }
+}
diff --git a/pom.xml b/pom.xml
index 258b49d..37f5d12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,9 +17,9 @@
- ISO-8859-1
-
+ works fine
+ ISO-8859-1
+ -->
${maven.build.timestamp}
yyyyMMddHHmmss
diff --git a/workflow/cargosoft-export-1.0.0.bpmn b/workflow/cargosoft-export-1.0.0.bpmn
index 4837132..2c4fff1 100644
--- a/workflow/cargosoft-export-1.0.0.bpmn
+++ b/workflow/cargosoft-export-1.0.0.bpmn
@@ -328,6 +328,9 @@ Das ist eine automatische generierte E-Mail. Bitte nicht auf diese E-Mail antwor
+
+
+
SequenceFlow_38
SequenceFlow_24
@@ -405,7 +408,7 @@ Das ist eine automatische generierte E-Mail. Bitte nicht auf diese E-Mail antwor
-
+
diff --git a/workflow/rechnungseingang-de-1.0.2.bpmn b/workflow/rechnungseingang-de-1.0.2.bpmn
new file mode 100644
index 0000000..1aa090c
--- /dev/null
+++ b/workflow/rechnungseingang-de-1.0.2.bpmn
@@ -0,0 +1,3097 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ExclusiveGateway_4
+ Task_2
+ ExclusiveGateway_1
+ StartEvent_1
+ IntermediateCatchEvent_3
+ IntermediateCatchEvent_13
+ IntermediateCatchEvent_5000-20
+ IntermediateCatchEvent_6
+ EventBasedGateway_1
+ IntermediateCatchEvent_19
+ IntermediateThrowEvent_3
+
+
+ ExclusiveGateway_3
+ IntermediateCatchEvent_2
+ ExclusiveGateway_6
+ IntermediateCatchEvent_5005-20
+ EventBasedGateway_2
+ Task_5005
+ IntermediateCatchEvent_5005-10
+ IntermediateCatchEvent_5005-30
+ ExclusiveGateway_5
+ IntermediateCatchEvent_21
+
+
+ Task_5000
+ EventBasedGateway_4
+ IntermediateCatchEvent_16
+ IntermediateCatchEvent_15
+ IntermediateThrowEvent_1
+ IntermediateCatchEvent_5000-10
+ IntermediateCatchEvent_5
+
+
+ Task_3
+ IntermediateCatchEvent_17
+ ExclusiveGateway_2
+ IntermediateCatchEvent_4
+ Task_6
+ Task_7
+ IntermediateCatchEvent_18
+ Task_5
+ EndEvent_2
+ IntermediateCatchEvent_14
+ IntermediateCatchEvent_8
+ IntermediateCatchEvent_20
+ Task_4
+ Task_8
+ IntermediateCatchEvent_12
+ IntermediateCatchEvent_7
+ EndEvent_1
+ EndEvent_3
+
+
+ IntermediateCatchEvent_9
+ Task_1
+ IntermediateCatchEvent_11
+ IntermediateThrowEvent_5
+ IntermediateCatchEvent_10
+ IntermediateCatchEvent_1
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_31
+ SequenceFlow_1
+ SequenceFlow_3
+ SequenceFlow_32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_31
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+ space.name]]>
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_46
+ SequenceFlow_24
+
+
+ SequenceFlow_0
+ SequenceFlow_15
+ SequenceFlow_21
+ SequenceFlow_33
+
+
+
+ SequenceFlow_0
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_38
+ SequenceFlow_34
+ SequenceFlow_37
+
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home
+space.name
+
+-
+
cargosoft-export-1.0
+ 1000
+ 100
+ (?!txtworkflowhistory)(^[a-zA-Z]|^_)
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ 0 && (parseFloat(a)!=parseFloat(b)) ) {
+ result.isValid=false;
+ result.errorMessage="Der Rechnungsbetrag " + a+ " stimmt nicht mit dem Positionsbetrag " + b + " überein.";
+ }]]>
+
+
+
+ SequenceFlow_8
+ SequenceFlow_51
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_38
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home
+space.name ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_10
+ SequenceFlow_41
+
+
+ SequenceFlow_37
+ SequenceFlow_8
+ SequenceFlow_10
+ SequenceFlow_54
+
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_33
+ SequenceFlow_20
+ SequenceFlow_22
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+ SequenceFlow_20
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_4
+ SequenceFlow_55
+ SequenceFlow_50
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_29
+ SequenceFlow_52
+
+
+ SequenceFlow_32
+ SequenceFlow_29
+ SequenceFlow_30
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_30
+ SequenceFlow_7
+
+
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_25
+ SequenceFlow_44
+ SequenceFlow_47
+
+
+ SequenceFlow_47
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ SequenceFlow_55
+ SequenceFlow_12
+
+
+
+
+ SequenceFlow_24
+ SequenceFlow_13
+ SequenceFlow_16
+
+
+ workitem['space.team'] && workitem['space.team'][0]!=""
+
+
+ !workitem['space.team'] || workitem['space.team'][0]==""
+
+
+ SequenceFlow_18
+ SequenceFlow_1
+ SequenceFlow_5
+
+
+ workitem['payment.type'] && workitem['payment.type'][0]!="direct_debit"
+
+
+ SequenceFlow_7
+ SequenceFlow_5
+ SequenceFlow_4
+
+
+ workitem['payment.type'] && workitem['payment.type'][0]=="direct_debit"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+ SequenceFlow_6
+ SequenceFlow_18
+
+
+ SequenceFlow_51
+ SequenceFlow_16
+ SequenceFlow_6
+
+
+
+ SequenceFlow_15
+
+
+
+
+ SequenceFlow_52
+
+
+
+
+
+
+ SequenceFlow_12
+ SequenceFlow_53
+ SequenceFlow_19
+ SequenceFlow_25
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_19
+ SequenceFlow_23
+
+
+
+ var a=workitem.get("invoice.total")[0];
+
+workitem['payment.type'] && workitem['payment.type'][0]!="direct_debit" && a>0
+
+
+
+ var a=workitem.get("invoice.total")[0];
+
+!(workitem['payment.type'] && workitem['payment.type'][0]!="direct_debit" && a>0)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- Rechnungscontrolling
]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_21
+
+
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_13
+ SequenceFlow_26
+ SequenceFlow_41
+ SequenceFlow_11
+ SequenceFlow_28
+ SequenceFlow_36
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_26
+
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home
+space.name ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_28
+ SequenceFlow_34
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home
+space.name ]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_36
+ SequenceFlow_35
+
+
+ SequenceFlow_35
+
+
+
+
+
+ SequenceFlow_39
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_39
+ SequenceFlow_40
+
+
+ SequenceFlow_40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+ space.name]]>
+
+
+ false
+
+
+
+ SequenceFlow_11
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_23
+ SequenceFlow_45
+ SequenceFlow_14
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ SequenceFlow_14
+ SequenceFlow_42
+
+
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_42
+ SequenceFlow_43
+ SequenceFlow_27
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_43
+ SequenceFlow_44
+
+
+
+
+
+
+
+
+
+ SequenceFlow_27
+ SequenceFlow_45
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _subject]]>
+
+
+
+
+
+
+
+
+ _amount (Brutto € _amount_brutto )
+_description ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ SequenceFlow_50
+ SequenceFlow_53
+
+
+
+
+
+
+
+
+
+
+ cdtr.name invoice.number ]]>
+
+
+
+
+
+
+
+
+ cdtr.name
+Rechnungsnummer: invoice.number
+Betrag: invoice.total invoice.currency
+
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+ SequenceFlow_54
+ SequenceFlow_56
+
+
+
+
+ SequenceFlow_56
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-
+
cargosoft-export-1.0
+ 1000
+ 100
+ (?!txtworkflowhistory)(^[a-zA-Z]|^_)
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ SequenceFlow_3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ txtlastcomment]]>
+
+
+
+
+
+
+
+
+ numsequencenumber: cdtr.name invoice.number (invoice.currency invoice.total ) space.name ]]>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $workflowgroup - $workflowstatus ]]>
+ SequenceFlow_17
+ SequenceFlow_9
+
+
+ SequenceFlow_9
+
+
+
+ SequenceFlow_17
+
+
+
+
+ SequenceFlow_22
+ SequenceFlow_46
+ SequenceFlow_49
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home]]>
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ SequenceFlow_49
+ SequenceFlow_48
+
+
+ SequenceFlow_48
+
+
+
+
+
+
+ Wurde ein Prozess Manager festgelegt, erfolgt eine Genehmigung.
+
+
+
+ Die Rechnung wurde sachlich geprüft und genehmigt und kann nun in den Zahlungslauf übergeben werden.
+
+
+
+
+ Datenübergabe an Cargosoft.
+
+Export erfolgt über eine asynchrone Verarbeitung im Modell 'cargosoft-export'
+
+
+
+ 0 (keine Gutschriften)]]>
+ Payment = Sepa
+und invoice.total >0 (keine Gutschriften)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file