1 /*******************************************************************************
2 * Copyright (c) 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.subscription;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
18 import java.util.TreeMap;
20 import org.eclipse.core.runtime.MultiStatus;
21 import org.simantics.databoard.Bindings;
22 import org.simantics.databoard.Databoard;
23 import org.simantics.databoard.binding.Binding;
24 import org.simantics.databoard.type.Datatype;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
28 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
29 import org.simantics.db.common.request.BinaryRead;
30 import org.simantics.db.common.request.ObjectsWithType;
31 import org.simantics.db.common.request.ResourceRead;
32 import org.simantics.db.common.request.TernaryRead;
33 import org.simantics.db.common.utils.NameUtils;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.db.layer0.variable.RVI;
36 import org.simantics.db.layer0.variable.Variable;
37 import org.simantics.db.layer0.variable.Variables;
38 import org.simantics.history.util.subscription.SubscriptionItem;
39 import org.simantics.layer0.Layer0;
40 import org.simantics.modeling.ModelingResources;
41 import org.simantics.scl.runtime.tuple.Tuple3;
42 import org.simantics.simulation.experiment.IDynamicExperiment;
43 import org.simantics.simulation.ontology.SimulationResource;
44 import org.simantics.utils.datastructures.Pair;
46 import gnu.trove.map.hash.THashMap;
49 * @author Tuukka Lehtonen
51 public class CollectSubscriptions extends ResourceRead<SubscriptionCollectionResult> {
53 private static final boolean PERF = false;
54 private static final boolean DEBUG = false;
56 protected Resource experiment;
57 protected double defaultSamplingInterval;
58 protected boolean synchronous;
60 public CollectSubscriptions(IDynamicExperiment experiment, double defaultSamplingInterval) {
61 this(experiment.getModel(), experiment.getResource(), defaultSamplingInterval, false);
64 public CollectSubscriptions(IDynamicExperiment experiment, double defaultSamplingInterval, boolean synchronous) {
65 this(experiment.getModel(), experiment.getResource(), defaultSamplingInterval, synchronous);
68 public CollectSubscriptions(Resource model, Resource experiment, double defaultSamplingInterval) {
69 this(model, experiment, defaultSamplingInterval, false);
72 public CollectSubscriptions(Resource model, Resource experiment, double defaultSamplingInterval, boolean synchronous) {
74 this.experiment = experiment;
75 this.defaultSamplingInterval = defaultSamplingInterval;
79 public SubscriptionCollectionResult perform(ReadGraph graph) throws DatabaseException {
80 MultiStatus status = new MultiStatus(ModelHistoryCollector.BUNDLE_ID, 0, "History collection subscription resolution problems:", null);
81 boolean oldSync = graph.setSynchronous(synchronous);
83 Map<String, SubscriptionItem> items = gatherSubscriptions(graph, resource, status, new TreeMap<String, SubscriptionItem>());
84 return new SubscriptionCollectionResult(new ArrayList<>(items.values()), status);
86 graph.setSynchronous(oldSync);
91 * Scans thru a model and writes up all the variables that are to be monitored.
95 * Spreadsheets (not in cur. impl)
96 * Monitors on diagram (not in cur. impl)
101 * @param variablesToMonitor
102 * @throws DatabaseException
104 public Map<String, SubscriptionItem> gatherSubscriptions(ReadGraph graph, Resource model, MultiStatus status,
105 Map<String, SubscriptionItem> items) throws DatabaseException {
107 System.out.println("DEBUG: CollectAprosSubscriptions.gatherSubscriptions");
108 long start = System.nanoTime();
110 // Get active experiment context if possible to be able
111 // to resolve the whole model, not just the configuration.
112 Variable configuration = Variables.getPossibleConfigurationContext(graph, model);
113 if (configuration == null)
115 Variable experimentVariable = null;
117 SimulationResource SIMU = SimulationResource.getInstance(graph);
118 Layer0 L0 = Layer0.getInstance(graph);
119 for (Resource run : graph.syncRequest(new ObjectsWithType(experiment, L0.ConsistsOf, SIMU.Run))) {
120 if (graph.hasStatement(run, SIMU.IsActive)) {
122 experimentVariable = Variables.switchRealization(graph, configuration, run);
123 } catch (DatabaseException e) {
124 experimentVariable = Variables.switchPossibleContext(graph, configuration, run);
129 ModelingResources MOD = ModelingResources.getInstance(graph);
130 Param constants = new Param(configuration, experimentVariable, defaultSamplingInterval);
131 for (Resource subscription : graph.syncRequest(new ObjectsWithType(model, L0.ConsistsOf, MOD.Subscription))) {
132 Map<String, SubscriptionItem> subscriptionItems = graph.syncRequest(
133 new SubscriptionRequest(subscription, constants),
134 TransientCacheAsyncListener.<Map<String, SubscriptionItem>>instance());
135 items.putAll(subscriptionItems);
139 System.out.println("DEBUG: CollectAprosSubscriptions.gatherSubscriptions ENDS, took " + ((System.nanoTime() - start)*1e-6) + " ms with " + items.size() + " items");
144 static class Param extends Tuple3 {
145 public Param(Variable configurationContext, Variable experimentContext, Double defaultSamplingInterval) {
146 super(configurationContext, experimentContext, defaultSamplingInterval);
150 static class SubscriptionRequest extends BinaryRead<Resource, Param, Map<String, SubscriptionItem>> {
152 public SubscriptionRequest(Resource subscription, Param constants) {
153 super(subscription, constants);
157 public Map<String, SubscriptionItem> perform(ReadGraph graph) throws DatabaseException {
159 System.out.println("DEBUG: CollectSubscriptions.SubscriptionRequest(" + NameUtils.getSafeName(graph, parameter, true) + ")");
160 long start = System.nanoTime();
162 ModelingResources MOD = ModelingResources.getInstance(graph);
163 Boolean v = graph.getPossibleRelatedValue(parameter, MOD.Subscription_Enabled, Bindings.BOOLEAN);
164 if (!Boolean.TRUE.equals(v))
165 return Collections.emptyMap();
167 Layer0 L0 = Layer0.getInstance(graph);
168 String groupId = graph.getPossibleRelatedValue(parameter, L0.HasName, Bindings.STRING);
170 return Collections.emptyMap();
172 Map<String, SubscriptionItem> items = graph.syncRequest(
173 new SubscriptionItemsRequest(parameter, groupId, parameter2),
174 TransientCacheAsyncListener.<Map<String, SubscriptionItem>>instance());
176 System.out.println("DEBUG: CollectSubscriptions.SubscriptionRequest(" + NameUtils.getSafeName(graph, parameter, true) + ") DONE in " + ((System.nanoTime() - start)*1e-6) + " ms");
183 static class SubscriptionItemsRequest extends TernaryRead<Resource, String, Param, Map<String, SubscriptionItem>> {
185 public SubscriptionItemsRequest(Resource subscription, String groupId, Param constants) {
186 super(subscription, groupId, constants);
190 public Map<String, SubscriptionItem> perform(ReadGraph graph) throws DatabaseException {
192 System.out.println("DEBUG: CollectSubscriptions.SubscriptionItemsRequest(" + NameUtils.getSafeName(graph, parameter, true) + ")");
193 long start = System.nanoTime();
195 Layer0 L0 = Layer0.getInstance(graph);
196 ModelingResources MOD = ModelingResources.getInstance(graph);
198 Collection<Resource> subscriptionItems = graph.syncRequest(new ObjectsWithType(parameter, L0.ConsistsOf, MOD.Subscription_Item));
199 if (subscriptionItems.isEmpty())
200 return Collections.emptyMap();
202 Map<String, SubscriptionItem> result = new THashMap<>(subscriptionItems.size());
203 for (Resource subscriptionItem : subscriptionItems) {
204 SubscriptionItem hi = graph.syncRequest(
205 new ItemRequest(subscriptionItem, parameter2, parameter3),
206 TransientCacheListener.<SubscriptionItem>instance());
208 result.put(hi.id, hi);
212 System.out.println("DEBUG: CollectSubscriptions.SubscriptionItemsRequest(" + NameUtils.getSafeName(graph, parameter, true) + ") DONE in " + ((System.nanoTime() - start)*1e-6) + " ms with " + result.size() + " items");
219 static class ItemRequest extends TernaryRead<Resource, String, Param, SubscriptionItem> {
221 public ItemRequest(Resource item, String groupId, Param constants) {
222 super(item, groupId, constants);
226 public SubscriptionItem perform(ReadGraph graph) throws DatabaseException {
227 ModelingResources MOD = ModelingResources.getInstance(graph);
228 Resource subscriptionItem = parameter;
229 String groupId = parameter2;
230 Param constants = parameter3;
231 Variable configurationContext = (Variable) constants.c0;
232 Variable experimentContext = (Variable) constants.c1;
233 double defaultSamplingInterval = (double) constants.c2;
235 Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class );
236 RVI rvi = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_VariableId, rviBinding);
238 //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' is missing RVI property"));
242 Layer0 L0 = Layer0.getInstance(graph);
243 String guid = graph.getPossibleRelatedValue(subscriptionItem, L0.HasName);
245 //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' has no name (ID)."));
248 String variablePersistentId = rvi.toString();
249 Pair<Variable, Variable> variable = Variables.resolvePossible(graph, rvi, configurationContext, experimentContext);
250 if (variable == null) {
252 System.out.println("DEBUG: unresolvable subscription: " + variablePersistentId);
253 // Don't log these, these problems are conveyed to the
254 // user through model browser UI labels.
255 //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' variable cannot be resolved from RVI " + rvi.toString(graph)));
258 String variableId = rvi.asPossibleString(graph, variable.second);
259 //System.out.println("DEBUG: " + variablePersistentId + " - " + variableId);
260 if (variableId == null) {
264 Datatype type = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Datatype, Bindings.getBindingUnchecked(Datatype.class));
265 if (type == null && variable != null) {
266 type = variable.first.getPossibleDatatype(graph);
269 //status.add(new Status(IStatus.WARNING, ModelHistoryCollector.BUNDLE_ID, "Subscription Item '" + NameUtils.getSafeName(graph, subscriptionItem) + "' is missing data type"));
270 // Can't function without a datatype.
274 Double itemSamplingInterval = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_SamplingInterval, Bindings.DOUBLE);
275 Double itemDeadband = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Deadband, Bindings.DOUBLE);
277 Double bias = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Bias, Bindings.DOUBLE);
278 Double gain = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Gain, Bindings.DOUBLE);
279 String unit = graph.getPossibleRelatedValue(subscriptionItem, MOD.Subscription_Item_Unit, Bindings.STRING);
281 double samplingInterval = itemSamplingInterval != null ? itemSamplingInterval : defaultSamplingInterval;
282 double deadband = itemDeadband != null ? itemDeadband : 0.0;
284 SubscriptionItem item = new SubscriptionItem();
286 // HACK: use id for storing the name of the item
287 // Assumption: subscription item's name is unique within the model
290 item.variableId = variableId;
291 item.groupId = groupId;
292 item.groupItemId = variablePersistentId;
293 // HACK: use format for storing the data type of the item
295 // HACK: use formatId for storing the unit of the item,
296 // empty unit is interpreted to mean "no unit" because
297 // formatId cannot be null.
298 item.formatId = unit == null ? "" : unit;
300 // Subscription parameters
301 item.deadband = deadband;
302 item.interval = samplingInterval;
303 if (bias != null) item.bias = bias;
304 if (gain != null) item.gain = gain;
307 //System.out.println("DEBUG: ItemRequest(" + parameter + ", " + parameter2.getURI(graph) + ", " + parameter3 + ")\n\t= " + item);
308 System.out.println("DEBUG: ItemRequest(" + parameter + ", " + parameter2 + ", " + parameter3 + ")\n\t= " + item);