From: lempinen Date: Tue, 24 Aug 2010 07:53:30 +0000 (+0000) Subject: Model browser's configuration is based on realization. Each variable know their path... X-Git-Tag: simantics-1.2.0~87 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=9a4fb977b69c24ab4ad5a97a5bb3823a582b144d;p=simantics%2Fsysdyn.git Model browser's configuration is based on realization. Each variable know their path/uri, so they can be shown on the trend view. git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@17492 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn.ui/adapters.xml b/org.simantics.sysdyn.ui/adapters.xml index 93d76d28..ea0799dc 100644 --- a/org.simantics.sysdyn.ui/adapters.xml +++ b/org.simantics.sysdyn.ui/adapters.xml @@ -16,5 +16,5 @@ - none 0 fill 1 + none 0 fill 1 \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index 5992bf10..544b4155 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -453,7 +453,7 @@ + class="org.simantics.sysdyn.ui.browser.contributions.Configuration" + preference="2.0"> diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/BrowserSelection.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/BrowserSelection.java new file mode 100644 index 00000000..f30b8008 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/BrowserSelection.java @@ -0,0 +1,32 @@ +package org.simantics.sysdyn.ui.browser; + +import org.eclipse.core.runtime.IAdaptable; +import org.simantics.db.Resource; + +public class BrowserSelection implements IAdaptable { + private Resource resource; + private Resource model; + private String URI; + + public BrowserSelection(Resource resource, String URI, Resource model) { + this.resource = resource; + this.URI = URI; + this.model = model; + } + + @Override + public Object getAdapter(Class adapter) { + if (adapter == Resource.class) + return resource; + return null; + } + + public Resource getModel() { + return this.model; + } + + public String getURI() { + return this.URI; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java index 181d0505..032328a8 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java @@ -17,12 +17,22 @@ import java.util.HashSet; import java.util.Set; import org.eclipse.swt.widgets.Composite; +import org.simantics.browsing.ui.GraphExplorer; +import org.simantics.browsing.ui.NodeContext; +import org.simantics.browsing.ui.swt.AdaptableHintContext; import org.simantics.browsing.ui.swt.ContextMenuInitializer; +import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver; +import org.simantics.browsing.ui.swt.GraphExplorerFactory; import org.simantics.browsing.ui.swt.GraphExplorerView; import org.simantics.browsing.ui.swt.IContextMenuInitializer; import org.simantics.browsing.ui.swt.IPropertyPage; +import org.simantics.db.Resource; +import org.simantics.db.layer0.SelectionHints; import org.simantics.sysdyn.ui.Activator; +import org.simantics.sysdyn.ui.browser.nodes.VariableNode; import org.simantics.sysdyn.ui.properties.SysdynPropertyPage; +import org.simantics.utils.datastructures.BinaryFunction; +import org.simantics.utils.datastructures.hints.IHintContext; public class SysdynBrowser extends GraphExplorerView { @@ -30,6 +40,37 @@ public class SysdynBrowser extends GraphExplorerView { // private static final Set browseContexts = Collections.singleton("http://www.simantics.org/Sysdyn-1.0/Browser"); private static final Set browseContexts = new HashSet(Arrays.asList("http://www.simantics.org/Sysdyn-1.0/Browser", "http://www.simantics.org/Operating-1.0/Browser")); + private BinaryFunction selectionTransformation = new BinaryFunction() { + + @Override + public Object[] call(GraphExplorer explorer, Object[] objects) { + Object[] result = new Object[objects.length]; + for (int i = 0; i < objects.length; i++) { + + NodeContext ctx = (NodeContext)objects[i]; + @SuppressWarnings("unchecked") + VariableNode vn = (VariableNode) ctx.getAdapter(VariableNode.class); + IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN); + if(vn != null) { + Resource resource = vn.getResource() == null ? vn.data : vn.getResource(); + context.setHint(SelectionHints.KEY_MAIN, new BrowserSelection(resource, vn.getURI(), vn.getModel())); + } else { + context.setHint(SelectionHints.KEY_MAIN, objects[i]); + } + result[i] = context; + } + return result; + } + + }; + + protected GraphExplorer createExplorerControl(Composite parent) { + return GraphExplorerFactory.getInstance() + .selectionDataResolver(new DefaultSelectionDataResolver()) + .selectionTransformation(selectionTransformation) + .create(parent, getStyle()); + } + @Override protected IContextMenuInitializer getContextMenuInitializer() { return new ContextMenuInitializer("#SysdynBrowserPopup"); @@ -51,7 +92,6 @@ public class SysdynBrowser extends GraphExplorerView { //toolBar.add(new HomeAction()); } - @SuppressWarnings("unchecked") @Override public Object getAdapter(Class adapter) { if (adapter == IPropertyPage.class) diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java index 650709b2..ce9230e3 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java @@ -26,7 +26,6 @@ import org.simantics.sysdyn.ui.browser.nodes.ModelNode; import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; import org.simantics.sysdyn.ui.browser.nodes.ModulesNode; -import org.simantics.sysdyn.ui.browser.nodes.OperatingInterfacesFolder; import org.simantics.sysdyn.ui.browser.nodes.VariableNode; public class AbstractNodeImager extends ImagerContributor> { @@ -36,7 +35,6 @@ public class AbstractNodeImager extends ImagerContributor String image = null; if (node instanceof ExperimentsFolder || -// node instanceof OperatingInterfacesFolder || node instanceof ModulesNode) image = "icons/folder.png"; else if (node instanceof ModuleTypeNode || node instanceof ModuleNode || node instanceof ConfigurationNode) diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java index 9f1c4dcf..3016f8e8 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java @@ -8,44 +8,49 @@ import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributo import org.simantics.db.Builtins; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.exception.DatabaseException; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; +import org.simantics.sysdyn.ui.browser.nodes.InputNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; +import org.simantics.sysdyn.ui.browser.nodes.VariableNode; -public class Configuration extends ViewpointContributor { +public class Configuration extends ViewpointContributor> { - @Override - public Collection getContribution(ReadGraph graph, ConfigurationNode configuration) throws DatabaseException { - ArrayList> result = new ArrayList>(); - Builtins b = graph.getBuiltins(); - SysdynResource sr = SysdynResource.getInstance(graph); - for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.data, b.ConsistsOf, sr.IndependentVariable))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.data, b.ConsistsOf, sr.Input))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.data, b.ConsistsOf, sr.Module))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - return result; - } + @Override + public Collection getContribution(ReadGraph graph, ConfigurationNode configuration) throws DatabaseException { + Builtins b = graph.getBuiltins(); + ArrayList> result = new ArrayList>(); + if (!graph.isInheritedFrom(graph.getSingleObject(configuration.data, b.InstanceOf), b.Realization)) + return result; + + SysdynResource sr = SysdynResource.getInstance(graph); + ArrayList variables = new ArrayList(); + ArrayList inputs = new ArrayList(); + ArrayList modules = new ArrayList(); + + for(Resource r : graph.getObjects(configuration.data, b.ConsistsOf)) { + Resource represents = graph.getSingleObject(r, b.Represents); + if(graph.isInstanceOf(represents, sr.IndependentVariable)) { + variables.add(r); + } else if (graph.isInstanceOf(represents, sr.Input)) { + inputs.add(r); + } else if (graph.isInstanceOf(represents, sr.Module)) { + modules.add(r); + } + } + + for (Resource r : variables) + result.add(new VariableNode(r)); + for (Resource r : inputs) + result.add(new InputNode(r)); + for (Resource r : modules) + result.add(new ModuleNode(r)); + return result; + } - @Override - public String getViewpointId() { - return "Standard"; - } + @Override + public String getViewpointId() { + return "Standard"; + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java index 2161aaee..53700ade 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java @@ -13,13 +13,14 @@ package org.simantics.sysdyn.ui.browser.contributions; import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; -public class ConfigurationLabeler extends LabelerContributor{ +public class ConfigurationLabeler extends LabelerContributor>{ @Override - public String getLabel(ReadGraph graph, ConfigurationNode conf) throws DatabaseException { + public String getLabel(ReadGraph graph, ConfigurationNode conf) throws DatabaseException { return "Configuration"; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java index cf9d84a8..307b3eb7 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java @@ -26,7 +26,8 @@ import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; public class Experiment extends ViewpointContributor { - @Override + @SuppressWarnings("unchecked") + @Override public Collection getContribution(ReadGraph graph, ExperimentsFolder experimentsFolder) throws DatabaseException { ArrayList> result = new ArrayList>(); Builtins b = graph.getBuiltins(); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java index 8c946d1f..76d98d4e 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java @@ -7,8 +7,9 @@ import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.request.PossibleObjectWithType; import org.simantics.db.exception.DatabaseException; -import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; import org.simantics.sysdyn.ui.browser.nodes.ModelNode; @@ -20,11 +21,11 @@ public class Model extends ViewpointContributor { public Collection getContribution(ReadGraph graph, ModelNode model) throws DatabaseException { ArrayList> result = new ArrayList>(); - result.add(new ConfigurationNode( - graph.getSingleObject( - model.data, - SimulationResource.getInstance(graph).HasConfiguration)) - ); + + Resource baseRealization = graph.syncRequest(new PossibleObjectWithType(model.data, b.ConsistsOf, SysdynResource.getInstance(graph).DefaultRealization)); + if (baseRealization != null) { + result.add(new ConfigurationNode(baseRealization)); + } result.add(new ExperimentsFolder(model.data)); result.add(new ModulesNode(model.data)); return result; diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java deleted file mode 100644 index 9cbfbc68..00000000 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.simantics.sysdyn.ui.browser.contributions; - -import java.util.ArrayList; -import java.util.Collection; - -import org.simantics.browsing.ui.common.node.AbstractNode; -import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; -import org.simantics.db.Builtins; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.request.ObjectsWithType; -import org.simantics.db.exception.DatabaseException; -import org.simantics.modeling.ModelingResources; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.sysdyn.SysdynResource; -import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; - -public class Module extends ViewpointContributor { - - @Override - public Collection getContribution(ReadGraph graph, ModuleNode module) throws DatabaseException { - ArrayList> result = new ArrayList>(); - Builtins b = graph.getBuiltins(); - SysdynResource sr = SysdynResource.getInstance(graph); - StructuralResource2 str = StructuralResource2.getInstance(graph); - - // ModuleTypeNode extends ModuleNode, so we get the instance in two different ways - Resource instance = graph.getPossibleObject(module.data, b.InstanceOf); - if(graph.isInheritedFrom(module.data, sr.ModuleSymbol)) { - ModelingResources mr = ModelingResources.getInstance(graph); - instance = graph.getPossibleObject(module.data, mr.SymbolToComponentType); - } - - if(instance == null) return result; - Resource conf = graph.getSingleObject(instance, str.IsDefinedBy); - for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.IndependentVariable))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Input))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Module))) { - try { - result.add(graph.adapt(r, AbstractNode.class)); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - return result; - } - - @Override - public String getViewpointId() { - return "Standard"; - } - -} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java new file mode 100644 index 00000000..b47e8d7e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java @@ -0,0 +1,52 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.common.node.AbstractNode; +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.modeling.ModelingResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.InputNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; +import org.simantics.sysdyn.ui.browser.nodes.VariableNode; + +public class ModuleType extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ModuleTypeNode module) throws DatabaseException { + ArrayList> result = new ArrayList>(); + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 str = StructuralResource2.getInstance(graph); + + ModelingResources mr = ModelingResources.getInstance(graph); + Resource instance = graph.getPossibleObject(module.data, mr.SymbolToComponentType); + + if(instance == null) return result; + Resource conf = graph.getSingleObject(instance, str.IsDefinedBy); + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.IndependentVariable))) { + result.add(new VariableNode(r)); + } + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Input))) { + result.add(new InputNode(r)); + } + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Module))) { + result.add(new ModuleNode(r)); + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java index 83acd782..cc763e6c 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java @@ -14,7 +14,8 @@ import org.simantics.sysdyn.SysdynResource; public class Project extends ViewpointContributor { - @Override + @SuppressWarnings("unchecked") + @Override public Collection getContribution(ReadGraph graph, Resource project) throws DatabaseException { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java index ecd79d25..a06e64a5 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java @@ -17,7 +17,8 @@ import org.simantics.sysdyn.ui.browser.nodes.ExperimentNode; public class SimulationResult extends ViewpointContributor { - @Override + @SuppressWarnings("unchecked") + @Override public Collection getContribution(ReadGraph graph, ExperimentNode experiment) throws DatabaseException { ArrayList> result = new ArrayList>(); SysdynResource sr = SysdynResource.getInstance(graph); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java index 24d13e76..7243a539 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java @@ -18,10 +18,10 @@ import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.sysdyn.ui.browser.nodes.VariableNode; -public class VariableLabeler extends LabelerContributor{ +public class VariableLabeler extends LabelerContributor>{ @Override - public String getLabel(ReadGraph graph, VariableNode var) throws DatabaseException { + public String getLabel(ReadGraph graph, VariableNode var) throws DatabaseException { Builtins b = graph.getBuiltins(); Resource varres = var.data; StringBuilder sb = new StringBuilder(); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java index cd1a4335..0499ec61 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java @@ -15,10 +15,10 @@ import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.browsing.ui.common.node.IDeletable; import org.simantics.db.Resource; -public class ConfigurationNode extends AbstractNode implements IDeletable { - - public ConfigurationNode(Resource resource) { - super(resource); +public class ConfigurationNode extends AbstractNode implements IDeletable { + + public ConfigurationNode(final Resource resource) { + super(resource); } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java index 82aa5cae..7575c02d 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java @@ -1,9 +1,8 @@ package org.simantics.sysdyn.ui.browser.nodes; -import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.db.Resource; -public class InputNode extends AbstractNode { +public class InputNode extends VariableNode { public InputNode(Resource resource) { super(resource); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java index 9801d563..7ced9908 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java @@ -18,6 +18,7 @@ import org.simantics.utils.ui.ExceptionUtils; public class ModelNode extends AbstractNode implements IDeletableNode, IModifiableNode { + public ModelNode(Resource resource) { super(resource); } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java index 0a8044ba..00117ddc 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java @@ -1,9 +1,8 @@ package org.simantics.sysdyn.ui.browser.nodes; -import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.db.Resource; -public class ModuleNode extends AbstractNode { +public class ModuleNode extends ConfigurationNode { public ModuleNode(Resource resource) { super(resource); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java index 6e680372..0e024004 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java @@ -22,7 +22,7 @@ import org.simantics.modeling.ModelingResources; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.ui.SimanticsUI; -// FIXME: should extend ModuleNode + public class ModuleTypeNode extends AbstractNode implements IDeletableNode, IModifiableNode { public ModuleTypeNode(Resource resource) { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java index 08ea8b9a..a4f399fe 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java @@ -12,12 +12,73 @@ package org.simantics.sysdyn.ui.browser.nodes; import org.simantics.browsing.ui.common.node.AbstractNode; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; -public class VariableNode extends AbstractNode { +public class VariableNode extends AbstractNode { - public VariableNode(Resource resource) { - super(resource); - } + Resource model = null; + String uri; + Resource resource; + public VariableNode(Resource resource) { + super(resource); + + SimanticsUI.getSession().asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + + VariableNode.this.resource = graph.getPossibleObject(data, b.Represents); + + if(VariableNode.this.resource == null) + return; + + uri = getName(graph); + + // don't search for a parent if the resource is not part of a realization + if(!graph.isInheritedFrom(graph.getSingleObject(data, b.InstanceOf), b.Realization)) + return; + + // search for the model parent and build the uri + Resource parent = graph.getSingleObject(data, b.PartOf); + while (!graph.isInstanceOf(parent, sr.SysdynModel)) { + uri = graph.getRelatedValue(parent, b.HasName) + "/" + uri; + parent = graph.getSingleObject(parent, b.PartOf); + } + // cut out the realization name + System.out.println(uri); + uri = uri.substring(uri.indexOf("/") + 1); + System.out.println(uri); + model = parent; + } + }); + } + + public String getURI() { + return uri; + } + + public Resource getModel() { + return model; + } + + public String getName(ReadGraph graph) throws DatabaseException { + return (String)graph.getRelatedValue(data, graph.getBuiltins().HasName); + } + + public Resource getParent(ReadGraph graph) throws DatabaseException { + return graph.getSingleObject(data, graph.getBuiltins().PartOf); + } + + public Resource getResource() { + return resource; + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java index 2c4c6e09..e425fe1a 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java @@ -1,5 +1,6 @@ package org.simantics.sysdyn.ui.editor; +import org.simantics.db.Builtins; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; @@ -13,55 +14,69 @@ import org.simantics.ui.SimanticsUI; public class OpenDiagramFromConfigurationAdapter extends org.simantics.modeling.ui.diagramEditor.OpenDiagramFromConfigurationAdapter { - private static final String EDITOR_ID = "org.simantics.sysdyn.ui.diagramViewer"; + private static final String EDITOR_ID = "org.simantics.sysdyn.ui.diagramViewer"; - public OpenDiagramFromConfigurationAdapter() { - super(); - } + public OpenDiagramFromConfigurationAdapter() { + super(); + } - @Override - protected String getEditorId() { - return EDITOR_ID; - } + @Override + protected String getEditorId() { + return EDITOR_ID; + } - @Override - public boolean canHandle(ReadGraph g, Resource r) throws DatabaseException { - if(g.isInheritedFrom(r, SysdynResource.getInstance(g).ModuleSymbol)) { - ModelingResources mr = ModelingResources.getInstance(g); - StructuralResource2 sr2 = StructuralResource2.getInstance(g); - Resource componentType = g.getSingleObject(r, mr.SymbolToComponentType); - r = g.getSingleObject(componentType, sr2.IsDefinedBy); - } - return ComponentUtils.compositeHasDiagram(g, r) /*|| ComponentUtils.componentHasDiagram(g, r)*/; - } + @Override + public boolean canHandle(ReadGraph g, Resource r) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + if(g.isInheritedFrom(r, sr.ModuleSymbol)) { + ModelingResources mr = ModelingResources.getInstance(g); + StructuralResource2 sr2 = StructuralResource2.getInstance(g); + Resource componentType = g.getSingleObject(r, mr.SymbolToComponentType); + r = g.getSingleObject(componentType, sr2.IsDefinedBy); + } + Builtins b = g.getBuiltins(); + Resource represents = g.getPossibleObject(r, b.Represents); + if(represents != null){ + if(g.isInstanceOf(represents, sr.Configuration)) { + r = represents; + } + } + return ComponentUtils.compositeHasDiagram(g, r) /*|| ComponentUtils.componentHasDiagram(g, r)*/; + } - @Override - public void openEditor(final Resource r) throws Exception { - Resource configuration = null; - try { - configuration = SimanticsUI.getSession().syncRequest(new Read() { + @Override + public void openEditor(final Resource r) throws Exception { + Resource configuration = null; + try { + configuration = SimanticsUI.getSession().syncRequest(new Read() { - @Override - public Resource perform(ReadGraph graph) throws DatabaseException { - if(graph.isInheritedFrom(r, SysdynResource.getInstance(graph).ModuleSymbol)) { - ModelingResources mr = ModelingResources.getInstance(graph); - StructuralResource2 sr2 = StructuralResource2.getInstance(graph); - Resource componentType = graph.getSingleObject(r, mr.SymbolToComponentType); - Resource configuration = graph.getSingleObject(componentType, sr2.IsDefinedBy); - return configuration; - } - else { - return null; - } - } - }); - } catch (DatabaseException e1) { - e1.printStackTrace(); - } - if (configuration != null) - super.openEditor(configuration); - else - super.openEditor(r); - } + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + if(graph.isInheritedFrom(r, SysdynResource.getInstance(graph).ModuleSymbol)) { + ModelingResources mr = ModelingResources.getInstance(graph); + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + Resource componentType = graph.getSingleObject(r, mr.SymbolToComponentType); + Resource configuration = graph.getSingleObject(componentType, sr2.IsDefinedBy); + return configuration; + } else { + Resource represents = graph.getPossibleObject(r, b.Represents); + if(represents != null && graph.isInstanceOf(represents, SysdynResource.getInstance(graph).Configuration)){ + return represents; + } + else { + return null; + } + } + } + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + if (configuration != null) + super.openEditor(configuration); + else + super.openEditor(r); + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java index b43486c5..d0142956 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java @@ -66,6 +66,12 @@ public class ShortcutTabWidget implements Widget { item = new TableItem(functionTable, SWT.NONE); item.setText("if then else"); item.setData("if then else"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("xidz()"); + item.setData("xidz( number, divisor , x)"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("interpolate()"); + item.setData("interpolate( x, table)"); functions.setControl(functionTable); } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java index d292a61b..6fd478ba 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java @@ -50,229 +50,218 @@ import org.simantics.sysdyn.manager.SysdynDataSet; import org.simantics.sysdyn.manager.SysdynModel; import org.simantics.sysdyn.manager.SysdynModelManager; import org.simantics.sysdyn.manager.SysdynResult; +import org.simantics.sysdyn.ui.browser.BrowserSelection; import org.simantics.ui.SimanticsUI; import org.simantics.utils.ui.ISelectionUtils; import org.simantics.utils.ui.jface.ActiveSelectionProvider; public class TrendView extends ViewPart { - Frame frame; - ChartPanel panel; - SysdynDatasets sysdynDatasets = new SysdynDatasets(); - - - @SuppressWarnings("serial") - class SysdynDatasets extends AbstractXYDataset { - - SysdynDataSet[] sets = new SysdynDataSet[0]; - - public void setDatasets(SysdynDataSet[] sets) { - this.sets = sets; - fireDatasetChanged(); - } - - @Override - public Number getY(int series, int item) { - return sets[series].values[item]; - } - - @Override - public Number getX(int series, int item) { - return sets[series].times[item]; - } - - @Override - public int getItemCount(int series) { - return sets[series].times.length; - } - - @Override - public Comparable getSeriesKey(int series) { - SysdynDataSet sds = sets[series]; - if(sds.result == null) - return sds.name; - else - return sds.name + " : " + sds.result; - } - - @Override - public int getSeriesCount() { - return sets.length; - } - - } - - @Override - public void createPartControl(Composite parent) { - final ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider(); - getSite().setSelectionProvider(selectionProvider); - - final Composite composite = new Composite(parent, - SWT.NO_BACKGROUND | SWT.EMBEDDED); - frame = SWT_AWT.new_Frame(composite); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - XYPlot plot = new XYPlot( - sysdynDatasets, - new NumberAxis("time"), - new NumberAxis("x"), - new XYLineAndShapeRenderer(true, false) - ); - - JFreeChart chart = new JFreeChart(plot); - panel = new ChartPanel(chart); - frame.add(panel); - - panel.requestFocus(); - } - - }); - - getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(new ISelectionListener() { - - @Override - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - if(selection.isEmpty() || Boolean.TRUE.equals(PinTrend.getState())) - return; - if(selection instanceof IStructuredSelection) { - Set ress = ISelectionUtils.filterSetSelection(selection, Resource.class); - List runtimes = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_VARIABLE_RESOURCE, Resource.class); - if(runtimes.isEmpty()) - return; - Resource runtime = runtimes.get(0); - setSelection(ress.toArray(Resource.NONE), runtime); - } - } - }); - - } - - Resource[] resources; - Resource runtime; - - protected void setSelection(Resource[] resources, Resource runtime) { - this.resources = resources; - this.runtime = runtime; - updateView(); - } - - public void updateView() { - - Session session = SimanticsUI.peekSession(); - if (session == null) - return; - - session.asyncRequest(new ReadRequest() { - @Override - public void run(ReadGraph g) throws DatabaseException { - - final ArrayList datasets = new ArrayList(); - for(Resource resource : resources) { -// SysdynDataSet set = load(g, resource, runtime); -// if(set == null) { -// return; -// } -// datasets.add(set); - Collection activeDataSets = loadAllActive(g, resource, runtime); - if(activeDataSets != null && !activeDataSets.isEmpty()) - datasets.addAll(activeDataSets); - } - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - sysdynDatasets.setDatasets(datasets.toArray(new SysdynDataSet[datasets.size()])); - } - - }); - - } - }); - } - - /* - protected SysdynDataSet load(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { - - Builtins b = g.getBuiltins(); - - SysdynResource sr = SysdynResource.getInstance(g); - - DiagramResource dr = DiagramResource.getInstance(g); - - if(runtime == null) return null; - Resource resource = ModelingUtils.getPossibleElementCorrespondendence(g, element); - if(resource == null || !g.isInstanceOf(resource, sr.Variable)) return null; - - String variableURI = g.getPossibleRelatedValue(runtime, dr.HasVariable); - - System.out.println("load dataset for '"+ g.getPossibleRelatedValue(resource, b.HasName) + "'in composite '" + variableURI + "'"); - Variable compositeVariable = Variables.getVariable(g, variableURI); - Variable item = compositeVariable.browsePossible(g, resource); - if(item == null) return null; - - System.out.println("load dataset for '" + item.getURI(g) + "'"); - - Accessor accessor = item.getInterface(g, Accessor.class); - if(accessor == null) return null; - try { - return (SysdynDataSet)accessor.getValue(Bindings.getBindingUnchecked(SysdynDataSet.class)); - } catch (RuntimeBindingConstructionException e) { - e.printStackTrace(); - } catch (AccessorException e) { - e.printStackTrace(); - } - return null; + Frame frame; + ChartPanel panel; + SysdynDatasets sysdynDatasets = new SysdynDatasets(); + - } - */ + @SuppressWarnings("serial") + class SysdynDatasets extends AbstractXYDataset { - @Override - public void setFocus() { - if(panel != null) - panel.requestFocus(); - } + SysdynDataSet[] sets = new SysdynDataSet[0]; - protected Collection loadAllActive(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { + public void setDatasets(SysdynDataSet[] sets) { + this.sets = sets; + fireDatasetChanged(); + } + + @Override + public Number getY(int series, int item) { + return sets[series].values[item]; + } - ArrayList dataSets = new ArrayList(); - Builtins b = g.getBuiltins(); + @Override + public Number getX(int series, int item) { + return sets[series].times[item]; + } - SysdynResource sr = SysdynResource.getInstance(g); + @Override + public int getItemCount(int series) { + return sets[series].times.length; + } - DiagramResource dr = DiagramResource.getInstance(g); + @Override + public Comparable getSeriesKey(int series) { + SysdynDataSet sds = sets[series]; + if(sds.result == null) + return sds.name; + else + return sds.name + " : " + sds.result; + } - if(runtime == null) return null; - Resource resource = ModelingUtils.getPossibleElementCorrespondendence(g, element); - if(resource == null || !g.isInstanceOf(resource, sr.Variable)) return null; + @Override + public int getSeriesCount() { + return sets.length; + } - String variableURI = g.getPossibleRelatedValue(runtime, dr.HasVariable); + } + + @Override + public void createPartControl(Composite parent) { + final ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider(); + getSite().setSelectionProvider(selectionProvider); + + final Composite composite = new Composite(parent, + SWT.NO_BACKGROUND | SWT.EMBEDDED); + frame = SWT_AWT.new_Frame(composite); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + XYPlot plot = new XYPlot( + sysdynDatasets, + new NumberAxis("time"), + new NumberAxis("x"), + new XYLineAndShapeRenderer(true, false) + ); + + JFreeChart chart = new JFreeChart(plot); + panel = new ChartPanel(chart); + frame.add(panel); + + panel.requestFocus(); + } + + }); + + getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(new ISelectionListener() { + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if(selection.isEmpty() || Boolean.TRUE.equals(PinTrend.getState())) + return; + if(selection instanceof IStructuredSelection) { + Set bs = ISelectionUtils.filterSetSelection(selection, BrowserSelection.class); + if(!bs.isEmpty()) { + updateDatasets(bs.toArray(new BrowserSelection[bs.size()])); + } else { + Set ress = ISelectionUtils.filterSetSelection(selection, Resource.class); + List runtimes = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_VARIABLE_RESOURCE, Resource.class); + if(runtimes.isEmpty()) + return; + Resource runtime = runtimes.get(0); + updateDatasets(ress.toArray(Resource.NONE), runtime); + } + } + } + }); - System.out.println("load dataset for '"+ g.getPossibleRelatedValue(resource, b.HasName) + "'in composite '" + variableURI + "'"); - Variable compositeVariable = Variables.getVariable(g, variableURI); - Variable item = compositeVariable.browsePossible(g, resource); - if(item == null) return null; + } + + ArrayList datasets = new ArrayList(); + + private void updateDatasets(final Resource[] resources, final Resource runtime) { + Session session = SimanticsUI.peekSession(); + if (session == null) + return; + + session.asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph g) throws DatabaseException { + datasets.clear(); + for(Resource resource : resources) { + Collection activeDataSets = loadAllActive(g, resource, runtime); + if(activeDataSets != null && !activeDataSets.isEmpty()) + datasets.addAll(activeDataSets); + } + updateView(); + } + }); + + } + + private void updateDatasets(final BrowserSelection[] browserSelections) { + Session session = SimanticsUI.peekSession(); + if (session == null) + return; + + session.asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph g) throws DatabaseException { + datasets.clear(); + for(BrowserSelection bs : browserSelections) { + if(bs.getURI() != null && bs.getModel() != null) { + Collection activeDataSets = loadAllActive(g, bs.getURI(), bs.getModel()); + if(activeDataSets != null && !activeDataSets.isEmpty()) + datasets.addAll(activeDataSets); + } + + } + updateView(); + } + }); + } + + private void updateView() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + sysdynDatasets.setDatasets(datasets.toArray(new SysdynDataSet[datasets.size()])); + } + + }); + } + + + @Override + public void setFocus() { + if(panel != null) + panel.requestFocus(); + } + + protected Collection loadAllActive(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { + + Builtins b = g.getBuiltins(); + + SysdynResource sr = SysdynResource.getInstance(g); + + DiagramResource dr = DiagramResource.getInstance(g); + + if(runtime == null) return null; + Resource resource = ModelingUtils.getPossibleElementCorrespondendence(g, element); + if(resource == null || !g.isInstanceOf(resource, sr.Variable)) return null; + + String variableURI = g.getPossibleRelatedValue(runtime, dr.HasVariable); + + System.out.println("load dataset for '"+ g.getPossibleRelatedValue(resource, b.HasName) + "'in composite '" + variableURI + "'"); + Variable compositeVariable = Variables.getVariable(g, variableURI); + Variable item = compositeVariable.browsePossible(g, resource); + if(item == null) return null; + + String rvi = Variables.getRVI(g, item); + System.out.println("HistoryVariable rvi='" + rvi + "'"); + + System.out.println("load dataset for '" + item.getURI(g) + "'"); + + Resource model = Variables.getModel(g, item); + + return loadAllActive(g, rvi.substring(1), model); - String rvi = Variables.getRVI(g, item); - System.out.println("HistoryVariable rvi='" + rvi + "'"); + } - System.out.println("load dataset for '" + item.getURI(g) + "'"); + protected Collection loadAllActive(ReadGraph g, String rvi, Resource model) throws DatabaseException { + ArrayList dataSets = new ArrayList(); - Resource model = Variables.getModel(g, item); - Resource configuration = g.getPossibleObject(model, SimulationResource.getInstance(g).HasConfiguration); - SysdynModel sm = SysdynModelManager.getInstance(g.getSession()).getModel(g, configuration); + Resource configuration = g.getPossibleObject(model, SimulationResource.getInstance(g).HasConfiguration); + SysdynModel sm = SysdynModelManager.getInstance(g.getSession()).getModel(g, configuration); - Collection activeResults = sm.getActiveResults(g); - for(SysdynResult sysdynResult : activeResults) { - SysdynDataSet sds = sysdynResult.getDataSet(rvi.substring(1).replace("/", ".")); - if(sds != null) - dataSets.add(sds); - } - return dataSets; + Collection activeResults = sm.getActiveResults(g); + for(SysdynResult sysdynResult : activeResults) { + SysdynDataSet sds = sysdynResult.getDataSet(rvi.replace("/", ".")); + if(sds != null) + dataSets.add(sds); + } + return dataSets; - } + } }