diff options
Diffstat (limited to 'plugins/org.eclipse.sirius.diagram/specific/org/eclipse/sirius/diagram/tools/internal/actions/repair/DiagramElementStateFactory.java')
-rw-r--r-- | plugins/org.eclipse.sirius.diagram/specific/org/eclipse/sirius/diagram/tools/internal/actions/repair/DiagramElementStateFactory.java | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/plugins/org.eclipse.sirius.diagram/specific/org/eclipse/sirius/diagram/tools/internal/actions/repair/DiagramElementStateFactory.java b/plugins/org.eclipse.sirius.diagram/specific/org/eclipse/sirius/diagram/tools/internal/actions/repair/DiagramElementStateFactory.java new file mode 100644 index 0000000000..a2e7d3b684 --- /dev/null +++ b/plugins/org.eclipse.sirius.diagram/specific/org/eclipse/sirius/diagram/tools/internal/actions/repair/DiagramElementStateFactory.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2010 THALES GLOBAL SERVICES. + * 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: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.sirius.diagram.tools.internal.actions.repair; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.ecore.EObject; + +import com.google.common.collect.Maps; + +import org.eclipse.sirius.common.tools.api.util.Option; +import org.eclipse.sirius.AbstractDNode; +import org.eclipse.sirius.DDiagramElement; +import org.eclipse.sirius.DDiagramElementContainer; +import org.eclipse.sirius.DEdge; +import org.eclipse.sirius.DNode; +import org.eclipse.sirius.DNodeListElement; +import org.eclipse.sirius.business.api.query.DDiagramElementQuery; +import org.eclipse.sirius.description.DiagramElementMapping; +import org.eclipse.sirius.description.RepresentationElementMapping; +import org.eclipse.sirius.diagram.tools.api.migration.DiagramCrossReferencer; + +/** + * Factory for {@link IDiagramElementState}. + * + * @author dlecan + */ +public class DiagramElementStateFactory { + + private static final Map<Class<? extends DDiagramElement>, Class<? extends IDiagramElementState<? extends DDiagramElement>>> ASSOCIATION = Maps.newLinkedHashMap(); + + static { + ASSOCIATION.put(DEdge.class, DEdgeDiagramElementState.class); + ASSOCIATION.put(DNode.class, DNodeDiagramElementState.class); + ASSOCIATION.put(DNodeListElement.class, DNodeListDiagramElementState.class); + ASSOCIATION.put(DDiagramElementContainer.class, DDiagramElementContainerDiagramElementState.class); + ASSOCIATION.put(AbstractDNode.class, AbstractDNodeDiagramElementState.class); + } + + private static final Map<Class<? extends DDiagramElement>, Constructor<? extends IDiagramElementState<? extends DDiagramElement>>> CACHE = Maps.newLinkedHashMap(); + + private static final Class<DefaultDiagramElementState> DEFAULT_DIAGRAM_ELT_STATE = DefaultDiagramElementState.class; + + /** + * Constructor. + */ + protected DiagramElementStateFactory() { + // Nothing + } + + /** + * Build a new factory instance. + * + * @return New instance. + */ + public static DiagramElementStateFactory newInstance() { + return new DiagramElementStateFactory(); + } + + /** + * Method to validate a diagram element. If <code>true</code>, + * {@link #buildDiagramElementState(DDiagramElement)} can be safely called. + * + * @param diagramElement + * Diagram element to validate. + * @return <code>true</code> if this element is valid. + * {@link #buildDiagramElementState(DDiagramElement)} can be safely + * called. + */ + public boolean isValid(final DDiagramElement diagramElement) { + boolean result = false; + + final EObject target = diagramElement.getTarget(); + final Option<? extends RepresentationElementMapping> mapping = new DDiagramElementQuery(diagramElement).getMapping(); + + if (target != null && mapping != null && mapping.some()) { + if (diagramElement instanceof DEdge) { + DEdge edge = (DEdge) diagramElement; + if (edge.getSourceNode() instanceof DDiagramElement) { + result = isValid((DDiagramElement) edge.getSourceNode()); + } + if (result && edge.getTargetNode() instanceof DDiagramElement) { + result = isValid((DDiagramElement) edge.getTargetNode()); + } + } else if (diagramElement.eContainer() instanceof DDiagramElement) { + result = isValid((DDiagramElement) diagramElement.eContainer()); + } else { + result = true; + } + } + + return result; + } + + /** + * Build a diagram element state. + * <p> + * Provided diagram element must have been validated firstly with + * {@link #isValid(DDiagramElement)}. + * </p> + * + * @param id + * Id of current diagram element + * @param diagramElement + * Diagram element + * @param crossReferencer + * Current cross-referencer + * @return A diagram element state. Cannot be <code>null</code>. + */ + public IDiagramElementState<? extends DDiagramElement> buildDiagramElementState(final Identifier id, final DDiagramElement diagramElement, final DiagramCrossReferencer crossReferencer) { + + final EObject target = diagramElement.getTarget(); + final DiagramElementMapping mapping = diagramElement.getDiagramElementMapping(); + + IDiagramElementState<DDiagramElement> diagramElementState = createDiagramElementStateInstance(id, diagramElement, crossReferencer); + diagramElementState.storeElementState(target, mapping, diagramElement); + return diagramElementState; + } + + @SuppressWarnings("unchecked") + private IDiagramElementState<DDiagramElement> createDiagramElementStateInstance(final Identifier id, final DDiagramElement diagramElement, final DiagramCrossReferencer crossReferencer) { + Constructor<? extends IDiagramElementState<? extends DDiagramElement>> cachedConstructor = CACHE.get(diagramElement.getClass()); + + // Cache found constructor in order to improve performances + if (cachedConstructor == null) { + Class<? extends IDiagramElementState<? extends DDiagramElement>> clazz = getDiagramElementStateClass(diagramElement); + + try { + cachedConstructor = clazz.getConstructor(Identifier.class, DiagramCrossReferencer.class); + CACHE.put(diagramElement.getClass(), cachedConstructor); + } catch (SecurityException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + try { + return (IDiagramElementState<DDiagramElement>) cachedConstructor.newInstance(id, crossReferencer); + } catch (InstantiationException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause().getMessage(), e.getCause()); + } + + } + + private Class<? extends IDiagramElementState<? extends DDiagramElement>> getDiagramElementStateClass(final DDiagramElement diagramElement) { + // Use default diagram element state type + Class<? extends IDiagramElementState<? extends DDiagramElement>> classFound = DEFAULT_DIAGRAM_ELT_STATE; + + for (Entry<Class<? extends DDiagramElement>, Class<? extends IDiagramElementState<? extends DDiagramElement>>> entry : ASSOCIATION.entrySet()) { + Class<? extends DDiagramElement> clazz = entry.getKey(); + + if (clazz.isAssignableFrom(diagramElement.getClass())) { + classFound = entry.getValue(); + break; + } + } + + return classFound; + } + + /** + * Dispose the local resource. + */ + public void dispose() { + CACHE.clear(); + } + +} |