]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/subscription/CollectSubscriptions.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / subscription / CollectSubscriptions.java
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/subscription/CollectSubscriptions.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/subscription/CollectSubscriptions.java
new file mode 100644 (file)
index 0000000..169c246
--- /dev/null
@@ -0,0 +1,315 @@
+/*******************************************************************************\r
+ * Copyright (c) 2011 Association for Decentralized Information Management in\r
+ * 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.modeling.subscription;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+\r
+import org.eclipse.core.runtime.MultiStatus;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Databoard;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.BinaryRead;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.request.ResourceRead;\r
+import org.simantics.db.common.request.TernaryRead;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.RVI;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.history.util.subscription.SubscriptionItem;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.scl.runtime.tuple.Tuple3;\r
+import org.simantics.simulation.experiment.IDynamicExperiment;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class CollectSubscriptions extends ResourceRead<SubscriptionCollectionResult> {\r
+\r
+    private static final boolean PERF = false;\r
+    private static final boolean DEBUG = false;\r
+\r
+    protected Resource           experiment;\r
+    protected double             defaultSamplingInterval;\r
+    protected boolean            synchronous;\r
+\r
+    public CollectSubscriptions(IDynamicExperiment experiment, double defaultSamplingInterval) {\r
+        this(experiment.getModel(), experiment.getResource(), defaultSamplingInterval, false);\r
+    }\r
+\r
+    public CollectSubscriptions(IDynamicExperiment experiment, double defaultSamplingInterval, boolean synchronous) {\r
+        this(experiment.getModel(), experiment.getResource(), defaultSamplingInterval, synchronous);\r
+    }\r
+\r
+    public CollectSubscriptions(Resource model, Resource experiment, double defaultSamplingInterval) {\r
+        this(model, experiment, defaultSamplingInterval, false);\r
+    }\r
+\r
+    public CollectSubscriptions(Resource model, Resource experiment, double defaultSamplingInterval, boolean synchronous) {\r
+        super(model);\r
+        this.experiment = experiment;\r
+        this.defaultSamplingInterval = defaultSamplingInterval;\r
+    }\r
+\r
+    @Override\r
+    public SubscriptionCollectionResult perform(ReadGraph graph) throws DatabaseException {\r
+        MultiStatus status = new MultiStatus(ModelHistoryCollector.BUNDLE_ID, 0, "History collection subscription resolution problems:", null);\r
+        boolean oldSync = graph.setSynchronous(synchronous);\r
+        try {\r
+            Map<String, SubscriptionItem> items = gatherSubscriptions(graph, resource, status, new TreeMap<String, SubscriptionItem>());\r
+            return new SubscriptionCollectionResult(new ArrayList<>(items.values()), status);\r
+        } finally {\r
+            graph.setSynchronous(oldSync);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Scans thru a model and writes up all the variables that are to be monitored.\r
+     * This includes:\r
+     *   Subscriptions\r
+     *   Charts\r
+     *   Spreadsheets (not in cur. impl)\r
+     *   Monitors on diagram (not in cur. impl)\r
+     * \r
+     * @param graph\r
+     * @param model\r
+     * @param status \r
+     * @param variablesToMonitor\r
+     * @throws DatabaseException\r
+     */\r
+    public Map<String, SubscriptionItem> gatherSubscriptions(ReadGraph graph, Resource model, MultiStatus status,\r
+            Map<String, SubscriptionItem> items) throws DatabaseException {\r
+        if (PERF)\r
+            System.out.println("DEBUG: CollectAprosSubscriptions.gatherSubscriptions");\r
+        long start = System.nanoTime();\r
+\r
+        // Get active experiment context if possible to be able\r
+        // to resolve the whole model, not just the configuration.\r
+        Variable configuration = Variables.getPossibleConfigurationContext(graph, model);\r
+        if (configuration == null)\r
+            return items;\r
+        Variable experimentVariable = null;\r
+\r
+        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        for (Resource run : graph.syncRequest(new ObjectsWithType(experiment, L0.ConsistsOf, SIMU.Run))) {\r
+            if (graph.hasStatement(run, SIMU.IsActive)) {\r
+                try {\r
+                    experimentVariable = Variables.switchRealization(graph, configuration, run);\r
+                } catch (DatabaseException e) {\r
+                    experimentVariable = Variables.switchPossibleContext(graph, configuration, run);\r
+                }\r
+            }\r
+        }\r
+\r
+        ModelingResources MOD = ModelingResources.getInstance(graph);\r
+        Param constants = new Param(configuration, experimentVariable, defaultSamplingInterval);\r
+        for (Resource subscription : graph.syncRequest(new ObjectsWithType(model, L0.ConsistsOf, MOD.Subscription))) {\r
+            Map<String, SubscriptionItem> subscriptionItems = graph.syncRequest(\r
+                    new SubscriptionRequest(subscription, constants),\r
+                    TransientCacheAsyncListener.<Map<String, SubscriptionItem>>instance());\r
+            items.putAll(subscriptionItems);\r
+        }\r
+\r
+        if (PERF)\r
+            System.out.println("DEBUG: CollectAprosSubscriptions.gatherSubscriptions ENDS, took " + ((System.nanoTime() - start)*1e-6) + " ms with " + items.size() + " items");\r
+\r
+        return items;\r
+    }\r
+\r
+    static class Param extends Tuple3 {\r
+        public Param(Variable configurationContext, Variable experimentContext, Double defaultSamplingInterval) {\r
+            super(configurationContext, experimentContext, defaultSamplingInterval);\r
+        }\r
+    }\r
+\r
+    static class SubscriptionRequest extends BinaryRead<Resource, Param, Map<String, SubscriptionItem>> {\r
+\r
+        public SubscriptionRequest(Resource subscription, Param constants) {\r
+            super(subscription, constants);\r
+        }\r
+\r
+        @Override\r
+        public Map<String, SubscriptionItem> perform(ReadGraph graph) throws DatabaseException {\r
+            if (PERF)\r
+                System.out.println("DEBUG: CollectSubscriptions.SubscriptionRequest(" + NameUtils.getSafeName(graph, parameter, true) + ")");\r
+            long start = System.nanoTime();\r
+\r
+            ModelingResources MOD = ModelingResources.getInstance(graph);\r
+            Boolean v = graph.getPossibleRelatedValue(parameter, MOD.Subscription_Enabled, Bindings.BOOLEAN);\r
+            if (!Boolean.TRUE.equals(v))\r
+                return Collections.emptyMap();\r
+\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+            String groupId = graph.getPossibleRelatedValue(parameter, L0.HasName, Bindings.STRING);\r
+            if (groupId == null)\r
+                return Collections.emptyMap();\r
+\r
+            Map<String, SubscriptionItem> items = graph.syncRequest(\r
+                    new SubscriptionItemsRequest(parameter, groupId, parameter2),\r
+                    TransientCacheAsyncListener.<Map<String, SubscriptionItem>>instance());\r
+            if (PERF)\r
+                System.out.println("DEBUG: CollectSubscriptions.SubscriptionRequest(" + NameUtils.getSafeName(graph, parameter, true) + ") DONE in " + ((System.nanoTime() - start)*1e-6) + " ms");\r
+\r
+            return items;\r
+        }\r
+\r
+    }\r
+\r
+    static class SubscriptionItemsRequest extends TernaryRead<Resource, String, Param, Map<String, SubscriptionItem>> {\r
+\r
+        public SubscriptionItemsRequest(Resource subscription, String groupId, Param constants) {\r
+            super(subscription, groupId, constants);\r
+        }\r
+\r
+        @Override\r
+        public Map<String, SubscriptionItem> perform(ReadGraph graph) throws DatabaseException {\r
+            if (PERF)\r
+                System.out.println("DEBUG: CollectSubscriptions.SubscriptionItemsRequest(" + NameUtils.getSafeName(graph, parameter, true) + ")");\r
+            long start = System.nanoTime();\r
+\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+            ModelingResources MOD = ModelingResources.getInstance(graph);\r
+\r
+            Collection<Resource> subscriptionItems = graph.syncRequest(new ObjectsWithType(parameter, L0.ConsistsOf, MOD.Subscription_Item));\r
+            if (subscriptionItems.isEmpty())\r
+                return Collections.emptyMap();\r
+\r
+            Map<String, SubscriptionItem> result = new THashMap<>(subscriptionItems.size());\r
+            for (Resource subscriptionItem : subscriptionItems) {\r
+                SubscriptionItem hi = graph.syncRequest(\r
+                        new ItemRequest(subscriptionItem, parameter2, parameter3),\r
+                        TransientCacheListener.<SubscriptionItem>instance());\r
+                if (hi != null)\r
+                    result.put(hi.id, hi);\r
+            }\r
+\r
+            if (PERF)\r
+                System.out.println("DEBUG: CollectSubscriptions.SubscriptionItemsRequest(" + NameUtils.getSafeName(graph, parameter, true) + ") DONE in " + ((System.nanoTime() - start)*1e-6) + " ms with " + result.size() + " items");\r
+\r
+            return result;\r
+        }\r
+\r
+    }\r
+\r
+    static class ItemRequest extends TernaryRead<Resource, String, Param, SubscriptionItem> {\r
+\r
+        public ItemRequest(Resource item, String groupId, Param constants) {\r
+            super(item, groupId, constants);\r
+        }\r
+\r
+        @Override\r
+        public SubscriptionItem perform(ReadGraph graph) throws DatabaseException {\r
+            ModelingResources MOD = ModelingResources.getInstance(graph);\r
+            Resource subscriptionItem = parameter;\r
+            String groupId = parameter2;\r
+            Param constants = parameter3;\r
+            Variable configurationContext = (Variable) constants.c0;\r
+            Variable experimentContext = (Variable) constants.c1;\r
+            double defaultSamplingInterval = (double) constants.c2;\r
+\r
+            Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class );\r
+            RVI rvi = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_VariableId, rviBinding);\r
+            if (rvi == null) {\r
+                //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' is missing RVI property"));\r
+                return null;\r
+            }\r
+\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+            String guid = graph.getPossibleRelatedValue(subscriptionItem, L0.HasName);\r
+            if (guid == null) {\r
+                //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' has no name (ID)."));\r
+                return null;\r
+            }\r
+            String variablePersistentId = rvi.toString();\r
+            Pair<Variable, Variable> variable = Variables.resolvePossible(graph, rvi, configurationContext, experimentContext);\r
+            if (variable == null) {\r
+                if (DEBUG)\r
+                    System.out.println("DEBUG: unresolvable subscription: " + variablePersistentId);\r
+                // Don't log these, these problems are conveyed to the\r
+                // user through model browser UI labels.\r
+                //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' variable cannot be resolved from RVI " + rvi.toString(graph)));\r
+                return null;\r
+            }\r
+            String variableId = rvi.asPossibleString(graph, variable.second);\r
+            //System.out.println("DEBUG: " + variablePersistentId + " - " + variableId);\r
+            if (variableId == null) {\r
+                return null;\r
+            }\r
+\r
+            Datatype type = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Datatype, Bindings.getBindingUnchecked(Datatype.class));\r
+            if (type == null && variable != null) {\r
+                type = variable.first.getPossibleDatatype(graph);\r
+            }\r
+            if (type == null) {\r
+                //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' is missing data type"));\r
+                // Can't function without a datatype.\r
+                return null;\r
+            }\r
+\r
+            Double itemSamplingInterval = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_SamplingInterval, Bindings.DOUBLE);\r
+            Double itemDeadband = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Deadband, Bindings.DOUBLE);\r
+\r
+            Double bias = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Bias, Bindings.DOUBLE);\r
+            Double gain = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Gain, Bindings.DOUBLE);\r
+            String unit = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Unit, Bindings.STRING);\r
+\r
+            double samplingInterval = itemSamplingInterval != null ? itemSamplingInterval : defaultSamplingInterval;\r
+            double deadband = itemDeadband != null ? itemDeadband : 0.0;\r
+\r
+            SubscriptionItem item = new SubscriptionItem();\r
+\r
+            // HACK: use id for storing the name of the item\r
+            // Assumption: subscription item's name is unique within the model\r
+            item.id = guid;\r
+\r
+            item.variableId = variableId;\r
+            item.groupId = groupId;\r
+            item.groupItemId = variablePersistentId;\r
+            // HACK: use format for storing the data type of the item\r
+            item.format = type;\r
+            // HACK: use formatId for storing the unit of the item,\r
+            // empty unit is interpreted to mean "no unit" because\r
+            // formatId cannot be null.\r
+            item.formatId = unit == null ? "" : unit;\r
+\r
+            // Subscription parameters\r
+            item.deadband = deadband;\r
+            item.interval = samplingInterval;\r
+            if (bias != null) item.bias = bias;\r
+            if (gain != null) item.gain = gain;\r
+\r
+            if (DEBUG)\r
+                //System.out.println("DEBUG: ItemRequest(" + parameter + ", " + parameter2.getURI(graph) + ", " + parameter3 + ")\n\t= " + item);\r
+                System.out.println("DEBUG: ItemRequest(" + parameter + ", " + parameter2 + ", " + parameter3 + ")\n\t= " + item);\r
+\r
+            return item;\r
+        }\r
+\r
+    }\r
+\r
+}
\ No newline at end of file