X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph.profile%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fprofile%2Fcommon%2FProfileObserver.java;fp=bundles%2Forg.simantics.scenegraph.profile%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fprofile%2Fcommon%2FProfileObserver.java;h=e724d35a0f6e8762047a17e119a612f9a7717099;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 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 index 000000000..e724d35a0 --- /dev/null +++ b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java @@ -0,0 +1,326 @@ +/******************************************************************************* + * 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 constants = new HashMap(); + + private Map> temporaryProperties = new HashMap>(); + private Map> properties = new HashMap>(); + + 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 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>() { + @Override + public void execute(final Collection entries) { + + if (isDisposed()) + return; + + ThreadUtils.asyncExec(thread, new Runnable() { + +// private void init(INode node) { +// //ProfileVariables.init(node, ProfileObserver.this); +//// NodeUtil.forChildren(node, new NodeProcedure() { +//// @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 getTemporaryProperty(INode element, String key) { + Map 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 void setTemporaryProperty(INode element, String key, T value) { + //System.out.println(this + ".setTemporaryProperty(" + element + ", " + key + ", " + value + ")"); + Map map = temporaryProperties.get(element); + if (map == null) { + if (value == null) + return; + map = new HashMap(8); + temporaryProperties.put(element, map); + } + if (value == null) { + map.remove(key); + if (map.isEmpty()) + properties.remove(element); + } else + map.put(key, value); + } + + @SuppressWarnings("unchecked") + @Override + public T getProperty(INode element, String key) { + Map 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 setProperty(INode element, String key, T value) { + T result = null; + //System.out.println(this + ".setProperty(" + element + ", " + key + ", " + value + ")"); + Map map = properties.get(element); + if (map == null) { + if (value == null) + return null; + map = new HashMap(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 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; + } + +}