From 623c0311361706261d69de42330545eeb968a033 Mon Sep 17 00:00:00 2001 From: lempinen Date: Tue, 18 Oct 2011 06:26:29 +0000 Subject: [PATCH] Issue decorations and better error handling git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@22796 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ontology/graph.tg | Bin 70118 -> 70418 bytes .../graph/Profiles.pgraph | 21 +- .../graph/Sysdyn.pgraph | 4 +- .../org/simantics/sysdyn/SysdynResource.java | 15 + org.simantics.sysdyn.ui/adapters.xml | 2 +- org.simantics.sysdyn.ui/icons/error.svg | 151 +++++ org.simantics.sysdyn.ui/icons/fatal.svg | 612 ++++++++++++++++++ org.simantics.sysdyn.ui/icons/warning.svg | 173 +++++ org.simantics.sysdyn.ui/plugin.xml | 6 + .../org/simantics/sysdyn/ui/Activator.java | 13 + .../profiles/IssueDecorationStyle.java | 131 ++++ .../profiles/SimulationPlaybackStyle.java | 11 + .../ui/handlers/NewModuleNodeHandler.java | 17 +- .../sysdyn/ui/utils/ProfileEntries.java | 35 +- .../simantics/sysdyn/ui/utils/SheetUtils.java | 11 + .../ui/validation/DependencyFunction.java | 73 ++- .../validation/ExpressionIssueFunction.java | 36 +- .../validation/NoSuchVariableException.java | 11 + .../ui/validation/SyntaxErrorException.java | 11 + .../UndefinedExpressionException.java | 11 + .../UnsupportedCharactersException.java | 11 + .../sysdyn/ui/validation/ValidationUtils.java | 17 +- org.simantics.sysdyn/META-INF/MANIFEST.MF | 3 +- .../adapter/SysdynVariableProperties.java | 11 + .../adapter/VariableValueSubscription.java | 11 + .../sysdyn/manager/FunctionUtils.java | 11 + .../simantics/sysdyn/manager/SysdynModel.java | 53 +- .../sysdyn/simulation/SimulationJob.java | 180 +++++- 28 files changed, 1562 insertions(+), 79 deletions(-) create mode 100644 org.simantics.sysdyn.ui/icons/error.svg create mode 100644 org.simantics.sysdyn.ui/icons/fatal.svg create mode 100644 org.simantics.sysdyn.ui/icons/warning.svg create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/IssueDecorationStyle.java diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index 14b2d4f329d56191a881bd8a7dadcd0dc24db9af..8915d0aee8bdd65e14d131c183beb5c6af328325 100644 GIT binary patch literal 70418 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 Rld(bD%3sTuzt;zi{{vOFs{sH2 literal 70118 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 diff --git a/org.simantics.sysdyn.ontology/graph/Profiles.pgraph b/org.simantics.sysdyn.ontology/graph/Profiles.pgraph index 40a270f2..58ff98d7 100644 --- a/org.simantics.sysdyn.ontology/graph/Profiles.pgraph +++ b/org.simantics.sysdyn.ontology/graph/Profiles.pgraph @@ -13,14 +13,29 @@ groupStyleEntry : L0.Template DIA.ProfileEntry.HasStyle %style DIA.ProfileEntry.HasGroup %group + +// PROFILES SYSDYN.SimulationPlaybackProfile - none 0 fill 1 + none 0 fill 1 \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/icons/error.svg b/org.simantics.sysdyn.ui/icons/error.svg new file mode 100644 index 00000000..e4eb0ab1 --- /dev/null +++ b/org.simantics.sysdyn.ui/icons/error.svg @@ -0,0 +1,151 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.sysdyn.ui/icons/fatal.svg b/org.simantics.sysdyn.ui/icons/fatal.svg new file mode 100644 index 00000000..5ee48164 --- /dev/null +++ b/org.simantics.sysdyn.ui/icons/fatal.svg @@ -0,0 +1,612 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.sysdyn.ui/icons/warning.svg b/org.simantics.sysdyn.ui/icons/warning.svg new file mode 100644 index 00000000..1dd13ec6 --- /dev/null +++ b/org.simantics.sysdyn.ui/icons/warning.svg @@ -0,0 +1,173 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index a23cc2f2..a9237d57 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -173,6 +173,12 @@ relationship="stack" relative="org.simantics.browsing.ui.graph.propertyView"> + + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java index e531f9bb..cb2d6dd3 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java @@ -23,7 +23,9 @@ import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.resource.ResourceManager; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.simantics.utils.FileUtils; public class Activator extends AbstractUIPlugin { @@ -34,6 +36,10 @@ public class Activator extends AbstractUIPlugin { private static Activator plugin; private static LocalResourceManager resourceManager; + + public static String FATAL_SVG_TEXT; + public static String ERROR_SVG_TEXT; + public static String WARNING_SVG_TEXT; @Override public void start(BundleContext context) throws Exception { @@ -43,6 +49,13 @@ public class Activator extends AbstractUIPlugin { BasicConfigurator.configure(appender); Logger.getRootLogger().setLevel(Level.WARN); plugin = this; + + + Bundle bundle = context.getBundle(); + + FATAL_SVG_TEXT = FileUtils.getContents(bundle.getResource("icons/fatal.svg")); + ERROR_SVG_TEXT = FileUtils.getContents(bundle.getResource("icons/error.svg")); + WARNING_SVG_TEXT = FileUtils.getContents(bundle.getResource("icons/warning.svg")); } @Override diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/IssueDecorationStyle.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/IssueDecorationStyle.java new file mode 100644 index 00000000..1912264e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/IssueDecorationStyle.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * 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.ui.elements2.profiles; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.util.Collections; +import java.util.Set; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.PossibleTypedParent; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.diagram.profile.StyleBase; +import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; +import org.simantics.issues.Issue.Severity; +import org.simantics.issues.common.ErrorIssues; +import org.simantics.issues.common.FatalIssues; +import org.simantics.issues.common.IssueContexts; +import org.simantics.issues.common.WarningIssues; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.nodes.SVGNode; +import org.simantics.scenegraph.profile.EvaluationContext; +import org.simantics.scenegraph.profile.common.ProfileVariables; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.sysdyn.ui.Activator; +import org.simantics.utils.datastructures.map.Tuple; + +/** + * @author Tuukka Lehtonen + */ +public class IssueDecorationStyle extends StyleBase { + + private static final String DECORATION_NODE_NAME = "issueDecorations"; + + @Override + public IssueResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource module, Variable configuration) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + Resource config = graph.getPossibleObject(module, MOD.ElementToComponent); + if (config == null) + return null; + + AffineTransform transform = DiagramGraphUtil.getAffineTransform(graph, module); + + Resource model = graph.syncRequest(new PossibleTypedParent(config, SimulationResource.getInstance(graph).Model)); + if (model == null) + return null; + + Resource project = graph.getPossibleObject(model, L0.PartOf); + if (project == null) + return null; + + Set fatals = graph.syncRequest(new FatalIssues(project, true)); + Set fatalContexts = graph.syncRequest(new IssueContexts(fatals)); + if (fatalContexts.contains(config)) + return new IssueResult(Severity.FATAL, transform); + + Set errors = graph.syncRequest(new ErrorIssues(project, true)); + Set errorContexts = graph.syncRequest(new IssueContexts(errors)); + if (errorContexts.contains(config)) + return new IssueResult(Severity.ERROR, transform); + + Set warnings = graph.syncRequest(new WarningIssues(project, true)); + Set warningContexts = graph.syncRequest(new IssueContexts(warnings)); + if (warningContexts.contains(config)) + return new IssueResult(Severity.WARNING, transform); + + return null; + } + + @Override + public void applyStyleForNode(EvaluationContext observer, INode node, IssueResult result) { + if (result == null) { + ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); + return; + } + + SVGNode svgNode = ProfileVariables.claimChild(node, "", DECORATION_NODE_NAME, SVGNode.class, observer); + + Rectangle2D bounds = NodeUtil.getLocalBounds(node, Collections.singleton(svgNode)); + + double tx = bounds.getMaxX(); + double ty = bounds.getY(); + + svgNode.setZIndex( Integer.MAX_VALUE ); + svgNode.setTransform( AffineTransform.getTranslateInstance(tx-1, ty-1)); + svgNode.getTransform().scale(0.5, 0.5); + + + Severity sev = result.getSeverity(); + if (Severity.FATAL.equals(sev)) + svgNode.setData(Activator.FATAL_SVG_TEXT); + else if (Severity.ERROR.equals(sev)) + svgNode.setData(Activator.ERROR_SVG_TEXT); + else if (Severity.WARNING.equals(sev)) + svgNode.setData(Activator.WARNING_SVG_TEXT); + } + + @Override + protected void cleanupStyleForNode(INode node) { + ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); + } + +} + +/** + * This is needed to keep the issue decoration up-to-date when its parent + * element moves. + */ +class IssueResult extends Tuple { + public IssueResult(Severity severity, AffineTransform transform) { + super(severity, transform); + } + public Severity getSeverity() { + return (Severity) getField(0); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/SimulationPlaybackStyle.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/SimulationPlaybackStyle.java index 0bdedd0d..1dd87165 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/SimulationPlaybackStyle.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/SimulationPlaybackStyle.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.elements2.profiles; import java.awt.Color; diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java index e6ec15a6..4478bae7 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 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 @@ -67,6 +67,8 @@ public class NewModuleNodeHandler extends AbstractHandler { g.claim(moduleType, l0.Inherits, sr.Module); g.claim(moduleType, l0.PartOf, model); + + Resource configuration = GraphUtils.create2(g, sr.Configuration, l0.HasName, name + "Configuration", @@ -88,6 +90,19 @@ public class NewModuleNodeHandler extends AbstractHandler { g.deny(diagram, L0X.HasTrigger, trigger); } } + + GraphUtils.create2(g, + sr.Validations_Dependencies_DependencyConnectionsIssueSource, + L0X.IsActivatedBy, model, + l0.PartOf, moduleType + ); + + GraphUtils.create2(g, + sr.Validations_Expressions_ExpressionIssueSource, + L0X.IsActivatedBy, model, + l0.PartOf, moduleType + ); + Resource mapping = g.newResource(); g.claim(mapping, l0.InstanceOf, null, sr.DiagramToCompositeMapping); g.claim(diagram, L0X.HasTrigger, mapping); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ProfileEntries.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ProfileEntries.java index 265aed91..f568a6ca 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ProfileEntries.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ProfileEntries.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.utils; import org.simantics.db.Resource; @@ -14,37 +25,37 @@ public class ProfileEntries { public static void createStandardProfiles(WriteGraph graph, final Resource model) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + DiagramResource DIA = DiagramResource.getInstance(graph); - final Resource a = createSimulationPlaybackProfile(graph); + Resource simulationPlaybackProfile = createProfile(graph, "Simulation Playback", sr.SimulationPlaybackProfile ,sr.Profiles_SimulationPlaybackColours); - Resource plain = Profiles.createProfile(graph, "Plain"); + Resource defaultProfile = createProfile(graph, "Default", sr.DefaultProfile, sr.Profiles_IssueWarnings); - graph.claim(model, DIA.HasProfile, plain); - graph.claim(model, L0.ConsistsOf, a); - graph.claim(model, L0.ConsistsOf, plain); + graph.claim(model, DIA.HasProfile, defaultProfile); + graph.claim(model, L0.ConsistsOf, simulationPlaybackProfile); + graph.claim(model, L0.ConsistsOf, defaultProfile); // FIXME: add virtual graph write back once this is fixed: https://www.simulationsite.net/redmine/issues/3296 // graph.sync(new WriteRequest(graph.getService(VirtualGraphSupport.class).getWorkspacePersistent("profiles")) { // @Override // public void perform(WriteGraph graph) throws DatabaseException { // DiagramResource DIA = DiagramResource.getInstance(graph); - graph.claim(model, DIA.HasActiveProfile, plain); + graph.claim(model, DIA.HasActiveProfile, defaultProfile); // } // }); } - public static Resource createSimulationPlaybackProfile(WriteGraph graph) - throws DatabaseException { + public static Resource createProfile(WriteGraph graph, String name, Resource type, Resource... entries) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - Resource profile = Profiles.createProfile(graph, "Simulation Playback", - sr.Profiles_SimulationPlaybackColours); + Resource profile = Profiles.createProfile(graph, name, + entries); graph.deny(profile, L0.InstanceOf); - graph.claim(profile, L0.InstanceOf, null, sr.SimulationPlaybackProfile); + graph.claim(profile, L0.InstanceOf, null, type); return profile; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java index 5360fd83..c593f278 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.utils; import org.simantics.databoard.Bindings; diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/DependencyFunction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/DependencyFunction.java index a6431ad4..ebd5f7ad 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/DependencyFunction.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/DependencyFunction.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; import java.util.Collection; @@ -13,6 +24,7 @@ import org.simantics.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import org.simantics.scl.reflection.annotations.SCLValue; import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; public class DependencyFunction { @@ -47,36 +59,44 @@ public class DependencyFunction { Resource variable = (Resource)_resource; Collection existing = (Collection)_existing; - if(!graph.hasStatement(variable) || !graph.hasStatement(variable, Layer0.getInstance(graph).PartOf)) + IssueResource ISSUE = IssueResource.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + + if(!graph.isInstanceOf(variable, sr.IndependentVariable)) + return Boolean.TRUE; + + if(!graph.hasStatement(variable) || !graph.hasStatement(variable, l0.PartOf)) return Boolean.FALSE; String name = graph.getRelatedValue(variable, Layer0.getInstance(graph).HasName, Bindings.STRING); - Set references; - Set dependencies; + Set dependencies = ValidationUtils.getDependencies(graph, variable); + + Set references = null; try { references = ValidationUtils.getReferences(graph, variable); - dependencies = ValidationUtils.getDependencies(graph, variable); - - + } catch (SyntaxErrorException e) { + } catch (UnsupportedCharactersException e) { + } catch (UndefinedExpressionException e) { + } + + if(references != null && dependencies != null) { for(String reference : references) { if(!dependencies.contains(reference) && match(graph, existing, variable, getMissingLinkLabel(name, reference)) == null) return Boolean.FALSE; } + } + if(dependencies != null) { for(String dependency : dependencies) { - if(!references.contains(dependency) && match(graph, existing, variable, getUnusedDependencyLabel(name, dependency)) == null) + if(references == null || + (!references.contains(dependency) && + match(graph, existing, variable, getUnusedDependencyLabel(name, dependency)) == null)) return Boolean.FALSE; } - } catch (SyntaxErrorException e) { - } catch (UnsupportedCharactersException e) { - } catch (UndefinedExpressionException e) { } - IssueResource ISSUE = IssueResource.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - Layer0 l0 = Layer0.getInstance(graph); - Resource context; for(Resource exist : existing) { context = graph.getSingleObject(exist, ISSUE.HasIssueContext); @@ -108,11 +128,16 @@ public class DependencyFunction { Set labels = new HashSet(); String label; - Set references; - Set dependencies; + Set dependencies = ValidationUtils.getDependencies(graph, variable); + Set references = null; try { references = ValidationUtils.getReferences(graph, variable); - dependencies = ValidationUtils.getDependencies(graph, variable); + } catch (SyntaxErrorException e) { + } catch (UnsupportedCharactersException e) { + } catch (UndefinedExpressionException e) { + } + + if(references != null && dependencies != null) { for(String reference : references) { if(!dependencies.contains(reference)) { if(ValidationUtils.isReachable(graph, variable, reference)) { @@ -130,19 +155,18 @@ public class DependencyFunction { } } } + } + if(dependencies != null) { for(String dependency : dependencies) { label = getUnusedDependencyLabel(name, dependency); - if(!references.contains(dependency)) { + if(references == null || !references.contains(dependency)) { labels.add(label); if(match(graph, existing, variable, label) == null) { ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Warning, sr.DependencyIssue); } } } - } catch (SyntaxErrorException e) { - } catch (UnsupportedCharactersException e) { - } catch (UndefinedExpressionException e) { } Set toBeRemoved = new HashSet(); @@ -171,7 +195,12 @@ public class DependencyFunction { public static Object dependencyBaseRealizationFunction(Object _graph, Object _model) throws DatabaseException { ReadGraph graph = (ReadGraph)_graph; Resource model = (Resource)_model; - return graph.getSingleObject(model, SimulationResource.getInstance(graph).HasConfiguration); + SysdynResource sr = SysdynResource.getInstance(graph); + if(graph.isInstanceOf(model, sr.SysdynModel)) + return graph.getSingleObject(model, SimulationResource.getInstance(graph).HasConfiguration); + else if (graph.isInheritedFrom(model, sr.Module)) + return graph.getSingleObject(model, StructuralResource2.getInstance(graph).IsDefinedBy); + else return null; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java index 344310fb..483f2d74 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; import java.util.Collection; @@ -13,6 +24,7 @@ import org.simantics.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import org.simantics.scl.reflection.annotations.SCLValue; import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; /** @@ -41,8 +53,17 @@ public class ExpressionIssueFunction { ReadGraph graph = (ReadGraph)_graph; Resource variable = (Resource)_resource; Collection existing = (Collection)_existing; - String name = graph.getRelatedValue(variable, Layer0.getInstance(graph).HasName, Bindings.STRING); - + + SysdynResource sr = SysdynResource.getInstance(graph); + IssueResource ISSUE = IssueResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + + if(!graph.isInstanceOf(variable, sr.IndependentVariable)) { + return Boolean.TRUE; + } + + String name = graph.getRelatedValue(variable, l0.HasName, Bindings.STRING); +System.out.println(name); // Try if there are any errors while parsing the expressions try { ValidationUtils.getReferences(graph, variable); @@ -57,10 +78,6 @@ public class ExpressionIssueFunction { return Boolean.FALSE; } - SysdynResource sr = SysdynResource.getInstance(graph); - IssueResource ISSUE = IssueResource.getInstance(graph); - Layer0 l0 = Layer0.getInstance(graph); - Resource context; // There were no errors -> There should be no expression issues for this variable for(Resource exist : existing) { @@ -133,7 +150,12 @@ public class ExpressionIssueFunction { public static Object expressionBaseRealizationFunction(Object _graph, Object _model) throws DatabaseException { ReadGraph graph = (ReadGraph)_graph; Resource model = (Resource)_model; - return graph.getSingleObject(model, SimulationResource.getInstance(graph).HasConfiguration); + SysdynResource sr = SysdynResource.getInstance(graph); + if(graph.isInstanceOf(model, sr.SysdynModel)) + return graph.getSingleObject(model, SimulationResource.getInstance(graph).HasConfiguration); + else if (graph.isInheritedFrom(model, sr.Module)) { + return graph.getSingleObject(model, StructuralResource2.getInstance(graph).IsDefinedBy); + } else return null; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableException.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableException.java index 668ddee4..4ec11767 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableException.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableException.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; public class NoSuchVariableException extends RuntimeException { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/SyntaxErrorException.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/SyntaxErrorException.java index 8d577c98..0592a5d7 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/SyntaxErrorException.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/SyntaxErrorException.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; public class SyntaxErrorException extends RuntimeException { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UndefinedExpressionException.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UndefinedExpressionException.java index bffa074e..1c53cd87 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UndefinedExpressionException.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UndefinedExpressionException.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; public class UndefinedExpressionException extends RuntimeException { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnsupportedCharactersException.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnsupportedCharactersException.java index e96b6096..b2aa82f4 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnsupportedCharactersException.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnsupportedCharactersException.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; public class UnsupportedCharactersException extends RuntimeException { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java index 349e0303..7659e3d5 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ui.validation; import java.io.StringReader; @@ -69,7 +80,11 @@ public class ValidationUtils { if(expressionList == null || expressionList.isEmpty()) throw new UndefinedExpressionException(); for(Resource expression : expressionList) { - for(Resource s : graph.syncRequest(new ObjectsWithType(expression, sr.HasEquation, l0.String))) { + Collection equations = graph.syncRequest(new ObjectsWithType(expression, sr.HasEquation, l0.String)); + if(equations.isEmpty()) + throw new UndefinedExpressionException(); + + for(Resource s : equations) { String value = graph.getValue(s, Bindings.STRING); if(value.length() == 0) throw new UndefinedExpressionException(); diff --git a/org.simantics.sysdyn/META-INF/MANIFEST.MF b/org.simantics.sysdyn/META-INF/MANIFEST.MF index 4b4c2998..c83f7bdb 100644 --- a/org.simantics.sysdyn/META-INF/MANIFEST.MF +++ b/org.simantics.sysdyn/META-INF/MANIFEST.MF @@ -23,7 +23,8 @@ Require-Bundle: org.simantics.objmap;bundle-version="0.1.0", org.simantics.scl.runtime;bundle-version="0.1.3", org.simantics.db.layer0;bundle-version="1.1.0", org.simantics.spreadsheet.common;bundle-version="1.1.0", - org.simantics.spreadsheet;bundle-version="1.1.0" + org.simantics.spreadsheet;bundle-version="1.1.0", + org.eclipse.jface.text;bundle-version="3.6.1" Export-Package: org.simantics.sysdyn, org.simantics.sysdyn.adapter, org.simantics.sysdyn.expressionParser, diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/SysdynVariableProperties.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/SysdynVariableProperties.java index 102348c9..c21b4a9c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/SysdynVariableProperties.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/SysdynVariableProperties.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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; public class SysdynVariableProperties { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java index e04aed72..75a561c1 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.ArrayList; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/FunctionUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/FunctionUtils.java index ee40f1e8..725eed58 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/FunctionUtils.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/FunctionUtils.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * 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.manager; import java.io.File; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java index 56bd084a..0a857906 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -167,10 +167,23 @@ public class SysdynModel implements IMappingListener, IModel { public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor, final Experiment experiment) throws IOException { canceled = false; progressMonitor.subTask("Write modelica classes"); + + // Write Modelica files ModelicaWriter writer = new ModelicaWriter(); - for(Configuration c : modules) { - writer.write(c); + try { + for(Configuration c : modules) { + writer.write(c); + } + } catch (Exception e) { + setExperimentStopped(experiment); + + + monitor.showConsole(); + + monitor.message("Error when writing Modelica code."); + return; } + progressMonitor.worked(1); progressMonitor.subTask("Write initial files"); @@ -203,7 +216,7 @@ public class SysdynModel implements IMappingListener, IModel { final SimulationLocation simulationLocation = ModelicaManager.createInputFiles( getSimulationDir(), configuration.getName(), - writer.toString(), + modelText, inits, functionscript.toString()); @@ -350,10 +363,22 @@ public class SysdynModel implements IMappingListener, IModel { public synchronized boolean update(ReadGraph graph) throws DatabaseException { if(mapping.isDomainModified()) { mapping.updateRange(graph); - for(Resource config : readModules(graph, configurationResource)) { + Set configs = readModules(graph, configurationResource); + for(Resource config : configs) { if(!modules.contains(config)) modules.add((Configuration)mapping.map(graph, config)); } + + HashSet toBeRemoved = null; + for(Configuration module : modules) { + if(!configs.contains(mapping.inverseGet(module))) { + if(toBeRemoved == null) + toBeRemoved = new HashSet(); + toBeRemoved.add(module); + } + } + if(toBeRemoved != null) + modules.removeAll(toBeRemoved); return true; } else @@ -366,10 +391,22 @@ public class SysdynModel implements IMappingListener, IModel { @Override public void run(ReadGraph graph) throws DatabaseException { mapping.updateRange(graph); - for(Resource config : readModules(graph, configurationResource)) { - if(!modules.contains(config)) - modules.add((Configuration)mapping.map(graph, config)); - } + Set configs = readModules(graph, configurationResource); + for(Resource config : configs) { + if(!modules.contains(config)) + modules.add((Configuration)mapping.map(graph, config)); + } + + HashSet toBeRemoved = null; + for(Configuration module : modules) { + if(!configs.contains(mapping.inverseGet(module))) { + if(toBeRemoved == null) + toBeRemoved = new HashSet(); + toBeRemoved.add(module); + } + } + if(toBeRemoved != null) + modules.removeAll(toBeRemoved); } }); return true; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java index b2a729b6..3d51aa8f 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java @@ -18,12 +18,18 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.ui.console.IConsole; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleManager; +import org.eclipse.ui.console.IHyperlink; +import org.eclipse.ui.console.IPatternMatchListener; import org.eclipse.ui.console.MessageConsole; import org.eclipse.ui.console.MessageConsoleStream; -import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.console.PatternMatchEvent; +import org.eclipse.ui.console.TextConsole; import org.simantics.modelica.IModelicaMonitor; import org.simantics.simulation.experiment.Experiment; import org.simantics.sysdyn.manager.SysdynModel; @@ -39,10 +45,10 @@ public class SimulationJob extends Job { this.model = model; this.experiment = experiment; if(PlatformUI.isWorkbenchRunning()) { - this.monitor = new ModelicaMonitor(); + this.monitor = new ModelicaMonitor(); } else { - // Fallback to headless - this.monitor = new HeadlessModelicaMonitor(); + // Fallback to headless + this.monitor = new HeadlessModelicaMonitor(); } } @@ -65,7 +71,7 @@ public class SimulationJob extends Job { monitor.done(); return Status.OK_STATUS; } - + @Override public boolean belongsTo(Object family) { return "SimulationJob".equals(family); @@ -77,9 +83,9 @@ public class SimulationJob extends Job { @Override public void message(String message) { - message(message, "hh:mm:ss"); + message(message, "hh:mm:ss"); } - + /** * Print message to a console with a specified time stamp format * @@ -90,22 +96,22 @@ public class SimulationJob extends Job { Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat(timeStampFormat); String time = sdf.format(cal.getTime()); - + System.out.println("[" + time +"] " + message); } public void clearConsole() { } - + public void showConsole() { } } - + //org.simantics.sysdyn.ui.modelicaEditor private class ModelicaMonitor implements IModelicaMonitor { MessageConsole console; - + public ModelicaMonitor() { ConsolePlugin plugin = ConsolePlugin.getDefault(); IConsoleManager conMan = plugin.getConsoleManager(); @@ -117,14 +123,103 @@ public class SimulationJob extends Job { MessageConsole myConsole = new MessageConsole("Simulation", null); conMan.addConsoles(new IConsole[]{myConsole}); console = myConsole; + console.addPatternMatchListener(new IPatternMatchListener() { + + @Override + public void matchFound(PatternMatchEvent event) { + try { + console.addHyperlink(new IssueLink(), event.getOffset(), event.getLength()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + @Override + public void disconnect() { + } + + @Override + public void connect(TextConsole console) { + } + + @Override + public String getPattern() { + + return "Issues view"; + } + + @Override + public String getLineQualifier() { + return null; + } + + @Override + public int getCompilerFlags() { + return 0; + } + }); + + /* Link to the modelica document: to be opened to a modelica code viewer. + console.addPatternMatchListener(new IPatternMatchListener() { + + @Override + public void matchFound(PatternMatchEvent event) { + try { + if(event.getSource() instanceof MessageConsole) { + MessageConsole console = (MessageConsole) event.getSource(); + IDocument document = console.getDocument(); + String s = document.get(event.getOffset(), event.getLength()); + s = s.substring(s.indexOf(":") + 1, s.lastIndexOf(":")); + String[] split = s.split(":|-"); + + //TODO: Find the modelica document and its locations + int startOffset = modelicaDocument.getLineOffset(Integer.parseInt(split[0])) + Integer.parseInt(split[1]); + int endOffset = modelicaDocument.getLineOffset(Integer.parseInt(split[2])) + Integer.parseInt(split[3]); + System.out.println("Open modelica editor for model at: " + startOffset + ", " + (endOffset - startOffset)); + + } + + console.addHyperlink(new ModelicaLink(), event.getOffset(), event.getLength()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + @Override + public void disconnect() { + } + + @Override + public void connect(TextConsole console) { + } + + @Override + public String getPattern() { + return "\\[[^\\[]*:[\\d]*:[\\d]*\\-[\\d]*:[\\d]*:writable\\]"; + + } + + @Override + public String getLineQualifier() { + return null; + } + + @Override + public int getCompilerFlags() { + return 0; + } + }); + */ + + } } @Override public void message(String message) { - message(message, "hh:mm:ss"); + message(message, "hh:mm:ss"); } - + /** * Print message to a console with a specified time stamp format * @@ -135,18 +230,23 @@ public class SimulationJob extends Job { Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat(timeStampFormat); String time = sdf.format(cal.getTime()); - + MessageConsoleStream out = this.console.newMessageStream(); if(message.length() > 1) - out.println("[" + time +"] " + message); - if(message.contains("Error")) - showConsole(); + out.println("[" + time +"] " + message); + + + + if(message.contains("Error")) { + showConsole(); + out.println("See Issues view"); + } } public void clearConsole() { this.console.clearConsole(); } - + public void showConsole() { ConsolePlugin plugin = ConsolePlugin.getDefault(); IConsoleManager conMan = plugin.getConsoleManager(); @@ -154,10 +254,48 @@ public class SimulationJob extends Job { } } - + @Override protected void canceling() { - model.cancelSimulation(); + + } + + + class IssueLink implements IHyperlink { + + @Override + public void linkEntered() { + } + + @Override + public void linkExited() { + } + + @Override + public void linkActivated() { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("org.simantics.issues.ui.issueview"); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + } + + class ModelicaLink implements IHyperlink { + + @Override + public void linkEntered() { + } + + @Override + public void linkExited() { + } + + @Override + public void linkActivated() { + System.out.println("MODELICA LINK"); + } + } } -- 2.47.1