]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph.profile / src / org / simantics / scenegraph / profile / common / ProfileObserver.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.profile.common;\r
13 \r
14 import java.util.Collection;\r
15 import java.util.HashMap;\r
16 import java.util.Map;\r
17 import java.util.concurrent.TimeUnit;\r
18 \r
19 import org.simantics.Simantics;\r
20 import org.simantics.db.AsyncRequestProcessor;\r
21 import org.simantics.db.Resource;\r
22 import org.simantics.db.Session;\r
23 import org.simantics.db.common.session.SessionEventListenerAdapter;\r
24 import org.simantics.db.common.utils.Logger;\r
25 import org.simantics.db.procedure.Procedure;\r
26 import org.simantics.db.service.SessionEventSupport;\r
27 import org.simantics.scenegraph.INode;\r
28 import org.simantics.scenegraph.g2d.G2DSceneGraph;\r
29 import org.simantics.scenegraph.profile.EvaluationContext;\r
30 import org.simantics.scenegraph.profile.ProfileEntry;\r
31 import org.simantics.scenegraph.profile.impl.DebugPolicy;\r
32 import org.simantics.scenegraph.profile.impl.ProfileActivationListener;\r
33 import org.simantics.scenegraph.profile.request.RuntimeProfileActiveEntries;\r
34 import org.simantics.utils.datastructures.disposable.IDisposable;\r
35 import org.simantics.utils.threads.IThreadWorkQueue;\r
36 import org.simantics.utils.threads.ThreadUtils;\r
37 \r
38 public class ProfileObserver implements EvaluationContext {\r
39 \r
40     private final Session                     session;\r
41 \r
42     /**\r
43      * Runtime diagram resource.\r
44      */\r
45     private final Resource                    resource;\r
46 \r
47     private final IDisposable                 canvas;\r
48     private final IThreadWorkQueue            thread;\r
49     @SuppressWarnings("unused")\r
50     private final Object                      diagram;\r
51     private final Runnable                    notification;\r
52     private final G2DSceneGraph               sceneGraph;\r
53 \r
54     private boolean                           dirty               = true;\r
55     private boolean                           disposed            = false;\r
56 \r
57     private ProfileActivationListener         activationListener;\r
58 \r
59     private Map<String, Object>               constants           = new HashMap<String, Object>();\r
60 \r
61     private Map<INode, Map<String, Object>>   temporaryProperties = new HashMap<INode, Map<String, Object>>();\r
62     private Map<INode, Map<String, Object>>   properties          = new HashMap<INode, Map<String, Object>>();\r
63 \r
64     private final SessionEventListenerAdapter transactionListener = new SessionEventListenerAdapter() {\r
65         @Override\r
66         public void writeTransactionFinished() {\r
67             if (isDisposed())\r
68                 dispose();\r
69             if (dirty)\r
70                 perform();\r
71         }\r
72         @Override\r
73         public void readTransactionFinished() {\r
74             if (isDisposed())\r
75                 dispose();\r
76             if (dirty)\r
77                 perform();\r
78         }\r
79     };\r
80 \r
81     public ProfileObserver(Session session, Resource resource, IThreadWorkQueue thread, IDisposable canvas, G2DSceneGraph sceneGraph, Object diagram, Map<String, Object> constants, Runnable notification) {\r
82         //System.out.println(this + " NEW PROFILE OBSERVER: ");\r
83         this.session = session;\r
84         this.resource = resource;\r
85         this.thread = thread;\r
86         this.canvas = canvas;\r
87         this.diagram = diagram;\r
88         this.sceneGraph = sceneGraph;\r
89         this.constants.putAll(constants);\r
90         this.notification = notification;\r
91 \r
92         attachSessionListener();\r
93 \r
94         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
95             System.out.println("ProfileObserver(" + this + ")");\r
96         \r
97         // Tell SceneGraph that this observer is not yet done applying its operations\r
98         if(sceneGraph != null)\r
99             sceneGraph.setPending(ProfileObserver.this);\r
100         \r
101     }\r
102 \r
103     private void attachSessionListener() {\r
104         SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);\r
105         eventSupport.addListener(transactionListener);\r
106     }\r
107 \r
108     private void detachSessionListener() {\r
109         SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);\r
110         eventSupport.removeListener(transactionListener);\r
111     }\r
112 \r
113     public void dispose() {\r
114         synchronized (this) {\r
115             if (disposed)\r
116                 return;\r
117             disposed = true;\r
118         }\r
119 \r
120         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
121             System.out.println("ProfileObserver.dispose(" + this + ")");\r
122 \r
123         if(activationListener != null) { \r
124             activationListener.cleanup();\r
125             activationListener = null;\r
126         }\r
127 \r
128         detachSessionListener();\r
129     }\r
130 \r
131     @Override\r
132     public void update() {\r
133         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)\r
134             System.out.println("Profile observer marked dirty.");\r
135         dirty = true;\r
136     }\r
137 \r
138     private void perform() {\r
139         dirty = false;\r
140         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)\r
141             System.out.println("Profile observer detected a change.");\r
142         \r
143         session.asyncRequest(new RuntimeProfileActiveEntries(resource), new Procedure<Collection<ProfileEntry>>() {\r
144             @Override\r
145             public void execute(final Collection<ProfileEntry> entries) {\r
146 \r
147                 if (isDisposed())\r
148                     return;\r
149 \r
150                 ThreadUtils.asyncExec(thread, new Runnable() {\r
151                     \r
152 //                    private void init(INode node) {\r
153 //                        //ProfileVariables.init(node, ProfileObserver.this);\r
154 ////                        NodeUtil.forChildren(node, new NodeProcedure<Object>() {\r
155 ////                            @Override\r
156 ////                            public Object execute(INode node, String id) {\r
157 ////                                init(node);\r
158 ////                                return null;\r
159 ////                            }\r
160 ////                        }, null);\r
161 //                    }\r
162 \r
163                     @Override\r
164                     public void run() {\r
165 \r
166                         if (isDisposed())\r
167                             return;\r
168 \r
169                         temporaryProperties.clear();\r
170 \r
171 //                        init(sceneGraph);\r
172 \r
173 //                        for(IElement e : diagram.getElements()) {\r
174 //                            Node node = NodeUtils.\r
175 //                            Variables.init(e, ProfileObserver.this);\r
176 //                        }\r
177 \r
178                         for(ProfileEntry e : entries) {\r
179                             if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
180                                 System.out.println("Apply profile entry: " + e);\r
181                             e.apply(ProfileObserver.this);\r
182                         }\r
183 \r
184                         if(dirty) {\r
185                                 sceneGraph.setPending(ProfileObserver.this);\r
186 //                              System.err.println("setPending, dirty=true");\r
187                         }\r
188                         else {\r
189                                 sceneGraph.clearPending(ProfileObserver.this);\r
190 //                              System.err.println("clearPending, dirty=false");\r
191                         }\r
192                         \r
193                         notification.run();\r
194 //                        canvas.getContentContext().setDirty();\r
195                         \r
196                         // Something is underway, schedule update\r
197                         if(dirty) {\r
198                                 Simantics.async(new Runnable() {\r
199 \r
200                                                                 @Override\r
201                                                                 public void run() {\r
202 \r
203                                                             if (isDisposed()) return;\r
204                                                             \r
205                                                                         if(dirty) perform();\r
206                                                                         \r
207                                                                 }\r
208                                         \r
209                                 }, 100, TimeUnit.MILLISECONDS);\r
210                         }\r
211 \r
212                     }\r
213                 });\r
214             }\r
215 \r
216             @Override\r
217             public void exception(Throwable t) {\r
218                 Logger.defaultLogError(t);\r
219             }\r
220         });\r
221     }\r
222 \r
223     @Override\r
224     public boolean isDisposed() {\r
225         return disposed || canvas.isDisposed();\r
226     }\r
227 \r
228     @Override\r
229     public void exception(Throwable throwable) {\r
230         Logger.defaultLogError(throwable);\r
231     }\r
232 \r
233     @SuppressWarnings("unchecked")\r
234     @Override\r
235     public <T> T getTemporaryProperty(INode element, String key) {\r
236         Map<String, Object> map = temporaryProperties.get(element);\r
237         T t = map == null ? null : (T) map.get(key);\r
238         //System.out.println(this + ".getTemporaryProperty(" + element + ", " + key + "): " + t);\r
239         return t;\r
240     }\r
241 \r
242     @Override\r
243     public <T> void setTemporaryProperty(INode element, String key, T value) {\r
244         //System.out.println(this + ".setTemporaryProperty(" + element + ", " + key + ", " + value + ")");\r
245         Map<String, Object> map = temporaryProperties.get(element);\r
246         if (map == null) {\r
247             if (value == null)\r
248                 return;\r
249             map = new HashMap<String, Object>(8);\r
250             temporaryProperties.put(element, map);\r
251         }\r
252         if (value == null) {\r
253             map.remove(key);\r
254             if (map.isEmpty())\r
255                 properties.remove(element);\r
256         } else\r
257             map.put(key, value);\r
258     }\r
259 \r
260     @SuppressWarnings("unchecked")\r
261     @Override\r
262     public <T> T getProperty(INode element, String key) {\r
263         Map<String, Object> map = properties.get(element);\r
264         T t = map == null ? null : (T) map.get(key);\r
265         //System.out.println(this + ".getProperty(" + element + ", " + key + "): " + t);\r
266         return t;\r
267     }\r
268 \r
269     @SuppressWarnings("unchecked")\r
270     @Override\r
271     public <T> T setProperty(INode element, String key, T value) {\r
272         T result = null;\r
273         //System.out.println(this + ".setProperty(" + element + ", " + key + ", " + value + ")");\r
274         Map<String, Object> map = properties.get(element);\r
275         if (map == null) {\r
276             if (value == null)\r
277                 return null;\r
278             map = new HashMap<String, Object>(8);\r
279             properties.put(element, map);\r
280         }\r
281         if (value == null) {\r
282             result = (T) map.remove(key);\r
283             if (map.isEmpty())\r
284                 properties.remove(element);\r
285         } else\r
286             result = (T) map.put(key, value);\r
287         return result;\r
288     }\r
289 \r
290     @SuppressWarnings("unchecked")\r
291     @Override\r
292     public <T> T getConstant(String key) {\r
293         return (T) constants.get(key);\r
294     }\r
295 \r
296     @Override\r
297     public String toString() {\r
298         return "ProfileObserver[" + resource.getResourceId() + "]";\r
299     }\r
300 \r
301 //    @Override\r
302 //    public ICanvasContext getContext() {\r
303 //      return canvas;\r
304 //    }\r
305 //    \r
306 //    @Override\r
307 //    public IDiagram getDiagram() {\r
308 //      return diagram;\r
309 //    }\r
310 \r
311     public void listen(AsyncRequestProcessor processor, IDisposable disposable) {\r
312         activationListener = new ProfileActivationListener(resource, this, disposable);\r
313         processor.asyncRequest(new RuntimeProfileActiveEntries(resource), activationListener);\r
314     }\r
315 \r
316     @Override\r
317     public Resource getResource() {\r
318         return resource;\r
319     }\r
320 \r
321     @Override\r
322     public G2DSceneGraph getSceneGraph() {\r
323         return sceneGraph;\r
324     }\r
325 \r
326 }\r