diff options
Diffstat (limited to 'extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram')
17 files changed, 1829 insertions, 0 deletions
diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/Activator.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/Activator.java new file mode 100644 index 00000000000..1edda3a568f --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/Activator.java @@ -0,0 +1,69 @@ +/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * 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:
+ * Francois Le Fevre (CEA LIST) francois.le-fevre@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.diagram.dnd.smart;
+
+import org.eclipse.papyrus.infra.core.log.LogHelper;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.papyrus.uml.diagram.dnd"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ public static LogHelper log;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ log = new LogHelper(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/Uml2Graph.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/Uml2Graph.java new file mode 100644 index 00000000000..c6394e3cc04 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/Uml2Graph.java @@ -0,0 +1,429 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.TreeSet; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.papyrus.infra.emf.Activator; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.EClassComparator; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.EdgeEReference; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.UmlGraph; +import org.eclipse.uml2.uml.UMLFactory; +import org.eclipse.uml2.uml.UMLPackage; + +/** + * Object model to manipulate the graph + * @author Francois Le Fevre - CEA francois.le-fevre@cea.fr + * + */ +public class Uml2Graph { + + private static Uml2Graph INSTANCE = null; + public static final String NAME_SPLITTER=new String("@"); + + private UmlGraph myGraph; + private HashMap<String, NodeEClass> nodeEClassMap; + private HashMap<EClass, List<EClass>> eclass2ChildrenMap; + private HashMap<EClass, EList<EClass>> eclass2ParentMap; + private HashMap<EClass, List<EClass>> eclass2ConcreteMap; + + private HashMap<String, EdgeEReference> edgeEReferenceMap; + private UMLFactory umlFactory; + + public static Uml2Graph getInstance() + { + if (INSTANCE == null) + { INSTANCE = new Uml2Graph(); + } + return INSTANCE; + } + + private Uml2Graph(){ + Date start = new Date(); + //initialiaze the uml factory + umlFactory = UMLFactory.eINSTANCE; + + //create the graph + myGraph = new UmlGraph(); + + //prepare the map to navigate + nodeEClassMap = new HashMap<String, NodeEClass>(); + edgeEReferenceMap = new HashMap<String, EdgeEReference>(); + eclass2ChildrenMap = new HashMap<EClass, List<EClass>>(); + eclass2ParentMap = new HashMap<EClass, EList<EClass>>(); + eclass2ConcreteMap = new HashMap<EClass, List<EClass>>(); + + extractNodesFromUml(); + + buildParent2ChildrenMap(); + buildChildren2ParentMap(); + + extractEdgesFromUml(); + + Date end = new Date(); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Parsing of UML model2: done "+(end.getTime()-start.getTime())); + } + } + + private void buildChildren2ParentMap() { + + for(EClass eclass : eclass2ParentMap.keySet()){ + EList<EClass> eclassParents = eclass2ParentMap.get(eclass); + for(EClass eclassParent : eclassParents){ + List<EClass> eclassChildren = eclass2ChildrenMap.get(eclassParent); + if(eclassChildren==null){ + eclassChildren = new ArrayList<EClass>(); + } + eclassChildren.add(eclass); + eclass2ChildrenMap.put(eclassParent, eclassChildren); + } + } + + } + + private void buildParent2ChildrenMap() { + for(NodeEClass nodeEClass : nodeEClassMap.values()){ + fillSpecificHierarchy(nodeEClass.geteClass()); + } + } + + /** + * Extract the parent Eclass information + * @param myEClass + */ + private void fillSpecificHierarchy(EClass myEClass){ + if(myEClass!=null){ + EList<EClass> myEClassParents = myEClass.getEAllSuperTypes(); + eclass2ParentMap.put(myEClass,myEClassParents); + } + } + + private void extractNodesFromUml(){ + //TODO update to get all EClass directly + for(Method m : UMLPackage.eINSTANCE.getClass().getMethods()){ + if("interface org.eclipse.emf.ecore.EClass".equals(m.getReturnType().toString())){ + + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Will extract data from " + m.getName()); + + } + try { + //Explore the EClass + EClass myEclass = (EClass)m.invoke(umlFactory.getUMLPackage()); + exploreNode(myEclass); + + } catch (IllegalAccessException e) { + Activator.log.error(e.getMessage(),e); + } catch (IllegalArgumentException e) { + Activator.log.error(e.getMessage(),e); + } catch (InvocationTargetException e) { + Activator.log.error(e.getMessage(),e); + } + } + else{ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("No parsing of method which returns:" + m.getReturnType().toString()+"\t"+m.getName()); + } + } + } + } + + private void exploreNode(EClass myEClass){ + if(myEClass!=null){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("exploreEClass "+myEClass.getInstanceClassName()+"\t"+myEClass.isAbstract()); + } + NodeEClass nodeEClass; + if(nodeEClassMap.get(myEClass.getInstanceClassName())==null){ + + nodeEClass = nodeEClassMap.get(myEClass.getInstanceClassName()); + if(nodeEClass==null){ + nodeEClass = new NodeEClass(myEClass.getInstanceClassName(),myEClass); + myGraph.addVertex(nodeEClass); + nodeEClassMap.put(myEClass.getInstanceClassName(),nodeEClass); + } + for(EReference er : myEClass.getEAllReferences()){ + if(!er.getEType().getInstanceClassName().startsWith("org.eclipse.emf.ecore.")){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("exploreEClass AllContainments "+er.getEType().getInstanceClassName()); + } + + NodeEClass nodeEClassEReference = nodeEClassMap.get(er.getEType().getInstanceClassName()); + if(nodeEClassEReference==null){ + nodeEClassEReference = new NodeEClass(er.getEType().getInstanceClassName(),er.getEReferenceType()); + myGraph.addVertex(nodeEClassEReference); + nodeEClassMap.put(er.getEType().getInstanceClassName(),nodeEClassEReference); + + EList<EClass> myEClassParents = er.getEReferenceType().getEAllSuperTypes(); + for(EClass myEClassParent : myEClassParents){ + NodeEClass nodeEClassEReference2 = nodeEClassMap.get(myEClassParent.getInstanceClassName()); + if(nodeEClassEReference2==null){ + nodeEClassEReference2 = new NodeEClass(myEClassParent.getInstanceClassName(),myEClassParent); + myGraph.addVertex(nodeEClassEReference2); + nodeEClassMap.put(myEClassParent.getInstanceClassName(),nodeEClassEReference2); + } + } + } + } + } + + EList<EClass> myEClassParents = myEClass.getEAllSuperTypes(); + for(EClass myEClassParent : myEClassParents){ + NodeEClass nodeEClassEReference2 = nodeEClassMap.get(myEClassParent.getInstanceClassName()); + if(nodeEClassEReference2==null){ + nodeEClassEReference2 = new NodeEClass(myEClassParent.getInstanceClassName(),myEClassParent); + myGraph.addVertex(nodeEClassEReference2); + nodeEClassMap.put(myEClassParent.getInstanceClassName(),nodeEClassEReference2); + } + } + } + } + } + + + private void extractEdgesFromUml(){ + //TODO update to get all EClass directly + for(Method m : UMLPackage.eINSTANCE. getClass().getMethods()){ + if("interface org.eclipse.emf.ecore.EClass".equals(m.getReturnType().toString())){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Will extract data from " + m.getName()); + } + try { + //Explore the EClass + EClass myEclass = (EClass)m.invoke(umlFactory.getUMLPackage()); + exploreEdgesOfEClass(myEclass); + + } catch (IllegalAccessException e) { + Activator.log.error(e.getMessage(),e); + } catch (IllegalArgumentException e) { + Activator.log.error(e.getMessage(),e); + } catch (InvocationTargetException e) { + Activator.log.error(e.getMessage(),e); + } + } + else{ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("No parsing of method which returns:" + m.getReturnType().toString()+"\t"+m.getName()); + } + } + } + } + + private void exploreEdgesOfEClass(EClass myEClass){ + if(myEClass!=null){ + + + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("exploreEdgesofEClass "+myEClass.getInstanceClassName()+"\t"+myEClass.isAbstract()); + } + NodeEClass source = nodeEClassMap.get(myEClass.getInstanceClassName()); + + for(EReference er : myEClass.getEAllReferences()){ + NodeEClass target = nodeEClassMap.get(er.getEType().getInstanceClassName()); + + if(source!=null && target !=null){ + //Filter the EReference + if(!"org.eclipse.emf.ecore.EAnnotation".equals(er.getEType().getInstanceClassName()) + && !"ownedElement".equals(er.getName()) + && !"owner".equals(er.getName()) + && !"ownedMember".equals(er.getName()) + && !"importedMember".equals(er.getName()) + && !"namespace".equals(er.getName()) + && !"member".equals(er.getName()) + && !"redefinedElement".equals(er.getName()) + && !"clientDependency".equals(er.getName()) + && !"packageImport".equals(er.getName()) + && !"elementImport".equals(er.getName()) + && !"ownedComment".equals(er.getName()) + ){ + + //Work with real Target + List<EClass> targetConcretEclasses = getAllConcreteEClasses(target.geteClass()); + + NodeEClass targetConcretEclasseNode2; + EdgeEReference edgeEReference2; + String edgeName2; + boolean b; + for(EClass targetConcretEclasse : targetConcretEclasses){ + targetConcretEclasseNode2 = nodeEClassMap.get(targetConcretEclasse.getInstanceTypeName()); + edgeName2 = buildUniqName(myEClass, er, targetConcretEclasse); + edgeEReference2 = new EdgeEReference(edgeName2,er.eContainmentFeature().isContainment(), er,targetConcretEclasse); + b = myGraph.addEdge(edgeEReference2, source, targetConcretEclasseNode2); + if(!b){ + Activator.log.error("problem in creation of graph",new Error()); + } + edgeEReferenceMap.put(edgeName2,edgeEReference2); + } + + } + } + } + } + } + + /** + * Given an EClass, return all concrete EClasses, withitself if it is already a concrete EClass + * @param initialEClass + * @return + */ + public List<EClass> getAllConcreteEClasses(EClass initialEClass){ + List<EClass> result=null; + if(initialEClass!=null){ + + result = eclass2ConcreteMap.get(initialEClass); + + if(result==null){ + result = new ArrayList<EClass>(); + TreeSet<EClass> preResult = new TreeSet<EClass>(new EClassComparator()); + + if(initialEClass!=null){ + + //Add it if it is alaready a concrete EClass + if(!initialEClass.isAbstract()){ + preResult.add(initialEClass); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("adding non abstract class: "+initialEClass.getInstanceTypeName()); + } + } + + //Explore its children + List<EClass> potentialConcreteEClasses= eclass2ChildrenMap.get(initialEClass); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("exploring "+initialEClass.getInstanceTypeName()+ "\tchildren["+potentialConcreteEClasses+"]"); + } + if(potentialConcreteEClasses!=null){ + for(EClass potentialConcreteEClass: potentialConcreteEClasses){ + //Explore it again + preResult.addAll(getAllConcreteEClasses(potentialConcreteEClass)); + } + } + } + + result.addAll(preResult); + + eclass2ConcreteMap.put(initialEClass,result); + } + } + return result; + } + + public void computeStatusActions(EClass source,EClass target) { + NodeEClass sourceNode = nodeEClassMap.get(source.getInstanceTypeName()); + NodeEClass targetNode = nodeEClassMap.get(target.getInstanceTypeName()); + + Collection<EdgeEReference> mySourceIncidentEdges = myGraph.getInEdges(sourceNode); + for(EdgeEReference myEdgeEReference : mySourceIncidentEdges){ + NodeEClass potentialIntermediate = myGraph.getSource(myEdgeEReference); + Collection<EdgeEReference> mySourceIncidentEdges2 = myGraph.getInEdges(potentialIntermediate); + for(EdgeEReference myEdgeEReference2 : mySourceIncidentEdges2){ + NodeEClass potentialTarget = myGraph.getSource(myEdgeEReference2); + if(potentialTarget==targetNode){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Found path source["+source.getInstanceTypeName()+"] <- "+myEdgeEReference2.getName()+"["+potentialIntermediate.geteClass().getInstanceTypeName()+"] <- target["+target.getInstanceTypeName()+"]"); + } + } + } + + Collection<EdgeEReference> mySourceIncidentEdges3 = myGraph.getOutEdges(potentialIntermediate); + for(EdgeEReference myEdgeEReference3 : mySourceIncidentEdges3){ + NodeEClass potentialTarget = myGraph.getSource(myEdgeEReference3); + if(potentialTarget==targetNode){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Found path source["+source.getInstanceTypeName()+"] <- "+myEdgeEReference3.getName()+"["+potentialIntermediate.geteClass().getInstanceTypeName()+"] -> target["+target.getInstanceTypeName()+"]"); + } + } + } + } + + Collection<EdgeEReference> mySourceIncidentEdges3 = myGraph.getOutEdges(sourceNode); + for(EdgeEReference myEdgeEReferenceZ : mySourceIncidentEdges3){ + NodeEClass potentialIntermediate = myGraph.getSource(myEdgeEReferenceZ); + Collection<EdgeEReference> mySourceIncidentEdges2 = myGraph.getInEdges(potentialIntermediate); + for(EdgeEReference myEdgeEReferenceE : mySourceIncidentEdges2){ + NodeEClass potentialTarget = myGraph.getSource(myEdgeEReferenceE); + if(potentialTarget==targetNode){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Found path source["+source.getInstanceTypeName()+"] <- "+myEdgeEReferenceZ.getName()+"["+potentialIntermediate.geteClass().getInstanceTypeName()+"] <- target["+target.getInstanceTypeName()+"]"); + } + } + } + + Collection<EdgeEReference> mySourceIncidentEdges4 = myGraph.getOutEdges(potentialIntermediate); + for(EdgeEReference myEdgeEReference4 : mySourceIncidentEdges4){ + NodeEClass potentialTarget = myGraph.getSource(myEdgeEReference4); + if(potentialTarget==targetNode){ + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("Found path source["+source.getInstanceTypeName()+"] <- "+myEdgeEReferenceZ.getName()+"["+potentialIntermediate.geteClass().getInstanceTypeName()+"] -> target["+target.getInstanceTypeName()+"]"); + } + } + } + } + } + + + /** + * Generate an unique name for a given EReference based on the source and target + * @param myEClass + * @param er + * @param targetConcreteEClass + * @return + */ + private String buildUniqName(EClass myEClass, EReference er, EClass targetConcreteEClass) { + return er.getName()+NAME_SPLITTER+myEClass.getInstanceTypeName()+NAME_SPLITTER+er.getEType().getInstanceTypeName()+NAME_SPLITTER+targetConcreteEClass.getInstanceTypeName(); + } + + public UmlGraph getUmlGraph() { + return myGraph; + } + + public HashMap<String, NodeEClass> getEclass2Node() { + return nodeEClassMap; + } + + public static Uml2Graph getINSTANCE() { + return INSTANCE; + } + + public HashMap<String, NodeEClass> getNodeEClassMap() { + return nodeEClassMap; + } + + public HashMap<EClass, List<EClass>> getEclass2ChildrenMap() { + return eclass2ChildrenMap; + } + + public HashMap<EClass, EList<EClass>> getEclass2ParentMap() { + return eclass2ParentMap; + } + + public HashMap<String, EdgeEReference> getEdgeEReferenceMap() { + return edgeEReferenceMap; + } + + public UMLFactory getUmlFactory() { + return umlFactory; + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/AbstractUml2GraphServices.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/AbstractUml2GraphServices.java new file mode 100644 index 00000000000..c7150c4807c --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/AbstractUml2GraphServices.java @@ -0,0 +1,70 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api; + +import java.util.Set; + +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.Uml2Graph; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.service.AllPathDetector; + + +/** + * Shared implementation to retrieve the set of path for a given drag and drop + * @author Francois Le Fevre - francois.le-fevre@cea.fr + * + */ +public abstract class AbstractUml2GraphServices implements Uml2GraphServices { + + protected AllPathDetector allPathDetector; + + /** + * The graph view of the UML model + */ + protected Uml2Graph uml2Graph; + + public AbstractUml2GraphServices(){ + allPathDetector = new AllPathDetector(); + uml2Graph = Uml2Graph.getInstance(); + } + + public AbstractUml2GraphServices(int depth, int threshold){ + allPathDetector = new AllPathDetector(depth, threshold); + uml2Graph = Uml2Graph.getInstance(); + } + + /** + * @see org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api.Uml2GraphServices#proposedActionsFromDnd(org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass, org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass) + * + * @param source + * @param target + * @return + */ + public Set<Path> proposedActionsFromDnd(NodeEClass source, NodeEClass target) { + //Compute the paths and filter them + return allPathDetector.filterAnalysis(uml2Graph,source, target); + } + + /* + * Getter + */ + + /** + * @return the allPathDetector + */ + public AllPathDetector getAllPathDetector() { + return allPathDetector; + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/Uml2GraphServices.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/Uml2GraphServices.java new file mode 100644 index 00000000000..c6b8365d00c --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/api/Uml2GraphServices.java @@ -0,0 +1,57 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; + +/** + * Interface defining services relative to given a source/target give me the set of possible actions + * @author Francois Le Fevre - francois.le-fevre@cea.fr + * + */ +public interface Uml2GraphServices { + + /** + * @param source the initial EClass selected by the user in the ModelExplorer + * @param target the targeted EClass selected by the user in the Diagram + * @return the set of path could not be null + */ + public Set<Path> proposedActionsFromDnd(EClass source, EClass target); + + /** + * @param source the initial EClass selected by the user in the ModelExplorer + * @param target the targeted EClass selected by the user in the Diagram + * @return the set of path could not be null + */ + public Set<Path> proposedActionsFromDnd(String source, String target); + + /** + * @param source the initial EClass selected by the user in the ModelExplorer + * @param target the targeted EClass selected by the user in the Diagram + * @return the set of path could not be null + */ + public Set<Path> proposedActionsFromDnd(NodeEClass source, NodeEClass target); + + /** + * @param source the initial EClass selected by the user in the ModelExplorer + * @param target the targeted EClass selected by the user in the Diagram + * @return the set of path could not be null + */ + public Collection<String> proposedLitteralActionsFromDnd(String source, String target); + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/AbstractUmlGraph.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/AbstractUmlGraph.java new file mode 100644 index 00000000000..7c46446cdce --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/AbstractUmlGraph.java @@ -0,0 +1,57 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import java.util.Collection; +import java.util.HashMap; + +/** + * The main class dedicated to hold the graph defintion of an uml model + * @author flefevre + * + */ +public abstract class AbstractUmlGraph implements IUmlGraph{ + + protected HashMap<EdgeEReference, NodeEClass> edge2Source; + protected HashMap<EdgeEReference, NodeEClass> edge2Target; + + protected HashMap<NodeEClass, Collection<EdgeEReference>> source2InEdges; + protected HashMap<NodeEClass, Collection<EdgeEReference>> source2OutEdges; + + public AbstractUmlGraph(){ + edge2Source = new HashMap<EdgeEReference, NodeEClass>(); + edge2Target = new HashMap<EdgeEReference, NodeEClass>(); + + source2InEdges = new HashMap<NodeEClass, Collection<EdgeEReference>>() ; + source2OutEdges = new HashMap<NodeEClass, Collection<EdgeEReference>>() ; + } + + public NodeEClass getSource(EdgeEReference myEdgeEReference){ + return edge2Source.get(myEdgeEReference); + } + + public NodeEClass getDest(EdgeEReference myEdgeEReference){ + return edge2Target.get(myEdgeEReference); + } + + + public Collection<EdgeEReference> getOutEdges(NodeEClass nodeEClassEReference){ + return source2OutEdges.get(nodeEClassEReference); + } + + public Collection<EdgeEReference> getInEdges(NodeEClass nodeEClassEReference){ + return source2InEdges.get(nodeEClassEReference); + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EClassComparator.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EClassComparator.java new file mode 100644 index 00000000000..8d4ad9d40c6 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EClassComparator.java @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import java.util.Comparator; + +import org.eclipse.emf.ecore.EClass; + +/** + * Comparator of two ECLass + * @author flefevre + * + */ +public class EClassComparator implements Comparator<EClass>{ + + public int compare(EClass e1, EClass e2) { + if(e1.getName()!=null){ + return e1.getName().compareTo(e2.getName()); + } + else{ + return -1; + } + } +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EdgeEReference.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EdgeEReference.java new file mode 100644 index 00000000000..343da05c3be --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/EdgeEReference.java @@ -0,0 +1,110 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; + +/** + * Object model to manipulate the edges of the uml graph + * @author Francois Le Fevre - CEA francois.le-fevre@cea.fr + * + */ +public class EdgeEReference implements Comparable<EdgeEReference>{ + + /** + * the name of the Ecore EdgeEreference + * + */ + private final String name; + /** + * is the EReference a composition + */ + private final boolean isComposition; + /** + * the Ecore Ereference + */ + private final EReference eReference; + /** + * the target class associated with the EReference + */ + private final EClass targetConcretEclasse; + + public EdgeEReference(String name, boolean isComposition, EReference eReference,EClass targetConcretEclasse) { + super(); + this.name = name; + this.isComposition=isComposition; + this.eReference = eReference; + this.targetConcretEclasse = targetConcretEclasse; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((eReference == null) ? 0 : eReference.hashCode()); + result = prime * result + (isComposition ? 1231 : 1237); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + EdgeEReference other = (EdgeEReference) obj; + if (eReference == null) { + if (other.eReference != null) + return false; + } else if (!eReference.equals(other.eReference)) + return false; + if (isComposition != other.isComposition) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + public int compareTo(EdgeEReference o) { + + return this.getName().compareTo(o.getName()); + } + + /* + * getter methods + */ + + public EClass getTargetConcretEclasse() { + return targetConcretEclasse; + } + + public String getName() { + return name; + } + + public boolean isComposition() { + return isComposition; + } + + public EReference geteReference() { + return eReference; + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/IUmlGraph.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/IUmlGraph.java new file mode 100644 index 00000000000..b3269c1449b --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/IUmlGraph.java @@ -0,0 +1,67 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import java.util.Collection; + +/** + * Interface defining the contracts to add edge or vertex and the getter methods + * @author flefevre + * + */ +public interface IUmlGraph{ + + /** + * @param nodeEClassEReference non-null + */ + public void addVertex(NodeEClass nodeEClassEReference); + + /** + * @param edgeEReference non-null ecore ereference between the source and the target + * @param source non-null + * @param target non-null + * @return + */ + public boolean addEdge(EdgeEReference edgeEReference, NodeEClass source, NodeEClass target); + + /** + * given an Edge it should return the source NodeEClass + * @param myEdgeEReference + * @return + */ + public NodeEClass getSource(EdgeEReference myEdgeEReference); + + + /** + * given an Edge it should return the target NodeEClass + * @param myEdgeEReference + * @return + */ + public NodeEClass getDest(EdgeEReference myEdgeEReference); + + /** + * given a nodeEClass, return the collection of outgoing edges + * @param nodeEClassEReference + * @return + */ + public Collection<EdgeEReference> getOutEdges(NodeEClass nodeEClassEReference); + + /** + * given a nodeEClass, return the collection of ingoing edges + * @param nodeEClassEReference + * @return + */ + public Collection<EdgeEReference> getInEdges(NodeEClass nodeEClassEReference); + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/NodeEClass.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/NodeEClass.java new file mode 100644 index 00000000000..382a87edcf9 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/NodeEClass.java @@ -0,0 +1,89 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import org.eclipse.emf.ecore.EClass; + +/** + * Object model to manipulate the node of the uml graph + * @author Francois Le Fevre - CEA francois.le-fevre@cea.fr + * + */ +public class NodeEClass implements Comparable<NodeEClass>{ + + /** + * the name of the EClass + */ + private String name; + /** + * the ECore EClass + */ + private EClass eClass; + + public NodeEClass(String name, EClass eClass) { + super(); + this.name = name; + this.eClass = eClass; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NodeEClass other = (NodeEClass) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + + public int compareTo(NodeEClass o) { + + return this.getName().compareTo(o.getName()); + } + + + @Override + public String toString() { + return name ; + } + + /* + * Getter methods + */ + + + public EClass geteClass() { + return eClass; + } + + public String getName() { + return name; + } +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/Path.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/Path.java new file mode 100644 index 00000000000..29d0f6ea638 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/Path.java @@ -0,0 +1,83 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import java.util.List; + +/** + * A path is the succession of EdgeEReference between two NodeEClass + * @author Francois Le Fevre - CEA francois.le-fevre@cea.fr + */ +public class Path implements Comparable<Path>{ + + private final List<EdgeEReference> way; + private final String name; + + public Path(List<EdgeEReference> way) { + super(); + this.way = way; + this.name = getRepresentation(way); + } + + + private String getRepresentation(List<EdgeEReference> path){ + StringBuffer tmp = new StringBuffer(); + for(EdgeEReference c : path){ + tmp.append(c.getName()+" _ "); + } + return tmp.toString(); + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Path other = (Path) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + + public List<EdgeEReference> getWay() { + return way; + } + + + public String getName() { + return name; + } + + + public int compareTo(Path o) { + return name.compareTo(o.getName()); + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/UmlGraph.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/UmlGraph.java new file mode 100644 index 00000000000..393458310e6 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/model/UmlGraph.java @@ -0,0 +1,56 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * The main class dedicated to hold the graph defintion of an uml model + * @author flefevre + * + */ +public class UmlGraph extends AbstractUmlGraph{ + + public UmlGraph(){ + super(); + } + + public void addVertex(NodeEClass nodeEClassEReference){ + source2InEdges.put(nodeEClassEReference,new ArrayList<EdgeEReference>()); + source2OutEdges.put(nodeEClassEReference,new ArrayList<EdgeEReference>()); + } + + public boolean addEdge(EdgeEReference edgeEReference, NodeEClass source, NodeEClass target){ + edge2Source.put(edgeEReference, source); + edge2Target.put(edgeEReference, target); + + Collection<EdgeEReference> ins = source2InEdges.get(target); + if(ins==null){ + ins = new ArrayList<EdgeEReference>(); + } + ins.add(edgeEReference); + source2InEdges.put(target,ins); + + Collection<EdgeEReference> outs = source2OutEdges.get(source); + if(outs==null){ + outs = new ArrayList<EdgeEReference>(); + } + outs.add(edgeEReference); + source2OutEdges.put(source, outs); + + return true; + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/AllPathDetector.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/AllPathDetector.java new file mode 100644 index 00000000000..a000b9ec0a4 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/AllPathDetector.java @@ -0,0 +1,258 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.eclipse.papyrus.infra.emf.Activator; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.Uml2Graph; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.EdgeEReference; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.UmlGraph; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.util.FilterUtils; + +import java.util.Date; + +/** + * Class dedicated to compute the path between two nodes given an uml graph + * @author Francois Le Fevre - CEA francois.le-fevre@cea.fr + */ +public class AllPathDetector +{ + /** + * the maximum number of edges to walk throught + */ + protected int depth; + + /** + * the maximum number of path to filter + */ + protected int displayThreshold; + + protected HashMap<String, Set<Path> > precomputePath; + + public AllPathDetector(){ + this.depth = 2; + this.displayThreshold=20; + precomputePath = new HashMap<String, Set<Path>>(); + } + + public AllPathDetector(int depth, int threshold){ + this.depth = depth; + this.displayThreshold=threshold; + precomputePath = new HashMap<String, Set<Path>>(); + } + + /** + * Given a graph, a start node and a end node, and the maximum steps , it will return a list of possible path between the two nodes + * @param graph + * @param startNode + * @param endNode + * @param maxDepth + * @return + */ + public List<Path> getAllPathsBetweenNodes(UmlGraph graph, + NodeEClass startNode, NodeEClass endNode, int maxDepth) + { + List<Path> allPaths = new ArrayList<Path>(); + + List<EdgeEReference> currentPath = new ArrayList<EdgeEReference>(); + + findAllPaths(startNode, startNode, endNode, currentPath, graph, maxDepth , 0 , allPaths); + + return allPaths; + } + + /** + * Recursive methods in charge to compute the different paths between a start and an end node given a maximum of edges to walk throught + * @param currentNode + * @param startNode + * @param endNode + * @param currentPath + * @param graph + * @param maxDepth + * @param currentDepth + * @param allPaths + */ + public void findAllPaths(NodeEClass currentNode, NodeEClass startNode, NodeEClass endNode, + List<EdgeEReference> currentPath,UmlGraph graph, + int maxDepth, int currentDepth, List<Path> allPaths) + { + + Collection<EdgeEReference> outgoingEdges = graph.getOutEdges(currentNode); + if (currentDepth < maxDepth) + { + for (EdgeEReference outEdge : outgoingEdges) + { + NodeEClass outNode = graph.getDest(outEdge); + if (outNode.equals(startNode)) + { + List<EdgeEReference> cyclePath = new ArrayList<EdgeEReference>(currentPath); + cyclePath.add(outEdge); + continue; + } + + List<EdgeEReference> newPath = new ArrayList<EdgeEReference>(currentPath); + newPath.add(outEdge); + + if (outNode.equals(endNode)) + { + Path myPath = new Path(newPath); + allPaths.add(myPath); + continue; + } + + findAllPaths(outNode, startNode, endNode, newPath, graph, maxDepth, currentDepth + 1, allPaths); + } + } + } + + /** + * Method in charge to filter the different paths found, to retrieve a shorter number of soultion. + * it is an heuristic. + * @param uml2graph + * @param source + * @param target + * @return + */ + public Set<Path> filterAnalysis(Uml2Graph uml2graph, NodeEClass source, NodeEClass target){ + Date startTime = new Date(); + + Set<Path> result = precomputePath.get(source.getName()+Uml2Graph.NAME_SPLITTER+target.getName()); + + if(result==null){ + result = new TreeSet<Path>(); + + List<Path> resultFull = getAllPathsBetweenNodes(uml2graph.getUmlGraph(), target ,source, depth); + Date endTime = new Date(); + + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("path compute in "+(endTime.getTime()-startTime.getTime())); + } + + startTime = new Date(); + List<Path> hard = FilterUtils.hardFilter(resultFull); + + List<Path> tmp = new ArrayList<Path>(); + if(hard.size()<=displayThreshold){ + result.addAll(hard); + } + else{ + for(Path h : hard){ + if(h.getWay().size()<=2){ + tmp.add(h); + } + } + + if(tmp.size()<=displayThreshold){ + result.addAll(tmp); + } + } + + List<Path> soft = FilterUtils.softFilter(resultFull); + tmp = new ArrayList<Path>(); + if(soft.size()<=displayThreshold){ + result.addAll(soft); + } + else{ + for(Path s : soft){ + if(s.getWay().size()<=2){ + tmp.add(s); + } + } + + if(tmp.size()<=displayThreshold){ + result.addAll(tmp); + } + } + List<Path> trim = FilterUtils.trimFilter(resultFull); + tmp = new ArrayList<Path>(); + if(trim.size()<=displayThreshold){ + result.addAll(trim); + } + else{ + for(Path t : trim){ + if(t.getWay().size()<=2){ + tmp.add(t); + } + } + + if(tmp.size()<=displayThreshold){ + result.addAll(tmp); + } + } + List<Path> end = FilterUtils.endFilter(resultFull); + tmp = new ArrayList<Path>(); + if(end.size()<=displayThreshold){ + result.addAll(end); + } + else{ + for(Path e : end){ + if(e.getWay().size()<=2){ + tmp.add(e); + } + } + + if(tmp.size()<=displayThreshold){ + result.addAll(tmp); + } + } + + precomputePath.put(source.getName()+Uml2Graph.NAME_SPLITTER+target.getName(), result); + endTime = new Date(); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("path filter in "+(endTime.getTime()-startTime.getTime())); + } + } + + return result; + } + + /* + * getter and setter + */ + + /** + * @return the depth + */ + public int getDepth() { + return depth; + } + + /** + * @param depth the depth to set + */ + public void setDepth(int depth) { + this.depth = depth; + } + + /** + * @return the displayThreshold + */ + public int getDisplayThreshold() { + return displayThreshold; + } + + /** + * @param displayThreshold the displayThreshold to set + */ + public void setDisplayThreshold(int displayThreshold) { + this.displayThreshold = displayThreshold; + } +}
\ No newline at end of file diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/GenericUml2GraphServices.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/GenericUml2GraphServices.java new file mode 100644 index 00000000000..729d16f6367 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/service/GenericUml2GraphServices.java @@ -0,0 +1,88 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api.AbstractUml2GraphServices; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.NodeEClass; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; + +/** + * One basic implementation to retrieve Path of actions given a set of source/target elements + * @author flefevre + * + */ +public class GenericUml2GraphServices extends AbstractUml2GraphServices { + + + public GenericUml2GraphServices() + { + super(); + } + + public GenericUml2GraphServices(int depth, int threshold) + { + super(depth,threshold); + } + + /** + * @see org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api.Uml2GraphServices#proposedActionsFromDnd(org.eclipse.emf.ecore.EClass, org.eclipse.emf.ecore.EClass) + * + * @param source + * @param target + * @return + */ + public Set<Path> proposedActionsFromDnd(EClass source, EClass target) { + //Retrieve the node from the graph + NodeEClass mySourceNode = uml2Graph.getNodeEClassMap().get(source.getInstanceTypeName()); + NodeEClass myTargetNode = uml2Graph.getNodeEClassMap().get(target.getInstanceTypeName()); + //Compute the paths and filter them + return proposedActionsFromDnd(mySourceNode, myTargetNode) ; + } + + /** + * @see org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api.Uml2GraphServices#proposedActionsFromDnd(java.lang.String, java.lang.String) + * + * @param source + * @param target + * @return + */ + public Set<Path> proposedActionsFromDnd(String source, String target) { + NodeEClass mySourceNode = uml2Graph.getNodeEClassMap().get(source); + NodeEClass myTargetNode = uml2Graph.getNodeEClassMap().get(target); + return proposedActionsFromDnd(mySourceNode, myTargetNode); + } + + /** + * @see org.eclipse.papyrus.uml.diagram.dnd.smart.graph.api.Uml2GraphServices#proposedLitteralActionsFromDnd(java.lang.String, java.lang.String) + * + * @param source + * @param target + * @return + */ + public Collection<String> proposedLitteralActionsFromDnd(String source, String target) { + Collection<String> result = new ArrayList<String>(); + + Set<Path> paths= proposedActionsFromDnd(source, target); + + for(Path p :paths){ + result.add(p.getName()+"\n"); + } + return result; + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/util/FilterUtils.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/util/FilterUtils.java new file mode 100644 index 00000000000..9310dc5f922 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/graph/util/FilterUtils.java @@ -0,0 +1,120 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.dnd.smart.graph.util; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.Uml2Graph; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.EdgeEReference; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; + +/** + * A set of filter methods in charge to reduce the number of paths found. + * @author flefevre + * + */ +public class FilterUtils { + + public static List<Path> hardFilter(List<Path> bs){ + List<Path> result = new ArrayList<Path>(); + + boolean isprint; + for(Path b : bs){ + isprint=true; + for(EdgeEReference c : b.getWay()){ + String[] names = c.getName().split(Uml2Graph.NAME_SPLITTER); + if(!names[2].equals(names[3])){ + isprint=false; + break; + } + } + + if(isprint){ + result.add(b); + } + } + + return result; + } + + public static List<Path> softFilter(List<Path> bs){ + List<Path> result = new ArrayList<Path>(); + + boolean isprint; + for(Path b : bs){ + isprint=false; + for(EdgeEReference c : b.getWay()){ + String[] names = c.getName().split(Uml2Graph.NAME_SPLITTER); + if(names[2].equals(names[3])){ + isprint=true; + } + } + + if(isprint){ + result.add(b); + } + } + + return result; + } + + public static List<Path> endFilter(List<Path> bs){ + List<Path> result = new ArrayList<Path>(); + + boolean isprint; + for(Path b : bs){ + isprint=false; + + EdgeEReference c = b.getWay().get(b.getWay().size()-1); + String[] names = c.getName().split(Uml2Graph.NAME_SPLITTER); + if(names[2].equals(names[3])){ + isprint=true; + } + + if(isprint){ + result.add(b); + } + } + + return result; + } + + public static List<Path> startFilter(List<Path> bs){ + List<Path> result = new ArrayList<Path>(); + + boolean isprint; + for(Path b : bs){ + isprint=false; + + EdgeEReference c = b.getWay().get(0); + String[] names = c.getName().split(Uml2Graph.NAME_SPLITTER); + if(names[2].equals(names[3])){ + isprint=true; + } + + if(isprint){ + result.add(b); + } + } + + return result; + } + + public static List<Path> trimFilter(List<Path> bs){ + List<Path> tmp = endFilter(bs); + return startFilter(tmp); + } + +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/Messages.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/Messages.java new file mode 100644 index 00000000000..efd8cf6961b --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/Messages.java @@ -0,0 +1,33 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * @author flefevre + * + */ +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.papyrus.uml.diagram.dnd.smart.messages.messages"; //$NON-NLS-1$ + public static String SmartDropStrategy_Description; + public static String SmartDropStrategy_Label; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/messages.properties b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/messages.properties new file mode 100644 index 00000000000..7a3a252cb88 --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/messages/messages.properties @@ -0,0 +1,2 @@ +SmartDropStrategy_Description=SmartDrop an eobject into a target eobject +SmartDropStrategy_Label=SmartDrop will propose you any available command.
\ No newline at end of file diff --git a/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/strategy/SmartDropStrategy.java b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/strategy/SmartDropStrategy.java new file mode 100644 index 00000000000..fa6044e3dde --- /dev/null +++ b/extraplugins/uml/org.eclipse.papyrus.uml.diagram.dnd.smart/src/org/eclipse/papyrus/uml/diagram/dnd/smart/strategy/SmartDropStrategy.java @@ -0,0 +1,207 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.dnd.smart.strategy; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.util.FeatureMapUtil; +import org.eclipse.gef.EditPart; +import org.eclipse.gef.Request; +import org.eclipse.gef.commands.Command; +import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; +import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; +import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; +import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; +import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil; +import org.eclipse.papyrus.infra.gmfdiag.dnd.strategy.TransactionalCommandsDropStrategy; +import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; +import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; +import org.eclipse.papyrus.uml.diagram.dnd.smart.Activator; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.EdgeEReference; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.model.Path; +import org.eclipse.papyrus.uml.diagram.dnd.smart.graph.service.GenericUml2GraphServices; +import org.eclipse.papyrus.uml.diagram.dnd.smart.messages.Messages; +import org.eclipse.swt.graphics.Image; + +/** + * A DropStrategy to "Signal" a Class. + * Drop a signal on a Class operation section to type it. + * This will create a new Reception operation in the interaction, typed by the dropped classifier. + * + * @author Francois Le Fevre + * + */ +public class SmartDropStrategy extends TransactionalCommandsDropStrategy { + + GenericUml2GraphServices genericUml2GraphServices; + + public SmartDropStrategy(){ + genericUml2GraphServices = new GenericUml2GraphServices(); + } + + public String getLabel() { + return Messages.SmartDropStrategy_Label; + } + + public String getDescription() { + return Messages.SmartDropStrategy_Description; + } + + public Image getImage() { + return null; + } + + public String getID() { + return Activator.PLUGIN_ID + ".smart.represents"; //$NON-NLS-1$ + } + + /** + * @see org.eclipse.papyrus.infra.gmfdiag.dnd.strategy.DropStrategy#getPriority() + * + * @return + * @deprecated + */ + public int getPriority() { + return 0; + } + + /** + * @see org.eclipse.papyrus.infra.gmfdiag.dnd.strategy.TransactionalCommandsDropStrategy#doGetCommands(org.eclipse.gef.Request, org.eclipse.gef.EditPart) + * + * @param request + * @param targetEditPart + * @return + */ + @Override + protected List<Command> doGetCommands(Request request, final EditPart targetEditPart) { + List<EObject> sourceElements = getSourceEObjects(request); + // The only supported case is "Drop a single signal on a single Operation of a Classifier" + if (sourceElements.size() != 1) { + return null; + } + final EObject sourceElement = sourceElements.get(0); + + final EObject targetElement = getTargetSemanticElement(targetEditPart); + + final Set<Path> paths = genericUml2GraphServices.proposedActionsFromDnd(sourceElement.eClass(), targetElement.eClass()); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("paths size "+paths.size()); + } + + IElementEditService provider = ElementEditServiceUtils.getCommandProvider(sourceElement); + if(provider == null) { + return null; + } + + List<Command> myCommands = new ArrayList<Command>(); + + for(final Path p : paths){ + + CompositeCommand cc = new CompositeCommand(getLabel()); + + Command resultCommand = new Command(getLabel()) { + @SuppressWarnings("unchecked") + @Override + public void execute() { + EObject container= targetElement; + + //Filter to have only one command + //Doing the initial cascade from Target to Source + for(int i=0; i< p.getWay().size()-1 ; i++){ + EdgeEReference er = p.getWay().get(i); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("creation of "+er.geteReference().getName()+"\tin "+container.toString()+"\twith "+ er.getTargetConcretEclasse().getInstanceTypeName()); + } + + // Creates the slot + EObject newlyIntermediateEObject = EMFCoreUtil.create(container, er.geteReference(), er.getTargetConcretEclasse()); + + //set name + if(newlyIntermediateEObject.eClass().getEStructuralFeature("name")!=null){ + newlyIntermediateEObject.eSet(newlyIntermediateEObject.eClass().getEStructuralFeature("name"), er.geteReference().getName());//$NON-NLS-1$ + } + + container=newlyIntermediateEObject; + } + //Finally the set the final intermediate with the Source + EReference er = p.getWay().get(p.getWay().size()-1).geteReference(); + if (FeatureMapUtil.isMany(container,er)) { + ((Collection) container.eGet(er)).add(sourceElement); + } else { + container.eSet(er, sourceElement); + } + + //Graphical command: key question on which element + DropObjectsRequest dropObjectsRequest = new DropObjectsRequest(); + ArrayList<EObject> list = new ArrayList<EObject>(); + if(Activator.log.isDebugEnabled()){ + Activator.log.debug("will display "+container); + } + + list.add(container); + dropObjectsRequest.setObjects(list); + dropObjectsRequest.setLocation(new Point(-1,-1)); + Command command = targetEditPart.getCommand(dropObjectsRequest); + if( command!=null){ + command.execute(); + } + } + }; + cc.add(new CommandProxy(resultCommand)); + + + if(cc.canExecute()){ + ICommandProxy ic = new ICommandProxy(cc.reduce()); + String[] shortty = p.getName().split(" _ "); + String name = new String(); + String splitter = new String(""); + + if(shortty.length>1){ + + name = name.concat("create a "); + int n=0; + for(String s : shortty){ + String[] t = s.split("@"); + + if(n==shortty.length-1){ + splitter = " with your dropped element referenced as "; + name = name.concat(splitter+ t[0].replace("org.eclipse.uml2.uml.", "")+"("+t[3].replace("org.eclipse.uml2.uml.", "")+")"); + } + else{ + name = name.concat(splitter+ t[0].replace("org.eclipse.uml2.uml.", "")+"("+t[3].replace("org.eclipse.uml2.uml.", "")+")"); + splitter = " with "; + } + n++; + } + } + else{ + String[] t = shortty[0].split("@"); + name = name.concat("create a reference of your dropped element as ("+t[3].replace("org.eclipse.uml2.uml.", "")+")"); + } + + ic.setLabel("SmartDrop "+(shortty.length-1)+": "+name); + myCommands.add(ic); + } + + } + + return myCommands; + } + +} |