From f73caa3e98a12e6f21be197cb74912af02677c55 Mon Sep 17 00:00:00 2001 From: joergviola Date: Mon, 8 Mar 2010 20:27:33 +0000 Subject: [PATCH] More flexible service locator interface. https://sourceforge.net/tracker/?func=detail&aid=2700937&group_id=176962&atid=879334 --- base/plugin.xml | 3 +- base/schema/org.adempiere.base.Callout.exsd | 119 ++++++++++++++++++ base/src/org/adempiere/base/Core.java | 41 ++++++ .../org/adempiere/base/IResourceFinder.java | 2 +- base/src/org/adempiere/base/IService.java | 5 + .../org/adempiere/base/IServiceLocator.java | 14 ++- base/src/org/adempiere/base/Service.java | 26 +++- base/src/org/adempiere/base/ServiceQuery.java | 9 ++ .../base/equinox/EquinoxResourceFinder.java | 35 ------ .../base/equinox/EquinoxServiceLocator.java | 33 ++++- .../adempiere/base/equinox/ExtensionList.java | 63 ++++++++++ base/src/org/compiere/Adempiere.java | 7 +- base/src/org/compiere/model/Callout.java | 4 +- base/src/org/compiere/model/GridTab.java | 11 +- base/src/org/compiere/util/Env.java | 7 +- client/plugin.xml | 2 +- 16 files changed, 326 insertions(+), 55 deletions(-) create mode 100644 base/schema/org.adempiere.base.Callout.exsd create mode 100644 base/src/org/adempiere/base/Core.java create mode 100644 base/src/org/adempiere/base/IService.java create mode 100644 base/src/org/adempiere/base/ServiceQuery.java delete mode 100644 base/src/org/adempiere/base/equinox/EquinoxResourceFinder.java diff --git a/base/plugin.xml b/base/plugin.xml index cb6b8fe432..a02eda5e25 100644 --- a/base/plugin.xml +++ b/base/plugin.xml @@ -1,6 +1,7 @@ - + + diff --git a/base/schema/org.adempiere.base.Callout.exsd b/base/schema/org.adempiere.base.Callout.exsd new file mode 100644 index 0000000000..a4657b6ea9 --- /dev/null +++ b/base/schema/org.adempiere.base.Callout.exsd @@ -0,0 +1,119 @@ + + + + + + + + + This is the ADempiere Call extension point. + +Callouts provided by plugins are not entered into the application dictionary. +Instead, you specify Table and Column in the extension declaration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/base/src/org/adempiere/base/Core.java b/base/src/org/adempiere/base/Core.java new file mode 100644 index 0000000000..df6ce32268 --- /dev/null +++ b/base/src/org/adempiere/base/Core.java @@ -0,0 +1,41 @@ +package org.adempiere.base; + +import java.net.URL; +import java.util.List; + +import org.adempiere.base.equinox.ExtensionList; +import org.compiere.model.Callout; + +/** + * This is a facade class for the Service Locator. + * It provides simple access to all core services. + * + * @author viola + */ +public class Core { + + public static IResourceFinder getResourceFinder() { + return new IResourceFinder() { + + public URL getResource(String name) { + List f = Service.list(IResourceFinder.class); + for (IResourceFinder finder : f) { + URL url = finder.getResource(name); + if (url!=null) + return url; + } + return null; + } + }; + } + + public static Callout getCallout(String tableName, String columnName) { + ServiceQuery query = new ServiceQuery(); + query.put("tableName", tableName); + query.put("columnName", columnName); + + return Service.locate(Callout.class, query); + } + + +} diff --git a/base/src/org/adempiere/base/IResourceFinder.java b/base/src/org/adempiere/base/IResourceFinder.java index a99ea7b76b..12d751d355 100644 --- a/base/src/org/adempiere/base/IResourceFinder.java +++ b/base/src/org/adempiere/base/IResourceFinder.java @@ -18,7 +18,7 @@ package org.adempiere.base; import java.net.URL; -public interface IResourceFinder { +public interface IResourceFinder extends IService { URL getResource(String name); diff --git a/base/src/org/adempiere/base/IService.java b/base/src/org/adempiere/base/IService.java new file mode 100644 index 0000000000..5745fce41f --- /dev/null +++ b/base/src/org/adempiere/base/IService.java @@ -0,0 +1,5 @@ +package org.adempiere.base; + +public interface IService { + +} diff --git a/base/src/org/adempiere/base/IServiceLocator.java b/base/src/org/adempiere/base/IServiceLocator.java index 7b127bfd4d..3d75392dd1 100644 --- a/base/src/org/adempiere/base/IServiceLocator.java +++ b/base/src/org/adempiere/base/IServiceLocator.java @@ -16,16 +16,24 @@ *****************************************************************************/ package org.adempiere.base; +import java.util.List; + +import org.compiere.model.Callout; + /** * A service locator looks up services. * This is the central authority for adempiere service definition, * because each service defined has to be looked up via this interface. + * + * A service in adempiere is an interface extended from the tagging interface IService. + * * @author viola * */ public interface IServiceLocator { - - IResourceFinder getResourceFinder(); - + T locate(Class type); + T locate(Class type, ServiceQuery query); + List list(Class type); + List list(Class type, ServiceQuery query); } diff --git a/base/src/org/adempiere/base/Service.java b/base/src/org/adempiere/base/Service.java index 4ab5206ec8..bc397e5c24 100644 --- a/base/src/org/adempiere/base/Service.java +++ b/base/src/org/adempiere/base/Service.java @@ -16,26 +16,46 @@ *****************************************************************************/ package org.adempiere.base; +import java.util.List; + import org.adempiere.base.equinox.EquinoxServiceLocator; /** * This is a very simple factory for service locators + * * @author viola - * + * */ public class Service { private static IServiceLocator theLocator; public static IServiceLocator locator() { - if (theLocator==null) { + if (theLocator == null) { synchronized (Service.class) { - if (theLocator==null) { + if (theLocator == null) { theLocator = new EquinoxServiceLocator(); + System.out + .println("Started service locator: " + theLocator); } } } return theLocator; } + public static T locate(Class type) { + return locator().locate(type); + } + + public static T locate(Class type, ServiceQuery query) { + return locator().locate(type, query); + } + + public static List list(Class type) { + return locator().list(type); + } + + public static List list(Class type, ServiceQuery query) { + return locator().list(type, query); + } } diff --git a/base/src/org/adempiere/base/ServiceQuery.java b/base/src/org/adempiere/base/ServiceQuery.java new file mode 100644 index 0000000000..3cb1f42a6e --- /dev/null +++ b/base/src/org/adempiere/base/ServiceQuery.java @@ -0,0 +1,9 @@ +package org.adempiere.base; + +import java.util.HashMap; + +public class ServiceQuery extends HashMap { + + private static final long serialVersionUID = -3624488575106821781L; + +} diff --git a/base/src/org/adempiere/base/equinox/EquinoxResourceFinder.java b/base/src/org/adempiere/base/equinox/EquinoxResourceFinder.java deleted file mode 100644 index b720e95006..0000000000 --- a/base/src/org/adempiere/base/equinox/EquinoxResourceFinder.java +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.adempiere.base.equinox; - -import java.net.URL; - -import org.adempiere.base.IResourceFinder; - -public class EquinoxResourceFinder implements IResourceFinder { - - public URL getResource(String name) { - ExtensionList list = new ExtensionList(IResourceFinder.class, "org.adempiere.base.ResourceFinder"); - for (IResourceFinder rf : list) { - URL url = rf.getResource(name); - if (url!=null) - return url; - } - return null; - } - -} \ No newline at end of file diff --git a/base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java b/base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java index 907ef8e7ed..fe13648039 100644 --- a/base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java +++ b/base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java @@ -16,14 +16,41 @@ *****************************************************************************/ package org.adempiere.base.equinox; -import org.adempiere.base.IResourceFinder; +import java.util.List; + +import org.adempiere.base.IService; import org.adempiere.base.IServiceLocator; +import org.adempiere.base.ServiceQuery; +/** + * This is the Equinox implementation of the ADempiere Service Locator. + * It delegates work to the ExtensionList that lookups up services as extensions. + * The ids of extension points have to correspond to the interface names of the services. + * + * @author viola + * + */ public class EquinoxServiceLocator implements IServiceLocator { - public IResourceFinder getResourceFinder() { - return new EquinoxResourceFinder(); + public List list(Class type) { + ExtensionList list = new ExtensionList(type, type.getName()); + return list.asList(); + } + + public List list(Class type, ServiceQuery query) { + ExtensionList list = new ExtensionList(type, type.getName(), query); + return list.asList(); + } + + public T locate(Class type) { + ExtensionList list = new ExtensionList(type, type.getName()); + return list.first(); + } + + public T locate(Class type, ServiceQuery query) { + ExtensionList list = new ExtensionList(type, type.getName(), query); + return list.first(); } } diff --git a/base/src/org/adempiere/base/equinox/ExtensionList.java b/base/src/org/adempiere/base/equinox/ExtensionList.java index 760a36e4f8..02a2bebc7e 100644 --- a/base/src/org/adempiere/base/equinox/ExtensionList.java +++ b/base/src/org/adempiere/base/equinox/ExtensionList.java @@ -16,12 +16,28 @@ *****************************************************************************/ package org.adempiere.base.equinox; +import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; +import java.util.List; +import org.adempiere.base.ServiceQuery; +import org.compiere.model.Callout; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; +/** + * This List looks up services as extensions in equinox. + * The extension point must be the class name of the service interface. + * The query attributes are checked against the attributes + * of the extension configuration element. + * + * In order to minimize equinox lookups, a filtering iterator is used. + * @author viola + * + * @param The service this list holds implementations of. + */ public class ExtensionList implements Iterable{ public class ExtensionIterator implements Iterator { @@ -29,11 +45,31 @@ public class ExtensionList implements Iterable{ private int index = 0; public boolean hasNext() { + iterateUntilAccepted(); return index implements Iterable{ } private IConfigurationElement[] elements; + private HashMap filters = new HashMap(); public ExtensionList(Class clazz, String id) { try { @@ -58,8 +95,34 @@ public class ExtensionList implements Iterable{ } } + public ExtensionList(Class type, String name, ServiceQuery query) { + this(type, name); + for (String key : query.keySet()) { + addFilter(key, query.get(key)); + } + } + public Iterator iterator() { return new ExtensionIterator(); } + public void addFilter(String name, String value) { + filters.put(name, value); + } + + public T first() { + Iterator i = iterator(); + if (!i.hasNext()) + return null; + return i.next(); + } + + public List asList() { + List result = new ArrayList(); + for (T t : this) { + result.add(t); + } + return result; + } + } diff --git a/base/src/org/compiere/Adempiere.java b/base/src/org/compiere/Adempiere.java index a306fef357..787ee1fc30 100644 --- a/base/src/org/compiere/Adempiere.java +++ b/base/src/org/compiere/Adempiere.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.List; import java.util.Properties; import java.util.logging.Level; @@ -30,6 +31,8 @@ import javax.jnlp.ServiceManager; import javax.jnlp.UnavailableServiceException; import javax.swing.ImageIcon; +import org.adempiere.base.Core; +import org.adempiere.base.IResourceFinder; import org.adempiere.base.Service; import org.compiere.db.CConnection; import org.compiere.model.MClient; @@ -337,7 +340,7 @@ public final class Adempiere if (s_imageLogo == null) { Toolkit tk = Toolkit.getDefaultToolkit(); - URL url = Service.locator().getResourceFinder().getResource(s_file100x30); + URL url = Core.getResourceFinder().getResource(s_file100x30); // URL url = org.compiere.Adempiere.class.getResource(s_file100x30); // System.out.println(url); if (url == null) @@ -583,7 +586,7 @@ public final class Adempiere } // startupEnvironment public static URL getResource(String name) { - return Service.locator().getResourceFinder().getResource(name); + return Core.getResourceFinder().getResource(name); } diff --git a/base/src/org/compiere/model/Callout.java b/base/src/org/compiere/model/Callout.java index 59501e7024..1709ed74df 100644 --- a/base/src/org/compiere/model/Callout.java +++ b/base/src/org/compiere/model/Callout.java @@ -18,6 +18,8 @@ package org.compiere.model; import java.util.Properties; +import org.adempiere.base.IService; + /** * Callout Interface for Callout. * Used in MTab and ImpFormatRow @@ -25,7 +27,7 @@ import java.util.Properties; * @author Jorg Janke * @version $Id: Callout.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ */ -public interface Callout +public interface Callout extends IService { /** * Start Callout. diff --git a/base/src/org/compiere/model/GridTab.java b/base/src/org/compiere/model/GridTab.java index bfda81e985..041ede129a 100644 --- a/base/src/org/compiere/model/GridTab.java +++ b/base/src/org/compiere/model/GridTab.java @@ -37,6 +37,8 @@ import java.util.logging.Level; import javax.script.ScriptEngine; import javax.swing.event.EventListenerList; +import org.adempiere.base.Core; +import org.adempiere.base.Service; import org.compiere.util.CLogMgt; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -2682,6 +2684,13 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable */ public String processCallout (GridField field) { + Object value = field.getValue(); + Object oldValue = field.getOldValue(); + Callout co = Core.getCallout(getTableName(), field.getColumnName()); + if (co!=null) { + return co.start(m_vo.ctx, "", m_vo.WindowNo, this, field, value, oldValue); + } + String callout = field.getCallout(); if (callout.length() == 0) return ""; @@ -2689,8 +2698,6 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable if (isProcessed() && !field.isAlwaysUpdateable()) // only active records return ""; // "DocProcessed"; - Object value = field.getValue(); - Object oldValue = field.getOldValue(); log.fine(field.getColumnName() + "=" + value + " (" + callout + ") - old=" + oldValue); diff --git a/base/src/org/compiere/util/Env.java b/base/src/org/compiere/util/Env.java index 076e681113..aa25b4e9ea 100644 --- a/base/src/org/compiere/util/Env.java +++ b/base/src/org/compiere/util/Env.java @@ -46,6 +46,7 @@ import javax.swing.JFrame; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; +import org.adempiere.base.Core; import org.adempiere.base.IResourceFinder; import org.adempiere.base.Service; import org.compiere.Adempiere; @@ -1485,7 +1486,7 @@ public final class Env */ public static Image getImage (String fileNameInImageDir) { - IResourceFinder rf = Service.locator().getResourceFinder(); + IResourceFinder rf = Core.getResourceFinder(); URL url = rf.getResource("images/" + fileNameInImageDir); // URL url = Adempiere.class.getResource("images/" + fileNameInImageDir); @@ -1506,7 +1507,7 @@ public final class Env */ public static ImageIcon getImageIcon (String fileNameInImageDir) { - IResourceFinder rf = Service.locator().getResourceFinder(); + IResourceFinder rf = Core.getResourceFinder(); URL url = rf.getResource("images/" + fileNameInImageDir); // URL url = Adempiere.class.getResource("images/" + fileNameInImageDir); if (url == null) @@ -1528,7 +1529,7 @@ public final class Env */ public static ImageIcon getImageIcon2 (String fileName) { - IResourceFinder rf = Service.locator().getResourceFinder(); + IResourceFinder rf = Core.getResourceFinder(); URL url = rf.getResource("images/" + fileName+".gif"); // URL url = Adempiere.class.getResource("images/" + fileName+".gif"); if (url == null) diff --git a/client/plugin.xml b/client/plugin.xml index 41786b2054..071f08d40f 100644 --- a/client/plugin.xml +++ b/client/plugin.xml @@ -4,7 +4,7 @@ + point="org.adempiere.base.IResourceFinder">