--- /dev/null
+/*******************************************************************************\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.db.services.activation;\r
+\r
+import org.simantics.db.Disposable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.CommonDBUtils;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.utils.queries.QueryExecutor2;\r
+import org.simantics.layer0.utils.triggers.IActivation;\r
+import org.simantics.layer0.utils.triggers.IActivationManager;\r
+import org.simantics.layer0.utils.triggers.IModification;\r
+import org.simantics.layer0.utils.triggers.ITrigger;\r
+import org.simantics.operation.Layer0X;\r
+import org.simantics.utils.logging.TimeLogger;\r
+import org.simantics.utils.threads.logger.IThreadLogger;\r
+import org.simantics.utils.threads.logger.ThreadLogger;\r
+\r
+@SuppressWarnings("deprecation") // No replacement given so now way to fix this error.\r
+public class ActivationManager implements IActivationManager, Disposable {\r
+\r
+ Session session;\r
+ static IThreadLogger threadLogger = ThreadLogger.getInstance();\r
+\r
+ class Activation extends QueryExecutor2 implements IActivation {\r
+ final boolean DEBUG = false;\r
+ final boolean BREAK_INFINITE_ACTIVATION_LOOPS = true;\r
+\r
+ /**\r
+ * After {@value InfiniteLoop} the activation will be forcibly\r
+ * deactivated if {@link #BREAK_INFINITE_ACTIVATION_LOOPS} is\r
+ * <code>true</code>.\r
+ */\r
+ final int INFINITE_LOOP_COUNT = 100;\r
+\r
+ Resource resource;\r
+ int transactionCount = 0;\r
+ boolean disposed = false;\r
+ boolean runOnce = false;\r
+\r
+ public Activation(Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+\r
+ public void runOnceAndDeactivate() {\r
+ runOnce = true;\r
+ }\r
+\r
+ @Override\r
+ public void run(ReadGraph g) throws DatabaseException {\r
+// ITask task = threadLogger.begin("Activation.perform");\r
+ Layer0X L0X = Layer0X.getInstance(g);\r
+ for(Resource r : g.getObjects(resource, L0X.HasTrigger))\r
+ if(calcModification(g, r) != null)\r
+ execute(g, r);\r
+// task.finish();\r
+ }\r
+\r
+ private IModification calcModification(ReadGraph g, Resource trigger) throws DatabaseException {\r
+// new Exception().printStackTrace();\r
+ //ITask task = ThreadLogger.getInstance().begin("Activation.calcModification");\r
+ IModification modi = g.syncRequest(g.adapt(trigger, ITrigger.class));\r
+ //task.finish();\r
+ return modi;\r
+ }\r
+\r
+ private WriteRequest getRequest(final Resource trigger) {\r
+ return new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph g) throws DatabaseException {\r
+ int count = 0;\r
+ while (true) {\r
+ \r
+ CommonDBUtils.selectClusterSet(g, trigger);\r
+ \r
+ TimeLogger.log("ActivationManager: start calculating modification");\r
+ IModification modification = calcModification(g, trigger);\r
+ TimeLogger.log("ActivationManager: finished calculating modification");\r
+ if (modification != null)\r
+ ++count;\r
+ else {\r
+ if (count > 0) {\r
+ CommentMetadata cm = g.getMetadata(CommentMetadata.class);\r
+ String msg = "ActivationManager modification count=" + count;\r
+ g.addMetadata(cm.add(msg));\r
+ if (DEBUG)\r
+ System.out.println("DEBUG: " + msg);\r
+ }\r
+ if(runOnce)\r
+ deactivate();\r
+ return; \r
+ }\r
+ if (BREAK_INFINITE_ACTIVATION_LOOPS) {\r
+ if (count > INFINITE_LOOP_COUNT) {\r
+ deactivate();\r
+ String msg = "Possible dynamic activation loop. Forcing break."\r
+ + "Loop count was " + count\r
+ + ". Activated resource was "\r
+ + NameUtils.getURIOrSafeNameInternal(g, resource) + ".";\r
+ System.out.println("WARNING: " + msg);\r
+ throw new DatabaseException(msg);\r
+ }\r
+ }\r
+ try {\r
+ modification.perform(g);\r
+ TimeLogger.log("ActivationManager: performed modification");\r
+ } catch (DatabaseException e) {\r
+ deactivate();\r
+ throw e;\r
+ }\r
+ }\r
+ }\r
+ };\r
+ }\r
+ \r
+ private void executeOnce(WriteGraph graph, final Resource trigger) throws DatabaseException {\r
+ getRequest(trigger).perform(graph);\r
+// graph.syncRequest(getRequest(trigger));\r
+ }\r
+\r
+ private void execute(final ReadGraph graph, final Resource trigger) {\r
+ graph.asyncRequest(getRequest(trigger)); \r
+ }\r
+\r
+ @Override\r
+ public void deactivate() {\r
+ disposed = true; \r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return disposed || session == null;\r
+ }\r
+ \r
+ }\r
+ \r
+ public ActivationManager(Session session) {\r
+ this.session = session;\r
+ }\r
+\r
+ @Override\r
+ public IActivation activate(Resource r) {\r
+ Session s = session;\r
+ if (s == null)\r
+ throw new IllegalStateException("ActivationManager is disposed");\r
+ Activation activation = new Activation(r);\r
+ try {\r
+ activation.execute(session);\r
+ } catch (DatabaseException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+ return activation;\r
+ }\r
+\r
+ @Override\r
+ public IActivation activate(WriteGraph graph, Resource r) throws DatabaseException {\r
+ Session s = session;\r
+ if (s == null)\r
+ throw new IllegalStateException("ActivationManager is disposed");\r
+ Activation activation = new Activation(r);\r
+ activation.execute(graph);\r
+ return activation;\r
+ }\r
+\r
+ @Override\r
+ public void activateOnce(Resource resource) {\r
+ activate(resource).runOnceAndDeactivate(); \r
+ }\r
+ \r
+ @Override\r
+ public void activateOnce(WriteGraph graph, Resource resource) throws DatabaseException {\r
+ \r
+ Session s = session;\r
+ if (s == null)\r
+ throw new IllegalStateException("ActivationManager is disposed");\r
+ \r
+ Layer0X L0X = Layer0X.getInstance(graph);\r
+ for(Resource r : graph.getObjects(resource, L0X.HasTrigger)) {\r
+ new Activation(resource).executeOnce(graph, r);\r
+ }\r
+\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ session = null;\r
+ }\r
+\r
+}\r