1 package org.simantics.modeling.scl;
3 import gnu.trove.list.array.TIntArrayList;
4 import gnu.trove.set.hash.THashSet;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collection;
11 import org.simantics.db.ReadGraph;
12 import org.simantics.db.Resource;
13 import org.simantics.db.exception.DatabaseException;
14 import org.simantics.diagram.stubs.DiagramResource;
16 public class RouteGraphMatching {
18 public static boolean TRACE = false;
20 private static class Link {
24 public Link(int a, int b) {
30 private static class MatchingProcess {
35 ArrayList<Resource>[] alternatives;
36 TIntArrayList stack = new TIntArrayList();
37 THashSet<Resource> knownResources = new THashSet<Resource>();
39 @SuppressWarnings("unchecked")
40 public MatchingProcess(ReadGraph graph, int size) {
42 this.DIA = DiagramResource.getInstance(graph);
43 this.result = new Resource[size];
44 this.ls = new ArrayList[size];
45 this.alternatives = new ArrayList[size];
46 for(int i=0;i<size;++i)
47 this.ls[i] = new ArrayList<Link>(2);
50 public void addLink(int a, int b) {
51 Link link = new Link(a, b);
56 public boolean match(List<Resource> known) throws DatabaseException {
57 for(int i=0;i<known.size();++i) {
58 result[i] = known.get(i);
61 while(!stack.isEmpty()) {
62 while(!stack.isEmpty()) {
63 int pos = stack.removeAt(stack.size()-1);
67 if(!removeKnownResourcesFromAlternatives())
70 for(int i=0;i<result.length;++i)
71 if(result[i] == null) {
72 System.err.println("Didn't resolve resource " + i + ".");
79 private boolean removeKnownResourcesFromAlternatives() throws DatabaseException {
80 for(int i=0;i<result.length;++i) {
81 ArrayList<Resource> alt = alternatives[i];
83 alt.removeAll(knownResources);
87 result[i] = alt.get(0);
88 alternatives[i] = null;
96 private void printState() {
97 for(int i=0;i<result.length;++i) {
98 System.out.print(" {" + i + "} ");
100 System.out.print(" = " + result[i].getResourceId());
101 else if(alternatives[i] != null) {
102 System.out.print(" in");
103 for(Resource r : alternatives[i])
104 System.out.print(" " + r.getResourceId());
107 System.out.print(" unknown");
108 if(!ls[i].isEmpty()) {
109 System.out.print(", links to");
111 System.out.print(" " + (l.a==i ? l.b : l.a));
113 System.out.println();
117 private boolean propagate(int pos) throws DatabaseException {
119 System.out.println("propagate(" + pos + ")");
120 Resource r = result[pos];
121 knownResources.add(r);
122 ArrayList<Resource> neighbors =
123 new ArrayList<Resource>(graph.getObjects(r, DIA.AreConnected));
124 neighbors.removeAll(knownResources);
126 for(Link link : ls[pos]) {
127 int other = link.a == pos ? link.b : link.a;
128 ls[other].remove(link);
129 if(!setAlternatives(other, neighbors))
137 private boolean setKnown(int i, Resource value) throws DatabaseException {
139 System.out.println("setKnown(" + i + ", " + value + ")");
140 if(result[i] != null)
141 return result[i].equals(value);
142 if(alternatives[i] != null) {
143 if(!alternatives[i].contains(value))
145 alternatives[i] = null;
152 private boolean setAlternatives(int i, Collection<Resource> values) throws DatabaseException {
154 System.out.println("setAlternatives(" + i + ", " + values + ")");
155 if(result[i] != null)
156 return values.contains(result[i]);
159 if(values.size() == 1)
160 return setKnown(i, values.iterator().next());
161 ArrayList<Resource> oldAlternatives = alternatives[i];
162 if(oldAlternatives == null) {
163 alternatives[i] = new ArrayList<Resource>(values);
166 oldAlternatives.retainAll(values);
167 if(oldAlternatives.isEmpty())
169 if(oldAlternatives.size() == 1)
170 return setKnown(i, oldAlternatives.get(0));
175 public static List<Resource> matchRouteGraph(ReadGraph graph,
176 List<Resource> connectors, int routeLineCount, List<Integer> links) throws DatabaseException {
177 MatchingProcess process = new MatchingProcess(graph, connectors.size() + routeLineCount);
178 for(int i=0;i<links.size();i+=2)
179 process.addLink(links.get(i), links.get(i+1));
180 if(!process.match(connectors))
182 return Arrays.asList(process.result);