Related to issue 25906: Tree Extension Project, merge with pi
authorAugusto Mauch <augusto.mauch@openbravo.com>
Wed, 05 Mar 2014 23:13:24 +0100
changeset 22632 ba33a4a3e422
parent 22357 74df619a7316 (current diff)
parent 22631 22d0633c457c (diff)
child 22634 827c45d7b645
Related to issue 25906: Tree Extension Project, merge with pi
modules/org.openbravo.client.application/src-db/database/sourcedata/AD_COLUMN.xml
modules/org.openbravo.client.application/src-db/database/sourcedata/AD_PREFERENCE.xml
modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml
modules/org.openbravo.client.application/src-db/database/sourcedata/AD_TABLE.xml
modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE.xml
modules/org.openbravo.client.application/src/org/openbravo/client/application/ApplicationComponentProvider.java
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/ApplicationDictionaryCachedStructures.java
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-fk-filter.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js
modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-form-styles.js
modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-toolbar-styles.css
modules/org.openbravo.client.kernel/src-db/database/sourcedata/OBCLKER_UIDEFINITION.xml
modules/org.openbravo.service.datasource/src-db/database/sourcedata/AD_MESSAGE.xml
modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
src-db/database/model/functions/AD_GET_ORG_LE_BU.xml
src-db/database/model/functions/AD_ORGTYPE_ISLE_ISBU.xml
src-db/database/model/functions/AD_ORGTYPE_ISTRANS_ALLOWED.xml
src-db/database/model/functions/AD_ORG_CHK_CALENDAR.xml
src-db/database/model/functions/AD_ORG_CHK_READY.xml
src-db/database/model/functions/AD_ORG_CHK_SCHEMAS.xml
src-db/database/model/functions/AD_ORG_GETCALENDAROWNER.xml
src-db/database/model/functions/AD_ORG_GETPERIODCONTROLALLOW.xml
src-db/database/model/tables/AD_TAB.xml
src-db/database/model/tables/AD_TABLE.xml
src-db/database/model/tables/AD_TREE.xml
src-db/database/sourcedata/AD_AUXILIARINPUT.xml
src-db/database/sourcedata/AD_COLUMN.xml
src-db/database/sourcedata/AD_DATASET_TABLE.xml
src-db/database/sourcedata/AD_ELEMENT.xml
src-db/database/sourcedata/AD_FIELD.xml
src-db/database/sourcedata/AD_FIELDGROUP.xml
src-db/database/sourcedata/AD_MESSAGE.xml
src-db/database/sourcedata/AD_MODULE.xml
src-db/database/sourcedata/AD_PREFERENCE.xml
src-db/database/sourcedata/AD_REFERENCE.xml
src-db/database/sourcedata/AD_REF_LIST.xml
src-db/database/sourcedata/AD_REF_TABLE.xml
src-db/database/sourcedata/AD_TAB.xml
src-db/database/sourcedata/AD_TABLE.xml
src-db/database/sourcedata/AD_TREENODE.xml
src-db/database/sourcedata/AD_WINDOW.xml
src-db/database/sourcedata/OBCLKER_TEMPLATE.xml
src-db/database/sourcedata/OBSERDS_DATASOURCE.xml
src-db/database/sourcedata/OBUISEL_SELECTOR.xml
src-db/database/sourcedata/OBUISEL_SELECTOR_FIELD.xml
src-wad/src/org/openbravo/wad/WadUtility.java
src/org/openbravo/base/secureApp/OrgTree.java
src/org/openbravo/dal/security/OrganizationStructureProvider.java
src/org/openbravo/erpCommon/ad_reports/GeneralAccountingReports.java
src/org/openbravo/erpCommon/businessUtility/InitialClientSetup.java
src/org/openbravo/erpCommon/businessUtility/InitialOrgSetup.java
src/org/openbravo/erpCommon/businessUtility/InitialSetupUtility.java
src/org/openbravo/erpCommon/utility/WindowTree.java
src/org/openbravo/erpCommon/utility/WindowTreeChecks.java
src/org/openbravo/erpCommon/utility/WindowTreeUtility.java
src/org/openbravo/erpCommon/utility/WindowTree_data.xsql
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_COLUMN.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_COLUMN.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -1778,7 +1778,7 @@
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--37DCA71E621340B8A6FDE1264630AC48-->  <POSITION><![CDATA[45]]></POSITION>
+<!--37DCA71E621340B8A6FDE1264630AC48-->  <POSITION><![CDATA[47]]></POSITION>
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--37DCA71E621340B8A6FDE1264630AC48-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
@@ -2459,7 +2459,7 @@
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--59D7AB430670477ABA73B3DF07C8CA7D-->  <POSITION><![CDATA[47]]></POSITION>
+<!--59D7AB430670477ABA73B3DF07C8CA7D-->  <POSITION><![CDATA[49]]></POSITION>
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--59D7AB430670477ABA73B3DF07C8CA7D-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
@@ -3203,7 +3203,7 @@
 <!--718F42F7BD4E4F56908615C8301C8810-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--718F42F7BD4E4F56908615C8301C8810-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--718F42F7BD4E4F56908615C8301C8810-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--718F42F7BD4E4F56908615C8301C8810-->  <POSITION><![CDATA[46]]></POSITION>
+<!--718F42F7BD4E4F56908615C8301C8810-->  <POSITION><![CDATA[48]]></POSITION>
 <!--718F42F7BD4E4F56908615C8301C8810-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--718F42F7BD4E4F56908615C8301C8810-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--718F42F7BD4E4F56908615C8301C8810-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
@@ -6090,7 +6090,7 @@
 <!--961FB60572894A78810B8845F499D387-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--961FB60572894A78810B8845F499D387-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--961FB60572894A78810B8845F499D387-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--961FB60572894A78810B8845F499D387-->  <POSITION><![CDATA[44]]></POSITION>
+<!--961FB60572894A78810B8845F499D387-->  <POSITION><![CDATA[46]]></POSITION>
 <!--961FB60572894A78810B8845F499D387-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--961FB60572894A78810B8845F499D387-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--961FB60572894A78810B8845F499D387-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
@@ -7478,7 +7478,7 @@
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <POSITION><![CDATA[43]]></POSITION>
+<!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <POSITION><![CDATA[45]]></POSITION>
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--D3F8F1142D914AD0ACAD03B45BEB3E9F-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
@@ -7876,7 +7876,7 @@
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
-<!--E4F41D289C6A42A5BAF8BD766A15645F-->  <POSITION><![CDATA[42]]></POSITION>
+<!--E4F41D289C6A42A5BAF8BD766A15645F-->  <POSITION><![CDATA[44]]></POSITION>
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
 <!--E4F41D289C6A42A5BAF8BD766A15645F-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_PREFERENCE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_PREFERENCE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -56,7 +56,10 @@
   {"id": "ViewGrid_DeleteSelectedRecords", "keyComb": {"key": "Delete"}},
   {"id": "ViewForm_OpenLinkOut", "keyComb": {"ctrl": true, "alt": true, "key": "Enter"}},
   {"id": "Selector_ShowPopup", "keyComb": {"ctrl": true, "key": "Enter"}},
-  {"id": "SelectorLink_ShowPopup", "keyComb": {"ctrl": true, "key": "Enter"}}
+  {"id": "SelectorLink_ShowPopup", "keyComb": {"ctrl": true, "key": "Enter"}},
+  {"id": "TreeItem_ShowPopup", "keyComb": {"ctrl": true, "key": "Enter"}},
+  {"id": "TreeItem_ShowTree", "keyComb": {"alt": true, "key": "Arrow_Down"}},
+  {"id": "TreeItem_MoveToTree", "keyComb": {"alt": false, "key": "Arrow_Down"}}
 ]]]></VALUE>
 <!--5EE6D055A7FE4C4DA7EB557F6C61D0EA-->  <PROPERTY><![CDATA[OBUIAPP_KeyboardShortcuts]]></PROPERTY>
 <!--5EE6D055A7FE4C4DA7EB557F6C61D0EA-->  <ISPROPERTYLIST><![CDATA[Y]]></ISPROPERTYLIST>
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_REF_LIST.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -153,6 +153,17 @@
 <!--57A4B4D636954DF88444CAD72B20598B-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
 <!--57A4B4D636954DF88444CAD72B20598B--></AD_REF_LIST>
 
+<!--67C9AE863A644F46BC21F563E4910F6C--><AD_REF_LIST>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <AD_REF_LIST_ID><![CDATA[67C9AE863A644F46BC21F563E4910F6C]]></AD_REF_LIST_ID>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <VALUE><![CDATA[OBUIAPP_UseClassicTreeView]]></VALUE>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <NAME><![CDATA[Use Classic Popup Tree]]></NAME>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <AD_REFERENCE_ID><![CDATA[A26BA480E2014707B47257024C3CBFF7]]></AD_REFERENCE_ID>
+<!--67C9AE863A644F46BC21F563E4910F6C-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
+<!--67C9AE863A644F46BC21F563E4910F6C--></AD_REF_LIST>
+
 <!--6D7755B77E254D83AAC62B93D3A62ED9--><AD_REF_LIST>
 <!--6D7755B77E254D83AAC62B93D3A62ED9-->  <AD_REF_LIST_ID><![CDATA[6D7755B77E254D83AAC62B93D3A62ED9]]></AD_REF_LIST_ID>
 <!--6D7755B77E254D83AAC62B93D3A62ED9-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_TABLE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/AD_TABLE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -20,6 +20,7 @@
 <!--090A37D22E61FE94012E620CD15D0030-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--090A37D22E61FE94012E620CD15D0030-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--090A37D22E61FE94012E620CD15D0030-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--090A37D22E61FE94012E620CD15D0030-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--090A37D22E61FE94012E620CD15D0030--></AD_TABLE>
 
 <!--1A801FD9F44E4EFFA2EA928693A6BBCB--><AD_TABLE>
@@ -41,6 +42,7 @@
 <!--1A801FD9F44E4EFFA2EA928693A6BBCB-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--1A801FD9F44E4EFFA2EA928693A6BBCB-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--1A801FD9F44E4EFFA2EA928693A6BBCB-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--1A801FD9F44E4EFFA2EA928693A6BBCB-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--1A801FD9F44E4EFFA2EA928693A6BBCB--></AD_TABLE>
 
 <!--30123B1001FC4E82BB4CB9725E069B48--><AD_TABLE>
@@ -62,6 +64,7 @@
 <!--30123B1001FC4E82BB4CB9725E069B48-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--30123B1001FC4E82BB4CB9725E069B48-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--30123B1001FC4E82BB4CB9725E069B48-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--30123B1001FC4E82BB4CB9725E069B48-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--30123B1001FC4E82BB4CB9725E069B48--></AD_TABLE>
 
 <!--5D50320222DD4865ADFD50364C84291D--><AD_TABLE>
@@ -109,6 +112,7 @@
 <!--6EDC4A262444493BAE672E7E144A36F7-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--6EDC4A262444493BAE672E7E144A36F7-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--6EDC4A262444493BAE672E7E144A36F7-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--6EDC4A262444493BAE672E7E144A36F7-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--6EDC4A262444493BAE672E7E144A36F7--></AD_TABLE>
 
 <!--79127717F4514B459D9014C91E793CE9--><AD_TABLE>
@@ -134,6 +138,7 @@
 <!--79127717F4514B459D9014C91E793CE9-->  <ISDEFAULTACCT><![CDATA[N]]></ISDEFAULTACCT>
 <!--79127717F4514B459D9014C91E793CE9-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--79127717F4514B459D9014C91E793CE9-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--79127717F4514B459D9014C91E793CE9-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--79127717F4514B459D9014C91E793CE9--></AD_TABLE>
 
 <!--815D739C48414E01AF9F44EE3E8CCEBB--><AD_TABLE>
@@ -155,6 +160,7 @@
 <!--815D739C48414E01AF9F44EE3E8CCEBB-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--815D739C48414E01AF9F44EE3E8CCEBB-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--815D739C48414E01AF9F44EE3E8CCEBB-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--815D739C48414E01AF9F44EE3E8CCEBB-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--815D739C48414E01AF9F44EE3E8CCEBB--></AD_TABLE>
 
 <!--8A16662B37184121A1EDAA89890E160C--><AD_TABLE>
@@ -202,6 +208,7 @@
 <!--B733B9E74A0D4FE1A3EC2A100E0ADD47-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--B733B9E74A0D4FE1A3EC2A100E0ADD47-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--B733B9E74A0D4FE1A3EC2A100E0ADD47-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--B733B9E74A0D4FE1A3EC2A100E0ADD47-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--B733B9E74A0D4FE1A3EC2A100E0ADD47--></AD_TABLE>
 
 <!--DEADAC2161894A56A041B81A74B02D9E--><AD_TABLE>
@@ -225,6 +232,7 @@
 <!--DEADAC2161894A56A041B81A74B02D9E-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--DEADAC2161894A56A041B81A74B02D9E-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--DEADAC2161894A56A041B81A74B02D9E-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--DEADAC2161894A56A041B81A74B02D9E-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--DEADAC2161894A56A041B81A74B02D9E--></AD_TABLE>
 
 <!--E6F29F8A30BC4603B1D1195051C4F3A6--><AD_TABLE>
@@ -248,6 +256,7 @@
 <!--E6F29F8A30BC4603B1D1195051C4F3A6-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--E6F29F8A30BC4603B1D1195051C4F3A6-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--E6F29F8A30BC4603B1D1195051C4F3A6-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--E6F29F8A30BC4603B1D1195051C4F3A6-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--E6F29F8A30BC4603B1D1195051C4F3A6--></AD_TABLE>
 
 <!--F167EB822B8A4284AC37D5B40B785D51--><AD_TABLE>
@@ -294,6 +303,7 @@
 <!--FF8081813157AED2013157B1F75F0007-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--FF8081813157AED2013157B1F75F0007-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--FF8081813157AED2013157B1F75F0007-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--FF8081813157AED2013157B1F75F0007-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--FF8081813157AED2013157B1F75F0007--></AD_TABLE>
 
 <!--FF80818132D7FB620132D8129D1A0028--><AD_TABLE>
@@ -316,6 +326,7 @@
 <!--FF80818132D7FB620132D8129D1A0028-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--FF80818132D7FB620132D8129D1A0028-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--FF80818132D7FB620132D8129D1A0028-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--FF80818132D7FB620132D8129D1A0028-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--FF80818132D7FB620132D8129D1A0028--></AD_TABLE>
 
 <!--FF80818132D85DB50132D860924E0004--><AD_TABLE>
@@ -337,6 +348,7 @@
 <!--FF80818132D85DB50132D860924E0004-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--FF80818132D85DB50132D860924E0004-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--FF80818132D85DB50132D860924E0004-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--FF80818132D85DB50132D860924E0004-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--FF80818132D85DB50132D860924E0004--></AD_TABLE>
 
 <!--FF80818132F263D40132F26C10790010--><AD_TABLE>
@@ -358,6 +370,7 @@
 <!--FF80818132F263D40132F26C10790010-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
 <!--FF80818132F263D40132F26C10790010-->  <AD_PACKAGE_ID><![CDATA[BA250A68426F4D71BACAE830EF4EC696]]></AD_PACKAGE_ID>
 <!--FF80818132F263D40132F26C10790010-->  <DATAORIGINTYPE><![CDATA[Table]]></DATAORIGINTYPE>
+<!--FF80818132F263D40132F26C10790010-->  <ISTREE><![CDATA[N]]></ISTREE>
 <!--FF80818132F263D40132F26C10790010--></AD_TABLE>
 
 </data>
--- a/modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src-db/database/sourcedata/OBCLKER_TEMPLATE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -120,6 +120,18 @@
 <!--91DD63545B674BE8801E1FA4F48FF4C6-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
 <!--91DD63545B674BE8801E1FA4F48FF4C6--></OBCLKER_TEMPLATE>
 
+<!--9690A685A3D245899EA2A9C15D50D9FB--><OBCLKER_TEMPLATE>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <OBCLKER_TEMPLATE_ID><![CDATA[9690A685A3D245899EA2A9C15D50D9FB]]></OBCLKER_TEMPLATE_ID>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <AD_MODULE_ID><![CDATA[9BA0836A3CD74EE4AB48753A47211BCC]]></AD_MODULE_ID>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <NAME><![CDATA[Tree Selector Template]]></NAME>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <TEMPLATECLASSPATHLOCATION><![CDATA[/org/openbravo/client/application/templates/ob-tree-selector.js.ftl]]></TEMPLATECLASSPATHLOCATION>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <TEMPLATE_LANGUAGE><![CDATA[OBCLFRE_Freemarker]]></TEMPLATE_LANGUAGE>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <COMPONENT_TYPE><![CDATA[OBUISEL_Selector]]></COMPONENT_TYPE>
+<!--9690A685A3D245899EA2A9C15D50D9FB-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--9690A685A3D245899EA2A9C15D50D9FB--></OBCLKER_TEMPLATE>
+
 <!--9E97FF309FE44C61A761F50801F79349--><OBCLKER_TEMPLATE>
 <!--9E97FF309FE44C61A761F50801F79349-->  <OBCLKER_TEMPLATE_ID><![CDATA[9E97FF309FE44C61A761F50801F79349]]></OBCLKER_TEMPLATE_ID>
 <!--9E97FF309FE44C61A761F50801F79349-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/ApplicationComponentProvider.java	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/ApplicationComponentProvider.java	Wed Mar 05 23:13:24 2014 +0100
@@ -170,7 +170,14 @@
         "web/org.openbravo.client.application/js/calendar/ob-multicalendar.js", true));
     globalResources.add(createStaticResource(
         "web/org.openbravo.client.application/js/grid/ob-grid.js", false));
-
+    globalResources.add(createStaticResource(
+        "web/org.openbravo.client.application/js/grid/ob-tree-grid.js", false));
+    globalResources.add(createStaticResource(
+        "web/org.openbravo.client.application/js/grid/ob-tree-view-grid.js", false));
+    globalResources.add(createStaticResource(
+        "web/org.openbravo.client.application/js/form/formitem/ob-formitem-tree.js", true));
+    globalResources.add(createStaticResource(
+        "web/org.openbravo.client.application/js/form/formitem/ob-formitem-tree-filter.js", true));
     globalResources.add(createStaticResource(
         "web/org.openbravo.client.application/js/navbar/ob-quickrun-widget.js", false));
 
