]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java
2bd089d1e8ed1589ecadb76f6f18662169b405ef
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / NodeValueRequest.java
1 package org.simantics.db.layer0.variable;
2
3 import org.simantics.databoard.binding.Binding;
4 import org.simantics.databoard.binding.error.BindingException;
5 import org.simantics.databoard.binding.mutable.Variant;
6 import org.simantics.databoard.util.ObjectUtils;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.common.request.ParametrizedPrimitiveRead;
9 import org.simantics.db.common.utils.Logger;
10 import org.simantics.db.exception.DatabaseException;
11 import org.simantics.db.procedure.Listener;
12 import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException;
13 import org.simantics.simulator.variable.exceptions.NodeManagerException;
14 import org.simantics.utils.datastructures.Pair;
15
16 @SuppressWarnings("rawtypes")
17 class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Binding>, Variant> implements VariableNodeReadRunnable {
18
19     private Listener<Variant> listener = null;
20     private Variant value = Variables.PENDING_NODE_VALUE;
21     private boolean wasRun = false;
22
23     static class Probe implements Runnable {
24
25         private Pair<VariableNode,Binding> parameter;
26                 public Variant result;
27         
28         public Probe(Pair<VariableNode,Binding> parameter) {
29                 this.parameter = parameter;
30         }
31         
32                 @SuppressWarnings("unchecked")
33                 @Override
34                 public void run() {
35                         try {
36                                 result = NodeValueRequest.get(parameter);
37                                 parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L);
38                         } catch (NodeManagerException e) {
39                                 e.printStackTrace();
40                         } catch (BindingException e) {
41                                 e.printStackTrace();
42                         }
43                 }
44         
45     }
46     
47     public NodeValueRequest(VariableNode node) {
48         super(Pair.<VariableNode, Binding>make(node, null));
49     }
50
51     public NodeValueRequest(VariableNode node, Binding binding) {
52         super(Pair.<VariableNode, Binding>make(node, binding));
53     }
54
55     @SuppressWarnings("unchecked")
56     @Override
57     public void register(ReadGraph graph, final Listener<Variant> procedure) {
58         
59         VariableNode node = parameter.first;
60
61         if(procedure.isDisposed()) {
62                 
63                 // We are not listening
64                 Variant result = (Variant)node.support.valueCache.get(node.node);
65
66                 if(result != null) {
67                         // Return cached value immediately
68                         procedure.execute(result);
69                 } else {
70
71 //              
72 //            listener = procedure;
73 //            
74 //            if(graph.getSynchronous()) {
75 //                try {
76 //                    parameter.support.manager.getRealm().syncExec(this);
77 //                } catch (InterruptedException e) {
78 //                    if (!wasRun) procedure.exception(e);
79 //                } catch (Throwable e) {
80 //                    if (!wasRun) procedure.exception(e);
81 //                }
82 //            } else {
83 //                parameter.support.manager.getRealm().asyncExec(this);
84 //            
85 //                if(value == Variables.PENDING_NODE_VALUE) {
86 //                    procedure.execute(Variables.PENDING_NODE_VALUE);
87 //                }
88 //            }
89 //            return;
90             
91                         NodeValueRequest.Probe probe = new Probe(parameter);
92                         node.support.manager.getRealm().asyncExec(probe);
93                         if(probe.result != null) {
94                                 procedure.execute(probe.result);
95                         } else {
96                                 procedure.execute(Variables.PENDING_NODE_VALUE);
97                         }
98
99                 }
100
101                 return;            
102         }
103         
104         // We need to listen
105         listener = procedure;
106                 // Register listening
107                 node.support.manager.addNodeListener(node.node, this);
108                 synchronized(this) {
109                         if(wasRun) {
110                                 procedure.execute(value);
111                         } else {
112                                 Variant result = (Variant)node.support.valueCache.get(node.node);
113                                 if(result != null) {
114                                         procedure.execute(result);
115                                 } else {
116                         procedure.execute(Variables.PENDING_NODE_VALUE);
117                                 }
118                         }
119                 }
120         
121 //        if(listener != null) {
122 //            throw new UnsupportedOperationException();
123 //        }
124 //        listener = procedure;
125 //        if(graph.getSynchronous()) {
126 //            try {
127 //                parameter.support.manager.getRealm().syncExec(new VariableNodeReadRunnable() {
128 //                    @Override
129 //                    public void run() {
130 //                        parameter.support.manager.addNodeListener(parameter.node, NodeValueRequest.this);
131 //                    }
132 //                    @Override
133 //                    public String toString() {
134 //                        return "NodeValueRequest.register.sync.addNodeListener @ " + System.identityHashCode(NodeValueRequest.this);
135 //                    }
136 //                });
137 //                
138 //                if (!wasRun) procedure.exception(new InternalException("No invocation of listener from node manager " + parameter.support.manager.getClass().getName()));
139 //            } catch (InterruptedException e) {
140 //                if (!wasRun) procedure.exception(e);
141 //            } catch (Throwable e) {
142 //                if (!wasRun) procedure.exception(e);
143 //            }
144 //        } else {
145 //            parameter.support.manager.addNodeListener(parameter.node, this);
146 //            if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE);
147 //        }
148                 
149     }
150     
151     static class NodeListener implements VariableNodeReadRunnable {
152         
153         private VariableNode node;
154         private NodeValueRequest request;
155         
156         public NodeListener(VariableNode node, NodeValueRequest request) {
157                 this.node = node;
158                 this.request = request;
159         }
160
161         @SuppressWarnings("unchecked")
162         @Override
163         public void run() {
164             node.support.manager.addNodeListener(node.node, request);
165         }
166         
167     }
168
169
170     @SuppressWarnings("unchecked")
171     @Override
172     public void unregistered() {
173         VariableNode node = parameter.first;
174         node.support.manager.removeNodeListener(node.node, this);
175         node.support.valueCache.removeListening(node.node);
176         listener = null;
177     }
178     
179     @SuppressWarnings("unchecked")
180     public static Variant get(Pair<VariableNode,Binding> parameter) throws NodeManagerException, BindingException {
181
182         VariableNode node = parameter.first;
183         Binding binding = parameter.second;
184         
185         if (binding != null) {
186                 Object raw = node.support.manager.getValue(node.node, binding);
187                 if(raw == null) return null;
188                 else return new Variant(binding, raw);
189         } else {
190                 return node.support.manager.getValue(node.node);
191         }
192         
193     }
194     
195     @SuppressWarnings("unchecked")
196     @Override
197     public synchronized void run() {
198         
199         VariableNode node = parameter.first;
200         
201         try {
202                 Variant newValue = get(parameter);
203             if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
204                 //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
205                 return;
206             }
207             value = newValue;
208             node.support.valueCache.put(node.node, value);
209         } catch (Throwable e) {
210             // Must catch everything to prevent DB client from getting stuck.
211             if(!(e instanceof NodeIsNotValidAnymoreException))
212                 Logger.defaultLogError(e);
213             // Invoke the exception method of the listener
214             Listener<Variant> listener = this.listener;
215             if (listener != null) listener.exception(new DatabaseException("External data access error", e));
216             wasRun = true;
217             return;
218         }
219         // Must always invoke an existing listener, regardless of earlier errors.
220         Listener<Variant> listener = this.listener;
221         if (listener != null) {
222             //System.out.println("LISTENER " + listener + " invoked with value " + value);
223             listener.execute(value);
224         }
225         wasRun = true;
226     }
227
228     @Override
229     public String toString() {
230         return "NodeValueRequest.run " + parameter.first.node + " " + parameter.first.support.manager + " " + System.identityHashCode(this);
231     }
232
233 }