]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural.synchronization/src/org/simantics/structural/synchronization/base/ModuleUpdateContext.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.structural.synchronization / src / org / simantics / structural / synchronization / base / ModuleUpdateContext.java
1 package org.simantics.structural.synchronization.base;
2
3 import java.util.ArrayList;
4
5 import org.simantics.databoard.binding.mutable.Variant;
6 import org.simantics.structural.synchronization.utils.ComponentBase;
7 import org.simantics.structural.synchronization.utils.Solver;
8
9 import gnu.trove.map.hash.THashMap;
10
11 public class ModuleUpdateContext<T extends ComponentBase<T>> {
12
13     private ModuleUpdaterBase<T> updater;
14     private final SynchronizationEventHandlerBase<T> handler;
15     public final T component;
16     public CommandBuilder command;
17     private ArrayList<Runnable> postUpdateActions; 
18     private THashMap<String, Variant> storedProperties;
19     
20     private int pendingRuleCount;
21     public boolean stateLoadedFromUndo;
22
23     public ModuleUpdateContext(SynchronizationEventHandlerBase<T> handler, ModuleUpdaterBase<T> updater, T component) {
24         assert(updater != null);
25         this.handler = handler;
26         this.updater = updater;
27         this.component = component;
28     }
29
30     public void incPendingCount() {
31         ++pendingRuleCount;
32     }
33     
34     public void decPendingCount() {
35         --pendingRuleCount;
36         if(pendingRuleCount == 0) {
37                 try {
38                         command.apply(getSolver());
39                         command = null;
40                 } catch (Exception e) {
41                         handler.reportProblem("Exception while issuing command.", e);
42                 }
43             if(getModuleId() <= 0) {
44                 setModuleId(getSolver().getId(getModuleName()));
45                 component.setModuleId(getModuleId());
46             }
47             if(postUpdateActions != null) {
48                 for(Runnable action : postUpdateActions)
49                     try {
50                         action.run();
51                     } catch(Exception e) {
52                         handler.reportProblem("Post update action failed.", e);
53                     }
54                 postUpdateActions = null;
55             }
56             handler.resolver.unmarkPending(component);
57         }
58     }
59     
60     public void addPostUpdateAction(Runnable action) {
61         if(postUpdateActions == null)
62             postUpdateActions = new ArrayList<Runnable>(2);
63         postUpdateActions.add(action);
64     }
65
66     public int getModuleId() {
67         return component.getModuleId();
68     }
69
70     public ModuleUpdaterBase<T> getUpdater() {
71         return updater;
72     }
73
74     public SynchronizationEventHandlerBase<T> getHandler() {
75         return handler;
76     }
77
78     @SuppressWarnings("unchecked")
79     public <E extends SynchronizationEventHandlerBase<?>> E getConcreteHandler() {
80         return (E) handler;
81     }
82
83     public void setModuleId(int moduleId) {
84         component.setModuleId(moduleId);
85     }
86
87     public Solver getSolver() {
88         return handler.solver;
89     }
90     
91     public <S> S getConcreteSolver() {
92         return handler.solver.getConcreteSolver();
93     }
94
95     public String getModuleType() {
96         return updater != null ? updater.moduleType : null;
97     }
98
99     public String getModuleName() {
100         return component.solverComponentName;
101     }
102
103     public void setModuleName(String moduleName) {
104         component.solverComponentName = moduleName;
105     }
106
107     public void reportProblem(String description) {
108         handler.reportProblem(description);
109        
110     }
111     
112     public void reportProblem(String description, Exception e) {
113         handler.reportProblem(description, e);
114     }
115
116     public void resolveReference(String connectionPoint, ModuleCallback moduleCallback) {
117         handler.resolver.resolveReference(component, connectionPoint, moduleCallback);
118     }
119     
120     public void storeProperty(String name, Variant value) {
121         if(storedProperties == null)
122             storedProperties = new THashMap<String, Variant>();
123         storedProperties.put(name, value);
124     }
125     
126     public Variant getStoredProperty(String name) {
127         if(storedProperties == null)
128             return null;
129         return storedProperties.get(name);
130     }
131
132     public void addPostSynchronizationAction(Runnable action) {
133         handler.addPostSynchronizationAction(action); 
134     }
135     
136     @SuppressWarnings("unchecked")
137         public <C> C getConcreteCommand() {
138         return (C)command.getConcrete();
139     }
140
141     public void setDidChanges() {
142         handler.setDidChanges();
143     }
144     
145     ArrayList<ResynchronizeAction> resynchronizeActions;
146
147     private class ResynchronizeAction {
148         final String connectionPoint;
149         final ModuleCallback callback;
150         
151         public ResynchronizeAction(String connectionPoint,
152                 ModuleCallback callback) {
153             this.connectionPoint = connectionPoint;
154             this.callback = callback;
155         }
156     }
157     
158     public void resynchronize(String connectionPoint, ModuleCallback callback) {
159         if(resynchronizeActions == null) {
160             resynchronizeActions = new ArrayList<ResynchronizeAction>();
161             handler.addPostSynchronizationAction(new Runnable() {
162                 @Override
163                 public void run() {
164                     ArrayList<ResynchronizeAction> resynchronizeActions = ModuleUpdateContext.this.resynchronizeActions;
165                     ModuleUpdateContext.this.resynchronizeActions = null;
166                     
167                     command = updater.createUpdateCommandBuilder(getModuleName());
168                     for(ResynchronizeAction action : resynchronizeActions)
169                         resolveReference(action.connectionPoint, action.callback);
170                     try {
171                         command.apply(getSolver());
172                     } catch (Exception e) {
173                         handler.reportProblem("Exception while issuing command.", e);
174                     }
175                 }
176             });
177         }
178         resynchronizeActions.add(new ResynchronizeAction(connectionPoint, callback));
179     }
180
181 }