From b5cb64bc92ad852902f6eaeff8a21dd2cfe2a626 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Tue, 11 Apr 2023 07:20:13 +0200 Subject: [PATCH] IDEMPIERE-5567 Support of UUID for Search (UU) data type (FHCA-4195) (#1771) * IDEMPIERE-5567 Support of UUID for Search (UU) data type (FHCA-4195) * - Search editor now assigns the value correctly when selecting from Info Window - Info Window shows correctly the first UU key column - Added Record UUID new data type to work with record ID editor but with UU column - Added column/field Test.Record_UU for testing * - Fix opening Record ID editor after saved * - Implement changes suggested by Heng Sin's peer review * - Remove other unnecessary changes * - safer comparison --- .../oracle/202304060001_IDEMPIERE-5567.sql | 82 +++++++++ .../202304060001_IDEMPIERE-5567.sql | 75 ++++++++ .../base/callout/TableIDCallout.java | 4 + .../src/org/compiere/model/Query.java | 8 +- .../src/org/compiere/model/SystemIDs.java | 1 + .../src/org/compiere/util/DB.java | 46 ++++- .../src/org/compiere/util/DisplayType.java | 8 +- .../WInfoWindowListItemRenderer.java | 6 + .../webui/component/WListItemRenderer.java | 19 +- .../adempiere/webui/component/WListbox.java | 50 +++--- .../webui/editor/InfoListSubModel.java | 6 +- .../webui/editor/WRecordIDEditor.java | 84 ++++++--- .../adempiere/webui/editor/WSearchEditor.java | 24 ++- .../webui/factory/DefaultEditorFactory.java | 2 +- .../org/adempiere/webui/info/InfoWindow.java | 44 +++-- .../webui/info/RelatedInfoWindow.java | 11 +- .../webui/panel/InfoAssignmentPanel.java | 2 +- .../webui/panel/InfoGeneralPanel.java | 43 +++-- .../org/adempiere/webui/panel/InfoPanel.java | 166 +++++++++++------- .../webui/window/WRecordIDDialog.java | 49 ++++-- .../adempiere/webui/window/WRecordInfo.java | 7 +- .../src/org/compiere/minigrid/IDColumn.java | 2 +- .../src/org/compiere/minigrid/IMiniTable.java | 3 +- .../compiere/minigrid/SelectableIDColumn.java | 34 ++++ .../src/org/compiere/minigrid/UUIDColumn.java | 94 ++++++++++ 25 files changed, 689 insertions(+), 181 deletions(-) create mode 100644 migration/iD11/oracle/202304060001_IDEMPIERE-5567.sql create mode 100644 migration/iD11/postgresql/202304060001_IDEMPIERE-5567.sql create mode 100644 org.adempiere.ui/src/org/compiere/minigrid/SelectableIDColumn.java create mode 100644 org.adempiere.ui/src/org/compiere/minigrid/UUIDColumn.java diff --git a/migration/iD11/oracle/202304060001_IDEMPIERE-5567.sql b/migration/iD11/oracle/202304060001_IDEMPIERE-5567.sql new file mode 100644 index 0000000000..d3a1e152e9 --- /dev/null +++ b/migration/iD11/oracle/202304060001_IDEMPIERE-5567.sql @@ -0,0 +1,82 @@ +-- IDEMPIERE-5567 Support of UUID on Search (FHCA-4195) +SELECT register_migration_script('202304060001_IDEMPIERE-5567.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Apr 6, 2023, 12:01:14 AM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','UUID based table is not compatible with Record_ID',0,0,'Y',TO_TIMESTAMP('2023-04-06 00:01:13','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-06 00:01:13','YYYY-MM-DD HH24:MI:SS'),100,200830,'UUTableNotCompatibleWithRecordID','D','5b220b22-2a21-493c-81f0-877dbc083874') +; + +ALTER TABLE t_selection ADD t_selection_uu VARCHAR2(36 CHAR) DEFAULT '' NOT NULL; + +ALTER TABLE T_SELECTION MODIFY T_SELECTION_ID DEFAULT 0; + +ALTER TABLE t_selection DROP CONSTRAINT t_selection_key; + +DROP INDEX t_selection_key; + +ALTER TABLE t_selection ADD CONSTRAINT t_selection_pkey PRIMARY KEY (ad_pinstance_id, t_selection_id, t_selection_uu); + +ALTER TABLE t_selection_infowindow ADD t_selection_uu VARCHAR2(36 CHAR) DEFAULT '' NOT NULL; + +ALTER TABLE t_selection_infowindow MODIFY t_selection_id DEFAULT 0; + +ALTER TABLE t_selection_infowindow DROP CONSTRAINT t_selection_infowindow_key; + +DROP INDEX t_selection_infowindow_key; + +ALTER TABLE t_selection_infowindow ADD CONSTRAINT t_selection_infowindow_key PRIMARY KEY (ad_pinstance_id, t_selection_id, t_selection_uu, columnname); + +-- Apr 6, 2023, 1:39:46 AM CEST +UPDATE AD_Reference SET IsActive='Y',Updated=TO_TIMESTAMP('2023-04-06 01:39:46','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200235 +; + +-- Apr 8, 2023, 12:42:49 PM CEST +INSERT INTO AD_Reference (AD_Reference_ID,Name,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU,ShowInactive) VALUES (200240,'Record UUID','D',0,0,'Y',TO_TIMESTAMP('2023-04-08 12:42:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 12:42:49','YYYY-MM-DD HH24:MI:SS'),100,'D','N','9bab064f-725d-4fc2-bdab-3ea690905549','N') +; + +-- Apr 8, 2023, 1:00:34 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203804,0,0,'Y',TO_TIMESTAMP('2023-04-08 13:00:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:00:22','YYYY-MM-DD HH24:MI:SS'),100,'Record_UU','Record UUID',NULL,NULL,'Record UUID','D','0f02ad7f-7837-494f-b67f-092f3bba2fbc') +; + +-- Apr 8, 2023, 1:00:51 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215833,0,'Record UUID',135,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-04-08 13:00:51','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:00:51','YYYY-MM-DD HH24:MI:SS'),100,203804,'Y','N','D','N','N','N','Y','b608cf28-12a4-48ec-9e73-cecefa353432','Y',0,'N','N','N','N') +; + +-- Apr 8, 2023, 1:01:07 PM CEST +ALTER TABLE Test ADD Record_UU VARCHAR2(36 CHAR) DEFAULT NULL +; + +-- Apr 8, 2023, 1:01:18 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207617,'Record UUID',152,215833,'Y',36,300,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-08 13:01:17','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:01:17','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','008d5c60-1fca-4f56-9494-96041e502a1c','Y',280,2) +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=240, XPosition=4,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207617 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=250,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205590 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=260,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8351 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=270,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8352 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=280,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3060 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=290,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3061 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=300,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206818 +; + diff --git a/migration/iD11/postgresql/202304060001_IDEMPIERE-5567.sql b/migration/iD11/postgresql/202304060001_IDEMPIERE-5567.sql new file mode 100644 index 0000000000..91b40d7dc5 --- /dev/null +++ b/migration/iD11/postgresql/202304060001_IDEMPIERE-5567.sql @@ -0,0 +1,75 @@ +-- IDEMPIERE-5567 Support of UUID on Search (FHCA-4195) +SELECT register_migration_script('202304060001_IDEMPIERE-5567.sql') FROM dual; + +-- Apr 6, 2023, 12:01:14 AM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','UUID based table is not compatible with Record_ID',0,0,'Y',TO_TIMESTAMP('2023-04-06 00:01:13','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-06 00:01:13','YYYY-MM-DD HH24:MI:SS'),100,200830,'UUTableNotCompatibleWithRecordID','D','5b220b22-2a21-493c-81f0-877dbc083874') +; + +ALTER TABLE t_selection ADD COLUMN t_selection_uu VARCHAR(36) NOT NULL DEFAULT ''; + +ALTER TABLE t_selection ALTER COLUMN t_selection_id SET DEFAULT 0; + +ALTER TABLE t_selection DROP CONSTRAINT t_selection_pkey; + +ALTER TABLE t_selection ADD CONSTRAINT t_selection_pkey PRIMARY KEY (ad_pinstance_id, t_selection_id, t_selection_uu); + +ALTER TABLE t_selection_infowindow ADD COLUMN t_selection_uu VARCHAR(36) NOT NULL DEFAULT ''; + +ALTER TABLE t_selection_infowindow ALTER COLUMN t_selection_id SET DEFAULT 0; + +ALTER TABLE t_selection_infowindow DROP CONSTRAINT t_selection_infowindow_key; + +ALTER TABLE t_selection_infowindow ADD CONSTRAINT t_selection_infowindow_key PRIMARY KEY (ad_pinstance_id, t_selection_id, t_selection_uu, columnname); + +-- Apr 6, 2023, 1:39:46 AM CEST +UPDATE AD_Reference SET IsActive='Y',Updated=TO_TIMESTAMP('2023-04-06 01:39:46','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200235 +; + +-- Apr 8, 2023, 12:42:49 PM CEST +INSERT INTO AD_Reference (AD_Reference_ID,Name,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU,ShowInactive) VALUES (200240,'Record UUID','D',0,0,'Y',TO_TIMESTAMP('2023-04-08 12:42:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 12:42:49','YYYY-MM-DD HH24:MI:SS'),100,'D','N','9bab064f-725d-4fc2-bdab-3ea690905549','N') +; + +-- Apr 8, 2023, 1:00:34 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203804,0,0,'Y',TO_TIMESTAMP('2023-04-08 13:00:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:00:22','YYYY-MM-DD HH24:MI:SS'),100,'Record_UU','Record UUID',NULL,NULL,'Record UUID','D','0f02ad7f-7837-494f-b67f-092f3bba2fbc') +; + +-- Apr 8, 2023, 1:00:51 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215833,0,'Record UUID',135,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-04-08 13:00:51','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:00:51','YYYY-MM-DD HH24:MI:SS'),100,203804,'Y','N','D','N','N','N','Y','b608cf28-12a4-48ec-9e73-cecefa353432','Y',0,'N','N','N','N') +; + +-- Apr 8, 2023, 1:01:07 PM CEST +ALTER TABLE Test ADD COLUMN Record_UU VARCHAR(36) DEFAULT NULL +; + +-- Apr 8, 2023, 1:01:18 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207617,'Record UUID',152,215833,'Y',36,300,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-04-08 13:01:17','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-08 13:01:17','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','008d5c60-1fca-4f56-9494-96041e502a1c','Y',280,2) +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=240, XPosition=4,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207617 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=250,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205590 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=260,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8351 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=270,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8352 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=280,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3060 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=290,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3061 +; + +-- Apr 8, 2023, 1:02:12 PM CEST +UPDATE AD_Field SET SeqNo=300,Updated=TO_TIMESTAMP('2023-04-08 13:02:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206818 +; + diff --git a/org.adempiere.base.callout/src/org/adempiere/base/callout/TableIDCallout.java b/org.adempiere.base.callout/src/org/adempiere/base/callout/TableIDCallout.java index 72eee93d2d..d39914f596 100644 --- a/org.adempiere.base.callout/src/org/adempiere/base/callout/TableIDCallout.java +++ b/org.adempiere.base.callout/src/org/adempiere/base/callout/TableIDCallout.java @@ -51,6 +51,10 @@ public class TableIDCallout implements IColumnCallout { if (recordId != null) { mTab.setValue(recordId, null); } + GridField recordUU = mTab.getField("Record_UU"); + if (recordUU != null) { + mTab.setValue(recordUU, null); + } return null; } } diff --git a/org.adempiere.base/src/org/compiere/model/Query.java b/org.adempiere.base/src/org/compiere/model/Query.java index f1363a55e5..6d6eafd5d8 100644 --- a/org.adempiere.base/src/org/compiere/model/Query.java +++ b/org.adempiere.base/src/org/compiere/model/Query.java @@ -849,8 +849,12 @@ public class Query // if (whereBuffer.length() > 0) whereBuffer.append(" AND "); - whereBuffer.append(" EXISTS (SELECT 1 FROM T_Selection s WHERE s.AD_PInstance_ID=?" - +" AND s.T_Selection_ID="+table.getTableName()+"."+keys[0]+")"); + whereBuffer.append(" EXISTS (SELECT 1 FROM T_Selection s WHERE s.AD_PInstance_ID=? AND s."); + if (table.isUUIDKeyTable()) + whereBuffer.append("T_Selection_UU="); + else + whereBuffer.append("T_Selection_ID="); + whereBuffer.append(table.getTableName()).append(".").append(keys[0]).append(")"); } StringBuilder sqlBuffer = new StringBuilder(selectClause); diff --git a/org.adempiere.base/src/org/compiere/model/SystemIDs.java b/org.adempiere.base/src/org/compiere/model/SystemIDs.java index 45bdec9863..ae41caf5f7 100644 --- a/org.adempiere.base/src/org/compiere/model/SystemIDs.java +++ b/org.adempiere.base/src/org/compiere/model/SystemIDs.java @@ -150,6 +150,7 @@ public class SystemIDs public final static int REFERENCE_DATATYPE_QUANTITY = 29; public final static int REFERENCE_DATATYPE_RADIOGROUP_LIST= 200152; public final static int REFERENCE_DATATYPE_RECORD_ID = 200202; + public final static int REFERENCE_DATATYPE_RECORD_UU = 200240; public final static int REFERENCE_DATATYPE_ROWID = 26; public final static int REFERENCE_DATATYPE_SCHEDULER_STATE = 200173; public final static int REFERENCE_DATATYPE_SEARCH = 30; diff --git a/org.adempiere.base/src/org/compiere/util/DB.java b/org.adempiere.base/src/org/compiere/util/DB.java index 25314975e0..79bfdd6dfa 100644 --- a/org.adempiere.base/src/org/compiere/util/DB.java +++ b/org.adempiere.base/src/org/compiere/util/DB.java @@ -38,6 +38,7 @@ import java.util.logging.Level; import javax.sql.RowSet; +import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.adempiere.util.ProcessUtil; import org.compiere.Adempiere; @@ -2408,24 +2409,51 @@ public final class DB * saveKeys is map with key is rowID, value is list value of all viewID * viewIDIndex is index of viewID need save. * @param AD_PInstance_ID - * @param saveKeys + * @param saveKeys - Collection of KeyNamePair * @param trxName */ - public static void createT_SelectionNew (int AD_PInstance_ID, Collection saveKeys, String trxName) + public static void createT_SelectionNew (int AD_PInstance_ID, Collection saveKeys, String trxName) { + Collection saveKeysNP = new ArrayList(); + for (NamePair saveKey : saveKeys) + saveKeysNP.add(saveKey); + createT_SelectionNewNP(AD_PInstance_ID, saveKeysNP, trxName); + } + + /** + * Create persistent selection in T_Selection table + * saveKeys is map with key is rowID, value is list value of all viewID + * viewIDIndex is index of viewID need save. + * @param AD_PInstance_ID + * @param saveKeys can receive a Collection of KeyNamePair (IDs) or ValueNamePair (UUIDs) + * @param trxName + */ + public static void createT_SelectionNewNP (int AD_PInstance_ID, Collection saveKeys, String trxName) { - StringBuilder insert = new StringBuilder(); - insert.append("INSERT INTO T_SELECTION(AD_PINSTANCE_ID, T_SELECTION_ID, ViewID) "); + String initialInsert = "INSERT INTO T_SELECTION(AD_PINSTANCE_ID, T_SELECTION_ID, T_SELECTION_UU, ViewID) "; + StringBuilder insert = new StringBuilder(initialInsert); int counter = 0; - for(KeyNamePair saveKey : saveKeys) + for(NamePair saveKey : saveKeys) { - Integer selectedId = saveKey.getKey(); + Object selectedId; + if (saveKey instanceof KeyNamePair) + selectedId = ((KeyNamePair)saveKey).getKey(); + else if (saveKey instanceof ValueNamePair) + selectedId = ((ValueNamePair)saveKey).getValue(); + else + throw new AdempiereException("NamePair type not allowed in DB.createT_SelectionNewNP, just KeyNamePair or ValueNamePair are allowed"); counter++; if (counter > 1) insert.append(" UNION "); insert.append("SELECT "); insert.append(AD_PInstance_ID); insert.append(", "); - insert.append(selectedId); + if (selectedId instanceof Integer) { + insert.append((Integer)selectedId); + insert.append(", ''"); + } else { + insert.append("0, "); + insert.append(DB.TO_STRING(selectedId.toString())); + } insert.append(", "); String viewIDValue = saveKey.getName(); @@ -2443,8 +2471,8 @@ public final class DB if (counter >= 1000) { DB.executeUpdateEx(insert.toString(), trxName); - insert = new StringBuilder(); - insert.append("INSERT INTO T_SELECTION(AD_PINSTANCE_ID, T_SELECTION_ID, ViewID) "); + insert.delete(0, insert.length()); + insert.append(initialInsert); counter = 0; } } diff --git a/org.adempiere.base/src/org/compiere/util/DisplayType.java b/org.adempiere.base/src/org/compiere/util/DisplayType.java index ca44ea4242..85cdbb9fa0 100644 --- a/org.adempiere.base/src/org/compiere/util/DisplayType.java +++ b/org.adempiere.base/src/org/compiere/util/DisplayType.java @@ -47,6 +47,7 @@ import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_PRODUCTATTRIBUTE; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_QUANTITY; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_RADIOGROUP_LIST; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_RECORD_ID; +import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_RECORD_UU; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_ROWID; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_SCHEDULER_STATE; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_SEARCH; @@ -194,6 +195,7 @@ public final class DisplayType public static final int RecordID = REFERENCE_DATATYPE_RECORD_ID; + public static final int RecordUU = REFERENCE_DATATYPE_RECORD_UU; public static final int TimestampWithTimeZone = REFERENCE_DATATYPE_TIMESTAMP_WITH_TIMEZONE; @@ -283,7 +285,7 @@ public final class DisplayType public static boolean isUUID (int displayType) { if (displayType == UUID || displayType == TableUU || displayType == TableDirUU - || displayType == SearchUU) + || displayType == SearchUU || displayType == RecordUU) return true; //not custom type, don't have to check factory @@ -417,7 +419,7 @@ public final class DisplayType || displayType == ChosenMultipleSelectionTable || displayType == ChosenMultipleSelectionSearch || displayType == TimeZoneId - || displayType == UUID + || displayType == UUID || displayType == RecordUU || displayType == TableDirUU || displayType == TableUU || displayType == SearchUU) return true; @@ -1135,6 +1137,8 @@ public final class DisplayType return "RadiogroupList"; case RecordID: return "RecordID"; + case RecordUU: + return "RecordUUID"; case RowID: return "RowID"; case SchedulerState: diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WInfoWindowListItemRenderer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WInfoWindowListItemRenderer.java index 29d22c7e97..2dc37b1008 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WInfoWindowListItemRenderer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WInfoWindowListItemRenderer.java @@ -31,6 +31,7 @@ import org.adempiere.webui.info.InfoWindow; import org.adempiere.webui.theme.ThemeManager; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.GridField; import org.compiere.model.InfoColumnVO; import org.compiere.model.MStyle; @@ -110,6 +111,11 @@ public class WInfoWindowListItemRenderer extends WListItemRenderer IDColumn idc = (IDColumn)value; value = idc.getRecord_ID(); } + else if(value instanceof UUIDColumn) + { + UUIDColumn idc = (UUIDColumn)value; + value = idc.getRecord_UU(); + } else if(value instanceof KeyNamePair) { KeyNamePair knp = (KeyNamePair)value; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListItemRenderer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListItemRenderer.java index 629c9e8687..79951bd9b0 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListItemRenderer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListItemRenderer.java @@ -39,6 +39,8 @@ import org.adempiere.webui.event.TableValueChangeEvent; import org.adempiere.webui.event.TableValueChangeListener; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.SelectableIDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.MImage; import org.compiere.util.DisplayType; import org.compiere.util.Env; @@ -348,10 +350,13 @@ public class WListItemRenderer implements ListitemRenderer, EventListene } } } - // if ID column make it invisible - else if (value instanceof IDColumn) + // if ID or UUID column make it invisible + else if (value instanceof IDColumn || value instanceof UUIDColumn) { - listcell.setValue(((IDColumn) value).getRecord_ID()); + if (value instanceof IDColumn) + listcell.setValue(((IDColumn) value).getRecord_ID()); + else + listcell.setValue(((UUIDColumn) value).getRecord_UU()); if (!table.isCheckmark()) { table.setCheckmark(true); table.removeEventListener(Events.ON_SELECT, this); @@ -468,7 +473,7 @@ public class WListItemRenderer implements ListitemRenderer, EventListene String headerText = headerValue.toString(); if (m_headers.size() <= headerIndex || m_headers.get(headerIndex) == null) { - if (classType != null && classType.isAssignableFrom(IDColumn.class)) + if (classType != null && (classType.isAssignableFrom(IDColumn.class) || classType.isAssignableFrom(UUIDColumn.class))) { header = new ListHeader(""); ZKUpdateUtil.setWidth(header, "30px"); @@ -500,7 +505,7 @@ public class WListItemRenderer implements ListitemRenderer, EventListene if (width > 0 && width < 180) width = 180; } - else if (classType.equals(IDColumn.class)) + else if (classType.equals(IDColumn.class) || classType.equals(UUIDColumn.class)) { header.setSort("none"); if (width < 30) @@ -681,13 +686,13 @@ public class WListItemRenderer implements ListitemRenderer, EventListene WListbox table = (WListbox) event.getTarget(); if (table.isCheckmark()) { int cnt = table.getRowCount(); - if (cnt == 0 || !(table.getValueAt(0, 0) instanceof IDColumn)) + if (cnt == 0 || !(table.getValueAt(0, 0) instanceof IDColumn || table.getValueAt(0, 0) instanceof UUIDColumn)) return; //update IDColumn tableColumn = m_tableColumns.get(0); for (int i = 0; i < cnt; i++) { - IDColumn idcolumn = (IDColumn) table.getValueAt(i, 0); + SelectableIDColumn idcolumn = (SelectableIDColumn) table.getValueAt(i, 0); Listitem item = table.getItemAtIndex(i); value = item.isSelected(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java index 377a5ce1e6..665a703671 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java @@ -17,6 +17,7 @@ package org.adempiere.webui.component; +import java.io.Serializable; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; @@ -36,6 +37,8 @@ import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; import org.compiere.minigrid.IMiniTable; +import org.compiere.minigrid.SelectableIDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.MRole; import org.compiere.model.PO; import org.compiere.util.CLogger; @@ -57,7 +60,7 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis /** * generated serial id */ - private static final long serialVersionUID = -5501893389366975849L; + private static final long serialVersionUID = 3758442599469915640L; /** Logger. */ private static final CLogger logger = CLogger.getCLogger(WListbox.class); @@ -237,8 +240,8 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis // F3P: If allowed, use idcolumn as a switch for read/write (Some logic as boolean) if(allowIDColumnForReadWrite && column != 0 - && val instanceof IDColumn - && ((IDColumn)val).isSelected() == false) + && val instanceof SelectableIDColumn + && ((SelectableIDColumn)val).isSelected() == false) { return false; } @@ -418,7 +421,7 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis { setColorColumn(columnIndex); } - if (layout[columnIndex].getColClass() == IDColumn.class) + if (layout[columnIndex].getColClass() == IDColumn.class || layout[columnIndex].getColClass() == UUIDColumn.class) { m_keyColumnIndex = columnIndex; } @@ -626,6 +629,10 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis { data = new IDColumn(rs.getInt(rsColIndex)); } + else if (columnClass == UUIDColumn.class) + { + data = new UUIDColumn(rs.getString(rsColIndex)); + } else if (columnClass == Boolean.class) { data = Boolean.valueOf(rs.getString(rsColIndex).equals("Y")); @@ -739,6 +746,10 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis { data = new IDColumn(((Integer)data).intValue()); } + else if (columnClass == UUIDColumn.class) + { + data = new UUIDColumn(data.toString()); + } else if (columnClass == Double.class) { data = Double.valueOf(((BigDecimal)data).doubleValue()); @@ -768,9 +779,9 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis * Get the key of currently selected row based on layout defined in * {@link #prepareTable(ColumnInfo[], String, String, boolean, String)}. * - * @return ID if key + * @return ID (int) or UUID (String) - if key */ - public Integer getSelectedRowKey() + public T getSelectedRowKey() { if (m_layout == null) { @@ -787,22 +798,22 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis * IDEMPIERE-1334 * get key of record at index * @param index - * @return + * @return ID (int) or UUID (String) */ - public Integer getRowKeyAt (int index){ + @SuppressWarnings("unchecked") + public T getRowKeyAt (int index){ if (index < 0 || m_keyColumnIndex < 0) return null; Object data = getModel().getDataAt(index, m_keyColumnIndex); if (data instanceof IDColumn) - { data = ((IDColumn)data).getRecord_ID(); - } - if (data instanceof Integer) - { - return (Integer)data; - } + else if (data instanceof UUIDColumn) + data = ((UUIDColumn)data).getRecord_UU(); + + if (data instanceof Integer || data instanceof String) + return (T) data; return null; } @@ -819,7 +830,7 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis ListModelTable model = getModel(); List lsSelectedItem = new ArrayList (); for (int index = 0; index < model.getSize(); index++){ - Integer key = getRowKeyAt(index); + Object key = getRowKeyAt(index); if (key == null) continue; @@ -833,7 +844,7 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis /** * @return key for first row (row 0). null if table is empty. */ - public Integer getFirstRowKey() + public T getFirstRowKey() { if (m_layout == null) { @@ -1066,21 +1077,20 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis int col = event.getColumn(); // column of table field which caused the event int row = event.getRow(); // row of table field which caused the event boolean newBoolean; - IDColumn idColumn; // if the event was caused by an ID Column and the value is a boolean // then set the IDColumn's select field if (col >= 0 && row >=0) { - if (this.getValueAt(row, col) instanceof IDColumn + if (this.getValueAt(row, col) instanceof SelectableIDColumn && event.getNewValue() instanceof Boolean) { newBoolean = ((Boolean)event.getNewValue()).booleanValue(); - idColumn = (IDColumn)this.getValueAt(row, col); + SelectableIDColumn idColumn = (SelectableIDColumn)this.getValueAt(row, col); idColumn.setSelected(newBoolean); this.setValueAt(idColumn, row, col); } - // othewise just set the value in the model to the new value + // otherwise just set the value in the model to the new value else { this.setValueAt(event.getNewValue(), row, col); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java index 9b2fdd6758..a10902d1f6 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java @@ -113,10 +113,10 @@ public class InfoListSubModel implements ListSubModel { int rowCount = ip.getRowCount(); if (rowCount > 0) { List added = new ArrayList(); - List keys = new ArrayList(); + List keys = new ArrayList(); for(int i = 0; i < rowCount; i++) { - Integer key = ip.getRowKeyAt(i); - if (key != null && key.intValue() > 0 && !keys.contains(key)) { + Object key = ip.getRowKeyAt(i); + if (key != null && (key instanceof Integer && ((Integer)key).intValue() > 0 || key instanceof String && key.toString().length() > 0) && !keys.contains(key)) { keys.add(key); } if (nRows > 0 && keys.size() >= nRows) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WRecordIDEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WRecordIDEditor.java index 556f659d75..145a80555c 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WRecordIDEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WRecordIDEditor.java @@ -38,6 +38,7 @@ import org.adempiere.webui.event.ContextMenuEvent; import org.adempiere.webui.event.ContextMenuListener; import org.adempiere.webui.event.ValueChangeEvent; import org.adempiere.webui.theme.ThemeManager; +import org.adempiere.webui.window.Dialog; import org.adempiere.webui.window.FindWindow; import org.adempiere.webui.window.WFieldRecordInfo; import org.adempiere.webui.window.WRecordIDDialog; @@ -201,13 +202,23 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo { String s = tableIDValue != null ? String.valueOf(tableIDValue) : ""; int tableID = s.length() > 0 ? Integer.parseInt(s) : 0; - s = recordIDValue != null ? String.valueOf(recordIDValue) : ""; - int recordID = s.length() > 0 ? Integer.parseInt(s) : 0; - if(tableID <= 0 || recordID < 0) - return; - if (!MRole.getDefault().isTableAccess(tableID, false)) - throw new AdempiereException(Msg.getMsg(Env.getCtx(), "AccessTableNoView")); - AEnv.zoom(tableID, recordID); + MTable table = MTable.get(tableID); + if (table.isUUIDKeyTable()) { + String recordUU = recordIDValue != null ? recordIDValue.toString() : ""; + if(tableID <= 0) + return; + if (!MRole.getDefault().isTableAccess(tableID, false)) + throw new AdempiereException(Msg.getMsg(Env.getCtx(), "AccessTableNoView")); + AEnv.zoomUU(tableID, recordUU); + } else { + s = recordIDValue != null ? String.valueOf(recordIDValue) : ""; + int recordID = s.length() > 0 ? Integer.parseInt(s) : 0; + if(tableID <= 0 || recordID < 0) + return; + if (!MRole.getDefault().isTableAccess(tableID, false)) + throw new AdempiereException(Msg.getMsg(Env.getCtx(), "AccessTableNoView")); + AEnv.zoom(tableID, recordID); + } } @@ -251,11 +262,18 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo if (GridField.PROPERTY.equals(evt.getPropertyName())) { int tableID = tableIDValue != null ? Integer.parseInt(String.valueOf(tableIDValue)) : 0; - int recordID = Integer.parseInt(Objects.toString(evt.getNewValue(), "-1")); - if (tableID > 0 && recordID >= 0) - { - MTable table = MTable.get(Env.getCtx(), tableID); - table.getPO(recordID, null); // calls po.checkCrossTenant() method + if (tableID > 0) { + MTable table = MTable.get(tableID); + if (table.isUUIDKeyTable()) { + String recordUU = Objects.toString(evt.getNewValue(), ""); + if (tableID > 0 && recordUU.length() > 0) + table.getPOByUU(recordUU, null); // calls po.checkCrossTenant() method + + } else { + int recordID = Integer.parseInt(Objects.toString(evt.getNewValue(), "-1")); + if (tableID > 0 && recordID >= 0) + table.getPO(recordID, null); // calls po.checkCrossTenant() method + } } setValue(evt.getNewValue(), false); } @@ -283,10 +301,17 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo tableIDValue = tableIDGridField.getValue(); } if(value != null && tableIDValue != null) { - int recordID = Integer.parseInt(String.valueOf(value)); int tableID = Integer.parseInt(String.valueOf(tableIDValue)); - if(recordID >= 0 && tableID > 0) - recordTextBox.setValue(getIdentifier(tableID, recordID)); + if (tableID > 0) { + MTable table = MTable.get(tableID); + Object recordID; + if (table.isUUIDKeyTable()) + recordID = value.toString(); + else + recordID = Integer.parseInt(String.valueOf(value)); + if(recordID != null && tableID > 0) + recordTextBox.setValue(getIdentifier(tableID, recordID)); + } } } @@ -294,7 +319,7 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo && ( (value == null && recordIDValue != null) || (value != null && recordIDValue == null) - || !value.equals(recordIDValue) + || (value != null && !value.equals(recordIDValue)) )) { // Record_ID ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), recordIDValue, value); @@ -314,10 +339,14 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo return ""; if((tableIDValue != null) && (recordIDValue != null)) { int tableID; - int recordID; + Object recordID; try { tableID = Integer.parseInt(String.valueOf(tableIDValue)); - recordID = Integer.parseInt(String.valueOf(recordIDValue)); + MTable table = MTable.get(tableID); + if (table.isUUIDKeyTable()) + recordID = recordIDValue.toString(); + else + recordID = Integer.parseInt(String.valueOf(recordIDValue)); } catch (NumberFormatException e) { return recordIDValue.toString(); } @@ -336,10 +365,14 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo String key = gridTab.getWindowNo() + "|AD_Table_ID"; Object rowTableIdValue = gridRowCtx.get(key); int rowTableID; - int rowRecordID; + Object rowRecordID; try { rowTableID = Integer.parseInt(String.valueOf(rowTableIdValue)); - rowRecordID = Integer.parseInt(String.valueOf(value)); + MTable table = MTable.get(rowTableID); + if (table.isUUIDKeyTable()) + rowRecordID = value.toString(); + else + rowRecordID = Integer.parseInt(String.valueOf(value)); } catch (NumberFormatException e) { return value.toString(); } @@ -364,6 +397,15 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo tableIDValue = Integer.parseInt(tableIdTxt); } } + if (tableIDValue != null && tableIDValue instanceof Integer) { + MTable table = MTable.get((Integer)tableIDValue); + if (table.isUUIDKeyTable()) { + if (! getColumnName().endsWith("_UU")) { + Dialog.error(tableIDGridField.getWindowNo(), "UUTableNotCompatibleWithRecordID"); + return; + } + } + } new WRecordIDDialog(recordTextBox.getPage(), this, tableIDGridField); } } @@ -404,7 +446,7 @@ public class WRecordIDEditor extends WEditor implements ContextMenuListener, IZo * @param recordID * @return String */ - public String getIdentifier(int tableID, int recordID) { + public String getIdentifier(int tableID, Object recordID) { MLookup lookup = getRecordsLookup(tableID); return lookup != null ? lookup.getDisplay(recordID) : ""; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java index 92f0513204..5d7f51245d 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java @@ -459,7 +459,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value } if (log.isLoggable(Level.CONFIG)) log.config(getColumnName() + " - " + text); - int id = -1; + Object id = null; if (m_tableName == null) // sets table name & key column setTableAndKeyColumn(); @@ -467,15 +467,27 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value final InfoPanel ip = InfoManager.create(lookup, gridField, m_tableName, m_keyColumnName, getComponent().getText(), false, getWhereClause()); if (ip != null && ip.loadedOK() && ip.getRowCount() == 1) { - Integer key = ip.getFirstRowKey(); - if (key != null && key.intValue() > 0) + if (ip.getFirstRowKey() instanceof Integer) { - id = key.intValue(); + Integer key = (Integer) ip.getFirstRowKey(); + if (key != null && key.intValue() > 0) + { + id = key.intValue(); + } } + else + { + Object key = ip.getFirstRowKey(); + if (key != null && key.toString().length() > 0) + { + id = key.toString(); + } + } + } // No (unique) result - if (id <= 0) + if (id == null || (id instanceof Integer && ((Integer) id).intValue() <= 0)) { //m_value = null; // force re-display if (ip != null && ip.loadedOK()) @@ -492,7 +504,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value if (log.isLoggable(Level.FINE)) log.fine(getColumnName() + " - Unique ID=" + id); - actionCombo(Integer.valueOf(id)); // data binding + actionCombo(id); // data binding focusNext(); //safety check: if focus is going no where, focus back to self diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java index 07b7598cb1..02e2225436 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java @@ -232,7 +232,7 @@ public class DefaultEditorFactory implements IEditorFactory { { editor = new WTimeZoneEditor(gridField, tableEditor); } - else if (displayType == DisplayType.RecordID) + else if (displayType == DisplayType.RecordID || displayType == DisplayType.RecordUU) { editor = new WRecordIDEditor(gridField, tableEditor, editorConfiguration); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java index fb7a63c1b7..b929ad2fa6 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java @@ -90,6 +90,8 @@ import org.adempiere.webui.window.Dialog; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.EmbedWinInfo; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.SelectableIDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.AccessSqlParser.TableInfo; import org.compiere.model.GridField; import org.compiere.model.GridFieldVO; @@ -197,8 +199,8 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL // F3P: Keep original values: when a row is unselected, restore original values private boolean hasEditable = false; - private Map> cacheOriginalValues = new HashMap<>(); - private Map> temporarySelectedData = new HashMap<>(); + private Map> cacheOriginalValues = new HashMap<>(); + private Map> temporarySelectedData = new HashMap<>(); private WInfoWindowListItemRenderer infoWindowListItemRenderer = null; // F3P: export @@ -929,7 +931,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL : tableInfos[0].getTableName(); String keySelectClause = keyTableAlias+"."+p_keyColumn; - list.add(new ColumnInfo(" ", keySelectClause, IDColumn.class, true, false, null, p_keyColumn)); + if (p_keyColumn.endsWith("_UU")) + list.add(new ColumnInfo(" ", keySelectClause, UUIDColumn.class, true, false, null, p_keyColumn)); + else + list.add(new ColumnInfo(" ", keySelectClause, IDColumn.class, true, false, null, p_keyColumn)); List gridDisplayedIC = new ArrayList<>(); gridDisplayedIC.add(null); // First column does not have any matching info column @@ -980,7 +985,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL gridDisplayedIC.add(infoColumn); if (keyColumnOfView == infoColumn.getAD_InfoColumn()){ - if (columnInfo.getColClass().equals(IDColumn.class)) + if (columnInfo.getColClass().equals(IDColumn.class) || columnInfo.getColClass().equals(UUIDColumn.class)) isIDColumnKeyOfView = true; indexKeyOfView = list.size() - 1; } @@ -2708,6 +2713,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL IDColumn idc = (IDColumn)val; val = idc.getRecord_ID(); } + else if(val instanceof UUIDColumn) + { + UUIDColumn idc = (UUIDColumn)val; + val = idc.getRecord_UU(); + } else if(val instanceof KeyNamePair) { KeyNamePair knp = (KeyNamePair)val; @@ -2824,7 +2834,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL */ protected void restoreOriginalValues(int rowIndex) { - Integer viewIdKey = getColumnValue(rowIndex); + Object viewIdKey = getColumnValue(rowIndex); if(cacheOriginalValues.containsKey(viewIdKey)) // Only cache if not cached to avoid caching subsequent modifications { @@ -2845,7 +2855,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL */ protected void cacheOriginalValues(int rowIndex) { - Integer viewIdKey = getColumnValue(rowIndex); + Object viewIdKey = getColumnValue(rowIndex); if(cacheOriginalValues.containsKey(viewIdKey) == false) // Only cache if not cached to avoid caching subsequent modifications { @@ -2873,10 +2883,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL { Object col0 = contentPanel.getValueAt(row, 0); - if(col0 instanceof IDColumn) + if(col0 instanceof SelectableIDColumn) { - IDColumn idc = (IDColumn)col0; - + SelectableIDColumn idc = (SelectableIDColumn)col0; + if(idc.isSelected()) { cacheOriginalValues(row); @@ -2916,7 +2926,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL for(int rowIndex:contentPanel.getSelectedIndices()) { - Integer keyViewValue = getColumnValue(rowIndex); + Object keyViewValue = getColumnValue(rowIndex); @SuppressWarnings("unchecked") List row = (List)model.get(rowIndex); @@ -2924,7 +2934,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL temporarySelectedData.put(keyViewValue, clonedRow); } - for(Entry> entry: recordSelectedData.entrySet()) + for(Entry> entry: recordSelectedData.entrySet()) { ArrayList clonedRow = new ArrayList<>(entry.getValue()); temporarySelectedData.put(entry.getKey(), clonedRow); @@ -2948,7 +2958,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL @Override - public boolean onRestoreSelectedItemIndexInPage(Integer keyViewValue, int rowIndex, Object oRow) + public boolean onRestoreSelectedItemIndexInPage(Object keyViewValue, int rowIndex, Object oRow) { if(hasEditable && temporarySelectedData != null) { @@ -2976,15 +2986,19 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } // Restore isSelected status on IDColumn - Object id = (IDColumn)row.get(0); - + Object id = row.get(0); if(id instanceof IDColumn) { IDColumn idc = (IDColumn)id; idc.setSelected(true); } + else if (id instanceof UUIDColumn) + { + UUIDColumn idc = (UUIDColumn)id; + idc.setSelected(true); + } - // Restore listners + // Restore listeners model.addTableModelListener(this); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java index 7d97319f4c..3c6d02f196 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java @@ -33,6 +33,7 @@ import org.adempiere.webui.editor.WEditor; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.EmbedWinInfo; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.MSysConfig; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -120,6 +121,9 @@ public class RelatedInfoWindow implements EventListener, Sortable if (parentId != null && parentId instanceof IDColumn){ IDColumn ID = (IDColumn) parentId; linkPara = ID.getRecord_ID(); + } else if (parentId != null && parentId instanceof UUIDColumn) { + UUIDColumn ID = (UUIDColumn) parentId; + linkPara = ID.getRecord_UU(); }else if (parentId != null){ linkPara = parentId.toString(); } @@ -342,6 +346,9 @@ public class RelatedInfoWindow implements EventListener, Sortable if (parentId != null && parentId instanceof IDColumn){ IDColumn ID = (IDColumn) parentId; linkPara = ID.getRecord_ID(); + } else if (parentId != null && parentId instanceof UUIDColumn) { + UUIDColumn ID = (UUIDColumn) parentId; + linkPara = ID.getRecord_UU(); }else if (parentId != null){ linkPara = parentId.toString(); } @@ -423,9 +430,9 @@ public class RelatedInfoWindow implements EventListener, Sortable Class c = columnsLayout[col].getColClass(); int colIndex = col + colOffset; if (c == IDColumn.class) - { value = new IDColumn(rs.getInt(colIndex)); - } + else if (c == UUIDColumn.class) + value = new UUIDColumn(rs.getString(colIndex)); else if (c == Boolean.class) value = Boolean.valueOf("Y".equals(rs.getString(colIndex))); else if (c == Timestamp.class) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoAssignmentPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoAssignmentPanel.java index 24554e68bb..9af67e7e40 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoAssignmentPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoAssignmentPanel.java @@ -396,7 +396,7 @@ public class InfoAssignmentPanel extends InfoPanel implements EventListener 0) + if (getSelectedRowKey() != null && getSelectedRowKey() instanceof Integer && ((Integer)getSelectedRowKey()).intValue() > 0) { MQuery zoomQuery = new MQuery(); // ColumnName might be changed in MTab.validateQuery String column = getKeyColumn(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java index 828e9204bb..70813d8c53 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java @@ -37,12 +37,14 @@ import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.Dialog; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.GridField; import org.compiere.model.I_C_ElementValue; import org.compiere.model.MColumn; import org.compiere.model.MLookupFactory; import org.compiere.model.MReference; import org.compiere.model.MTable; +import org.compiere.model.PO; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; @@ -390,9 +392,11 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener private boolean initInfoTable () { - // Get Query Columns + MTable table = MTable.get(Env.getCtx(), p_tableName); + String uucolName = PO.getUUIDColumnName(p_tableName); - String sql = "SELECT c.ColumnName, t.AD_Table_ID, t.TableName, c.ColumnSql " + // Get Query Columns + final String sqlqc = "SELECT c.ColumnName, t.AD_Table_ID, t.TableName, c.ColumnSql " + "FROM AD_Table t" + " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID)" + "WHERE c.AD_Reference_ID IN (10,14)" @@ -410,7 +414,7 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener ResultSet rs = null; try { - pstmt = DB.prepareStatement(sql, null); + pstmt = DB.prepareStatement(sqlqc, null); pstmt.setString(1, p_tableName); rs = pstmt.executeQuery(); @@ -437,7 +441,7 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener } catch (SQLException e) { - log.log(Level.SEVERE, sql, e); + log.log(Level.SEVERE, sqlqc, e); return false; } finally @@ -466,23 +470,27 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener } // Set Title - String title = Msg.translate(Env.getCtx(), tableName + "_ID"); // best bet - - if (title.endsWith("_ID")) - title = Msg.translate(Env.getCtx(), tableName); // second best bet + String title = null; + if (table.isUUIDKeyTable()) + title = Msg.translate(Env.getCtx(), uucolName); + else { + title = Msg.translate(Env.getCtx(), tableName + "_ID"); // best bet + if (title.endsWith("_ID")) + title = Msg.translate(Env.getCtx(), tableName); // second best bet + } setTitle(getTitle() + " " + title); // Get Display Columns int AD_Window_ID = 0; - MTable table = MTable.get(AD_Table_ID); if (table.getAD_Window_ID() > 0) { AD_Window_ID = table.getAD_Window_ID(); } else { AD_Window_ID = table.getWindowIDFromMenu(); } ArrayList list = new ArrayList(); - sql = "SELECT c.ColumnName, c.AD_Reference_ID, c.IsKey, f.IsDisplayed, c.AD_Reference_Value_ID, c.ColumnSql, c.AD_Column_ID " + StringBuilder sqlc = new StringBuilder().append( + "SELECT c.ColumnName, c.AD_Reference_ID, c.IsKey, f.IsDisplayed, c.AD_Reference_Value_ID, c.ColumnSql, c.AD_Column_ID " + "FROM AD_Column c" + " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID)" + " INNER JOIN AD_Tab tab ON (t.AD_Table_ID=tab.AD_Table_ID)" @@ -493,11 +501,16 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener + " AND (c.IsKey='Y' OR " + " (f.IsEncrypted='N' AND f.ObscureType IS NULL)) " + " AND c.IsActive = 'Y' " - + "ORDER BY c.IsKey DESC, f.SeqNo"; + + "ORDER BY "); + if (table.isUUIDKeyTable()) + sqlc.append("CASE WHEN c.columnname=").append(DB.TO_STRING(uucolName)).append("THEN 0 ELSE 1 END"); + else + sqlc.append("c.IsKey DESC"); + sqlc.append(", f.SeqNo"); try { - pstmt = DB.prepareStatement(sql, null); + pstmt = DB.prepareStatement(sqlc.toString(), null); pstmt.setInt(1, AD_Table_ID); pstmt.setInt(2, AD_Window_ID); rs = pstmt.executeQuery(); @@ -523,6 +536,8 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener if (isKey) colClass = IDColumn.class; + else if (uucolName.equals(columnName) && table.isUUIDKeyTable()) + colClass = UUIDColumn.class; else if (!isDisplayed) ; else if (displayType == DisplayType.YesNo) @@ -577,7 +592,7 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener } catch (SQLException e) { - log.log(Level.SEVERE, sql, e); + log.log(Level.SEVERE, sqlc.toString(), e); return false; } finally @@ -590,7 +605,7 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener if (list.size() == 0) { Dialog.error(p_WindowNo, "Error", "No Info Columns"); - log.log(Level.SEVERE, "No Info for AD_Table_ID=" + AD_Table_ID + " - " + sql); + log.log(Level.SEVERE, "No Info for AD_Table_ID=" + AD_Table_ID + " - " + sqlc.toString()); return false; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java index 318cb08f72..8fd9c6f728 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java @@ -18,6 +18,7 @@ package org.adempiere.webui.panel; import java.awt.event.MouseEvent; +import java.io.Serializable; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -70,6 +71,7 @@ import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.Dialog; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; +import org.compiere.minigrid.UUIDColumn; import org.compiere.model.GridField; import org.compiere.model.InfoColumnVO; import org.compiere.model.InfoRelatedVO; @@ -90,6 +92,7 @@ import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Msg; +import org.compiere.util.NamePair; import org.compiere.util.Trx; import org.compiere.util.Util; import org.compiere.util.ValueNamePair; @@ -146,7 +149,7 @@ public abstract class InfoPanel extends Window implements EventListener, // attribute key of info process protected final static String ATT_INFO_PROCESS_KEY = "INFO_PROCESS"; protected int pageSize; - public LinkedHashMap> m_values = null; + public LinkedHashMap> m_values = null; protected InfoRelatedVO[] relatedInfoList; // for test disable load all record when num of record < 1000 protected boolean isIgnoreCacheAll = true; @@ -171,7 +174,7 @@ public abstract class InfoPanel extends Window implements EventListener, /** * store selected record info * key of map is value of column play as keyView - * in case has no key coloumn of view, use value of {@link #p_keyColumn} + * in case has no key column of view, use value of {@link #p_keyColumn} * zk6.x listview don't provide event when click to checkbox select all, * so we can't manage selectedRecord time by time. * each time change page we will update this list with current @@ -180,7 +183,7 @@ public abstract class InfoPanel extends Window implements EventListener, * onclick. because don't direct use recordSelectedData, call * {@link #getSelectedRowInfo()} */ - protected Map> recordSelectedData = new HashMap>(); + protected Map> recordSelectedData = new HashMap>(); /** * when requery but don't clear selected record (example after run process) @@ -477,7 +480,7 @@ public abstract class InfoPanel extends Window implements EventListener, /** Cancel pressed - need to differentiate between OK - Cancel - Exit */ private boolean m_cancel = false; /** Result IDs */ - private ArrayList m_results = new ArrayList(3); + private ArrayList m_results = new ArrayList(3); private ListModelTable model; /** Layout of Grid */ @@ -569,7 +572,7 @@ public abstract class InfoPanel extends Window implements EventListener, /** * save selected id and viewID */ - protected Collection m_viewIDMap = new ArrayList (); + protected Collection m_viewIDMap = new ArrayList (); /** * store index of infoColumn have data append. each infoColumn just append only one time. @@ -638,7 +641,7 @@ public abstract class InfoPanel extends Window implements EventListener, int selectedCount = recordSelectedData.size(); for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){ - Integer keyCandidate = getColumnValue(rowIndex); + Object keyCandidate = getColumnValue(rowIndex); @SuppressWarnings("unchecked") List candidateRecord = (List)contentPanel.getModel().get(rowIndex); @@ -730,10 +733,9 @@ public abstract class InfoPanel extends Window implements EventListener, Class c = p_layout[col].getColClass(); int colIndex = col + colOffset; if (c == IDColumn.class) - { value = new IDColumn(rs.getInt(colIndex)); - - } + else if (c == UUIDColumn.class) + value = new UUIDColumn(rs.getString(colIndex)); else if (c == Boolean.class) value = Boolean.valueOf("Y".equals(rs.getString(colIndex))); else if (c == Timestamp.class) @@ -1513,7 +1515,7 @@ public abstract class InfoPanel extends Window implements EventListener, } else // singleSelection { - Integer data = getSelectedRowKey(); + Serializable data = getSelectedRowKey(); if (data != null) m_results.add(data); } @@ -1529,9 +1531,9 @@ public abstract class InfoPanel extends Window implements EventListener, * Get the key of currently selected row * @return selected key */ - protected Integer getSelectedRowKey() + protected T getSelectedRowKey() { - Integer key = contentPanel.getSelectedRowKey(); + T key = contentPanel.getSelectedRowKey(); return key; } // getSelectedRowKey @@ -1542,10 +1544,10 @@ public abstract class InfoPanel extends Window implements EventListener, * @return IDs if selection present * author ashley */ - protected ArrayList getSelectedRowKeys() + protected ArrayList getSelectedRowKeys() { - ArrayList selectedDataList = new ArrayList(); - Collection lsKeyValueOfSelectedRow = getSelectedRowInfo().keySet(); + ArrayList selectedDataList = new ArrayList(); + Collection lsKeyValueOfSelectedRow = getSelectedRowInfo().keySet(); if (lsKeyValueOfSelectedRow.size() == 0) { return selectedDataList; @@ -1553,7 +1555,7 @@ public abstract class InfoPanel extends Window implements EventListener, if (p_multipleSelection) { - for (Integer key : lsKeyValueOfSelectedRow){ + for (Object key : lsKeyValueOfSelectedRow){ selectedDataList.add(key); } } @@ -1566,7 +1568,7 @@ public abstract class InfoPanel extends Window implements EventListener, * @deprecated use getSaveKeys * @return selected keys (Integers) */ - public Collection getSelectedKeysCollection() + public Collection getSelectedKeysCollection() { m_ok = true; saveSelection(); @@ -1579,18 +1581,18 @@ public abstract class InfoPanel extends Window implements EventListener, * Save selected id, viewID of all process to map viewIDMap to save into T_Selection * @param infoCulumnId */ - public Collection getSaveKeys (int infoCulumnId){ + public Collection getSaveKeys (int infoCulumnId){ // clear result from prev time m_viewIDMap.clear(); if (p_multipleSelection) { - Map > selectedRow = getSelectedRowInfo(); + Map > selectedRow = getSelectedRowInfo(); - for (Entry> selectedInfo : selectedRow.entrySet()) + for (Entry> selectedInfo : selectedRow.entrySet()) { // get key data column - Integer keyData = selectedInfo.getKey(); + Object keyData = selectedInfo.getKey(); if (infoCulumnId > 0){ // have viewID, get it @@ -1598,11 +1600,16 @@ public abstract class InfoPanel extends Window implements EventListener, // get row data from model Object viewIDValue = selectedInfo.getValue().get(dataIndex); - - m_viewIDMap.add (new KeyNamePair(keyData, viewIDValue == null?null:viewIDValue.toString())); + if (keyData instanceof String) + m_viewIDMap.add (new ValueNamePair((String) keyData, viewIDValue == null?null:viewIDValue.toString())); + else + m_viewIDMap.add (new KeyNamePair((Integer) keyData, viewIDValue == null?null:viewIDValue.toString())); }else{ // hasn't viewID, set viewID value is null - m_viewIDMap.add (new KeyNamePair(keyData, null)); + if (keyData instanceof String) + m_viewIDMap.add (new ValueNamePair((String) keyData, null)); + else + m_viewIDMap.add (new KeyNamePair((Integer) keyData, null)); } } @@ -1659,7 +1666,7 @@ public abstract class InfoPanel extends Window implements EventListener, */ protected void updateListSelected (){ for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){ - Integer keyCandidate = getColumnValue(rowIndex); + Object keyCandidate = getColumnValue(rowIndex); @SuppressWarnings("unchecked") List candidateRecord = (List)contentPanel.getModel().get(rowIndex); @@ -1670,15 +1677,22 @@ public abstract class InfoPanel extends Window implements EventListener, if (recordSelectedData.containsKey(keyCandidate)){// unselected record List recordSelected = recordSelectedData.get(keyCandidate); IDColumn idcSel = null; + UUIDColumn uucSel = null; if (recordSelected.get(0) instanceof IDColumn) { idcSel = (IDColumn) recordSelected.get(0); + } else if (recordSelected.get(0) instanceof UUIDColumn) { + uucSel = (UUIDColumn) recordSelected.get(0); } IDColumn idcCan = null; + UUIDColumn uucCan = null; if (candidateRecord.get(0) instanceof IDColumn) { idcCan = (IDColumn) candidateRecord.get(0); + } else if (candidateRecord.get(0) instanceof UUIDColumn) { + uucCan = (UUIDColumn) candidateRecord.get(0); } - if (idcSel != null && idcCan != null && idcSel.getRecord_ID().equals(idcCan.getRecord_ID())) { - recordSelected.set(0, candidateRecord.get(0)); // set same IDColumn for comparison + if ( (idcSel != null && idcCan != null && idcSel.getRecord_ID().equals(idcCan.getRecord_ID())) + || (uucSel != null && uucCan != null && uucSel.getRecord_UU().equals(uucCan.getRecord_UU())) ) { + recordSelected.set(0, candidateRecord.get(0)); // set same ID/UUID Column for comparison } if (recordSelected.equals(candidateRecord)) { recordSelectedData.remove(keyCandidate); @@ -1712,7 +1726,7 @@ public abstract class InfoPanel extends Window implements EventListener, Collection lsSelectionRecord = new ArrayList(); for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){ - Integer keyViewValue = getColumnValue(rowIndex); + Object keyViewValue = getColumnValue(rowIndex); if (recordSelectedData.containsKey(keyViewValue)){ // TODO: maybe add logic to check value of current record (focus only to viewKeys value) is same as value save in lsSelectedKeyValue // because record can change by other user @@ -1733,7 +1747,7 @@ public abstract class InfoPanel extends Window implements EventListener, * @param row row * @return false to skip restore selection */ - public boolean onRestoreSelectedItemIndexInPage(Integer keyViewValue, int rowIndex, Object row) + public boolean onRestoreSelectedItemIndexInPage(Object keyViewValue, int rowIndex, Object row) { return true; } @@ -1744,15 +1758,15 @@ public abstract class InfoPanel extends Window implements EventListener, return new AdempiereException(errorMessage); } /** - * get keyView value at rowIndex and clumnIndex - * also check in case value is null will rise a exception + * get keyView value at rowIndex and columnIndex + * also check in case value is null will raise an exception * @param rowIndex * @return */ - protected Integer getColumnValue (int rowIndex){ + protected Object getColumnValue (int rowIndex){ int keyIndex = getIndexKeyColumnOfView(); - Integer keyValue = null; + Object keyValue = null; // get row data from model Object keyColumValue = contentPanel.getModel().getDataAt(rowIndex, keyIndex); // throw exception when value is null @@ -1763,20 +1777,26 @@ public abstract class InfoPanel extends Window implements EventListener, } // IDColumn is recreate after change page, because use value of IDColumn - if (keyColumValue != null && keyColumValue instanceof IDColumn){ - keyColumValue = ((IDColumn)keyColumValue).getRecord_ID(); + if (keyColumValue != null) { + if (keyColumValue instanceof IDColumn) { + keyColumValue = ((IDColumn)keyColumValue).getRecord_ID(); + } else if (keyColumValue instanceof UUIDColumn) { + keyColumValue = ((UUIDColumn)keyColumValue).getRecord_UU(); + } } - if (keyColumValue instanceof Integer){ + if (keyColumValue instanceof Integer) { keyValue = (Integer)keyColumValue; - }else { - String msg = "keyView column must be integer"; + } else if (keyColumValue instanceof String) { + keyValue = (String)keyColumValue; + } else { + String msg = "keyView column must be integer or string"; AdempiereException ex = new AdempiereException (msg); log.severe(msg); throw ex; } - return (Integer)keyValue; + return keyValue; } /** @@ -1805,7 +1825,7 @@ public abstract class InfoPanel extends Window implements EventListener, * update list column key value of selected record and return this list * @return {@link #recordSelectedData} after update */ - public Map> getSelectedRowInfo (){ + public Map> getSelectedRowInfo (){ updateListSelected(); return recordSelectedData; } @@ -1819,7 +1839,7 @@ public abstract class InfoPanel extends Window implements EventListener, { if (!m_ok || m_results.size() == 0) return null; - return m_results.toArray(new Integer[0]); + return m_results.toArray(new Object[0]); } // getSelectedKeys; /** @@ -2372,7 +2392,7 @@ public abstract class InfoPanel extends Window implements EventListener, title = m_process.getValue(); // store in T_Selection table selected rows for Execute Process that retrieves from T_Selection in code. - DB.createT_SelectionNew(pInstanceID, getSaveKeys(getInfoColumnIDFromProcess(processId)), null); + DB.createT_SelectionNewNP(pInstanceID, getSaveKeys(getInfoColumnIDFromProcess(processId)), null); ADForm form = ADForm.openForm(adFormID, null, m_pi); Mode mode = form.getWindowMode(); @@ -2417,7 +2437,7 @@ public abstract class InfoPanel extends Window implements EventListener, if (DialogEvents.ON_BEFORE_RUN_PROCESS.equals(event.getName())){ updateListSelected(); // store in T_Selection table selected rows for Execute Process that retrieves from T_Selection in code. - DB.createT_SelectionNew(pInstanceID, getSaveKeys(getInfoColumnIDFromProcess(processModalDialog.getAD_Process_ID())), + DB.createT_SelectionNewNP(pInstanceID, getSaveKeys(getInfoColumnIDFromProcess(processModalDialog.getAD_Process_ID())), null); saveResultSelection(getInfoColumnIDFromProcess(processModalDialog.getAD_Process_ID())); createT_Selection_InfoWindow(pInstanceID); @@ -2466,25 +2486,31 @@ public abstract class InfoPanel extends Window implements EventListener, return; } - m_values = new LinkedHashMap>(); + m_values = new LinkedHashMap>(); if (p_multipleSelection) { - Map > selectedRow = getSelectedRowInfo(); + Map > selectedRow = getSelectedRowInfo(); // for selected rows - for (Entry> selectedInfo : selectedRow.entrySet()) + for (Entry> selectedInfo : selectedRow.entrySet()) { // get key and viewID - Integer keyData = selectedInfo.getKey(); - KeyNamePair kp = null; + Object keyData = selectedInfo.getKey(); + NamePair kp = null; if (infoColumnId > 0){ int dataIndex = columnDataIndex.get(infoColumnId) + p_layout.length; Object viewIDValue = selectedInfo.getValue().get(dataIndex); - kp = new KeyNamePair(keyData, viewIDValue == null ? null : viewIDValue.toString()); + if (keyData instanceof String) + kp = new ValueNamePair((String) keyData, viewIDValue == null ? null : viewIDValue.toString()); + else + kp = new KeyNamePair((Integer) keyData, viewIDValue == null ? null : viewIDValue.toString()); }else{ - kp = new KeyNamePair(keyData, null); + if (keyData instanceof String) + kp = new ValueNamePair((String) keyData, null); + else + kp = new KeyNamePair((Integer) keyData, null); } // get Data @@ -2507,9 +2533,15 @@ public abstract class InfoPanel extends Window implements EventListener, */ public void createT_Selection_InfoWindow(int AD_PInstance_ID) { + MTable table = MTable.get(Env.getCtx(), getTableName()); StringBuilder insert = new StringBuilder(); - insert.append("INSERT INTO T_Selection_InfoWindow (AD_PINSTANCE_ID, T_SELECTION_ID, COLUMNNAME , VALUE_STRING, VALUE_NUMBER , VALUE_DATE ) VALUES(?,?,?,?,?,?) "); - for (Entry> records : m_values.entrySet()) { + insert.append("INSERT INTO T_Selection_InfoWindow (AD_PINSTANCE_ID, "); + if (table.isUUIDKeyTable()) + insert.append("T_SELECTION_UU"); + else + insert.append("T_SELECTION_ID"); + insert.append(", COLUMNNAME , VALUE_STRING, VALUE_NUMBER , VALUE_DATE ) VALUES(?,?,?,?,?,?) "); + for (Entry> records : m_values.entrySet()) { //set Record ID LinkedHashMap fields = records.getValue(); @@ -2525,6 +2557,11 @@ public abstract class InfoPanel extends Window implements EventListener, KeyNamePair knp = (KeyNamePair)key; parameters.add(knp.getKey()); } + else if(key instanceof ValueNamePair) + { + ValueNamePair vnp = (ValueNamePair)key; + parameters.add(vnp.getValue()); + } else { parameters.add(key); @@ -2541,6 +2578,13 @@ public abstract class InfoPanel extends Window implements EventListener, parameters.add(id.getRecord_ID()); parameters.add(null); } + else if (data instanceof UUIDColumn) + { + UUIDColumn id = (UUIDColumn) data; + parameters.add(null); + parameters.add(id.getRecord_UU()); + parameters.add(null); + } else if (data instanceof String) { parameters.add(data); @@ -2726,7 +2770,7 @@ public abstract class InfoPanel extends Window implements EventListener, */ public void zoom() { - Integer recordId = contentPanel.getSelectedRowKey(); + Object recordId = contentPanel.getSelectedRowKey(); // prevent NPE when double click is raise but no recore is selected if (recordId == null) return; @@ -2742,13 +2786,17 @@ public abstract class InfoPanel extends Window implements EventListener, int AD_Table_ID = MTable.getTable_ID(p_tableName); if (AD_Table_ID <= 0) { - if (p_keyColumn.endsWith("_ID")) + if (p_keyColumn.endsWith("_ID") || p_keyColumn.endsWith("_UU")) { AD_Table_ID = MTable.getTable_ID(p_keyColumn.substring(0, p_keyColumn.length() - 3)); } } - if (AD_Table_ID > 0) - AEnv.zoom(AD_Table_ID, recordId); + if (AD_Table_ID > 0) { + if (recordId instanceof String) + AEnv.zoomUU(AD_Table_ID, (String) recordId); + else + AEnv.zoom(AD_Table_ID, (Integer) recordId); + } } } @@ -2805,7 +2853,7 @@ public abstract class InfoPanel extends Window implements EventListener, */ private void addAllCurrentContentPanelToSelected() { for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){ - Integer keyCandidate = getColumnValue(rowIndex); + Object keyCandidate = getColumnValue(rowIndex); @SuppressWarnings("unchecked") List candidateRecord = (List)contentPanel.getModel().get(rowIndex); if (!recordSelectedData.containsKey(keyCandidate)) { @@ -2975,7 +3023,7 @@ public abstract class InfoPanel extends Window implements EventListener, * * @return first row key/id */ - public Integer getFirstRowKey() { + public Object getFirstRowKey() { return contentPanel.getFirstRowKey(); } @@ -2984,7 +3032,7 @@ public abstract class InfoPanel extends Window implements EventListener, * @param row * @return row key/id */ - public Integer getRowKeyAt(int row) { + public Object getRowKeyAt(int row) { return contentPanel.getRowKeyAt(row); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordIDDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordIDDialog.java index 8f5357b2c9..03948e184b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordIDDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordIDDialog.java @@ -39,6 +39,8 @@ import org.adempiere.webui.event.ValueChangeListener; import org.adempiere.webui.factory.ButtonFactory; import org.compiere.model.GridField; import org.compiere.model.MLookup; +import org.compiere.model.MTable; +import org.compiere.model.PO; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Msg; @@ -69,7 +71,7 @@ public class WRecordIDDialog extends Window implements EventListener, Val /** Current tab's AD_Table_ID GrodField */ private GridField tableIDGridField; /** Current Record_ID value from {@link #editor} */ - private Integer recordIDValue; + private Object recordIDValue; /** Current AD_Table_ID value from {@link #editor} */ private Integer tableIDValue; @@ -93,17 +95,8 @@ public class WRecordIDDialog extends Window implements EventListener, Val */ public WRecordIDDialog(Page page, WRecordIDEditor editor, GridField tableIDGridField) { super(); - + this.editor = editor; - this.tableIDGridField = tableIDGridField; - if(editor.getValue() instanceof Integer) { - this.recordIDValue = (Integer)editor.getValue(); - } else { - if (editor.getValue() == null) - this.recordIDValue = null; - else - this.recordIDValue = Integer.valueOf(editor.getValue().toString()); - } if (editor.getAD_Table_ID() instanceof Integer) { tableIDValue = (Integer) editor.getAD_Table_ID(); @@ -114,6 +107,20 @@ public class WRecordIDDialog extends Window implements EventListener, Val tableIDValue = Integer.valueOf(editor.getAD_Table_ID().toString()); } + + this.tableIDGridField = tableIDGridField; + if(editor.getValue() instanceof Integer) { + this.recordIDValue = (Integer)editor.getValue(); + } else { + if (editor.getValue() == null) + this.recordIDValue = null; + else { + MTable table = MTable.get(tableIDValue); + if (editor.getValue() instanceof String && table != null && table.isUUIDKeyTable()) + this.recordIDValue = editor.getValue().toString(); + } + } + init(page); } @@ -152,8 +159,13 @@ public class WRecordIDDialog extends Window implements EventListener, Val if (editor.getGridField().getGridTab() != null) { parentTextBox = new Textbox(); parentTextBox.setReadonly(true); - parentTextBox.setValue(editor.getIdentifier( - editor.getGridField().getGridTab().getAD_Table_ID(), editor.getGridField().getGridTab().getRecord_ID())); + MTable table = MTable.get(tableID); + Object recordId; + if (table.isUUIDKeyTable()) + recordId = editor.getGridField().getGridTab().getValue(PO.getUUIDColumnName(table.getTableName())); + else + recordId = editor.getGridField().getGridTab().getRecord_ID(); + parentTextBox.setValue(editor.getIdentifier(tableID, recordId)); } if (recordsEditor != null) @@ -219,14 +231,21 @@ public class WRecordIDDialog extends Window implements EventListener, Val @Override public void valueChange(ValueChangeEvent evt) { if (evt.getSource().equals(tableIDEditor)) { + int tableID = Integer.parseInt(Objects.toString(evt.getNewValue(), "-1")); + if (tableID > 0) { + MTable table = MTable.get(tableID); + if (table.isUUIDKeyTable()) { + if (! editor.getColumnName().endsWith("_UU")) + throw new WrongValueException(tableIDEditor.getComponent(), Msg.getMsg(Env.getCtx(), "UUTableNotCompatibleWithRecordID")); + } + } + // the Record_ID should be cleared when a different AD_Table_ID is selected if (recordsEditor != null) { recordsEditor.setValue(null); recordsEditorLabel.detach(); recordsEditor.getComponent().detach(); } - int tableID = Integer.parseInt(Objects.toString(evt.getNewValue(), "-1")); - MLookup recordsLookup = editor.getRecordsLookup(tableID); if(recordsLookup != null) { recordsEditor = new WSearchEditor("Record_ID", false, false, true, recordsLookup); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordInfo.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordInfo.java index ce9af85c58..f80be8ff0f 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordInfo.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WRecordInfo.java @@ -343,8 +343,11 @@ public class WRecordInfo extends Window implements EventListener } else { uuid = po.get_UUID(); } - if (!Util.isEmpty(uuid)) - m_info.append("\n ").append(uuidcol).append("=").append(uuid); + if (!Util.isEmpty(uuid)) { + StringBuilder uuinfo = new StringBuilder(uuidcol).append("=").append(uuid); + if (! m_info.toString().contains(uuinfo)) + m_info.append("\n ").append(uuinfo); + } if (po.get_KeyColumns().length == 1) { String ticketURL; if (Record_ID <= 0) diff --git a/org.adempiere.ui/src/org/compiere/minigrid/IDColumn.java b/org.adempiere.ui/src/org/compiere/minigrid/IDColumn.java index d0b569adb6..c4f8291d10 100644 --- a/org.adempiere.ui/src/org/compiere/minigrid/IDColumn.java +++ b/org.adempiere.ui/src/org/compiere/minigrid/IDColumn.java @@ -22,7 +22,7 @@ package org.compiere.minigrid; * @author Jorg Janke * @version $Id: IDColumn.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ */ -public class IDColumn +public class IDColumn implements SelectableIDColumn { /** * ID Column constructor diff --git a/org.adempiere.ui/src/org/compiere/minigrid/IMiniTable.java b/org.adempiere.ui/src/org/compiere/minigrid/IMiniTable.java index 16573bcd57..d98450d611 100644 --- a/org.adempiere.ui/src/org/compiere/minigrid/IMiniTable.java +++ b/org.adempiere.ui/src/org/compiere/minigrid/IMiniTable.java @@ -26,6 +26,7 @@ **********************************************************************/ package org.compiere.minigrid; +import java.io.Serializable; import java.sql.ResultSet; import org.compiere.model.PO; @@ -125,7 +126,7 @@ public interface IMiniTable * * @return row key */ - public Integer getSelectedRowKey(); + public T getSelectedRowKey(); /** * diff --git a/org.adempiere.ui/src/org/compiere/minigrid/SelectableIDColumn.java b/org.adempiere.ui/src/org/compiere/minigrid/SelectableIDColumn.java new file mode 100644 index 0000000000..419c23f7de --- /dev/null +++ b/org.adempiere.ui/src/org/compiere/minigrid/SelectableIDColumn.java @@ -0,0 +1,34 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - Carlos Ruiz - globalqss - bxservice * + **********************************************************************/ + +package org.compiere.minigrid; + +public interface SelectableIDColumn { + + public void setSelected(boolean selected); + + public boolean isSelected(); + +} diff --git a/org.adempiere.ui/src/org/compiere/minigrid/UUIDColumn.java b/org.adempiere.ui/src/org/compiere/minigrid/UUIDColumn.java new file mode 100644 index 0000000000..4262408ffb --- /dev/null +++ b/org.adempiere.ui/src/org/compiere/minigrid/UUIDColumn.java @@ -0,0 +1,94 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - Carlos Ruiz - globalqss - bxservice * + **********************************************************************/ + +package org.compiere.minigrid; + +/** +* UUID Column for MiniGrid allows to select a column and maintains the record UUID +* @author Carlos Ruiz - globalqss - bxservice +*/ +public class UUIDColumn implements SelectableIDColumn +{ + /** + * UUID Column constructor + * @param record_UU + */ + public UUIDColumn(String record_UU) + { + super(); + setRecord_UU(record_UU); + setSelected(false); + } // UUIDColumn + + /** Is the row selected */ + private boolean m_selected = false; + /** The Record_UU */ + private String m_record_UU; + + + /** + * Set Selection + * @param selected + */ + public void setSelected(boolean selected) + { + m_selected = selected; + } + /** + * Is Selected + * @return true if selected + */ + public boolean isSelected() + { + return m_selected; + } + + /** + * Set Record_UU + * @param record_UU + */ + public void setRecord_UU(String record_UU) + { + m_record_UU = record_UU; + } + /** + * Get Record UU + * @return UU + */ + public String getRecord_UU() + { + return m_record_UU; + } + + /** + * To String + * @return String representation + */ + public String toString() + { + return "UUIDColumn - UU=" + m_record_UU + ", Selected=" + m_selected; + } // toString + +} // UUIDColumn