/**
*
*/
package org.nightlabs.jfire.trade.ui.articlecontainer.detail;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.nightlabs.base.ui.entity.EntityEditorRegistry;
import org.nightlabs.base.ui.entity.editor.EntityEditorPageSettings;
import org.nightlabs.base.ui.entity.editor.IEntityEditorPageFactory;
import org.nightlabs.eclipse.extension.AbstractEPProcessor;
import org.nightlabs.jfire.trade.ArticleContainer;
import org.nightlabs.jfire.trade.ui.TradePlugin;
import org.nightlabs.util.reflect.ReflectUtil;
/**
* This registry processes the extension-point <code>org.nightlabs.jfire.trade.ui.articleContainerEditorPageFactory</code>.
* The extension-point allows for the registration of {@link IEntityEditorPageFactory}s on the basis
* of an editor-id as well the type (class) of the currently edited {@link ArticleContainer}.
* <p>
* Additionally to the editorID and articleContainerClass pages are registered with an id-String.
* When resolving the page-factories for an editor and the ArticleContainer it edits one factory
* will be returned for each id. As multiple registrations are allowed for one id (for different
* articleContainerClasses) the one that first matches when running through the the class/interface-hierarchy
* will be returned.
* </p>
*
* @author Alexander Bieber <!-- alex [AT] nightlabs [DOT] de -->
*/
public class ArticleContainerEditorPageFactoryRegistry extends AbstractEPProcessor {
protected static final String FACTOY_ELEMENT_NAME = "articleContainerEditorPageFactory"; //$NON-NLS-1$
protected static final String ARTICLE_CONTAINER_ATTRIBUTE_NAME = "articleContainerClass"; //$NON-NLS-1$
public static final String EXTENSION_POINT_ID = TradePlugin.getDefault().getBundle().getSymbolicName() + "." + FACTOY_ELEMENT_NAME; //$NON-NLS-1$
/**
* Maps editorID to a map from page-factory-id the map of
* the registrations per class for this id.
*/
private Map<String, Map<String, Map<String, EntityEditorPageSettings>>> pageSettings = new HashMap<String, Map<String,Map<String,EntityEditorPageSettings>>>();
/**
*
*/
public ArticleContainerEditorPageFactoryRegistry() {
}
/* (non-Javadoc)
* @see org.nightlabs.base.ui.extensionpoint.AbstractEPProcessor#getExtensionPointID()
*/
@Override
public String getExtensionPointID() {
return EXTENSION_POINT_ID;
}
/* (non-Javadoc)
* @see org.nightlabs.base.ui.extensionpoint.AbstractEPProcessor#processElement(org.eclipse.core.runtime.IExtension, org.eclipse.core.runtime.IConfigurationElement)
*/
@Override
public void processElement(IExtension extension, IConfigurationElement element) throws Exception {
if (element.getName().equals(FACTOY_ELEMENT_NAME)) {
String editorID = element.getAttribute("editorID"); //$NON-NLS-1$
String id = element.getAttribute("id"); //$NON-NLS-1$
String articleContainerClass = element.getAttribute("articleContainerClass"); //$NON-NLS-1$
addPage(editorID, id, articleContainerClass, new EntityEditorPageSettings(extension, element));
}
}
public void addPage(String editorID, String id, String articleContainerClass, EntityEditorPageSettings settings) {
if (editorID == null || "".equals(editorID)) //$NON-NLS-1$
throw new IllegalArgumentException("Missing/Invalid editorID for page settings: " + settings); //$NON-NLS-1$
if (id == null || "".equals(id)) //$NON-NLS-1$
throw new IllegalArgumentException("Missing/Invalid id for page settings: " + settings); //$NON-NLS-1$
if (articleContainerClass == null || "".equals(articleContainerClass)) //$NON-NLS-1$
throw new IllegalArgumentException("Missing/Invalid articleContainerClass for page settings: " + settings); //$NON-NLS-1$
Map<String, Map<String, EntityEditorPageSettings>> editorID2PageSettings = pageSettings.get(editorID);
if (editorID2PageSettings == null) {
editorID2PageSettings = new HashMap<String, Map<String,EntityEditorPageSettings>>();
pageSettings.put(editorID, editorID2PageSettings);
}
Map<String, EntityEditorPageSettings> class2PageSetting = editorID2PageSettings.get(id);
if(class2PageSetting == null) {
class2PageSetting = new HashMap<String, EntityEditorPageSettings>();
editorID2PageSettings.put(id, class2PageSetting);
}
EntityEditorPageSettings pageSettings = class2PageSetting.get(articleContainerClass);
if(pageSettings != null)
throw new IllegalStateException("An entityEditorPageFactory was already registered for: " + //$NON-NLS-1$
"editorID = " + editorID + //$NON-NLS-1$
", id = " + id + //$NON-NLS-1$
", articleContainerClass = " + articleContainerClass); //$NON-NLS-1$
class2PageSetting.put(articleContainerClass, settings);
}
/**
* Get the unsorted set of {@link EntityEditorPageSettings} for the registrations
* to the articleContainerEditorPageFactory extension-point.
* <p>
* For each id the first matching setting will be returned when running through
* the class/interface-hierarchy of the given articleContainerClass.
* </p>
*
* @param editorID The editorID to search registrations for.
* @param articleContainerClass The type (class) of ArticleContainer to search registrations for.
*/
public Set<EntityEditorPageSettings> getPageSettings(String editorID, Class<?> articleContainerClass) {
checkProcessing();
Set<EntityEditorPageSettings> result = null;
Map<String, Map<String, EntityEditorPageSettings>> editorRegistrations = pageSettings.get(editorID);
List<Class<?>> classTypeHierarchy = ReflectUtil.collectTypeHierarchy(articleContainerClass);
for (String pageId : editorRegistrations.keySet()) {
EntityEditorPageSettings settings = null;
for (Class<?> typeInHierarchy : classTypeHierarchy) {
settings = getEntityEditorPageSettings(editorID, pageId, typeInHierarchy.getName());
if (settings != null)
break;
}
if (settings != null) {
if (result == null)
result = new HashSet<EntityEditorPageSettings>();
result.add(settings);
}
}
return result;
}
private EntityEditorPageSettings getEntityEditorPageSettings(String editorID, String id, String articleContainerClass) {
Map<String, Map<String, EntityEditorPageSettings>> id2Class2Settings = pageSettings.get(editorID);
if (id2Class2Settings == null)
return null;
Map<String, EntityEditorPageSettings> class2Settings = id2Class2Settings.get(id);
if (class2Settings == null)
return null;
return class2Settings.get(articleContainerClass);
}
/**
* Returns the ordered {@link EntityEditorPageSettings} that are merged from registrations to the
* <code>articleContainerEditorPageFactory</code> extension-point as well as to the
* <code>entityEditor</code> extension-point.
*
* @param editorID The editorID to search registrations for.
* @param articleContainerClass The class of ArticleContainer to search registrations for.
*/
public List<EntityEditorPageSettings> getPagesSettingsOrdered(String editorID, Class<?> articleContainerClass) {
Set<EntityEditorPageSettings> baseSettings = EntityEditorRegistry.sharedInstance().getPageSettings(editorID);
Set<EntityEditorPageSettings> articleContainerSettings = getPageSettings(editorID, articleContainerClass);
List<EntityEditorPageSettings> settingsOrdered = new LinkedList<EntityEditorPageSettings>();
if (articleContainerSettings != null)
settingsOrdered.addAll(articleContainerSettings);
if (baseSettings != null)
settingsOrdered.addAll(baseSettings);
Collections.sort(settingsOrdered);
return settingsOrdered;
}
private static ArticleContainerEditorPageFactoryRegistry sharedInstance;
/**
* Returns and lazily creates a static instance of ArticleContainerEditorPageFactoryRegistry
*/
public static ArticleContainerEditorPageFactoryRegistry sharedInstance() {
if (sharedInstance == null) {
synchronized (ArticleContainerEditorPageFactoryRegistry.class) {
if (sharedInstance == null) {
sharedInstance = new ArticleContainerEditorPageFactoryRegistry();
sharedInstance.process();
}
}
}
return sharedInstance;
}
}