1 package org.simantics.structural.synchronization.base;
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.procedure.TObjectObjectProcedure;
6 import java.util.ArrayList;
7 import java.util.Collections;
9 import org.simantics.databoard.util.URIStringUtils;
10 import org.simantics.structural.synchronization.protocol.SynchronizationEventHandler;
12 abstract public class ReferenceResolverBase<T extends ComponentBase<T>> {
14 protected SynchronizationEventHandler eventHandler;
15 protected Solver solver;
16 protected THashMap<T, ArrayList<PendingResolve<T>>> pendingResolves = new THashMap<T, ArrayList<PendingResolve<T>>>();
18 protected static class PendingResolve<T> {
19 public final T component;
20 public final String connectionPoint;
21 public final ModuleCallback moduleCallback;
23 public PendingResolve(T component, String connectionPoint,
24 ModuleCallback moduleCallback) {
25 this.component = component;
26 this.connectionPoint = connectionPoint;
27 this.moduleCallback = moduleCallback;
31 public String toString() {
32 return connectionPoint + "->" + moduleCallback;
36 public ReferenceResolverBase(Solver solver) {
40 public void setEventHandler(SynchronizationEventHandler eventHandler) {
41 this.eventHandler = eventHandler;
45 * Marks that the component might be updated in this synchronization and
46 * therefore it may not be yet used for resolving references.
48 public void markPending(T component) {
49 //System.out.println("markPending: " + fullPathOfComponent(component));
50 pendingResolves.put(component, new ArrayList<PendingResolve<T>>(2));
54 * Marks that the component is not modified anymore in this synchornization.
55 * This information is local, some children of the component may be marked
58 public void unmarkPending(T component) {
59 //System.out.println("unmarkPending: " + fullPathOfComponent(component));
60 ArrayList<PendingResolve<T>> resolves = pendingResolves.remove(component);
62 for(PendingResolve<T> resolve : resolves) {
63 resolveReference(resolve.component,
64 resolve.connectionPoint,
65 resolve.moduleCallback);
70 * Tries to resolve the given relative reference and then calls the ModuleCallback.
72 public void resolveReference(T component, String connectionPoint, ModuleCallback moduleCallback) {
75 char c = connectionPoint.charAt(pos++);
78 component = component.getParent();
83 c = connectionPoint.charAt(endPos);
84 if(c == '/' || c == '#')
88 String segment = URIStringUtils.unescape(connectionPoint.substring(pos, endPos));
90 component = component.getChild(segment);
91 if(component == null) {
92 String message = "Couldn't resolve " + connectionPoint +
93 ", because child " + segment + " does not exist.";
94 if(eventHandler == null)
95 System.err.println(message);
97 eventHandler.reportProblem(message);
100 ArrayList<PendingResolve<T>> pendingList = pendingResolves.get(component);
101 if(pendingList != null) {
102 pendingList.add(new PendingResolve<T>(component, connectionPoint.substring(pos), moduleCallback));
107 String segment = connectionPoint.substring(pos);
108 moduleCallback.execute(resolveConnectionPoint(component.componentId, segment));
114 abstract public int resolveConnectionPoint(int moduleId, String connectionPoint);
116 private static void fullPathOfComponent(StringBuilder b, ComponentBase<?> component) {
117 if(component != null) {
118 fullPathOfComponent(b, component.parent);
119 b.append("/").append(component.solverComponentName);
123 private static String fullPathOfComponent(ComponentBase<?> component) {
124 StringBuilder b = new StringBuilder();
125 fullPathOfComponent(b, component);
129 public void printPending() {
130 if(!pendingResolves.isEmpty()) {
131 final ArrayList<String> pending = new ArrayList<String>();
132 pendingResolves.forEachEntry(new TObjectObjectProcedure<T, ArrayList<PendingResolve<T>>>() {
134 public boolean execute(T a, ArrayList<PendingResolve<T>> b) {
136 // System.out.println(" " + a.solverComponentName + " (" + a.uid + ", " + a.parent.solverComponentName + ") " + b.size());
137 pending.add(fullPathOfComponent(a) + " " + b);
141 Collections.sort(pending);
142 System.out.println("Still pending:");
143 for(String p : pending)
144 System.out.println(" " + p);
148 public void resolvePendingSelfReferences() {
149 // Can be customized in subclasses