]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
ca898582fe41f6c7880b84b92d28ebf076e0d004
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.sysdyn.ui.structure;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Collections;\r
17 import java.util.HashMap;\r
18 \r
19 import org.simantics.db.ReadGraph;\r
20 import org.simantics.db.Resource;\r
21 import org.simantics.db.common.request.ObjectsWithType;\r
22 import org.simantics.db.exception.DatabaseException;\r
23 import org.simantics.db.request.Read;\r
24 import org.simantics.graphviz.Edge;\r
25 import org.simantics.graphviz.Graph;\r
26 import org.simantics.graphviz.IGraph;\r
27 import org.simantics.graphviz.Node;\r
28 import org.simantics.layer0.Layer0;\r
29 import org.simantics.modeling.ModelingResources;\r
30 import org.simantics.sysdyn.SysdynResource;\r
31 \r
32 /**\r
33  * Builds a graph of the dependencies of a selected variable\r
34  * \r
35  * \r
36  * @author Teemu Lempinen\r
37  *\r
38  */\r
39 public class DependencyGraphRequest implements Read<Graph> {\r
40 \r
41         Resource root;\r
42         HashMap<Resource, Node> nodes;\r
43         boolean isInverted;\r
44         int levels;\r
45 \r
46         /**\r
47          * Builds a graph of the dependencies of a selected variable\r
48          * \r
49          * @param root Variable from which to find dependencies\r
50          * @param levels How many steps of dependencies are calculated from the variable\r
51          * @param isInverted true => variables that affect root; false => variables that are affected by root \r
52          */\r
53         public DependencyGraphRequest(Resource root, int levels, boolean isInverted) {\r
54                 this.root = root;\r
55                 this.isInverted = isInverted;    \r
56                 this.levels = levels;\r
57         }\r
58 \r
59         @Override\r
60         public Graph perform(ReadGraph g) throws DatabaseException {\r
61 \r
62                 nodes = new HashMap<Resource, Node>();\r
63                 Graph graph = new Graph();\r
64                 graph.setRankdir("LR");\r
65                 ModelingResources mr = ModelingResources.getInstance(g);\r
66                 Resource element = g.getPossibleObject(root, mr.ElementToComponent);\r
67                 if (element != null) {\r
68                         root = element;\r
69                 }\r
70                 SysdynResource sr = SysdynResource.getInstance(g);\r
71                 if (g.isInstanceOf(root, sr.IndependentVariable) || g.isInstanceOf(root, sr.Input)) {\r
72                         setRoot(g, graph, root);\r
73                         Collection<Resource> resources = new ArrayList<Resource>(); \r
74                         resources.add(root);\r
75                         for (int i = 0; i < levels && !resources.isEmpty(); i++) {\r
76                                 Collection<Resource> newResources = new ArrayList<Resource>();\r
77                                 for(Resource r : resources) {\r
78                                         newResources.addAll(setDependencies(g, graph, r));\r
79                                 }\r
80                                 resources = new ArrayList<Resource>(newResources);\r
81                         }\r
82                 }\r
83                 return graph;\r
84         }\r
85 \r
86         /**\r
87          * Create a root node and set appearance settings for it\r
88          * @param g ReadGraph\r
89          * @param graph Graphviz graph\r
90          * @param root Root resource\r
91          * @throws DatabaseException\r
92          */\r
93         private void setRoot(ReadGraph g, IGraph graph, Resource root) throws DatabaseException {\r
94                 Node n;\r
95                 n = new Node(graph, getName(g, root));\r
96                 setShape(g, root, n);\r
97                 n.set("style", "filled");\r
98                 n.setFillColor("#d3d3d3");\r
99                 nodes.put(root, n);\r
100         }\r
101 \r
102 \r
103         /**\r
104          * Call for calculating  \r
105          * @param g\r
106          * @param graph\r
107          * @param r\r
108          * @param toDependency\r
109          * @param fromDependency\r
110          * @param connectionType\r
111          * @return\r
112          * @throws DatabaseException\r
113          */\r
114         private Collection<Resource> getDependants(ReadGraph g, IGraph graph, Resource r, Resource toDependency, Resource fromDependency, Resource connectionType) throws DatabaseException {\r
115                 SysdynResource sr = SysdynResource.getInstance(g);\r
116 \r
117                 Collection<Resource> dependencies = g.syncRequest(new ObjectsWithType(r, toDependency, connectionType));\r
118 \r
119                 Collection<Resource> dependants = new ArrayList<Resource>();\r
120                 Node n;\r
121                 for(Resource d : dependencies) {\r
122                         Resource dependant = g.getPossibleObject(d, fromDependency);\r
123                         if(dependant == null)\r
124                                 continue;\r
125                         if(g.isInstanceOf(dependant, sr.Cloud)) {\r
126                                 break;\r
127                         }\r
128                         if( !nodes.containsKey(dependant)) {\r
129                                 n= new Node(graph, getName(g, dependant));\r
130                                 setShape(g, dependant, n);\r
131                                 nodes.put(dependant, n);\r
132                                 dependants.add(dependant);\r
133                         }\r
134 \r
135                         if(isInverted) {\r
136                                 new Edge(graph, nodes.get(r), nodes.get(dependant));\r
137                         } else {\r
138                                 new Edge(graph, nodes.get(dependant), nodes.get(r));\r
139                         }\r
140                 }\r
141                 return dependants;\r
142         }\r
143         \r
144         private Collection<Resource> setDependencies(ReadGraph g, IGraph graph, Resource r) throws DatabaseException{\r
145                 SysdynResource sr = SysdynResource.getInstance(g);\r
146 \r
147                 // stop here if element is a module\r
148                 if (g.isInstanceOf(r, sr.Module))\r
149                         return Collections.emptyList();\r
150 \r
151                 Collection<Resource> dependants;\r
152                 if(isInverted) {\r
153                     dependants = getDependants(g, graph, r, sr.Variable_isTailOf, sr.Variable_HasHead, sr.Dependency);\r
154                     if (g.isInstanceOf(r, sr.Valve)) {\r
155                         dependants.addAll(getDependants(g, graph, r, sr.Variable_isTailOf, sr.Variable_HasHead, sr.Flow));\r
156                         dependants.addAll(getDependants(g, graph, r, sr.Variable_isHeadOf, sr.Variable_HasTail, sr.Flow));\r
157                     }\r
158                 } else {\r
159                     dependants = getDependants(g, graph, r, sr.Variable_isHeadOf, sr.Variable_HasTail, sr.Dependency);\r
160                     if (g.isInstanceOf(r, sr.Stock)) {\r
161                         dependants.addAll(getDependants(g, graph, r, sr.Variable_isTailOf, sr.Variable_HasHead, sr.Flow));\r
162                         dependants.addAll(getDependants(g, graph, r, sr.Variable_isHeadOf, sr.Variable_HasTail, sr.Flow));\r
163                     }\r
164                 }\r
165 \r
166                 return dependants;\r
167         }\r
168         \r
169         /**\r
170          * Set shape for a node. Rectangle for stocks, ellipse for auxiliaries and rounded rectangle for modules. \r
171          * @param g ReadGraph\r
172          * @param r Resource\r
173          * @param n Node\r
174          * @throws DatabaseException\r
175          */\r
176         private void setShape(ReadGraph g, Resource r, Node n) throws DatabaseException {\r
177                 SysdynResource sr = SysdynResource.getInstance(g);\r
178                 if(g.isInstanceOf(r, sr.Stock))\r
179                         n.setShape("rectangle");\r
180                 else if(g.isInstanceOf(r, sr.Module)) {\r
181                         n.setShape("rectangle");\r
182                         n.setStyle("rounded"); \r
183                 }\r
184                 else\r
185                         n.setShape("ellipse");\r
186         }\r
187 \r
188         private String getName(ReadGraph g, Resource r) throws DatabaseException {\r
189                 return (String)g.getRelatedValue(r, Layer0.getInstance(g).HasName);\r
190         }\r
191 \r
192 }\r