From 3af596efed59d266bf33c44e9eac914ce123a3d2 Mon Sep 17 00:00:00 2001 From: lempinen Date: Thu, 1 Dec 2011 07:44:31 +0000 Subject: [PATCH] Array variables working in charts git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@23381 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/ui/trend/chart/XYDataset.java | 118 +++--- .../SysdynDatasetSelectionListener.java | 136 +----- .../sysdyn/adapter/HistoryVariable.java | 389 +++++++++--------- .../sysdyn/adapter/VariableRVIUtils.java | 187 +++++++++ 4 files changed, 463 insertions(+), 367 deletions(-) create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableRVIUtils.java diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/XYDataset.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/XYDataset.java index 339bdc7f..e87cae31 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/XYDataset.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/XYDataset.java @@ -16,6 +16,8 @@ import java.awt.Color; import java.util.ArrayList; import java.util.List; +import javax.swing.SwingUtilities; + import org.jfree.chart.renderer.AbstractRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.general.Dataset; @@ -37,6 +39,7 @@ import org.simantics.modeling.ModelingResources; import org.simantics.operation.Layer0X; import org.simantics.sysdyn.JFreeChartResource; import org.simantics.sysdyn.adapter.SysdynVariableProperties; +import org.simantics.sysdyn.manager.SysdynDataSet; import org.simantics.ui.SimanticsUI; /** @@ -121,7 +124,6 @@ public class XYDataset implements IDataset { @Override public ArrayList perform(ReadGraph graph) throws DatabaseException { - Layer0 l0 = Layer0.getInstance(graph); JFreeChartResource jfree = JFreeChartResource.getInstance(graph); ArrayList series = new ArrayList(); @@ -132,9 +134,6 @@ public class XYDataset implements IDataset { if(rvi == null) continue; - // Get label. If there is no label, rvi is used - String label = graph.getPossibleRelatedValue(r, l0.HasLabel); - if(label == null || label.isEmpty()) label = rvi.substring(1).replace('/', '.'); try { // Get visual properties Integer width = graph.getPossibleRelatedValue(r, jfree.Series_lineWidth, Bindings.INTEGER); @@ -146,41 +145,56 @@ public class XYDataset implements IDataset { if(width == null) width = 1; // Get values - double[] va = v.getPossiblePropertyValue(graph, SysdynVariableProperties.VALUES , Bindings.DOUBLE_ARRAY); - - -// Object o = v.getPossiblePropertyValue(graph, SysdynVariableProperties.ACTIVE_DATASETS , Bindings.VARIANT); -// System.out.println(o); - - // Get domain axis values (time OR other variable) - double[] ta; - if(domainValues != null) { - ta = domainValues; - - // If domainAxis is other than time, parameter values size is different. - if(domainValues.length > va.length) { - double value = va[0]; - va = new double[domainValues.length]; - for(int i = 0; i < domainValues.length; i++) - va[i] = value; +// double[] va = v.getPossiblePropertyValue(graph, SysdynVariableProperties.VALUES , Bindings.DOUBLE_ARRAY); + + + Object object = v.getPossiblePropertyValue(graph, SysdynVariableProperties.ACTIVE_DATASETS , Bindings.VARIANT); + if(object == null || !(object instanceof ArrayList)) + return series; + ArrayList datasets = (ArrayList)object; + for(Object o : datasets) { + if(!(o instanceof SysdynDataSet)) + continue; + + SysdynDataSet dataset = (SysdynDataSet)o; + double[] va = dataset.values; + + // Get domain axis values (time OR other variable) + double[] ta; + if(domainValues != null) { + ta = domainValues; + + // If domainAxis is other than time, parameter values size is different. + if(domainValues.length > va.length) { + double value = va[0]; + va = new double[domainValues.length]; + for(int i = 0; i < domainValues.length; i++) + va[i] = value; + } + + // If domainAxis is a parameter, the domainValues array is too short + if(domainValues.length < va.length && domainValues.length == 2 && domainValues[0] == domainValues[1]) { + double value = domainValues[0]; + ta = new double[va.length]; + for(int i = 0; i < va.length; i++) + ta[i] = value; + } + + } else { + ta = dataset.times; } - // If domainAxis is a parameter, the domainValues array is too short - if(domainValues.length < va.length && domainValues.length == 2 && domainValues[0] == domainValues[1]) { - double value = domainValues[0]; - ta = new double[va.length]; - for(int i = 0; i < va.length; i++) - ta[i] = value; + if(ta!=null && va!=null && (va.length == ta.length)) { + // Add series if everything OK + String name = dataset.name; + if(dataset.result != null && !dataset.result.isEmpty()) + name = name + " : " + dataset.result; + series.add(new TempSeries(name, new double[][] {ta, va}, width, color)); + if(ta.length == 0 || va.length == 0) + System.out.println(dataset.name + " : " + dataset.result + ". Sizes: " + va.length + " and " + ta.length); } - - } else { - ta = v.getPossiblePropertyValue(graph, SysdynVariableProperties.TIMES , Bindings.DOUBLE_ARRAY); } - if(ta!=null && va!=null && (va.length == ta.length)) { - // Add series if everything OK - series.add(new TempSeries(label, new double[][] {ta, va}, width, color)); - } } catch (MissingVariableException e) { // Do nothing, if variable was not found. Move on to the next series } @@ -197,21 +211,27 @@ public class XYDataset implements IDataset { } @Override - public void execute(ArrayList series) { - // Remove all series - for(int i = dataset.getSeriesCount() - 1; i >= 0; i-- ) { - dataset.removeSeries(dataset.getSeriesKey(i)); - } - - // Add found series - for(int i = 0; i < series.size(); i++) { - TempSeries s = series.get(i); - dataset.removeSeries(s.name); - dataset.addSeries(s.name, s.values); - getRenderer().setSeriesStroke(i, new BasicStroke((float)s.width)); - if(s.color != null) - getRenderer().setSeriesPaint(i, s.color); - } + public void execute(final ArrayList series) { + // Modify series in AWT thread to avoid synchronization problems + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + // Remove all series + for(int i = dataset.getSeriesCount() - 1; i >= 0; i-- ) { + dataset.removeSeries(dataset.getSeriesKey(i)); + } + + // Add found series + for(int i = 0; i < series.size(); i++) { + TempSeries s = series.get(i); + dataset.addSeries(s.name, s.values); + getRenderer().setSeriesStroke(i, new BasicStroke((float)s.width)); + if(s.color != null) + getRenderer().setSeriesPaint(i, s.color); + } + } + }); } @Override diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java index 0359d533..e2d8cdeb 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java @@ -15,7 +15,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Set; @@ -23,24 +22,21 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; -import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; -import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.SelectionHints; import org.simantics.db.layer0.exception.MissingVariableException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingUtils; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.sysdyn.JFreeChartResource; import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.adapter.VariableRVIUtils; import org.simantics.sysdyn.manager.SysdynDataSet; import org.simantics.sysdyn.manager.SysdynModel; import org.simantics.sysdyn.manager.SysdynModelManager; @@ -211,7 +207,6 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen */ protected Collection loadAllActive(ReadGraph g, Variable variable) throws DatabaseException { ArrayList dataSets = new ArrayList(); - HashMap rvis = new LinkedHashMap(); // HashMap // Get variable's rvi and change it to modelica format String rvi; @@ -225,23 +220,8 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen if(rvi.length() > 1) rvi = rvi.substring(1); - Resource r = variable.getPropertyValue(g, Variables.REPRESENTS); - SysdynResource sr = SysdynResource.getInstance(g); - Resource arrayIndexes = g.getPossibleObject(r, sr.HasArrayIndexes); - if(arrayIndexes == null) { - // If variable is single-dimensional, use the same rvi - rvis.put(rvi, rvi); - } else { - // If variable is multidimensional, get all indexes that are active and add them to rvis-map - List arrayIndexList= OrderedSetUtils.toList(g, arrayIndexes); - resolveActiveArrayIndexes(g, variable, arrayIndexList); - - if(arrayIndexList.size() > 0) - traverseIndexes(g, rvi, rvis, arrayIndexList); - else - rvis.put(rvi, rvi); - } + HashMap rvis = VariableRVIUtils.getActiveRVIs(g, variable); Resource modelResource = Variables.getModel(g, variable); SysdynModel model = getSysdynModel(g, modelResource); @@ -253,9 +233,13 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen Collection activeResults = model.getAndUpdateActiveResults(g); for(SysdynResult sysdynResult : activeResults) { for(String currvi : rvis.keySet()) { - SysdynDataSet sds = sysdynResult.getDataSet(currvi); + SysdynDataSet sds = sysdynResult.getDataSet(currvi.substring(1).replace("/", ".")); if(sds != null) { - sds.name = rvis.get(currvi); + try { + sds.name = rvis.get(currvi).substring(1).replace("/", "."); + } catch (NullPointerException e) { + e.printStackTrace(); + } dataSets.add(sds); } } @@ -264,110 +248,6 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen } - /** - * Resolves and replaces all overridden enumerations in enumerations -list - * - * @param graph ReadGraph - * @param variable Selected variable - * @param enumerations List of array indexes of the variable - * @return - */ - private static List resolveActiveArrayIndexes(ReadGraph graph, Variable variable, List enumerations) { - try { - Layer0 l0 = Layer0.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - String uri = variable.getURI(graph); - uri = uri.substring(0, uri.lastIndexOf("/")); - // The parent configuration or module - Variable v = Variables.getPossibleVariable(graph, uri); - if(v != null) { - Variable rp = (Variable)v.getProperty(graph, Variables.REPRESENTS); - Resource module = rp.getValue(graph); - if(module != null && graph.isInheritedFrom(graph.getSingleObject(module, l0.InstanceOf), sr.Module)) { - // If the variable is located in a module, it might have overridden (redeclared) enumerations - boolean somethingIsReplaced = false; - // Find all redeclarations - for(Resource redeclaration : graph.syncRequest(new ObjectsWithType(module, sr.HasRedeclaration, sr.Redeclaration))) { - Resource replaced = graph.getSingleObject(redeclaration, sr.ReplacedEnumeration); - if(enumerations.contains(replaced)) { - // Replace the redelcared enumeration in enumerations -list with the replacing enumeration - enumerations.add(enumerations.indexOf(replaced), graph.getSingleObject(redeclaration, sr.ReplacingEnumeration)); - enumerations.remove(replaced); - somethingIsReplaced = true; - } - } - - if(somethingIsReplaced) { - // If something was replaced, do the same again for the parent configuration. The - // enumerations may be replaced throughout the whole model hierarchy - resolveActiveArrayIndexes(graph, v, enumerations); - } - } - } - } catch (DatabaseException e) { - e.printStackTrace(); - - } - return enumerations; - } - - /** - * Recursive function for finding number format and label for the set of rvis. (rvis.put("Variable[1]", "Variable[index1]"); - * At the end of the recursive calls, rvis contains all possible combinations of enumeration indexes that are - * set to be shown in charts - * - * @param g ReadGraph - * @param rvi RVI of the variable - * @param rvis RVI map containing the full rvi with enumerations. Key contains numerical - * value of the enumeration and value contains the name of the enumeration (e.g. ["Variable[1]", "Variable[index1]"]) - * @param arrayIndexes ArrayIndex resources, Enumerations. - * @throws DatabaseException - */ - private void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes) throws DatabaseException { - traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(0), "", ""); - } - - /** - * Recursive function for finding number format and label for the set of rvis. (rvis.put("Variable[1]", "Variable[index1]"); - * At the end of the recursive calls, rvis contains all possible combinations of enumeration indexes that are - * set to be shown in charts - * - * @param g ReadGraph - * @param rvi RVI of the variable - * @param rvis RVI map containing the full rvi with enumerations. Key contains numerical - * @param arrayIndexes ArrayIndex resources, Enumerations. - * @param currentEnumeration Currently evaluated enumeration index (in arrayIndexes list) - * @param indexesSoFar String representation of the indexes so far in numerical format - * @param indexNamesSoFar String representation of the indexes so far in name format - * @throws DatabaseException - */ - private void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes, Resource currentEnumeration, String indexesSoFar, String indexNamesSoFar) throws DatabaseException { - SysdynResource sr = SysdynResource.getInstance(g); - // Enumeration indexes of the current enumeration (e.g. the first EnumIndexes in Var[EnumIndexes, EnumIndexes, EnumIndexes]) - Resource enumerationIndexes = g.getPossibleObject(currentEnumeration, sr.HasEnumerationIndexes); - if(enumerationIndexes == null) - return; - List indexes = OrderedSetUtils.toList(g, enumerationIndexes); - for(int i = 0; i < indexes.size(); i++) { - Boolean b = g.getPossibleRelatedValue(indexes.get(i), sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); - // If this index is not wanted to be shown in charts, the recursion does not go any further and rvis.put() is not called for this enumeration - if(Boolean.TRUE.equals(b)) { - int arrayIndex = arrayIndexes.indexOf(currentEnumeration); - // Get the name of the index - String name = g.getRelatedValue(indexes.get(i), Layer0.getInstance(g).HasName); - if(arrayIndex < arrayIndexes.size() - 1) - // If there are still more EnumIndexes, recursively call the function and add current index to indexesSoFar and indexNamesSoFar - traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(arrayIndex + 1), - indexesSoFar + (i + 1) +",", indexNamesSoFar + (name) +","); - else { - // The last enumeration. Add [rvi[1, 1, 1] = rvi[index1, index1, index1]}and so on to the rvis map - rvis.put( - rvi + "[" + indexesSoFar + (i + 1) + "]", - rvi + "[" + indexNamesSoFar + (name) + "]"); - } - } - } - } /** * Find a variable representing element diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/HistoryVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/HistoryVariable.java index 150d6b32..e77511bc 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/HistoryVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/HistoryVariable.java @@ -13,6 +13,7 @@ package org.simantics.sysdyn.adapter; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Map; import org.simantics.databoard.Accessors; @@ -58,197 +59,201 @@ import org.simantics.sysdyn.manager.SysdynResult; public class HistoryVariable extends ChildVariable implements PropertyProvider { static Boolean DEBUG = false; - - SysdynExperiment experiment; - SysdynModel model = null; - String rvi = null; - + + private SysdynExperiment experiment; + private SysdynModel model = null; + private String rvi = null; + private HashMap rvis = null; + /** * Variable representing a variable with some history (active experiment) * * @param parent Parent variable * @param resource Resource that the variable represents */ - public HistoryVariable(Variable parent, Resource resource) { - super(parent, resource); - experiment = SysdynExperiment.INSTANCE; - } - - - @SuppressWarnings("unchecked") - @Override - public T getInterface(ReadGraph graph, Class clazz) throws DatabaseException { - /* - * Implementation for OperatingInterfaces (and Tacton integration?) - * Should get rid of this and use only properties. - */ - if(RecordAccessor.class.equals(clazz) || Accessor.class.equals(clazz)) { - SimulationResource SIMU = SimulationResource.getInstance(graph); - Resource model = Variables.getModel(graph, this); - Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration); - final SysdynModel sm = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); - SysdynResult sr = new SysdynResult(sm.getSimulationResult()); // TODO: copy or not to copy ... - - String tmp = Variables.getRVI(graph, this); - if(DEBUG) - System.out.println("HistoryVariable rvi='" + tmp + "'"); - final String rvi = tmp.substring(1).replace("/", "."); - SysdynDataSet ds = sr.getDataSet(rvi); - if(ds == null) ds = new SysdynDataSet("", "", new double[0], new double[0]); // We need a dataset, so if not set, create it - try { - final RecordAccessor ac = (RecordAccessor)Accessors.getAccessor(Bindings.getBindingUnchecked(SysdynDataSet.class), ds); - - sm.addResultListener(new Runnable() { // FIXME: remove listener at some point.. - @Override - public void run() { - if(HistoryVariable.this.experiment.getState().equals(ExperimentState.DISPOSED)) - return; - - SysdynResult sr = new SysdynResult(sm.getSimulationResult()); - SysdynDataSet ds = sr.getDataSet(rvi); - if(ds == null) return; - try { - if(ds.result == null) ds.result = ""; - ac.setValue(Bindings.getBindingUnchecked(SysdynDataSet.class), ds); - } catch (RuntimeBindingConstructionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (AccessorException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - }}); - return (T)ac; - } catch (RuntimeBindingConstructionException e) { - e.printStackTrace(); - } catch (AccessorConstructionException e) { - e.printStackTrace(); - } - return null; - - } - return super.getInterface(graph, clazz); - } - - @Override - public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException { - try { - return getChild(graph, name); - } catch (DatabaseException e) { - return null; - } - } - - @Override - public Variable getChild(ReadGraph graph, String name) throws DatabaseException { + public HistoryVariable(Variable parent, Resource resource) { + super(parent, resource); + experiment = SysdynExperiment.INSTANCE; + } + + + @SuppressWarnings("unchecked") + @Override + public T getInterface(ReadGraph graph, Class clazz) throws DatabaseException { + /* + * Implementation for OperatingInterfaces (and Tacton integration?) + * Should get rid of this and use only properties. + */ + if(RecordAccessor.class.equals(clazz) || Accessor.class.equals(clazz)) { + SimulationResource SIMU = SimulationResource.getInstance(graph); + Resource model = Variables.getModel(graph, this); + Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration); + final SysdynModel sm = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); + SysdynResult sr = new SysdynResult(sm.getSimulationResult()); // TODO: copy or not to copy ... + + String tmp = Variables.getRVI(graph, this); + if(DEBUG) + System.out.println("HistoryVariable rvi='" + tmp + "'"); + final String rvi = tmp.substring(1).replace("/", "."); + SysdynDataSet ds = sr.getDataSet(rvi); + if(ds == null) ds = new SysdynDataSet("", "", new double[0], new double[0]); // We need a dataset, so if not set, create it + try { + final RecordAccessor ac = (RecordAccessor)Accessors.getAccessor(Bindings.getBindingUnchecked(SysdynDataSet.class), ds); + + sm.addResultListener(new Runnable() { // FIXME: remove listener at some point.. + @Override + public void run() { + if(HistoryVariable.this.experiment.getState().equals(ExperimentState.DISPOSED)) + return; + + SysdynResult sr = new SysdynResult(sm.getSimulationResult()); + SysdynDataSet ds = sr.getDataSet(rvi); + if(ds == null) return; + try { + if(ds.result == null) ds.result = ""; + ac.setValue(Bindings.getBindingUnchecked(SysdynDataSet.class), ds); + } catch (RuntimeBindingConstructionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (AccessorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }}); + return (T)ac; + } catch (RuntimeBindingConstructionException e) { + e.printStackTrace(); + } catch (AccessorConstructionException e) { + e.printStackTrace(); + } + return null; + + } + return super.getInterface(graph, clazz); + } + + @Override + public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException { + try { + return getChild(graph, name); + } catch (DatabaseException e) { + return null; + } + } + + @Override + public Variable getChild(ReadGraph graph, String name) throws DatabaseException { // If the variable represents a module, it may have children - SysdynResource sr = SysdynResource.getInstance(graph); - Layer0 l0 = Layer0.getInstance(graph); - Resource instanceOf = graph.getSingleObject(this.resource, l0.InstanceOf); - if(graph.isInheritedFrom(instanceOf, sr.Module)) { - // Find the configuration of the module - StructuralResource2 sr2 = StructuralResource2.getInstance(graph); - if(instanceOf == null) - throw new MissingVariableException("No instanceof for resource " + NameUtils.getSafeName(graph, resource)); - Resource configuration = graph.getPossibleObject(instanceOf, sr2.IsDefinedBy); - if(configuration == null) - throw new MissingVariableException("No configuration for " + NameUtils.getSafeName(graph, instanceOf)); - // Get the components in the configuration and find the child - Map children = graph.syncRequest(new UnescapedChildMapOfResource(configuration)); - Resource child = children.get(name); - return graph.adaptContextual(child, this, Variable.class, Variable.class); - } else { - return super.getChild(graph, name); - } - } + SysdynResource sr = SysdynResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + Resource instanceOf = graph.getSingleObject(this.resource, l0.InstanceOf); + if(graph.isInheritedFrom(instanceOf, sr.Module)) { + // Find the configuration of the module + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + if(instanceOf == null) + throw new MissingVariableException("No instanceof for resource " + NameUtils.getSafeName(graph, resource)); + Resource configuration = graph.getPossibleObject(instanceOf, sr2.IsDefinedBy); + if(configuration == null) + throw new MissingVariableException("No configuration for " + NameUtils.getSafeName(graph, instanceOf)); + // Get the components in the configuration and find the child + Map children = graph.syncRequest(new UnescapedChildMapOfResource(configuration)); + Resource child = children.get(name); + return graph.adaptContextual(child, this, Variable.class, Variable.class); + } else { + return super.getChild(graph, name); + } + } - @Override - public Collection browseChildren(ReadGraph graph) throws DatabaseException { + @Override + public Collection browseChildren(ReadGraph graph) throws DatabaseException { // If the variable represents a module, it may have children - SysdynResource sr = SysdynResource.getInstance(graph); - StructuralResource2 sr2 = StructuralResource2.getInstance(graph); - Layer0 l0 = Layer0.getInstance(graph); - Resource instanceOf = graph.getPossibleObject(this.resource, l0.InstanceOf); - if(graph.isInheritedFrom(instanceOf, sr.Module)) { - ArrayList result = new ArrayList(); - if(instanceOf == null) - return result; - // Find the configuration of the model - Resource configuration = graph.getPossibleObject(instanceOf, sr2.IsDefinedBy); - if(configuration == null) - return result; - // Add all children to the result - for(Resource child : graph.syncRequest(new UnescapedChildMapOfResource(configuration)).values()) - result.add(graph.adaptContextual(child, this, Variable.class, Variable.class)); - return result; - } else { - return super.browseChildren(graph); - } - } - - @Override - public Variable getPossibleExtraProperty(ReadGraph graph, String name) throws DatabaseException { - if(SysdynVariableProperties.TIME.equals(name)) { - // Get current time - return graph.syncRequest(new PropertyRequest(this, name)); - } else if(SysdynVariableProperties.VALUES.equals(name) || SysdynVariableProperties.TIMES.equals(name) || - SysdynVariableProperties.ACTIVE_DATASETS.equals(name)) { - // For these requests, we need to make sure that model and rvi exist - if(model == null) { - SimulationResource SIMU = SimulationResource.getInstance(graph); - Resource modelResource = Variables.getModel(graph, this); - Resource configuration = graph.getPossibleObject(modelResource, SIMU.HasConfiguration); - model = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); - // Update active results - model.getAndUpdateActiveResults(graph); - } - if(rvi == null) { - rvi = Variables.getRVI(graph, this).substring(1).replace("/", "."); - } - if(SysdynVariableProperties.TIMES.equals(name)) - // If times were requested, just return them without listening - return getProperty(name); - else - // Otherwise make a request and listen for changes in the result - return graph.syncRequest(new PropertyRequest(this, name)); - } - return super.getPossibleExtraProperty(graph, name); - } - - /** - * Register a property subscription - * - * @param request PropertyRequest - * @param procedure - * @param property Name of the requested property - * @return - */ - protected VariableValueSubscription registerSubscription(ExternalRead request, Listener procedure, String property) { - if(SysdynVariableProperties.TIME.equals(property) && experiment instanceof SysdynPlaybackExperiment) { - // Current time is requested from experiment - VariableValueSubscription subscription = new VariableValueSubscription(request, this, property, procedure); - experiment.addVariableValueSubscription(subscription); - subscription.update(); - return subscription; - } else if(model != null && ( - SysdynVariableProperties.VALUES.equals(property) || - SysdynVariableProperties.TIMES.equals(property) || - SysdynVariableProperties.ACTIVE_DATASETS.equals(property))) { - // Other properties are requested from model (they listen to new simulation results) - VariableValueSubscription subscription = new VariableValueSubscription(request, this, property, procedure); - model.addVariableValueSubscription(subscription); - subscription.update(); - return subscription; + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + Resource instanceOf = graph.getPossibleObject(this.resource, l0.InstanceOf); + if(graph.isInheritedFrom(instanceOf, sr.Module)) { + ArrayList result = new ArrayList(); + if(instanceOf == null) + return result; + // Find the configuration of the model + Resource configuration = graph.getPossibleObject(instanceOf, sr2.IsDefinedBy); + if(configuration == null) + return result; + // Add all children to the result + for(Resource child : graph.syncRequest(new UnescapedChildMapOfResource(configuration)).values()) + result.add(graph.adaptContextual(child, this, Variable.class, Variable.class)); + return result; } else { - return null; - } - } + return super.browseChildren(graph); + } + } + + @Override + public Variable getPossibleExtraProperty(ReadGraph graph, String name) throws DatabaseException { + if(SysdynVariableProperties.TIME.equals(name)) { + // Get current time + return graph.syncRequest(new PropertyRequest(this, name)); + } else if(SysdynVariableProperties.VALUES.equals(name) || SysdynVariableProperties.TIMES.equals(name) || + SysdynVariableProperties.ACTIVE_DATASETS.equals(name)) { + // For these requests, we need to make sure that model and rvi exist + if(model == null) { + SimulationResource SIMU = SimulationResource.getInstance(graph); + Resource modelResource = Variables.getModel(graph, this); + Resource configuration = graph.getPossibleObject(modelResource, SIMU.HasConfiguration); + model = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); + // Update active results + model.getAndUpdateActiveResults(graph); + } + if(rvi == null) { + rvi = Variables.getRVI(graph, this).substring(1).replace("/", "."); + } + + rvis = VariableRVIUtils.getActiveRVIs(graph, this); + + if(SysdynVariableProperties.TIMES.equals(name)) + // If times were requested, just return them without listening + return getProperty(name); + else + // Otherwise make a request and listen for changes in the result + return graph.syncRequest(new PropertyRequest(this, name)); + } + return super.getPossibleExtraProperty(graph, name); + } + + /** + * Register a property subscription + * + * @param request PropertyRequest + * @param procedure + * @param property Name of the requested property + * @return + */ + protected VariableValueSubscription registerSubscription(ExternalRead request, Listener procedure, String property) { + if(SysdynVariableProperties.TIME.equals(property) && experiment instanceof SysdynPlaybackExperiment) { + // Current time is requested from experiment + VariableValueSubscription subscription = new VariableValueSubscription(request, this, property, procedure); + experiment.addVariableValueSubscription(subscription); + subscription.update(); + return subscription; + } else if(model != null && ( + SysdynVariableProperties.VALUES.equals(property) || + SysdynVariableProperties.TIMES.equals(property) || + SysdynVariableProperties.ACTIVE_DATASETS.equals(property))) { + // Other properties are requested from model (they listen to new simulation results) + VariableValueSubscription subscription = new VariableValueSubscription(request, this, property, procedure); + model.addVariableValueSubscription(subscription); + subscription.update(); + return subscription; + } else { + return null; + } + } - /** - * Unregisters a subscription - * @param subscription - */ + /** + * Unregisters a subscription + * @param subscription + */ protected void unregisterSubscription(VariableValueSubscription subscription) { subscription.setListener(null); if(SysdynVariableProperties.TIME.equals(subscription.property)) @@ -280,8 +285,8 @@ public class HistoryVariable extends ChildVariable implements PropertyProvider { return new ConstantPropertyVariable(this, name, new double[0], Datatypes.DOUBLE_ARRAY); else return new ConstantPropertyVariable(this, name, ds.values, Datatypes.DOUBLE_ARRAY); - } else if(SysdynVariableProperties.TIMES.equals(name)) { - // Get the times of this variable from the currently active experiment + } else if(SysdynVariableProperties.TIMES.equals(name)) { + // Get the times of this variable from the currently active experiment SysdynResult sr = new SysdynResult(model.getSimulationResult()); SysdynDataSet ds = sr.getDataSet(rvi); if(ds == null) @@ -292,16 +297,20 @@ public class HistoryVariable extends ChildVariable implements PropertyProvider { // Get all active datasets for this variable (currentyl active experiment and all active saved results) Collection activeResults = model.getActiveResults(); ArrayList result = new ArrayList(); - for(SysdynResult sr : activeResults) { - DataSet ds = sr.getDataSet(rvi); - if(ds != null) - result.add(ds); + for(SysdynResult sysdynResult : activeResults) { + for(String currvi : rvis.keySet()) { + SysdynDataSet sds = sysdynResult.getDataSet(currvi.substring(1).replace("/", ".")); + if(sds != null) { + sds.name = rvis.get(currvi).substring(1).replace("/", "."); + result.add(sds); + } + } } return new ConstantPropertyVariable(this, name, result, Datatypes.VARIANT); } return null; } - + /** * Class for supporting requests with different property parameters. Equals-method has been modified * from ParametrizedPrivimiteRead to check also the property value. @@ -312,14 +321,14 @@ public class HistoryVariable extends ChildVariable implements PropertyProvider { class PropertyRequest extends ParametrizedPrimitiveRead { String property; - + public PropertyRequest(Variable parameter, String property) { super(parameter); this.property = property; } VariableValueSubscription subscription; - + @Override public void register(Listener procedure) { subscription = registerSubscription(this, procedure, property); @@ -329,7 +338,7 @@ public class HistoryVariable extends ChildVariable implements PropertyProvider { unregisterSubscription(subscription); subscription = null; } - + @Override public boolean equals(Object object) { if(object instanceof PropertyRequest && super.equals(object)) { @@ -338,6 +347,6 @@ public class HistoryVariable extends ChildVariable implements PropertyProvider { return super.equals(object); } } - + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableRVIUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableRVIUtils.java new file mode 100644 index 00000000..32a0bc2b --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableRVIUtils.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.sysdyn.adapter; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.layer0.Layer0; +import org.simantics.sysdyn.SysdynResource; + +/** + * Utils for finding all active rvis for a single variable. A variable can have multiple + * rvis, if it is an array variable. Active rvis can be limited using a boolean value sr.ShowEnumerationIndexInCharts + * + * Example rvis for a variable with two enumerations (/ModuleInstance1/ModuleInstance2/Variable[Enumeration, Enumeration2]): + * + * /ModuleInstance1/ModuleInstance2/Variable[index1, index1] + * /ModuleInstance1/ModuleInstance2/Variable[index1, index2] + * /ModuleInstance1/ModuleInstance2/Variable[index2, index1] + * /ModuleInstance1/ModuleInstance2/Variable[index2, index2] + * + * + * + * @author Teemu Lempinen + * + */ +public class VariableRVIUtils { + + /** + * Recursive function for finding number format and label for the set of rvis. (rvis.put("Variable[1]", "Variable[index1]"); + * At the end of the recursive calls, rvis contains all possible combinations of enumeration indexes that are + * set to be shown in charts + * + * @param g ReadGraph + * @param rvi RVI of the variable + * @param rvis RVI map containing the full rvi with enumerations. Key contains numerical + * value of the enumeration and value contains the name of the enumeration (e.g. ["Variable[1]", "Variable[index1]"]) + * @param arrayIndexes ArrayIndex resources, Enumerations. + * @throws DatabaseException + */ + private static void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes) throws DatabaseException { + traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(0), "", ""); + } + + /** + * Recursive function for finding number format and label for the set of rvis. (rvis.put("Variable[1]", "Variable[index1]"); + * At the end of the recursive calls, rvis contains all possible combinations of enumeration indexes that are + * set to be shown in charts + * + * @param g ReadGraph + * @param rvi RVI of the variable + * @param rvis RVI map containing the full rvi with enumerations. Key contains numerical + * @param arrayIndexes ArrayIndex resources, Enumerations. + * @param currentEnumeration Currently evaluated enumeration index (in arrayIndexes list) + * @param indexesSoFar String representation of the indexes so far in numerical format + * @param indexNamesSoFar String representation of the indexes so far in name format + * @throws DatabaseException + */ + private static void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes, Resource currentEnumeration, String indexesSoFar, String indexNamesSoFar) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + // Enumeration indexes of the current enumeration (e.g. the first EnumIndexes in Var[EnumIndexes, EnumIndexes, EnumIndexes]) + Resource enumerationIndexes = g.getPossibleObject(currentEnumeration, sr.HasEnumerationIndexes); + if(enumerationIndexes == null) + return; + List indexes = OrderedSetUtils.toList(g, enumerationIndexes); + for(int i = 0; i < indexes.size(); i++) { + Boolean b = g.getPossibleRelatedValue(indexes.get(i), sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); + // If this index is not wanted to be shown in charts, the recursion does not go any further and rvis.put() is not called for this enumeration + if(Boolean.TRUE.equals(b)) { + int arrayIndex = arrayIndexes.indexOf(currentEnumeration); + // Get the name of the index + String name = g.getRelatedValue(indexes.get(i), Layer0.getInstance(g).HasName); + if(arrayIndex < arrayIndexes.size() - 1) + // If there are still more EnumIndexes, recursively call the function and add current index to indexesSoFar and indexNamesSoFar + traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(arrayIndex + 1), + indexesSoFar + (i + 1) +",", indexNamesSoFar + (name) +","); + else { + // The last enumeration. Add [rvi[1, 1, 1] = rvi[index1, index1, index1]}and so on to the rvis map + rvis.put( + rvi + "[" + indexesSoFar + (i + 1) + "]", + rvi + "[" + indexNamesSoFar + (name) + "]"); + } + } + } + } + + /** + * Resolves and replaces all overridden enumerations in enumerations -list + * + * @param graph ReadGraph + * @param variable Selected variable + * @param enumerations List of array indexes of the variable + * @return + */ + private static List resolveActiveArrayIndexes(ReadGraph graph, Variable variable, List enumerations) { + try { + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + String uri = variable.getURI(graph); + uri = uri.substring(0, uri.lastIndexOf("/")); + // The parent configuration or module + Variable v = Variables.getPossibleVariable(graph, uri); + if(v != null) { + Variable rp = (Variable)v.getProperty(graph, Variables.REPRESENTS); + Resource module = rp.getValue(graph); + if(module != null && graph.isInheritedFrom(graph.getSingleObject(module, l0.InstanceOf), sr.Module)) { + // If the variable is located in a module, it might have overridden (redeclared) enumerations + boolean somethingIsReplaced = false; + // Find all redeclarations + for(Resource redeclaration : graph.syncRequest(new ObjectsWithType(module, sr.HasRedeclaration, sr.Redeclaration))) { + Resource replaced = graph.getSingleObject(redeclaration, sr.ReplacedEnumeration); + if(enumerations.contains(replaced)) { + // Replace the redelcared enumeration in enumerations -list with the replacing enumeration + enumerations.add(enumerations.indexOf(replaced), graph.getSingleObject(redeclaration, sr.ReplacingEnumeration)); + enumerations.remove(replaced); + somethingIsReplaced = true; + } + } + + if(somethingIsReplaced) { + // If something was replaced, do the same again for the parent configuration. The + // enumerations may be replaced throughout the whole model hierarchy + resolveActiveArrayIndexes(graph, v, enumerations); + } + } + } + } catch (DatabaseException e) { + e.printStackTrace(); + + } + return enumerations; + } + + + /** + * Returns rvis in a map in format /ModuleInstance/Variable[1] = /ModuleInstance/Variable[index1] + * @param graph ReadGraph + * @param variable Variable for the rvis + * @return rvis in a map. Keys are numerical formatted array indexes and values are textual. + * @throws DatabaseException + */ + public static HashMap getActiveRVIs(ReadGraph graph, Variable variable) throws DatabaseException { + HashMap rvis = new LinkedHashMap(); + + SysdynResource sr = SysdynResource.getInstance(graph); + + String rvi = Variables.getRVI(graph, variable); + + Resource r = variable.getPropertyValue(graph, Variables.REPRESENTS); + + Resource arrayIndexes = graph.getPossibleObject(r, sr.HasArrayIndexes); + if(arrayIndexes == null) { + // If variable is single-dimensional, use the same rvi + rvis.put(rvi, rvi); + } else { + // If variable is multidimensional, get all indexes that are active and add them to rvis-map + List arrayIndexList= OrderedSetUtils.toList(graph, arrayIndexes); + resolveActiveArrayIndexes(graph, variable, arrayIndexList); + + if(arrayIndexList.size() > 0) + traverseIndexes(graph, rvi, rvis, arrayIndexList); + else + rvis.put(rvi, rvi); + } + + return rvis; + } + +} -- 2.47.1