]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java
new file mode 100644 (file)
index 0000000..e724d35
--- /dev/null
@@ -0,0 +1,326 @@
+/*******************************************************************************\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