1 /*******************************************************************************
\r
2 * Copyright (c) 2010, 2012 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.structure;
\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
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
33 * Builds a graph of the dependencies of a selected variable
\r
36 * @author Teemu Lempinen
\r
39 public class DependencyGraphRequest implements Read<Graph> {
\r
42 HashMap<Resource, Node> nodes;
\r
47 * Builds a graph of the dependencies of a selected variable
\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
53 public DependencyGraphRequest(Resource root, int levels, boolean isInverted) {
\r
55 this.isInverted = isInverted;
\r
56 this.levels = levels;
\r
60 public Graph perform(ReadGraph g) throws DatabaseException {
\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
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
80 resources = new ArrayList<Resource>(newResources);
\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
93 private void setRoot(ReadGraph g, IGraph graph, Resource root) throws DatabaseException {
\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
104 * Call for calculating
\r
108 * @param toDependency
\r
109 * @param fromDependency
\r
110 * @param connectionType
\r
112 * @throws DatabaseException
\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
117 Collection<Resource> dependencies = g.syncRequest(new ObjectsWithType(r, toDependency, connectionType));
\r
119 Collection<Resource> dependants = new ArrayList<Resource>();
\r
121 for(Resource d : dependencies) {
\r
122 Resource dependant = g.getPossibleObject(d, fromDependency);
\r
123 if(dependant == null)
\r
125 if(g.isInstanceOf(dependant, sr.Cloud)) {
\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
136 new Edge(graph, nodes.get(r), nodes.get(dependant));
\r
138 new Edge(graph, nodes.get(dependant), nodes.get(r));
\r
144 private Collection<Resource> setDependencies(ReadGraph g, IGraph graph, Resource r) throws DatabaseException{
\r
145 SysdynResource sr = SysdynResource.getInstance(g);
\r
147 // stop here if element is a module
\r
148 if (g.isInstanceOf(r, sr.Module))
\r
149 return Collections.emptyList();
\r
151 Collection<Resource> dependants;
\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
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
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
174 * @throws DatabaseException
\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
185 n.setShape("ellipse");
\r
188 private String getName(ReadGraph g, Resource r) throws DatabaseException {
\r
189 return (String)g.getRelatedValue(r, Layer0.getInstance(g).HasName);
\r