From 0af05090d10b6963572c70fff949c99581d60da7 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Mon, 6 Dec 2010 13:04:44 +0800 Subject: [PATCH] Implemented system event on top of osgi event admin framework and dynamic service framework. Added event.test project as example of usage. Modify ModelEventValidationEngine to invoke osgi event handler. --- event.test/.classpath | 7 + event.test/.project | 33 +++ .../.settings/org.eclipse.jdt.core.prefs | 8 + event.test/META-INF/MANIFEST.MF | 13 ++ event.test/OSGI-INF/event.xml | 5 + event.test/build.properties | 5 + event.test/src/event/test/Activator.java | 30 +++ event.test/src/event/test/MyEventHandler.java | 39 ++++ org.adempiere.base-feature/feature.xml | 21 ++ org.adempiere.base/.project | 5 + org.adempiere.base/META-INF/MANIFEST.MF | 4 + org.adempiere.base/OSGI-INF/eventmanager.xml | 8 + org.adempiere.base/build.properties | 7 +- .../src/org/adempiere/base/BaseActivator.java | 9 +- .../adempiere/base/event/EventManager.java | 211 ++++++++++++++++++ .../adempiere/base/event/EventProperty.java | 34 +++ .../adempiere/base/event/FactsEventData.java | 64 ++++++ .../adempiere/base/event/IEventManager.java | 98 ++++++++ .../adempiere/base/event/IEventTopics.java | 94 ++++++++ .../adempiere/base/event/ImportEventData.java | 61 +++++ .../adempiere/base/event/LoginEventData.java | 70 ++++++ .../compiere/model/ModelValidationEngine.java | 69 +++++- .../org/compiere/model/ModelValidator.java | 83 +++++-- .../src/org/compiere/model/PO.java | 12 + org.adempiere.install/install.app.launch | 4 +- .../install.console.app.launch | 4 +- org.adempiere.server-feature/server.product | 6 +- .../server.product.eventtest.launch | 33 +++ .../server.product.launch | 6 +- .../swingclient.product | 4 + .../swingclient.product.launch | 4 +- 31 files changed, 1009 insertions(+), 42 deletions(-) create mode 100644 event.test/.classpath create mode 100644 event.test/.project create mode 100644 event.test/.settings/org.eclipse.jdt.core.prefs create mode 100644 event.test/META-INF/MANIFEST.MF create mode 100644 event.test/OSGI-INF/event.xml create mode 100644 event.test/build.properties create mode 100644 event.test/src/event/test/Activator.java create mode 100644 event.test/src/event/test/MyEventHandler.java create mode 100644 org.adempiere.base/OSGI-INF/eventmanager.xml create mode 100644 org.adempiere.base/src/org/adempiere/base/event/EventManager.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/EventProperty.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/FactsEventData.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/IEventManager.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/IEventTopics.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/ImportEventData.java create mode 100644 org.adempiere.base/src/org/adempiere/base/event/LoginEventData.java create mode 100644 org.adempiere.server-feature/server.product.eventtest.launch diff --git a/event.test/.classpath b/event.test/.classpath new file mode 100644 index 0000000000..ad32c83a78 --- /dev/null +++ b/event.test/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/event.test/.project b/event.test/.project new file mode 100644 index 0000000000..161f7edb9f --- /dev/null +++ b/event.test/.project @@ -0,0 +1,33 @@ + + + event.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/event.test/.settings/org.eclipse.jdt.core.prefs b/event.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..18d2a1601c --- /dev/null +++ b/event.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Sun Dec 05 18:12:35 MYT 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/event.test/META-INF/MANIFEST.MF b/event.test/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..670ef0d376 --- /dev/null +++ b/event.test/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: event.test +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: event.test.Activator +Require-Bundle: org.adempiere.base;bundle-version="1.0.0" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Import-Package: org.eclipse.equinox.events;version="1.0.0", + org.osgi.framework, + org.osgi.service.event;version="1.2.0" +Service-Component: OSGI-INF/event.xml diff --git a/event.test/OSGI-INF/event.xml b/event.test/OSGI-INF/event.xml new file mode 100644 index 0000000000..4b33a64fa5 --- /dev/null +++ b/event.test/OSGI-INF/event.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/event.test/build.properties b/event.test/build.properties new file mode 100644 index 0000000000..9ea938077d --- /dev/null +++ b/event.test/build.properties @@ -0,0 +1,5 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/event.xml +source.. = src/ diff --git a/event.test/src/event/test/Activator.java b/event.test/src/event/test/Activator.java new file mode 100644 index 0000000000..d6b4ed6432 --- /dev/null +++ b/event.test/src/event/test/Activator.java @@ -0,0 +1,30 @@ +package event.test; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } + +} diff --git a/event.test/src/event/test/MyEventHandler.java b/event.test/src/event/test/MyEventHandler.java new file mode 100644 index 0000000000..85f9b377d1 --- /dev/null +++ b/event.test/src/event/test/MyEventHandler.java @@ -0,0 +1,39 @@ +package event.test; + +import org.adempiere.base.event.IEventManager; +import org.adempiere.base.event.IEventTopics; +import org.adempiere.base.event.LoginEventData; +import org.compiere.model.PO; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; + +/** + * + * @author hengsin + * + */ +public class MyEventHandler implements EventHandler { + + @Override + public void handleEvent(Event event) { + if (event.getTopic().equals(IEventTopics.AFTER_LOGIN)) { + LoginEventData eventData = (LoginEventData) event.getProperty(IEventManager.EVENT_DATA); + System.out.println(" topic="+event.getTopic()+" AD_Client_ID="+eventData.getAD_Client_ID() + +" AD_Org_ID="+eventData.getAD_Org_ID()+" AD_Role_ID="+eventData.getAD_Role_ID() + +" AD_User_ID="+eventData.getAD_User_ID()); + } else if (event.getTopic().equals(IEventTopics.PO_AFTER_NEW)) { + PO po = (PO) event.getProperty(IEventManager.EVENT_DATA); + System.out.println(" topic="+event.getTopic()+" po="+po); + } + + } + + public void bindEventManager(IEventManager eventManager) { + eventManager.register(IEventTopics.AFTER_LOGIN, this); + eventManager.register(IEventTopics.PO_AFTER_NEW, "(tableName=C_Order)", this); + } + + public void unbindEventManager(IEventManager eventManager) { + eventManager.unregister(this); + } +} diff --git a/org.adempiere.base-feature/feature.xml b/org.adempiere.base-feature/feature.xml index 3cb8280f16..c1ce1be344 100644 --- a/org.adempiere.base-feature/feature.xml +++ b/org.adempiere.base-feature/feature.xml @@ -300,4 +300,25 @@ version="0.0.0" unpack="false"/> + + + + + + diff --git a/org.adempiere.base/.project b/org.adempiere.base/.project index cba43891c4..f4aae4f2b0 100644 --- a/org.adempiere.base/.project +++ b/org.adempiere.base/.project @@ -34,6 +34,11 @@ + + org.eclipse.pde.ds.core.builder + + + org.eclipse.jem.workbench.JavaEMFNature diff --git a/org.adempiere.base/META-INF/MANIFEST.MF b/org.adempiere.base/META-INF/MANIFEST.MF index 0953248ab6..b557e4c637 100644 --- a/org.adempiere.base/META-INF/MANIFEST.MF +++ b/org.adempiere.base/META-INF/MANIFEST.MF @@ -59,6 +59,7 @@ Export-Package: bsh, net.sourceforge.barbecue.twod.pdf417, org.adempiere.apps.graph, org.adempiere.base, + org.adempiere.base.event, org.adempiere.exceptions, org.adempiere.impexp, org.adempiere.model, @@ -164,6 +165,7 @@ Import-Package: com.sun.mail.smtp;version="1.4.0", org.eclipse.osgi.framework.console;version="1.1.0", org.eclipse.osgi.service.datalocation, org.osgi.framework, + org.osgi.service.event;version="1.2.0", org.restlet, org.restlet.data, org.restlet.representation, @@ -171,3 +173,5 @@ Import-Package: com.sun.mail.smtp;version="1.4.0", Eclipse-BuddyPolicy: registered Eclipse-ExtensibleAPI: true Bundle-Activator: org.adempiere.base.BaseActivator +Service-Component: OSGI-INF/eventmanager.xml +Bundle-ActivationPolicy: lazy diff --git a/org.adempiere.base/OSGI-INF/eventmanager.xml b/org.adempiere.base/OSGI-INF/eventmanager.xml new file mode 100644 index 0000000000..2f30624198 --- /dev/null +++ b/org.adempiere.base/OSGI-INF/eventmanager.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.adempiere.base/build.properties b/org.adempiere.base/build.properties index f156f1bc4e..b72d202993 100644 --- a/org.adempiere.base/build.properties +++ b/org.adempiere.base/build.properties @@ -1,5 +1,3 @@ -source.base.jar = src/ -output.base.jar = build/ bin.includes = META-INF/,\ base.jar,\ plugin.xml,\ @@ -14,4 +12,7 @@ bin.includes = META-INF/,\ iText-2.1.7.jar,\ jcommon-1.0.16.jar,\ jfreechart-1.0.13.jar,\ - jnlp.jar + jnlp.jar,\ + OSGI-INF/eventmanager.xml +output.base.jar = build/ +source.base.jar = src/ diff --git a/org.adempiere.base/src/org/adempiere/base/BaseActivator.java b/org.adempiere.base/src/org/adempiere/base/BaseActivator.java index ad59c7c220..108b3b283c 100644 --- a/org.adempiere.base/src/org/adempiere/base/BaseActivator.java +++ b/org.adempiere.base/src/org/adempiere/base/BaseActivator.java @@ -24,8 +24,10 @@ import org.osgi.framework.BundleContext; */ public class BaseActivator implements BundleActivator { + private static BundleContext bundleContext = null; + /** - * + * default constructor */ public BaseActivator() { } @@ -35,6 +37,7 @@ public class BaseActivator implements BundleActivator { */ @Override public void start(BundleContext context) throws Exception { + bundleContext = context; context.registerService(CommandProvider.class.getName(), new StackTraceCommand(), null); } @@ -43,6 +46,10 @@ public class BaseActivator implements BundleActivator { */ @Override public void stop(BundleContext context) throws Exception { + bundleContext = null; } + public static BundleContext getBundleContext() { + return bundleContext; + } } diff --git a/org.adempiere.base/src/org/adempiere/base/event/EventManager.java b/org.adempiere.base/src/org/adempiere/base/event/EventManager.java new file mode 100644 index 0000000000..d798126c2d --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/EventManager.java @@ -0,0 +1,211 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.adempiere.base.BaseActivator; +import org.compiere.util.CLogger; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; +import org.osgi.service.event.EventConstants; +import org.osgi.service.event.EventHandler; + +/** + * Simple wrapper for the osgi event admin service. + * Usage: EventManager.getInstance().sendEvent/postEvent + * @author hengsin + * + */ +public class EventManager implements IEventManager { + + private EventAdmin eventAdmin; + private static IEventManager instance = null; + private final static CLogger log = CLogger.getCLogger(EventManager.class); + + private Map> registrations = new HashMap>(); + + /** + * @param eventAdmin + */ + public void bindEventAdmin(EventAdmin eventAdmin) { + if (instance == null) + instance = this; + this.eventAdmin = eventAdmin; + } + + /** + * @param eventAdmin + */ + public void unbindEventAdmin(EventAdmin eventAdmin) { + this.eventAdmin = null; + } + + /** + * Get the singleton instance created by the osgi service framework + * @return EventManager + */ + public static IEventManager getInstance() { + return instance; + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#postEvent(org.osgi.service.event.Event) + */ + @Override + public boolean postEvent(Event event) { + if (eventAdmin != null) { + eventAdmin.postEvent(event); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#sendEvent(org.osgi.service.event.Event) + */ + @Override + public boolean sendEvent(Event event) { + if (eventAdmin != null) { + eventAdmin.postEvent(event); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#register(java.lang.String, org.osgi.service.event.EventHandler) + */ + @Override + public boolean register(String topic, EventHandler eventHandler) { + return register(topic, null, eventHandler); + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#register(java.lang.String[], org.osgi.service.event.EventHandler) + */ + @Override + public boolean register(String[] topics, EventHandler eventHandler) { + return register(topics, null, eventHandler); + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#register(java.lang.String, java.lang.String, org.osgi.service.event.EventHandler) + */ + @Override + public boolean register(String topic, String filter, EventHandler eventHandler) { + String[] topics = new String[] {topic}; + return register(topics, filter, eventHandler); + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#register(java.lang.String[], java.lang.String, org.osgi.service.event.EventHandler) + */ + @Override + public boolean register(String[] topics, String filter, EventHandler eventHandler) { + BundleContext bundleContext = BaseActivator.getBundleContext(); + if (bundleContext == null) { + log.severe("No bundle context. Topic="+Arrays.toString(topics)); + return false; + } + Dictionary d = new Hashtable(); + d.put(EventConstants.EVENT_TOPIC, topics); + if (filter != null) + d.put(EventConstants.EVENT_FILTER, filter); + ServiceRegistration registration = bundleContext.registerService(EventHandler.class.getName(), eventHandler, d); + synchronized(registrations) { + List list = registrations.get(eventHandler); + if (list == null) { + list = new ArrayList(); + registrations.put(eventHandler, list); + } + list.add(registration); + } + return true; + } + + /* (non-Javadoc) + * @see org.adempiere.base.event.IEventManager#unregister(org.osgi.service.event.EventHandler) + */ + @Override + public boolean unregister(EventHandler eventHandler) { + List serviceRegistrations = null; + synchronized(registrations) { + serviceRegistrations = registrations.remove(eventHandler); + } + if (serviceRegistrations == null) + return false; + for (ServiceRegistration registration : serviceRegistrations) + registration.unregister(); + return true; + } + + /** + * @param topic + * @param parameter + */ + @SuppressWarnings("unchecked") + public static Event newEvent(String topic, Object data) { + Event event = null; + if (data instanceof Dictionary) { + Dictionarydict = (Dictionary)data; + if (dict.get(EVENT_ERROR_MESSAGES) == null) + dict.put(EVENT_ERROR_MESSAGES, new ArrayList()); + event = new Event(topic, dict); + } else if (data instanceof Map) { + Map map = (Map)data; + if (!map.containsKey(EVENT_ERROR_MESSAGES)) + map.put(EVENT_ERROR_MESSAGES, new ArrayList()); + event = new Event(topic, map); + } else { + Map map = new HashMap(3); + map.put(EventConstants.EVENT_TOPIC, topic); + if (data != null) + map.put(EVENT_DATA, data); + map.put(EVENT_ERROR_MESSAGES, new ArrayList()); + event = new Event(topic, map); + } + return event; + } + + /** + * + * @param topic + * @param properties + * @return event object + */ + public static Event newEvent(String topic, EventProperty ...properties) { + Event event = null; + Map map = new HashMap(3); + if (properties != null) { + for(int i = 0; i < properties.length; i++) { + map.put(properties[i].name, properties[i].value); + } + if (!map.containsKey(EventConstants.EVENT_TOPIC)) + map.put(EventConstants.EVENT_TOPIC, topic); + if (!map.containsKey(EVENT_ERROR_MESSAGES)) + map.put(EVENT_ERROR_MESSAGES, new ArrayList()); + } + event = new Event(topic, map); + return event; + } +} diff --git a/org.adempiere.base/src/org/adempiere/base/event/EventProperty.java b/org.adempiere.base/src/org/adempiere/base/event/EventProperty.java new file mode 100644 index 0000000000..05260d46f4 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/EventProperty.java @@ -0,0 +1,34 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +/** + * + * @author hengsin + * + */ +public class EventProperty { + public String name; + public Object value; + + /** + * @param name + * @param value + */ + public EventProperty(String name, Object value) { + super(); + this.name = name; + this.value = value; + } +} diff --git a/org.adempiere.base/src/org/adempiere/base/event/FactsEventData.java b/org.adempiere.base/src/org/adempiere/base/event/FactsEventData.java new file mode 100644 index 0000000000..014eb58ae2 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/FactsEventData.java @@ -0,0 +1,64 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +import java.util.List; + +import org.compiere.acct.Fact; +import org.compiere.model.MAcctSchema; +import org.compiere.model.PO; + +/** + * + * @author hengsin + * + */ +public class FactsEventData { + private MAcctSchema acctSchema; + private List facts; + private PO po; + + /** + * @param acctSchema + * @param facts + * @param po + */ + public FactsEventData(MAcctSchema acctSchema, List facts, PO po) { + super(); + this.acctSchema = acctSchema; + this.facts = facts; + this.po = po; + } + + /** + * @return the acctSchema + */ + public MAcctSchema getAcctSchema() { + return acctSchema; + } + + /** + * @return the facts + */ + public List getFacts() { + return facts; + } + + /** + * @return the po + */ + public PO getPo() { + return po; + } +} diff --git a/org.adempiere.base/src/org/adempiere/base/event/IEventManager.java b/org.adempiere.base/src/org/adempiere/base/event/IEventManager.java new file mode 100644 index 0000000000..e337830e12 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/IEventManager.java @@ -0,0 +1,98 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; + +/** + * + * @author hengsin + * + */ +public interface IEventManager { + + public static final String EVENT_DATA = "event.data"; + public static final String EVENT_ERROR_MESSAGES = "event.errorMessages"; + + /** + * Initiate asynchronous delivery of an event. This method returns to the + * caller before delivery of the event is completed. + * + * @param event The event to send to all listeners which subscribe to the + * topic of the event. + * + * @throws SecurityException If the caller does not have + * TopicPermission[topic,PUBLISH] for the topic + * specified in the event. + */ + public abstract boolean postEvent(Event event); + + /** + * Initiate synchronous delivery of an event. This method does not return to + * the caller until delivery of the event is completed. + * + * @param event The event to send to all listeners which subscribe to the + * topic of the event. + * + * @throws SecurityException If the caller does not have + * TopicPermission[topic,PUBLISH] for the topic + * specified in the event. + */ + public abstract boolean sendEvent(Event event); + + /** + * register a new event handler + * @param topic + * @param eventHandler + * @return true if registration is successful, false otherwise + */ + public abstract boolean register(String topic, EventHandler eventHandler); + + /** + * register a new event handler + * @param topics + * @param eventHandler + * @return true if registration is successful, false otherwise + */ + public abstract boolean register(String[] topics, EventHandler eventHandler); + + /** + * register a new event handler + * @param topic + * @param filter + * @param eventHandler + * @return true if registration is successful, false otherwise + */ + public abstract boolean register(String topic, String filter, + EventHandler eventHandler); + + /** + * register a new event handler + * @param topics + * @param filter + * @param eventHandler + * @return true if registration is successful, false otherwise + */ + public abstract boolean register(String[] topics, String filter, + EventHandler eventHandler); + + /** + * un-register an event handler + * @param eventHandler + * @return true if unregistration is done, false otherwise + */ + public abstract boolean unregister(EventHandler eventHandler); + +} \ No newline at end of file diff --git a/org.adempiere.base/src/org/adempiere/base/event/IEventTopics.java b/org.adempiere.base/src/org/adempiere/base/event/IEventTopics.java new file mode 100644 index 0000000000..9cb100a673 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/IEventTopics.java @@ -0,0 +1,94 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +/** + * + * @author hengsin + * + */ +public interface IEventTopics { + + public static final String MODEL_EVENT_PREFIX = "adempiere/po/"; + /** Model Change Type New */ + public static final String PO_BEFORE_NEW = MODEL_EVENT_PREFIX+"beforeNew"; + public static final String PO_AFTER_NEW = MODEL_EVENT_PREFIX+"afterNew"; + public static final String PO_AFTER_NEW_REPLICATION = MODEL_EVENT_PREFIX+"afterNewReplication"; // @Trifon + /** Model Change Type Change */ + public static final String PO_BEFORE_CHANGE = MODEL_EVENT_PREFIX+"beforeChange"; + public static final String PO_AFTER_CHANGE = MODEL_EVENT_PREFIX+"afterChange"; + public static final String PO_AFTER_CHANGE_REPLICATION = MODEL_EVENT_PREFIX+"afterChangeReplication"; // @Trifon + /** Model Change Type Delete */ + public static final String PO_BEFORE_DELETE = MODEL_EVENT_PREFIX+"beforeDelete"; + public static final String PO_AFTER_DELETE = MODEL_EVENT_PREFIX+"afterDelete"; + public static final String PO_BEFORE_DELETE_REPLICATION = MODEL_EVENT_PREFIX+"beforeDeleteReplication"; // @Trifon + //asynchrous model event + public static final String PO_POST_CREATE = MODEL_EVENT_PREFIX+"postCreate"; + public static final String PO_POST_UPADTE = MODEL_EVENT_PREFIX+"postUpdate"; + public static final String PO_POST_DELETE = MODEL_EVENT_PREFIX+"postDelete"; + public static final String PO_ALL = MODEL_EVENT_PREFIX+"*"; + + public static final String DOC_EVENT_PREFIX = "adempiere/doc/"; + /** Called before document is prepared */ + public static final String DOC_BEFORE_PREPARE = DOC_EVENT_PREFIX+"beforePrepare"; + /** Called before document is void */ + public static final String DOC_BEFORE_VOID = DOC_EVENT_PREFIX+"beforeVoid"; + /** Called before document is close */ + public static final String DOC_BEFORE_CLOSE = DOC_EVENT_PREFIX+"beforeClose"; + /** Called before document is reactivate */ + public static final String DOC_BEFORE_REACTIVATE = DOC_EVENT_PREFIX+"beforeReactivate"; + /** Called before document is reversecorrect */ + public static final String DOC_BEFORE_REVERSECORRECT = DOC_EVENT_PREFIX+"beforeReverseCorrect"; + /** Called before document is reverseaccrual */ + public static final String DOC_BEFORE_REVERSEACCRUAL = DOC_EVENT_PREFIX+"beforeReverseAccrual"; + /** Called before document is completed */ + public static final String DOC_BEFORE_COMPLETE = DOC_EVENT_PREFIX+"beforeComplete"; + /** Called after document is prepared */ + public static final String DOC_AFTER_PREPARE = DOC_EVENT_PREFIX+"afterPrepare"; + /** Called after document is completed */ + public static final String DOC_AFTER_COMPLETE = DOC_EVENT_PREFIX+"afterComplete"; + /** Called after document is void */ + public static final String DOC_AFTER_VOID = DOC_EVENT_PREFIX+"afterVoid"; + /** Called after document is closed */ + public static final String DOC_AFTER_CLOSE = DOC_EVENT_PREFIX+"afterClose"; + /** Called after document is reactivated */ + public static final String DOC_AFTER_REACTIVATE = DOC_EVENT_PREFIX+"afterReactivate"; + /** Called after document is reversecorrect */ + public static final String DOC_AFTER_REVERSECORRECT = DOC_EVENT_PREFIX+"afterReverseCorrect"; + /** Called after document is reverseaccrual */ + public static final String DOC_AFTER_REVERSEACCRUAL = DOC_EVENT_PREFIX+"afterReverseAccrual"; + /** Called before document is posted */ + public static final String DOC_BEFORE_POST = DOC_EVENT_PREFIX+"beforePost"; + /** Called after document is posted */ + public static final String DOC_AFTER_POST = DOC_EVENT_PREFIX+"afterPost"; + public static final String DOC_ALL = DOC_EVENT_PREFIX+"*"; + + public static final String AFTER_LOGIN = "adempiere/afterLogin"; + + public static final String ACCT_FACTS_VALIDATE = "adempiere/acct/factsValidate"; + + /** Import Events **/ + public static final String IMPORT_PREFIX = "adempiere/import/"; + /** Event triggered before all import records are validated */ + public static final String IMPORT_BEFORE_VALIDATE = IMPORT_PREFIX+"beforeValidate"; + /** Event triggered after all import records are validated */ + public static final String IMPORT_AFTER_VALIDATE = IMPORT_PREFIX+"afterValidate"; + /** Event triggered before an import record is processed */ + public static final String IMPORT_BEFORE_IMPORT = IMPORT_PREFIX+"beforeImport"; + /** Event triggered after an import record is processed */ + public static final String IMPORT_AFTER_IMPORT = IMPORT_PREFIX+"afterImport"; + + public static final String PREF_AFTER_LOAD = "adempiere/pref/afterLoad"; +} + diff --git a/org.adempiere.base/src/org/adempiere/base/event/ImportEventData.java b/org.adempiere.base/src/org/adempiere/base/event/ImportEventData.java new file mode 100644 index 0000000000..5bd3818c2a --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/ImportEventData.java @@ -0,0 +1,61 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +import org.adempiere.process.ImportProcess; +import org.compiere.model.PO; + +/** + * + * @author hengsin + * + */ +public class ImportEventData { + private ImportProcess importProcess; + private PO source; + private PO target; + + /** + * @param importProcess + * @param source + * @param target + */ + public ImportEventData(ImportProcess importProcess, PO source, PO target) { + super(); + this.importProcess = importProcess; + this.source = source; + this.target = target; + } + + /** + * @return the importProcess + */ + public ImportProcess getImportProcess() { + return importProcess; + } + + /** + * @return the source + */ + public PO getSource() { + return source; + } + + /** + * @return the target + */ + public PO getTarget() { + return target; + } +} diff --git a/org.adempiere.base/src/org/adempiere/base/event/LoginEventData.java b/org.adempiere.base/src/org/adempiere/base/event/LoginEventData.java new file mode 100644 index 0000000000..408e80eeed --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/LoginEventData.java @@ -0,0 +1,70 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2010 Heng Sin Low * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.base.event; + +/** + * + * @author hengsin + * + */ +public class LoginEventData { + private int AD_Client_ID; + private int AD_Org_ID; + private int AD_Role_ID; + private int AD_User_ID; + + /** + * @param aD_Client_ID + * @param aD_Org_ID + * @param aD_Role_ID + * @param aD_User_ID + */ + public LoginEventData(int aD_Client_ID, int aD_Org_ID, int aD_Role_ID, + int aD_User_ID) { + super(); + AD_Client_ID = aD_Client_ID; + AD_Org_ID = aD_Org_ID; + AD_Role_ID = aD_Role_ID; + AD_User_ID = aD_User_ID; + } + + /** + * @return the aD_Client_ID + */ + public int getAD_Client_ID() { + return AD_Client_ID; + } + + /** + * @return the aD_Org_ID + */ + public int getAD_Org_ID() { + return AD_Org_ID; + } + + /** + * @return the aD_Role_ID + */ + public int getAD_Role_ID() { + return AD_Role_ID; + } + + /** + * @return the aD_User_ID + */ + public int getAD_User_ID() { + return AD_User_ID; + } + +} diff --git a/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java b/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java index 3d53b678dd..faab982dfa 100644 --- a/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java +++ b/org.adempiere.base/src/org/compiere/model/ModelValidationEngine.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.logging.Level; @@ -27,12 +28,20 @@ import java.util.logging.Level; import javax.script.ScriptEngine; import org.adempiere.base.Core; +import org.adempiere.base.event.EventManager; +import org.adempiere.base.event.EventProperty; +import org.adempiere.base.event.FactsEventData; +import org.adempiere.base.event.IEventManager; +import org.adempiere.base.event.IEventTopics; +import org.adempiere.base.event.ImportEventData; +import org.adempiere.base.event.LoginEventData; import org.adempiere.model.ImportValidator; import org.adempiere.process.ImportProcess; import org.compiere.acct.Fact; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; +import org.osgi.service.event.Event; /** * Model Validation Engine @@ -146,7 +155,7 @@ public class ModelValidationEngine { // ModelValidator validator = null; - if (Core.isExtension(className)) + if (Core.isExtension(className)) { validator = Core.getModelValidator(className); } @@ -250,7 +259,15 @@ public class ModelValidationEngine } } } - // + + //now process osgi event handler + LoginEventData eventData = new LoginEventData(AD_Client_ID, AD_Org_ID, AD_Role_ID, AD_User_ID); + Event event = EventManager.newEvent(IEventTopics.AFTER_LOGIN, eventData); + EventManager.getInstance().sendEvent(event); + @SuppressWarnings("unchecked") + List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); + if (errors != null && !errors.isEmpty()) + return errors.get(0); if (AD_User_ID == 0 && AD_Role_ID == 0) ; // don't validate for user system on role system @@ -378,7 +395,15 @@ public class ModelValidationEngine } } } - // + + //now process osgi event handlers + Event event = EventManager.newEvent(ModelValidator.tableEventTopics[changeType], + new EventProperty(EventManager.EVENT_DATA, po), new EventProperty("tableName", po.get_TableName())); + EventManager.getInstance().sendEvent(event); + @SuppressWarnings("unchecked") + List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); + if (errors != null && !errors.isEmpty()) + return errors.get(0); return null; } // fireModelChange @@ -534,7 +559,15 @@ public class ModelValidationEngine } } } - // + + //now process osgi event handlers + Event event = EventManager.newEvent(ModelValidator.documentEventTopics[docTiming], + new EventProperty(EventManager.EVENT_DATA, po), new EventProperty("tableName", po.get_TableName())); + EventManager.getInstance().sendEvent(event); + @SuppressWarnings("unchecked") + List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); + if (errors != null && !errors.isEmpty()) + return errors.get(0); return null; } // fireDocValidate @@ -676,6 +709,15 @@ public class ModelValidationEngine return error; } + //process osgi event handlers + FactsEventData eventData = new FactsEventData(schema, facts, po); + Event event = EventManager.newEvent(IEventTopics.ACCT_FACTS_VALIDATE, + new EventProperty(EventManager.EVENT_DATA, eventData), new EventProperty("tableName", po.get_TableName())); + @SuppressWarnings("unchecked") + List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); + if (errors != null && !errors.isEmpty()) + return errors.get(0); + return null; } // fireFactsValidate @@ -737,6 +779,20 @@ public class ModelValidationEngine validator.validate(process, importModel, targetModel, timing); } } + + //osgi event handler + ImportEventData eventData = new ImportEventData(process, importModel, targetModel); + String topic = null; + if (timing == ImportValidator.TIMING_AFTER_IMPORT) + topic = IEventTopics.IMPORT_AFTER_IMPORT; + else if (timing == ImportValidator.TIMING_AFTER_VALIDATE) + topic = IEventTopics.IMPORT_AFTER_VALIDATE; + else if (timing == ImportValidator.TIMING_BEFORE_IMPORT) + topic = IEventTopics.IMPORT_BEFORE_IMPORT; + else if (timing == ImportValidator.TIMING_BEFORE_VALIDATE) + topic = IEventTopics.IMPORT_BEFORE_VALIDATE; + Event event = EventManager.newEvent(topic, new EventProperty(EventManager.EVENT_DATA, eventData), new EventProperty("importTableName", process.getImportTableName())); + EventManager.getInstance().sendEvent(event); } /** @@ -827,6 +883,11 @@ public class ModelValidationEngine } } } + + //osgi event handlers + @SuppressWarnings("rawtypes") + Event event = new Event(IEventTopics.PREF_AFTER_LOAD, (Map)null); + EventManager.getInstance().sendEvent(event); } /** diff --git a/org.adempiere.base/src/org/compiere/model/ModelValidator.java b/org.adempiere.base/src/org/compiere/model/ModelValidator.java index de3329bbd8..bb3c3d1623 100644 --- a/org.adempiere.base/src/org/compiere/model/ModelValidator.java +++ b/org.adempiere.base/src/org/compiere/model/ModelValidator.java @@ -17,35 +17,37 @@ *****************************************************************************/ package org.compiere.model; +import org.adempiere.base.event.IEventTopics; + /** * Model Validator - * + * * @author Jorg Janke * @version $Id: ModelValidator.java,v 1.2 2006/07/30 00:58:18 jjanke Exp $ - * + * * 2007/02/26 laydasalasc - globalqss - Add new timings for all before/after events on documents */ public interface ModelValidator { /** Model Change Type New */ - public static final int TYPE_BEFORE_NEW = 1; // teo_sarca [ 1675490 ] + public static final int TYPE_BEFORE_NEW = 1; // teo_sarca [ 1675490 ] public static final int TYPE_NEW = 1; public static final int CHANGETYPE_NEW = 1; // Compatibility with Compiere 260c - public static final int TYPE_AFTER_NEW = 4; // teo_sarca [ 1675490 ] + public static final int TYPE_AFTER_NEW = 4; // teo_sarca [ 1675490 ] public static final int TYPE_AFTER_NEW_REPLICATION = 7; // @Trifon /** Model Change Type Change */ - public static final int TYPE_BEFORE_CHANGE = 2; // teo_sarca [ 1675490 ] + public static final int TYPE_BEFORE_CHANGE = 2; // teo_sarca [ 1675490 ] public static final int TYPE_CHANGE = 2; public static final int CHANGETYPE_CHANGE = 2; // Compatibility with Compiere 260c - public static final int TYPE_AFTER_CHANGE = 5; // teo_sarca [ 1675490 ] + public static final int TYPE_AFTER_CHANGE = 5; // teo_sarca [ 1675490 ] public static final int TYPE_AFTER_CHANGE_REPLICATION = 8; // @Trifon /** Model Change Type Delete */ - public static final int TYPE_BEFORE_DELETE = 3; // teo_sarca [ 1675490 ] + public static final int TYPE_BEFORE_DELETE = 3; // teo_sarca [ 1675490 ] public static final int TYPE_DELETE = 3; public static final int CHANGETYPE_DELETE = 3; // Compatibility with Compiere 260c public static final int TYPE_AFTER_DELETE = 6; // teo_sarca [ 1675490 ] - public static final int TYPE_BEFORE_DELETE_REPLICATION = 9; // @Trifon - + public static final int TYPE_BEFORE_DELETE_REPLICATION = 9; // @Trifon + // Correlation between constant events and list of event script model validators public static String[] tableEventValidators = new String[] { "", // 0 @@ -54,12 +56,26 @@ public interface ModelValidator X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableBeforeDelete, // TYPE_BEFORE_DELETE = 3 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterNew, // TYPE_AFTER_NEW = 4 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterChange, // TYPE_AFTER_CHANGE = 5 - X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterDelete, // TYPE_AFTER_DELETE = 6 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterDelete, // TYPE_AFTER_DELETE = 6 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterNewReplication, // TYPE_AFTER_NEW_REPLICATION = 7 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterChangeReplication, // TYPE_AFTER_CHANGE_REPLICATION = 8 - X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableBeforeDeleteReplication // TYPE_BEFORE_DELETE_REPLICATION = 9 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableBeforeDeleteReplication // TYPE_BEFORE_DELETE_REPLICATION = 9 }; - + + // Correlation between constant events and list of osgi event topic + public static String[] tableEventTopics = new String[] { + "", // 0 + IEventTopics.PO_BEFORE_NEW, // TYPE_BEFORE_NEW = 1 + IEventTopics.PO_BEFORE_CHANGE, // TYPE_BEFORE_CHANGE = 2 + IEventTopics.PO_BEFORE_DELETE, // TYPE_BEFORE_DELETE = 3 + IEventTopics.PO_AFTER_NEW, // TYPE_AFTER_NEW = 4 + IEventTopics.PO_AFTER_CHANGE, // TYPE_AFTER_CHANGE = 5 + IEventTopics.PO_AFTER_DELETE, // TYPE_AFTER_DELETE = 6 + IEventTopics.PO_AFTER_NEW_REPLICATION, // TYPE_AFTER_NEW_REPLICATION = 7 + IEventTopics.PO_AFTER_CHANGE_REPLICATION, // TYPE_AFTER_CHANGE_REPLICATION = 8 + IEventTopics.PO_BEFORE_DELETE_REPLICATION// TYPE_BEFORE_DELETE_REPLICATION = 9 + }; + /** Called before document is prepared */ public static final int TIMING_BEFORE_PREPARE = 1; public static final int DOCTIMING_BEFORE_PREPARE = 1; // Compatibility with Compiere 260c @@ -94,7 +110,7 @@ public interface ModelValidator public static final int TIMING_BEFORE_POST = 15; /** Called after document is posted */ public static final int TIMING_AFTER_POST = 16; - + // Correlation between constant events and list of event script model validators public static String[] documentEventValidators = new String[] { "", // 0 @@ -115,10 +131,31 @@ public interface ModelValidator X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_DocumentBeforePost, // TIMING_BEFORE_POST = 15 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_DocumentAfterPost // TIMING_AFTER_POST = 16 }; - + + // Correlation between constant events and list of osgi event topics + public static String[] documentEventTopics = new String[] { + "", // 0 + IEventTopics.DOC_BEFORE_PREPARE, // TIMING_BEFORE_PREPARE = 1 + IEventTopics.DOC_BEFORE_VOID, // TIMING_BEFORE_VOID = 2 + IEventTopics.DOC_BEFORE_CLOSE, // TIMING_BEFORE_CLOSE = 3 + IEventTopics.DOC_BEFORE_REACTIVATE, // TIMING_BEFORE_REACTIVATE = 4 + IEventTopics.DOC_BEFORE_REVERSECORRECT, // TIMING_BEFORE_REVERSECORRECT = 5 + IEventTopics.DOC_BEFORE_REVERSEACCRUAL, // TIMING_BEFORE_REVERSEACCRUAL = 6 + IEventTopics.DOC_BEFORE_COMPLETE, // TIMING_BEFORE_COMPLETE = 7 + IEventTopics.DOC_AFTER_PREPARE, // TIMING_AFTER_PREPARE = 8 + IEventTopics.DOC_AFTER_COMPLETE, // TIMING_AFTER_COMPLETE = 9 + IEventTopics.DOC_AFTER_VOID, // TIMING_AFTER_VOID = 10 + IEventTopics.DOC_AFTER_CLOSE, // TIMING_AFTER_CLOSE = 11 + IEventTopics.DOC_AFTER_REACTIVATE, // TIMING_AFTER_REACTIVATE = 12 + IEventTopics.DOC_AFTER_REVERSECORRECT, // TIMING_AFTER_REVERSECORRECT = 13 + IEventTopics.DOC_AFTER_REVERSEACCRUAL, // TIMING_AFTER_REVERSEACCRUAL = 14 + IEventTopics.DOC_BEFORE_POST, // TIMING_BEFORE_POST = 15 + IEventTopics.DOC_AFTER_POST // TIMING_AFTER_POST = 16 + }; + /** * Initialize Validation - * @param engine validation engine + * @param engine validation engine * @param client client */ public void initialize (ModelValidationEngine engine, MClient client); @@ -128,9 +165,9 @@ public interface ModelValidator * @return AD_Client_ID */ public int getAD_Client_ID(); - + /** - * User logged in + * User logged in * Called before preferences are set * @param AD_Org_ID org * @param AD_Role_ID role @@ -139,10 +176,10 @@ public interface ModelValidator */ public String login (int AD_Org_ID, int AD_Role_ID, int AD_User_ID); - + /** * Model Change of a monitored Table. - * Called after PO.beforeSave/PO.beforeDelete + * Called after PO.beforeSave/PO.beforeDelete * when you called addModelChange for the table * @param po persistent object * @param type TYPE_ @@ -151,18 +188,18 @@ public interface ModelValidator */ public String modelChange (PO po, int type) throws Exception; - + /** * Validate Document. - * Called as first step of DocAction.prepareIt + * Called as first step of DocAction.prepareIt * or at the end of DocAction.completeIt * when you called addDocValidate for the table. * Note that totals, etc. may not be correct before the prepare stage. * @param po persistent object * @param timing see TIMING_ constants - * @return error message or null - + * @return error message or null - * if not null, the document will be marked as Invalid. */ public String docValidate (PO po, int timing); - + } // ModelValidator diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index afbc9b1448..75862afb2f 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -41,6 +41,8 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.adempiere.base.event.EventManager; +import org.adempiere.base.event.IEventTopics; import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.compiere.Adempiere; @@ -57,6 +59,7 @@ import org.compiere.util.SecureEngine; import org.compiere.util.Trace; import org.compiere.util.Trx; import org.compiere.util.ValueNamePair; +import org.osgi.service.event.Event; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -2219,6 +2222,11 @@ public abstract class PO // OK if (success) { + //post osgi event + String topic = newRecord ? IEventTopics.PO_POST_CREATE : IEventTopics.PO_POST_UPADTE; + Event event = EventManager.newEvent(topic, this); + EventManager.getInstance().postEvent(event); + if (s_docWFMgr == null) { try @@ -3053,6 +3061,10 @@ public abstract class PO // Reset if (success) { + //osgi event handler + Event event = EventManager.newEvent(IEventTopics.PO_POST_DELETE, this); + EventManager.getInstance().postEvent(event); + m_idOld = 0; int size = p_info.getColumnCount(); m_oldValues = new Object[size]; diff --git a/org.adempiere.install/install.app.launch b/org.adempiere.install/install.app.launch index 54d86821eb..902b6eb1ad 100644 --- a/org.adempiere.install/install.app.launch +++ b/org.adempiere.install/install.app.launch @@ -19,8 +19,8 @@ - - + + diff --git a/org.adempiere.install/install.console.app.launch b/org.adempiere.install/install.console.app.launch index eeef1dc5c0..4cdf35d867 100644 --- a/org.adempiere.install/install.console.app.launch +++ b/org.adempiere.install/install.console.app.launch @@ -19,8 +19,8 @@ - - + + diff --git a/org.adempiere.server-feature/server.product b/org.adempiere.server-feature/server.product index 7d6b1026e8..12bec589ee 100644 --- a/org.adempiere.server-feature/server.product +++ b/org.adempiere.server-feature/server.product @@ -33,6 +33,7 @@ + @@ -41,11 +42,12 @@ - + + - + diff --git a/org.adempiere.server-feature/server.product.eventtest.launch b/org.adempiere.server-feature/server.product.eventtest.launch new file mode 100644 index 0000000000..ea522c7af7 --- /dev/null +++ b/org.adempiere.server-feature/server.product.eventtest.launch @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.adempiere.server-feature/server.product.launch b/org.adempiere.server-feature/server.product.launch index c223091b07..3762427c39 100644 --- a/org.adempiere.server-feature/server.product.launch +++ b/org.adempiere.server-feature/server.product.launch @@ -7,7 +7,7 @@ - + @@ -21,8 +21,8 @@ - - + + diff --git a/org.adempiere.ui.swing-feature/swingclient.product b/org.adempiere.ui.swing-feature/swingclient.product index e7e2485459..a860309522 100644 --- a/org.adempiere.ui.swing-feature/swingclient.product +++ b/org.adempiere.ui.swing-feature/swingclient.product @@ -31,6 +31,10 @@ + + + + diff --git a/org.adempiere.ui.swing-feature/swingclient.product.launch b/org.adempiere.ui.swing-feature/swingclient.product.launch index 042c44455a..d76031eac3 100644 --- a/org.adempiere.ui.swing-feature/swingclient.product.launch +++ b/org.adempiere.ui.swing-feature/swingclient.product.launch @@ -21,8 +21,8 @@ - - + +