From 60c0bf681f2d4bd54ec5c8c5bf04a791d7ac719f Mon Sep 17 00:00:00 2001 From: hengsin Date: Fri, 28 Apr 2023 19:16:56 +0800 Subject: [PATCH] IDEMPIERE-5688 Enhancement to WindowValidator API (#1799) --- .../adwindow/AbstractADWindowContent.java | 86 ++++++++++++++++-- .../webui/adwindow/ProcessButtonPopup.java | 25 +++++- .../validator/WindowValidatorEvent.java | 27 ++++++ .../validator/WindowValidatorEventType.java | 6 +- .../validator/WindowValidatorManager.java | 89 ++++++++++++++----- 5 files changed, 198 insertions(+), 35 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java index 6c1c6cdd08..2a8a067bdf 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java @@ -182,6 +182,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements */ private static final String ON_DEFER_SET_DETAILPANE_SELECTION_EVENT = "onDeferSetDetailpaneSelection"; + /** ProcessModalDialog attribute to store reference for post process execution callback */ + private static final String PROCESS_POST_CALLBACK_ATTRIBUTE = "processPostCallbackAttribute"; + private static final CLogger logger; static @@ -1476,6 +1479,13 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements { statusBar.setStatusLine(s, b, logs); } + + if (dialog.getAttribute(PROCESS_POST_CALLBACK_ATTRIBUTE) != null && dialog.getAttribute(PROCESS_POST_CALLBACK_ATTRIBUTE) instanceof Callback) + { + @SuppressWarnings("unchecked") + Callback callback = (Callback) dialog.getAttribute(PROCESS_POST_CALLBACK_ATTRIBUTE); + callback.onCallback(dialog.getProcessInfo() != null && !dialog.getProcessInfo().isError()); + } } else if (ADTabpanel.ON_DYNAMIC_DISPLAY_EVENT.equals(event.getName())) { @@ -3639,9 +3649,29 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements if (!win.isStartProcess()) { return; } - boolean startWOasking = true; - boolean isProcessMandatory = true; - executeButtonProcess(wButton, startWOasking, table_ID, recordIdParam, isProcessMandatory); + + final Callback postCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + WindowValidatorEvent event = new WindowValidatorEvent(adwindow, WindowValidatorEventType.AFTER_DOC_ACTION.getName()); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(event, null); + } + } + }; + Callback preCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + boolean startWOasking = true; + boolean isProcessMandatory = true; + executeButtonProcess(wButton, startWOasking, table_ID, recordIdParam, isProcessMandatory, postCallback); + } + } + }; + + WindowValidatorEvent validatorEvent = new WindowValidatorEvent(adwindow, WindowValidatorEventType.BEFORE_DOC_ACTION.getName(), wButton); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(validatorEvent, preCallback); } }); getComponent().getParent().appendChild(win); @@ -3768,8 +3798,27 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements return; } // Posted - executeButtonProcess(wButton, startWOasking, table_ID, record_ID, - isProcessMandatory); + final int finalRecordId = record_ID; + final Callback postCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + WindowValidatorEvent event = new WindowValidatorEvent(adwindow, WindowValidatorEventType.AFTER_PROCESS.getName()); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(event, null); + } + } + }; + Callback preCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + executeButtonProcess(wButton, startWOasking, table_ID, finalRecordId, isProcessMandatory, postCallback); + } + } + }; + + WindowValidatorEvent validatorEvent = new WindowValidatorEvent(adwindow, WindowValidatorEventType.BEFORE_PROCESS.getName(), wButton); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(validatorEvent, preCallback); } // actionButton /** @@ -3865,10 +3914,11 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @param table_ID * @param record_ID * @param isProcessMandatory + * @param callback */ public void executeButtonProcess(final IProcessButton wButton, final boolean startWOasking, final int table_ID, final int record_ID, - boolean isProcessMandatory) { + boolean isProcessMandatory, Callback callback) { /** * Start Process ---- */ @@ -3896,7 +3946,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements if (wButton.getInfoWindow_ID() > 0) executionButtonInfoWindow0(wButton); else - executeButtonProcess0(wButton, startWOasking, table_ID, record_ID); + executeButtonProcess0(wButton, startWOasking, table_ID, record_ID, callback); } } }); @@ -3906,7 +3956,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements if (wButton.getInfoWindow_ID() > 0) executionButtonInfoWindow0(wButton); else - executeButtonProcess0(wButton, startWOasking, table_ID, record_ID); + executeButtonProcess0(wButton, startWOasking, table_ID, record_ID, callback); } } @@ -3916,9 +3966,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @param startWOasking * @param table_ID * @param record_ID + * @param callback */ private void executeButtonProcess0(final IProcessButton wButton, - boolean startWOasking, int table_ID, int record_ID) { + boolean startWOasking, int table_ID, int record_ID, Callback callback) { // call form MProcess pr = new MProcess(ctx, wButton.getProcess_ID(), null); int adFormID = pr.getAD_Form_ID(); @@ -4001,6 +4052,8 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements { dialog.setBorder("normal"); getComponent().getParent().appendChild(dialog); + if (callback != null) + dialog.setAttribute(PROCESS_POST_CALLBACK_ATTRIBUTE, callback); if (ClientInfo.isMobile()) { dialog.doHighlighted(); @@ -4012,6 +4065,21 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } Executions.schedule(getComponent().getDesktop(), e -> dialog.focus(), new Event("onPostShowProcessModalDialog")); } + else if (callback != null) + { + if (dialog.isCancel()) + { + callback.onCallback(Boolean.FALSE); + } + else + { + pi = dialog.getProcessInfo(); + if (pi == null || pi.isError()) + callback.onCallback(Boolean.FALSE); + else + callback.onCallback(Boolean.TRUE); + } + } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ProcessButtonPopup.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ProcessButtonPopup.java index 9e6a09a34c..2bfb2a6b08 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ProcessButtonPopup.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ProcessButtonPopup.java @@ -27,6 +27,9 @@ package org.adempiere.webui.adwindow; import java.util.List; import org.adempiere.util.Callback; +import org.adempiere.webui.adwindow.validator.WindowValidatorEvent; +import org.adempiere.webui.adwindow.validator.WindowValidatorEventType; +import org.adempiere.webui.adwindow.validator.WindowValidatorManager; import org.adempiere.webui.component.Menupopup; import org.adempiere.webui.editor.IProcessButton; import org.adempiere.webui.editor.WButtonEditor; @@ -140,7 +143,27 @@ public class ProcessButtonPopup extends Menupopup implements EventListener postCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + WindowValidatorEvent event = new WindowValidatorEvent(adwindow, WindowValidatorEventType.AFTER_DOC_ACTION.getName()); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(event, null); + } + } + }; + Callback preCallback = new Callback() { + @Override + public void onCallback(Boolean result) { + if (result) { + windowContent.executeButtonProcess(pb, true, gridTab.getAD_Table_ID(), gridTab.getRecord_ID(), true, postCallback); + } + } + }; + + WindowValidatorEvent validatorEvent = new WindowValidatorEvent(adwindow, WindowValidatorEventType.BEFORE_DOC_ACTION.getName(), pb); + WindowValidatorManager.getInstance().fireWindowValidatorEvent(validatorEvent, preCallback); } } }); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEvent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEvent.java index 3de4331524..db2bfd6b7a 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEvent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEvent.java @@ -35,14 +35,26 @@ public class WindowValidatorEvent { private ADWindow window; /** Event name **/ private String name; + /** Event data **/ + private Object data; /** * @param window * @param name */ public WindowValidatorEvent(ADWindow window, String name) { + this(window, name, null); + } + + /** + * @param window + * @param name + * @param data + */ + public WindowValidatorEvent(ADWindow window, String name, Object data) { this.window = window; this.name = name; + this.data = data; } /** @@ -58,4 +70,19 @@ public class WindowValidatorEvent { public String getName() { return this.name; } + + /** + * @return Event data + */ + public Object getData() { + return data; + } + + /** + * Set event data + * @param data + */ + public void setData(Object data) { + this.data = data; + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEventType.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEventType.java index 24565f1dab..b4c2899669 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEventType.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorEventType.java @@ -41,7 +41,11 @@ public enum WindowValidatorEventType { BEFORE_SAVE("beforeSave"), AFTER_SAVE("afterSave"), BEFORE_COPY("beforeCopy"), - AFTER_COPY("afterCopy"); + AFTER_COPY("afterCopy"), + BEFORE_DOC_ACTION("beforeDocAction"), + AFTER_DOC_ACTION("afterDocAction"), + BEFORE_PROCESS("beforeProcess"), + AFTER_PROCESS("afterProcess"); /** Event name **/ private String name; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorManager.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorManager.java index a633151f5d..35eb4b22d5 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorManager.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/validator/WindowValidatorManager.java @@ -31,6 +31,7 @@ import java.util.Map; import org.adempiere.util.Callback; import org.adempiere.webui.adwindow.ADWindow; +import org.compiere.util.Util; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -50,10 +51,10 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu /** {@link BundleContext} instance **/ private BundleContext context; - /** AD_Window_UU:List **/ - private Map> validatorMap = new HashMap>(); + /** AD_Window_UU:List **/ + private Map> validatorMap = new HashMap<>(); /** WindowValidator for all AD Window **/ - private List globalValidators = new ArrayList(); + private List globalValidators = new ArrayList<>(); /** WindowValidator osgi service tracker **/ private ServiceTracker serviceTracker; @@ -67,16 +68,24 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu if (obj instanceof String) { String uuid = (String) reference.getProperty("AD_Window_UU"); + String events = (String) reference.getProperty("events"); if (uuid == null || "*".equals(uuid)) { - globalValidators.add(service); + String[] validatorEvents = null; + if (!Util.isEmpty(events, true) && !"*".equals(events.trim())) { + validatorEvents = events.split("[,]"); + } + WindowValidatorEntry entry = new WindowValidatorEntry(service, validatorEvents); + globalValidators.add(entry); return service; } - addService(service, uuid); + addService(service, uuid, events); } else if (obj instanceof String []) { String[] uuids = (String []) reference.getProperty("AD_Window_UU"); - for (String uuid : uuids) - addService(service, uuid); + String events = (String) reference.getProperty("events"); + for (String uuid : uuids) { + addService(service, uuid, events); + } } return service; } @@ -85,14 +94,20 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu * Add {@link WindowValidator} service for an AD Window * @param service * @param uuid AD_Window_UU + * @param events */ - protected void addService(WindowValidator service, String uuid) { - List list = validatorMap.get(uuid); + protected void addService(WindowValidator service, String uuid, String events) { + List list = validatorMap.get(uuid); if (list == null) { - list = new ArrayList(); + list = new ArrayList(); validatorMap.put(uuid, list); } - list.add(service); + String[] validatorEvents = null; + if (!Util.isEmpty(events, true) && !"*".equals(events.trim())) { + validatorEvents = events.split("[,]"); + } + WindowValidatorEntry entry = new WindowValidatorEntry(service, validatorEvents); + list.add(entry); } @Override @@ -109,7 +124,7 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu if (obj instanceof String) { String uuid = (String) reference.getProperty("AD_Window_UU"); if (uuid == null || "*".equals(uuid)) { - globalValidators.remove(service); + globalValidators.removeIf(i -> i.validator.equals(service)); } else removeService(service, uuid); @@ -127,9 +142,9 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu * @param uuid */ protected void removeService(WindowValidator service, String uuid) { - List list = validatorMap.get(uuid); + List list = validatorMap.get(uuid); if (list != null) { - list.remove(service); + list.removeIf(i -> i.validator.equals(service)); } } @@ -171,21 +186,36 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu public void fireWindowValidatorEvent(WindowValidatorEvent event, Callback callback) { ADWindow window = event.getWindow(); String uuid = window.getAD_Window_UU(); - List list = validatorMap.get(uuid); + List list = validatorMap.get(uuid); int listSize = list != null ? list.size() : 0; - WindowValidator[] validators = new WindowValidator[listSize+globalValidators.size()]; - int index = -1; + List validators = new ArrayList<>(); if (listSize > 0) { - for(WindowValidator validator : list) { - index++; - validators[index] = validator; + for(WindowValidatorEntry validatorEntry : list) { + if (validatorEntry.events == null || validatorEntry.events.length == 0) { + validators.add(validatorEntry.validator); + } else { + for(String e : validatorEntry.events) { + if (e.trim().equalsIgnoreCase(event.getName())) { + validators.add(validatorEntry.validator); + break; + } + } + } } } - for(WindowValidator validator : globalValidators) { - index++; - validators[index] = validator; + for(WindowValidatorEntry validatorEntry : globalValidators) { + if (validatorEntry.events == null || validatorEntry.events.length == 0) { + validators.add(validatorEntry.validator); + } else { + for(String e : validatorEntry.events) { + if (e.trim().equalsIgnoreCase(event.getName())) { + validators.add(validatorEntry.validator); + break; + } + } + } } - ChainCallback chain = new ChainCallback(event, validators, callback); + ChainCallback chain = new ChainCallback(event, validators.toArray(new WindowValidator[0]), callback); chain.start(); } @@ -238,4 +268,15 @@ public class WindowValidatorManager implements BundleActivator, ServiceTrackerCu } } + + private static class WindowValidatorEntry { + private WindowValidator validator; + private String[] events; + + private WindowValidatorEntry(WindowValidator validator, String[] events) { + super(); + this.validator = validator; + this.events = events; + } + } }