]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Loops under structure view in Sysdyn: consider flows bidirectional dependencies,...
authormiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 20 Jan 2014 08:33:48 +0000 (08:33 +0000)
committermiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 20 Jan 2014 08:33:48 +0000 (08:33 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28672 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/LoopGraphRequest.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Loops.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureView.java
org.simantics.sysdyn/src/org/simantics/sysdyn/utils/ConfigurationUtils.java

index 348d098e28b6f5ebe434dfc572d4a5da6eb198bd..02e052d80e1eb4e3172ec255c3492767d2eaa243 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 2012, 2014 Association for Decentralized Information Management in\r
  * Industry THTH ry.\r
  * All rights reserved. This program and the accompanying materials\r
  * are made available under the terms of the Eclipse Public License v1.0\r
  *******************************************************************************/\r
 package org.simantics.sysdyn.ui.structure;\r
 \r
-import java.util.Set;\r
-\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.jobs.Job;\r
 import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.IStructuredSelection;\r
 import org.eclipse.swt.SWT;\r
 import org.eclipse.swt.custom.CTabFolder;\r
-import org.eclipse.swt.custom.CTabItem;\r
 import org.eclipse.swt.events.ModifyEvent;\r
 import org.eclipse.swt.events.ModifyListener;\r
 import org.eclipse.swt.events.SelectionAdapter;\r
@@ -34,38 +24,24 @@ import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;\r
 import org.eclipse.swt.widgets.Spinner;\r
 import org.simantics.db.Resource;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.graphviz.Graph;\r
-import org.simantics.graphviz.ui.GraphvizComponent;\r
 import org.simantics.ui.SimanticsUI;\r
-import org.simantics.utils.ui.ISelectionUtils;\r
 \r
-public class Dependencies extends CTabItem {\r
+public class Dependencies extends StructureTabItem {\r
     \r
-    private GraphvizComponent component;\r
     private boolean isInverted = false;\r
     private Button bButton, fButton;\r
-    private Resource currentSelection;\r
     private int levels = 3;\r
-    private GraphListener graphListener;\r
 \r
-    static int MAXLEVELS = 4;\r
-    static int MINLEVELS = 1;\r
+    private static int MAXLEVELS = 4;\r
+    private static int MINLEVELS = 1;\r
 \r
-    public Dependencies(CTabFolder parent, ISelection selection, int style) {\r
+    public Dependencies(CTabFolder parent, int style) {\r
         super(parent, style);\r
         \r
-        Composite dependencies = new Composite(parent, SWT.NONE);\r
-        GridDataFactory.fillDefaults().grab(true, true).applyTo(dependencies);\r
-        GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(dependencies);\r
-\r
-        component = new GraphvizComponent(dependencies, SWT.NONE);\r
-        GridDataFactory.fillDefaults().grab(true, true).applyTo(component);\r
-        \r
-        Label line = new Label(dependencies, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL);\r
+        Label line = new Label(structureComposite, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL);\r
         GridDataFactory.fillDefaults().grab(true, false).applyTo(line);\r
         \r
-        Composite composite = new Composite(dependencies, SWT.NONE);\r
+        Composite composite = new Composite(structureComposite, SWT.NONE);\r
         RowLayout layout = new RowLayout();\r
         layout.center = true;\r
         composite.setLayout(layout);\r
@@ -118,31 +94,11 @@ public class Dependencies extends CTabItem {
             }\r
         });\r
         \r
-        drawSelection(selection);\r
-        \r
         this.setText("Dependencies");\r
-        this.setControl(dependencies);\r
+        this.setControl(structureComposite);\r
     }\r
 \r
-\r
-    public void drawSelection(ISelection selection) {\r
-        if(selection == null || selection.isEmpty())\r
-            return;\r
-        if(selection instanceof IStructuredSelection) {                    \r
-            Object[] els = ((IStructuredSelection) selection).toArray();\r
-            if(els.length == 1) {\r
-                Set<Resource> ress = ISelectionUtils.filterSetSelection(selection, Resource.class);\r
-                if(ress.isEmpty()) return;\r
-                Resource r = (ress.toArray(Resource.NONE))[0];\r
-                if(r != null && !r.equals(currentSelection)) {\r
-                    currentSelection = r;\r
-                    readGraph(currentSelection);\r
-                }\r
-            }\r
-        }           \r
-    }\r
-\r
-    private void readGraph(Resource resource) {\r
+    protected void readGraph(Resource resource) {\r
         if(graphListener != null)\r
             graphListener.dispose();\r
         \r
@@ -151,38 +107,7 @@ public class Dependencies extends CTabItem {
                 resource, levels, isInverted), graphListener);\r
     }\r
 \r
-    private class GraphListener implements Listener<Graph> {\r
-        \r
-        private boolean disposed = false;\r
-        \r
-        public void dispose() {\r
-            disposed = true;\r
-        }\r
-        \r
-        @Override\r
-        public void exception(Throwable e) {\r
-            e.printStackTrace();\r
-        }\r
-\r
-        @Override\r
-        public void execute(final Graph graph) {\r
-            Job job = new Job("Loading dependencies graph") {\r
-\r
-                @Override\r
-                protected IStatus run(IProgressMonitor monitor) {\r
-                    if(!isDisposed()) {\r
-                        component.setGraph(graph, "dot");\r
-                        component.fit();                            \r
-                    }\r
-                    return Status.OK_STATUS;\r
-                }\r
-            };\r
-            job.schedule();\r
-        }\r
-\r
-        @Override\r
-        public boolean isDisposed() {\r
-            return disposed;\r
-        }\r
+    protected String getJobLabel() {\r
+       return "Loading dependencies graph";\r
     }\r
 }\r
index 4d15341ee4b0e4016e753a57fe6ee2178ddbe822..f9b7c8740b4a254e5587d11ab9df1ab290a9105a 100644 (file)
@@ -44,8 +44,8 @@ public class LoopGraphRequest extends DependencyGraphRequest {
         * @param levels How many steps of dependencies are calculated from the variable\r
         * @param isInverted true => variables that affect root; false => variables that are affected by root \r
         */\r
-       public LoopGraphRequest(Resource root, int levels, boolean isInverted) {\r
-               super(root, levels, isInverted);\r
+       public LoopGraphRequest(Resource root) {\r
+               super(root, 999, false);\r
        }\r
 \r
        @Override\r
@@ -61,9 +61,11 @@ public class LoopGraphRequest extends DependencyGraphRequest {
                }\r
                SysdynResource sr = SysdynResource.getInstance(g);\r
                if (g.isInstanceOf(root, sr.IndependentVariable) || g.isInstanceOf(root, sr.Input)) {\r
+                       // Get ALL loops in the diagram in which the root exists.\r
                        List<List<Resource>> loops = ConfigurationUtils.getLoops(g, root);\r
                        setRoot(g, graph, root);\r
                        \r
+                       // Add the edges to the graph.\r
                        edges = new MapList<Resource, Edge>();\r
                        for (List<Resource> loop : loops) {\r
                                Resource prev = null;\r
@@ -98,8 +100,8 @@ public class LoopGraphRequest extends DependencyGraphRequest {
         * @throws DatabaseException \r
         */\r
        private void claimEdge(ReadGraph g, IGraph graph, Resource tail, Resource head) throws DatabaseException {\r
-               // If edge exists, return\r
-               for (Edge e : edges.getValues(tail))\r
+               // If edge exists, increase the size of the arrowhead and return.\r
+               for (Edge e : edges.getValues(tail)) {\r
                        if (((Node)e.getHead()).get("label").equals(getName(g, head))) {\r
                                // Change the size of the arrowhead (fancily :-)\r
                                String arrowsize = e.get("arrowsize");\r
@@ -108,6 +110,7 @@ public class LoopGraphRequest extends DependencyGraphRequest {
                                e.setArrowsize(Math.min(2.2, Math.sqrt(Double.valueOf(arrowsize) + 0.8)));\r
                                return;\r
                        }\r
+               }\r
 \r
                for (Edge e : edges.getValues(head)) { // Seek for opposite edges\r
                        if (((Node)e.getHead()).get("label").equals(getName(g, tail))) {\r
index 6afb8edbc83f5579f994e16aad1218ce5790f930..798b504323d675b774fe9a9740cc46ec71a78542 100644 (file)
  *******************************************************************************/\r
 package org.simantics.sysdyn.ui.structure;\r
 \r
-import java.util.Set;\r
-\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.jobs.Job;\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.IStructuredSelection;\r
-import org.eclipse.swt.SWT;\r
 import org.eclipse.swt.custom.CTabFolder;\r
-import org.eclipse.swt.custom.CTabItem;\r
-import org.eclipse.swt.events.ModifyEvent;\r
-import org.eclipse.swt.events.ModifyListener;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.layout.RowLayout;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Label;\r
-import org.eclipse.swt.widgets.Spinner;\r
 import org.simantics.db.Resource;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.graphviz.Graph;\r
-import org.simantics.graphviz.ui.GraphvizComponent;\r
 import org.simantics.ui.SimanticsUI;\r
-import org.simantics.utils.ui.ISelectionUtils;\r
-\r
-public class Loops extends CTabItem {\r
-    \r
-    private GraphvizComponent component;\r
-    private boolean isInverted = false;\r
-    private Button bButton, fButton;\r
-    private Resource currentSelection;\r
-    private int levels = 3;\r
-    private GraphListener graphListener;\r
 \r
-    static int MAXLEVELS = 4;\r
-    static int MINLEVELS = 1;\r
+/**\r
+ * Tab for loops.\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class Loops extends StructureTabItem {\r
 \r
     public Loops(CTabFolder parent, int style) {\r
         super(parent, style);\r
-        \r
-        Composite loops = new Composite(parent, SWT.NONE);\r
-        GridDataFactory.fillDefaults().grab(true, true).applyTo(loops);\r
-        GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(loops);\r
-\r
-        component = new GraphvizComponent(loops, SWT.NONE);\r
-        GridDataFactory.fillDefaults().grab(true, true).applyTo(component);\r
-        \r
-        Label line = new Label(loops, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL);\r
-        GridDataFactory.fillDefaults().grab(true, false).applyTo(line);\r
-        \r
-        Composite composite = new Composite(loops, SWT.NONE);\r
-        RowLayout layout = new RowLayout();\r
-        layout.center = true;\r
-        composite.setLayout(layout);\r
-\r
-        Label label = new Label(composite, SWT.NONE);\r
-        label.setText("Direction: ");\r
-\r
-        bButton = new Button(composite, SWT.RADIO);\r
-        bButton.setText("Backward");\r
-        bButton.setSelection(true);\r
-        bButton.addSelectionListener(new SelectionAdapter() {\r
-            public void widgetSelected(SelectionEvent event) {\r
-                if(bButton.getSelection())\r
-                    isInverted = false;\r
-                else \r
-                    isInverted = true;\r
-                if(currentSelection != null) {\r
-                    readGraph(currentSelection);\r
-                }\r
-            }\r
-        });\r
-\r
-        fButton = new Button(composite, SWT.RADIO);\r
-        fButton.setText("Forward");\r
-\r
-        label = new Label(composite, SWT.NONE);\r
-        label.setText("Steps: ");\r
-\r
-        Spinner spinner = new Spinner(composite, SWT.BORDER);\r
-        spinner.setMaximum(MAXLEVELS);\r
-        spinner.setMinimum(MINLEVELS);\r
-        spinner.setTextLimit(1);\r
-        spinner.setSelection(levels);\r
-\r
-        spinner.addModifyListener(new ModifyListener() {\r
-\r
-            @Override\r
-            public void modifyText(ModifyEvent e) {\r
-                Spinner s = (Spinner)e.widget;\r
-                int lvls = Integer.parseInt(s.getText());\r
-                if(lvls > MAXLEVELS)\r
-                    levels = MAXLEVELS;\r
-                else if (lvls < MINLEVELS)\r
-                    levels = MINLEVELS;\r
-                levels = lvls;\r
-                if(currentSelection != null) {\r
-                    readGraph(currentSelection);\r
-                }\r
-\r
-            }\r
-        });\r
-        \r
         this.setText("Loops");\r
-        this.setControl(loops);\r
+        this.setControl(structureComposite);\r
     }\r
 \r
-\r
-    public void drawSelection(ISelection selection) {\r
-        if(selection == null || selection.isEmpty())\r
-            return;\r
-        if(selection instanceof IStructuredSelection) {                    \r
-            Object[] els = ((IStructuredSelection) selection).toArray();\r
-            if(els.length == 1) {\r
-                Set<Resource> ress = ISelectionUtils.filterSetSelection(selection, Resource.class);\r
-                if(ress.isEmpty()) return;\r
-                Resource r = (ress.toArray(Resource.NONE))[0];\r
-                if(r != null && !r.equals(currentSelection)) {\r
-                    currentSelection = r;\r
-                    readGraph(currentSelection);\r
-                }\r
-            }\r
-        }           \r
-    }\r
-\r
-    private void readGraph(Resource resource) {\r
+    protected void readGraph(Resource resource) {\r
         if(graphListener != null)\r
             graphListener.dispose();\r
         \r
         graphListener = new GraphListener();\r
         SimanticsUI.getSession().asyncRequest(new LoopGraphRequest(\r
-                resource, levels, isInverted), graphListener);\r
+                resource), graphListener);\r
     }\r
 \r
-    private class GraphListener implements Listener<Graph> {\r
-        \r
-        private boolean disposed = false;\r
-        \r
-        public void dispose() {\r
-            disposed = true;\r
-        }\r
-        \r
-        @Override\r
-        public void exception(Throwable e) {\r
-            e.printStackTrace();\r
-        }\r
-\r
-        @Override\r
-        public void execute(final Graph graph) {\r
-            Job job = new Job("Loading loops graph") {\r
-\r
-                @Override\r
-                protected IStatus run(IProgressMonitor monitor) {\r
-                    if(!isDisposed()) {\r
-                        component.setGraph(graph, "dot");\r
-                        component.fit();                            \r
-                    }\r
-                    return Status.OK_STATUS;\r
-                }\r
-            };\r
-            job.schedule();\r
-        }\r
-\r
-        @Override\r
-        public boolean isDisposed() {\r
-            return disposed;\r
-        }\r
+    protected String getJobLabel() {\r
+       return "Loading loops graph";\r
     }\r
+    \r
 }\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java
new file mode 100644 (file)
index 0000000..ceadd9d
--- /dev/null
@@ -0,0 +1,115 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010, 2012, 2014 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.structure;\r
+\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.core.runtime.jobs.Job;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CTabFolder;\r
+import org.eclipse.swt.custom.CTabItem;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.graphviz.Graph;\r
+import org.simantics.graphviz.ui.GraphvizComponent;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+/**\r
+ * Super class for certain kinds of structure tabs.\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public abstract class StructureTabItem extends CTabItem {\r
+    \r
+    protected GraphvizComponent component;\r
+    protected GraphListener graphListener;\r
+    protected Composite structureComposite;\r
+    protected Resource currentSelection;\r
+    \r
+    public StructureTabItem(CTabFolder parent, int style) {\r
+        super(parent, style);\r
+        \r
+        structureComposite = new Composite(parent, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(structureComposite);\r
+        GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(structureComposite);\r
+\r
+        component = new GraphvizComponent(structureComposite, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(component);\r
+    }\r
+\r
+\r
+    public void drawSelection(ISelection selection) {\r
+        if(selection == null || selection.isEmpty())\r
+            return;\r
+        if(selection instanceof IStructuredSelection) {                    \r
+            Object[] els = ((IStructuredSelection) selection).toArray();\r
+            if(els.length == 1) {\r
+                Set<Resource> ress = ISelectionUtils.filterSetSelection(selection, Resource.class);\r
+                if(ress.isEmpty()) return;\r
+                Resource r = (ress.toArray(Resource.NONE))[0];\r
+                if(r != null && !r.equals(currentSelection)) {\r
+                    currentSelection = r;\r
+                    readGraph(currentSelection);\r
+                }\r
+            }\r
+        }           \r
+    }\r
+\r
+    abstract protected void readGraph(Resource resource);\r
+\r
+    class GraphListener implements Listener<Graph> {\r
+        \r
+        private boolean disposed = false;\r
+        \r
+        public void dispose() {\r
+            disposed = true;\r
+        }\r
+        \r
+        @Override\r
+        public void exception(Throwable e) {\r
+            e.printStackTrace();\r
+        }\r
+\r
+        @Override\r
+        public void execute(final Graph graph) {\r
+            Job job = new Job(getJobLabel()) {\r
+\r
+                @Override\r
+                protected IStatus run(IProgressMonitor monitor) {\r
+                    if(!isDisposed()) {\r
+                        component.setGraph(graph, "dot");\r
+                        component.fit();                            \r
+                    }\r
+                    return Status.OK_STATUS;\r
+                }\r
+            };\r
+            job.schedule();\r
+        }\r
+\r
+        @Override\r
+        public boolean isDisposed() {\r
+            return disposed;\r
+        }\r
+    }\r
+    \r
+    protected String getJobLabel() {\r
+       return "Loading dependencies graph";\r
+    }\r
+}\r
index 7d7f53dd296f870147a01e5ad96082b1d48374b4..39dc59ddc8d1dd6fb41b87c096f45fcc28782672 100644 (file)
@@ -34,7 +34,7 @@ public class StructureView extends ViewPart {
 \r
     private CTabFolder tabFolder;\r
     private ISelectionListener selectionListener;\r
-    private Dependencies dependencies;\r
+    private StructureTabItem dependencies;\r
     private ModuleStructure moduleStructure;\r
     private Loops loops;\r
     \r
@@ -47,8 +47,8 @@ public class StructureView extends ViewPart {
         final ISelection currentSeletion = getSite().getWorkbenchWindow().getSelectionService().getSelection();\r
         \r
         // Dependencies\r
-        dependencies = new Dependencies(tabFolder, currentSeletion, SWT.NONE);\r
-\r
+        dependencies = new Dependencies(tabFolder, SWT.NONE);\r
+        dependencies.drawSelection(currentSeletion);\r
         \r
         // Hierarchical model structure\r
         moduleStructure = new ModuleStructure(tabFolder, SWT.NONE);\r
index ef821e853edcf49b965780c30c2a6ffae695dece..e10cbe9da9185540c63ed3a1e98afd35967644d7 100644 (file)
@@ -1,3 +1,14 @@
+/*******************************************************************************\r
+ * Copyright (c) 2014 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
 package org.simantics.sysdyn.utils;\r
 \r
 import java.util.ArrayList;\r
@@ -96,13 +107,27 @@ public class ConfigurationUtils {
                HashMap<Resource, ElementaryLoopItem> elementaryLoopItems = new HashMap<Resource, ElementaryLoopItem>();\r
                for (Resource variable : variables) {\r
                        ArrayList<Resource> dependingVariables = new ArrayList<Resource>();\r
+                       // Add forward dependencies and flows.\r
                        Collection<Resource> dependencies = g.getObjects(variable, sr.Variable_isTailOf);\r
                        for (Resource dependency : dependencies) {\r
                                Resource head = g.getPossibleObject(dependency, sr.Variable_HasHead);\r
-                               if (!g.isInstanceOf(head, sr.Module)) {\r
+                               if (head != null \r
+                                               && !g.isInstanceOf(head, sr.Module)\r
+                                               && !g.isInstanceOf(head, sr.Cloud)) {\r
                                        dependingVariables.add(head);\r
                                }\r
                        }\r
+                       // Add backward flows.\r
+                       Collection<Resource> backwardFlows = g.getObjects(variable, sr.Variable_isHeadOf);\r
+                       for (Resource flow : backwardFlows) {\r
+                               if (g.isInstanceOf(flow, sr.Flow)) {\r
+                                       Resource tail = g.getPossibleObject(flow, sr.Variable_HasTail);\r
+                                       if (tail != null && !g.isInstanceOf(tail, sr.Cloud)) {\r
+                                               dependingVariables.add(tail);\r
+                                       }\r
+                               }\r
+                       }\r
+                       // Put the variable in the hash map.\r
                        elementaryLoopItems.put(variable, new ElementaryLoopItem(k, dependingVariables));\r
                        nodes[k++] = variable;\r
                }\r