/* ***************************************************************************** * JFire - it's hot - Free ERP System - http://jfire.org * * Copyright (C) 2004-2005 NightLabs - http://NightLabs.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, * * Boston, MA 02110-1301 USA * * * * Or get it online : * * http://opensource.org/licenses/lgpl-license.php * * * * * ******************************************************************************/ package org.nightlabs.jfire.trade.ui.articlecontainer.detail; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.nightlabs.eclipse.extension.AbstractEPProcessor; import org.nightlabs.eclipse.extension.EPProcessorException; import org.nightlabs.jfire.trade.ArticleContainer; import org.nightlabs.jfire.trade.SegmentType; /** * @author Marco Schulze - marco at nightlabs dot de */ public class SegmentEditFactoryRegistry extends AbstractEPProcessor { protected static SegmentEditFactoryRegistry _sharedInstance = null; private static boolean initializingSharedInstance = false; public static synchronized SegmentEditFactoryRegistry sharedInstance() { if (initializingSharedInstance) throw new IllegalStateException("Circular call to the method sharedInstance() during initialization!"); //$NON-NLS-1$ if (_sharedInstance == null) { initializingSharedInstance = true; try { _sharedInstance = new SegmentEditFactoryRegistry(); _sharedInstance.process(); } finally { initializingSharedInstance = false; } } return _sharedInstance; } /** * key: String articleContainerClass<br/> * value: Map {<br/> * key: String segmentTypeClass<br/> * value: SegmentEditFactory editFactory<br/> * } */ protected Map<String, Map<String, SegmentEditFactory>> segmentEditFactoriesByArticleContainerClass = new HashMap<String, Map<String,SegmentEditFactory>>(); // protected static boolean isValidArticleContainerClass(String articleContainerClass) // { // return // Order.class.getName().equals(articleContainerClass) || // Offer.class.getName().equals(articleContainerClass) || // SegmentEditFactory.SEGMENTCONTEXT_INVOICE.equals(articleContainerClass) || // SegmentEditFactory.SEGMENTCONTEXT_DELIVERY_NOTE.equals(articleContainerClass) || // SegmentEditFactory.SEGMENTCONTEXT_RECEPTION_NOTE.equals(articleContainerClass); // } // // protected static void assertValidArticleContainerClass(String articleContainerClass) // { // if (!isValidArticleContainerClass(articleContainerClass)) // throw new IllegalArgumentException("articleContainerClass \""+articleContainerClass+"\" is not valid!"); //$NON-NLS-1$ //$NON-NLS-2$ // } protected Map<String, SegmentEditFactory> getSegmentEditFactories(String articleContainerClass) { // assertValidArticleContainerClass(articleContainerClass); Map<String, SegmentEditFactory> res = segmentEditFactoriesByArticleContainerClass.get(articleContainerClass); if (res == null) { res = new HashMap<String, SegmentEditFactory>(); segmentEditFactoriesByArticleContainerClass.put(articleContainerClass, res); } return res; } /** * @param articleContainerClass The type of {@link ArticleContainer} that should be searched for. * @param segmentTypeClass This class will be resolved recursively. Means you can * subclass a <tt>SegmentType</tt> and it will use the parent's factory, if you * don't override it for your child. * @param throwExceptionIfNotFound If <tt>false</tt> return <tt>null</tt>, if * <tt>true</tt> throw an {@link IllegalStateException}, in case nothing can be found. * * @return */ public SegmentEditFactory getSegmentEditFactory( Class<?> articleContainerClass, Class<? extends SegmentType> segmentTypeClass, boolean throwExceptionIfNotFound) { Class<?> searchClass = articleContainerClass; SegmentEditFactory factory = null; while (searchClass != null) { factory = getSegmentEditFactory(searchClass.getName(), segmentTypeClass); if (factory != null) return factory; Class<?>[] interfaces = searchClass.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { factory = getSegmentEditFactory(interfaces[i].getName(), segmentTypeClass); if (factory != null) return factory; } searchClass = searchClass.getSuperclass(); } if (throwExceptionIfNotFound && factory == null) throw new IllegalStateException("Nothing registered for articleContainerClass=\""+articleContainerClass+"\", segmentTypeClass=\""+segmentTypeClass.getName()+"\" (or a super-class)!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return factory; } private SegmentEditFactory getSegmentEditFactory(String articleContainerClass, Class<?> segmentTypeClass) { Map<String, SegmentEditFactory> m = getSegmentEditFactories(articleContainerClass); SegmentEditFactory factory = null; Class<?> clazz = segmentTypeClass; do { factory = m.get(clazz.getName()); clazz = clazz.getSuperclass(); } while (factory == null && clazz != Object.class); return factory; } protected void addSegmentEditFactory(SegmentEditFactory sef) { Map<String, SegmentEditFactory> sefMap = getSegmentEditFactories(sef.getArticleContainerClass().toString()); sefMap.put(sef.getSegmentTypeClass().toString(), sef); } /** * @see org.nightlabs.base.ui.extensionpoint.IEPProcessor#getExtensionPointID() */ @Override public String getExtensionPointID() { return "org.nightlabs.jfire.trade.ui.segmentEditFactory"; //$NON-NLS-1$ } /** * @see org.nightlabs.base.ui.extensionpoint.IEPProcessor#processElement(IExtension, org.eclipse.core.runtime.IConfigurationElement) */ @Override public void processElement(IExtension extension, IConfigurationElement element) throws Exception { try { SegmentEditFactory segmentEditFactory = (SegmentEditFactory) element.createExecutableExtension("class"); //$NON-NLS-1$ String segmentTypeClass = element.getAttribute("segmentTypeClass"); //$NON-NLS-1$ String articleContainerClass = element.getAttribute("articleContainerClass"); //$NON-NLS-1$ String segmentEditFactoryName = element.getAttribute("name"); //$NON-NLS-1$ // assertValidArticleContainerClass(articleContainerClass); if (segmentTypeClass == null || "".equals(segmentTypeClass)) //$NON-NLS-1$ throw new EPProcessorException("segmentTypeClass undefined!"); //$NON-NLS-1$ segmentEditFactory.init(segmentEditFactoryName, articleContainerClass, segmentTypeClass); // ArticleEditFactoryRegistry articleEditFactoryRegistry = new ArticleEditFactoryRegistry(); // SegmentEditFactoryRegistryEntry sefre = new SegmentEditFactoryRegistryEntry( // segmentEditFactory, articleEditFactoryRegistry); // IConfigurationElement[] children = element.getChildren("articleEditFactory"); // for (int i = 0; i < children.length; ++i) { // IConfigurationElement child = children[i]; // // ArticleEditFactory articleEditFactory = (ArticleEditFactory) child.createExecutableExtension("class"); // String productTypeClass = child.getAttribute("productTypeClass"); // String articleEditFactoryName = child.getAttribute("name"); // // articleEditFactory.setSegmentEditFactory(segmentEditFactory); // articleEditFactory.setProductTypeClass(productTypeClass); // articleEditFactory.setName(articleEditFactoryName); // // articleEditFactoryRegistry.addArticleEditFactory(articleEditFactory); // } addSegmentEditFactory(segmentEditFactory); } catch (Throwable t) { throw new EPProcessorException("Extension to "+getExtensionPointID()+" with class "+element.getAttribute("class")+" has errors!", t); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } } }