package org.dresdenocl.tools.transformation.internal;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dresdenocl.tools.template.ITemplate;
import org.dresdenocl.tools.transformation.ITransformation;
import org.dresdenocl.tools.transformation.ITransformationRegistry;
import org.dresdenocl.tools.transformation.ParallelTransformation;
import org.dresdenocl.tools.transformation.TransformationPlugin;
import org.dresdenocl.tools.transformation.event.ITransformationRegistryListener;
import org.dresdenocl.tools.transformation.event.TransformationRegistryEvent;
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.IRegistryEventListener;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
/**
* Default implementation of the {@link ITransformationRegistr}
*
* @author Bjoern Freitag
*
*/
public class TransformationRegistry implements ITransformationRegistry,
IRegistryEventListener {
/** {@link Logger} for this class. */
private static final Logger LOGGER = TransformationPlugin
.getLogger(TransformationRegistry.class);
/**
* the map of template engines
*/
private Map<String, Class<?>> transformations;
/** The full identifier of the {@link ITransformation}s' extension point. */
private static final String TRANSFORMATION_EXTENSION_POINT_ID = TransformationPlugin.ID
+ ".transformations";
/** A list of listeners. */
private ListenerList listeners;
/**
* The constructor
*/
public TransformationRegistry() {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("TransformationRegistry() - enter"); //$NON-NLS-1$
}
// no else.
this.transformations = new HashMap<String, Class<?>>();
if (Platform.isRunning()) {
this.added(this.getExtensionPoint().getExtensions());
/* Register this registry as a listener for plug-in events. */
Platform.getExtensionRegistry().addListener(this,
TRANSFORMATION_EXTENSION_POINT_ID);
}
else {
LOGGER.warn("Plarform is not running. Please register transformations manually.");
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("TransformationRegistry() - exit"); //$NON-NLS-1$
}
}
/**
* @see org.dresdenocl.tools.transformation.ITransformationRegistry#addTransformation(ITransformation)
*/
public void addTransformation(ITransformation<?, ?, ?> transformation) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("addTransformation(transformation=" + transformation + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$
}
// no else.
if (transformation == null) {
throw new IllegalArgumentException(
"The parameter 'transformation' must not be null."); //$NON-NLS-1$
}
// no else.
/*
* Check if model is already contained in the registry; this is meant to
* be captured and dealt with on the UI, e.g., by showing an error
* message; this is better than silently do nothing.
*/
if (this.transformations.containsValue(transformation)) {
LOGGER.warn("Transformation '" + transformation.getClass().getSimpleName() + "' is already loaded. The transformation will be replaced."); //$NON-NLS-1$//$NON-NLS-2$
}
// no else.
addTransformation(transformation.getClass());
/* Inform listeners. */
this.fireTransformationAdded(transformation.getClass());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("addTransformation() - exit"); //$NON-NLS-1$
}
// no else.
}
private void addTransformation(Class<?> clazz) {
this.transformations.put(clazz.getSimpleName(), clazz);
}
/**
* @see org.dresdenocl.tools.transformation.ITransformationRegistry#dispose()
*/
public void dispose() {
if (this.transformations.size() != 0) {
this.transformations.clear();
}
}
/**
* @see org.dresdenocl.tools.template.ITransformationRegistry#getTransformationClass(String)
*/
public Class<?> getTransformationClass(String transformationName) {
if (transformationName == null) {
throw new IllegalArgumentException(
"The parameter transformationName must not be null.");
}
// no else.
return this.transformations.get(transformationName);
}
/**
* @see org.dresdenocl.tools.template.ITransformationRegistry#removeTransformation(ITransformation)
*/
public void removeTransformation(ITransformation<?, ?, ?> transformation) {
if (transformation == null) {
throw new IllegalArgumentException(
"The parameter transformationName must not be null.");
}
// no else.
this.fireTransformationRemoved(this.transformations
.remove(transformation.getClass().getSimpleName()));
}
/**
* @see org.dresdenocl.tools.template.ITransformationRegistry#removeTransformation(String)
*/
public void removeTransformation(String transformationName) {
if (transformationName == null) {
throw new IllegalArgumentException(
"The parameter transformationName must not be null.");
}
// no else.
this.transformations.remove(transformationName);
}
/**
* @see org.dresdenocl.tools.template.ITransformationRegistry#addTransformationRegistryListener(ITransformationRegistryListener)
*/
public void addTransformationRegistryListener(
ITransformationRegistryListener listener) {
this.getListeners().add(listener);
}
/**
* <p>
* A helper method that informs all listeners about an added
* {@link ITransformation}.
* </p>
*
* @param transformation
* The {@link ITransformation} that has been added.
*/
private void fireTransformationAdded(Class<?> transformation) {
TransformationRegistryEvent event;
event = null;
if (this.listeners != null) {
Object[] listeners;
listeners = this.listeners.getListeners();
for (int index = 0; index < listeners.length; index++) {
/* Lazily create the event. */
if (event == null) {
event = new TransformationRegistryEvent(this,
transformation);
}
// no else.
((ITransformationRegistryListener) listeners[index])
.transformationAdded(event);
}
// end for.
}
// no else.
}
/**
* <p>
* A helper method that informs all listeners about a removed
* {@link ITransformation}.
* </p>
*
* @param transformation
* The {@link ITemplate} that has been removed.
*/
private void fireTransformationRemoved(Class<?> transformation) {
TransformationRegistryEvent event = null;
if (this.listeners != null) {
Object[] listeners;
listeners = this.listeners.getListeners();
for (int index = 0; index < listeners.length; index++) {
/* Lazily create the event. */
if (event == null) {
event = new TransformationRegistryEvent(this,
transformation);
}
// no else.
((ITransformationRegistryListener) listeners[index])
.transformationRemoved(event);
}
// end for.
}
// no else.
}
/**
* @see org.dresdenocl.tools.template.ITransformationRegistry#removeTransformationRegistryListener(ITransformationRegistryListener)
*
*/
public void removeTransformationRegistryListener(
ITransformationRegistryListener listener) {
if (this.listeners != null) {
this.listeners.remove(listener);
}
// no else.
}
/**
* <p>
* A helper method that lazily creates the {@link ListenerList}.
* </p>
*/
private ListenerList getListeners() {
if (this.listeners == null) {
this.listeners = new ListenerList(ListenerList.IDENTITY);
}
// no else.
return this.listeners;
}
/**
* Add a new {@link ITransformation} from an extension
*
* @see org.eclipse.core.runtime.IRegistryEventListener#added(IExtension[])
*/
public void added(IExtension[] extensions) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("added(extensions=" + extensions + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
// no else.
/* Remove all registered objects from the meta-model cache. */
if (this.transformations != null) {
for (IExtension extension : extensions) {
for (IConfigurationElement configurationElement : extension
.getConfigurationElements()) {
try {
Class<?> clazz = Platform.getBundle(
extension.getNamespaceIdentifier()).loadClass(
configurationElement.getAttribute("class"));
this.addTransformation(clazz);
} catch (InvalidRegistryObjectException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// no else.
}
// end for (configurationElements).
}
// end for (extensions).
}
// no else.
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("added(IExtension[]) - exit"); //$NON-NLS-1$
}
// no else.
}
/**
* This method do nothing.
*
* @see org.eclipse.core.runtime.IRegistryEventListener#added(IExtensionPoint[])
*/
public void added(IExtensionPoint[] extensionPoints) {
// Do nothing
}
/**
* Remove an {@link ITransformation} from the extension
*
* @see org.eclipse.core.runtime.IRegistryEventListener#removed(IExtension[])
*/
public void removed(IExtension[] extensions) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("removed(extensions=" + extensions + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
// no else.
/* Remove all registered objects from the meta-model cache. */
if (this.transformations != null) {
for (IExtension extension : extensions) {
for (IConfigurationElement configurationElement : extension
.getConfigurationElements()) {
String transformationID;
try {
transformationID = ((ITransformation<?, ?, ?>) configurationElement
.createExecutableExtension("class"))
.getDisplayName();
} catch (CoreException e) {
continue;
}
this.removeTransformation(transformationID);
}
// end for (configurationElements).
}
// end for (extensions).
}
// no else.
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("removed(IExtension[]) - exit"); //$NON-NLS-1$
}
// no else.
}
/**
* This method do nothing.
*
* @see org.eclipse.core.runtime.IRegistryEventListener#removed(IExtensionPoint[])
*/
public void removed(IExtensionPoint[] extensionPoints) {
// Do nothing
}
/**
* <p>
* A helper method to get the worklist task {@link IExtensionPoint}.
* </p>
*
* @return The {@link ITranformation} {@link IExtensionPoint}.
*/
private IExtensionPoint getExtensionPoint() {
IExtensionPoint result;
/* Get the point from the registry. */
result = Platform.getExtensionRegistry().getExtensionPoint(
TRANSFORMATION_EXTENSION_POINT_ID);
/* This should not happen unless the id changes. */
if (result == null) {
throw new IllegalStateException(
"The extension point for new metamodels could not be found under the id " //$NON-NLS-1$
+ TRANSFORMATION_EXTENSION_POINT_ID);
}
// no else.
return result;
}
public List<String> getTransformationList() {
return new LinkedList<String>(this.transformations.keySet());
}
public List<String> getTransformationList(Class<?> modelIn,
Class<?> modelOut, Class<?> settings) {
List<String> itransList = new ArrayList<String>();
for (String s : this.transformations.keySet()) {
Class<?> clazz = this.transformations.get(s);
ParameterizedType superclass = ((ParameterizedType) clazz
.getGenericSuperclass());
Type[] types = superclass.getActualTypeArguments();
if (types[0].equals(modelIn)) {
if (types[1].equals(settings)) {
if (superclass.getRawType().equals(
ParallelTransformation.class)) {
if (types[2].equals(modelOut)) {
itransList.add(s);
} else if (types[3].equals(modelOut)) {
itransList.add(s);
}
} else {
if (types[types.length - 1].equals(modelOut)) {
itransList.add(s);
}
}
}
}
}
return itransList;
}
}