/******************************************************************************* | |
* Copyright (c) 2011, 2013 Formal Mind GmbH and University of Dusseldorf. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Michael Jastram - initial API and implementation | |
******************************************************************************/ | |
package org.eclipse.rmf.reqif10.pror.editor.presentation.service; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.agilemore.agilegrid.AgileGrid; | |
import org.agilemore.agilegrid.CellEditor; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IConfigurationElement; | |
import org.eclipse.core.runtime.IExtension; | |
import org.eclipse.core.runtime.IExtensionPoint; | |
import org.eclipse.core.runtime.IExtensionRegistry; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.emf.common.notify.AdapterFactory; | |
import org.eclipse.emf.edit.domain.EditingDomain; | |
import org.eclipse.emf.edit.provider.ItemProviderAdapter; | |
import org.eclipse.jface.dialogs.MessageDialog; | |
import org.eclipse.jface.preference.IPreferenceStore; | |
import org.eclipse.rmf.reqif10.AttributeValue; | |
import org.eclipse.rmf.reqif10.DatatypeDefinition; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionBoolean; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionDate; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionEnumeration; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionInteger; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionReal; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionString; | |
import org.eclipse.rmf.reqif10.DatatypeDefinitionXHTML; | |
import org.eclipse.rmf.reqif10.ReqIF; | |
import org.eclipse.rmf.reqif10.SpecElementWithAttributes; | |
import org.eclipse.rmf.reqif10.common.util.ReqIF10Util; | |
import org.eclipse.rmf.reqif10.pror.configuration.ProrPresentationConfiguration; | |
import org.eclipse.rmf.reqif10.pror.configuration.ProrPresentationConfigurations; | |
import org.eclipse.rmf.reqif10.pror.configuration.provider.ProrPresentationConfigurationItemProvider; | |
import org.eclipse.rmf.reqif10.pror.configuration.provider.ProrPresentationConfigurationsItemProvider; | |
import org.eclipse.rmf.reqif10.pror.edit.presentation.service.PresentationInterface; | |
import org.eclipse.rmf.reqif10.pror.edit.presentation.service.PresentationManager; | |
import org.eclipse.rmf.reqif10.pror.editor.preferences.PreferenceConstants; | |
import org.eclipse.rmf.reqif10.pror.editor.presentation.Reqif10EditorPlugin; | |
import org.eclipse.rmf.reqif10.pror.util.ConfigurationUtil; | |
import org.eclipse.rmf.reqif10.pror.util.ProrUtil; | |
/** | |
* This class manages installed Presentations (and is therefore independent of | |
* open ReqIF Files). It is not meant to be instantiated and consists | |
* exclusively of static methods. | |
* <p> | |
* | |
* | |
*/ | |
public class PresentationServiceManager { | |
public static final String PRESENTATION_EXTENSION_POINT_NAME = "org.eclipse.rmf.reqif10.pror.editor.presentation"; | |
private static Map<Class<? extends ProrPresentationConfiguration>, PresentationInterface> presentationServiceRegistry; | |
/* | |
* Private default constructor, to ensure that this class is never | |
* instantiated. | |
*/ | |
private PresentationServiceManager() { | |
throw new InstantiationError( | |
"This class is not designed to be instantiated."); | |
} | |
// // There is one entry per Plugin | |
// private static Set<PresentationData> presentationTypeRegistry; | |
/** | |
* Returns the cached {@link PresentationInterface} representing all installed | |
* Presentation Extensions. | |
* | |
* We use this method to initialize the presentation service map in the item | |
* provider plugin. | |
* | |
* @return A an unmodifyable map of {@link ProrPresentationConfiguration} | |
* classes and {@link PresentationInterface}s. | |
*/ | |
public static Map<Class<? extends ProrPresentationConfiguration>, PresentationInterface> getPresentationInterfaceMap() { | |
if (presentationServiceRegistry == null) { | |
HashMap<Class<? extends ProrPresentationConfiguration>, PresentationInterface> tmpRegistry = new HashMap<Class<? extends ProrPresentationConfiguration>, PresentationInterface>(); | |
IExtensionRegistry registry = Platform.getExtensionRegistry(); | |
IExtensionPoint extensionPoint = registry | |
.getExtensionPoint(PRESENTATION_EXTENSION_POINT_NAME); | |
IExtension[] extensions = extensionPoint.getExtensions(); | |
for (IExtension extension : extensions) { | |
IConfigurationElement[] configElements = extension | |
.getConfigurationElements(); | |
for (IConfigurationElement configElement : configElements) { | |
try { | |
PresentationInterface service = (PresentationInterface) configElement | |
.createExecutableExtension("service"); | |
tmpRegistry.put(service.getConfigurationInterface(), | |
service); | |
PresentationManager.addService( | |
service.getConfigurationInterface(), service); | |
} catch (CoreException e) { | |
MessageDialog | |
.openError( | |
null, | |
"Plugin Configuration Error", | |
"When initializing the installed plugins, something went wrong. " | |
+ "You can continue working, but Presentations may not be activated:" | |
+ e.getMessage()); | |
e.printStackTrace(); | |
} | |
} | |
} | |
presentationServiceRegistry = Collections | |
.unmodifiableMap(tmpRegistry); | |
} | |
return presentationServiceRegistry; | |
} | |
/** | |
* Returns the {@link PresentationInterface} for the given | |
* {@link ProrPresentationConfiguration} instance, or null if none found. | |
*/ | |
public static PresentationInterface getPresentationService( | |
ProrPresentationConfiguration configuration) { | |
for (Class<? extends ProrPresentationConfiguration> clazz : getPresentationInterfaceMap() | |
.keySet()) { | |
if (clazz.isInstance(configuration)) { | |
return getPresentationInterfaceMap().get(clazz); | |
} | |
} | |
return null; | |
} | |
/** | |
* Upon opening a ReqIF File, this method notifies each | |
* {@link ProrPresentationConfigurationItemProvider#registerPresentationConfiguration(ReqIF, EditingDomain)} | |
*/ | |
public static void notifiyOpenReqif(ReqIF reqif, | |
AdapterFactory adapterFactory, EditingDomain editingDomain) { | |
ProrPresentationConfigurations configs = ConfigurationUtil | |
.getPresentationConfigurations(reqif); | |
if (configs == null) | |
return; | |
((ProrPresentationConfigurationsItemProvider) ProrUtil.getItemProvider( | |
adapterFactory, configs)).setEditingDomain(editingDomain); | |
for (ProrPresentationConfiguration config : configs | |
.getPresentationConfigurations()) { | |
System.out.println("Registering: " + config); | |
ProrUtil.getConfigItemProvider(config, adapterFactory) | |
.registerPresentationConfiguration(config, editingDomain); | |
} | |
} | |
/** | |
* Upon closing a ReqIF File, this method notifies each | |
* {@link ProrPresentationConfigurationItemProvider#unregisterReqIF(ReqIF, EditingDomain)} | |
*/ | |
public static void notifiyCloseReqif(ReqIF reqif, | |
AdapterFactory adapterFactory, EditingDomain editingDomain) { | |
ProrPresentationConfigurations configs = ConfigurationUtil | |
.getPresentationConfigurations(reqif); | |
if (configs == null) | |
return; | |
for (ProrPresentationConfiguration config : configs | |
.getPresentationConfigurations()) { | |
System.out.println("Unregistering: " + config); | |
ProrUtil.getConfigItemProvider(config, adapterFactory) | |
.unregisterPresentationConfiguration(config); | |
} | |
} | |
public static PresentationInterface getPresentationService( | |
AttributeValue value, EditingDomain editingDomain) { | |
PresentationInterface service = null; | |
ProrPresentationConfiguration config = ConfigurationUtil | |
.getPresentationConfig(value); | |
if (config != null) { | |
service = PresentationServiceManager.getPresentationService(config); | |
} | |
return service; | |
} | |
/** | |
* This map caches the Default-Renderers. If a Datattype does not have a | |
* default, there is still an entry in the map to null. This way we know | |
* whether we already looked up a default. This map may be flushed, which is | |
* done when the user changes preference settings. | |
*/ | |
private final static Map<DatatypeDefinition, PresentationEditorInterface> defaultRenderers = new HashMap<DatatypeDefinition, PresentationEditorInterface>(); | |
/** | |
* Clears the cache of default renderers. The cache will be rebuild on | |
* demand. | |
*/ | |
public static void clearDefaultRenderers() { | |
defaultRenderers.clear(); | |
} | |
/** | |
* Returns a default renderer for the AttributeValue's Datatype, if there is | |
* one, otherwise null. | |
* | |
* @param adapterFactory | |
*/ | |
public static IProrCellRenderer getDefaultCellRenderer( | |
AttributeValue attrValue, AdapterFactory adapterFactory) { | |
DatatypeDefinition dd = ReqIF10Util.getDatatypeDefinition(attrValue); | |
if (dd == null) | |
return null; | |
// We do this to prevent repeated lookups if a dd has no default | |
// renderer. | |
ensureDefaultEntry(dd, adapterFactory); | |
PresentationEditorInterface presentationEditor = defaultRenderers | |
.get(dd); | |
return presentationEditor == null ? null : presentationEditor | |
.getCellRenderer(attrValue); | |
} | |
public static CellEditor getDefaultCellEditor(AgileGrid agileGrid, | |
EditingDomain editingDomain, AdapterFactory adapterFactory, | |
AttributeValue attrValue, SpecElementWithAttributes specElement, | |
Object affectedObject) { | |
DatatypeDefinition dd = ReqIF10Util.getDatatypeDefinition(attrValue); | |
if (dd == null) | |
return null; | |
// We do this to prevent repeated lookups if a dd has no default | |
// renderer. | |
ensureDefaultEntry(dd, adapterFactory); | |
PresentationEditorInterface presentationEditor = defaultRenderers | |
.get(dd); | |
return presentationEditor == null ? null : presentationEditor | |
.getCellEditor(agileGrid, editingDomain, attrValue, | |
specElement, affectedObject); | |
} | |
/** | |
* Ensures that there is an entry for the given {@link DatatypeDefinition} | |
* in the cache of default Handlers. | |
*/ | |
private static void ensureDefaultEntry(DatatypeDefinition dd, | |
AdapterFactory adapterFactory) { | |
if (defaultRenderers.containsKey(dd)) { | |
return; | |
} | |
String className = getPresentationClassName(dd); | |
Map<Class<? extends ProrPresentationConfiguration>, PresentationInterface> presentationMap = PresentationServiceManager | |
.getPresentationInterfaceMap(); | |
for (@SuppressWarnings("rawtypes") | |
Class key : presentationMap.keySet()) { | |
if (className.equals(key.getCanonicalName())) { | |
PresentationInterface p = presentationMap.get(key); | |
ProrPresentationConfiguration config = p | |
.getConfigurationInstance(); | |
config.setDatatype(dd); | |
ItemProviderAdapter provider = ProrUtil.getItemProvider( | |
adapterFactory, config); | |
if (provider instanceof PresentationEditorInterface) { | |
defaultRenderers.put(dd, | |
(PresentationEditorInterface) provider); | |
} else { | |
defaultRenderers.put(dd, null); | |
} | |
} | |
} | |
} | |
private static String getPresentationClassName( | |
org.eclipse.rmf.reqif10.DatatypeDefinition dd) { | |
IPreferenceStore store = Reqif10EditorPlugin.getPlugin() | |
.getPreferenceStore(); | |
if (dd instanceof DatatypeDefinitionString) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_STRING); | |
else if (dd instanceof DatatypeDefinitionXHTML) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_XHTML); | |
else if (dd instanceof DatatypeDefinitionBoolean) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_BOOLEAN); | |
else if (dd instanceof DatatypeDefinitionDate) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_DATE); | |
else if (dd instanceof DatatypeDefinitionEnumeration) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_ENUMERATION); | |
else if (dd instanceof DatatypeDefinitionInteger) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_INTEGER); | |
else if (dd instanceof DatatypeDefinitionReal) | |
return store | |
.getString(PreferenceConstants.P_DEFAULT_PRESENTATION_REAL); | |
else | |
throw new IllegalArgumentException("Not yet covered: " + dd); | |
} | |
} |