@@ -316,6 +323,10 @@
     globalResources.add(createStyleSheetResource(
         "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
             + KernelConstants.SKIN_PARAMETER
+            + "/org.openbravo.client.application/ob-tree-grid-styles.css", false));
+    globalResources.add(createStyleSheetResource(
+        "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
+            + KernelConstants.SKIN_PARAMETER
             + "/org.openbravo.client.application/ob-navigation-bar-styles.css", false));
     globalResources.add(createStyleSheetResource(
         "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
@@ -370,6 +381,10 @@
     globalResources.add(createStaticResource(
         "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
             + KernelConstants.SKIN_PARAMETER
+            + "/org.openbravo.client.application/ob-tree-grid-styles.js", false));
+    globalResources.add(createStaticResource(
+        "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
+            + KernelConstants.SKIN_PARAMETER
             + "/org.openbravo.client.application/ob-toolbar-styles.js", false));
     globalResources.add(createStaticResource(
         "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/event/TableTreeEventHandler.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,96 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.client.application.event;
+
+import javax.enterprise.event.Observes;
+
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.client.kernel.event.EntityNewEvent;
+import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
+import org.openbravo.client.kernel.event.EntityUpdateEvent;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.database.ConnectionProvider;
+import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.service.db.DalConnectionProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This event handler listen to events that are fired in the TableTree table. This table is used to
+ * define trees for the Tables.
+ * 
+ * This event handler is in charge of ensuring that each table define at most one ADTree table
+ * 
+ */
+public class TableTreeEventHandler extends EntityPersistenceEventObserver {
+
+  private static Entity[] entities = { ModelProvider.getInstance().getEntity(TableTree.ENTITY_NAME) };
+  private static Logger logger = LoggerFactory.getLogger(TableTreeEventHandler.class);
+  private static final String ADTREE_STRUCTURE = "ADTree";
+
+  @Override
+  protected Entity[] getObservedEntities() {
+    return entities;
+  }
+
+  public void onNew(@Observes EntityNewEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    Property treeStructureProperty = entities[0].getProperty(TableTree.PROPERTY_TREESTRUCTURE);
+    Property tableProperty = entities[0].getProperty(TableTree.PROPERTY_TABLE);
+    String treeStructureValue = (String) event.getCurrentState(treeStructureProperty);
+    Table tableValue = (Table) event.getCurrentState(tableProperty);
+    checkTreeStructure(tableValue, treeStructureValue);
+  }
+
+  public void onUpdate(@Observes EntityUpdateEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    Property treeStructureProperty = entities[0].getProperty(TableTree.PROPERTY_TREESTRUCTURE);
+    Property tableProperty = entities[0].getProperty(TableTree.PROPERTY_TABLE);
+    String treeStructureValue = (String) event.getCurrentState(treeStructureProperty);
+    Table tableValue = (Table) event.getCurrentState(tableProperty);
+    checkTreeStructure(tableValue, treeStructureValue);
+  }
+
+  private void checkTreeStructure(Table table, String treeStructure) {
+    if (ADTREE_STRUCTURE.equals(treeStructure)) {
+      // Check that there is no other ADTree Defined for this table
+      OBCriteria<TableTree> obq = OBDal.getInstance().createCriteria(TableTree.class);
+      obq.add(Restrictions.eq(TableTree.PROPERTY_TABLE, table));
+      obq.add(Restrictions.eq(TableTree.PROPERTY_TREESTRUCTURE, treeStructure));
+      if (obq.count() > 0) {
+        String language = OBContext.getOBContext().getLanguage().getLanguage();
+        ConnectionProvider conn = new DalConnectionProvider(false);
+        throw new OBException(Utility.messageBD(conn, "OBUIAPP_OneADTreePerTable", language));
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/event/TreeTablesEventHandler.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,172 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.client.application.event;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.client.kernel.event.EntityDeleteEvent;
+import org.openbravo.client.kernel.event.EntityNewEvent;
+import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.service.datasource.DataSourceService;
+import org.openbravo.service.datasource.DataSourceServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This event handler listen to events that are fired in all the tables with the flag isTree
+ * checked. When a record is created or deleted in one of these tables, the add or remove method of
+ * the corresponding datasource is executed.
+ * 
+ */
+public class TreeTablesEventHandler extends EntityPersistenceEventObserver {
+
+  private static Entity[] entities = getTreeTables();
+
+  private static final String TREENODE_DATASOURCE = "90034CAE96E847D78FBEF6D38CB1930D";
+  private static final String LINKTOPARENT_DATASOURCE = "610BEAE5E223447DBE6FF672B703F72F";
+
+  private static final String TREENODE_STRUCTURE = "ADTree";
+  private static final String LINKTOPARENT_STRUCTURE = "LinkToParent";
+  // private static final String CUSTOM_STRUCTURE = "Custom";
+  private static Logger logger = LoggerFactory.getLogger(TreeTablesEventHandler.class);
+
+  @Inject
+  private DataSourceServiceProvider dataSourceServiceProvider;
+
+  @Override
+  protected Entity[] getObservedEntities() {
+    return entities;
+  }
+
+  public void onNew(@Observes EntityNewEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    OBContext.setAdminMode(true);
+    try {
+      BaseOBObject bob = event.getTargetInstance();
+      DataSourceService dataSource = getDataSource(bob.getEntity().getTableId());
+      if (dataSource == null) {
+        return;
+      }
+      JSONObject jsonBob = this.fromBobToJSONObject(bob);
+      Map<String, String> parameters = new HashMap<String, String>();
+      parameters.put("jsonBob", jsonBob.toString());
+      dataSource.add(parameters, null);
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+  }
+
+  public void onDelete(@Observes EntityDeleteEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    OBContext.setAdminMode(true);
+    try {
+      BaseOBObject bob = event.getTargetInstance();
+      DataSourceService dataSource = getDataSource(bob.getEntity().getTableId());
+      if (dataSource == null) {
+        return;
+      }
+      JSONObject jsonBob = this.fromBobToJSONObject(bob);
+      Map<String, String> parameters = new HashMap<String, String>();
+      parameters.put("jsonBob", jsonBob.toString());
+      dataSource.remove(parameters);
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+  }
+
+  private DataSourceService getDataSource(String tableId) {
+    Table table = OBDal.getInstance().get(Table.class, tableId);
+    OBCriteria<TableTree> obq = OBDal.getInstance().createCriteria(TableTree.class);
+    obq.add(Restrictions.eq(TableTree.PROPERTY_TABLE, table));
+    obq.add(Restrictions.eq(TableTree.PROPERTY_ISMAINTREE, true));
+    List<TableTree> tableTreeList = obq.list();
+    if (tableTreeList.isEmpty()) {
+      return null;
+    }
+    TableTree mainTableTree = tableTreeList.get(0);
+    DataSourceService dataSource = null;
+    if (TREENODE_STRUCTURE.equals(mainTableTree.getTreeStructure())) {
+      dataSource = dataSourceServiceProvider.getDataSource(TREENODE_DATASOURCE);
+    } else if (LINKTOPARENT_STRUCTURE.equals(mainTableTree.getTreeStructure())) {
+      dataSource = dataSourceServiceProvider.getDataSource(LINKTOPARENT_DATASOURCE);
+    }
+    return dataSource;
+  }
+
+  private JSONObject fromBobToJSONObject(BaseOBObject bob) {
+    Entity entity = bob.getEntity();
+    List<Property> propertyList = entity.getProperties();
+    JSONObject jsonBob = new JSONObject();
+    try {
+      for (Property property : propertyList) {
+        if (property.isOneToMany()) {
+          continue;
+        }
+        if (property.getReferencedProperty() != null) {
+          BaseOBObject referencedbob = (BaseOBObject) bob.get(property.getName());
+          if (referencedbob != null) {
+            jsonBob.put(property.getName(), referencedbob.getId());
+          } else {
+            jsonBob.put(property.getName(), (Object) null);
+          }
+        } else {
+          jsonBob.put(property.getName(), bob.get(property.getName()));
+        }
+      }
+      jsonBob.put("_entity", entity.getName());
+    } catch (JSONException e) {
+      logger.error("Error while converting the BOB to JsonObject", e);
+    }
+    return jsonBob;
+  }
+
+  private static Entity[] getTreeTables() {
+    OBCriteria<Table> treeTablesCriteria = OBDal.getInstance().createCriteria(Table.class);
+    treeTablesCriteria.add(Restrictions.eq(Table.PROPERTY_ISTREE, true));
+    List<Table> treeTableList = treeTablesCriteria.list();
+    ArrayList<Entity> entityArray = new ArrayList<Entity>();
+    for (Table treeTable : treeTableList) {
+      entityArray.add(ModelProvider.getInstance().getEntityByTableId(treeTable.getId()));
+    }
+    return (Entity[]) entityArray.toArray(new Entity[entityArray.size()]);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-tree-grid.js.ftl	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,30 @@
+<#--
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+*/
+-->
+
+isc.OBTreeViewGrid.create({
+    view: this,
+    referencedTableId: '${data.referencedTableId}',
+    orderedTree:  ${data.orderedTree?string},
+    applyWhereClauseToChildren:  ${data.applyWhereClauseToChildren?string},
+    dataSourceId:  '${data.dataSourceId}',
+    treeStructure:  '${data.treeStructure}',
+    fields: this.gridFields
+})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-tree-selector.js.ftl	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,63 @@
+<#--
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+*/
+-->
+
+    treeReferenceId: '${data.id}',
+    dataSourceId: '${data.dataSourceId}',
+    parentSelectionAllowed:  ${data.parentSelectionAllowed?string},
+    popupTextMatchStyle: 'substring',
+    textMatchStyle: 'substring',
+    defaultPopupFilterField : '${data.defaultPopupFilterField}',
+    displayField: '${data.displayField?js_string}',
+    valueField: '${data.valueField?js_string}',
+    referencedTableId: '${data.referencedTableId?js_string}',
+    pickListFields: [
+    <#list data.pickListFields as pickListField>
+<@compress single_line=true>
+        {<#list pickListField.properties as property>
+        ${property.name}: ${property.value}<#if property_has_next>,</#if>
+         </#list>       
+        }<#if pickListField_has_next>,</#if>
+</@compress>
+    </#list>
+    ],
+    showSelectorGrid: ${data.showSelectorGrid},
+    treeGridFields : [
+    <#list data.treeGridFields as treeGridField>
+<@compress single_line=true>
+        {
+        <#list treeGridField.properties as property>
+        ${property.name}: ${property.value}<#if property_has_next>,</#if>
+         </#list>         
+         ${treeGridField.filterEditorProperties}         
+        }<#if treeGridField_has_next>,</#if>
+</@compress>
+    </#list>
+    ],
+    extraSearchFields: [${data.extraSearchFields}],
+<#--
+    // create the datasource in the init method, this
+    // prevents too early creation, it is created when the
+    // fields on the form are actually created
+-->
+    init: function() {
+        this.optionDataSource = ${data.dataSourceJavascript};
+        this.Super('init', arguments);
+    }, 
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-tab.js.ftl	Wed Mar 05 23:13:24 2014 +0100
@@ -54,6 +54,9 @@
     <#if tabComponent.trlTab>
     isTrlTab: ${tabComponent.trlTab?string},
     </#if> 
+    <#if tabComponent.tree>
+    isTree: ${tabComponent.tree?string},
+    </#if>     
     
     standardProperties:{
 <@compress single_line=true>
@@ -163,6 +166,10 @@
             </#list>
         },
     </#if>
+    
+
+    
+    
     initWidget: function() {
         this.prepareFields();
         this.dataSource = ${tabComponent.dataSourceJavaScript};
@@ -170,6 +177,9 @@
         this.dataSource.potentiallyShared = true;
         this.viewForm = isc.OBViewForm.create(isc.clone(OB.ViewFormProperties), ${tabComponent.viewForm}); 
         this.viewGrid = ${tabComponent.viewGrid};
+    <#if tabComponent.tree>
+        this.treeGrid = ${tabComponent.treeGrid};
+    </#if>
         this.Super('initWidget', arguments);
     }
 </#macro>
\ No newline at end of file
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/ApplicationDictionaryCachedStructures.java	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/ApplicationDictionaryCachedStructures.java	Wed Mar 05 23:13:24 2014 +0100
@@ -39,6 +39,8 @@
 import org.openbravo.model.ad.domain.ModelImplementation;
 import org.openbravo.model.ad.domain.Reference;
 import org.openbravo.model.ad.domain.ReferencedTable;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.domain.ReferencedTreeField;
 import org.openbravo.model.ad.ui.AuxiliaryInput;
 import org.openbravo.model.ad.ui.Field;
 import org.openbravo.model.ad.ui.Tab;
@@ -216,6 +218,7 @@
     if (c.getReferenceSearchKey() != null) {
       initializeReference(c.getReferenceSearchKey());
     }
+
   }
 
   private void initializeReference(Reference reference) {
@@ -229,6 +232,11 @@
       SelectorField displayField = s.getDisplayfield();
       initializeDALObject(displayField);
     }
+    for (ReferencedTree t : reference.getADReferencedTreeList()) {
+      initializeDALObject(t);
+      ReferencedTreeField displayField = t.getDisplayfield();
+      initializeDALObject(displayField);
+    }
 
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBTreeGridComponent.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,108 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.application.window;
+
+import org.openbravo.client.kernel.BaseTemplateComponent;
+import org.openbravo.client.kernel.Template;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.ad.ui.Tab;
+import org.openbravo.model.ad.utility.TableTree;
+
+/**
+ * The backing bean for generating the OBTreeGridPopup client-side representation.
+ * 
+ * @author AugustoMauch
+ */
+public class OBTreeGridComponent extends BaseTemplateComponent {
+
+  private static final String DEFAULT_TEMPLATE_ID = "74451C30650946FC855FCFDB4577070C";
+
+  private static final String TREENODE_DATASOURCE = "90034CAE96E847D78FBEF6D38CB1930D";
+  private static final String LINKTOPARENT_DATASOURCE = "610BEAE5E223447DBE6FF672B703F72F";
+
+  private static final String TREENODE_STRUCTURE = "ADTree";
+  private static final String LINKTOPARENT_STRUCTURE = "LinkToParent";
+
+  private Tab tab;
+  private OBViewTab viewTab;
+
+  protected Template getComponentTemplate() {
+    return OBDal.getInstance().get(Template.class, DEFAULT_TEMPLATE_ID);
+  }
+
+  public Tab getTab() {
+    return tab;
+  }
+
+  public void setTab(Tab tab) {
+    this.tab = tab;
+  }
+
+  public OBViewTab getViewTab() {
+    return viewTab;
+  }
+
+  public void setViewTab(OBViewTab viewTab) {
+    this.viewTab = viewTab;
+  }
+
+  public String getReferencedTableId() {
+    return tab.getTable().getId();
+  }
+
+  public boolean isOrderedTree() {
+    TableTree tableTree = tab.getTableTree();
+    if (tableTree != null) {
+      return tableTree.isOrdered();
+    } else {
+      return false;
+    }
+  }
+
+  public boolean isApplyWhereClauseToChildren() {
+    TableTree tableTree = tab.getTableTree();
+    return tableTree.isApplyWhereClauseToChildNodes();
+  }
+
+  public String getDataSourceId() {
+    String dataSourceId = null;
+    TableTree tableTree = tab.getTableTree();
+    if (tableTree != null) {
+      if (TREENODE_STRUCTURE.equals(tableTree.getTreeStructure())) {
+        dataSourceId = TREENODE_DATASOURCE;
+      } else if (LINKTOPARENT_STRUCTURE.equals(tableTree.getTreeStructure())) {
+        dataSourceId = LINKTOPARENT_DATASOURCE;
+      } else {
+        return tableTree.getDatasource().getId();
+      }
+      return dataSourceId;
+    } else {
+      return null;
+    }
+  }
+
+  public String getTreeStructure() {
+    TableTree tableTree = tab.getTableTree();
+    if (tableTree != null) {
+      return tableTree.getTreeStructure();
+    } else {
+      return null;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBTreeReferenceComponent.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,627 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.application.window;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.model.domaintype.DomainType;
+import org.openbravo.base.model.domaintype.ForeignKeyDomainType;
+import org.openbravo.base.model.domaintype.PrimitiveDomainType;
+import org.openbravo.base.model.domaintype.StringEnumerateDomainType;
+import org.openbravo.base.util.Check;
+import org.openbravo.client.kernel.BaseTemplateComponent;
+import org.openbravo.client.kernel.Component;
+import org.openbravo.client.kernel.ComponentProvider;
+import org.openbravo.client.kernel.Template;
+import org.openbravo.client.kernel.reference.FKComboUIDefinition;
+import org.openbravo.client.kernel.reference.UIDefinition;
+import org.openbravo.client.kernel.reference.UIDefinitionController;
+import org.openbravo.dal.core.DalUtil;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.dal.service.OBDao;
+import org.openbravo.model.ad.datamodel.Column;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.domain.ReferencedTreeField;
+import org.openbravo.model.ad.module.Module;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.service.datasource.DataSourceConstants;
+import org.openbravo.service.datasource.DataSourceProperty;
+import org.openbravo.service.datasource.DataSourceProperty.RefListEntry;
+import org.openbravo.service.json.JsonConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The backing bean for generating the OBTreeReference client-side representation.
+ * 
+ * @author AugustoMauch
+ */
+public class OBTreeReferenceComponent extends BaseTemplateComponent {
+
+  private static final String TREE_REFERENCE_TEMPLATE = "9690A685A3D245899EA2A9C15D50D9FB";
+
+  private static final String TREENODE_DATASOURCE = "90034CAE96E847D78FBEF6D38CB1930D";
+  private static final String LINKTOPARENT_DATASOURCE = "610BEAE5E223447DBE6FF672B703F72F";
+
+  private static final String TREENODE_STRUCTURE = "ADTree";
+  private static final String LINKTOPARENT_STRUCTURE = "LinkToParent";
+
+  private ReferencedTree referencedTree;
+  private List<ReferencedTreeField> treeFields;
+
+  private static Logger log = LoggerFactory.getLogger(OBTreeReferenceComponent.class);
+
+  @Override
+  protected Template getComponentTemplate() {
+    Template template = OBDal.getInstance().get(Template.class, TREE_REFERENCE_TEMPLATE);
+    return template;
+  }
+
+  public void setReferencedTree(ReferencedTree referencedTree) {
+    this.referencedTree = referencedTree;
+  }
+
+  public ReferencedTree getreferencedTree() {
+    return referencedTree;
+  }
+
+  public static String getAdditionalProperties(ReferencedTree referencedTree,
+      boolean onlyDisplayField) {
+    if (onlyDisplayField
+        && (referencedTree.getDisplayfield() == null || !referencedTree.getDisplayfield()
+            .isActive())) {
+      return "";
+    }
+    final StringBuilder extraProperties = new StringBuilder();
+    for (ReferencedTreeField treeField : referencedTree.getADReferencedTreeFieldList()) {
+      if (onlyDisplayField && treeField != referencedTree.getDisplayfield()) {
+        continue;
+      }
+      if (!treeField.isActive()) {
+        continue;
+      }
+      String fieldName = getPropertyOrDataSourceField(treeField);
+      final DomainType domainType = getDomainType(treeField);
+      if (domainType instanceof ForeignKeyDomainType) {
+        fieldName = fieldName + DalUtil.FIELDSEPARATOR + JsonConstants.IDENTIFIER;
+      }
+      if (extraProperties.length() > 0) {
+        extraProperties.append(",");
+      }
+      extraProperties.append(fieldName);
+    }
+    return extraProperties.toString();
+  }
+
+  public boolean isParentSelectionAllowed() {
+    return getReferencedTree().getTableTreeCategory().isParentSelectionAllowed();
+  }
+
+  private static String getPropertyOrDataSourceField(ReferencedTreeField treeField) {
+    String result = null;
+    if (treeField.getProperty() != null) {
+      result = treeField.getProperty();
+    }
+    return result.replace(DalUtil.DOT, DalUtil.FIELDSEPARATOR);
+  }
+
+  private static DomainType getDomainType(ReferencedTreeField treeField) {
+    if (treeField.getRefTree().getTable() != null && treeField.getProperty() != null) {
+      final String entityName = treeField.getRefTree().getTable().getName();
+      final Entity entity = ModelProvider.getInstance().getEntity(entityName);
+      final Property property = DalUtil.getPropertyFromPath(entity, treeField.getProperty());
+      Check.isNotNull(property, "Property " + treeField.getProperty() + " not found in Entity "
+          + entity);
+      return property.getDomainType();
+    }
+    return null;
+  }
+
+  @Inject
+  @ComponentProvider.Qualifier(DataSourceConstants.DS_COMPONENT_TYPE)
+  private ComponentProvider componentProvider;
+
+  public Module getModule() {
+    return getReferencedTree().getModule();
+  }
+
+  /**
+   * Computes the field in the popup which can receive the value entered by the user in the
+   * suggestion box, to set the first default filter.
+   * 
+   * @return the field in the popup to set.
+   */
+  public String getDefaultPopupFilterField() {
+    if (getReferencedTree().getDisplayfield() != null
+        && getReferencedTree().getDisplayfield().isShowingrid()) {
+      if (getReferencedTree().getDisplayfield().getProperty() != null) {
+        return getReferencedTree().getDisplayfield().getProperty()
+            .replace(DalUtil.DOT, DalUtil.FIELDSEPARATOR);
+      }
+    }
+    // a very common case, return the first selector field which is part of the
+    // identifier
+    if (getReferencedTree().getDisplayfield() == null
+        || (getReferencedTree().getDisplayfield().getProperty() != null && getReferencedTree()
+            .getDisplayfield().getProperty().equals(JsonConstants.IDENTIFIER))) {
+      final Entity entity = getEntity();
+      if (entity != null) {
+        for (Property prop : entity.getIdentifierProperties()) {
+          for (ReferencedTreeField treeField : getActiveTreeFields()) {
+            if (treeField.getProperty() != null && treeField.getProperty().equals(prop.getName())) {
+              return treeField.getProperty();
+            }
+          }
+        }
+      }
+    }
+    return JsonConstants.IDENTIFIER;
+  }
+
+  public ReferencedTree getReferencedTree() {
+    if (referencedTree == null) {
+      referencedTree = OBDal.getInstance().get(ReferencedTree.class, getId());
+      Check.isNotNull(referencedTree, "No tree reference found using id " + getId());
+      Check.isTrue(referencedTree.isActive(), "Tree reference " + referencedTree
+          + " is not active anymore");
+    }
+    return referencedTree;
+  }
+
+  private List<ReferencedTreeField> getActiveTreeFields() {
+    if (treeFields == null) {
+      treeFields = OBDao.getActiveOBObjectList(getReferencedTree(),
+          ReferencedTree.PROPERTY_ADREFERENCEDTREEFIELDLIST);
+    }
+    return treeFields;
+  }
+
+  public String getValueField() {
+    if (getReferencedTree().getValuefield() != null) {
+      final String valueField = getPropertyOrDataSourceField(getReferencedTree().getValuefield());
+      final DomainType domainType = getDomainType(getReferencedTree().getValuefield());
+      if (domainType instanceof ForeignKeyDomainType) {
+        return valueField + DalUtil.FIELDSEPARATOR + JsonConstants.ID;
+      }
+      return valueField;
+    }
+    return JsonConstants.ID;
+  }
+
+  public String getDisplayField() {
+    if (getReferencedTree().getDisplayfield() != null) {
+      return getPropertyOrDataSourceField(getReferencedTree().getDisplayfield());
+    }
+    // in all other cases use an identifier
+    return JsonConstants.IDENTIFIER;
+  }
+
+  private boolean isBoolean(ReferencedTreeField treeField) {
+    final DomainType domainType = getDomainType(treeField);
+    if (domainType instanceof PrimitiveDomainType) {
+      final PrimitiveDomainType primitiveDomainType = (PrimitiveDomainType) domainType;
+      return boolean.class == primitiveDomainType.getPrimitiveType()
+          || Boolean.class == primitiveDomainType.getPrimitiveType();
+    }
+    return false;
+  }
+
+  /**
+   * @return true if there is at least one active field shown in grid
+   */
+  public String getShowSelectorGrid() {
+    if (OBDao.getFilteredCriteria(ReferencedTreeField.class,
+        Restrictions.eq(ReferencedTreeField.PROPERTY_REFTREE, getReferencedTree()),
+        Restrictions.eq(ReferencedTreeField.PROPERTY_SHOWINGRID, true)).count() > 0) {
+      return Boolean.TRUE.toString();
+    }
+    return Boolean.FALSE.toString();
+  }
+
+  public String getTitle() {
+    String description = getReferencedTree().getReference().getName();
+    if (description == null) {
+      return "";
+    }
+    return description;
+  }
+
+  public String getDataSourceJavascript() {
+    final String dataSourceId;
+
+    Check.isNotNull(getReferencedTree().getTable(), "The table is null for this tree reference: "
+        + referencedTree);
+    dataSourceId = getReferencedTree().getTable().getName();
+
+    final Map<String, Object> dsParameters = new HashMap<String, Object>(getParameters());
+    dsParameters.put(DataSourceConstants.DS_ONLY_GENERATE_CREATESTATEMENT, true);
+    dsParameters.put(DataSourceConstants.MINIMAL_PROPERTY_OUTPUT, true);
+    final String extraProperties = getAdditionalProperties(getReferencedTree(), false);
+    if (extraProperties.length() > 0) {
+      dsParameters.put(JsonConstants.ADDITIONAL_PROPERTIES_PARAMETER, extraProperties.toString());
+    }
+
+    final Component component = componentProvider.getComponent(dataSourceId, dsParameters);
+
+    return component.generate();
+  }
+
+  public String getExtraSearchFields() {
+    final String displayField = getDisplayField();
+    final StringBuilder sb = new StringBuilder();
+    for (ReferencedTreeField treeField : getActiveTreeFields()) {
+      String fieldName = getPropertyOrDataSourceField(treeField);
+      if (fieldName.equals(displayField)) {
+        continue;
+      }
+      // prevent booleans as search fields, they don't work
+      if (treeField.isSearchinsuggestionbox() && !isBoolean(treeField)) {
+
+        // handle the case that the field is a foreign key
+        // in that case always show the identifier
+        final DomainType domainType = getDomainType(treeField);
+        if (domainType instanceof ForeignKeyDomainType) {
+          fieldName = fieldName + DalUtil.FIELDSEPARATOR + JsonConstants.IDENTIFIER;
+        }
+
+        if (sb.length() > 0) {
+          sb.append(",");
+        }
+        sb.append("'" + fieldName + "'");
+      }
+    }
+    return sb.toString();
+  }
+
+  public List<LocalTreeField> getPickListFields() {
+    // return the displayfield as the first column of the picklist and add all the extra fields with
+    // the showInPicklist flag.
+    List<LocalTreeField> pickListFields = new ArrayList<LocalTreeField>();
+    final String displayField = getDisplayField();
+    final LocalTreeField LocalTreeField = new LocalTreeField();
+    LocalTreeField.setName(displayField);
+    LocalTreeField.setPickListField(true);
+    pickListFields.add(LocalTreeField);
+    pickListFields.addAll(getTreeFields(true, false));
+    return pickListFields;
+  }
+
+  public List<LocalTreeField> getTreeGridFields() {
+    return getTreeFields(false, true);
+  }
+
+  private List<LocalTreeField> getTreeFields(boolean pickList, boolean popupGrid) {
+    final List<LocalTreeField> result = new ArrayList<LocalTreeField>();
+
+    final List<ReferencedTreeField> sortedFields = new ArrayList<ReferencedTreeField>(
+        getActiveTreeFields());
+    Collections.sort(sortedFields, new TreeFieldComparator());
+
+    for (ReferencedTreeField treeField : sortedFields) {
+      if (popupGrid && !treeField.isShowingrid()) {
+        continue;
+      }
+      if (pickList
+          && (!treeField.isShowinpicklist() || treeField.equals(getReferencedTree()
+              .getDisplayfield()))) {
+        continue;
+      }
+      final LocalTreeField LocalTreeField = new LocalTreeField();
+      LocalTreeField.setPickListField(pickList);
+      String fieldName = getPropertyOrDataSourceField(treeField);
+
+      // handle the case that the field is a foreign key
+      // in that case always show the identifier
+      final DomainType domainType = getDomainType(treeField);
+      if (domainType instanceof ForeignKeyDomainType) {
+        String displayField = fieldName.replace(".", DalUtil.FIELDSEPARATOR)
+            + DalUtil.FIELDSEPARATOR + JsonConstants.IDENTIFIER;
+        LocalTreeField.setDisplayField(displayField);
+      }
+
+      fieldName = fieldName.replace(".", DalUtil.FIELDSEPARATOR);
+
+      LocalTreeField.setName(fieldName);
+      LocalTreeField.setTitle(treeField.getName());
+      LocalTreeField.setSort(treeField.isSort());
+      LocalTreeField.setFilter(treeField.isFilter());
+      LocalTreeField.setDomainType(domainType);
+      LocalTreeField.setUIDefinition(getUIDefinition(treeField));
+      LocalTreeField.setReferencedTreeField(treeField);
+      result.add(LocalTreeField);
+    }
+    return result;
+  }
+
+  // used to create picklist and grid fields
+  public static class LocalTreeField {
+    private String title = " ";
+    private String name;
+    private String displayField;
+    private boolean filter;
+    private boolean sort;
+    private DomainType domainType;
+    private UIDefinition uiDefinition;
+    private ReferencedTreeField treeField;
+    private boolean pickListField;
+
+    public DomainType getDomainType() {
+      return domainType;
+    }
+
+    public void setDomainType(DomainType domainType) {
+      this.domainType = domainType;
+    }
+
+    public String getTitle() {
+      return title;
+    }
+
+    public void setTitle(String title) {
+      this.title = title;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public String getDisplayField() {
+      return displayField;
+    }
+
+    public void setDisplayField(String displayField) {
+      this.displayField = displayField;
+    }
+
+    public String getFilterEditorProperties() {
+      if (getUIDefinition() != null) {
+        if (getUIDefinition() instanceof FKComboUIDefinition) {
+          return ", canFilter:true, required: false, filterEditorType: 'OBTreeFilterSelectItem', filterEditorProperties: {entity: '"
+              + getEntityName() + "'}";
+        }
+        return getUIDefinition().getFilterEditorProperties(null);
+      }
+      return ", filterEditorType: 'OBTextItem'";
+    }
+
+    public List<LocalTreeFieldProperty> getProperties() {
+      final List<LocalTreeFieldProperty> result = new ArrayList<LocalTreeFieldProperty>();
+      result.add(createLocalTreeFieldProperty("title", title));
+      result.add(createLocalTreeFieldProperty("name", name));
+      // is used at runtime to set canFilter on false for a field
+      if (!isPickListField()) {
+        if (!filter) {
+          result.add(createLocalTreeFieldProperty("disableFilter", !filter));
+        }
+        if (!sort) {
+          result.add(createLocalTreeFieldProperty("canSort", sort));
+        }
+      }
+      result.add(createLocalTreeFieldProperty("type", getType()));
+      if ((domainType instanceof PrimitiveDomainType)) {
+        final PrimitiveDomainType primitiveDomainType = (PrimitiveDomainType) domainType;
+        if (Date.class.isAssignableFrom(primitiveDomainType.getPrimitiveType())) {
+          result.add(createLocalTreeFieldProperty("width", 100));
+        }
+      }
+      if (domainType instanceof ForeignKeyDomainType) {
+        result.add(createLocalTreeFieldProperty("displayField", displayField));
+      }
+
+      if (domainType instanceof StringEnumerateDomainType) {
+        Column column = null;
+        if (treeField.getRefTree().getTable() != null && treeField.getProperty() != null) {
+          final String entityName = treeField.getRefTree().getTable().getName();
+          final Entity entity = ModelProvider.getInstance().getEntity(entityName);
+          final Property property = DalUtil.getPropertyFromPath(entity, treeField.getProperty());
+          if (property != null) {
+            column = OBDal.getInstance().get(Column.class, property.getColumnId());
+          }
+        }
+        if (column != null && column.getReferenceSearchKey() != null) {
+          Set<String> allowedValues = DataSourceProperty.getAllowedValues(column
+              .getReferenceSearchKey());
+          List<RefListEntry> entries = DataSourceProperty.createValueMap(allowedValues, column
+              .getReferenceSearchKey().getId());
+          JSONObject jsonValueMap = new JSONObject();
+          for (RefListEntry entry : entries) {
+            try {
+              jsonValueMap.put(entry.getValue(), entry.getLabel());
+            } catch (JSONException e) {
+              log.error("Error generating value map for " + name, e);
+            }
+          }
+          LocalTreeFieldProperty valueMap = new LocalTreeFieldProperty();
+          valueMap.setName("valueMap");
+          valueMap.setValue(jsonValueMap.toString());
+          result.add(valueMap);
+        } else {
+          log.warn("Cannot set value map for selector enum " + name);
+        }
+
+      }
+      return result;
+    }
+
+    private LocalTreeFieldProperty createLocalTreeFieldProperty(String propName, Object propValue) {
+      LocalTreeFieldProperty LocalTreeFieldProperty = new LocalTreeFieldProperty();
+      LocalTreeFieldProperty.setName(propName);
+      if (propValue instanceof String) {
+        LocalTreeFieldProperty.setStringValue((String) propValue);
+      } else {
+        LocalTreeFieldProperty.setValue("" + propValue);
+      }
+      return LocalTreeFieldProperty;
+    }
+
+    public boolean isFilter() {
+      return filter;
+    }
+
+    public void setFilter(boolean filter) {
+      this.filter = filter;
+    }
+
+    public boolean isSort() {
+      return sort;
+    }
+
+    public void setSort(boolean sort) {
+      this.sort = sort;
+    }
+
+    public static class LocalTreeFieldProperty {
+      private String name;
+      private String value;
+
+      public String getName() {
+        return name;
+      }
+
+      public void setName(String name) {
+        this.name = name;
+      }
+
+      public String getValue() {
+        return value;
+      }
+
+      public void setStringValue(String value) {
+        this.value = "'" + StringEscapeUtils.escapeJavaScript(value) + "'";
+      }
+
+      public void setValue(String value) {
+        this.value = value;
+      }
+    }
+
+    public String getType() {
+      if (getUIDefinition() == null) {
+        return "text";
+      }
+      return getUIDefinition().getName();
+    }
+
+    public UIDefinition getUIDefinition() {
+      return uiDefinition;
+    }
+
+    public void setUIDefinition(UIDefinition uiDefinition) {
+      this.uiDefinition = uiDefinition;
+    }
+
+    public void setReferencedTreeField(ReferencedTreeField treeField) {
+      this.treeField = treeField;
+    }
+
+    public ReferencedTreeField getReferencedTreeField() {
+      return treeField;
+    }
+
+    public String getEntityName() {
+      if (treeField == null) {
+        return null;
+      }
+      if (treeField.getRefTree().getTable() != null && treeField.getProperty() != null) {
+        final String entityName = treeField.getRefTree().getTable().getName();
+        final Entity entity = ModelProvider.getInstance().getEntity(entityName);
+        final Property property = DalUtil.getPropertyFromPath(entity, treeField.getProperty());
+        return property.getTargetEntity().getName();
+      }
+      return null;
+    }
+
+    public boolean isPickListField() {
+      return pickListField;
+    }
+
+    public void setPickListField(boolean pickListField) {
+      this.pickListField = pickListField;
+    }
+
+  }
+
+  private class TreeFieldComparator implements Comparator<ReferencedTreeField> {
+
+    @Override
+    public int compare(ReferencedTreeField field0, ReferencedTreeField field1) {
+      return (int) (field0.getRecordSortNo() - field1.getRecordSortNo());
+    }
+
+  }
+
+  private UIDefinition getUIDefinition(ReferencedTreeField treeField) {
+    if (treeField.getRefTree().getTable() != null && treeField.getProperty() != null) {
+      final String entityName = treeField.getRefTree().getTable().getName();
+      final Entity entity = ModelProvider.getInstance().getEntity(entityName);
+      final Property property = DalUtil.getPropertyFromPath(entity, treeField.getProperty());
+      return UIDefinitionController.getInstance().getUIDefinition(property.getColumnId());
+    }
+    return null;
+  }
+
+  private Entity getEntity() {
+    if (getReferencedTree().getTable() != null) {
+      final String entityName = getReferencedTree().getTable().getName();
+      return ModelProvider.getInstance().getEntity(entityName);
+    }
+    return null;
+  }
+
+  public String getDataSourceId() {
+    String dataSourceId = null;
+    TableTree tableTree = referencedTree.getTableTreeCategory();
+    if (tableTree != null) {
+      if (TREENODE_STRUCTURE.equals(tableTree.getTreeStructure())) {
+        dataSourceId = TREENODE_DATASOURCE;
+      } else if (LINKTOPARENT_STRUCTURE.equals(tableTree.getTreeStructure())) {
+        dataSourceId = LINKTOPARENT_DATASOURCE;
+      } else {
+        return tableTree.getDatasource().getId();
+      }
+      return dataSourceId;
+    } else {
+      return null;
+    }
+  }
+
+  public String getReferencedTableId() {
+    return referencedTree.getTable().getId();
+  }
+}
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/OBViewTab.java	Wed Mar 05 23:13:24 2014 +0100
@@ -50,7 +50,9 @@
 import org.openbravo.dal.service.OBCriteria;
 import org.openbravo.dal.service.OBDal;
 import org.openbravo.data.Sqlc;
+import org.openbravo.erpCommon.businessUtility.Preferences;
 import org.openbravo.erpCommon.obps.ActivationKey;
+import org.openbravo.erpCommon.utility.PropertyException;
 import org.openbravo.erpCommon.utility.Utility;
 import org.openbravo.model.ad.datamodel.Column;
 import org.openbravo.model.ad.domain.ModelImplementation;
@@ -247,14 +249,34 @@
       iconButtons.add(auditBtn);
     }
 
-    // Tree button
-    if (tab.isTreeIncluded()) {
-      IconButton treeBtn = new IconButton();
-      treeBtn.type = "tree";
-      treeBtn.label = Utility.messageBD(new DalConnectionProvider(false), "Tree", OBContext
-          .getOBContext().getLanguage().getLanguage());
-      treeBtn.action = "OB.ToolbarUtils.showTree(this.view);";
-      iconButtons.add(treeBtn);
+    String useClassicPopupTreeStr = null;
+    try {
+      useClassicPopupTreeStr = Preferences.getPreferenceValue("OBUIAPP_UseClassicTreeView", true,
+          OBContext.getOBContext().getCurrentClient(), OBContext.getOBContext()
+              .getCurrentOrganization(), OBContext.getOBContext().getUser(), OBContext
+              .getOBContext().getRole(), tab.getWindow());
+    } catch (PropertyException e) {
+      // The property is not defined, so the classic popup tree should not be used
+    }
+    boolean useClassicPopupTree = ("Y".equals(useClassicPopupTreeStr));
+
+    if (tab.getTableTree() != null) {
+      if (useClassicPopupTree) {
+        // Classic Tree button
+        IconButton treeBtn = new IconButton();
+        treeBtn.type = "tree";
+        treeBtn.label = Utility.messageBD(new DalConnectionProvider(false), "Tree", OBContext
+            .getOBContext().getLanguage().getLanguage());
+        treeBtn.action = "OB.ToolbarUtils.showTree(this.view);";
+        iconButtons.add(treeBtn);
+      } else {
+        IconButton treeBtn = new IconButton();
+        treeBtn.type = "treeGrid";
+        treeBtn.label = Utility.messageBD(new DalConnectionProvider(false),
+            "OBUIAPP_TOGGLE_TREE_BUTTON", OBContext.getOBContext().getLanguage().getLanguage());
+        treeBtn.action = "OB.ToolbarUtils.toggleTreeGridVisibility(this.view);";
+        iconButtons.add(treeBtn);
+      }
     }
 
     return iconButtons;
@@ -968,6 +990,22 @@
     return tab.isShowParentsButtons();
   }
 
+  public boolean isTree() {
+    return (tab.getTableTree() != null);
+  }
+
+  public String getTreeGrid() {
+    final OBTreeGridComponent treeGridComponent = createComponent(OBTreeGridComponent.class);
+    treeGridComponent.setParameters(getParameters());
+    treeGridComponent.setTab(tab);
+    treeGridComponent.setViewTab(this);
+    return treeGridComponent.generate();
+  }
+
+  public String getReferencedTableId() {
+    return tab.getTable().getId();
+  }
+
   private class FormFieldComparator implements Comparator<Field> {
 
     /**
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-fk-filter.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-fk-filter.js	Wed Mar 05 23:13:24 2014 +0100
@@ -48,7 +48,8 @@
   init: function () {
     var me = this,
         grid = this.form.grid.sourceWidget,
-        gridField = grid.getField(this.name);
+        gridField = grid.getField(this.name),
+        dataSource;
 
     // the textMatchStyle is sometimes overridden from the underlying
     // grid, this happens when used within the selector editor.
@@ -116,8 +117,7 @@
         }
       }
     };
-
-    this.setOptionDataSource(OB.Datasource.create({
+    dataSource = OB.Datasource.create({
       dataURL: grid.getDataSource().dataURL,
       requestProperties: {
         params: {
@@ -126,7 +126,11 @@
         }
       },
       fields: this.pickListFields
-    }));
+    });
+    if (grid.Class === 'OBTreeGrid') {
+      dataSource.requestProperties.params.tabId = grid.view.tabId;
+    }
+    this.setOptionDataSource(dataSource);
 
     this.Super('init', arguments);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-tree-filter.js	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,320 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+isc.ClassFactory.defineClass('OBTreeItemPopupFilterWindow', isc.OBPopup);
+
+isc.OBTreeItemPopupFilterWindow.addProperties({
+  canDragReposition: true,
+  canDragResize: true,
+  dismissOnEscape: true,
+  destroyOnClose: false,
+  showMaximizeButton: true,
+  multiselect: true,
+
+  defaultTreeGridField: {
+    canFreeze: true,
+    canGroupBy: false
+  },
+
+  initWidget: function () {
+    var treeWindow = this,
+        okButton, cancelButton, i;
+
+    okButton = isc.OBFormButton.create({
+      title: OB.I18N.getLabel('OBUISC_Dialog.OK_BUTTON_TITLE'),
+      click: function () {
+        treeWindow.accept();
+      }
+    });
+    cancelButton = isc.OBFormButton.create({
+      title: OB.I18N.getLabel('OBUISC_Dialog.CANCEL_BUTTON_TITLE'),
+      click: function () {
+        treeWindow.closeClick();
+      }
+    });
+
+    OB.Utilities.applyDefaultValues(this.treeGridFields, this.defaultTreeGridField);
+
+    for (i = 0; i < this.treeGridFields.length; i++) {
+      this.treeGridFields[i].canSort = (this.treeGridFields[i].canSort === false ? false : true);
+      if (this.treeGridFields[i].disableFilter) {
+        this.treeGridFields[i].canFilter = false;
+      } else {
+        this.treeGridFields[i].canFilter = true;
+      }
+    }
+    this.treeGrid = isc.OBTreeGrid.create({
+      view: this.view,
+      treePopup: this,
+      autoFetchData: true,
+      filterOnKeypress: true,
+      selectionAppearance: 'checkbox',
+      dataSourceId: this.dataSourceId,
+      treeReferenceId: this.treeReferenceId,
+      width: '100%',
+      height: '100%',
+      bodyStyleName: 'OBGridBody',
+      showFilterEditor: true,
+      alternateRecordStyles: true,
+      sortField: this.displayField,
+
+      init: function () {
+        OB.Datasource.get(this.dataSourceId, this, null, true);
+        this.copyFunctionsFromViewGrid();
+        this.Super('init', arguments);
+        this.filterNoRecordsEmptyMessage = '<span class="' + this.emptyMessageStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridFilterNoResults') + '</span>' + '<span onclick="window[\'' + this.ID + '\'].clearFilter();" class="' + this.emptyMessageLinkStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridClearFilter') + '</span>';
+      },
+
+      copyFunctionsFromViewGrid: function () {
+        this.filterEditorProperties = this.view.viewGrid.filterEditorProperties;
+        this.checkShowFilterFunnelIcon = this.view.viewGrid.checkShowFilterFunnelIcon;
+        this.isGridFiltered = this.view.viewGrid.isGridFiltered;
+        this.isGridFilteredWithCriteria = this.view.viewGrid.isGridFilteredWithCriteria;
+        this.isValidFilterField = this.view.viewGrid.isValidFilterField;
+        this.convertCriteria = this.view.viewGrid.convertCriteria;
+        this.resetEmptyMessage = this.view.viewGrid.resetEmptyMessage;
+        this.filterData = this.view.viewGrid.filterData;
+        this.loadingDataMessage = this.view.viewGrid.loadingDataMessage;
+        this.emptyMessage = this.view.viewGrid.emptyMessage;
+        this.noDataEmptyMessage = this.view.viewGrid.noDataEmptyMessage;
+      },
+
+      onFetchData: function (criteria, requestProperties) {
+        requestProperties = requestProperties || {};
+        requestProperties.params = this.getFetchRequestParams(requestProperties.params);
+      },
+
+      getFetchRequestParams: function (params) {
+        params = params || {};
+        if (this.getSelectedRecord()) {
+          params._targetRecordId = this.targetRecordId;
+        }
+        return params;
+      },
+
+      dataArrived: function () {
+        var record, rowNum, i, selectedRecords = [],
+            ds, ids;
+        this.Super('dataArrived', arguments);
+      },
+
+      fields: this.treeGridFields,
+
+      handleFilterEditorSubmit: function (criteria, context) {
+        this.Super('handleFilterEditorSubmit', [criteria, context]);
+      },
+
+      setDataSource: function (ds, fields) {
+        var me = this,
+            i;
+        ds.transformRequest = function (dsRequest) {
+          var target = window[dsRequest.componentId];
+          dsRequest.params = dsRequest.params || {};
+          dsRequest.params._startRow = 0;
+          dsRequest.params._endRow = OB.Properties.TreeDatasourceFetchLimit;
+          dsRequest.params.treeReferenceId = target.treeReferenceId;
+          return this.Super('transformRequest', arguments);
+        };
+
+        ds.transformResponse = function (dsResponse, dsRequest, jsonData) {
+          if (jsonData.response.error) {
+            dsResponse.error = jsonData.response.error;
+          }
+          return this.Super('transformResponse', arguments);
+        };
+
+        ds.handleError = function (response, request) {
+          if (response && response.error && response.error.type === 'tooManyNodes') {
+            isc.warn(OB.I18N.getLabel('OBUIAPP_TooManyNodes'));
+          }
+        };
+
+        fields = this.treePopup.treeGridFields;
+        for (i = 0; i < fields.length; i++) {
+          fields[i].escapeHTML = true;
+        }
+        ds.primaryKeys = {
+          id: 'id'
+        };
+        return this.Super('setDataSource', [ds, fields]);
+      },
+
+      // show or hide the filter button
+      filterEditorSubmit: function (criteria) {
+        this.checkShowFilterFunnelIcon(criteria);
+      }
+    });
+
+
+    this.items = [isc.VLayout.create({
+      height: this.height,
+      width: this.width,
+      members: [this.treeGrid, isc.LayoutSpacer.create({
+        height: 10
+      }), isc.HLayout.create({
+        styleName: this.buttonBarStyleName,
+        height: 30,
+        defaultLayoutAlign: 'center',
+        members: [isc.LayoutSpacer.create({}), okButton, isc.LayoutSpacer.create({
+          width: 20
+        }), cancelButton, isc.LayoutSpacer.create({})]
+      })]
+    })];
+    this.Super('initWidget', arguments);
+  },
+
+  destroy: function () {
+    var i;
+    for (i = 0; i < this.items.length; i++) {
+      this.items[i].destroy();
+    }
+    return this.Super('destroy', arguments);
+  },
+
+
+  show: function (refreshGrid) {
+    if (refreshGrid) {
+      this.treeGrid.invalidateCache();
+    }
+    var ret = this.Super('show', arguments);
+    if (this.treeGrid.isDrawn()) {
+      this.treeGrid.focusInFilterEditor();
+    } else {
+      isc.Page.setEvent(isc.EH.IDLE, this.treeGrid, isc.Page.FIRE_ONCE, 'focusInFilterEditor');
+    }
+
+    this.treeGrid.checkShowFilterFunnelIcon(this.treeGrid.getCriteria());
+
+    return ret;
+  },
+
+  resized: function () {
+    this.items[0].setWidth(this.width - 4);
+    this.items[0].setHeight(this.height - 40);
+    this.items[0].redraw();
+    return this.Super('resized', arguments);
+  },
+
+  accept: function () {
+    if (this.changeCriteriacallback) {
+      this.fireCallback(this.changeCriteriacallback, 'value', [this.getCriteria()]);
+    }
+    this.hide();
+  },
+
+  clearValues: function () {
+    this.treeGrid.deselectAllRecords();
+  },
+
+  getCriteria: function () {
+    var selection = this.treeGrid.getSelection(),
+        criteria = {},
+        i, len = selection.length,
+        fieldName = this.fieldName + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER;
+    if (len === 0) {
+      return {};
+    } else if (len === 1) {
+      criteria._constructor = 'AdvancedCriteria';
+      criteria.operator = 'and';
+      criteria.criteria = [{
+        fieldName: fieldName,
+        operator: 'equals',
+        value: selection[0][OB.Constants.IDENTIFIER]
+      }];
+    } else {
+      criteria._constructor = 'AdvancedCriteria';
+      criteria._OrExpression = true;
+      criteria.operator = 'or';
+      criteria.fieldName = fieldName;
+      criteria.criteria = [];
+      for (i = 0; i < len; i++) {
+        criteria.criteria.push({
+          fieldName: fieldName,
+          operator: 'equals',
+          value: selection[i][OB.Constants.IDENTIFIER]
+        });
+      }
+    }
+    return criteria;
+  }
+
+});
+
+isc.ClassFactory.defineClass('OBTreeFilterItem', isc.OBTextItem);
+
+isc.OBTreeFilterItem.addProperties({
+  showPickerIcon: true,
+  filterDialogConstructor: isc.OBTreeItemPopupFilterWindow,
+  lastValueFromPopup: null,
+  pickerConstructor: 'ImgButton',
+  pickerIconDefaults: {
+    name: 'showDateRange',
+    width: 21,
+    height: 21,
+    showOver: false,
+    showFocused: false,
+    showFocusedWithItem: false,
+    hspace: 0,
+    click: function (form, item, icon) {
+      if (!item.disabled) {
+        item.showDialog();
+      }
+    }
+  },
+
+  pickerIconSrc: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/form/search_picker.png',
+  filterDialogCallback: function (criteria) {
+    this.grid.parentElement.setFilterEditorCriteria(criteria);
+    this.lastValueFromPopup = this.getValue();
+    this.form.grid.performAction();
+  },
+
+  init: function () {
+    var field;
+    this.Super('init', arguments);
+    field = this.grid.getField(this.name);
+    this.criteriaField = field.displayField;
+    this.addAutoChild('filterDialog', {
+      title: this.title,
+      filterItem: this,
+      treeGridFields: field.editorProperties.treeGridFields,
+      treeReferenceId: field.editorProperties.treeReferenceId,
+      dataSourceId: field.editorProperties.dataSourceId,
+      fieldName: field.name,
+      view: this.grid.parentElement.view,
+      changeCriteriacallback: this.getID() + '.filterDialogCallback(value)'
+    }, 'isc.OBTreeItemPopupFilterWindow');
+  },
+
+  destroy: function () {
+    if (this.filterDialog) {
+      this.filterDialog.destroy();
+    }
+    return this.Super('destroy', arguments);
+  },
+
+
+  showDialog: function () {
+    var hasChanged = false;
+    if (this.lastValueFromPopup !== this.getValue()) {
+      hasChanged = true;
+    }
+    this.filterDialog.show(hasChanged);
+  }
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-tree.js	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,670 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+
+// = Tree Item =
+// Contains the OBTreeItem. This widget consists of three main parts:
+// 1) a text item with a picker icon
+// 2) a tree grid that will show data filtered by the text entered in the text item
+// 3) a popup window showing a search grid and a tree grid with data
+//
+isc.ClassFactory.defineClass('OBTreeItem', isc.OBTextItem);
+
+isc.ClassFactory.mixInInterface('OBTreeItem', 'OBLinkTitleItem');
+
+isc.OBTreeItem.addProperties({
+  showPickerIcon: true,
+  pickerIconSrc: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/form/comboBoxPicker.png',
+  pickerIconHSpace: 0,
+  iconHSpace: 0,
+  tree: null,
+  init: function () {
+    this.Super('init', arguments);
+    this.tree = isc.OBTreeItemTree.create({
+      treeItem: this
+    });
+    this.treeDisplayField = this.getTreeDisplayField();
+    this.treeWindow = isc.OBTreeItemPopupWindow.create({
+      // solves issue: https://issues.openbravo.com/view.php?id=17268
+      title: (this.form && this.form.grid ? this.form.grid.getField(this.name).title : this.title),
+      dataSource: this.optionDataSource,
+      treeItem: this,
+      valueField: this.valueField,
+      displayField: this.displayField,
+      treeGridFields: isc.shallowClone(this.treeGridFields)
+    });
+    this.enableShortcuts();
+  },
+
+  destroy: function () {
+    if (this.tree) {
+      this.tree.destroy();
+    }
+    if (this.treeWindow) {
+      this.treeWindow.destroy();
+    }
+    return this.Super('destroy', arguments);
+  },
+
+  enableShortcuts: function () {
+    var ksAction_ShowPopup, ksAction_ShowTree, ksAction_MoveToTree;
+    ksAction_ShowPopup = function (caller) {
+      caller.openTreeWindow();
+      return false; //To avoid keyboard shortcut propagation
+    };
+    OB.KeyboardManager.Shortcuts.set('TreeItem_ShowPopup', 'OBTreeItem', ksAction_ShowPopup);
+
+    ksAction_ShowTree = function (caller) {
+      caller.tree.show();
+      return false; //To avoid keyboard shortcut propagation
+    };
+    OB.KeyboardManager.Shortcuts.set('TreeItem_ShowTree', 'OBTreeItem', ksAction_ShowTree);
+
+    ksAction_MoveToTree = function (caller) {
+      if (caller.tree.isVisible()) {
+        caller.tree.focus();
+      }
+      return false; //To avoid keyboard shortcut propagation
+    };
+    OB.KeyboardManager.Shortcuts.set('TreeItem_MoveToTree', 'OBTreeItem', ksAction_MoveToTree);
+  },
+
+  getTreeDisplayField: function () {
+    if (!this.displayField.contains(OB.Constants.FIELDSEPARATOR)) {
+      return this.displayField;
+    } else {
+      return this.displayField.substr(this.displayField.lastIndexOf(OB.Constants.FIELDSEPARATOR) + 1);
+    }
+  },
+
+  keyPress: function (keyName, character, form, item, icon) {
+    var response = OB.KeyboardManager.Shortcuts.monitor('OBTreeItem', this);
+    if (response !== false) {
+      response = this.Super('keyPress', arguments);
+    }
+    return response;
+  },
+
+  icons: [{
+    src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/form/search_picker.png',
+    width: 21,
+    height: 21,
+    click: function (form, item, icon) {
+      item.openTreeWindow();
+    }
+  }],
+
+  openTreeWindow: function () {
+    var selectedValue = this.getValue(),
+        criteria, innerCriteria;
+    if (this.treeWindow.treeGrid) {
+      //If there is a record selected in the item, use it to filter the tree
+      if (OB.Utilities.isUUID(selectedValue)) {
+        this.targetRecordId = selectedValue;
+        this.targetRecordIdentifier = this.getDisplayValue();
+      }
+    }
+    this.treeWindow.show(true);
+  },
+
+  showPicker: function () {
+    this.toggleTreePicker();
+  },
+
+  toggleTreePicker: function () {
+    if (this.tree.isVisible()) {
+      this.tree.hide();
+    } else {
+      this.tree.show();
+    }
+  },
+
+  moved: function () {
+    this.tree.updatePosition();
+    return this.Super('moved', arguments);
+  },
+
+  changed: function (form, item, value) {
+    if (!this.tree.isVisible() && !this.valueChangedFromPopup && !this.valueChangedFromDropDownTree) {
+      this.tree.show();
+    }
+    this.fireOnPause('refreshTree', this.refreshTree, 500, this);
+    return this.Super('changed', arguments);
+  },
+
+  refreshTree: function () {
+    this.tree.fetchData();
+  },
+
+
+  blur: function (form, item) {
+    // Do not execute FormItem.blur if the tree is visible, to avoid executing callouts without having selected a record
+    if (!this.tree.isVisible()) {
+      this.Super('blur', arguments);
+    }
+  },
+
+  setValueFromRecord: function (record) {
+    var currentValue = this.getValue(),
+        identifierFieldName = this.name + OB.Constants.FIELDSEPARATOR + OB.Constants.IDENTIFIER,
+        i;
+    if (!record) {
+      this.storeValue(null);
+      this.form.setValue(this.name + OB.Constants.FIELDSEPARATOR + this.displayField, null);
+      this.form.setValue(identifierFieldName, null);
+    } else {
+      this.storeValue(record[this.valueField]);
+      this.form.setValue(this.name + OB.Constants.FIELDSEPARATOR + this.displayField, record[this.displayField]);
+      this.form.setValue(identifierFieldName, record[OB.Constants.IDENTIFIER]);
+      if (!this.valueMap) {
+        this.valueMap = {};
+      }
+      this.valueMap[record[this.valueField]] = record[this.treeDisplayField].replace(/[\n\r]/g, '');
+      this.updateValueMap();
+    }
+    this.form.handleItemChange(this);
+    // only jump to the next field if the value has really been set
+    // do not jump to the next field if the event has been triggered by the Tab key,
+    // to prevent a field from being skipped (see https://issues.openbravo.com/view.php?id=21419)
+    if (currentValue && this.form.focusInNextItem && isc.EH.getKeyName() !== 'Tab') {
+      this.form.focusInNextItem(this.name);
+    }
+    delete this._notUpdatingManually;
+  },
+
+  mapValueToDisplay: function (value) {
+    var ret = this.Super('mapValueToDisplay', arguments);
+    if (ret === value && this.isDisabled()) {
+      return '';
+    }
+    // if value is null then don't set it in the valueMap, this results 
+    // in null being displayed in the combobox
+    if (ret === value && value) {
+      if (!this.valueMap) {
+        this.valueMap = {};
+        this.valueMap[value] = '';
+        return '';
+      } else if (!this.valueMap[value] && OB.Utilities.isUUID(value)) {
+        return '';
+      }
+    }
+    if (value && value !== '' && ret === '' && !OB.Utilities.isUUID(value)) {
+      this.savedEnteredValue = value;
+    }
+    return ret;
+  }
+
+});
+
+// Tree that is displayed under the tree form item
+isc.ClassFactory.defineClass('OBTreeItemTree', isc.OBTreeGrid);
+
+isc.OBTreeItemTree.addProperties({
+  treeItem: null,
+  height: 200,
+  autoFetchData: false,
+  visibility: 'hidden',
+  canResizeFields: false,
+  init: function () {
+    OB.Datasource.get(this.treeItem.dataSourceId, this, null, true);
+    this.Super('init', arguments);
+  },
+
+  dataArrived: function () {
+    var selectedValue, record, rowNum, me = this;
+    this.Super('dataArrived', arguments);
+    selectedValue = this.treeItem.getValue();
+    record = this.data.find('id', selectedValue);
+    //If there is a record selected in the item, select it
+    if (record) {
+      rowNum = this.getRecordIndex(record);
+      this.selectSingleRecord(record);
+      // give grid time to draw
+      setTimeout(function () {
+        me.scrollRecordIntoView(rowNum, true);
+      }, 100);
+    }
+  },
+
+  show: function () {
+    this.updatePosition();
+    this.fetchData();
+    this._pageClickID = this.ns.Page.setEvent('mouseDown', this, null, 'clickOutsideTree');
+    return this.Super('show', arguments);
+  },
+
+  clickOutsideTree: function () {
+    var target, event, eventInfo;
+    if (!this.isVisible()) {
+      return;
+    }
+    target = isc.EH.lastEvent.target;
+    eventInfo = this.treeItem.form.getEventItemInfo();
+    // Do not hide if the picker of the formitem was clicked
+    // Do picker itself will hide the tree
+    if (eventInfo.icon === 'picker' && eventInfo.item.ID === this.treeItem.ID) {
+      return;
+    }
+    if (!this.contains(target, true)) {
+      this.hide();
+    }
+  },
+
+  updatePosition: function () {
+    var me = this,
+        interval, treeItemWidth;
+    if (this.treeItem) {
+      treeItemWidth = this.treeItem.getVisibleWidth();
+      if (treeItemWidth && treeItemWidth > this.getWidth()) {
+        this.setWidth(treeItemWidth);
+      }
+      this.placeNear(this.treeItem.getPageLeft(), this.treeItem.getPageTop() + 21);
+    }
+  },
+
+  setDataSource: function (ds, fields) {
+    var me = this,
+        i;
+    ds.transformRequest = function (dsRequest) {
+      var target = window[dsRequest.componentId];
+      dsRequest.params = dsRequest.params || {};
+      dsRequest.params._startRow = 0;
+      dsRequest.params._endRow = OB.Properties.TreeDatasourceFetchLimit;
+      dsRequest.params.treeReferenceId = target.treeItem.treeReferenceId;
+      return this.Super('transformRequest', arguments);
+    };
+
+    ds.transformResponse = function (dsResponse, dsRequest, jsonData) {
+      if (jsonData.response.error) {
+        dsResponse.error = jsonData.response.error;
+      }
+      return this.Super('transformResponse', arguments);
+    };
+
+    ds.handleError = function (response, request) {
+      if (response && response.error && response.error.type === 'tooManyNodes') {
+        me.treeItem.form.view.messageBar.setMessage('error', null, OB.I18N.getLabel('OBUIAPP_TooManyNodes'));
+      }
+    };
+
+    fields = this.treeItem.pickListFields;
+
+    for (i = 0; i < fields.length; i++) {
+      fields[i].escapeHTML = true;
+    }
+    ds.primaryKeys = {
+      id: 'id'
+    };
+    return this.Super('setDataSource', [ds, fields]);
+  },
+
+  //Select the record
+  rowDoubleClick: function (record, recordNum, fieldNum) {
+    var id = record[OB.Constants.ID],
+        identifier = record[OB.Constants.IDENTIFIER];
+    if (!this.treeItem.parentSelectionAllowed && this.data.hasChildren(record)) {
+      return;
+    }
+    this.treeItem.form.view.toolBar.updateButtonState(true);
+    this.hide();
+    this.treeItem.valueChangedFromDropDownTree = true;
+    this.treeItem.setValueFromRecord(record);
+    delete this.treeItem.valueChangedFromDropDownTree;
+  },
+
+  fetchData: function (criteria, callback, requestProperties) {
+    return this.Super('fetchData', [this.getCriteriaFromTreeItem(), callback, requestProperties]);
+  },
+
+  getCriteriaFromTreeItem: function () {
+    var value = this.treeItem.getValue(),
+        criteria = {};
+    if (!value) {
+      return null;
+    }
+    if (OB.Utilities.isUUID(value)) {
+      value = this.treeItem.valueMap[value] ? this.treeItem.valueMap[value] : value;
+    }
+    criteria.fieldName = this.getFields()[0].name;
+    criteria.operator = 'iContains';
+    criteria.value = value;
+    return {
+      criteria: criteria
+    };
+  }
+});
+
+//
+isc.ClassFactory.defineClass('OBTreeItemPopupWindow', isc.OBPopup);
+
+isc.OBTreeItemPopupWindow.addProperties({
+  canDragReposition: true,
+  canDragResize: true,
+  dismissOnEscape: true,
+  showMaximizeButton: true,
+  multiselect: false,
+
+  defaultTreeGridField: {
+    canFreeze: true,
+    canGroupBy: false
+  },
+
+  initWidget: function () {
+    var treeWindow = this,
+        okButton, cancelButton, i;
+    okButton = isc.OBFormButton.create({
+      title: OB.I18N.getLabel('OBUISC_Dialog.OK_BUTTON_TITLE'),
+      click: function () {
+        treeWindow.setValueInField();
+      }
+    });
+    cancelButton = isc.OBFormButton.create({
+      title: OB.I18N.getLabel('OBUISC_Dialog.CANCEL_BUTTON_TITLE'),
+      click: function () {
+        treeWindow.closeClick();
+      }
+    });
+
+    this.setFilterEditorProperties(this.treeGridFields);
+
+    OB.Utilities.applyDefaultValues(this.treeGridFields, this.defaultTreeGridField);
+
+    for (i = 0; i < this.treeGridFields.length; i++) {
+      this.treeGridFields[i].canSort = (this.treeGridFields[i].canSort === false ? false : true);
+      if (this.treeGridFields[i].disableFilter) {
+        this.treeGridFields[i].canFilter = false;
+      } else {
+        this.treeGridFields[i].canFilter = true;
+      }
+    }
+    if (!this.dataSource.fields || !this.dataSource.fields.length || this.dataSource.fields.length === 0) {
+      this.dataSource.fields = this.treeGridFields;
+      this.dataSource.init();
+    }
+    this.treeGrid = isc.OBTreeGrid.create({
+      treeItem: this.treeItem,
+      treeWindow: this,
+      view: this.treeItem.form.view,
+      selectionAppearance: this.selectionAppearance,
+      treePopup: this,
+      autoFetchData: false,
+      filterOnKeypress: true,
+      width: '100%',
+      height: '100%',
+      bodyStyleName: 'OBGridBody',
+      showFilterEditor: true,
+      alternateRecordStyles: true,
+      dataSource: this.dataSource,
+      sortField: this.displayField,
+      init: function () {
+        OB.Datasource.get(this.treeItem.dataSourceId, this, null, true);
+        this.copyFunctionsFromViewGrid();
+        this.Super('init', arguments);
+        this.filterNoRecordsEmptyMessage = '<span class="' + this.emptyMessageStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridFilterNoResults') + '</span>' + '<span onclick="window[\'' + this.ID + '\'].clearFilter();" class="' + this.emptyMessageLinkStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridClearFilter') + '</span>';
+        this.emptyMessage = this.filterNoRecordsEmptyMessage;
+      },
+
+      copyFunctionsFromViewGrid: function () {
+        var view = this.treeItem.form.view;
+        this.filterEditorProperties = view.viewGrid.filterEditorProperties;
+        this.checkShowFilterFunnelIconSuper = view.viewGrid.checkShowFilterFunnelIcon;
+        this.isGridFiltered = view.viewGrid.isGridFiltered;
+        this.isGridFilteredWithCriteria = view.viewGrid.isGridFilteredWithCriteria;
+        this.isValidFilterField = view.viewGrid.isValidFilterField;
+        this.resetEmptyMessage = view.viewGrid.resetEmptyMessage;
+        this.filterData = view.viewGrid.filterData;
+        this.loadingDataMessage = view.viewGrid.loadingDataMessage;
+        this.noDataEmptyMessage = view.viewGrid.noDataEmptyMessage;
+      },
+
+      convertCriteria: function (criteria) {
+        return criteria;
+      },
+
+      onFetchData: function (criteria, requestProperties) {
+        requestProperties = requestProperties || {};
+        requestProperties.params = this.getFetchRequestParams(requestProperties.params);
+      },
+
+      getFetchRequestParams: function (params) {
+        params = params || {};
+        if (this.getSelectedRecord()) {
+          params._targetRecordId = this.targetRecordId;
+        }
+        return params;
+      },
+
+      dataArrived: function () {
+        var record, rowNum, i, selectedRecords = [],
+            ds, ids, me = this;
+        this.Super('dataArrived', arguments);
+        if (this.treeItem.targetRecordId) {
+          record = this.data.find(OB.Constants.ID, this.treeItem.targetRecordId);
+          rowNum = this.getRecordIndex(record);
+          this.selectSingleRecord(record);
+          // give grid time to draw
+          setTimeout(function () {
+            me.scrollRecordIntoView(rowNum, true);
+          }, 100);
+          delete this.treeItem.targetRecordId;
+        }
+      },
+      fields: this.treeGridFields,
+      recordDoubleClick: function () {
+        this.treeWindow.setValueInField();
+      },
+
+      handleFilterEditorSubmit: function (criteria, context) {
+        var innerCriteria;
+        if (this.treeItem.targetRecordId) {
+          innerCriteria = {};
+          innerCriteria.fieldName = OB.Constants.ID;
+          innerCriteria.operator = 'equals';
+          innerCriteria.value = this.treeItem.targetRecordId;
+          criteria = {
+            _constructor: 'AdvancedCriteria',
+            criteria: [innerCriteria],
+            operator: 'and'
+          };
+        }
+        this.Super('handleFilterEditorSubmit', [criteria, context]);
+      },
+
+      setFilterValues: function (criteria) {
+        var innerCriteria;
+        if (criteria && criteria.criteria && criteria.criteria[0] && criteria.criteria[0].fieldName === OB.Constants.ID) {
+          // Target record id criteria. Show the identifier of the row in the filter values
+          innerCriteria = {};
+          innerCriteria.fieldName = this.treeItem.treeDisplayField;
+          innerCriteria.operator = 'iContains';
+          innerCriteria.value = this.treeItem.getDisplayValue();
+          criteria = {
+            _constructor: 'AdvancedCriteria',
+            criteria: [innerCriteria],
+            operator: 'and'
+          };
+        }
+        this.Super('setFilterValues', criteria);
+      },
+
+      setDataSource: function (ds, fields) {
+        var me = this;
+        ds.transformRequest = function (dsRequest) {
+          var target = window[dsRequest.componentId];
+          dsRequest.params = dsRequest.params || {};
+          dsRequest.params._startRow = 0;
+          dsRequest.params._endRow = OB.Properties.TreeDatasourceFetchLimit;
+          dsRequest.params.treeReferenceId = target.treeItem.treeReferenceId;
+          return this.Super('transformRequest', arguments);
+        };
+
+        ds.transformResponse = function (dsResponse, dsRequest, jsonData) {
+          if (jsonData.response.error) {
+            dsResponse.error = jsonData.response.error;
+          }
+          return this.Super('transformResponse', arguments);
+        };
+
+        ds.handleError = function (response, request) {
+          if (response && response.error && response.error.type === 'tooManyNodes') {
+            isc.warn(OB.I18N.getLabel('OBUIAPP_TooManyNodes'));
+          }
+        };
+
+        fields = this.treePopup.treeGridFields;
+        ds.primaryKeys = {
+          id: 'id'
+        };
+        return this.Super('setDataSource', [ds, fields]);
+      },
+
+      // show or hide the filter button
+      filterEditorSubmit: function (criteria) {
+        this.checkShowFilterFunnelIcon(criteria);
+      },
+
+      checkShowFilterFunnelIcon: function (criteria) {
+        var innerCriteria;
+        if (criteria && criteria.criteria && criteria.criteria[0] && criteria.criteria[0].fieldName === OB.Constants.ID) {
+          // Target record id criteria. Show the identifier of the row in the filter values
+          innerCriteria = {};
+          innerCriteria.fieldName = this.treeItem.treeDisplayField;
+          innerCriteria.operator = 'iContains';
+          innerCriteria.value = this.treeItem.getDisplayValue();
+          criteria = {
+            _constructor: 'AdvancedCriteria',
+            criteria: [innerCriteria],
+            operator: 'and'
+          };
+        }
+        this.checkShowFilterFunnelIconSuper(criteria);
+      }
+    });
+
+    this.items = [isc.VLayout.create({
+      height: this.height,
+      width: this.width,
+      members: [this.treeGrid, isc.LayoutSpacer.create({
+        height: 10
+      }), isc.HLayout.create({
+        styleName: this.buttonBarStyleName,
+        height: 30,
+        defaultLayoutAlign: 'center',
+        members: [isc.LayoutSpacer.create({}), okButton, isc.LayoutSpacer.create({
+          width: 20
+        }), cancelButton, isc.LayoutSpacer.create({})]
+      })]
+    })];
+    this.Super('initWidget', arguments);
+  },
+
+  setFilterEditorProperties: function (gridFields) {
+    var i, gridField;
+    for (i = 0; i < gridFields.length; i++) {
+      gridField = gridFields[i];
+      gridField.filterEditorProperties = gridField.filterEditorProperties || {};
+      gridFields[i].filterEditorProperties.treeWindow = this;
+    }
+  },
+
+  destroy: function () {
+    var i;
+    for (i = 0; i < this.items.length; i++) {
+      this.items[i].destroy();
+    }
+    return this.Super('destroy', arguments);
+  },
+
+  closeClick: function () {
+    this.hide(arguments);
+    this.treeItem.focusInItem();
+  },
+
+  hide: function () {
+    this.Super('hide', arguments);
+    //focus is now moved to the next item in the form automatically
+    if (!this.treeItem.form.getFocusItem()) {
+      this.treeItem.focusInItem();
+    }
+  },
+
+  show: function (applyDefaultFilter) {
+    // draw now already otherwise the filter does not work the
+    // first time    
+    var ret = this.Super('show', arguments);
+    if (applyDefaultFilter) {
+      this.treeGrid.setFilterEditorCriteria(this.defaultFilter);
+      this.treeGrid.filterByEditor();
+    }
+    if (this.treeGrid.isDrawn()) {
+      this.treeGrid.focusInFilterEditor();
+    } else {
+      isc.Page.setEvent(isc.EH.IDLE, this.treeGrid, isc.Page.FIRE_ONCE, 'focusInFilterEditor');
+    }
+
+    if (this.treeItem.getValue()) {
+      this.treeGrid.selectSingleRecord(this.treeGrid.data.find(this.valueField, this.treeItem.getValue()));
+    } else {
+      this.treeGrid.selectSingleRecord(null);
+    }
+
+    this.treeGrid.checkShowFilterFunnelIcon(this.treeGrid.getCriteria());
+
+    return ret;
+  },
+
+  resized: function () {
+    this.items[0].setWidth(this.width - 4);
+    this.items[0].setHeight(this.height - 40);
+    this.items[0].redraw();
+    return this.Super('resized', arguments);
+  },
+
+  setValueInField: function () {
+    var record = this.treeGrid.getSelectedRecord();
+    if (!this.treeItem.parentSelectionAllowed && this.treeGrid.data.hasChildren(record)) {
+      return;
+    }
+    this.treeItem.valueChangedFromPopup = true;
+    this.treeItem.setValueFromRecord(record);
+    delete this.treeItem.valueChangedFromPopup;
+    this.hide();
+  }
+});
+
+isc.ClassFactory.defineClass('OBTreeFilterSelectItem', isc.OBFKFilterTextItem);
+
+isc.OBTreeFilterSelectItem.addProperties({
+
+  filterDataBoundPickList: function (requestProperties, dropCache) {
+    requestProperties = requestProperties || {};
+    requestProperties.params = requestProperties.params || {};
+    // on purpose not passing the third boolean param
+    var contextInfo = this.treeWindow.treeItem.form.view.getContextInfo(false, true);
+
+    // also add the special ORG parameter
+    if (this.treeWindow.treeItem.form.getField('organization')) {
+      requestProperties.params[OB.Constants.ORG_PARAMETER] = this.treeWindow.treeItem.form.getValue('organization');
+    } else if (contextInfo.inpadOrgId) {
+      requestProperties.params[OB.Constants.ORG_PARAMETER] = contextInfo.inpadOrgId;
+    }
+    requestProperties.params._tableId = this.treeWindow.treeItem.referencedTableId;
+    return this.Super('filterDataBoundPickList', [requestProperties, true]);
+  }
+});
\ No newline at end of file
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Wed Mar 05 23:13:24 2014 +0100
@@ -1441,6 +1441,10 @@
   },
 
   doClose: function () {
+    if (this.view.isShowingTree) {
+      this.view.treeGrid.refreshRecord(this.getValues());
+    }
+
     this.view.switchFormGridVisibility();
     this.view.messageBar.hide();
     if (this.isNew) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-tree-grid.js	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,135 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+// Base OBTreeGrid class
+// This class is extended by the tree used in the Tree Windows and in the Tree References
+isc.ClassFactory.defineClass('OBTreeGrid', isc.TreeGrid);
+
+isc.OBTreeGrid.addProperties({
+  showOpenIcons: true,
+  showDropIcons: false,
+  openerImage: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/treegrid/iconTree.png',
+  openerIconSize: 16,
+  showCustomIconOpen: true,
+  extraIconGap: 5,
+  openerIconWidth: 24,
+  nodeIcon: null,
+  folderIcon: null,
+  showSortArrow: 'both',
+  showRecordComponentsByCell: true,
+  showRecordComponents: true,
+  autoFetchTextMatchStyle: 'substring',
+  dataProperties: {
+    modelType: 'parent',
+    rootValue: '-1',
+    idField: 'nodeId',
+    parentIdField: 'parentId',
+    openProperty: 'isOpen'
+  },
+
+
+  initWidget: function () {
+    this.sorterDefaults = {};
+    this.Super('initWidget', arguments);
+  },
+
+  /**
+   * When the grid is filtered, show the records that did not comply with the filter (but were ancestors of nodes that did) in grey
+   */
+  getCellCSSText: function (record, rowNum, colNum) {
+    if (record.notFilterHit) {
+      return 'color:#606060;';
+    } else {
+      return '';
+    }
+  },
+
+  clearFilter: function (keepFilterClause, noPerformAction) {
+    var i = 0,
+        fld, length;
+    this.view.messageBar.hide();
+    if (!keepFilterClause) {
+      delete this.filterClause;
+      delete this.sqlFilterClause;
+    }
+    this.forceRefresh = true;
+    if (this.filterEditor) {
+      if (this.filterEditor.getEditForm()) {
+        this.filterEditor.getEditForm().clearValues();
+        // clear the date values in a different way
+        length = this.filterEditor.getEditForm().getFields().length;
+
+        for (i = 0; i < length; i++) {
+          fld = this.filterEditor.getEditForm().getFields()[i];
+          if (fld.clearFilterValues) {
+            fld.clearFilterValues();
+          }
+        }
+      } else {
+        this.filterEditor.setValuesAsCriteria(null);
+      }
+    }
+    if (!noPerformAction) {
+      this.filterEditor.performAction();
+    }
+  },
+
+  createRecordComponent: function (record, colNum) {
+    var field = this.getField(colNum),
+        rowNum = this.getRecordIndex(record),
+        isSummary = record && (record[this.groupSummaryRecordProperty] || record[this.gridSummaryRecordProperty]),
+        isEditRecord = rowNum === this.getEditRow(),
+        canvas, clientClassArray, clientClass, clientClassProps, clientClassIsShownInGridEdit;
+
+    if (isSummary) {
+      return null;
+    }
+
+    if (field.clientClass) {
+      clientClassArray = OB.Utilities.clientClassSplitProps(field.clientClass);
+      clientClass = clientClassArray[0];
+      clientClassProps = clientClassArray[1];
+
+      clientClassIsShownInGridEdit = new Function('return ' + clientClass + '.getInstanceProperty("isShownInGridEdit")')();
+
+      if (!isEditRecord || clientClassIsShownInGridEdit) {
+        canvas = isc.ClassFactory.newInstance(clientClass, {
+          grid: this,
+          align: this.getCellAlign(record, rowNum, colNum),
+          field: field,
+          record: record,
+          rowNum: rowNum,
+          colNum: colNum
+        }, clientClassProps);
+        if (canvas) {
+          if (canvas.setRecord) {
+            canvas.setRecord(record);
+          }
+          return canvas;
+        }
+      }
+    }
+    return null;
+  },
+
+  handleFilterEditorSubmit: function (criteria, context, callback) {
+    this.setOpenState('[]');
+    this.Super('handleFilterEditorSubmit', arguments);
+  }
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-tree-view-grid.js	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,440 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+isc.ClassFactory.defineClass('OBTreeViewGrid', isc.OBTreeGrid);
+
+isc.OBTreeViewGrid.addProperties({
+  referencedTableId: null,
+  parentTabRecordId: null,
+  view: null,
+  orderedTree: false,
+
+  arrowKeyAction: 'select',
+  canPickFields: false,
+  canDropOnLeaves: true,
+  canHover: false,
+  // It will be set to false if the tree is ordered
+  canReorderRecords: true,
+  canAcceptDroppedRecords: true,
+  dropIconSuffix: 'into',
+  autoFetchData: false,
+  closedIconSuffix: '',
+  showFilterEditor: true,
+  selectionAppearance: 'checkbox',
+  showSelectedStyle: true,
+
+  autoFitFieldWidths: true,
+  autoFitWidthApproach: 'title',
+  canAutoFitFields: false,
+  minFieldWidth: 75,
+  width: '100%',
+  height: '100%',
+
+  // the grid will be refreshed when:
+  // - The tree category is LinkToParent and
+  // - There has been at least a reparent
+  needsViewGridRefresh: false,
+  init: function () {
+    this.copyFunctionsFromViewGrid();
+    this.Super('init', arguments);
+    if (this.orderedTree) {
+      this.canSort = false;
+    } else {
+      this.canSort = true;
+    }
+    this.confirmNodeReparent = OB.PropertyStore.get('OBUIAPP_ConfirmNodeReparent', this.view.windowId);
+    this.filterNoRecordsEmptyMessage = '<span class="' + this.emptyMessageStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridFilterNoResults') + '</span>' + '<span onclick="window[\'' + this.ID + '\'].clearFilter();" class="' + this.emptyMessageLinkStyle + '">' + OB.I18N.getLabel('OBUIAPP_GridClearFilter') + '</span>';
+  },
+
+  // Some OBTreeViewGrid functionality is alreadyd implemented in OBViewGrid
+  // Instead of rewriting it, copy it
+  // Do not do this for functions that makes call to super() if it needs to use code from OBGrid. It would not use OBGrid as prototype, but ListGrid
+  copyFunctionsFromViewGrid: function () {
+    this.filterEditorProperties = this.view.viewGrid.filterEditorProperties;
+    this.checkShowFilterFunnelIcon = this.view.viewGrid.checkShowFilterFunnelIcon;
+    this.isGridFiltered = this.view.viewGrid.isGridFiltered;
+    this.isGridFilteredWithCriteria = this.view.viewGrid.isGridFilteredWithCriteria;
+    this.isValidFilterField = this.view.viewGrid.isValidFilterField;
+    this.convertCriteria = this.view.viewGrid.convertCriteria;
+    this.resetEmptyMessage = this.view.viewGrid.resetEmptyMessage;
+    this.filterData = this.view.viewGrid.filterData;
+    this.loadingDataMessage = this.view.viewGrid.loadingDataMessage;
+    this.emptyMessage = this.view.viewGrid.emptyMessage;
+    this.noDataEmptyMessage = this.view.viewGrid.noDataEmptyMessage;
+    this.clearFilter = this.view.viewGrid.clearFilter;
+  },
+
+  // Sets the fields of the datasource and extends the transformRequest and transformResponse functions
+  setDataSource: function (ds, fields) {
+    var me = this;
+    ds.transformRequest = function (dsRequest) {
+      dsRequest.params = dsRequest.params || {};
+      dsRequest.params._startRow = 0;
+      dsRequest.params._endRow = OB.Properties.TreeDatasourceFetchLimit;
+      dsRequest.params.referencedTableId = me.referencedTableId;
+      me.parentTabRecordId = me.getParentTabRecordId();
+      dsRequest.params.parentRecordId = me.parentTabRecordId;
+      dsRequest.params.tabId = me.view.tabId;
+      if (dsRequest.dropIndex || dsRequest.dropIndex === 0) {
+        //Only send the index if the tree is ordered
+        dsRequest = me.addOrderedTreeParameters(dsRequest);
+      }
+      dsRequest.params._selectedProperties = me.getSelectedPropertiesString();
+      // Includes the context, it could be used in the hqlwhereclause
+      isc.addProperties(dsRequest.params, me.view.getContextInfo(true, false));
+      dsRequest.willHandleError = true;
+      return this.Super('transformRequest', arguments);
+    };
+
+    ds.transformResponse = function (dsResponse, dsRequest, jsonData) {
+      if (jsonData.response.message) {
+        me.view.messageBar.setMessage(jsonData.response.message.messageType, null, jsonData.response.message.message);
+      } else if (dsRequest.operationType === 'update') {
+        me.view.messageBar.hide();
+      }
+      if (jsonData.response.error) {
+        dsResponse.error = jsonData.response.error;
+      }
+      return this.Super('transformResponse', arguments);
+    };
+
+    ds.handleError = function (response, request) {
+      if (response && response.error && response.error.type === 'tooManyNodes') {
+        me.view.messageBar.setMessage('error', null, OB.I18N.getLabel('OBUIAPP_TooManyNodes'));
+      }
+    };
+
+    ds.updateData = function (updatedRecord, callback, requestProperties) {
+      // the new callback checks if the node movement has to be reverted
+      var newCallback = function (dsResponse, data, dsRequest) {
+          var i, node, parentNode;
+          for (i = 0; i < data.length; i++) {
+            node = data[i];
+            if (node.revertMovement) {
+              parentNode = dsRequest.dragTree.find('id', node.parentId);
+              if (parentNode) {
+                // move the node back to its previous index
+                dsRequest.dragTree.move(node, parentNode, node.prevIndex);
+              }
+            }
+          }
+          };
+      this.Super('updateData', [updatedRecord, newCallback, requestProperties]);
+    };
+    fields = this.getTreeGridFields(me.fields);
+    ds.primaryKeys = {
+      id: 'id'
+    };
+    return this.Super('setDataSource', [ds, fields]);
+  },
+
+  // Used to copy the fields from the OBViewGrid to the OBTreeViewGrid.
+  // It does not copy the fields that start with underscore
+  getTreeGridFields: function (fields) {
+    var treeGridFields = isc.shallowClone(fields),
+        i, nDeleted = 0;
+    for (i = 0; i < treeGridFields.length; i++) {
+      if (treeGridFields[i - nDeleted].name[0] === '_') {
+        treeGridFields.splice(i - nDeleted, 1);
+        nDeleted = nDeleted + 1;
+      }
+    }
+    return treeGridFields;
+  },
+
+  // Adds to the request the parameters related with the node ordering
+  // * prevNodeId: Id of the node placed right before the moved node. Null if there are none
+  // * prevNodeId: Id of the node placed right after the moved node. Null if there are none
+  addOrderedTreeParameters: function (dsRequest) {
+    var childrenOfNewParent, prevNode, nextNode;
+    if (this.orderedTree) {
+      dsRequest.params.dropIndex = dsRequest.dropIndex;
+      childrenOfNewParent = this.getData().getChildren(dsRequest.newParentNode);
+      if (childrenOfNewParent.length !== 0) {
+        if (dsRequest.dropIndex === 0) {
+          nextNode = childrenOfNewParent[dsRequest.dropIndex];
+          dsRequest.params.nextNodeId = nextNode.id;
+        } else if (dsRequest.dropIndex === childrenOfNewParent.length) {
+          prevNode = childrenOfNewParent[dsRequest.dropIndex - 1];
+          dsRequest.params.prevNodeId = prevNode.id;
+        } else {
+          prevNode = childrenOfNewParent[dsRequest.dropIndex - 1];
+          dsRequest.params.prevNodeId = prevNode.id;
+          nextNode = childrenOfNewParent[dsRequest.dropIndex];
+          dsRequest.params.nextNodeId = nextNode.id;
+        }
+      }
+    }
+    return dsRequest;
+  },
+
+
+  // Returns the id of the parent tab, if any
+  getParentTabRecordId: function () {
+    if (!this.view.parentView) {
+      return null;
+    }
+    return this.view.parentView.viewGrid.getSelectedRecord().id;
+  },
+
+  // Returns a string that represents a jsonarray containing the names of all the TreeGrid fields 
+  getSelectedPropertiesString: function () {
+    var selectedProperties = '[',
+        first = true,
+        len = this.fields.length,
+        i;
+    for (i = 0; i < len; i++) {
+      if (first) {
+        first = false;
+        selectedProperties = selectedProperties + "'" + this.fields[i].name + "'";
+      } else {
+        selectedProperties = selectedProperties + ',' + "'" + this.fields[i].name + "'";
+      }
+    }
+    selectedProperties = selectedProperties + ']';
+    return selectedProperties;
+  },
+
+  transferNodes: function (nodes, folder, index, sourceWidget, callback) {
+    var me = this,
+        i, len = nodes.length,
+        nodesIdentifier = "",
+        parentIdentifier, message;
+    if (folder.canBeParentNode === false) {
+      return;
+    }
+    if (this.canReorderRecords) {
+      if (this.confirmNodeReparent && this.canReorderRecords) {
+        for (i = 0; i < len; i++) {
+          nodesIdentifier = nodesIdentifier + nodes[i][OB.Constants.IDENTIFIER];
+          if ((i + 1) < len) {
+            nodesIdentifier = nodesIdentifier + ", ";
+          }
+        }
+        if (folder.nodeId === this.dataProperties.rootValue) {
+          parentIdentifier = OB.I18N.getLabel('OBUIAPP_RootNode');
+        } else {
+          parentIdentifier = folder[OB.Constants.IDENTIFIER];
+        }
+
+        message = OB.I18N.getLabel('OBUIAPP_MoveTreeNode', [nodesIdentifier, parentIdentifier]);
+        isc.confirm(message, function (value) {
+          if (value) {
+            me.doTransferNodes(nodes, folder, index, sourceWidget, callback);
+          }
+        });
+      } else {
+        this.doTransferNodes(nodes, folder, index, sourceWidget, callback);
+      }
+    }
+  },
+
+  // smartclients transferNodes does not update the tree it a node is moved within its same parent
+  // do it here
+  doTransferNodes: function (nodes, folder, index, sourceWidget, callback) {
+    var node, dataSource, oldValues, dragTree, dropNeighbor, dataSourceProperties, i;
+    if (this.movedToSameParent(nodes, folder)) {
+      dragTree = sourceWidget.getData();
+      dataSource = this.getDataSource();
+      for (i = 0; i < nodes.length; i++) {
+        node = nodes[i];
+        // stores the node original index just in case the movement is not valid and the node has to be moved back to its original position
+        node.prevIndex = this.getData().getChildren(this.getData().getParent(node)).indexOf(node);
+        oldValues = isc.addProperties({}, node);
+        dataSourceProperties = {
+          oldValues: oldValues,
+          parentNode: this.data.getParent(node),
+          newParentNode: folder,
+          dragTree: dragTree,
+          draggedNode: node,
+          draggedNodeList: nodes,
+          dropIndex: index
+        };
+        if (index > 0) {
+          dataSourceProperties.dropNeighbor = this.data.getChildren(folder)[index - 1];
+        }
+        this.updateDataViaDataSource(node, dataSource, dataSourceProperties, sourceWidget);
+      }
+    } else {
+      if (this.treeStructure === 'LinkToParent') {
+        this.needsViewGridRefresh = true;
+      }
+    }
+
+    this.Super('transferNodes', arguments);
+  },
+
+  // Checks if any node has been moved to another position of its current parent node
+  movedToSameParent: function (nodes, newParent) {
+    var i, len = nodes.length;
+    for (i = 0; i < len; i++) {
+      if (nodes[i].parentId !== newParent.id) {
+        return false;
+      }
+    }
+    return true;
+  },
+
+  // Returns a node from its id (the id property of the record, not the nodeId property)
+  // If no node exists with that id, it return null
+  getNodeByID: function (nodeId) {
+    var i, node, nodeList = this.data.getNodeList();
+    for (i = 0; i < nodeList.length; i++) {
+      node = nodeList[i];
+      if (node.id === nodeId) {
+        return node;
+      }
+    }
+    return null;
+  },
+
+  setView: function (view) {
+    this.view = view;
+  },
+
+  // Opens the record in the edit form
+  // TODO: Check if the record is readonly?
+  recordDoubleClick: function (viewer, record, recordNum, field, fieldNum, value, rawValue) {
+    this.view.editRecordFromTreeGrid(record, false, (field ? field.name : null));
+  },
+
+  show: function () {
+    this.view.toolBar.updateButtonState();
+    this.Super('show', arguments);
+    this.checkShowFilterFunnelIcon(this.getCriteria());
+  },
+
+  // When hiding the tree grid to show the view grid, only refresh it if needed
+  hide: function () {
+    this.copyCriteriaToViewGrid();
+    if (this.needsViewGridRefresh) {
+      this.needsViewGridRefresh = false;
+      this.view.viewGrid.refreshGrid();
+    }
+    this.Super('hide', arguments);
+  },
+
+  // Takes the criteria from the view grid and applies it to the tree grid
+  copyCriteriaFromViewGrid: function () {
+    var viewGridCriteria = this.view.viewGrid.getCriteria();
+    this.setCriteria(viewGridCriteria);
+  },
+
+  // Takes the criteria from the tree grid and applies it to the view grid
+  copyCriteriaToViewGrid: function () {
+    var treeGridCriteria = this.getCriteria();
+    this.view.viewGrid.setCriteria(treeGridCriteria);
+  },
+
+  rowMouseDown: function (record, rowNum, colNum) {
+    this.Super('rowMouseDown', arguments);
+    if (!isc.EventHandler.ctrlKeyDown()) {
+      this.deselectAllRecords();
+    }
+    this.selectRecord(rowNum);
+  },
+
+  recordClick: function (viewer, record, recordNum, field, fieldNum, value, rawValue) {
+    if (isc.EH.getEventType() === 'mouseUp') {
+      // Don't do anything on the mouseUp event, the record is actually selected in the mouseDown event
+      return;
+    }
+    this.deselectAllRecords();
+    this.selectRecord(recordNum);
+  },
+
+  selectionUpdated: function (record, recordList) {
+    var me = this,
+        callback = function () {
+        me.delayedSelectionUpdated();
+        };
+    // wait 2 times longer than the fire on pause delay default
+    this.fireOnPause('delayedSelectionUpdated_' + this.ID, callback, this.fireOnPauseDelay * 2);
+  },
+
+  delayedSelectionUpdated: function (record, recordList) {
+    var selectedRecordId = this.getSelectedRecord() ? this.getSelectedRecord().id : null,
+        length, tabViewPane, i;
+    this.view.updateSubtabVisibility();
+    // refresh the tabs
+    if (this.view.childTabSet) {
+      length = this.view.childTabSet.tabs.length;
+      for (i = 0; i < length; i++) {
+        tabViewPane = this.view.childTabSet.tabs[i].pane;
+        tabViewPane.doRefreshContents(true);
+      }
+    }
+  },
+
+  getFetchRequestParams: function (params) {
+    params = this.view.viewGrid.getFetchRequestParams(params);
+    params._tabId = this.view.tabId;
+    return params;
+  },
+
+  // show or hide the filter button
+  filterEditorSubmit: function (criteria) {
+    this.checkShowFilterFunnelIcon(criteria);
+  },
+
+  // If any filter change, the view grid will have to te refreshed when the tree grid is hidden
+  editorChanged: function (item) {
+    this.needsViewGridRefresh = true;
+    this.Super('editorChanged', arguments);
+  },
+
+  getCriteria: function () {
+    var criteria = this.Super('getCriteria', arguments) || {};
+    if ((criteria === null || !criteria.criteria) && this.initialCriteria) {
+      criteria = isc.shallowClone(this.initialCriteria);
+    }
+    criteria = this.convertCriteria(criteria);
+    return criteria;
+  },
+
+  refreshGrid: function (callback) {
+    this.actionAfterDataArrived = callback;
+    this.fetchData(this.getCriteria());
+  },
+
+  dataArrived: function (startRow, endRow) {
+    this.resetEmptyMessage();
+    if (this.actionAfterDataArrived) {
+      this.actionAfterDataArrived();
+      this.actionAfterDataArrived = null;
+    }
+  },
+
+  // refreshes record after edition
+  refreshRecord: function (values) {
+    var record, p;
+    record = this.getNodeByID(values.id);
+    if (record) {
+      for (p in values) {
+        if (values.hasOwnProperty(p)) {
+          record[p] = values[p];
+        }
+      }
+      this.markForRedraw();
+    } else {
+      // record not found, can be new, force refresh
+      this.setData([]);
+      this.fetchData(this.getCriteria());
+    }
+  }
+});
\ No newline at end of file
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Wed Mar 05 23:13:24 2014 +0100
@@ -299,19 +299,6 @@
     }
   },
 
-  // To avoid JS error if OBViewGrid doesn't extend OBGrid (for debugging purposes)
-  isGridFiltered: function () {
-    return this.Super('isGridFiltered', arguments);
-  },
-  // To avoid JS error if OBViewGrid doesn't extend OBGrid (for debugging purposes)
-  checkShowFilterFunnelIcon: function () {
-    return this.Super('checkShowFilterFunnelIcon', arguments);
-  },
-  // To avoid JS error if OBViewGrid doesn't extend OBGrid (for debugging purposes)
-  focusInFirstFilterEditor: function () {
-    return this.Super('focusInFirstFilterEditor', arguments);
-  },
-
   initWidget: function () {
     var i, vwState;
 
@@ -1500,7 +1487,11 @@
     // do not refresh if the parent is not selected and we have no data
     // anyway
     if (this.view.parentProperty && (!this.data || !this.data.getLength || this.data.getLength() === 0)) {
-      selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      if (this.view.parentView.isShowingTree) {
+        selectedValues = this.view.parentView.treeGrid.getSelectedRecords();
+      } else {
+        selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      }
       if (selectedValues && !this.isOpenDirectMode && selectedValues.length === 0) {
         if (callback) {
           callback();
@@ -1837,7 +1828,8 @@
 
   convertCriteria: function (criteria) {
     var selectedValues, prop, fld, value, i, j, k, criterion, fldName, length, today = new Date(),
-        currentTimeZoneOffsetInMinutes = -today.getTimezoneOffset();
+        currentTimeZoneOffsetInMinutes = -today.getTimezoneOffset(),
+        applyParentTabCriteria = true;
 
     if (!criteria) {
       criteria = {};
@@ -1870,9 +1862,12 @@
 
     // note pass in criteria otherwise infinite looping!
     this.resetEmptyMessage(criteria);
-
     if (this.view.parentProperty && !this.isOpenDirectMode) {
-      selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      if (this.view.parentView.isShowingTree) {
+        selectedValues = this.view.parentView.treeGrid.getSelectedRecords();
+      } else {
+        selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      }
       var parentPropertyFilterValue = -1;
       if (selectedValues) {
         if (selectedValues.length === 0) {
@@ -1954,7 +1949,11 @@
       // result in an empty criteria which is ignored not generating the
       // request. Forcing load
       // See issue #22645
-      selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      if (this.view.parentView.isShowingTree) {
+        selectedValues = this.view.parentView.treeGrid.getSelectedRecords();
+      } else {
+        selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      }
       if (selectedValues.length !== 1) {
         // if there is not a single record selected, always false criterion
         criteria.criteria.push({
@@ -1968,6 +1967,15 @@
       }
     }
 
+    if (this.view.parentView && this.applyWhereClauseToChildren === false && criteria.criteria.length > 1) {
+      for (i = 0; i < criteria.criteria.length; i++) {
+        criterion = criteria.criteria[i];
+        if (criterion.fieldName === this.view.parentProperty) {
+          criteria.criteria.splice(i, 1);
+        }
+      }
+    }
+
     this.checkShowFilterFunnelIcon(criteria);
 
     return criteria;
@@ -2065,7 +2073,7 @@
   makeVisible: function () {
     if (this.view.isShowingForm) {
       this.view.switchFormGridVisibility();
-    } else {
+    } else if (!this.view.isShowingTree) {
       this.show();
     }
   },
@@ -2121,7 +2129,11 @@
     } else if (this.isGridFiltered(criteria)) {
       // there can be some initial filters, but still no parent selected
       if (this.view.parentView) {
-        selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+        if (this.view.parentView.isShowingTree) {
+          selectedValues = this.view.parentView.treeGrid.getSelectedRecords();
+        } else {
+          selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+        }
         parentIsNew = this.view.parentView.isShowingForm && this.view.parentView.viewForm.isNew;
         parentIsNew = parentIsNew || (selectedValues.length === 1 && selectedValues[0]._new);
         if (parentIsNew) {
@@ -2143,7 +2155,11 @@
     } else if (this.view.isRootView) {
       this.emptyMessage = this.noDataEmptyMessage;
     } else {
-      selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      if (this.view.parentView.isShowingTree) {
+        selectedValues = this.view.parentView.treeGrid.getSelectedRecords();
+      } else {
+        selectedValues = this.view.parentView.viewGrid.getSelectedRecords();
+      }
       parentIsNew = this.view.parentView.isShowingForm && this.view.parentView.viewForm.isNew;
       parentIsNew = parentIsNew || (selectedValues.length === 1 && selectedValues[0]._new);
       if (parentIsNew) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Wed Mar 05 23:13:24 2014 +0100
@@ -193,6 +193,8 @@
 
   propertyToColumns: [],
 
+  isShowingTree: false,
+
   initWidget: function (properties) {
     var length, rightMemberButtons = [],
         leftMemberButtons = [],
@@ -504,6 +506,14 @@
         this.formGridLayout.addMember(this.viewGrid);
       }
 
+      if (this.treeGrid) {
+        this.treeGrid.setWidth('100%');
+        this.treeGrid.setView(this);
+        OB.Datasource.get(this.treeGrid.dataSourceId, this.treeGrid, null, true);
+        this.treeGrid.hide();
+        this.formGridLayout.addMember(this.treeGrid);
+      }
+
       if (this.viewForm) {
         this.viewForm.setWidth('100%');
         this.formGridLayout.addMember(this.viewForm);
@@ -623,8 +633,10 @@
     url = url + '?tabId=' + this.tabId;
     if (this.isShowingForm && this.viewForm.isNew && this.isRootView) {
       url = url + '&command=NEW';
-    } else if ((this.isShowingForm || !this.isRootView) && this.viewGrid.getSelectedRecords() && this.viewGrid.getSelectedRecords().length === 1) {
+    } else if ((this.isShowingForm || !this.isRootView) && !this.isShowingTree && this.viewGrid.getSelectedRecords() && this.viewGrid.getSelectedRecords().length === 1) {
       url = url + '&recordId=' + this.viewGrid.getSelectedRecord().id;
+    } else if ((this.isShowingForm || !this.isRootView) && this.isShowingTree && this.treeGrid.getSelectedRecords() && this.treeGrid.getSelectedRecords().length === 1) {
+      url = url + '&recordId=' + this.treeGrid.getSelectedRecord().id;
     } else if (!this.isShowingForm && this.isRootView) {
       crit = this.viewGrid.getCriteria();
       if (crit && crit.criteria && crit.criteria.length > 0) {
@@ -712,6 +724,9 @@
     if (this.viewGrid && readOnly) {
       this.viewGrid.setReadOnlyMode();
     }
+    if (this.treeGrid && readOnly) {
+      this.treeGrid.canReorderRecords = false;
+    }
   },
 
   setEditOrDeleteOnly: function (editOrDeleteOnly) {
@@ -974,6 +989,9 @@
       callback = null;
     }
 
+    if (this.treeGrid && this.isShowingTree) {
+      this.treeGrid.fetchData(this.treeGrid.getCriteria());
+    }
     this.viewGrid.refreshContents(callback);
 
     this.toolBar.updateButtonState(true);
@@ -1085,6 +1103,14 @@
       if (!this.viewForm.getDataSource()) {
         this.prepareViewForm();
       }
+      if (this.treeGrid) {
+        if (this.isShowingTree) {
+          this.treeGrid.hide();
+          this.changePreviousNextRecordsButtonVisibility(false);
+        } else {
+          this.changePreviousNextRecordsButtonVisibility(true);
+        }
+      }
       this.viewGrid.hide();
       this.statusBarFormLayout.show();
       this.statusBarFormLayout.setHeight('100%');
@@ -1098,7 +1124,11 @@
       this.viewForm.resetForm();
       this.isShowingForm = false;
       this.viewGrid.markForRedraw('showing');
-      this.viewGrid.show();
+      if (this.isShowingTree) {
+        this.treeGrid.show();
+      } else {
+        this.viewGrid.show();
+      }
       if (this.isActiveView()) {
         if (this.viewGrid.getSelectedRecords() && this.viewGrid.getSelectedRecords().length === 1) {
           this.viewGrid.focus();
@@ -1112,6 +1142,16 @@
     this.updateTabTitle();
   },
 
+  changePreviousNextRecordsButtonVisibility: function (show) {
+    if (show) {
+      this.statusBar.previousButton.show();
+      this.statusBar.nextButton.show();
+    } else {
+      this.statusBar.previousButton.hide();
+      this.statusBar.nextButton.hide();
+    }
+  },
+
   doHandleClick: function () {
     if (!this.childTabSet) {
       return;
@@ -1180,6 +1220,21 @@
     }
   },
 
+  // ** {{{ editRecord }}} **
+  // Opens the edit form and selects the record in the grid, will refresh
+  // child views also
+  editRecordFromTreeGrid: function (record, preventFocus, focusFieldName) {
+    var rowNum,
+    // at this point the time fields of the record are formatted in local time
+    localTime = true;
+    this.messageBar.hide();
+
+    if (!this.isShowingForm) {
+      this.switchFormGridVisibility();
+    }
+    this.viewForm.editRecord(record, preventFocus, false, focusFieldName, localTime);
+  },
+
   setMaximizeRestoreButtonState: function () {
     // single view, no maximize or restore
     if (!this.hasChildTabs && this.isRootView) {
@@ -1637,7 +1692,12 @@
       }
     }
     if (!this.isShowingForm) {
-      this.viewGrid.refreshGrid(refreshCallback, newRecordsToBeIncluded);
+      if (this.isShowingTree) {
+        this.treeGrid.setData([]);
+        this.treeGrid.refreshGrid(refreshCallback);
+      } else {
+        this.viewGrid.refreshGrid(refreshCallback, newRecordsToBeIncluded);
+      }
     } else {
       if (this.viewForm.hasChanged) {
         callback = function (ok) {
@@ -2057,7 +2117,7 @@
   //++++++++++++++++++ Reading context ++++++++++++++++++++++++++++++
   getContextInfo: function (onlySessionProperties, classicMode, forceSettingContextVars, convertToClassicFormat) {
     var contextInfo = {},
-        addProperty, rowNum, properties, i, p;
+        addProperty, rowNum, properties, i, p, grid;
     // if classicmode is undefined then both classic and new props are used
     var classicModeUndefined = (typeof classicMode === 'undefined');
     var value, field, record, form, component, propertyObj, type, length;
@@ -2066,6 +2126,12 @@
       classicMode = true;
     }
 
+    if (this.isShowingTree) {
+      grid = this.treeGrid;
+    } else {
+      grid = this.viewGrid;
+    }
+
     // a special case, the editform has been build but it is not present yet in the
     // form, so isEditingGrid is true but the edit form is not there yet, in that 
     // case use the viewGrid as component and the selected record
@@ -2097,12 +2163,12 @@
       component = this.viewForm;
       form = component;
     } else {
-      record = this.viewGrid.getSelectedRecord();
-      rowNum = this.viewGrid.getRecordIndex(record);
+      record = grid.getSelectedRecord();
+      rowNum = grid.getRecordIndex(record);
       if (rowNum || rowNum === 0) {
-        record = isc.addProperties({}, record, this.viewGrid.getEditValues(rowNum));
+        record = isc.addProperties({}, record, grid.getEditValues(rowNum));
       }
-      component = this.viewGrid;
+      component = grid;
     }
 
     properties = this.propertyToColumns;
@@ -2110,9 +2176,9 @@
     if (record) {
 
       // add the id of the record itself also if not set
-      if (!record[OB.Constants.ID] && this.viewGrid.getSelectedRecord()) {
+      if (!record[OB.Constants.ID] && grid.getSelectedRecord()) {
         // if in edit mode then the grid always has the current record selected
-        record[OB.Constants.ID] = this.viewGrid.getSelectedRecord()[OB.Constants.ID];
+        record[OB.Constants.ID] = grid.getSelectedRecord()[OB.Constants.ID];
       }
 
       // New records in grid have a dummy id (see OBViewGrid.createNewRecordForEditing)
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-manage-views.js	Wed Mar 05 23:13:24 2014 +0100
@@ -158,6 +158,12 @@
       // if there is no record selected etc.
       if (view.isShowingForm) {
         view.switchFormGridVisibility();
+      } else if (view.isShowingTree) {
+        if (view.viewGrid && view.treeGrid) {
+          view.viewGrid.show();
+          view.treeGrid.hide();
+        }
+        view.isShowingTree = false;
       }
 
       if (viewTabDefinition.grid) {
@@ -192,6 +198,10 @@
     formData = OB.Personalization.getPersonalizationDataFromForm(view.viewForm);
     persDataByTab.form = formData.form;
 
+    if (view.isShowingTree) {
+      // Copy the criteria from the tree grid to the view grid
+      view.treeGrid.copyCriteriaToViewGrid();
+    }
     // ahd the grid state
     persDataByTab.grid = view.viewGrid.getViewState(false, true);
 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Wed Mar 05 23:13:24 2014 +0100
@@ -124,7 +124,7 @@
     updateState: function () {
       var view = this.view,
           selectedRecords = view.viewGrid.getSelectedRecords();
-      this.setDisabled(view.viewGrid.isGrouped || view.isShowingForm || view.readOnly || view.editOrDeleteOnly || view.singleRecord || !view.hasValidState() || (selectedRecords && selectedRecords.length > 1));
+      this.setDisabled(view.viewGrid.isGrouped || view.isShowingForm || view.readOnly || view.editOrDeleteOnly || view.singleRecord || !view.hasValidState() || (selectedRecords && selectedRecords.length > 1) || view.isShowingTree);
     },
     keyboardShortcutId: 'ToolBar_NewRow'
   },
@@ -504,6 +504,15 @@
       },
       keyboardShortcutId: 'ToolBar_Email'
     },
+    'treeGrid': {
+      updateState: function () {
+        if (this.view) {
+          this.setDisabled(this.view.isShowingForm || this.view.isEditingGrid);
+        } else {
+          this.setDisabled(true);
+        }
+      }
+    },
     'tree': {
       updateState: function () {
         var view = this.view,
@@ -1714,6 +1723,24 @@
   view.setContextInfo(view.getContextInfo(true, true, true, true), openPopupTree, true);
 };
 
+OB.ToolbarUtils.toggleTreeGridVisibility = function (view) {
+  var treeGrid = view.treeGrid,
+      viewGrid = view.viewGrid;
+  if (view.isShowingTree) {
+    viewGrid.show();
+    treeGrid.hide();
+    view.isShowingTree = false;
+  } else {
+    treeGrid.copyCriteriaFromViewGrid();
+    treeGrid.setData([]); // forcing refresh
+    treeGrid.fetchData(treeGrid.getCriteria());
+    treeGrid.checkShowFilterFunnelIcon(treeGrid.getCriteria());
+    treeGrid.show();
+    viewGrid.hide();
+    view.isShowingTree = true;
+  }
+};
+
 
 // ** {{{ OB.ToolbarUtils.createCloneButton(/*String*/ actionHandler, /*Object*/ requestParams, /*Array[String]*/ tabIds, /*String*/ askMsg, /*Integer*/ sortOrder, /*Boolean*/ editRecordAfterClone, /*String*/ buttonId, /*Boolean*/ overwriteIfExists, /*Array[String]*/ tabIdsToAvoid}}} **
 // Automatically set up a clone button for the provided tabs
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconFolder.png has changed
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconFolder_into.png has changed
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconFolder_open.png has changed
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconNode.png has changed
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconTree_closed.png has changed
Binary file modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconTree_opened.png has changed
--- a/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-form-styles.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-form-styles.js	Wed Mar 05 23:13:24 2014 +0100
@@ -342,6 +342,13 @@
   errorOrientation: 'left'
 });
 
+isc.OBTreeItemTree.addProperties({
+  baseStyle: 'OBFormFieldPickListCell',
+  bodyStyleName: 'OBPickListBody',
+  className: 'scrollingMenu',
+  cellHeight: 22
+});
+
 /* =====================================================================
  * Date range filter item and dialog
  =======================================================================*/
--- a/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-toolbar-styles.css	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-toolbar-styles.css	Wed Mar 05 23:13:24 2014 +0100
@@ -262,6 +262,12 @@
   background-image: url(./images/toolbar/iconButton-tree.png);
 }
 
+.OBToolbarIconButton_icon_treeGrid {
+  background-repeat: no-repeat;
+  background-position: center center;
+  background-image: url(./images/toolbar/iconButton-tree.png);
+}
+
 .OBToolbarIconButton_icon_clone {
   background-repeat: no-repeat;
   background-position: center center;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-tree-grid-styles.css	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,92 @@
+.OBTreeGridCell,
+.OBTreeGridCellOver,
+.OBTreeGridCellDark,
+.OBTreeGridCellOverDark,
+.OBTreeGridCellSelected,
+.OBTreeGridCellSelectedDark,
+.OBTreeGridCellSelectedOver,
+.OBTreeGridCellSelectedOverDark,
+.OBTreeGridCellDisabled,
+.OBTreeGridCellDisabledDark,
+
+.OBTreeGridCellSelectedViewInactive,
+.OBTreeGridCellSelectedViewInactiveDark,
+
+.OBTreeGridCellEdit,
+.OBTreeGridCellEditOver,
+.OBTreeGridCellEditDark,
+.OBTreeGridCellEditOverDark,
+.OBTreeGridCellEditSelected,
+.OBTreeGridCellEditSelectedDark,
+.OBTreeGridCellEditSelectedOver,
+.OBTreeGridCellEditSelectedOverDark,
+.OBTreeGridCellEditDisabled,
+.OBTreeGridCellEditDisabledDark,
+
+.OBTreeGridCellError,
+.OBTreeGridCellErrorOver,
+.OBTreeGridCellErrorDark,
+.OBTreeGridCellErrorOverDark,
+.OBTreeGridCellErrorSelected,
+.OBTreeGridCellErrorSelectedDark,
+.OBTreeGridCellErrorSelectedOver,
+.OBTreeGridCellErrorSelectedOverDark,
+.OBTreeGridCellErrorDisabled,
+.OBTreeGridCellErrorDisabledDark,
+
+.OBTreeGridCellErrorEdit,
+.OBTreeGridCellErrorEditOver,
+.OBTreeGridCellErrorEditDark,
+.OBTreeGridCellErrorEditOverDark,
+.OBTreeGridCellErrorEditSelected,
+.OBTreeGridCellErrorEditSelectedDark,
+.OBTreeGridCellErrorEditSelectedOver,
+.OBTreeGridCellErrorEditSelectedOverDark,
+.OBTreeGridCellErrorEditDisabled,
+.OBTreeGridCellErrorEditDisabledDark {
+  font-family: arial, sans-serif;
+  font-size: 12px;
+  vertical-align: middle;  
+  border: 1px solid #cdd7bb;
+  border-width: 0px 1px 1px 0px;
+  border-top-style:solid;
+  border-right-style:solid;
+  border-bottom-style:solid;
+  border-left-style:solid;  
+/*  margin: 0px; */
+  padding: 0px 4px 0px 4px;
+}
+
+.OBTreeGridHeaderCellTitle,
+.OBTreeGridHeaderCellTitleOver,
+.OBTreeGridHeaderCellTitleDown,
+.OBTreeGridHeaderCellTitleSelected,
+.OBTreeGridHeaderCellTitleSelectedOver,
+.OBTreeGridHeaderCellTitleSelectedDown,
+.OBTreeGridHeaderCellTitleDisabled,
+.OBTreeGridHeaderCellTitleSelectedDisabled {
+  font-size: 11px;
+  font-family: 'lucida sans', sans-serif;
+  font-weight: bold;
+  border: 1px solid #BBBFB6;
+  border-width: 0px 1px 0px 0px;
+  text-align: center;
+  background: none;
+}
+
+.OBTreeGridCellSelected,
+.OBTreeGridCellSelectedDark {
+  background-color: #ffe1c0; /* Orange for active grid, for non active grid: #b8d587 */
+}
+
+.OBTreeGridCellSelectedOver,
+.OBTreeGridCellSelectedOverDark {
+  background-color: #ffe1c0;
+}
+
+.OBTreeGridCellOver,
+.OBTreeGridCellOverDark,
+.OBTreeGridCellEditOver,
+.OBTreeGridCellEditOverDark {
+  background-color: #e1e1e1;  /* Orange for active grid, for non active grid: #dbe6c7 */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.application/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/ob-tree-grid-styles.js	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,74 @@
+isc.OBTreeGrid.addProperties({
+  bodyStyleName: 'OBGridBody',
+  baseStyle: 'OBTreeGridCell',
+  recordStyleError: 'OBGridCellError',
+  recordStyleSelectedViewInActive: 'OBGridCellSelectedViewInactive',
+  headerBaseStyle: 'OBGridHeaderCell',
+  headerBarStyle: 'OBGridHeaderBar',
+  headerTitleStyle: 'OBGridHeaderCellTitle',
+  emptyMessageStyle: 'OBGridNotificationText',
+  emptyMessageLinkStyle: 'OBGridNotificationTextLink',
+  cellPadding: 0,
+  /* Set in the CSS */
+  cellAlign: 'center',
+  leaveHeaderMenuButtonSpace: false,
+  sorterConstructor: 'ImgButton',
+  sortAscendingImage: {
+    src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_sortAscending.png',
+    width: 7,
+    height: 11
+  },
+  sortDescendingImage: {
+    src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_sortDescending.png',
+    width: 7,
+    height: 11
+  },
+  headerMenuButtonConstructor: 'OBGridHeaderImgButton',
+  headerButtonConstructor: 'ImgButton',
+  headerMenuButtonWidth: 17,
+  headerMenuButtonSrc: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeaderMenuButton.png',
+  hoverWidth: 200
+});
+
+isc.OBTreeGrid.changeDefaults('headerButtonDefaults', {
+  showTitle: true,
+  showDown: true,
+  showFocused: false,
+  // baseStyle / titleStyle is auto-assigned from headerBaseStyle
+  src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_bg.png'
+});
+
+isc.OBTreeGrid.changeDefaults('headerMenuButtonDefaults', {
+  showDown: false,
+  showTitle: true
+  //src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_bg.png'
+});
+
+isc.OBTreeGrid.changeDefaults('sorterDefaults', {});
+
+isc.OBTreeGrid.changeDefaults('filterEditorDefaults', {
+  height: 22,
+  styleName: 'OBGridFilterBase',
+  baseStyle: 'OBGridFilterCell'
+});
+
+isc.OBTreeGrid.changeDefaults('headerButtonDefaults', {
+  showTitle: true,
+  showDown: true,
+  showFocused: false,
+  // baseStyle / titleStyle is auto-assigned from headerBaseStyle
+  src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_bg.png'
+});
+
+isc.OBTreeGrid.changeDefaults('headerMenuButtonDefaults', {
+  showDown: false,
+  showTitle: true
+//  src: OB.Styles.skinsPath + 'Default/org.openbravo.client.application/images/grid/gridHeader_bg.png'
+});
+
+isc.OBTreeGrid.addProperties({
+  // note should be the same as the height of the OBGridButtonsComponent
+  recordComponentHeight: 21,
+  cellHeight: 25,
+  bodyStyleName: 'OBViewGridBody'
+});
\ No newline at end of file
--- a/modules/org.openbravo.client.kernel/src-db/database/sourcedata/OBCLKER_UIDEFINITION.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.client.kernel/src-db/database/sourcedata/OBCLKER_UIDEFINITION.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -290,6 +290,16 @@
 <!--B4F7A519D66D4D9187A71A9DBCD09EAD-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
 <!--B4F7A519D66D4D9187A71A9DBCD09EAD--></OBCLKER_UIDEFINITION>
 
+<!--B8A726E843FA40AD90255235E30A8E46--><OBCLKER_UIDEFINITION>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <OBCLKER_UIDEFINITION_ID><![CDATA[B8A726E843FA40AD90255235E30A8E46]]></OBCLKER_UIDEFINITION_ID>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <AD_MODULE_ID><![CDATA[4B828F4D03264080AA1D2057B13F613C]]></AD_MODULE_ID>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <AD_REFERENCE_ID><![CDATA[8C57A4A2E05F4261A1FADF47C30398AD]]></AD_REFERENCE_ID>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <CLASSNAME><![CDATA[org.openbravo.client.kernel.reference.FKTreeUIDefinition]]></CLASSNAME>
+<!--B8A726E843FA40AD90255235E30A8E46-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--B8A726E843FA40AD90255235E30A8E46--></OBCLKER_UIDEFINITION>
+
 <!--B93036D212284E62B29F0DEDAEEB9396--><OBCLKER_UIDEFINITION>
 <!--B93036D212284E62B29F0DEDAEEB9396-->  <OBCLKER_UIDEFINITION_ID><![CDATA[B93036D212284E62B29F0DEDAEEB9396]]></OBCLKER_UIDEFINITION_ID>
 <!--B93036D212284E62B29F0DEDAEEB9396-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/FKTreeUIDefinition.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,226 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License. 
+ * The Original Code is Openbravo ERP. 
+ * The Initial Developer of the Original Code is Openbravo SLU 
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.client.kernel.reference;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.codehaus.jettison.json.JSONObject;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.base.util.Check;
+import org.openbravo.base.weld.WeldUtils;
+import org.openbravo.client.application.ApplicationConstants;
+import org.openbravo.client.application.Parameter;
+import org.openbravo.client.application.window.OBTreeReferenceComponent;
+import org.openbravo.client.kernel.KernelUtils;
+import org.openbravo.dal.core.DalUtil;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.ad.domain.Reference;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.domain.ReferencedTreeField;
+import org.openbravo.model.ad.ui.Field;
+import org.openbravo.service.json.JsonConstants;
+import org.openbravo.userinterface.selector.Selector;
+import org.openbravo.userinterface.selector.SelectorComponent;
+import org.openbravo.userinterface.selector.SelectorConstants;
+
+/**
+ * Implementation of the foreign key tree ui definition. It uses a tree grid for its input and
+ * filter types
+ */
+public class FKTreeUIDefinition extends ForeignKeyUIDefinition {
+
+  private static final String PARAM_TAB_ID = "adTabId";
+  private static final String PARAM_COLUMN_NAME = "columnName";
+  private static final String SELECTOR_ITEM_PARAMETER = "IsSelectorItem";
+  private static final String PARAM_TARGET_PROPERTY_NAME = "targetProperty";
+
+  @Override
+  public String getFormEditorType() {
+    return "OBTreeItem";
+  }
+
+  @Override
+  public String getFilterEditorType() {
+    return "OBTreeFilterItem";
+  }
+
+  @Override
+  // get the current value for a selector item from the database
+  public String getFieldProperties(Field field, boolean getValueFromSession) {
+    try {
+      final JSONObject json = new JSONObject(super.getFieldProperties(field, getValueFromSession));
+      if (json.has("value")) {
+        final Property prop = KernelUtils.getInstance().getPropertyFromColumn(field.getColumn());
+        if (prop.isPrimitive()) {
+          json.put("identifier", json.getString("value"));
+        } else {
+          final BaseOBObject target = OBDal.getInstance().get(prop.getTargetEntity().getName(),
+              json.getString("value"));
+          if (target != null) {
+            final ReferencedTree referencedTree = getReferencedTree(field);
+            final ReferencedTreeField displayField = referencedTree.getDisplayfield();
+            if (displayField == null) {
+              json.put("identifier", target.getIdentifier());
+            } else if (displayField.getProperty() != null) {
+              json.put("identifier", DalUtil.getValueFromPath(target, displayField.getProperty()));
+            } else {
+              json.put("identifier", target.getIdentifier());
+            }
+          }
+        }
+      }
+      return json.toString();
+    } catch (Exception e) {
+      throw new OBException("Exception when processing field " + field, e);
+    }
+  }
+
+  public Map<String, Object> getDataSourceParameters() {
+    final Map<String, Object> params = new HashMap<String, Object>();
+    final Reference reference = OBDal.getInstance().get(Reference.class, getReference().getId());
+    for (ReferencedTree referencedTree : reference.getADReferencedTreeList()) {
+      if (referencedTree.isActive() && referencedTree.getTable() != null) {
+        final String extraProperties = OBTreeReferenceComponent.getAdditionalProperties(
+            referencedTree, true);
+        if (extraProperties.length() > 0) {
+          params.put(JsonConstants.ADDITIONAL_PROPERTIES_PARAMETER, extraProperties);
+        }
+        return params;
+      }
+    }
+    return params;
+  }
+
+  @Override
+  protected String getDisplayFieldName(Field field, Property prop) {
+    final ReferencedTree referencedTree = getReferencedTree(field);
+    final ReferencedTreeField displayField = referencedTree.getDisplayfield();
+    String displayFieldName = JsonConstants.IDENTIFIER;
+    if (displayField != null && displayField.getProperty() != null) {
+      displayFieldName = displayField.getProperty();
+    } else {
+      // fallback to the default
+      return null;
+    }
+
+    if (!prop.getReferencedProperty().getEntity().hasProperty(getFirstProperty(displayFieldName))) {
+      // If the first property of the display field name does not belong to the referenced entity,
+      // return the displayFieldName
+      // Otherwise trying to append the displayFieldName to the referenced property would later
+      // result in an error
+      return displayFieldName.replace(".", DalUtil.FIELDSEPARATOR);
+    } else {
+      final String result = (prop.getName() + DalUtil.FIELDSEPARATOR + displayFieldName).replace(
+          ".", DalUtil.FIELDSEPARATOR);
+      return result;
+    }
+
+  }
+
+  private String getFirstProperty(String displayFieldName) {
+    int dotPosition = displayFieldName.indexOf(DalUtil.DOT);
+    if (dotPosition == -1) {
+      return displayFieldName;
+    } else {
+      return displayFieldName.substring(0, dotPosition);
+    }
+  }
+
+  public String getFieldProperties(Field field) {
+    if (field == null) {
+      return super.getFieldProperties(field);
+    }
+    final ReferencedTree referencedTree = getReferencedTree(field);
+
+    final String tableName = field.getColumn().getTable().getDBTableName();
+    final String columnName = field.getColumn().getDBColumnName();
+    final String tableId = field.getColumn().getTable().getId();
+
+    Property property = null;
+    if (ApplicationConstants.DATASOURCEBASEDTABLE.equals(field.getColumn().getTable()
+        .getDataOriginType())) {
+      property = DalUtil.getPropertyByTableId(tableId, columnName);
+    } else {
+      property = DalUtil.getProperty(tableName, columnName);
+    }
+
+    final OBTreeReferenceComponent treeReferenceComponent = WeldUtils
+        .getInstanceFromStaticBeanManager(OBTreeReferenceComponent.class);
+    final Map<String, Object> parameters = new HashMap<String, Object>();
+    // TODO: Do not use Selector constants
+    parameters.put(PARAM_TAB_ID, field.getTab().getId());
+    parameters.put(PARAM_COLUMN_NAME, field.getColumn().getDBColumnName());
+    parameters.put(SELECTOR_ITEM_PARAMETER, "true");
+    parameters.put(PARAM_TARGET_PROPERTY_NAME, property.getName());
+    treeReferenceComponent.setId(referencedTree.getId());
+    treeReferenceComponent.setParameters(parameters);
+    treeReferenceComponent.setReferencedTree(referencedTree);
+
+    // append the super fields
+    final String treeFields = treeReferenceComponent.generate();
+    final String superJsonStr = super.getFieldProperties(field);
+    if (superJsonStr.trim().startsWith("{")) {
+      return treeFields + "," + superJsonStr.trim().substring(1, superJsonStr.trim().length() - 1);
+    }
+    return treeFields;
+  }
+
+  @Override
+  public String getParameterProperties(Parameter parameter) {
+    if (parameter == null) {
+      return super.getParameterProperties(parameter);
+    }
+
+    final Selector selector = parameter.getReferenceSearchKey().getOBUISELSelectorList().get(0);
+
+    final SelectorComponent selectorComponent = WeldUtils
+        .getInstanceFromStaticBeanManager(SelectorComponent.class);
+    final Map<String, Object> parameters = new HashMap<String, Object>();
+    parameters.put(SelectorConstants.PARAM_COLUMN_NAME, parameter.getDBColumnName());
+    parameters.put(SelectorComponent.SELECTOR_ITEM_PARAMETER, "true");
+    selectorComponent.setId(selector.getId());
+    selectorComponent.setParameters(parameters);
+
+    // append the super fields
+    final String selectorFields = selectorComponent.generate();
+    final String superJsonStr = super.getParameterProperties(parameter);
+    if (superJsonStr.trim().startsWith("{")) {
+      return selectorFields + ","
+          + superJsonStr.trim().substring(1, superJsonStr.trim().length() - 1);
+    } else {
+      return selectorFields + "," + superJsonStr;
+    }
+
+  }
+
+  private ReferencedTree getReferencedTree(Field field) {
+    final Reference reference = field.getColumn().getReferenceSearchKey();
+    Check.isNotNull(reference, "Field " + field + " does not have a reference value set");
+    for (ReferencedTree treeReference : reference.getADReferencedTreeList()) {
+      if (treeReference.isActive()) {
+        return treeReference;
+      }
+    }
+    Check.fail("No valid tree reference for field " + field);
+    return null;
+  }
+}
--- a/modules/org.openbravo.service.datasource/src-db/database/sourcedata/AD_MESSAGE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.service.datasource/src-db/database/sourcedata/AD_MESSAGE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -1,5 +1,17 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <data>
+<!--C870CF6294D94AB190FFF0CDF46B1568--><AD_MESSAGE>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <AD_MESSAGE_ID><![CDATA[C870CF6294D94AB190FFF0CDF46B1568]]></AD_MESSAGE_ID>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <VALUE><![CDATA[OBSERDS_ReparentNotInDevTreeNode]]></VALUE>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <MSGTEXT><![CDATA[The node must belong to a module that is in development in order to be reparented.]]></MSGTEXT>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <AD_MODULE_ID><![CDATA[A44B9BA75C354D8FB2E3F7D6EB6BFDC4]]></AD_MODULE_ID>
+<!--C870CF6294D94AB190FFF0CDF46B1568-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--C870CF6294D94AB190FFF0CDF46B1568--></AD_MESSAGE>
+
 <!--E7DFBB17F3104D5EA18467453C976C7A--><AD_MESSAGE>
 <!--E7DFBB17F3104D5EA18467453C976C7A-->  <AD_MESSAGE_ID><![CDATA[E7DFBB17F3104D5EA18467453C976C7A]]></AD_MESSAGE_ID>
 <!--E7DFBB17F3104D5EA18467453C976C7A-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/ADTreeDatasourceService.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,748 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.provider.OBProvider;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.client.application.ApplicationUtils;
+import org.openbravo.client.kernel.KernelUtils;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.dal.service.OBQuery;
+import org.openbravo.database.ConnectionProvider;
+import org.openbravo.erpCommon.businessUtility.Preferences;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.domain.ReferencedTreeField;
+import org.openbravo.model.ad.system.Client;
+import org.openbravo.model.ad.ui.Tab;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.model.ad.utility.Tree;
+import org.openbravo.model.ad.utility.TreeNode;
+import org.openbravo.model.common.enterprise.Organization;
+import org.openbravo.service.db.DalConnectionProvider;
+import org.openbravo.service.json.DataResolvingMode;
+import org.openbravo.service.json.DataToJsonConverter;
+import org.openbravo.service.json.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ADTreeDatasourceService extends TreeDatasourceService {
+  private static final Logger logger = LoggerFactory.getLogger(ADTreeDatasourceService.class);
+  private static final String AD_MENU_TABLE_ID = "116";
+  private static final String AD_ORG_TABLE_ID = "155";
+
+  @Override
+  /**
+   * Creates the treenode for the new node.
+   * If the tree does not exist yet, it creates it too
+   */
+  protected void addNewNode(JSONObject bobProperties) {
+    try {
+      Client client = OBContext.getOBContext().getCurrentClient();
+      Organization org = OBContext.getOBContext().getCurrentOrganization();
+      String bobId = bobProperties.getString("id");
+      String entityName = bobProperties.getString("_entity");
+      Entity entity = ModelProvider.getInstance().getEntity(entityName);
+      Table table = OBDal.getInstance().get(Table.class, entity.getTableId());
+      TableTree tableTree = getTableTree(table);
+      if (tableTree.isHandleNodesManually()) {
+        return;
+      }
+      Tree adTree = getTree(table, bobProperties);
+      if (adTree == null) {
+        // The adTree does not exists, create it
+        adTree = createTree(table, bobProperties);
+      }
+      // Adds the node to the adTree
+      TreeNode adTreeNode = OBProvider.getInstance().get(TreeNode.class);
+      adTreeNode.setClient(client);
+      adTreeNode.setOrganization(org);
+      adTreeNode.setTree(adTree);
+      adTreeNode.setNode(bobId);
+      adTreeNode.setSequenceNumber(100L);
+      // Added as root node
+      adTreeNode.setReportSet(ROOT_NODE_DB);
+      OBDal.getInstance().save(adTreeNode);
+      OBDal.getInstance().flush(); // force flush in admin mode
+    } catch (Exception e) {
+      logger.error("Error while adding the tree node", e);
+    }
+  }
+
+  @Override
+  /**
+   * Deletes the treenode and reparents its children
+   */
+  protected void deleteNode(JSONObject bobProperties) {
+    try {
+      String bobId = bobProperties.getString("id");
+      String entityName = bobProperties.getString("_entity");
+      Entity entity = ModelProvider.getInstance().getEntity(entityName);
+      Table table = OBDal.getInstance().get(Table.class, entity.getTableId());
+      TableTree tableTree = getTableTree(table);
+      if (tableTree.isHandleNodesManually()) {
+        return;
+      }
+      Tree tree = getTree(table, bobProperties);
+      OBCriteria<TreeNode> adTreeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      adTreeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
+      adTreeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, bobId));
+      TreeNode treeNode = (TreeNode) adTreeNodeCriteria.uniqueResult();
+      int nChildrenMoved = reparentChildrenOfDeletedNode(tree, treeNode.getReportSet(),
+          treeNode.getNode());
+      logger.info(nChildrenMoved + " children have been moved to another parent");
+      OBDal.getInstance().remove(treeNode);
+      OBDal.getInstance().flush(); // force flush in admin mode
+    } catch (Exception e) {
+      logger.error("Error while deleting tree node: ", e);
+      throw new OBException("The treenode could not be created");
+    }
+  }
+
+  /**
+   * Obtains the ADTree TableTree associated with the table
+   * 
+   * @param table
+   *          table whose ADTree TableTree will be returned
+   * @return the ADTree TableTree associated with the given table
+   */
+  private TableTree getTableTree(Table table) {
+    TableTree tableTree = null;
+    OBCriteria<TableTree> criteria = OBDal.getInstance().createCriteria(TableTree.class);
+    criteria.add(Restrictions.eq(TableTree.PROPERTY_TABLE, table));
+    criteria.add(Restrictions.eq(TableTree.PROPERTY_TREESTRUCTURE, "ADTree"));
+    // There can be at most one ADTree table per table, so it is safe to use uniqueResult
+    tableTree = (TableTree) criteria.uniqueResult();
+    return tableTree;
+  }
+
+  /**
+   * In the given tree, reparents the children of deletedNodeId, change it to newParentId
+   * 
+   * @return The number of nodes that have been reparented
+   */
+  public int reparentChildrenOfDeletedNode(Tree tree, String newParentId, String deletedNodeId) {
+    int nChildrenMoved = -1;
+    try {
+      ConnectionProvider conn = new DalConnectionProvider(false);
+      nChildrenMoved = TreeDatasourceServiceData.reparentChildrenADTree(conn, newParentId,
+          tree.getId(), deletedNodeId);
+    } catch (ServletException e) {
+      logger.error("Error while deleting tree node: ", e);
+    }
+    return nChildrenMoved;
+  }
+
+  /**
+   * 
+   * @param parentId
+   *          id of the node whose children are to be retrieved
+   * @param hqlWhereClause
+   *          hql where clase of the tab/selector
+   * @param hqlWhereClauseRootNodes
+   *          hql where clause that define what nodes are roots
+   * @return A JSONArray containing all the children of the given node
+   * @throws JSONException
+   * @throws TooManyTreeNodesException
+   *           if the number of returned nodes were to be too high
+   */
+  @Override
+  protected JSONArray fetchNodeChildren(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String parentId, String hqlWhereClause,
+      String hqlWhereClauseRootNodes) throws JSONException, TooManyTreeNodesException {
+
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    JSONArray selectedProperties = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      String selectedPropertiesStr = parameters.get("_selectedProperties");
+      selectedProperties = new JSONArray(selectedPropertiesStr);
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      treeReference.getADReferencedTreeFieldList();
+      selectedProperties = new JSONArray();
+      for (ReferencedTreeField treeField : treeReference.getADReferencedTreeFieldList()) {
+        selectedProperties.put(treeField.getProperty());
+      }
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONArray();
+    }
+    Tree tree = (Tree) datasourceParameters.get("tree");
+
+    JSONArray responseData = new JSONArray();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(tree.getTable().getId());
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+
+    // Joins the ADTreeNode with the referenced table
+    StringBuilder joinClause = new StringBuilder();
+    joinClause.append(" as tn ");
+    joinClause.append(" , " + entity.getName() + " as e ");
+    joinClause.append(" where tn.node = e.id ");
+    if (hqlWhereClause != null) {
+      joinClause.append(" and (" + hqlWhereClause + ")");
+    }
+    joinClause.append(" and tn.tree.id = '" + tree.getId() + "' ");
+    if (hqlWhereClauseRootNodes == null && tab != null && tab.getTabLevel() > 0) {
+      // Add the criteria to filter only the records that belong to the record selected in the
+      // parent tab
+      Tab parentTab = KernelUtils.getInstance().getParentTab(tab);
+      String parentPropertyName = ApplicationUtils.getParentProperty(tab, parentTab);
+      if (parentPropertyName != null) {
+        JSONArray criteria = (JSONArray) JsonUtils.buildCriteria(parameters).get("criteria");
+        String parentRecordId = getParentRecordIdFromCriteria(criteria, parentPropertyName);
+        if (parentRecordId != null) {
+          joinClause.append(" and e." + parentPropertyName + ".id = '" + parentRecordId + "' ");
+        }
+      }
+    }
+    if (hqlWhereClauseRootNodes != null) {
+      joinClause.append(" and (" + hqlWhereClauseRootNodes + ") ");
+    } else {
+      if (ROOT_NODE_CLIENT.equals(parentId)) {
+        if (AD_ORG_TABLE_ID.equals(tree.getTable().getId())) {
+          // The ad_org table needs a special treatment, since is the only table tree that has an
+          // actual node ('*' organization) with node_id = ROOT_NODE_DB
+          // In this table the root nodes have the parent_id property set to null
+          joinClause.append(" and tn.reportSet is null");
+        } else {
+          // Other ad_tree nodes can have either ROOT_NODE_DB or null as parent_id
+          joinClause.append(" and (tn.reportSet = '" + ROOT_NODE_DB + "' or tn.reportSet is null)");
+        }
+      } else {
+        joinClause.append(" and tn.reportSet = '" + parentId + "' ");
+      }
+    }
+    joinClause.append(" order by tn.sequenceNumber ");
+
+    // Selects the relevant properties from ADTreeNode and all the properties from the referenced
+    // table
+    String selectClause = " tn.id as treeNodeId, tn.reportSet as parentId, tn.sequenceNumber as seqNo, tn.node as nodeId, e as entity";
+    OBQuery<BaseOBObject> obq = OBDal.getInstance()
+        .createQuery("ADTreeNode", joinClause.toString());
+    obq.setSelectClause(selectClause);
+    obq.setFilterOnReadableOrganization(false);
+    int nResults = obq.count();
+
+    OBContext context = OBContext.getOBContext();
+    int nMaxResults = -1;
+    try {
+      nMaxResults = Integer.parseInt(Preferences.getPreferenceValue("TreeDatasourceFetchLimit",
+          false, context.getCurrentClient(), context.getCurrentOrganization(), context.getUser(),
+          context.getRole(), null));
+    } catch (Exception e) {
+      nMaxResults = 1000;
+    }
+    if (nResults > nMaxResults) {
+      throw new TooManyTreeNodesException();
+    }
+
+    boolean fetchRoot = ROOT_NODE_CLIENT.equals(parentId);
+
+    int PARENT_ID = 1;
+    int SEQNO = 2;
+    int NODE_ID = 3;
+    int ENTITY = 4;
+    int cont = 0;
+    ScrollableResults scrollNodes = obq.createQuery().scroll(ScrollMode.FORWARD_ONLY);
+    while (scrollNodes.next()) {
+      Object[] node = (Object[]) scrollNodes.get();
+      JSONObject value = null;
+      BaseOBObject bob = (BaseOBObject) node[ENTITY];
+      try {
+        value = toJsonConverter.toJsonObject((BaseOBObject) bob, DataResolvingMode.FULL);
+        value.put("nodeId", bob.getId().toString());
+        if (fetchRoot) {
+          value.put("parentId", ROOT_NODE_CLIENT);
+        } else {
+          value.put("parentId", node[PARENT_ID]);
+        }
+        addNodeCommonAttributes(entity, bob, value);
+        value.put("seqno", node[SEQNO]);
+        value.put("_hasChildren",
+            (this.nodeHasChildren(entity, (String) node[NODE_ID], hqlWhereClause)) ? true : false);
+      } catch (JSONException e) {
+        logger.error("Error while constructing JSON reponse", e);
+      }
+      responseData.put(value);
+      if ((cont % 100) == 0) {
+        OBDal.getInstance().flush();
+        OBDal.getInstance().getSession().clear();
+      }
+      cont++;
+    }
+    return responseData;
+  }
+
+  private String getParentRecordIdFromCriteria(JSONArray criteria, String parentPropertyName) {
+    String parentRecordId = null;
+    for (int i = 0; i < criteria.length(); i++) {
+      try {
+        JSONObject criterion = (JSONObject) criteria.get(i);
+        if (criterion.has("criteria")) {
+          return getParentRecordIdFromCriteria(criterion.getJSONArray("criteria"),
+              parentPropertyName);
+        }
+        if (parentPropertyName.equals(criterion.getString("fieldName"))) {
+          parentRecordId = criterion.getString("value");
+          break;
+        }
+      } catch (JSONException e) {
+        logger.error("Error while obtaining a property from a JSONObject", e);
+      }
+    }
+    return parentRecordId;
+  }
+
+  /**
+   * Check if a node has children
+   * 
+   * @param entity
+   *          the entity the node belongs to
+   * @param nodeId
+   *          the id of the node to be checked
+   * @param hqlWhereClause
+   *          the where clause to be applied to the children
+   * @return
+   */
+  private boolean nodeHasChildren(Entity entity, String nodeId, String hqlWhereClause) {
+    StringBuilder joinClause = new StringBuilder();
+    joinClause.append(" as tn ");
+    joinClause.append(" , " + entity.getName() + " as e ");
+    joinClause.append(" where tn.node = e.id ");
+    if (hqlWhereClause != null) {
+      joinClause.append(" and (" + hqlWhereClause + ")");
+    }
+    joinClause.append(" and tn.reportSet = ? order by tn.sequenceNumber ");
+    OBQuery<BaseOBObject> obq = OBDal.getInstance()
+        .createQuery("ADTreeNode", joinClause.toString());
+    final List<Object> parameters = new ArrayList<Object>();
+    parameters.add(nodeId);
+    obq.setParameters(parameters);
+    return obq.count() > 0;
+  }
+
+  /**
+   * Returns the sequence number of a node that has just been moved, and recompontes the sequence
+   * number of its peers when needed
+   * 
+   * @param tree
+   *          the ADTree being modified
+   * @param prevNodeId
+   *          id of the node that will be placed just before the updated node after it has been
+   *          moved
+   * @param nextNodeId
+   *          id of the node that will be placed just after the updated node after it has been moved
+   * @param newParentId
+   *          id of the parent node of the node whose sequence number is being calculated
+   * @return The sequence number of the node that has just been reparented
+   * @throws Exception
+   */
+  private Long calculateSequenceNumberAndRecompute(Tree tree, String prevNodeId, String nextNodeId,
+      String newParentId) throws Exception {
+    Long seqNo = null;
+    if (prevNodeId == null && nextNodeId == null) {
+      // Only child, no need to recompute sequence numbers
+      seqNo = 10L;
+    } else if (nextNodeId == null) {
+      // Last positioned child. Pick the highest sequence number of its brothers and add 10
+      // No need to recompute sequence numbers
+      OBCriteria<TreeNode> maxSeqNoCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      maxSeqNoCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
+      maxSeqNoCriteria.add(Restrictions.eq(TreeNode.PROPERTY_REPORTSET, newParentId));
+      maxSeqNoCriteria.setProjection(Projections.max(TreeNode.PROPERTY_SEQUENCENUMBER));
+      Long maxSeqNo = (Long) maxSeqNoCriteria.uniqueResult();
+      seqNo = maxSeqNo + 10;
+    } else {
+      // Sequence numbers of the nodes that are positioned after the new one needs to be recomputed
+      OBCriteria<TreeNode> nextNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      nextNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
+      nextNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, nextNodeId));
+      TreeNode nextNode = (TreeNode) nextNodeCriteria.uniqueResult();
+      seqNo = nextNode.getSequenceNumber();
+      recomputeSequenceNumbers(tree, newParentId, seqNo);
+    }
+    return seqNo;
+  }
+
+  /**
+   * Adds 10 to the seqno of all the child nodes of newParentId, if they seqNo is equals or higher
+   * than the provided seqNo For the ADMenu tree, it updates the seqno of all the nodes until the
+   * first node associated with a menu entry that belong to a module not in developement is reached
+   */
+  private void recomputeSequenceNumbers(Tree tree, String newParentId, Long seqNo) {
+    StringBuilder queryStr = new StringBuilder();
+    queryStr.append(" UPDATE ad_treenode ");
+    queryStr.append(" SET seqno = (seqno + 10) ");
+    queryStr.append(" WHERE ad_tree_id = ? ");
+    if (newParentId == null) {
+      queryStr.append(" AND parent_id is null ");
+    } else {
+      queryStr.append(" AND parent_id = ? ");
+    }
+    queryStr.append(" AND seqno >= ? ");
+
+    // Menu Tree, do not update the nodes that belong to windows not in development
+    int seqNoOfFirstModNotInDev = -1;
+    if (tree.getTable().getId().equals(AD_MENU_TABLE_ID)) {
+      seqNoOfFirstModNotInDev = getSeqNoOfFirstModNotInDev(tree.getId(), newParentId, seqNo);
+      if (seqNoOfFirstModNotInDev > 0) {
+        queryStr.append(" AND seqno < ? ");
+      }
+    }
+
+    ConnectionProvider conn = new DalConnectionProvider(false);
+    PreparedStatement st = null;
+    try {
+      int nParam = 1;
+      st = conn.getPreparedStatement(queryStr.toString());
+      st.setString(nParam++, tree.getId());
+      if (newParentId != null) {
+        st.setString(nParam++, newParentId);
+      }
+      st.setLong(nParam++, seqNo);
+      if (seqNoOfFirstModNotInDev > 0) {
+        st.setLong(nParam++, seqNoOfFirstModNotInDev);
+      }
+      int nUpdated = st.executeUpdate();
+      logger.debug("Recomputing sequence numbers: " + nUpdated + " nodes updated");
+    } catch (Exception e) {
+      logger.error("Exception while recomputing sequence numbers: ", e);
+    } finally {
+      try {
+        conn.releasePreparedStatement(st);
+      } catch (SQLException e) {
+        logger.error("Error while releasing a prepared statement", e);
+      }
+    }
+  }
+
+  /**
+   * Obtains the lower sequence number of the tree nodes that: belong to the treeId tree, are
+   * children of the parentId node, their sequence number is higher or equals to seqNo, are
+   * associated to a menu entry that belongs to a module not in development
+   */
+  private int getSeqNoOfFirstModNotInDev(String treeId, String parentId, Long seqNo) {
+    StringBuilder queryStr = new StringBuilder();
+    queryStr.append(" SELECT min(tn.seqno) ");
+    queryStr.append(" FROM ad_treenode tn, ad_menu me, ad_module mo ");
+    queryStr.append(" WHERE tn.node_id = me.ad_menu_id ");
+    queryStr.append(" AND me.ad_module_id = mo.ad_module_id ");
+    queryStr.append(" AND tn.ad_tree_id = ? ");
+    queryStr.append(" AND tn.parent_id = ? ");
+    queryStr.append(" AND tn.seqno >= ? ");
+    queryStr.append(" AND mo.isindevelopment = 'N' ");
+    ConnectionProvider conn = new DalConnectionProvider(false);
+    PreparedStatement st = null;
+    int seq = -1;
+    try {
+      st = conn.getPreparedStatement(queryStr.toString());
+      st.setString(1, treeId);
+      st.setString(2, parentId);
+      st.setLong(3, seqNo);
+      ResultSet rs = st.executeQuery();
+      if (rs.next()) {
+        seq = rs.getInt(1);
+      }
+    } catch (Exception e) {
+      logger.error("Exception while recomputing sequence numbers: ", e);
+    } finally {
+      try {
+        conn.releasePreparedStatement(st);
+      } catch (SQLException e) {
+        // Will not happen
+      }
+    }
+    return seq;
+  }
+
+  /**
+   * Checks if a tree is ordered
+   * 
+   * @param tree
+   * @return
+   */
+  private boolean isOrdered(Tree tree) {
+    Table table = tree.getTable();
+    List<TableTree> tableTreeList = table.getADTableTreeList();
+    if (tableTreeList.size() != 1) {
+      return false;
+    } else {
+      TableTree tableTree = tableTreeList.get(0);
+      return tableTree.isOrdered();
+    }
+  }
+
+  /**
+   * Returns a Tree given the referencedTableId and the parentRecordId
+   * 
+   * @param referencedTableId
+   * @param parentRecordId
+   * @return
+   */
+  private Tree getTree(String referencedTableId) {
+    Table referencedTable = OBDal.getInstance().get(Table.class, referencedTableId);
+
+    OBCriteria<Tree> treeCriteria = OBDal.getInstance().createCriteria(Tree.class);
+    treeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, referencedTable));
+    treeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext()
+        .getCurrentClient()));
+    return (Tree) treeCriteria.uniqueResult();
+  }
+
+  /**
+   * Returns a Tree given the referencedTableId and a jsonobject that contains the node properties
+   * This is called from the EventHandler, because the parentRecordId is not avaiable in the
+   * parameters
+   * 
+   * @param referencedTableId
+   * @param parentRecordId
+   * @return
+   */
+  private Tree getTree(Table table, JSONObject bobProperties) {
+    Tree tree = null;
+    OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class);
+    adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table));
+    tree = (Tree) adTreeCriteria.uniqueResult();
+    return tree;
+  }
+
+  /**
+   * Creates a new tree (record in ADTree)
+   * 
+   */
+  private Tree createTree(Table table, JSONObject bobProperties) {
+    Client client = OBContext.getOBContext().getCurrentClient();
+    Organization org = OBContext.getOBContext().getCurrentOrganization();
+
+    Tree adTree = OBProvider.getInstance().get(Tree.class);
+    adTree.setClient(client);
+    adTree.setOrganization(org);
+    adTree.setAllNodes(true);
+    adTree.setTypeArea(table.getName());
+    adTree.setTable(table);
+    String name = table.getName();
+    adTree.setName(name);
+    OBDal.getInstance().save(adTree);
+    return adTree;
+  }
+
+  /**
+   * Updates the parent of a given node a returns its definition in a JSONObject and recomputes the
+   * sequence number of the nodes if the tree is ordered
+   */
+  protected JSONObject moveNode(Map<String, String> parameters, String nodeId, String newParentId,
+      String prevNodeId, String nextNodeId) throws Exception {
+    String tableId = null;
+    String referencedTableId = parameters.get("referencedTableId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    JSONArray selectedProperties = null;
+    if (referencedTableId != null) {
+      tableId = referencedTableId;
+      String selectedPropertiesStr = parameters.get("_selectedProperties");
+      selectedProperties = new JSONArray(selectedPropertiesStr);
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      treeReference.getADReferencedTreeFieldList();
+      tableId = treeReference.getTable().getId();
+      selectedProperties = new JSONArray();
+      for (ReferencedTreeField treeField : treeReference.getADReferencedTreeFieldList()) {
+        selectedProperties.put(treeField.getProperty());
+      }
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONObject();
+    }
+
+    String parentIdDB = newParentId;
+    if (parentIdDB.equals(ROOT_NODE_CLIENT)) {
+      // AD_ORG is special, root nodes have parentId = null, while the other in the trees root nodes
+      // have parentId = '0'
+      if (AD_ORG_TABLE_ID.equals(tableId)) {
+        parentIdDB = null;
+      } else {
+        parentIdDB = ROOT_NODE_DB;
+      }
+    }
+
+    Tree tree = this.getTree(tableId);
+    boolean isOrdered = this.isOrdered(tree);
+    Long seqNo = null;
+    if (isOrdered) {
+      seqNo = this.calculateSequenceNumberAndRecompute(tree, prevNodeId, nextNodeId, parentIdDB);
+    }
+
+    OBCriteria<TreeNode> treeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+    treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
+    treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, nodeId));
+    TreeNode treeNode = (TreeNode) treeNodeCriteria.uniqueResult();
+    treeNode.setReportSet(parentIdDB);
+    if (isOrdered) {
+      treeNode.setSequenceNumber(seqNo);
+    }
+
+    OBDal.getInstance().flush(); // flush in admin mode
+    return null;
+  }
+
+  @Override
+  protected JSONObject getJSONObjectByNodeId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String nodeId) throws MultipleParentsException {
+    // In the ADTree structure, nodeId = recordId
+    return this.getJSONObjectByRecordId(parameters, datasourceParameters, nodeId);
+  }
+
+  @Override
+  protected JSONObject getJSONObjectByRecordId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String bobId) {
+
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    String hqlWhereClause = null;
+    if (tabId != null) {
+      Tab tab = OBDal.getInstance().get(Tab.class, tabId);
+      hqlWhereClause = tab.getHqlwhereclause();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      hqlWhereClause = treeReference.getHQLSQLWhereClause();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONObject();
+    }
+    Tree tree = (Tree) datasourceParameters.get("tree");
+
+    if (hqlWhereClause != null) {
+      hqlWhereClause = this.substituteParameters(hqlWhereClause, parameters);
+    }
+
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(tree.getTable().getId());
+
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+
+    JSONObject json = null;
+    try {
+      OBCriteria<TreeNode> treeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
+      treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, bobId));
+      TreeNode treeNode = (TreeNode) treeNodeCriteria.uniqueResult();
+      BaseOBObject bob = OBDal.getInstance().get(entity.getName(), treeNode.getNode());
+      json = toJsonConverter.toJsonObject((BaseOBObject) bob, DataResolvingMode.FULL);
+      json.put("nodeId", bobId);
+      if (treeNode.getReportSet() == null) {
+        json.put("parentId", ROOT_NODE_CLIENT);
+      } else {
+        json.put("parentId", treeNode.getReportSet());
+      }
+
+      addNodeCommonAttributes(entity, bob, json);
+      json.put("_hasChildren", this.nodeHasChildren(entity, treeNode.getNode(), hqlWhereClause));
+    } catch (Exception e) {
+      logger.error("Error on tree datasource", e);
+    }
+    return json;
+  }
+
+  /**
+   * Checks if the provided node complies with the hql where clause
+   */
+  protected boolean nodeConformsToWhereClause(TableTree tableTree, String nodeId,
+      String hqlWhereClause) {
+
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(tableTree.getTable().getId());
+    StringBuilder joinClause = new StringBuilder();
+    joinClause.append(" as tn ");
+    joinClause.append(" , " + entity.getName() + " as e ");
+    joinClause.append(" where tn.node = e.id ");
+    if (hqlWhereClause != null) {
+      joinClause.append(" and (" + hqlWhereClause + ")");
+    }
+    joinClause.append(" and tn.node = ?");
+    OBQuery<BaseOBObject> obq = OBDal.getInstance()
+        .createQuery("ADTreeNode", joinClause.toString());
+
+    final List<Object> parameters = new ArrayList<Object>();
+    parameters.add(nodeId);
+    obq.setParameters(parameters);
+
+    return obq.count() > 0;
+  }
+
+  @Override
+  protected JSONArray fetchFilteredNodesForTreesWithMultiParentNodes(
+      Map<String, String> parameters, Map<String, Object> datasourceParameters,
+      TableTree tableTree, List<String> filteredNodes, String hqlTreeWhereClause,
+      String hqlTreeWhereClauseRootNodes, boolean allowNotApplyingWhereClauseToChildren)
+      throws MultipleParentsException, TooManyTreeNodesException {
+    // Not applicable, an ADTreeNode can only have one parent node
+    return new JSONArray();
+  }
+
+  @Override
+  protected Map<String, Object> getDatasourceSpecificParams(Map<String, String> parameters) {
+    Map<String, Object> datasourceParams = new HashMap<String, Object>();
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    String tableId = null;
+    if (tabId != null) {
+      Tab tab = OBDal.getInstance().get(Tab.class, tabId);
+      tableId = tab.getTable().getId();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      tableId = treeReference.getTable().getId();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return datasourceParams;
+    }
+    Tree tree = this.getTree(tableId);
+    datasourceParams.put("tree", tree);
+    return datasourceParams;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/CheckTreeOperationManager.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,101 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013-2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource;
+
+import java.util.Map;
+
+/**
+ * Abstract class used to restrict the movements of nodes for a particular tree
+ * 
+ * To check if a node movement is valid for a particular tree, this class has to be subclassed and
+ * the checkNodeMovement method must be implemented to determine whether a node movement is valid.
+ * Also this annotations must be added for the class to be used using dependency injection:
+ * 
+ * @ApplicationScoped
+ * @Qualifier("entityName"), entityName being the name of the DAL entity associated with the tree
+ * 
+ */
+public abstract class CheckTreeOperationManager {
+
+  /**
+   * Checks if a node movement is valid
+   * 
+   * @param parameters
+   *          Map of the parameters sent to the client to the datasource
+   * @param nodeId
+   *          id of the node being moved
+   * @param newParentId
+   *          id of the new parent of the node (ROOT_NODE_CLIENT if the node is being moved to the
+   *          root)
+   * @param prevNodeId
+   *          id of the sibling node that would be placed just before the node being moved. Can be
+   *          null if the node is being placed in the first position of its siblings. Irrelevant if
+   *          the tree is not ordered
+   * @param nextNodeId
+   *          id of the sibling node that would be placed just after the node being moved. Can be
+   *          null if the node is being placed in the last position of its siblings. Irrelevant if
+   *          the tree is not ordered
+   * @return an ActionResponse object. If the movement is valid, the success attribute must be true,
+   *         false otherwise. The message and messageType attributes can be used to show a message
+   *         in the client message bar
+   */
+  public abstract ActionResponse checkNodeMovement(Map<String, String> parameters, String nodeId,
+      String newParentId, String prevNodeId, String nextNodeId);
+
+  protected class ActionResponse {
+    private boolean success;
+    private String messageType;
+    private String message;
+
+    public ActionResponse(boolean success) {
+      this.success = success;
+    }
+
+    public ActionResponse(boolean success, String messageType, String message) {
+      this.success = success;
+      this.messageType = messageType;
+      this.message = message;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public void setMessage(String message) {
+      this.message = message;
+    }
+
+    public String getMessageType() {
+      return messageType;
+    }
+
+    public void setMessageType(String messageType) {
+      this.messageType = messageType;
+    }
+
+    public boolean isSuccess() {
+      return success;
+    }
+
+    public void setSuccess(boolean success) {
+      this.success = success;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/LinkToParentTreeDatasourceService.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,848 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.provider.OBProvider;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.dal.service.OBQuery;
+import org.openbravo.database.ConnectionProvider;
+import org.openbravo.erpCommon.businessUtility.Preferences;
+import org.openbravo.model.ad.datamodel.Column;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.ui.Tab;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.service.db.DalConnectionProvider;
+import org.openbravo.service.json.DataResolvingMode;
+import org.openbravo.service.json.DataToJsonConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LinkToParentTreeDatasourceService extends TreeDatasourceService {
+  private static final Logger logger = LoggerFactory
+      .getLogger(LinkToParentTreeDatasourceService.class);
+  private static final String ID_SEPARATOR = "-";
+
+  @Override
+  protected void addNewNode(JSONObject bobProperties) {
+    // Nothing needs to be done
+  }
+
+  @Override
+  protected void deleteNode(JSONObject bobProperties) {
+    // When a node is deleted, reparents its children so that the referencial integrity is not
+    // broken
+    try {
+      String entityName = bobProperties.getString("_entity");
+      Entity entity = ModelProvider.getInstance().getEntity(entityName);
+      Table table = OBDal.getInstance().get(Table.class, entity.getTableId());
+      Property linkToParentProperty = getLinkToParentProperty(table);
+      Property nodeIdProperty = getNodeIdProperty(table);
+      String bobParentNode = null;
+      String bobNodeId = null;
+      if (bobProperties.has(linkToParentProperty.getName())) {
+        bobParentNode = bobProperties.getString(linkToParentProperty.getName());
+      }
+      if (bobProperties.has(nodeIdProperty.getName())) {
+        bobNodeId = bobProperties.getString(nodeIdProperty.getName());
+      }
+      int nChildrenMoved = reparentChildrenOfDeletedNode(entity, bobParentNode, bobNodeId);
+      logger.info(nChildrenMoved + " children have been moved to another parent");
+    } catch (Exception e) {
+      logger.error("Error while deleting tree node: ", e);
+      throw new OBException("The node could not be deleted");
+    }
+  }
+
+  /**
+   * Does the actual reparent
+   * 
+   * @param entity
+   * @param newParentId
+   *          new parent id to be used on the moved nodes
+   * @param oldParentId
+   *          parent id of the nodes to be moved
+   * @return the number of reparented nodes
+   */
+  public int reparentChildrenOfDeletedNode(Entity entity, String newParentId, String oldParentId) {
+    int nChildrenMoved = -1;
+    Table table = OBDal.getInstance().get(Table.class, entity.getTableId());
+    Property linkToParentProperty = getLinkToParentProperty(table);
+    Column linkToParentColumn = OBDal.getInstance().get(Column.class,
+        linkToParentProperty.getColumnId());
+    try {
+      ConnectionProvider conn = new DalConnectionProvider(false);
+      nChildrenMoved = TreeDatasourceServiceData.reparentChildrenLinkToParent(conn,
+          table.getDBTableName(), linkToParentColumn.getDBColumnName(), newParentId, oldParentId);
+    } catch (ServletException e) {
+      logger.error("Error while deleting tree node: ", e);
+    }
+    return nChildrenMoved;
+  }
+
+  /**
+   * Given a tableTree, returns the property that points to the parent node
+   * 
+   * @param tableTree
+   * @return the property that points to the parent node
+   */
+  private Property getLinkToParentProperty(TableTree tableTree) {
+    Column linkToParentColumn = tableTree.getLinkToParentColumn();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(tableTree.getTable().getId());
+    return entity.getPropertyByColumnName(linkToParentColumn.getDBColumnName());
+  }
+
+  /**
+   * Given a table, returns the property that points to the parent node. It is used when the
+   * TableTree is not available. Uses the first TableTree defined for that table
+   * 
+   * @param table
+   * @return the property that points to the parent node
+   */
+  private Property getLinkToParentProperty(Table table) {
+    List<TableTree> tableTreeList = table.getADTableTreeList();
+    if (tableTreeList.size() != 1) {
+      return null;
+    }
+    TableTree tableTree = tableTreeList.get(0);
+    Column linkToParentColumn = tableTree.getLinkToParentColumn();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    return entity.getPropertyByColumnName(linkToParentColumn.getDBColumnName());
+  }
+
+  /**
+   * Given a tableTree, returns the property that represents the node id
+   * 
+   * @param tableTree
+   * @return the property that represents the node id
+   */
+  private Property getNodeIdProperty(TableTree tableTree) {
+    Column nodeIdColumn = tableTree.getNodeIdColumn();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(tableTree.getTable().getId());
+    return entity.getPropertyByColumnName(nodeIdColumn.getDBColumnName());
+  }
+
+  /**
+   * Given a table, returns the property that represents the node id. It is used when the TableTree
+   * is not available. Uses the first TableTree defined for the provided table
+   * 
+   * @param table
+   * @return the property that represents the node id
+   */
+  private Property getNodeIdProperty(Table table) {
+    List<TableTree> tableTreeList = table.getADTableTreeList();
+    if (tableTreeList.size() != 1) {
+      return null;
+    }
+    TableTree tableTree = tableTreeList.get(0);
+    Column nodeIdColumn = tableTree.getNodeIdColumn();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    return entity.getPropertyByColumnName(nodeIdColumn.getDBColumnName());
+  }
+
+  /**
+   * 
+   * @param parameters
+   * @param parentId
+   *          id of the node whose children are to be retrieved
+   * @param hqlWhereClause
+   *          hql where clase of the tab/selector
+   * @param hqlWhereClauseRootNodes
+   *          hql where clause that define what nodes are roots
+   * @return
+   * @throws JSONException
+   * @throws TooManyTreeNodesException
+   *           if the number of returned nodes were to be too high
+   */
+  @Override
+  protected JSONArray fetchNodeChildren(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String parentId, String hqlWhereClause,
+      String hqlWhereClauseRootNodes) throws JSONException, TooManyTreeNodesException {
+
+    boolean fetchRoot = ROOT_NODE_CLIENT.equals(parentId);
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    Table table = null;
+    TableTree tableTree = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      table = tab.getTable();
+      tableTree = tab.getTableTree();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      table = treeReference.getTable();
+      tableTree = treeReference.getTableTreeCategory();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONArray();
+    }
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Property linkToParentProperty = getLinkToParentProperty(tableTree);
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+    boolean isMultiParentTree = tableTree.isHasMultiparentNodes();
+
+    StringBuilder whereClause = new StringBuilder();
+    whereClause.append(" as e where ");
+    String actualParentId = new String(parentId);
+    if (isMultiParentTree) {
+      // The ids of multi parent trees are formed by the concatenation of, beginning with its root
+      // node
+      if (parentId.contains(ID_SEPARATOR)) {
+        actualParentId = parentId.substring(parentId.lastIndexOf(ID_SEPARATOR) + 1);
+      }
+    }
+
+    boolean allowNotApplyingWhereClauseToChildren = !tableTree.isApplyWhereClauseToChildNodes();
+    if ((fetchRoot || !allowNotApplyingWhereClauseToChildren) && hqlWhereClause != null) {
+      // Include the hql where clause for all root nodes and for child nodes only if it is required
+      whereClause.append(hqlWhereClause + " and ");
+    }
+
+    if (hqlWhereClauseRootNodes != null && fetchRoot) {
+      // If we are fetching the root nodes and there is a defined hqlWhereClauseRootNodes, apply it
+      whereClause.append(" " + hqlWhereClauseRootNodes + " ");
+    } else {
+      whereClause.append(" e." + linkToParentProperty.getName());
+      if (fetchRoot) {
+        whereClause.append(" is null ");
+      } else {
+        if (!linkToParentProperty.isPrimitive()) {
+          whereClause.append(".id");
+        }
+        whereClause.append(" = ? ");
+      }
+    }
+    final OBQuery<BaseOBObject> query = OBDal.getInstance().createQuery(entity.getName(),
+        whereClause.toString());
+
+    final List<Object> queryParameters = new ArrayList<Object>();
+    queryParameters.add(actualParentId);
+    query.setParameters(queryParameters);
+
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+
+    JSONArray responseData = new JSONArray();
+
+    // Check if the number of results to be returned is not higher than the defined limit
+    int nResults = query.count();
+    OBContext context = OBContext.getOBContext();
+    int nMaxResults = -1;
+    try {
+      nMaxResults = Integer.parseInt(Preferences.getPreferenceValue("TreeDatasourceFetchLimit",
+          false, context.getCurrentClient(), context.getCurrentOrganization(), context.getUser(),
+          context.getRole(), null));
+    } catch (Exception e) {
+      nMaxResults = 1000;
+    }
+    if (nResults > nMaxResults) {
+      throw new TooManyTreeNodesException();
+    }
+    int count = 0;
+    final ScrollableResults scrollableResults = query.scroll(ScrollMode.FORWARD_ONLY);
+    while (scrollableResults.next()) {
+      BaseOBObject bob = (BaseOBObject) scrollableResults.get()[0];
+      final JSONObject json = toJsonConverter.toJsonObject((BaseOBObject) bob,
+          DataResolvingMode.FULL);
+      if (fetchRoot) {
+        json.put("parentId", ROOT_NODE_CLIENT);
+      } else {
+        json.put("parentId", parentId);
+      }
+      Object nodeId = bob.get(nodeIdProperty.getName());
+      String nodeIdStr = null;
+      if (nodeId instanceof String) {
+        nodeIdStr = (String) nodeId;
+      } else if (nodeId instanceof BaseOBObject) {
+        nodeIdStr = ((BaseOBObject) nodeId).getId().toString();
+      }
+
+      Object parentNodeId = bob.get(linkToParentProperty.getName());
+      String parentNodeIdStr = null;
+      if (parentNodeId instanceof String) {
+        parentNodeIdStr = (String) parentNodeId;
+      } else if (parentNodeId instanceof BaseOBObject) {
+        parentNodeIdStr = ((BaseOBObject) parentNodeId).getId().toString();
+      }
+
+      if (isMultiParentTree) {
+        json.put("nodeId", parentNodeIdStr + ID_SEPARATOR + nodeIdStr);
+      } else {
+        json.put("nodeId", nodeIdStr);
+      }
+      addNodeCommonAttributes(entity, bob, json);
+      json.put("_hasChildren", (this.nodeHasChildren(entity, linkToParentProperty, nodeIdProperty,
+          bob, hqlWhereClause)) ? true : false);
+      responseData.put(json);
+      count++;
+      if (count % 100 == 0) {
+        OBDal.getInstance().getSession().clear();
+      }
+
+    }
+    return responseData;
+  }
+
+  /**
+   * Check if a node has children that should be shown in the target treegrid
+   * 
+   * @param entity
+   * @param linkToParentProperty
+   *          property that points to the parent node
+   * @param nodeIdProperty
+   *          property that represents the node id
+   * @param node
+   *          bob with the node properties
+   * @param hqlWhereClause
+   *          where clause to be applied to the children
+   * @return
+   */
+  private boolean nodeHasChildren(Entity entity, Property linkToParentProperty,
+      Property nodeIdProperty, BaseOBObject node, String hqlWhereClause) {
+
+    Object nodeId = node.get(nodeIdProperty.getName());
+    String nodeIdStr = null;
+    if (nodeId instanceof String) {
+      nodeIdStr = (String) nodeId;
+    } else if (nodeId instanceof BaseOBObject) {
+      nodeIdStr = ((BaseOBObject) nodeId).getId().toString();
+    }
+    StringBuilder whereClause = new StringBuilder();
+    whereClause.append(" as e where e." + linkToParentProperty.getName());
+    if (!linkToParentProperty.isPrimitive()) {
+      whereClause.append(".id");
+    }
+    whereClause.append(" = ? ");
+    if (hqlWhereClause != null) {
+      whereClause.append(" and " + hqlWhereClause);
+    }
+    final OBQuery<BaseOBObject> query = OBDal.getInstance().createQuery(entity.getName(),
+        whereClause.toString());
+
+    final List<Object> parameters = new ArrayList<Object>();
+    parameters.add(nodeIdStr);
+    query.setParameters(parameters);
+
+    return query.count() > 0;
+  }
+
+  /**
+   * Updates the parent of a given node a returns its definition in a JSONObject
+   */
+  protected JSONObject moveNode(Map<String, String> parameters, String nodeId, String newParentId,
+      String prevNodeId, String nextNodeId) throws Exception {
+
+    String referencedTableId = parameters.get("referencedTableId");
+    String tabId = parameters.get("tabId");
+
+    Table table = OBDal.getInstance().get(Table.class, referencedTableId);
+    Entity referencedEntity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Tab tab = OBDal.getInstance().get(Tab.class, tabId);
+
+    String hqlWhereClause = tab.getHqlwhereclause();
+    if (hqlWhereClause != null) {
+      hqlWhereClause = this.substituteParameters(hqlWhereClause, parameters);
+    }
+
+    TableTree tableTree = tab.getTableTree();
+    Property linkToParentProperty = getLinkToParentProperty(tableTree);
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+
+    BaseOBObject bob = OBDal.getInstance().get(referencedEntity.getName(), nodeId);
+    BaseOBObject parentBob = null;
+    if (!ROOT_NODE_CLIENT.equals(newParentId)) {
+      parentBob = OBDal.getInstance().get(referencedEntity.getName(), newParentId);
+    }
+    bob.set(linkToParentProperty.getName(), parentBob);
+    OBDal.getInstance().flush();
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+    JSONObject updatedData = toJsonConverter.toJsonObject((BaseOBObject) bob,
+        DataResolvingMode.FULL);
+    addNodeCommonAttributes(entity, bob, updatedData);
+    updatedData.put("parentId", newParentId);
+    updatedData.put("_hasChildren", (this.nodeHasChildren(entity, linkToParentProperty,
+        nodeIdProperty, bob, hqlWhereClause)) ? true : false);
+
+    return updatedData;
+  }
+
+  /**
+   * @param parameters
+   * @param nodeId
+   * @return returns a json object with the definition of a node give its node id
+   */
+  @Override
+  protected JSONObject getJSONObjectByNodeId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String nodeId) throws MultipleParentsException {
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    Table table = null;
+    TableTree tableTree = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      table = tab.getTable();
+      tableTree = tab.getTableTree();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      table = treeReference.getTable();
+      tableTree = treeReference.getTableTreeCategory();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONObject();
+    }
+    // Obtain the recordId based on the nodeId
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+
+    StringBuilder whereClause = new StringBuilder();
+    whereClause.append(" where " + nodeIdProperty.getName());
+    if (!nodeIdProperty.isPrimitive()) {
+      whereClause.append(".id");
+    }
+    whereClause.append(" = ? ");
+    final OBQuery<BaseOBObject> query = OBDal.getInstance().createQuery(entity.getName(),
+        whereClause.toString());
+
+    final List<Object> queryParameters = new ArrayList<Object>();
+    queryParameters.add(nodeId);
+    query.setParameters(queryParameters);
+
+    if (query.count() != 1) {
+      // If the node has several parents, it is not possible to know which node should be returned
+      throw new MultipleParentsException();
+    }
+    BaseOBObject bob = query.uniqueResult();
+    return this.getJSONObjectByRecordId(parameters, datasourceParameters, bob.getId().toString());
+  }
+
+  /**
+   * Method that checks if a node conforms to a hqlWhereClause
+   * 
+   * @param tableTree
+   *          tableTree that defines the tree category that defines the tree
+   * @param nodeId
+   *          id of the node to be checked
+   * @param hqlWhereClause
+   *          hql where clause to be applied
+   * @return
+   */
+  @Override
+  protected boolean nodeConformsToWhereClause(TableTree tableTree, String nodeId,
+      String hqlWhereClause) {
+    if (hqlWhereClause == null || hqlWhereClause.isEmpty()) {
+      return true;
+    }
+    Table table = tableTree.getTable();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+
+    StringBuilder whereClause = new StringBuilder();
+    whereClause.append(" as e where e." + nodeIdProperty.getName());
+    if (!nodeIdProperty.isPrimitive()) {
+      whereClause.append(".id");
+    }
+    whereClause.append(" = ? ");
+    whereClause.append(" and " + hqlWhereClause);
+    final OBQuery<BaseOBObject> query = OBDal.getInstance().createQuery(entity.getName(),
+        whereClause.toString());
+
+    final List<Object> queryParameters = new ArrayList<Object>();
+    queryParameters.add(nodeId);
+    query.setParameters(queryParameters);
+
+    return (query.count() == 1);
+  }
+
+  protected JSONObject getJSONObjectByRecordId(Map<String, String> parameters, String bobId,
+      boolean fillNodeIdAndParentId) {
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    Table table = null;
+    TableTree tableTree = null;
+    String hqlWhereClause = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      table = tab.getTable();
+      tableTree = tab.getTableTree();
+      hqlWhereClause = tab.getHqlwhereclause();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      table = treeReference.getTable();
+      tableTree = treeReference.getTableTreeCategory();
+      hqlWhereClause = treeReference.getHQLSQLWhereClause();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONObject();
+    }
+
+    if (hqlWhereClause != null) {
+      hqlWhereClause = this.substituteParameters(hqlWhereClause, parameters);
+    }
+    Property linkToParentProperty = getLinkToParentProperty(tableTree);
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    JSONObject json = null;
+
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+
+    try {
+      BaseOBObject bob = OBDal.getInstance().get(entity.getName(), bobId);
+      json = toJsonConverter.toJsonObject((BaseOBObject) bob, DataResolvingMode.FULL);
+      if (fillNodeIdAndParentId) {
+        String parentId = null;
+        if (linkToParentProperty.isPrimitive()) {
+          parentId = (String) bob.get(linkToParentProperty.getName());
+        } else {
+          BaseOBObject parent = (BaseOBObject) bob.get(linkToParentProperty.getName());
+          if (parent != null) {
+            parentId = parent.getId().toString();
+          }
+        }
+        if (parentId != null) {
+          json.put("parentId", parentId);
+        } else {
+          json.put("parentId", (String) ROOT_NODE_CLIENT);
+        }
+        Object nodeId = bob.get(nodeIdProperty.getName());
+        String nodeIdStr = null;
+        if (nodeId instanceof String) {
+          nodeIdStr = (String) nodeId;
+        } else if (nodeId instanceof BaseOBObject) {
+          nodeIdStr = ((BaseOBObject) nodeId).getId().toString();
+        }
+        json.put("nodeId", nodeIdStr);
+      }
+      addNodeCommonAttributes(entity, bob, json);
+      json.put("_hasChildren", (this.nodeHasChildren(entity, linkToParentProperty, nodeIdProperty,
+          bob, hqlWhereClause)) ? true : false);
+    } catch (JSONException e) {
+      logger.error("Error on tree datasource", e);
+    }
+    return json;
+  }
+
+  /**
+   * @param parameters
+   * @param nodeId
+   * @return returns a json object with the definition of a node give its record id
+   */
+  @Override
+  protected JSONObject getJSONObjectByRecordId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String bobId) {
+    boolean fillNodeIdAndParentId = true;
+    return getJSONObjectByRecordId(parameters, bobId, fillNodeIdAndParentId);
+  }
+
+  @Override
+  protected JSONArray fetchFilteredNodesForTreesWithMultiParentNodes(
+      Map<String, String> parameters, Map<String, Object> datasourceParameters,
+      TableTree tableTree, List<String> filteredNodes, String hqlTreeWhereClause,
+      String hqlTreeWhereClauseRootNodes, boolean allowNotApplyingWhereClauseToChildren)
+      throws MultipleParentsException, TooManyTreeNodesException {
+
+    Property linkToParentProperty = getLinkToParentProperty(tableTree);
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+    JSONArray responseData = new JSONArray();
+    Map<String, JSONObject> addedNodesMap = new HashMap<String, JSONObject>();
+
+    try {
+
+      for (String nodeRecordId : filteredNodes) {
+        JSONObject node = getJSONObjectByRecordId(parameters, datasourceParameters, nodeRecordId);
+        BasicTreeInfo treeInfo = new BasicTreeInfo(nodeRecordId, node.getString(nodeIdProperty
+            .getName()), node.getString(linkToParentProperty.getName()));
+        List<JSONArray> pathsToRootNodes = buildPathToRootNodes(parameters, treeInfo, tableTree,
+            hqlTreeWhereClause, hqlTreeWhereClauseRootNodes);
+        for (JSONArray pathToRootNode : pathsToRootNodes) {
+          for (int i = 0; i < pathToRootNode.length(); i++) {
+            JSONObject pathNode = pathToRootNode.getJSONObject(i);
+            addedNodesMap.put(pathNode.getString("nodeId"), pathNode);
+          }
+        }
+      }
+
+      // Add the values in the map to responsedata
+      for (String key : addedNodesMap.keySet()) {
+        if (addedNodesMap.get(key).has("filterHit")) {
+          addedNodesMap.get(key).remove("filterHit");
+        } else {
+          addedNodesMap.get(key).put("notFilterHit", true);
+        }
+        responseData.put(addedNodesMap.get(key));
+      }
+    } catch (JSONException e) {
+      logger.error("Error while processing the filtered nodes from the datasource", e);
+    }
+
+    return responseData;
+  }
+
+  private List<JSONArray> buildPathToRootNodes(Map<String, String> parameters,
+      BasicTreeInfo recordInfo, TableTree tableTree, String hqlTreeWhereClause,
+      String hqlTreeWhereClauseRootNodes) throws TooManyTreeNodesException {
+    List<JSONArray> pathsToRootNodes = new ArrayList<JSONArray>();
+    try {
+      String recordId = recordInfo.getRecordId();
+      Property nodeIdProperty = getNodeIdProperty(tableTree);
+      if (isInvalidRoot(recordInfo, tableTree, hqlTreeWhereClause, hqlTreeWhereClauseRootNodes)) {
+        return pathsToRootNodes;
+      }
+      if (isValidRoot(recordInfo, tableTree, hqlTreeWhereClause, hqlTreeWhereClauseRootNodes)) {
+        boolean fillNodeIdAndParentId = false;
+        JSONObject node = getJSONObjectByRecordId(parameters, recordId, fillNodeIdAndParentId);
+        String nodeId = node.getString(nodeIdProperty.getName());
+        node.put("parentId", ROOT_NODE_CLIENT);
+        node.put("nodeId", nodeId);
+        node.put("filterHit", true);
+        JSONArray pathToRootNode = new JSONArray();
+        pathToRootNode.put(node);
+        pathsToRootNodes.add(pathToRootNode);
+        return pathsToRootNodes;
+      }
+      boolean fillNodeIdAndParentId = false;
+      JSONObject node = getJSONObjectByRecordId(parameters, recordId, fillNodeIdAndParentId);
+      String nodeId = node.getString(nodeIdProperty.getName());
+      List<BasicTreeInfo> parentInfoList = getRecordInfoOfParents(parameters, recordInfo,
+          hqlTreeWhereClause, hqlTreeWhereClauseRootNodes);
+      for (BasicTreeInfo parentInfo : parentInfoList) {
+        List<JSONArray> pathsToRootNodesAux = buildPathToRootNodes(parameters, parentInfo,
+            tableTree, hqlTreeWhereClause, hqlTreeWhereClauseRootNodes);
+        for (JSONArray pathToRootNode : pathsToRootNodesAux) {
+          if (pathToRootNode != null && pathToRootNode.length() > 0) {
+            JSONObject lastNode = pathToRootNode.getJSONObject(pathToRootNode.length() - 1);
+            lastNode.put("isOpen", true);
+            String lastNodeId = lastNode.getString("nodeId");
+            JSONObject auxNode = new JSONObject(node.toString());
+            auxNode.put("parentId", lastNodeId);
+            auxNode.put("nodeId", lastNodeId + ID_SEPARATOR + nodeId);
+            auxNode.put("filterHit", true);
+            pathToRootNode.put(auxNode);
+            pathsToRootNodes.add(pathToRootNode);
+          }
+        }
+      }
+    } catch (JSONException e) {
+      logger.error("Error while processing the filtered nodes from the datasource", e);
+    }
+
+    return pathsToRootNodes;
+  }
+
+  private boolean isValidRoot(BasicTreeInfo recordInfo, TableTree tableTree,
+      String hqlTreeWhereClause, String hqlTreeWhereClauseRootNodes) {
+    String nodeId = recordInfo.getNodeId();
+    String parentId = recordInfo.getParentId();
+    if (hqlTreeWhereClauseRootNodes == null) {
+      return ROOT_NODE_CLIENT.equals(parentId);
+    } else {
+      return nodeConformsToWhereClause(tableTree, nodeId, hqlTreeWhereClauseRootNodes);
+    }
+  }
+
+  private boolean isInvalidRoot(BasicTreeInfo recordInfo, TableTree tableTree,
+      String hqlTreeWhereClause, String hqlTreeWhereClauseRootNodes) {
+    String nodeId = recordInfo.getNodeId();
+    String parentId = recordInfo.getParentId();
+    if (hqlTreeWhereClauseRootNodes == null) {
+      return false;
+    } else if (ROOT_NODE_CLIENT.equals(parentId)
+        && !nodeConformsToWhereClause(tableTree, nodeId, hqlTreeWhereClauseRootNodes)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  private List<BasicTreeInfo> getRecordInfoOfParents(Map<String, String> parameters,
+      BasicTreeInfo treeInfo, String hqlWhereClause, String hqlWhereClauseRootNodes)
+      throws TooManyTreeNodesException {
+    List<BasicTreeInfo> treeInfoList = new ArrayList<BasicTreeInfo>();
+    try {
+      List<JSONObject> parentNodes = fetchParentsOfNode(parameters, treeInfo.getParentId(),
+          hqlWhereClause, hqlWhereClauseRootNodes);
+      for (JSONObject parentNode : parentNodes) {
+        treeInfoList.add(new BasicTreeInfo(parentNode.getString("id"), parentNode
+            .getString("nodeId"), parentNode.getString("parentId")));
+      }
+    } catch (JSONException e) {
+      logger.error("Error on tree datasource", e);
+    }
+    return treeInfoList;
+  }
+
+  protected List<JSONObject> fetchParentsOfNode(Map<String, String> parameters, String parentId,
+      String hqlWhereClause, String hqlWhereClauseRootNodes) throws TooManyTreeNodesException {
+    List<JSONObject> parentList = new ArrayList<JSONObject>();
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    Table table = null;
+    TableTree tableTree = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      table = tab.getTable();
+      tableTree = tab.getTableTree();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      table = treeReference.getTable();
+      tableTree = treeReference.getTableTreeCategory();
+    } else {
+      logger
+          .error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new ArrayList<JSONObject>();
+    }
+
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    Property linkToParentProperty = getLinkToParentProperty(tableTree);
+    Property nodeIdProperty = getNodeIdProperty(tableTree);
+
+    StringBuilder whereClause = new StringBuilder();
+    whereClause.append(" as e where ");
+    whereClause.append(" e." + nodeIdProperty.getName());
+    if (!nodeIdProperty.isPrimitive()) {
+      whereClause.append(".id");
+    }
+    whereClause.append(" = ? ");
+
+    final OBQuery<BaseOBObject> query = OBDal.getInstance().createQuery(entity.getName(),
+        whereClause.toString());
+
+    final List<Object> queryParameters = new ArrayList<Object>();
+    queryParameters.add(parentId);
+    query.setParameters(queryParameters);
+
+    final DataToJsonConverter toJsonConverter = OBProvider.getInstance().get(
+        DataToJsonConverter.class);
+
+    // Check if the number of results to be returned is not higher than the defined limit
+    int nResults = query.count();
+    OBContext context = OBContext.getOBContext();
+    int nMaxResults = -1;
+    try {
+      nMaxResults = Integer.parseInt(Preferences.getPreferenceValue("TreeDatasourceFetchLimit",
+          false, context.getCurrentClient(), context.getCurrentOrganization(), context.getUser(),
+          context.getRole(), null));
+    } catch (Exception e) {
+      nMaxResults = 100;
+    }
+    if (nResults > nMaxResults) {
+      throw new TooManyTreeNodesException();
+    }
+    int count = 0;
+    final ScrollableResults scrollableResults = query.scroll(ScrollMode.FORWARD_ONLY);
+    while (scrollableResults.next()) {
+      BaseOBObject bob = (BaseOBObject) scrollableResults.get()[0];
+      final JSONObject json = toJsonConverter.toJsonObject((BaseOBObject) bob,
+          DataResolvingMode.FULL);
+
+      Object nodeId = bob.get(nodeIdProperty.getName());
+      String nodeIdStr = null;
+      if (nodeId instanceof String) {
+        nodeIdStr = (String) nodeId;
+      } else if (nodeId instanceof BaseOBObject) {
+        nodeIdStr = ((BaseOBObject) nodeId).getId().toString();
+      }
+
+      Object parentNodeId = bob.get(linkToParentProperty.getName());
+      String parentNodeIdStr = null;
+      if (parentNodeId instanceof String) {
+        parentNodeIdStr = (String) parentNodeId;
+      } else if (parentNodeId instanceof BaseOBObject) {
+        parentNodeIdStr = ((BaseOBObject) parentNodeId).getId().toString();
+      }
+      try {
+        json.put("nodeId", nodeIdStr);
+        if (parentNodeIdStr == null) {
+          json.put("parentId", ROOT_NODE_CLIENT);
+        } else {
+          json.put("parentId", parentNodeIdStr);
+        }
+      } catch (JSONException e) {
+        logger.error("Error on tree datasource", e);
+      }
+
+      parentList.add(json);
+      count++;
+      if (count % 100 == 0) {
+        OBDal.getInstance().getSession().clear();
+      }
+
+    }
+    return parentList;
+  }
+
+  private class BasicTreeInfo {
+    private String recordId;
+    private String nodeId;
+    private String parentId;
+
+    public BasicTreeInfo(String recordId, String nodeId, String parentId) {
+      this.recordId = recordId;
+      this.nodeId = nodeId;
+      this.parentId = parentId;
+    }
+
+    public String getRecordId() {
+      return this.recordId;
+    }
+
+    public String getNodeId() {
+      return this.nodeId;
+    }
+
+    public String getParentId() {
+      return this.parentId;
+    }
+  }
+
+  @Override
+  protected Map<String, Object> getDatasourceSpecificParams(Map<String, String> parameters) {
+    return new HashMap<String, Object>();
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/TreeDatasourceService.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,972 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2013 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.inject.Inject;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.hibernate.criterion.Restrictions;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.base.exception.OBSecurityException;
+import org.openbravo.base.model.Entity;
+import org.openbravo.base.model.ModelProvider;
+import org.openbravo.base.model.Property;
+import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.client.kernel.ComponentProvider;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.erpCommon.businessUtility.Preferences;
+import org.openbravo.erpCommon.utility.OBMessageUtils;
+import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.model.ad.access.WindowAccess;
+import org.openbravo.model.ad.datamodel.Table;
+import org.openbravo.model.ad.domain.ReferencedTree;
+import org.openbravo.model.ad.ui.Tab;
+import org.openbravo.model.ad.utility.TableTree;
+import org.openbravo.service.datasource.CheckTreeOperationManager.ActionResponse;
+import org.openbravo.service.db.DalConnectionProvider;
+import org.openbravo.service.json.JsonConstants;
+import org.openbravo.service.json.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The TreeDatasourceService is an abstract class that provides a simple way of returning data in
+ * the correct format for a OBTreeGrid client side component using a datasource.
+ * 
+ */
+public abstract class TreeDatasourceService extends DefaultDataSourceService {
+  private static final Logger log = LoggerFactory.getLogger(TreeDatasourceService.class);
+  private static final String JSON_PREFIX = "<SCRIPT>//'\"]]>>isc_JSONResponseStart>>";
+  private static final String JSON_SUFFIX = "//isc_JSONResponseEnd";
+  protected static final String ROOT_NODE_DB = "0";
+  protected static final String ROOT_NODE_CLIENT = "-1";
+  private static final String AD_ORG_TABLE_ID = "155";
+  private static final String ROOT_ORGANIZATION_ID = "0";
+  private static final String SUMMARY_LEVEL_PROPERTY = "summaryLevel";
+  private static final String FOLDER_ICON_SRC = "../web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconFolder.png";
+  private static final String LEAF_ICON_SRC = "../web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.application/images/treegrid/iconNode.png";
+
+  @Inject
+  private DataSourceServiceProvider dataSourceServiceProvider;
+
+  // A CheckTreeOperationManager allows to check if an action on a node is valid before actually
+  // doing it
+  @Inject
+  @Any
+  private Instance<CheckTreeOperationManager> checkTreeOperationManagers;
+
+  /**
+   * This method is called when a new record is created in a tree table. It calls the addNewNode
+   * abstract method, which is implemented in the classes that extend TreeDatasourceService
+   */
+  @Override
+  public final String add(Map<String, String> parameters, String content) {
+    try {
+      // We can't get the bob from DAL, it has not been saved yet
+      JSONObject bobProperties = new JSONObject(parameters.get("jsonBob"));
+      Entity theEntity = getEntity();
+      if (!hasAccess(theEntity, null, false)) {
+        throw new OBException(OBMessageUtils.messageBD("AccessTableNoView"));
+      }
+      addNewNode(bobProperties);
+    } catch (Exception e) {
+      log.error("Error while adding the tree node", e);
+      throw new OBException(e);
+    }
+    // This is called from TreeTablesEventHandler, no need to return anything
+    return "";
+  }
+
+  /**
+   * Classes that extend TreeDatasourceService this method must implement this method to handle the
+   * creation of a node in a tree table
+   */
+  protected abstract void addNewNode(JSONObject bobProperties);
+
+  /**
+   * This method is called when a new record is deleted in a tree table. It calls the deleteNode
+   * abstract method, which is implemented in the classes that extend TreeDatasourceService
+   */
+  @Override
+  public final String remove(Map<String, String> parameters) {
+    try {
+      // We can't get the bob from DAL, it has not been saved yet
+      JSONObject bobProperties = new JSONObject(parameters.get("jsonBob"));
+      Entity theEntity = getEntity();
+      if (!hasAccess(theEntity, null, false)) {
+        throw new OBException(OBMessageUtils.messageBD("AccessTableNoView"));
+      }
+
+      this.deleteNode(bobProperties);
+    } catch (Exception e) {
+      log.error("Error while deleting tree node: ", e);
+      throw new OBException(e);
+    }
+
+    // This is called from TreeTablesEventHandler, no need to return anything
+    return "";
+  }
+
+  /**
+   * Classes that extend TreeDatasourceService this method must implement this method to handle the
+   * deletion of a node in a tree table
+   */
+  protected abstract void deleteNode(JSONObject bobProperties);
+
+  /**
+   * Fetches some tree nodes Two operation modes:
+   * 
+   * - If a criteria is included in the parameters, this method will return the nodes that conform
+   * to the criteria plus all its parent until reaching the root nodes
+   * 
+   * - Otherwise, the child nodes of a given node (its node id included in the parameters) are
+   * returned
+   * 
+   * Either the tabId (when it is called from a tree window) or the treeReferenceId (when called
+   * from a tree reference) must be included in the parameters
+   * 
+   * If the datasource were to return a number of nodes higher than the limit (defined in the
+   * TreeDatasourceFetchLimit preference), an empty data is returned and an error is shown to the
+   * user
+   */
+  @Override
+  public final String fetch(Map<String, String> parameters) {
+    OBContext.setAdminMode(true);
+    final JSONObject jsonResult = new JSONObject();
+
+    try {
+      // If the distinct parameter is included in the parameters, delegate to the default standard
+      // datasource
+      if (parameters.containsKey(JsonConstants.DISTINCT_PARAMETER)) {
+        String tabId = parameters.get("_tabId");
+        String tableId = parameters.get("_tableId");
+        Entity entity = null;
+        if (tabId != null) {
+          Tab tab = OBDal.getInstance().get(Tab.class, tabId);
+          entity = ModelProvider.getInstance().getEntityByTableId(tab.getTable().getId());
+        } else if (tableId != null) {
+          entity = ModelProvider.getInstance().getEntityByTableId(tableId);
+        }
+        DataSourceService dataSource = dataSourceServiceProvider.getDataSource(entity.getName());
+        return dataSource.fetch(parameters);
+      }
+
+      String tabId = parameters.get("tabId");
+      String treeReferenceId = parameters.get("treeReferenceId");
+      Tab tab = null;
+      Table table = null;
+      String hqlTreeWhereClause = null;
+      String hqlTreeWhereClauseRootNodes = null;
+      boolean fromTreeView = true;
+      if (tabId != null) {
+        tab = OBDal.getInstance().get(Tab.class, tabId);
+        table = tab.getTable();
+        hqlTreeWhereClause = tab.getHqlwhereclause();
+        hqlTreeWhereClauseRootNodes = tab.getHQLWhereClauseForRootNodes();
+
+      } else if (treeReferenceId != null) {
+        ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class,
+            treeReferenceId);
+        table = treeReference.getTable();
+        hqlTreeWhereClause = treeReference.getHQLSQLWhereClause();
+        hqlTreeWhereClauseRootNodes = treeReference.getHQLWhereClauseForRootNodes();
+        fromTreeView = false;
+      } else {
+        log.error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+        final JSONObject jsonResponse = new JSONObject();
+        JSONArray responseData = new JSONArray();
+        jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
+        jsonResponse.put(JsonConstants.RESPONSE_DATA, responseData);
+        jsonResponse.put(JsonConstants.RESPONSE_TOTALROWS, 0);
+        jsonResponse.put(JsonConstants.RESPONSE_STARTROW, 0);
+        jsonResponse.put(JsonConstants.RESPONSE_ENDROW, 0);
+        jsonResult.put(JsonConstants.RESPONSE_RESPONSE, jsonResponse);
+        return jsonResult.toString();
+      }
+
+      Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+      if (!hasAccess(entity, tab, fromTreeView)) {
+        return noAccessError().toString();
+      }
+
+      if (hqlTreeWhereClause != null) {
+        hqlTreeWhereClause = this.substituteParameters(hqlTreeWhereClause, parameters);
+      }
+      if (hqlTreeWhereClauseRootNodes != null) {
+        hqlTreeWhereClauseRootNodes = this.substituteParameters(hqlTreeWhereClauseRootNodes,
+            parameters);
+      }
+
+      JSONArray responseData = null;
+      boolean tooManyNodes = false;
+      // Do not consider dummy criteria as valid criteria
+      boolean validCriteria = false;
+      JSONArray criterias = (JSONArray) JsonUtils.buildCriteria(parameters).get("criteria");
+
+      String parentId = parameters.get("parentId");
+
+      for (int i = 0; i < criterias.length(); i++) {
+        JSONObject criteria = criterias.getJSONObject(i);
+        if (!isDummyCriteria(criteria) && !isSubtabCriteria(entity, criteria)
+            && !isParentIdCriteria(criteria) && !isEmptyCriteria(criteria)) {
+          validCriteria = true;
+        } else if (parentId == null && isParentIdCriteria(criteria)) {
+          parentId = criteria.getString("value");
+        }
+      }
+
+      Map<String, Object> datasourceSpecificParams = this.getDatasourceSpecificParams(parameters);
+
+      if (validCriteria && parentId.equals(ROOT_NODE_CLIENT)) {
+
+        try {
+          // Obtain the list of nodes that conforms to the criteria
+          List<String> filteredNodes = getFilteredNodes(table, parameters);
+          if (!filteredNodes.isEmpty()) {
+            // Return the filtered nodes and its parents
+            responseData = fetchFilteredNodes(parameters, datasourceSpecificParams, filteredNodes);
+          } else {
+            responseData = new JSONArray();
+          }
+        } catch (TooManyTreeNodesException e) {
+          tooManyNodes = true;
+        }
+      } else {
+        // Fetch the children of a given node
+        try {
+          responseData = fetchNodeChildren(parameters, datasourceSpecificParams, parentId,
+              hqlTreeWhereClause, hqlTreeWhereClauseRootNodes);
+        } catch (TooManyTreeNodesException e) {
+          tooManyNodes = true;
+        }
+      }
+
+      final JSONObject jsonResponse = new JSONObject();
+      if (tooManyNodes) {
+        responseData = new JSONArray();
+        jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
+        final JSONObject error = new JSONObject();
+        error.put("type", "tooManyNodes");
+        jsonResponse.put(JsonConstants.RESPONSE_ERROR, error);
+        jsonResponse.put(JsonConstants.RESPONSE_ERRORS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
+      } else {
+        jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_SUCCESS);
+      }
+      jsonResponse.put(JsonConstants.RESPONSE_DATA, responseData);
+      jsonResponse.put(JsonConstants.RESPONSE_TOTALROWS, responseData.length());
+      jsonResponse.put(JsonConstants.RESPONSE_STARTROW, 0);
+      jsonResponse.put(JsonConstants.RESPONSE_ENDROW, responseData.length() - 1);
+      jsonResult.put(JsonConstants.RESPONSE_RESPONSE, jsonResponse);
+    } catch (Throwable t) {
+      log.error("Error on tree datasource", t);
+      return JsonUtils.convertExceptionToJson(t);
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+    return jsonResult.toString();
+  }
+
+  protected abstract Map<String, Object> getDatasourceSpecificParams(Map<String, String> parameters);
+
+  private boolean isSubtabCriteria(Entity entity, JSONObject jsonCriteria) {
+    try {
+      if (jsonCriteria.has("criteria")) {
+        JSONArray criteriaArray = (JSONArray) jsonCriteria.get("criteria");
+        if (criteriaArray.length() == 1) {
+          return isSubtabCriteria(entity, criteriaArray.getJSONObject(0));
+        } else {
+          return false;
+        }
+      }
+      if (jsonCriteria.has("fieldName")) {
+        String fieldName = jsonCriteria.getString("fieldName");
+        if (entity.hasProperty(fieldName)) {
+          Property property = entity.getProperty(fieldName);
+          if (property.isParent()) {
+            return true;
+          } else {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      } else {
+        return false;
+      }
+    } catch (JSONException e) {
+      return false;
+    }
+  }
+
+  private boolean isEmptyCriteria(JSONObject jsonCriteria) {
+    try {
+      return jsonCriteria.has("criteria") && jsonCriteria.getJSONArray("criteria").length() == 0;
+    } catch (JSONException e) {
+      return false;
+    }
+  }
+
+  private boolean isDummyCriteria(JSONObject jsonCriteria) {
+    try {
+      if (jsonCriteria.has("criteria")) {
+        JSONArray criteriaArray = (JSONArray) jsonCriteria.get("criteria");
+        if (criteriaArray.length() == 1) {
+          return isDummyCriteria(criteriaArray.getJSONObject(0));
+        } else {
+          return false;
+        }
+      }
+      if (jsonCriteria.has("fieldName") && "_dummy".equals(jsonCriteria.get("fieldName"))) {
+        return true;
+      } else {
+        if (jsonCriteria.has("criteria")) {
+          JSONArray criteriaArray = jsonCriteria.getJSONArray("criteria");
+          if (criteriaArray.length() == 0) {
+            return true;
+          }
+        }
+        return false;
+      }
+    } catch (JSONException e) {
+      return false;
+    }
+  }
+
+  private boolean isParentIdCriteria(JSONObject jsonCriteria) {
+    boolean isParentIdCriteria = false;
+    try {
+      if (jsonCriteria.has("criteria")) {
+        JSONArray criteriaArray = (JSONArray) jsonCriteria.get("criteria");
+        if (criteriaArray.length() == 1) {
+          return isParentIdCriteria(criteriaArray.getJSONObject(0));
+        } else {
+          return false;
+        }
+      }
+      if (jsonCriteria.has("fieldName") && "parentId".equals(jsonCriteria.get("fieldName"))) {
+        isParentIdCriteria = true;
+      }
+    } catch (JSONException e) {
+      return false;
+    }
+    return isParentIdCriteria;
+  }
+
+  /**
+   * Checks if an entity is accessible
+   * 
+   * @param entity
+   *          Entity whose accessibility is to be determined
+   * @param tab
+   *          Tab from where the entity wants to be accessed. Can be null.
+   * @param fromReference
+   *          flag that determines if the entity is being accessed from a reference o from a tree
+   *          grid view
+   * @return true if the entity is accessible, false otherwise
+   */
+  private boolean hasAccess(Entity entity, Tab tab, boolean fromReference) {
+    boolean hasAccessToTable = true;
+    boolean isDerivedReadable = OBContext.getOBContext().getEntityAccessChecker()
+        .isDerivedReadable(entity);
+    try {
+      OBContext.getOBContext().getEntityAccessChecker().checkReadable(entity);
+    } catch (OBSecurityException e) {
+      hasAccessToTable = false;
+    }
+    if (fromReference) {
+      // If accessing the entity from a reference, it is enough for the entity to be derived
+      // readable
+      return hasAccessToTable || isDerivedReadable;
+    }
+    if (hasAccessToTable && tab != null) {
+      // If the tab has been provided, check if the user has access to its window
+      OBCriteria<WindowAccess> qWindowAccess = OBDal.getInstance().createCriteria(
+          WindowAccess.class);
+      qWindowAccess.add(Restrictions.eq(WindowAccess.PROPERTY_WINDOW, tab.getWindow()));
+      qWindowAccess.add(Restrictions.eq(WindowAccess.PROPERTY_ROLE, OBContext.getOBContext()
+          .getRole()));
+      hasAccessToTable = qWindowAccess.count() > 0;
+    }
+    return hasAccessToTable;
+  }
+
+  /**
+   * Given a criteria, return the list of nodes that conforms to the criteria If the number of
+   * returned nodes is too high, throws the TooManyTreeNodesException exception
+   * 
+   * @param table
+   *          tree table being fetched
+   * @param parameters
+   * @return the list of filtered nodes
+   * @throws TooManyTreeNodesException
+   */
+  private List<String> getFilteredNodes(Table table, Map<String, String> parameters)
+      throws TooManyTreeNodesException {
+    List<String> filteredNodes = new ArrayList<String>();
+    Entity entity = ModelProvider.getInstance().getEntityByTableId(table.getId());
+    // Delegate on the default standard datasource to fetch the filtered nodes
+    DataSourceService dataSource = dataSourceServiceProvider.getDataSource(entity.getName());
+    String dsResult = dataSource.fetch(parameters);
+    try {
+      JSONObject jsonDsResult = new JSONObject(dsResult);
+      JSONObject jsonResponse = jsonDsResult.getJSONObject(JsonConstants.RESPONSE_RESPONSE);
+      JSONArray dataArray = jsonResponse.getJSONArray(JsonConstants.RESPONSE_DATA);
+
+      // Check if the number of filtered results has reached the limit
+      // An _endRow parameter is included in the parameters, being equal to the limit amount nodes.
+      // If the number of nodes returned by the default datasource is equals to this limit, throw
+      // the TooManyTreeNodesException exception
+      int nRecords = dataArray.length();
+      OBContext context = OBContext.getOBContext();
+      int nMaxResults = -1;
+      try {
+        nMaxResults = Integer.parseInt(Preferences.getPreferenceValue("TreeDatasourceFetchLimit",
+            false, context.getCurrentClient(), context.getCurrentOrganization(), context.getUser(),
+            context.getRole(), null));
+      } catch (Exception e) {
+        nMaxResults = 1000;
+      }
+      if (nRecords >= nMaxResults) {
+        throw new TooManyTreeNodesException();
+      }
+
+      for (int i = 0; i < nRecords; i++) {
+        JSONObject data = dataArray.getJSONObject(i);
+        String ref = data.getString("$ref");
+        String id = ref.substring(ref.lastIndexOf("/") + 1);
+        filteredNodes.add(id);
+      }
+    } catch (JSONException e) {
+      log.error("Error while getting the filtered nodes from the datasource", e);
+    }
+    return filteredNodes;
+  }
+
+  /**
+   * Explodes the list of filteredNodes to include in the response those nodes plus its parents
+   * 
+   * @param parameters
+   * @param filteredNodes
+   *          list of filtered nodes
+   * @return a JSON array containing the filtered nodes plus all its parents until the root node is
+   *         reached
+   * @throws MultipleParentsException
+   * @throws TooManyTreeNodesException
+   */
+  private JSONArray fetchFilteredNodes(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, List<String> filteredNodes)
+      throws MultipleParentsException, TooManyTreeNodesException {
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    TableTree tableTree = null;
+    String hqlTreeWhereClause = null;
+    String hqlTreeWhereClauseRootNodes = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      tableTree = tab.getTableTree();
+      hqlTreeWhereClause = tab.getHqlwhereclause();
+      hqlTreeWhereClauseRootNodes = tab.getHQLWhereClauseForRootNodes();
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      tableTree = treeReference.getTableTreeCategory();
+      hqlTreeWhereClause = treeReference.getHQLSQLWhereClause();
+      hqlTreeWhereClauseRootNodes = treeReference.getHQLWhereClauseForRootNodes();
+    } else {
+      log.error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return new JSONArray();
+    }
+    if (hqlTreeWhereClause != null) {
+      hqlTreeWhereClause = this.substituteParameters(hqlTreeWhereClause, parameters);
+    }
+    if (hqlTreeWhereClauseRootNodes != null) {
+      hqlTreeWhereClauseRootNodes = this.substituteParameters(hqlTreeWhereClauseRootNodes,
+          parameters);
+    }
+    // If this property is true, the whereclause of the tabs does not need to be apllied to the
+    // non root nodes
+    boolean allowNotApplyingWhereClauseToChildren = !tableTree.isApplyWhereClauseToChildNodes();
+
+    if (tableTree.isHasMultiparentNodes()) {
+      return fetchFilteredNodesForTreesWithMultiParentNodes(parameters, datasourceParameters,
+          tableTree, filteredNodes, hqlTreeWhereClause, hqlTreeWhereClauseRootNodes,
+          allowNotApplyingWhereClauseToChildren);
+    } else {
+      return fetchFilteredNodesForTrueTrees(parameters, datasourceParameters, tableTree,
+          filteredNodes, hqlTreeWhereClause, hqlTreeWhereClauseRootNodes,
+          allowNotApplyingWhereClauseToChildren);
+    }
+
+  }
+
+  private JSONArray fetchFilteredNodesForTrueTrees(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, TableTree tableTree, List<String> filteredNodes,
+      String hqlTreeWhereClause, String hqlTreeWhereClauseRootNodes,
+      boolean allowNotApplyingWhereClauseToChildren) throws MultipleParentsException {
+
+    JSONArray responseData = new JSONArray();
+    Map<String, JSONObject> addedNodesMap = new HashMap<String, JSONObject>();
+
+    try {
+      for (String nodeId : filteredNodes) {
+        JSONObject node = getJSONObjectByRecordId(parameters, datasourceParameters, nodeId);
+        if (!allowNotApplyingWhereClauseToChildren
+            && !this.nodeConformsToWhereClause(tableTree, node.getString("id"), hqlTreeWhereClause)) {
+          // If the node does not conform the where clase, do not include it in the response
+          continue;
+        }
+        JSONObject savedNode = addedNodesMap.get(node.getString("id"));
+        if (hqlTreeWhereClauseRootNodes == null) {
+          // If there is no hqlTreeWhereClauseRootNodes, include all the parents until reaching the
+          // node with parentId ROOT_NODE
+          if (savedNode == null) {
+            // The nodes that conform to the filter will be flagged as filterHit to display them
+            // using a diferent style
+            node.put("filterHit", true);
+            addedNodesMap.put(node.getString("id"), node);
+          } else {
+            savedNode.put("filterHit", true);
+          }
+          while (node.has("parentId")
+              && !ROOT_NODE_CLIENT.equals(node.get("parentId"))
+              && (allowNotApplyingWhereClauseToChildren || this.nodeConformsToWhereClause(
+                  tableTree, node.getString("parentId"), hqlTreeWhereClause))) {
+            nodeId = node.getString("parentId");
+            node = getJSONObjectByNodeId(parameters, datasourceParameters, nodeId);
+            savedNode = addedNodesMap.get(node.getString("id"));
+            if (savedNode == null) {
+              // All the parents will be shown open in the tree grid
+              node.put("isOpen", true);
+              addedNodesMap.put(node.getString("id"), node);
+            } else {
+              savedNode.put("isOpen", true);
+            }
+          }
+        } else {
+          // If a node has hqlTreeWhereClauseRootNodes, we have to make sure that the filtered node
+          // is either a root node or a descendant of it
+          Map<String, JSONObject> preAddedNodesMap = new HashMap<String, JSONObject>();
+          if (savedNode == null) {
+            node.put("filterHit", true);
+            preAddedNodesMap.put(node.getString("id"), node);
+          } else {
+            savedNode.put("filterHit", true);
+          }
+          while (node.has("parentId")
+              && !isRoot(node, hqlTreeWhereClauseRootNodes, tableTree)
+              && (allowNotApplyingWhereClauseToChildren || this.nodeConformsToWhereClause(
+                  tableTree, node.getString("parentId"), hqlTreeWhereClause))) {
+            nodeId = node.getString("parentId");
+            node = getJSONObjectByNodeId(parameters, datasourceParameters, nodeId);
+            savedNode = addedNodesMap.get(node.getString("id"));
+            if (savedNode == null) {
+              node.put("isOpen", true);
+              preAddedNodesMap.put(node.getString("id"), node);
+            } else {
+              savedNode.put("isOpen", true);
+            }
+          }
+          // We have to make sure that the filtered node was not aboute the
+          // root nodes as defined by the hqlTreeWhereClauseRootNodes
+          if (this.nodeConformsToWhereClause(tableTree, node.getString("id"),
+              hqlTreeWhereClauseRootNodes)) {
+            addedNodesMap.putAll(preAddedNodesMap);
+          }
+        }
+        if (allowNotApplyingWhereClauseToChildren
+            || this.nodeConformsToWhereClause(tableTree, node.getString("parentId"),
+                hqlTreeWhereClause)) {
+          node.put("parentId", ROOT_NODE_CLIENT);
+        }
+      }
+
+      // Add the values in the map to responsedata
+      for (String key : addedNodesMap.keySet()) {
+        if (addedNodesMap.get(key).has("filterHit")) {
+          addedNodesMap.get(key).remove("filterHit");
+        } else {
+          addedNodesMap.get(key).put("notFilterHit", true);
+        }
+        responseData.put(addedNodesMap.get(key));
+      }
+    } catch (JSONException e) {
+      log.error("Error while processing the filtered nodes from the datasource", e);
+    }
+
+    return responseData;
+  }
+
+  protected abstract JSONArray fetchFilteredNodesForTreesWithMultiParentNodes(
+      Map<String, String> parameters, Map<String, Object> datasourceParameters,
+      TableTree tableTree, List<String> filteredNodes, String hqlTreeWhereClause,
+      String hqlTreeWhereClauseRootNodes, boolean allowNotApplyingWhereClauseToChildren)
+      throws MultipleParentsException, TooManyTreeNodesException;
+
+  /**
+   * Checks if a node is a root node
+   * 
+   * @param node
+   *          JSON objects that contains the properties of the node
+   * @param hqlTreeWhereClauseRootNodes
+   *          hqlWhereClause that defines the root nodes
+   * @param tableTree
+   *          tableTree that defines the tree category that defines the tree
+   * @return
+   */
+  private boolean isRoot(JSONObject node, String hqlTreeWhereClauseRootNodes, TableTree tableTree) {
+    try {
+      String nodeId = null;
+      String parentId = null;
+      nodeId = node.getString("id");
+      parentId = node.getString("parentId");
+      if (ROOT_NODE_CLIENT.equals(parentId)) {
+        return true;
+      }
+      if (hqlTreeWhereClauseRootNodes != null) {
+        return nodeConformsToWhereClause(tableTree, nodeId, hqlTreeWhereClauseRootNodes);
+      } else {
+        return false;
+      }
+    } catch (JSONException e) {
+      return false;
+    }
+  }
+
+  /**
+   * Method that checks if a node conforms to a hqlWhereClause
+   * 
+   * @param tableTree
+   *          tableTree that defines the tree category that defines the tree
+   * @param nodeId
+   *          id of the node to be checked
+   * @param hqlWhereClause
+   *          hql where clause to be applied
+   * @return
+   */
+  protected abstract boolean nodeConformsToWhereClause(TableTree tableTree, String nodeId,
+      String hqlWhereClause);
+
+  /**
+   * If a where clause contains parameters, substitute the parameter with the actual value
+   * 
+   * @param hqlTreeWhereClause
+   *          the original where clause as defined in the tab/selector
+   * @param parameters
+   * @return the updated where clause, having replaced the parameters with their actual values
+   */
+  protected String substituteParameters(String hqlTreeWhereClause, Map<String, String> parameters) {
+    Pattern pattern = Pattern.compile("@\\S*@");
+    Matcher matcher = pattern.matcher(hqlTreeWhereClause);
+    HashMap<String, String> replacements = new HashMap<String, String>();
+    while (matcher.find()) {
+      String contextPropertyName = hqlTreeWhereClause.substring(matcher.start(), matcher.end());
+      String value = parameters.get(contextPropertyName);
+      replacements.put(contextPropertyName, "'" + value + "'");
+    }
+    String hqlCopy = new String(hqlTreeWhereClause);
+    for (String key : replacements.keySet()) {
+      hqlCopy = hqlCopy.replaceAll(key, replacements.get(key));
+    }
+    return hqlCopy;
+  }
+
+  /**
+   * @param parameters
+   * @param nodeId
+   * @return returns a json object with the definition of a node give its record id
+   */
+  protected abstract JSONObject getJSONObjectByRecordId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String nodeId);
+
+  /**
+   * @param parameters
+   * @param nodeId
+   * @return returns a json object with the definition of a node give its node id
+   */
+  protected abstract JSONObject getJSONObjectByNodeId(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String nodeId) throws MultipleParentsException;
+
+  /**
+   * 
+   * @param parameters
+   * @param parentId
+   *          id of the node whose children are to be retrieved
+   * @param hqlWhereClause
+   *          hql where clase of the tab/selector
+   * @param hqlWhereClauseRootNodes
+   *          hql where clause that define what nodes are roots
+   * @return
+   * @throws JSONException
+   * @throws TooManyTreeNodesException
+   *           if the number of returned nodes were to be too high
+   */
+  protected abstract JSONArray fetchNodeChildren(Map<String, String> parameters,
+      Map<String, Object> datasourceParameters, String parentId, String hqlWhereClause,
+      String hqlWhereClauseRootNodes) throws JSONException, TooManyTreeNodesException;
+
+  @Override
+  /** This method is called when a node is reparented
+   * @param parameters
+   * @param content json objects containing the definition of the updated node(s)
+   * @return a valid response that contains the definition of the updated node(s)
+   */
+  public final String update(Map<String, String> parameters, String content) {
+    OBContext.setAdminMode(true);
+
+    String response = null;
+    try {
+      final JSONObject jsonObject = new JSONObject(content);
+      if (content == null) {
+        return "";
+      }
+      // These two parameters define the position where the node should be placed among its peer
+      // nodes
+      String prevNodeId = parameters.get("prevNodeId");
+      String nextNodeId = parameters.get("nextNodeId");
+      if (jsonObject.has("data")) {
+        JSONObject data = jsonObject.getJSONObject("data");
+        JSONObject oldValues = jsonObject.getJSONObject("oldValues");
+        response = processNodeMovement(parameters, data, oldValues, prevNodeId, nextNodeId);
+      } else if (jsonObject.has("transaction")) {
+        // If more than one nodes are moved at the same time, we need to handle a transaction
+        JSONArray jsonResultArray = new JSONArray();
+        JSONObject transaction = jsonObject.getJSONObject("transaction");
+        JSONArray operations = transaction.getJSONArray("operations");
+        for (int i = 0; i < operations.length(); i++) {
+          JSONObject operation = operations.getJSONObject(i);
+          JSONObject data = operation.getJSONObject("data");
+          JSONObject oldValues = operation.getJSONObject("oldValues");
+          jsonResultArray.put(processNodeMovement(parameters, data, oldValues, prevNodeId,
+              nextNodeId));
+        }
+        response = JSON_PREFIX + jsonResultArray.toString() + JSON_SUFFIX;
+      }
+    } catch (Exception e) {
+      log.error("Error while moving tree node", e);
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+    return response;
+  }
+
+  /**
+   * 
+   * @param parameters
+   * @param data
+   *          updated values of the node, including its new parent
+   * @param oldValues
+   *          previous values of the node, including its previous parent
+   * @param prevNodeId
+   * @param nextNodeId
+   *          new position of the node amont its peers
+   * @return
+   * @throws Exception
+   */
+  private String processNodeMovement(Map<String, String> parameters, JSONObject data,
+      JSONObject oldValues, String prevNodeId, String nextNodeId) throws Exception {
+    String nodeId = data.getString("id");
+    String newParentId = data.getString("parentId");
+
+    JSONObject jsonResult = new JSONObject();
+    JSONObject jsonResponse = new JSONObject();
+    JSONArray dataResponse = new JSONArray();
+
+    String tabId = parameters.get("tabId");
+    String treeReferenceId = parameters.get("treeReferenceId");
+    Tab tab = null;
+    TableTree tableTree = null;
+    if (tabId != null) {
+      tab = OBDal.getInstance().get(Tab.class, tabId);
+      tableTree = tab.getTableTree();
+      if (!hasAccess(tab.getTable().getEntity(), tab, false)) {
+        return noAccessError().toString();
+      }
+    } else if (treeReferenceId != null) {
+      ReferencedTree treeReference = OBDal.getInstance().get(ReferencedTree.class, treeReferenceId);
+      tableTree = treeReference.getTableTreeCategory();
+    } else {
+      log.error("A request to the TreeDatasourceService must include the tabId or the treeReferenceId parameter");
+      return null;
+    }
+
+    String tableName = tableTree.getTable().getName();
+    CheckTreeOperationManager ctom = null;
+    try {
+      ctom = checkTreeOperationManagers.select(new ComponentProvider.Selector(tableName)).get();
+    } catch (UnsatisfiedResolutionException e) {
+      // Controlled exception, there aren't any CheckTreeOperationManager
+    }
+    boolean success = true;
+    String messageType = null;
+    String message = null;
+    if (ctom != null) {
+      // Check if the node movement is allowed
+      ActionResponse actionResponse = ctom.checkNodeMovement(parameters, nodeId, newParentId,
+          prevNodeId, nextNodeId);
+      success = actionResponse.isSuccess();
+      messageType = actionResponse.getMessageType();
+      message = actionResponse.getMessage();
+    }
+
+    // Move it
+    if (success) {
+      JSONObject updatedData = moveNode(parameters, nodeId, newParentId, prevNodeId, nextNodeId);
+      if (updatedData != null) {
+        dataResponse.put(updatedData);
+      } else {
+        dataResponse.put(data);
+      }
+      jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_SUCCESS);
+    } else {
+      // These node movement is not valid, it has to be reverted in the client
+      oldValues.put("revertMovement", true);
+      dataResponse.put(oldValues);
+      jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
+    }
+
+    if (messageType != null && message != null) {
+      JSONObject jsonMessage = new JSONObject();
+      jsonMessage.put("messageType", messageType);
+      jsonMessage.put("message", message);
+      jsonResponse.put("message", jsonMessage);
+    }
+    jsonResponse.put(JsonConstants.RESPONSE_DATA, dataResponse);
+    jsonResponse.put(JsonConstants.RESPONSE_STARTROW, 0);
+    jsonResponse.put(JsonConstants.RESPONSE_ENDROW, 0);
+    jsonResponse.put(JsonConstants.RESPONSE_TOTALROWS, 1);
+    jsonResult.put(JsonConstants.RESPONSE_RESPONSE, jsonResponse);
+    return jsonResult.toString();
+  }
+
+  protected abstract JSONObject moveNode(Map<String, String> parameters, String nodeId,
+      String newParentId, String prevNodeId, String nextNodeId) throws Exception;
+
+  /**
+   * Exception thrown when an operation can not be done upon a node that has several parents
+   */
+  protected class MultipleParentsException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+  }
+
+  /**
+   * Exception thrown when the number of records returned by the datasource is higher than the
+   * defined limit
+   */
+  protected class TooManyTreeNodesException extends Exception {
+    private static final long serialVersionUID = 1L;
+  }
+
+  protected Entity getEntity(JSONObject bobProperties) throws JSONException {
+    String entityName = bobProperties.getString("_entity");
+    return ModelProvider.getInstance().getEntity(entityName);
+  }
+
+  private JSONObject noAccessError() {
+    JSONObject jsonResult = new JSONObject();
+    JSONObject jsonResponse = new JSONObject();
+    JSONObject jsonMessage = new JSONObject();
+    try {
+      jsonMessage.put("messageType", "error");
+      jsonMessage.put(
+          "message",
+          Utility.messageBD(new DalConnectionProvider(false), "AccessTableNoView", OBContext
+              .getOBContext().getLanguage().getLanguage()));
+      jsonResponse.put("message", jsonMessage);
+      jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
+      jsonResponse.put(JsonConstants.RESPONSE_DATA, new JSONArray());
+      jsonResponse.put(JsonConstants.RESPONSE_STARTROW, 0);
+      jsonResponse.put(JsonConstants.RESPONSE_ENDROW, 0);
+      jsonResponse.put(JsonConstants.RESPONSE_TOTALROWS, 0);
+      jsonResult.put(JsonConstants.RESPONSE_RESPONSE, jsonResponse);
+    } catch (JSONException e) {
+      log.error("Error generating no access message", e);
+    }
+
+    return jsonResult;
+  }
+
+  /**
+   * Adds to a json representation of a node some attributes that are common to all trees regardless
+   * of its particular implementation
+   * 
+   * @param entity
+   *          entity of the table associated with the tree
+   * @param bob
+   *          BaseOBObject representation of the node
+   * @param node
+   *          JSONObject representation of the node. The common attributes will be added to this
+   *          object
+   */
+  protected final void addNodeCommonAttributes(Entity entity, BaseOBObject bob, JSONObject node) {
+    try {
+      if (!canAcceptDrop(entity, bob)) {
+        node.put("canBeParentNode", false);
+        node.put("icon", LEAF_ICON_SRC);
+        node.put("showDropIcon", false);
+        node.put("showOpenIcon", false);
+      } else {
+        node.put("icon", FOLDER_ICON_SRC);
+        node.put("showDropIcon", true);
+
+      }
+    } catch (JSONException e) {
+      log.error("Error while adding the node common attributes", e);
+    }
+  }
+
+  /**
+   * 
+   * @param entity
+   *          entity of the tree being fetched
+   * @param bob
+   *          node whose disponibility to accept drops is to be determined
+   * @return true if the node can accept dropped records, false otherwise
+   */
+  private boolean canAcceptDrop(Entity entity, BaseOBObject bob) {
+    if (AD_ORG_TABLE_ID.equals(entity.getTableId()) && ROOT_ORGANIZATION_ID.equals(bob.getId())) {
+      // Special case, * organization has summaryField = false but can accept drop
+      return true;
+    }
+    boolean canAcceptDrop = true;
+    if (entity.hasProperty(SUMMARY_LEVEL_PROPERTY)
+        && (Boolean) bob.get(SUMMARY_LEVEL_PROPERTY) == false) {
+      canAcceptDrop = false;
+    }
+    // else {} If the entity does not have a summaryLevel property then all its nodes can accept
+    // drop
+    return canAcceptDrop;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/TreeDatasourceService_data.xsql	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.0  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2012 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ *************************************************************************
+-->
+<SqlClass name="TreeDatasourceServiceData" package="org.openbravo.service.datasource">
+  <SqlClassComment></SqlClassComment>
+     <SqlMethod name="select" type="preparedStatement" return="multiple">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      <![CDATA[
+        select 1 as name from dual
+      ]]>
+    </Sql>
+  </SqlMethod>
+  <SqlMethod name="reparentChildrenADTree" type="preparedStatement" return="rowcount">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      UPDATE ad_treenode set parent_id = ?
+      WHERE ad_tree_id = ?
+      AND parent_id= ?
+    </Sql>
+    <Parameter name="newParentId"/>
+    <Parameter name="adTreeId"/>
+    <Parameter name="oldParentId"/>
+  </SqlMethod>
+  <SqlMethod name="reparentChildrenLinkToParent" type="preparedStatement" return="rowcount">
+    <SqlMethodComment></SqlMethodComment>
+    <Sql>
+      UPDATE tableName set parentColumn = ?
+      WHERE parentColumn = ?
+    </Sql>
+    <Parameter name="tableName" optional="true" type="replace" after="UPDATE " text="tableName"/>
+    <Parameter name="parentColumn" optional="true" type="replace" after="set " text="parentColumn"/>
+    <Parameter name="newParentId"/>
+    <Parameter name="parentColumn" optional="true" type="replace" after="WHERE " text="parentColumn"/>
+    <Parameter name="oldParentId"/>
+  </SqlMethod>  
+</SqlClass>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/treeChecks/AssetsTreeOperationManager.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource.treeChecks;
+
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.openbravo.client.kernel.ComponentProvider.Qualifier;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.erpCommon.utility.OBMessageUtils;
+import org.openbravo.model.financialmgmt.assetmgmt.Asset;
+import org.openbravo.service.datasource.CheckTreeOperationManager;
+
+@ApplicationScoped
+@Qualifier("FinancialMgmtAsset")
+public class AssetsTreeOperationManager extends CheckTreeOperationManager {
+
+  /**
+   * Only allows to move an asset if it is not static
+   */
+  @Override
+  public ActionResponse checkNodeMovement(Map<String, String> parameters, String nodeId,
+      String newParentId, String prevNodeId, String nextNodeId) {
+    Asset asset = OBDal.getInstance().get(Asset.class, nodeId);
+    if (asset.isStatic()) {
+      return new ActionResponse(false, "error", OBMessageUtils.messageBD("StaticRecord"));
+    } else {
+      return new ActionResponse(true);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/treeChecks/MenuTreeOperationManager.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,52 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource.treeChecks;
+
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.openbravo.client.kernel.ComponentProvider.Qualifier;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.erpCommon.utility.OBMessageUtils;
+import org.openbravo.model.ad.module.Module;
+import org.openbravo.model.ad.ui.Menu;
+import org.openbravo.service.datasource.CheckTreeOperationManager;
+
+@ApplicationScoped
+@Qualifier("ADMenu")
+public class MenuTreeOperationManager extends CheckTreeOperationManager {
+
+  /**
+   * Only allows to move a node if it belong to a module that is in development
+   */
+  @Override
+  public ActionResponse checkNodeMovement(Map<String, String> parameters, String nodeId,
+      String newParentId, String prevNodeId, String nextNodeId) {
+    Menu menuEntry = OBDal.getInstance().get(Menu.class, nodeId);
+    Module module = menuEntry.getModule();
+    if (module != null && !module.isInDevelopment()) {
+      return new ActionResponse(false, "error",
+          OBMessageUtils.messageBD("OBSERDS_ReparentNotInDevTreeNode"));
+    } else {
+      return new ActionResponse(true);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/treeChecks/OrganizationTreeOperationManager.java	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License.
+ * The Original Code is Openbravo ERP.
+ * The Initial Developer of the Original Code is Openbravo SLU
+ * All portions are Copyright (C) 2014 Openbravo SLU
+ * All Rights Reserved.
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.datasource.treeChecks;
+
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.openbravo.client.kernel.ComponentProvider.Qualifier;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.erpCommon.utility.OBMessageUtils;
+import org.openbravo.model.common.enterprise.Organization;
+import org.openbravo.service.datasource.CheckTreeOperationManager;
+
+@ApplicationScoped
+@Qualifier("Organization")
+public class OrganizationTreeOperationManager extends CheckTreeOperationManager {
+
+  /**
+   * Only allows to move a node if it belong to a organization that is not set as ready
+   */
+  @Override
+  public ActionResponse checkNodeMovement(Map<String, String> parameters, String nodeId,
+      String newParentId, String prevNodeId, String nextNodeId) {
+    Organization organization = OBDal.getInstance().get(Organization.class, nodeId);
+    if (organization.isReady()) {
+      return new ActionResponse(false, "error", OBMessageUtils.messageBD("OrgIsReady"));
+    } else {
+      return new ActionResponse(true);
+    }
+  }
+}
--- a/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Wed Mar 05 22:49:04 2014 +0530
+++ b/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Wed Mar 05 23:13:24 2014 +0100
@@ -11,7 +11,7 @@
  * under the License.
  * The Original Code is Openbravo ERP.
  * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2011-2013 Openbravo SLU
+ * All portions are Copyright (C) 2011-2014 Openbravo SLU
  * All Rights Reserved.
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -74,6 +74,46 @@
   }
 });
 
+isc.Tree.addProperties({
+  _original_getLoadState: isc.Tree.getPrototype().getLoadState,
+  getLoadState: function (node) {
+    if (node._hasChildren === false) {
+      return isc.Tree.LOADED;
+    } else {
+      return this._original_getLoadState(node);
+    }
+  }
+});
+
+isc.ResultTree.addProperties({
+  _original_loadChildrenReply: isc.ResultTree.getPrototype().loadChildrenReply,
+  loadChildrenReply: function (dsResponse, data, request) {
+    var target = window[this.componentId];
+
+    if (dsResponse && dsResponse.error && dsResponse.error.type === 'tooManyNodes') {
+      if (target && target.view) {
+        target.view.messageBar.setMessage('error', null, OB.I18N.getLabel('OBUIAPP_TooManyNodes'));
+      }
+      return;
+    }
+
+    this._original_loadChildrenReply(dsResponse, data, request);
+    if (request && request.params && request.params.selectedRecords) {
+      if (target && target.treeDataArrived) {
+        target.treeDataArrived();
+      }
+    }
+  },
+  _original_indexOf: isc.ResultTree.getPrototype().indexOf,
+  indexOf: function (node, a, b, c, d) {
+    if (!node) {
+      return -1;
+    } else {
+      return this._original_indexOf(node, a, b, c, d);
+    }
+  }
+});
+
 isc.ResultSet.addProperties({
   _original_removeCacheData: isc.ResultSet.getPrototype().removeCacheData,
   removeCacheData: function (updateData) {
@@ -120,7 +160,6 @@
   }
 });
 
-
 isc.Canvas.addProperties({
 
   // make sure that the datasources are also destroyed
--- a/src-db/database/model/functions/AD_GET_ORG_LE_BU.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_GET_ORG_LE_BU.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -19,7 +19,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2012 Openbravo SLU
+* All portions are Copyright (C) 2012-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/
@@ -47,7 +47,7 @@
       WHERE hh.node_id=v_org_header_id
         AND ad_org.isready='Y'
         AND EXISTS (SELECT 1 FROM ad_tree
-                    WHERE ad_tree.treetype='OO'
+                    WHERE ad_tree.ad_table_id='155'
                       AND hh.ad_tree_id=ad_tree.ad_tree_id
                       AND hh.ad_client_id=ad_tree.ad_client_id);
     END LOOP;
@@ -64,7 +64,7 @@
       WHERE hh.node_id=v_org_header_id
         AND ad_org.isready='Y'
         AND EXISTS (SELECT 1 FROM ad_tree
-                    WHERE ad_tree.treetype='OO'
+                    WHERE ad_tree.ad_table_id='155'
                       AND hh.ad_tree_id=ad_tree.ad_tree_id
                       AND hh.ad_client_id=ad_tree.ad_client_id);
     END LOOP;
@@ -81,7 +81,7 @@
       WHERE hh.node_id=v_org_header_id
         AND ad_org.isready='Y'
         AND EXISTS (SELECT 1 FROM ad_tree
-                    WHERE ad_tree.treetype='OO'
+                    WHERE ad_tree.ad_table_id='155'
                       AND hh.ad_tree_id=ad_tree.ad_tree_id
                       AND hh.ad_client_id=ad_tree.ad_client_id);
     END LOOP;
--- a/src-db/database/model/functions/AD_ORGTYPE_ISLE_ISBU.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORGTYPE_ISLE_ISBU.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -13,7 +13,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2009 Openbravo SLU
+* All portions are Copyright (C) 2009-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/
@@ -40,7 +40,7 @@
                    WHERE pp.node_id = hh.parent_id
                    AND hh.ad_tree_id = pp.ad_tree_id
                    AND hh.parent_id=ad_org.ad_org_id 
-                   AND  EXISTS (SELECT 1 FROM ad_tree WHERE treetype='OO' AND hh.Ad_tree_id=ad_tree.ad_tree_id))
+                   AND  EXISTS (SELECT 1 FROM ad_tree WHERE ad_table_id='155' AND hh.Ad_tree_id=ad_tree.ad_tree_id))
   )
 
   LOOP
@@ -71,7 +71,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   );
                   
--- a/src-db/database/model/functions/AD_ORGTYPE_ISTRANS_ALLOWED.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORGTYPE_ISTRANS_ALLOWED.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -13,7 +13,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2008 Openbravo SLU
+* All portions are Copyright (C) 2008-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/      
@@ -63,7 +63,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   );
       
--- a/src-db/database/model/functions/AD_ORG_CHK_CALENDAR.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORG_CHK_CALENDAR.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -13,7 +13,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2008-2009 Openbravo SLU
+* All portions are Copyright (C) 2008-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/      
@@ -68,7 +68,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   AND IsReady='Y'
                   );
--- a/src-db/database/model/functions/AD_ORG_CHK_READY.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORG_CHK_READY.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -16,7 +16,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2008 Openbravo SLU
+* All portions are Copyright (C) 2008-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/
@@ -41,7 +41,7 @@
                 FROM ad_tree, ad_org
                 WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                 AND ad_tree.ad_client_id=t.ad_client_id
-                AND ad_tree.treetype='OO'
+                AND ad_tree.ad_table_id='155'
                 AND t.ad_tree_id=ad_tree.ad_tree_id
                 );
     
--- a/src-db/database/model/functions/AD_ORG_CHK_SCHEMAS.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORG_CHK_SCHEMAS.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -13,7 +13,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2008-2009 Openbravo SLU
+* All portions are Copyright (C) 2008-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/      
@@ -57,7 +57,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   AND AD_Org.IsReady='Y'
                   );
--- a/src-db/database/model/functions/AD_ORG_GETCALENDAROWNER.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORG_GETCALENDAROWNER.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -16,7 +16,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2008 Openbravo SLU
+* All portions are Copyright (C) 2008-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/
@@ -49,7 +49,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   );
 
--- a/src-db/database/model/functions/AD_ORG_GETPERIODCONTROLALLOW.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/functions/AD_ORG_GETPERIODCONTROLALLOW.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -16,7 +16,7 @@
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
-* All portions are Copyright (C) 2009 Openbravo SLU
+* All portions are Copyright (C) 2009-2014 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 ************************************************************************/
@@ -49,7 +49,7 @@
                   FROM ad_tree, ad_org
                   WHERE ad_tree.ad_client_id = ad_org.ad_client_id
                   AND ad_tree.ad_client_id=t.ad_client_id
-                  AND ad_tree.treetype='OO'
+                  AND ad_tree.ad_table_id='155'
                   AND t.ad_tree_id=ad_tree.ad_tree_id
                   );
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-db/database/model/tables/AD_REF_TREE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+  <database name="TABLE AD_REF_TREE">
+    <table name="AD_REF_TREE" primaryKey="AD_REF_TREE_KEY">
+      <column name="AD_REF_TREE_ID" primaryKey="true" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_CLIENT_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_ORG_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISACTIVE" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_REFERENCE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_TABLE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_COLUMN_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="WHERECLAUSE" primaryKey="false" required="false" type="VARCHAR" size="2000" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="VALUEFIELD_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="DISPLAYFIELD_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_TABLE_TREE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="WHERECLAUSEROOTNODES" primaryKey="false" required="false" type="VARCHAR" size="2000" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_MODULE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <foreign-key foreignTable="AD_CLIENT" name="AD_REF_TREE_AD_CLIENT">
+        <reference local="AD_CLIENT_ID" foreign="AD_CLIENT_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_ORG" name="AD_REF_TREE_AD_ORG">
+        <reference local="AD_ORG_ID" foreign="AD_ORG_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_COLUMN" name="AD_REF_TREE_COL" onDelete="cascade">
+        <reference local="AD_COLUMN_ID" foreign="AD_COLUMN_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_REF_TREE_FIELD" name="AD_REF_TREE_DSPFLD">
+        <reference local="DISPLAYFIELD_ID" foreign="AD_REF_TREE_FIELD_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_MODULE" name="AD_REF_TREE_MODULE" onDelete="cascade">
+        <reference local="AD_MODULE_ID" foreign="AD_MODULE_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_TABLE" name="AD_REF_TREE_TABLE" onDelete="cascade">
+        <reference local="AD_TABLE_ID" foreign="AD_TABLE_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_TABLE_TREE" name="AD_REF_TREE_TABTREE" onDelete="cascade">
+        <reference local="AD_TABLE_TREE_ID" foreign="AD_TABLE_TREE_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_REF_TREE_FIELD" name="AD_REF_TREE_VALFLD">
+        <reference local="VALUEFIELD_ID" foreign="AD_REF_TREE_FIELD_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_REFERENCE" name="AD_REFERENCE_REFTREE" onDelete="cascade">
+        <reference local="AD_REFERENCE_ID" foreign="AD_REFERENCE_ID"/>
+      </foreign-key>
+      <unique name="AD_REF_TREE_UNIQTREEREF">
+        <unique-column name="AD_REFERENCE_ID"/>
+      </unique>
+      <check name="AD_REF_TREE_ISACTIVE_CHK"><![CDATA[ISACTIVE IN ('Y', 'N')]]></check>
+    </table>
+  </database>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-db/database/model/tables/AD_REF_TREE_FIELD.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+  <database name="TABLE AD_REF_TREE_FIELD">
+    <table name="AD_REF_TREE_FIELD" primaryKey="AD_REF_TREE_FIELD_KEY">
+      <column name="AD_REF_TREE_FIELD_ID" primaryKey="true" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_REF_TREE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_CLIENT_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_ORG_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_MODULE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="NAME" primaryKey="false" required="true" type="NVARCHAR" size="60" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="PROPERTY" primaryKey="false" required="false" type="VARCHAR" size="255" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISCENTRALLYMAINTAINED" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="SORT" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="FILTER" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="SEARCHINSUGGESTIONBOX" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="SHOWINGRID" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="SORTNO" primaryKey="false" required="true" type="DECIMAL" size="10,0" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISACTIVE" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="SHOWINPICKLIST" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <foreign-key foreignTable="AD_MODULE" name="AD_REFTREE_F_AD_MODULE">
+        <reference local="AD_MODULE_ID" foreign="AD_MODULE_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_CLIENT" name="AD_REFTREE_F_CLIENT">
+        <reference local="AD_CLIENT_ID" foreign="AD_CLIENT_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_ORG" name="AD_REFTREE_F_ORG">
+        <reference local="AD_ORG_ID" foreign="AD_ORG_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_REF_TREE" name="AD_REFTREE_F_REFTREE" onDelete="cascade">
+        <reference local="AD_REF_TREE_ID" foreign="AD_REF_TREE_ID"/>
+      </foreign-key>
+      <index name="AD_REFTREEF_TREEREF_IDX" unique="false">
+        <index-column name="AD_REF_TREE_ID"/>
+      </index>
+      <check name="AD_REFTREE_F_CM_CHECK"><![CDATA[ISCENTRALLYMAINTAINED IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_FILTER_CHECK"><![CDATA[FILTER IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_ISACTIVE_CHECK"><![CDATA[ISACTIVE IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_SBOX_CHECK"><![CDATA[SEARCHINSUGGESTIONBOX IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_SHOWINGRID_CHECK"><![CDATA[SHOWINGRID IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_SHOWINPICK_CHK"><![CDATA[SHOWINPICKLIST IN ('Y', 'N')]]></check>
+      <check name="AD_REFTREE_F_SORT_CHECK"><![CDATA[SORT IN ('Y', 'N')]]></check>
+    </table>
+  </database>
--- a/src-db/database/model/tables/AD_TAB.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/tables/AD_TAB.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -169,6 +169,14 @@
         <default/>
         <onCreateDefault/>
       </column>
+      <column name="AD_TABLE_TREE_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="HQLTREEWHERECLAUSE" primaryKey="false" required="false" type="VARCHAR" size="2000" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
       <column name="DISABLE_PARENT_KEY_PROPERTY" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
         <default><![CDATA[N]]></default>
         <onCreateDefault><![CDATA['N']]></onCreateDefault>
@@ -203,6 +211,9 @@
       <foreign-key foreignTable="AD_TAB" name="AD_TAB_INCLUDED_TAB">
         <reference local="INCLUDED_TAB_ID" foreign="AD_TAB_ID"/>
       </foreign-key>
+      <foreign-key foreignTable="AD_TABLE_TREE" name="AD_TAB_TABLETREE_FK">
+        <reference local="AD_TABLE_TREE_ID" foreign="AD_TABLE_TREE_ID"/>
+      </foreign-key>
       <foreign-key foreignTable="AD_TABLE" name="AD_TABLE_TAB">
         <reference local="AD_TABLE_ID" foreign="AD_TABLE_ID"/>
       </foreign-key>
@@ -212,6 +223,9 @@
       <index name="AD_TAB_TABLE" unique="false">
         <index-column name="AD_TABLE_ID"/>
       </index>
+      <index name="AD_TAB_TABLETREE_FK" unique="false">
+        <index-column name="AD_TABLE_TREE_ID"/>
+      </index>
       <index name="AD_TAB_WINDOW" unique="false">
         <index-column name="AD_WINDOW_ID"/>
       </index>
--- a/src-db/database/model/tables/AD_TABLE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/tables/AD_TABLE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -133,6 +133,10 @@
         <default/>
         <onCreateDefault/>
       </column>
+      <column name="ISTREE" primaryKey="false" required="false" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault><![CDATA['N']]></onCreateDefault>
+      </column>
       <foreign-key foreignTable="OBSERDS_DATASOURCE" name="AD_COLUMN_DATASOURCE">
         <reference local="OBSERDS_DATASOURCE_ID" foreign="OBSERDS_DATASOURCE_ID"/>
       </foreign-key>
@@ -176,6 +180,7 @@
       <check name="AD_TABLE_ISFULLYAUDITED_CHK2"><![CDATA[(ISFULLYAUDITED = 'N') OR (UPPER((TABLENAME)) <> 'AD_AUDIT_TRAIL')]]></check>
       <check name="AD_TABLE_ISHIGHVOLUME_CHK"><![CDATA[ISHIGHVOLUME IN ('Y', 'N')]]></check>
       <check name="AD_TABLE_ISSECUR_YENABLED_CHK"><![CDATA[ISSECURITYENABLED IN ('Y', 'N')]]></check>
+      <check name="AD_TABLE_ISTREE_CHK"><![CDATA[ISTREE IN ('Y', 'N')]]></check>
       <check name="AD_TABLE_ISVIEW_CHK"><![CDATA[ISVIEW IN ('Y', 'N')]]></check>
     </table>
   </database>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-db/database/model/tables/AD_TABLE_TREE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -0,0 +1,114 @@
+<?xml version="1.0"?>
+  <database name="TABLE AD_TABLE_TREE">
+    <table name="AD_TABLE_TREE" primaryKey="AD_TABLETREE_KEY">
+      <column name="AD_TABLE_TREE_ID" primaryKey="true" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_CLIENT_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_ORG_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISACTIVE" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="CREATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATED" primaryKey="false" required="true" type="TIMESTAMP" size="7" autoIncrement="false">
+        <default><![CDATA[SYSDATE]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="UPDATEDBY" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_TABLE_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="LINKTOPARENTCOLUMN" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="NODEIDCOLUMN" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="HASMULTIPARENTNODES" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="AD_MODULE_ID" primaryKey="false" required="true" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="APPLYWHERECLAUSETOCHILDNODES" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="NAME" primaryKey="false" required="true" type="VARCHAR" size="200" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISPARENTSELECTIONALLOWED" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="ISORDERED" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="TREESTRUCTURE" primaryKey="false" required="false" type="VARCHAR" size="60" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="OBSERDS_DATASOURCE_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
+      <column name="ISHANDLENODESMANUALLY" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[N]]></default>
+        <onCreateDefault/>
+      </column>
+      <column name="ISMAINTREE" primaryKey="false" required="true" type="CHAR" size="1" autoIncrement="false">
+        <default><![CDATA[Y]]></default>
+        <onCreateDefault><![CDATA['Y']]></onCreateDefault>
+      </column>
+      <foreign-key foreignTable="AD_CLIENT" name="AD_TABLETREE_AD_CLIENT">
+        <reference local="AD_CLIENT_ID" foreign="AD_CLIENT_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_COLUMN" name="AD_TABLETREE_AD_COLPAR">
+        <reference local="LINKTOPARENTCOLUMN" foreign="AD_COLUMN_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_COLUMN" name="AD_TABLETREE_AD_IDCOL">
+        <reference local="NODEIDCOLUMN" foreign="AD_COLUMN_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_ORG" name="AD_TABLETREE_AD_ORG">
+        <reference local="AD_ORG_ID" foreign="AD_ORG_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_TABLE" name="AD_TABLETREE_AD_TABLE" onDelete="cascade">
+        <reference local="AD_TABLE_ID" foreign="AD_TABLE_ID"/>
+      </foreign-key>
+      <foreign-key foreignTable="AD_MODULE" name="AD_TABLTREE_AD_MODULE">
+        <reference local="AD_MODULE_ID" foreign="AD_MODULE_ID"/>
+      </foreign-key>
+      <index name="AD_TABLETREE_TABLE_IDX" unique="false">
+        <index-column name="AD_TABLE_ID"/>
+      </index>
+      <check name="AD_TABLETREE_APPLYHQL_CHK"><![CDATA[APPLYWHERECLAUSETOCHILDNODES IN ('Y', 'N')]]></check>
+      <check name="AD_TABLETREE_ISACTIVE_CHK"><![CDATA[ISACTIVE IN ('Y', 'N')]]></check>
+      <check name="AD_TABLETREE_ISMAINTREE_CHK"><![CDATA[ISMAINTREE IN ('Y', 'N')]]></check>
+      <check name="AD_TABLETREE_MULTPAR_CHK"><![CDATA[HASMULTIPARENTNODES IN ('Y', 'N')]]></check>
+    </table>
+  </database>
--- a/src-db/database/model/tables/AD_TREE.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/model/tables/AD_TREE.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -49,12 +49,19 @@
         <default><![CDATA[Y]]></default>
         <onCreateDefault/>
       </column>
+      <column name="AD_TABLE_ID" primaryKey="false" required="false" type="VARCHAR" size="32" autoIncrement="false">
+        <default/>
+        <onCreateDefault/>
+      </column>
       <foreign-key foreignTable="AD_CLIENT" name="AD_TREE_AD_CLIENT">
         <reference local="AD_CLIENT_ID" foreign="AD_CLIENT_ID"/>
       </foreign-key>
       <foreign-key foreignTable="AD_ORG" name="AD_TREE_AD_ORG">
         <reference local="AD_ORG_ID" foreign="AD_ORG_ID"/>
       </foreign-key>
+      <foreign-key foreignTable="AD_TABLE" name="AD_TREE_AD_TABLE">
+        <reference local="AD_TABLE_ID" foreign="AD_TABLE_ID"/>
+      </foreign-key>
       <unique name="AD_TREE_NAME">
         <unique-column name="AD_CLIENT_ID"/>
         <unique-column name="NAME"/>
--- a/src-db/database/sourcedata/AD_AUXILIARINPUT.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/sourcedata/AD_AUXILIARINPUT.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -1328,6 +1328,17 @@
 <!--35586436B2FB4809B66D519BC02230F4-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
 <!--35586436B2FB4809B66D519BC02230F4--></AD_AUXILIARINPUT>
 
+<!--364291215E9147639E19489DCE02B97F--><AD_AUXILIARINPUT>
+<!--364291215E9147639E19489DCE02B97F-->  <AD_AUXILIARINPUT_ID><![CDATA[364291215E9147639E19489DCE02B97F]]></AD_AUXILIARINPUT_ID>
+<!--364291215E9147639E19489DCE02B97F-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--364291215E9147639E19489DCE02B97F-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--364291215E9147639E19489DCE02B97F-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--364291215E9147639E19489DCE02B97F-->  <AD_TAB_ID><![CDATA[106]]></AD_TAB_ID>
+<!--364291215E9147639E19489DCE02B97F-->  <NAME><![CDATA[IsTreeTable]]></NAME>
+<!--364291215E9147639E19489DCE02B97F-->  <CODE><![CDATA[@SQL=SELECT istree FROM ad_table WHERE ad_table_id = @ad_table_id@]]></CODE>
+<!--364291215E9147639E19489DCE02B97F-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--364291215E9147639E19489DCE02B97F--></AD_AUXILIARINPUT>
+
 <!--3648B8ACFDE44EF4A649B7933D9DBD97--><AD_AUXILIARINPUT>
 <!--3648B8ACFDE44EF4A649B7933D9DBD97-->  <AD_AUXILIARINPUT_ID><![CDATA[3648B8ACFDE44EF4A649B7933D9DBD97]]></AD_AUXILIARINPUT_ID>
 <!--3648B8ACFDE44EF4A649B7933D9DBD97-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
--- a/src-db/database/sourcedata/AD_COLUMN.xml	Wed Mar 05 22:49:04 2014 +0530
+++ b/src-db/database/sourcedata/AD_COLUMN.xml	Wed Mar 05 23:13:24 2014 +0100
@@ -43501,8 +43501,7 @@
 <!--2866-->  <HELP><![CDATA[The Tree Type / Area field determines the type of tree this is.  For example, you may define one tree for your Products and another tree for your Business Partners.]]></HELP>
 <!--2866-->  <COLUMNNAME><![CDATA[TreeType]]></COLUMNNAME>
 <!--2866-->  <AD_TABLE_ID><![CDATA[288]]></AD_TABLE_ID>
-<!--2866-->  <AD_REFERENCE_ID><![CDATA[17]]></AD_REFERENCE_ID>
-<!--2866-->  <AD_REFERENCE_VALUE_ID><![CDATA[120]]></AD_REFERENCE_VALUE_ID>
+<!--2866-->  <AD_REFERENCE_ID><![CDATA[10]]></AD_REFERENCE_ID>
 <!--2866-->  <FIELDLENGTH><![CDATA[60]]></FIELDLENGTH>
 <!--2866-->  <ISKEY><![CDATA[N]]></ISKEY>
 <!--2866-->  <ISPARENT><![CDATA[N]]></ISPARENT>
@@ -220056,6 +220055,41 @@
 <!--00D6BA2224034FAD99CEA36332A9CE0D-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--00D6BA2224034FAD99CEA36332A9CE0D--></AD_COLUMN>
 
+<!--00ED8F7CB93B4006AA002FA9F3244E03--><AD_COLUMN>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_COLUMN_ID><![CDATA[00ED8F7CB93B4006AA002FA9F3244E03]]></AD_COLUMN_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <NAME><![CDATA[Created By]]></NAME>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <DESCRIPTION><![CDATA[User who created this records]]></DESCRIPTION>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <HELP><![CDATA[The Created By field indicates the user who created this record.]]></HELP>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <COLUMNNAME><![CDATA[Createdby]]></COLUMNNAME>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_REFERENCE_ID><![CDATA[30]]></AD_REFERENCE_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <SEQNO><![CDATA[60]]></SEQNO>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_ELEMENT_ID><![CDATA[246]]></AD_ELEMENT_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <POSITION><![CDATA[6]]></POSITION>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--00ED8F7CB93B4006AA002FA9F3244E03-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--00ED8F7CB93B4006AA002FA9F3244E03--></AD_COLUMN>
+
 <!--00FA42F2239C49ACA79CAC3A030F8DCD--><AD_COLUMN>
 <!--00FA42F2239C49ACA79CAC3A030F8DCD-->  <AD_COLUMN_ID><![CDATA[00FA42F2239C49ACA79CAC3A030F8DCD]]></AD_COLUMN_ID>
 <!--00FA42F2239C49ACA79CAC3A030F8DCD-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -221020,6 +221054,80 @@
 <!--04FC9DA93B104BC1BB03B854371A0211-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--04FC9DA93B104BC1BB03B854371A0211--></AD_COLUMN>
 
+<!--051C9694814F4161AFA2669DB1B92E21--><AD_COLUMN>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_COLUMN_ID><![CDATA[051C9694814F4161AFA2669DB1B92E21]]></AD_COLUMN_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <NAME><![CDATA[Property]]></NAME>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <DESCRIPTION><![CDATA[Configuration Property to assign value]]></DESCRIPTION>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <HELP><![CDATA[It is the "Configuration Property" this record sets value to. 
+
+Configuration Properties are defined by modules with the purpose other modules are capable to assign them values.]]></HELP>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <COLUMNNAME><![CDATA[Property]]></COLUMNNAME>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_TABLE_ID><![CDATA[10DF9CD898D1492BBD0620FDE6051B76]]></AD_TABLE_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_REFERENCE_ID><![CDATA[95E2A8B50A254B2AAE6774B8C2F28120]]></AD_REFERENCE_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_REFERENCE_VALUE_ID><![CDATA[45B39681AFBC4808A64C9B776A290BA4]]></AD_REFERENCE_VALUE_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <FIELDLENGTH><![CDATA[255]]></FIELDLENGTH>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <SEQNO><![CDATA[100]]></SEQNO>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_ELEMENT_ID><![CDATA[841CB823976F391BE040007F0101218F]]></AD_ELEMENT_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <POSITION><![CDATA[10]]></POSITION>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--051C9694814F4161AFA2669DB1B92E21-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--051C9694814F4161AFA2669DB1B92E21--></AD_COLUMN>
+
+<!--05427493B64040A2870A3EC49EB606CC--><AD_COLUMN>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_COLUMN_ID><![CDATA[05427493B64040A2870A3EC49EB606CC]]></AD_COLUMN_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--05427493B64040A2870A3EC49EB606CC-->  <NAME><![CDATA[Valuefield_ID]]></NAME>
+<!--05427493B64040A2870A3EC49EB606CC-->  <DESCRIPTION><![CDATA[The value of this field will be set in the foreign key column. ]]></DESCRIPTION>
+<!--05427493B64040A2870A3EC49EB606CC-->  <HELP><![CDATA[The value of this field will be set in the foreign key column. ]]></HELP>
+<!--05427493B64040A2870A3EC49EB606CC-->  <COLUMNNAME><![CDATA[Valuefield_ID]]></COLUMNNAME>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_TABLE_ID><![CDATA[58977D8AC43D4557B1176BBA5FBEB871]]></AD_TABLE_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_REFERENCE_ID><![CDATA[18]]></AD_REFERENCE_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_REFERENCE_VALUE_ID><![CDATA[BE0FDF9E98DA43908E1DACC43893E1F6]]></AD_REFERENCE_VALUE_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--05427493B64040A2870A3EC49EB606CC-->  <SEQNO><![CDATA[170]]></SEQNO>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_ELEMENT_ID><![CDATA[5D272070F3EE4507BE9C0F3549E043D6]]></AD_ELEMENT_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--05427493B64040A2870A3EC49EB606CC-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--05427493B64040A2870A3EC49EB606CC-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--05427493B64040A2870A3EC49EB606CC-->  <POSITION><![CDATA[15]]></POSITION>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--05427493B64040A2870A3EC49EB606CC-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--05427493B64040A2870A3EC49EB606CC-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--05427493B64040A2870A3EC49EB606CC-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--05427493B64040A2870A3EC49EB606CC--></AD_COLUMN>
+
 <!--0548F126F1054F2280D9F63F48E559DB--><AD_COLUMN>
 <!--0548F126F1054F2280D9F63F48E559DB-->  <AD_COLUMN_ID><![CDATA[0548F126F1054F2280D9F63F48E559DB]]></AD_COLUMN_ID>
 <!--0548F126F1054F2280D9F63F48E559DB-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -221240,6 +221348,43 @@
 <!--05C088F54F974D8482C0DFDAE726D0C5-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--05C088F54F974D8482C0DFDAE726D0C5--></AD_COLUMN>
 
+<!--05C58E74CB76448CBA4AF4CA43E193E3--><AD_COLUMN>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_COLUMN_ID><![CDATA[05C58E74CB76448CBA4AF4CA43E193E3]]></AD_COLUMN_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <NAME><![CDATA[Module]]></NAME>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <DESCRIPTION><![CDATA[Module]]></DESCRIPTION>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <HELP><![CDATA[Indicates the module the element forms part of.]]></HELP>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <COLUMNNAME><![CDATA[AD_Module_ID]]></COLUMNNAME>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_TABLE_ID><![CDATA[10DF9CD898D1492BBD0620FDE6051B76]]></AD_TABLE_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_REFERENCE_ID><![CDATA[19]]></AD_REFERENCE_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_VAL_RULE_ID><![CDATA[C45CFD74FF5145B0A356E9233D49996F]]></AD_VAL_RULE_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <DEFAULTVALUE><![CDATA[@SQL=SELECT AD_MODULE_ID FROM AD_REF_TREE WHERE AD_REF_TREE_ID = @AD_REF_TREE_ID@]]></DEFAULTVALUE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <SEQNO><![CDATA[50]]></SEQNO>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_ELEMENT_ID><![CDATA[565E666A619A2693E040007F01002851]]></AD_ELEMENT_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <POSITION><![CDATA[5]]></POSITION>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--05C58E74CB76448CBA4AF4CA43E193E3-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--05C58E74CB76448CBA4AF4CA43E193E3--></AD_COLUMN>
+
 <!--060657E87C824FD29A132A97802331F1--><AD_COLUMN>
 <!--060657E87C824FD29A132A97802331F1-->  <AD_COLUMN_ID><![CDATA[060657E87C824FD29A132A97802331F1]]></AD_COLUMN_ID>
 <!--060657E87C824FD29A132A97802331F1-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -221277,6 +221422,42 @@
 <!--060657E87C824FD29A132A97802331F1-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--060657E87C824FD29A132A97802331F1--></AD_COLUMN>
 
+<!--06146353992C48FE945CB1C60A28E7FC--><AD_COLUMN>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_COLUMN_ID><![CDATA[06146353992C48FE945CB1C60A28E7FC]]></AD_COLUMN_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <NAME><![CDATA[Organization]]></NAME>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <DESCRIPTION><![CDATA[Organizational entity within client]]></DESCRIPTION>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <HELP><![CDATA[An organization is a unit of your client or legal entity - examples are store, department. You can share data between organizations.]]></HELP>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <COLUMNNAME><![CDATA[AD_Org_ID]]></COLUMNNAME>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_TABLE_ID><![CDATA[10DF9CD898D1492BBD0620FDE6051B76]]></AD_TABLE_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_REFERENCE_ID><![CDATA[19]]></AD_REFERENCE_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <DEFAULTVALUE><![CDATA[@AD_ORG_ID@]]></DEFAULTVALUE>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <SEQNO><![CDATA[40]]></SEQNO>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_ELEMENT_ID><![CDATA[113]]></AD_ELEMENT_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISSESSIONATTR><![CDATA[Y]]></ISSESSIONATTR>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <POSITION><![CDATA[4]]></POSITION>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--06146353992C48FE945CB1C60A28E7FC-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--06146353992C48FE945CB1C60A28E7FC--></AD_COLUMN>
+
 <!--0665AD61112844B18C999D519EDB12A0--><AD_COLUMN>
 <!--0665AD61112844B18C999D519EDB12A0-->  <AD_COLUMN_ID><![CDATA[0665AD61112844B18C999D519EDB12A0]]></AD_COLUMN_ID>
 <!--0665AD61112844B18C999D519EDB12A0-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -222046,6 +222227,42 @@
 <!--0BD260C46B9547BDB318DEBBDAB70536-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--0BD260C46B9547BDB318DEBBDAB70536--></AD_COLUMN>
 
+<!--0C1DE920F9734332A37F459F72CE5045--><AD_COLUMN>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_COLUMN_ID><![CDATA[0C1DE920F9734332A37F459F72CE5045]]></AD_COLUMN_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <NAME><![CDATA[Column]]></NAME>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <DESCRIPTION><![CDATA[A link to the database column of the table.]]></DESCRIPTION>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <HELP><![CDATA[Link to the database column of the table]]></HELP>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <COLUMNNAME><![CDATA[AD_Column_ID]]></COLUMNNAME>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_TABLE_ID><![CDATA[58977D8AC43D4557B1176BBA5FBEB871]]></AD_TABLE_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_REFERENCE_ID><![CDATA[19]]></AD_REFERENCE_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_VAL_RULE_ID><![CDATA[100]]></AD_VAL_RULE_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <SEQNO><![CDATA[140]]></SEQNO>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_ELEMENT_ID><![CDATA[104]]></AD_ELEMENT_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <POSITION><![CDATA[12]]></POSITION>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--0C1DE920F9734332A37F459F72CE5045-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--0C1DE920F9734332A37F459F72CE5045--></AD_COLUMN>
+
 <!--0C6CC9768B5144EBB4827B9B98976816--><AD_COLUMN>
 <!--0C6CC9768B5144EBB4827B9B98976816-->  <AD_COLUMN_ID><![CDATA[0C6CC9768B5144EBB4827B9B98976816]]></AD_COLUMN_ID>
 <!--0C6CC9768B5144EBB4827B9B98976816-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -222572,6 +222789,42 @@
 <!--0ECBF3A6F9054BB3B46A02F7EBA78894-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--0ECBF3A6F9054BB3B46A02F7EBA78894--></AD_COLUMN>
 
+<!--0EFB6265D90B409EA1BA785F06A54F3A--><AD_COLUMN>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_COLUMN_ID><![CDATA[0EFB6265D90B409EA1BA785F06A54F3A]]></AD_COLUMN_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <NAME><![CDATA[Client]]></NAME>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <DESCRIPTION><![CDATA[Client for this installation.]]></DESCRIPTION>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <HELP><![CDATA[A Client is a company or a legal entity. You cannot share data between Clients.]]></HELP>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <COLUMNNAME><![CDATA[AD_Client_ID]]></COLUMNNAME>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_REFERENCE_ID><![CDATA[19]]></AD_REFERENCE_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <DEFAULTVALUE><![CDATA[@AD_CLIENT_ID@]]></DEFAULTVALUE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <SEQNO><![CDATA[20]]></SEQNO>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_ELEMENT_ID><![CDATA[102]]></AD_ELEMENT_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISSESSIONATTR><![CDATA[Y]]></ISSESSIONATTR>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <POSITION><![CDATA[2]]></POSITION>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--0EFB6265D90B409EA1BA785F06A54F3A-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--0EFB6265D90B409EA1BA785F06A54F3A--></AD_COLUMN>
+
 <!--0F050666DA634EAE8919F239440ACF8A--><AD_COLUMN>
 <!--0F050666DA634EAE8919F239440ACF8A-->  <AD_COLUMN_ID><![CDATA[0F050666DA634EAE8919F239440ACF8A]]></AD_COLUMN_ID>
 <!--0F050666DA634EAE8919F239440ACF8A-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -222643,6 +222896,42 @@
 <!--0F1394CAD68C4E1EBEC90416205E521B-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--0F1394CAD68C4E1EBEC90416205E521B--></AD_COLUMN>
 
+<!--0FA23D0D90E34E8790627C9928566EE3--><AD_COLUMN>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_COLUMN_ID><![CDATA[0FA23D0D90E34E8790627C9928566EE3]]></AD_COLUMN_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <NAME><![CDATA[Link to Parent Column]]></NAME>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <DESCRIPTION><![CDATA[For Link to Parent tables: column that points to the node id of the parent node]]></DESCRIPTION>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <HELP><![CDATA[This field is only used in Link To Parent tables. This field represents the column that points to the node id of the row that represents the parent of a node]]></HELP>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <COLUMNNAME><![CDATA[Linktoparentcolumn]]></COLUMNNAME>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_REFERENCE_ID><![CDATA[18]]></AD_REFERENCE_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_REFERENCE_VALUE_ID><![CDATA[E125179F7310445E880814C659CA9F5A]]></AD_REFERENCE_VALUE_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <SEQNO><![CDATA[110]]></SEQNO>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_ELEMENT_ID><![CDATA[D4D7E2ED15CA403C88268790EB09C018]]></AD_ELEMENT_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <POSITION><![CDATA[11]]></POSITION>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--0FA23D0D90E34E8790627C9928566EE3-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--0FA23D0D90E34E8790627C9928566EE3--></AD_COLUMN>
+
 <!--1050C23BA102443A86AB2AF85D8F098D--><AD_COLUMN>
 <!--1050C23BA102443A86AB2AF85D8F098D-->  <AD_COLUMN_ID><![CDATA[1050C23BA102443A86AB2AF85D8F098D]]></AD_COLUMN_ID>
 <!--1050C23BA102443A86AB2AF85D8F098D-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -223603,6 +223892,42 @@
 <!--154B76A81BCB4CD2AE569E0CC25A12FD-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--154B76A81BCB4CD2AE569E0CC25A12FD--></AD_COLUMN>
 
+<!--15A7EDDCA9B0453C9B450E7CA8398382--><AD_COLUMN>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_COLUMN_ID><![CDATA[15A7EDDCA9B0453C9B450E7CA8398382]]></AD_COLUMN_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <NAME><![CDATA[Sort]]></NAME>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <DESCRIPTION><![CDATA[Defines if this field can be sorted in the popup]]></DESCRIPTION>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <HELP><![CDATA[Defines if this field can be sorted in the popup]]></HELP>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <COLUMNNAME><![CDATA[Sort]]></COLUMNNAME>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_TABLE_ID><![CDATA[10DF9CD898D1492BBD0620FDE6051B76]]></AD_TABLE_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_REFERENCE_ID><![CDATA[20]]></AD_REFERENCE_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <FIELDLENGTH><![CDATA[1]]></FIELDLENGTH>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <DEFAULTVALUE><![CDATA[N]]></DEFAULTVALUE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <SEQNO><![CDATA[120]]></SEQNO>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_ELEMENT_ID><![CDATA[D21DE818DD4E499D851ADE875D6FD711]]></AD_ELEMENT_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <POSITION><![CDATA[12]]></POSITION>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--15A7EDDCA9B0453C9B450E7CA8398382-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--15A7EDDCA9B0453C9B450E7CA8398382--></AD_COLUMN>
+
 <!--15C276FA154D42EC98231860B161414D--><AD_COLUMN>
 <!--15C276FA154D42EC98231860B161414D-->  <AD_COLUMN_ID><![CDATA[15C276FA154D42EC98231860B161414D]]></AD_COLUMN_ID>
 <!--15C276FA154D42EC98231860B161414D-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -223636,6 +223961,44 @@
 <!--15C276FA154D42EC98231860B161414D-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--15C276FA154D42EC98231860B161414D--></AD_COLUMN>
 
+<!--15C9F8F0DCBB4867A8D20A717A82EB18--><AD_COLUMN>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_COLUMN_ID><![CDATA[15C9F8F0DCBB4867A8D20A717A82EB18]]></AD_COLUMN_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <NAME><![CDATA[Active]]></NAME>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <DESCRIPTION><![CDATA[A flag indicating whether this record is available for use or de-activated.]]></DESCRIPTION>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <HELP><![CDATA[There are two methods of making records unavailable in the system: One is to delete the record, the other is to de-activate the record. A de-activated record is not available for selection, but available for reporting. There are two reasons for de-activating and not deleting records: 
+(1) The system requires the record for auditing purposes.
+(2) The record is referenced by other records. E.g., you cannot delete a Business Partner, if there are existing invoices for it. By de-activating the Business Partner you prevent it from being used in future transactions.]]></HELP>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <COLUMNNAME><![CDATA[Isactive]]></COLUMNNAME>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_REFERENCE_ID><![CDATA[20]]></AD_REFERENCE_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <FIELDLENGTH><![CDATA[1]]></FIELDLENGTH>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <DEFAULTVALUE><![CDATA[Y]]></DEFAULTVALUE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <SEQNO><![CDATA[40]]></SEQNO>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_ELEMENT_ID><![CDATA[348]]></AD_ELEMENT_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <POSITION><![CDATA[4]]></POSITION>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--15C9F8F0DCBB4867A8D20A717A82EB18--></AD_COLUMN>
+
 <!--1655799099FD4E7A9EB982F98A5C8066--><AD_COLUMN>
 <!--1655799099FD4E7A9EB982F98A5C8066-->  <AD_COLUMN_ID><![CDATA[1655799099FD4E7A9EB982F98A5C8066]]></AD_COLUMN_ID>
 <!--1655799099FD4E7A9EB982F98A5C8066-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -224494,6 +224857,41 @@
 <!--17FDE34256AC11DE8CD0DFCC30CA23CC-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--17FDE34256AC11DE8CD0DFCC30CA23CC--></AD_COLUMN>
 
+<!--185D94205E434CB9999936489A9A1669--><AD_COLUMN>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_COLUMN_ID><![CDATA[185D94205E434CB9999936489A9A1669]]></AD_COLUMN_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--185D94205E434CB9999936489A9A1669-->  <NAME><![CDATA[Updated By]]></NAME>
+<!--185D94205E434CB9999936489A9A1669-->  <DESCRIPTION><![CDATA[User who updated this records]]></DESCRIPTION>
+<!--185D94205E434CB9999936489A9A1669-->  <HELP><![CDATA[The Updated By field indicates the user who updated this record.]]></HELP>
+<!--185D94205E434CB9999936489A9A1669-->  <COLUMNNAME><![CDATA[Updatedby]]></COLUMNNAME>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_REFERENCE_ID><![CDATA[30]]></AD_REFERENCE_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--185D94205E434CB9999936489A9A1669-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--185D94205E434CB9999936489A9A1669-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--185D94205E434CB9999936489A9A1669-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--185D94205E434CB9999936489A9A1669-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--185D94205E434CB9999936489A9A1669-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--185D94205E434CB9999936489A9A1669-->  <SEQNO><![CDATA[80]]></SEQNO>
+<!--185D94205E434CB9999936489A9A1669-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--185D94205E434CB9999936489A9A1669-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--185D94205E434CB9999936489A9A1669-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_ELEMENT_ID><![CDATA[608]]></AD_ELEMENT_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--185D94205E434CB9999936489A9A1669-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--185D94205E434CB9999936489A9A1669-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--185D94205E434CB9999936489A9A1669-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--185D94205E434CB9999936489A9A1669-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--185D94205E434CB9999936489A9A1669-->  <POSITION><![CDATA[8]]></POSITION>
+<!--185D94205E434CB9999936489A9A1669-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--185D94205E434CB9999936489A9A1669-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--185D94205E434CB9999936489A9A1669-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--185D94205E434CB9999936489A9A1669-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--185D94205E434CB9999936489A9A1669-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--185D94205E434CB9999936489A9A1669--></AD_COLUMN>
+
 <!--186A55DC0F9F4697A5916D454B08F432--><AD_COLUMN>
 <!--186A55DC0F9F4697A5916D454B08F432-->  <AD_COLUMN_ID><![CDATA[186A55DC0F9F4697A5916D454B08F432]]></AD_COLUMN_ID>
 <!--186A55DC0F9F4697A5916D454B08F432-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -227388,6 +227786,42 @@
 <!--2517D9B88D7D4F789D51EC421F68AE29-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--2517D9B88D7D4F789D51EC421F68AE29--></AD_COLUMN>
 
+<!--251C056DB4764D90AA183440E409083D--><AD_COLUMN>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_COLUMN_ID><![CDATA[251C056DB4764D90AA183440E409083D]]></AD_COLUMN_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--251C056DB4764D90AA183440E409083D-->  <NAME><![CDATA[AD_Table_Tree_ID]]></NAME>
+<!--251C056DB4764D90AA183440E409083D-->  <DESCRIPTION><![CDATA[Table tree structure to be used in this tab]]></DESCRIPTION>
+<!--251C056DB4764D90AA183440E409083D-->  <HELP><![CDATA[Tree tables can define several tree structures. If a table tree structure is set in this field, the tab will include a tree view that will allow to browse the data hierarchically.]]></HELP>
+<!--251C056DB4764D90AA183440E409083D-->  <COLUMNNAME><![CDATA[AD_Table_Tree_ID]]></COLUMNNAME>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_TABLE_ID><![CDATA[106]]></AD_TABLE_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_REFERENCE_ID><![CDATA[95E2A8B50A254B2AAE6774B8C2F28120]]></AD_REFERENCE_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_REFERENCE_VALUE_ID><![CDATA[CE9AF28566544F9787D5B936B0067809]]></AD_REFERENCE_VALUE_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--251C056DB4764D90AA183440E409083D-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--251C056DB4764D90AA183440E409083D-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--251C056DB4764D90AA183440E409083D-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--251C056DB4764D90AA183440E409083D-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--251C056DB4764D90AA183440E409083D-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--251C056DB4764D90AA183440E409083D-->  <SEQNO><![CDATA[172]]></SEQNO>
+<!--251C056DB4764D90AA183440E409083D-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--251C056DB4764D90AA183440E409083D-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--251C056DB4764D90AA183440E409083D-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_ELEMENT_ID><![CDATA[B309CE97F1774C62AE6043A57DD9BAF5]]></AD_ELEMENT_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--251C056DB4764D90AA183440E409083D-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--251C056DB4764D90AA183440E409083D-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--251C056DB4764D90AA183440E409083D-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--251C056DB4764D90AA183440E409083D-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--251C056DB4764D90AA183440E409083D-->  <POSITION><![CDATA[51]]></POSITION>
+<!--251C056DB4764D90AA183440E409083D-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--251C056DB4764D90AA183440E409083D-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--251C056DB4764D90AA183440E409083D-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--251C056DB4764D90AA183440E409083D-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--251C056DB4764D90AA183440E409083D-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--251C056DB4764D90AA183440E409083D--></AD_COLUMN>
+
 <!--252BC8724D9B492CB4521A698123680F--><AD_COLUMN>
 <!--252BC8724D9B492CB4521A698123680F-->  <AD_COLUMN_ID><![CDATA[252BC8724D9B492CB4521A698123680F]]></AD_COLUMN_ID>
 <!--252BC8724D9B492CB4521A698123680F-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -227809,6 +228243,41 @@
 <!--26B6C690FE9643EBB1F3E1D6FC9D9A3B-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--26B6C690FE9643EBB1F3E1D6FC9D9A3B--></AD_COLUMN>
 
+<!--26D75DD294F7469489673CBA815BBE04--><AD_COLUMN>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_COLUMN_ID><![CDATA[26D75DD294F7469489673CBA815BBE04]]></AD_COLUMN_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--26D75DD294F7469489673CBA815BBE04-->  <NAME><![CDATA[HQL Where Clause for Root Nodes]]></NAME>
+<!--26D75DD294F7469489673CBA815BBE04-->  <DESCRIPTION><![CDATA[Where clause that define what are the root nodes for this tree reference]]></DESCRIPTION>
+<!--26D75DD294F7469489673CBA815BBE04-->  <HELP><![CDATA[By default the root nodes of the tree are those whose parent is null or 0. When the default case does not apply, a HQL where clause can be set to define which are the root nodes for this tree reference.]]></HELP>
+<!--26D75DD294F7469489673CBA815BBE04-->  <COLUMNNAME><![CDATA[Whereclauserootnodes]]></COLUMNNAME>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_TABLE_ID><![CDATA[58977D8AC43D4557B1176BBA5FBEB871]]></AD_TABLE_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_REFERENCE_ID><![CDATA[10]]></AD_REFERENCE_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <FIELDLENGTH><![CDATA[2000]]></FIELDLENGTH>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--26D75DD294F7469489673CBA815BBE04-->  <SEQNO><![CDATA[200]]></SEQNO>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_ELEMENT_ID><![CDATA[EBE913C1DDD84066A1D88C9903717DB9]]></AD_ELEMENT_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--26D75DD294F7469489673CBA815BBE04-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--26D75DD294F7469489673CBA815BBE04-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--26D75DD294F7469489673CBA815BBE04-->  <POSITION><![CDATA[18]]></POSITION>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--26D75DD294F7469489673CBA815BBE04-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--26D75DD294F7469489673CBA815BBE04-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--26D75DD294F7469489673CBA815BBE04-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--26D75DD294F7469489673CBA815BBE04--></AD_COLUMN>
+
 <!--271274F74A1E4F63A2171B7C534BB9F2--><AD_COLUMN>
 <!--271274F74A1E4F63A2171B7C534BB9F2-->  <AD_COLUMN_ID><![CDATA[271274F74A1E4F63A2171B7C534BB9F2]]></AD_COLUMN_ID>
 <!--271274F74A1E4F63A2171B7C534BB9F2-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -228094,6 +228563,41 @@
 <!--2818FAD81CCA4A9A9569EC4092C447B3-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--2818FAD81CCA4A9A9569EC4092C447B3--></AD_COLUMN>
 
+<!--282008A8F9624489896871A2CEEC7689--><AD_COLUMN>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_COLUMN_ID><![CDATA[282008A8F9624489896871A2CEEC7689]]></AD_COLUMN_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--282008A8F9624489896871A2CEEC7689-->  <NAME><![CDATA[Created By]]></NAME>
+<!--282008A8F9624489896871A2CEEC7689-->  <DESCRIPTION><![CDATA[User who created this records]]></DESCRIPTION>
+<!--282008A8F9624489896871A2CEEC7689-->  <HELP><![CDATA[The Created By field indicates the user who created this record.]]></HELP>
+<!--282008A8F9624489896871A2CEEC7689-->  <COLUMNNAME><![CDATA[Createdby]]></COLUMNNAME>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_TABLE_ID><![CDATA[10DF9CD898D1492BBD0620FDE6051B76]]></AD_TABLE_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_REFERENCE_ID><![CDATA[30]]></AD_REFERENCE_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--282008A8F9624489896871A2CEEC7689-->  <SEQNO><![CDATA[190]]></SEQNO>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_ELEMENT_ID><![CDATA[246]]></AD_ELEMENT_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--282008A8F9624489896871A2CEEC7689-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--282008A8F9624489896871A2CEEC7689-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--282008A8F9624489896871A2CEEC7689-->  <POSITION><![CDATA[19]]></POSITION>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--282008A8F9624489896871A2CEEC7689-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--282008A8F9624489896871A2CEEC7689-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--282008A8F9624489896871A2CEEC7689-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--282008A8F9624489896871A2CEEC7689--></AD_COLUMN>
+
 <!--283EA4C588214FF9987F6BEE7F27C9CC--><AD_COLUMN>
 <!--283EA4C588214FF9987F6BEE7F27C9CC-->  <AD_COLUMN_ID><![CDATA[283EA4C588214FF9987F6BEE7F27C9CC]]></AD_COLUMN_ID>
 <!--283EA4C588214FF9987F6BEE7F27C9CC-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -228839,6 +229343,45 @@
 <!--2B9E746AE09F4E88AE00CBA9DBFC4062-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--2B9E746AE09F4E88AE00CBA9DBFC4062--></AD_COLUMN>
 
+<!--2BF196792D1E4585857593DA16E0FEDD--><AD_COLUMN>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_COLUMN_ID><![CDATA[2BF196792D1E4585857593DA16E0FEDD]]></AD_COLUMN_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <NAME><![CDATA[Tree Structure]]></NAME>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <DESCRIPTION><![CDATA[Inner structure of the tree]]></DESCRIPTION>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <HELP><![CDATA[Three different tree structures are available:
+- AD Tree Node: The information regarding the hierarchy of the data is stored in the ADTree and ADTreeNode tables.
+- Link to Parent in Table: This structure can be used when the informartion regarding the hierarchy of the data can be fetched from the own table. In this case, there has to be a column in the table that points to the row that represents the parent node of the record.
+- Custom: For other tree tables, a manual datasource can be defined]]></HELP>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <COLUMNNAME><![CDATA[Treestructure]]></COLUMNNAME>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_REFERENCE_ID><![CDATA[17]]></AD_REFERENCE_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_REFERENCE_VALUE_ID><![CDATA[3C8CD031B6514878807DF3F198BD4EC6]]></AD_REFERENCE_VALUE_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <FIELDLENGTH><![CDATA[60]]></FIELDLENGTH>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <SEQNO><![CDATA[200]]></SEQNO>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_ELEMENT_ID><![CDATA[FC6AA883E5FE4A338C509A0A5A05B873]]></AD_ELEMENT_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <POSITION><![CDATA[20]]></POSITION>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--2BF196792D1E4585857593DA16E0FEDD-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--2BF196792D1E4585857593DA16E0FEDD--></AD_COLUMN>
+
 <!--2C18C72E50CB499BB466F65C2E06F66D--><AD_COLUMN>
 <!--2C18C72E50CB499BB466F65C2E06F66D-->  <AD_COLUMN_ID><![CDATA[2C18C72E50CB499BB466F65C2E06F66D]]></AD_COLUMN_ID>
 <!--2C18C72E50CB499BB466F65C2E06F66D-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -229199,6 +229742,41 @@
 <!--2D699F3974F64AFD8A48DC90748F4DBE-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--2D699F3974F64AFD8A48DC90748F4DBE--></AD_COLUMN>
 
+<!--2D852A64DD7D4758AAA80AFB90FB5A84--><AD_COLUMN>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_COLUMN_ID><![CDATA[2D852A64DD7D4758AAA80AFB90FB5A84]]></AD_COLUMN_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <NAME><![CDATA[Table]]></NAME>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <DESCRIPTION><![CDATA[A dictionary table used for this tab that points to the database table.]]></DESCRIPTION>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <HELP><![CDATA[The Table indicates the table in which a field or fields reside.]]></HELP>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <COLUMNNAME><![CDATA[AD_Table_ID]]></COLUMNNAME>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_TABLE_ID><![CDATA[288]]></AD_TABLE_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_REFERENCE_ID><![CDATA[19]]></AD_REFERENCE_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <FIELDLENGTH><![CDATA[32]]></FIELDLENGTH>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISMANDATORY><![CDATA[N]]></ISMANDATORY>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISUPDATEABLE><![CDATA[Y]]></ISUPDATEABLE>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <SEQNO><![CDATA[11]]></SEQNO>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_ELEMENT_ID><![CDATA[126]]></AD_ELEMENT_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <POSITION><![CDATA[13]]></POSITION>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--2D852A64DD7D4758AAA80AFB90FB5A84--></AD_COLUMN>
+
 <!--2DA46B5D3E7D492D88636514FC5FF363--><AD_COLUMN>
 <!--2DA46B5D3E7D492D88636514FC5FF363-->  <AD_COLUMN_ID><![CDATA[2DA46B5D3E7D492D88636514FC5FF363]]></AD_COLUMN_ID>
 <!--2DA46B5D3E7D492D88636514FC5FF363-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -230087,6 +230665,42 @@
 <!--32DEE729EB9F4F4B8B50B3A99B719BE3-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--32DEE729EB9F4F4B8B50B3A99B719BE3--></AD_COLUMN>
 
+<!--330A666232BE4F35B365929633437498--><AD_COLUMN>
+<!--330A666232BE4F35B365929633437498-->  <AD_COLUMN_ID><![CDATA[330A666232BE4F35B365929633437498]]></AD_COLUMN_ID>
+<!--330A666232BE4F35B365929633437498-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--330A666232BE4F35B365929633437498-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--330A666232BE4F35B365929633437498-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--330A666232BE4F35B365929633437498-->  <NAME><![CDATA[Updated]]></NAME>
+<!--330A666232BE4F35B365929633437498-->  <DESCRIPTION><![CDATA[The date that this record was last updated]]></DESCRIPTION>
+<!--330A666232BE4F35B365929633437498-->  <HELP><![CDATA[The Updated field indicates the date that this record was updated.]]></HELP>
+<!--330A666232BE4F35B365929633437498-->  <COLUMNNAME><![CDATA[Updated]]></COLUMNNAME>
+<!--330A666232BE4F35B365929633437498-->  <AD_TABLE_ID><![CDATA[48F5363A7C0C44DE8114627C64DB4BDA]]></AD_TABLE_ID>
+<!--330A666232BE4F35B365929633437498-->  <AD_REFERENCE_ID><![CDATA[16]]></AD_REFERENCE_ID>
+<!--330A666232BE4F35B365929633437498-->  <FIELDLENGTH><![CDATA[19]]></FIELDLENGTH>
+<!--330A666232BE4F35B365929633437498-->  <DEFAULTVALUE><![CDATA[@#Date@]]></DEFAULTVALUE>
+<!--330A666232BE4F35B365929633437498-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--330A666232BE4F35B365929633437498-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--330A666232BE4F35B365929633437498-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--330A666232BE4F35B365929633437498-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--330A666232BE4F35B365929633437498-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--330A666232BE4F35B365929633437498-->  <SEQNO><![CDATA[70]]></SEQNO>
+<!--330A666232BE4F35B365929633437498-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--330A666232BE4F35B365929633437498-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--330A666232BE4F35B365929633437498-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--330A666232BE4F35B365929633437498-->  <AD_ELEMENT_ID><![CDATA[607]]></AD_ELEMENT_ID>
+<!--330A666232BE4F35B365929633437498-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--330A666232BE4F35B365929633437498-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--330A666232BE4F35B365929633437498-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--330A666232BE4F35B365929633437498-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--330A666232BE4F35B365929633437498-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--330A666232BE4F35B365929633437498-->  <POSITION><![CDATA[7]]></POSITION>
+<!--330A666232BE4F35B365929633437498-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--330A666232BE4F35B365929633437498-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--330A666232BE4F35B365929633437498-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEONNEW>
+<!--330A666232BE4F35B365929633437498-->  <IMAGESIZEVALUESACTION><![CDATA[N]]></IMAGESIZEVALUESACTION>
+<!--330A666232BE4F35B365929633437498-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
+<!--330A666232BE4F35B365929633437498--></AD_COLUMN>
+
 <!--33313B1A70F246599068F2E08BF30CAB--><AD_COLUMN>
 <!--33313B1A70F246599068F2E08BF30CAB-->  <AD_COLUMN_ID><![CDATA[33313B1A70F246599068F2E08BF30CAB]]></AD_COLUMN_ID>
 <!--33313B1A70F246599068F2E08BF30CAB-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -230508,6 +231122,42 @@
 <!--35D2E70BF3924621A4A20CC1AB0DB0F6-->  <ISUSEDSEQUENCE><![CDATA[N]]></ISUSEDSEQUENCE>
 <!--35D2E70BF3924621A4A20CC1AB0DB0F6--></AD_COLUMN>
 
+<!--35DB90C6E9E04161A76B427517E557BF--><AD_COLUMN>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_COLUMN_ID><![CDATA[35DB90C6E9E04161A76B427517E557BF]]></AD_COLUMN_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <NAME><![CDATA[Updated]]></NAME>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <DESCRIPTION><![CDATA[The date that this record was last updated]]></DESCRIPTION>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <HELP><![CDATA[The Updated field indicates the date that this record was updated.]]></HELP>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <COLUMNNAME><![CDATA[Updated]]></COLUMNNAME>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_TABLE_ID><![CDATA[58977D8AC43D4557B1176BBA5FBEB871]]></AD_TABLE_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_REFERENCE_ID><![CDATA[16]]></AD_REFERENCE_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <FIELDLENGTH><![CDATA[19]]></FIELDLENGTH>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <DEFAULTVALUE><![CDATA[@#Date@]]></DEFAULTVALUE>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISKEY><![CDATA[N]]></ISKEY>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISPARENT><![CDATA[N]]></ISPARENT>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISMANDATORY><![CDATA[Y]]></ISMANDATORY>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISUPDATEABLE><![CDATA[N]]></ISUPDATEABLE>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISIDENTIFIER><![CDATA[N]]></ISIDENTIFIER>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <SEQNO><![CDATA[70]]></SEQNO>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISTRANSLATED><![CDATA[N]]></ISTRANSLATED>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISENCRYPTED><![CDATA[N]]></ISENCRYPTED>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISSELECTIONCOLUMN><![CDATA[N]]></ISSELECTIONCOLUMN>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_ELEMENT_ID><![CDATA[607]]></AD_ELEMENT_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISSESSIONATTR><![CDATA[N]]></ISSESSIONATTR>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISSECONDARYKEY><![CDATA[N]]></ISSECONDARYKEY>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISDESENCRYPTABLE><![CDATA[N]]></ISDESENCRYPTABLE>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <DEVELOPMENTSTATUS><![CDATA[RE]]></DEVELOPMENTSTATUS>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <AD_MODULE_ID><![CDATA[0]]></AD_MODULE_ID>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <POSITION><![CDATA[7]]></POSITION>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISTRANSIENT><![CDATA[N]]></ISTRANSIENT>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <ISAUTOSAVE><![CDATA[Y]]></ISAUTOSAVE>
+<!--35DB90C6E9E04161A76B427517E557BF-->  <VALIDATEONNEW><![CDATA[Y]]></VALIDATEO