-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.scenegraph.profile.common;\r
-\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.concurrent.TimeUnit;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.db.AsyncRequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.common.session.SessionEventListenerAdapter;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.procedure.Procedure;\r
-import org.simantics.db.service.SessionEventSupport;\r
-import org.simantics.scenegraph.INode;\r
-import org.simantics.scenegraph.g2d.G2DSceneGraph;\r
-import org.simantics.scenegraph.profile.EvaluationContext;\r
-import org.simantics.scenegraph.profile.ProfileEntry;\r
-import org.simantics.scenegraph.profile.impl.DebugPolicy;\r
-import org.simantics.scenegraph.profile.impl.ProfileActivationListener;\r
-import org.simantics.scenegraph.profile.request.RuntimeProfileActiveEntries;\r
-import org.simantics.utils.datastructures.disposable.IDisposable;\r
-import org.simantics.utils.threads.IThreadWorkQueue;\r
-import org.simantics.utils.threads.ThreadUtils;\r
-\r
-public class ProfileObserver implements EvaluationContext {\r
-\r
- private final Session session;\r
-\r
- /**\r
- * Runtime diagram resource.\r
- */\r
- private final Resource resource;\r
-\r
- private final IDisposable canvas;\r
- private final IThreadWorkQueue thread;\r
- @SuppressWarnings("unused")\r
- private final Object diagram;\r
- private final Runnable notification;\r
- private final G2DSceneGraph sceneGraph;\r
-\r
- private boolean dirty = true;\r
- private boolean disposed = false;\r
-\r
- private ProfileActivationListener activationListener;\r
-\r
- private Map<String, Object> constants = new HashMap<String, Object>();\r
-\r
- private Map<INode, Map<String, Object>> temporaryProperties = new HashMap<INode, Map<String, Object>>();\r
- private Map<INode, Map<String, Object>> properties = new HashMap<INode, Map<String, Object>>();\r
-\r
- private final SessionEventListenerAdapter transactionListener = new SessionEventListenerAdapter() {\r
- @Override\r
- public void writeTransactionFinished() {\r
- if (isDisposed())\r
- dispose();\r
- if (dirty)\r
- perform();\r
- }\r
- @Override\r
- public void readTransactionFinished() {\r
- if (isDisposed())\r
- dispose();\r
- if (dirty)\r
- perform();\r
- }\r
- };\r
-\r
- public ProfileObserver(Session session, Resource resource, IThreadWorkQueue thread, IDisposable canvas, G2DSceneGraph sceneGraph, Object diagram, Map<String, Object> constants, Runnable notification) {\r
- //System.out.println(this + " NEW PROFILE OBSERVER: ");\r
- this.session = session;\r
- this.resource = resource;\r
- this.thread = thread;\r
- this.canvas = canvas;\r
- this.diagram = diagram;\r
- this.sceneGraph = sceneGraph;\r
- this.constants.putAll(constants);\r
- this.notification = notification;\r
-\r
- attachSessionListener();\r
-\r
- if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
- System.out.println("ProfileObserver(" + this + ")");\r
- \r
- // Tell SceneGraph that this observer is not yet done applying its operations\r
- if(sceneGraph != null)\r
- sceneGraph.setPending(ProfileObserver.this);\r
- \r
- }\r
-\r
- private void attachSessionListener() {\r
- SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);\r
- eventSupport.addListener(transactionListener);\r
- }\r
-\r
- private void detachSessionListener() {\r
- SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);\r
- eventSupport.removeListener(transactionListener);\r
- }\r
-\r
- public void dispose() {\r
- synchronized (this) {\r
- if (disposed)\r
- return;\r
- disposed = true;\r
- }\r
-\r
- if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
- System.out.println("ProfileObserver.dispose(" + this + ")");\r
-\r
- if(activationListener != null) { \r
- activationListener.cleanup();\r
- activationListener = null;\r
- }\r
-\r
- detachSessionListener();\r
- }\r
-\r
- @Override\r
- public void update() {\r
- if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)\r
- System.out.println("Profile observer marked dirty.");\r
- dirty = true;\r
- }\r
-\r
- private void perform() {\r
- dirty = false;\r
- if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)\r
- System.out.println("Profile observer detected a change.");\r
- \r
- session.asyncRequest(new RuntimeProfileActiveEntries(resource), new Procedure<Collection<ProfileEntry>>() {\r
- @Override\r
- public void execute(final Collection<ProfileEntry> entries) {\r
-\r
- if (isDisposed())\r
- return;\r
-\r
- ThreadUtils.asyncExec(thread, new Runnable() {\r
- \r
-// private void init(INode node) {\r
-// //ProfileVariables.init(node, ProfileObserver.this);\r
-//// NodeUtil.forChildren(node, new NodeProcedure<Object>() {\r
-//// @Override\r
-//// public Object execute(INode node, String id) {\r
-//// init(node);\r
-//// return null;\r
-//// }\r
-//// }, null);\r
-// }\r
-\r
- @Override\r
- public void run() {\r
-\r
- if (isDisposed())\r
- return;\r
-\r
- temporaryProperties.clear();\r
-\r
-// init(sceneGraph);\r
-\r
-// for(IElement e : diagram.getElements()) {\r
-// Node node = NodeUtils.\r
-// Variables.init(e, ProfileObserver.this);\r
-// }\r
-\r
- for(ProfileEntry e : entries) {\r
- if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)\r
- System.out.println("Apply profile entry: " + e);\r
- e.apply(ProfileObserver.this);\r
- }\r
-\r
- if(dirty) {\r
- sceneGraph.setPending(ProfileObserver.this);\r
-// System.err.println("setPending, dirty=true");\r
- }\r
- else {\r
- sceneGraph.clearPending(ProfileObserver.this);\r
-// System.err.println("clearPending, dirty=false");\r
- }\r
- \r
- notification.run();\r
-// canvas.getContentContext().setDirty();\r
- \r
- // Something is underway, schedule update\r
- if(dirty) {\r
- Simantics.async(new Runnable() {\r
-\r
- @Override\r
- public void run() {\r
-\r
- if (isDisposed()) return;\r
- \r
- if(dirty) perform();\r
- \r
- }\r
- \r
- }, 100, TimeUnit.MILLISECONDS);\r
- }\r
-\r
- }\r
- });\r
- }\r
-\r
- @Override\r
- public void exception(Throwable t) {\r
- Logger.defaultLogError(t);\r
- }\r
- });\r
- }\r
-\r
- @Override\r
- public boolean isDisposed() {\r
- return disposed || canvas.isDisposed();\r
- }\r
-\r
- @Override\r
- public void exception(Throwable throwable) {\r
- Logger.defaultLogError(throwable);\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T getTemporaryProperty(INode element, String key) {\r
- Map<String, Object> map = temporaryProperties.get(element);\r
- T t = map == null ? null : (T) map.get(key);\r
- //System.out.println(this + ".getTemporaryProperty(" + element + ", " + key + "): " + t);\r
- return t;\r
- }\r
-\r
- @Override\r
- public <T> void setTemporaryProperty(INode element, String key, T value) {\r
- //System.out.println(this + ".setTemporaryProperty(" + element + ", " + key + ", " + value + ")");\r
- Map<String, Object> map = temporaryProperties.get(element);\r
- if (map == null) {\r
- if (value == null)\r
- return;\r
- map = new HashMap<String, Object>(8);\r
- temporaryProperties.put(element, map);\r
- }\r
- if (value == null) {\r
- map.remove(key);\r
- if (map.isEmpty())\r
- properties.remove(element);\r
- } else\r
- map.put(key, value);\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T getProperty(INode element, String key) {\r
- Map<String, Object> map = properties.get(element);\r
- T t = map == null ? null : (T) map.get(key);\r
- //System.out.println(this + ".getProperty(" + element + ", " + key + "): " + t);\r
- return t;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T setProperty(INode element, String key, T value) {\r
- T result = null;\r
- //System.out.println(this + ".setProperty(" + element + ", " + key + ", " + value + ")");\r
- Map<String, Object> map = properties.get(element);\r
- if (map == null) {\r
- if (value == null)\r
- return null;\r
- map = new HashMap<String, Object>(8);\r
- properties.put(element, map);\r
- }\r
- if (value == null) {\r
- result = (T) map.remove(key);\r
- if (map.isEmpty())\r
- properties.remove(element);\r
- } else\r
- result = (T) map.put(key, value);\r
- return result;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T getConstant(String key) {\r
- return (T) constants.get(key);\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return "ProfileObserver[" + resource.getResourceId() + "]";\r
- }\r
-\r
-// @Override\r
-// public ICanvasContext getContext() {\r
-// return canvas;\r
-// }\r
-// \r
-// @Override\r
-// public IDiagram getDiagram() {\r
-// return diagram;\r
-// }\r
-\r
- public void listen(AsyncRequestProcessor processor, IDisposable disposable) {\r
- activationListener = new ProfileActivationListener(resource, this, disposable);\r
- processor.asyncRequest(new RuntimeProfileActiveEntries(resource), activationListener);\r
- }\r
-\r
- @Override\r
- public Resource getResource() {\r
- return resource;\r
- }\r
-\r
- @Override\r
- public G2DSceneGraph getSceneGraph() {\r
- return sceneGraph;\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.profile.common;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.simantics.Simantics;
+import org.simantics.db.AsyncRequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.common.session.SessionEventListenerAdapter;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.procedure.Procedure;
+import org.simantics.db.service.SessionEventSupport;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.G2DSceneGraph;
+import org.simantics.scenegraph.profile.EvaluationContext;
+import org.simantics.scenegraph.profile.ProfileEntry;
+import org.simantics.scenegraph.profile.impl.DebugPolicy;
+import org.simantics.scenegraph.profile.impl.ProfileActivationListener;
+import org.simantics.scenegraph.profile.request.RuntimeProfileActiveEntries;
+import org.simantics.utils.datastructures.disposable.IDisposable;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.ThreadUtils;
+
+public class ProfileObserver implements EvaluationContext {
+
+ private final Session session;
+
+ /**
+ * Runtime diagram resource.
+ */
+ private final Resource resource;
+
+ private final IDisposable canvas;
+ private final IThreadWorkQueue thread;
+ @SuppressWarnings("unused")
+ private final Object diagram;
+ private final Runnable notification;
+ private final G2DSceneGraph sceneGraph;
+
+ private boolean dirty = true;
+ private boolean disposed = false;
+
+ private ProfileActivationListener activationListener;
+
+ private Map<String, Object> constants = new HashMap<String, Object>();
+
+ private Map<INode, Map<String, Object>> temporaryProperties = new HashMap<INode, Map<String, Object>>();
+ private Map<INode, Map<String, Object>> properties = new HashMap<INode, Map<String, Object>>();
+
+ private final SessionEventListenerAdapter transactionListener = new SessionEventListenerAdapter() {
+ @Override
+ public void writeTransactionFinished() {
+ if (isDisposed())
+ dispose();
+ if (dirty)
+ perform();
+ }
+ @Override
+ public void readTransactionFinished() {
+ if (isDisposed())
+ dispose();
+ if (dirty)
+ perform();
+ }
+ };
+
+ public ProfileObserver(Session session, Resource resource, IThreadWorkQueue thread, IDisposable canvas, G2DSceneGraph sceneGraph, Object diagram, Map<String, Object> constants, Runnable notification) {
+ //System.out.println(this + " NEW PROFILE OBSERVER: ");
+ this.session = session;
+ this.resource = resource;
+ this.thread = thread;
+ this.canvas = canvas;
+ this.diagram = diagram;
+ this.sceneGraph = sceneGraph;
+ this.constants.putAll(constants);
+ this.notification = notification;
+
+ attachSessionListener();
+
+ if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)
+ System.out.println("ProfileObserver(" + this + ")");
+
+ // Tell SceneGraph that this observer is not yet done applying its operations
+ if(sceneGraph != null)
+ sceneGraph.setPending(ProfileObserver.this);
+
+ }
+
+ private void attachSessionListener() {
+ SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);
+ eventSupport.addListener(transactionListener);
+ }
+
+ private void detachSessionListener() {
+ SessionEventSupport eventSupport = session.getService(SessionEventSupport.class);
+ eventSupport.removeListener(transactionListener);
+ }
+
+ public void dispose() {
+ synchronized (this) {
+ if (disposed)
+ return;
+ disposed = true;
+ }
+
+ if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)
+ System.out.println("ProfileObserver.dispose(" + this + ")");
+
+ if(activationListener != null) {
+ activationListener.cleanup();
+ activationListener = null;
+ }
+
+ detachSessionListener();
+ }
+
+ @Override
+ public void update() {
+ if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)
+ System.out.println("Profile observer marked dirty.");
+ dirty = true;
+ }
+
+ private void perform() {
+ dirty = false;
+ if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)
+ System.out.println("Profile observer detected a change.");
+
+ session.asyncRequest(new RuntimeProfileActiveEntries(resource), new Procedure<Collection<ProfileEntry>>() {
+ @Override
+ public void execute(final Collection<ProfileEntry> entries) {
+
+ if (isDisposed())
+ return;
+
+ ThreadUtils.asyncExec(thread, new Runnable() {
+
+// private void init(INode node) {
+// //ProfileVariables.init(node, ProfileObserver.this);
+//// NodeUtil.forChildren(node, new NodeProcedure<Object>() {
+//// @Override
+//// public Object execute(INode node, String id) {
+//// init(node);
+//// return null;
+//// }
+//// }, null);
+// }
+
+ @Override
+ public void run() {
+
+ if (isDisposed())
+ return;
+
+ temporaryProperties.clear();
+
+// init(sceneGraph);
+
+// for(IElement e : diagram.getElements()) {
+// Node node = NodeUtils.
+// Variables.init(e, ProfileObserver.this);
+// }
+
+ for(ProfileEntry e : entries) {
+ if (DebugPolicy.DEBUG_PROFILE_OBSERVER_PERFORM)
+ System.out.println("Apply profile entry: " + e);
+ e.apply(ProfileObserver.this);
+ }
+
+ if(dirty) {
+ sceneGraph.setPending(ProfileObserver.this);
+// System.err.println("setPending, dirty=true");
+ }
+ else {
+ sceneGraph.clearPending(ProfileObserver.this);
+// System.err.println("clearPending, dirty=false");
+ }
+
+ notification.run();
+// canvas.getContentContext().setDirty();
+
+ // Something is underway, schedule update
+ if(dirty) {
+ Simantics.async(new Runnable() {
+
+ @Override
+ public void run() {
+
+ if (isDisposed()) return;
+
+ if(dirty) perform();
+
+ }
+
+ }, 100, TimeUnit.MILLISECONDS);
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public void exception(Throwable t) {
+ Logger.defaultLogError(t);
+ }
+ });
+ }
+
+ @Override
+ public boolean isDisposed() {
+ return disposed || canvas.isDisposed();
+ }
+
+ @Override
+ public void exception(Throwable throwable) {
+ Logger.defaultLogError(throwable);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getTemporaryProperty(INode element, String key) {
+ Map<String, Object> map = temporaryProperties.get(element);
+ T t = map == null ? null : (T) map.get(key);
+ //System.out.println(this + ".getTemporaryProperty(" + element + ", " + key + "): " + t);
+ return t;
+ }
+
+ @Override
+ public <T> void setTemporaryProperty(INode element, String key, T value) {
+ //System.out.println(this + ".setTemporaryProperty(" + element + ", " + key + ", " + value + ")");
+ Map<String, Object> map = temporaryProperties.get(element);
+ if (map == null) {
+ if (value == null)
+ return;
+ map = new HashMap<String, Object>(8);
+ temporaryProperties.put(element, map);
+ }
+ if (value == null) {
+ map.remove(key);
+ if (map.isEmpty())
+ temporaryProperties.remove(element);
+ } else
+ map.put(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getProperty(INode element, String key) {
+ Map<String, Object> map = properties.get(element);
+ T t = map == null ? null : (T) map.get(key);
+ //System.out.println(this + ".getProperty(" + element + ", " + key + "): " + t);
+ return t;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T setProperty(INode element, String key, T value) {
+ T result = null;
+ //System.out.println(this + ".setProperty(" + element + ", " + key + ", " + value + ")");
+ Map<String, Object> map = properties.get(element);
+ if (map == null) {
+ if (value == null)
+ return null;
+ map = new HashMap<String, Object>(8);
+ properties.put(element, map);
+ }
+ if (value == null) {
+ result = (T) map.remove(key);
+ if (map.isEmpty())
+ properties.remove(element);
+ } else
+ result = (T) map.put(key, value);
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getConstant(String key) {
+ return (T) constants.get(key);
+ }
+
+ @Override
+ public String toString() {
+ return "ProfileObserver[" + resource.getResourceId() + "]";
+ }
+
+// @Override
+// public ICanvasContext getContext() {
+// return canvas;
+// }
+//
+// @Override
+// public IDiagram getDiagram() {
+// return diagram;
+// }
+
+ public void listen(AsyncRequestProcessor processor, IDisposable disposable) {
+ activationListener = new ProfileActivationListener(resource, this, disposable);
+ processor.asyncRequest(new RuntimeProfileActiveEntries(resource), activationListener);
+ }
+
+ @Override
+ public Resource getResource() {
+ return resource;
+ }
+
+ @Override
+ public G2DSceneGraph getSceneGraph() {
+ return sceneGraph;
+ }
+
+}