From d0650613b391cc2c86f7c2242afc86fc7c54cef8 Mon Sep 17 00:00:00 2001 From: lempinen Date: Wed, 30 Nov 2011 07:39:04 +0000 Subject: [PATCH] Updated issues to new format git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@23369 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ontology/graph.tg | Bin 73355 -> 76823 bytes .../ChartAxisAndVariablesViewpoint.pgraph | 9 + .../graph/Sysdyn.pgraph | 7 +- .../graph/Validation.pgraph | 77 ++++-- .../org/simantics/sysdyn/SysdynResource.java | 72 ++++- org.simantics.sysdyn.ui/plugin.xml | 10 +- .../profiles/IssueDecorationStyle.java | 99 +++++-- .../ui/validation/DependencyFunction.java | 252 +++++++----------- .../validation/ExpressionIssueFunction.java | 154 +++-------- .../ui/validation/NoSuchVariableIssue.java | 73 +++++ .../sysdyn/ui/validation/ValidationUtils.java | 85 +++--- 11 files changed, 469 insertions(+), 369 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableIssue.java diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index 983ac388749e63470573e796ef1907abc7b047d8..66dd2706d43e3d3f76d073a87ea62b68e77bd67f 100644 GIT binary patch literal 76823 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 SYSDYN.DelayExpression.expression --> L0.String -- SYSDYN.DelayExpression.order --> L0.Integer -- SYSDYN.DelayExpression.delayTime --> L0.String -- SYSDYN.DelayExpression.initialValue --> L0.String -- VALIDATIONS.NoSuchVariableIssue.variableName --> L0.String @@ -1795,9 +1795,17 @@ + + + + + + + + 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 index 3cd3d6a7..009bb693 100644 --- 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 @@ -14,20 +14,21 @@ package org.simantics.sysdyn.ui.elements2.profiles; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.Collections; +import java.util.List; 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.common.utils.ListUtils; 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.IssueOld.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.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.scenegraph.INode; @@ -40,73 +41,120 @@ import org.simantics.sysdyn.ui.Activator; import org.simantics.utils.datastructures.map.Tuple; /** - * @author Tuukka Lehtonen + * Issue Decorations. Display an issue icon on + * a diagram element depending on the type of the issue + * . + * @author Teemu Lempinen + * */ 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 { + public IssueResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); ModelingResources MOD = ModelingResources.getInstance(graph); - Resource config = graph.getPossibleObject(module, MOD.ElementToComponent); - if (config == null) + + // Find a component for the element + Resource component = graph.getPossibleObject(element, MOD.ElementToComponent); + if (component == null) return null; - AffineTransform transform = DiagramGraphUtil.getAffineTransform(graph, module); + // Get the current transform of the element to be able to move the decoration with the element + AffineTransform transform = DiagramGraphUtil.getAffineTransform(graph, element); - Resource model = graph.syncRequest(new PossibleTypedParent(config, SimulationResource.getInstance(graph).Model)); + // Find the model of the component + Resource model = graph.syncRequest(new PossibleTypedParent(component, SimulationResource.getInstance(graph).Model)); if (model == null) return null; + // Project Resource project = graph.getPossibleObject(model, L0.PartOf); if (project == null) return null; + IssueResult result = null; + + /* + * Search for issues. Start from fatal and move to + * less important issues. This way the most important + * issue will be displayed. + * + * The issue is returned immediately after it is found. + */ + 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); - + result = getIssue(graph, IssueResult.Severity.FATAL, fatals, component, transform); + if(result != null) return result; + 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); + result = getIssue(graph, IssueResult.Severity.ERROR, errors, component, transform); + if(result != null) return result; 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); + result = getIssue(graph, IssueResult.Severity.WARNING, warnings, component, transform); + if(result != null) return result; + // No issue was found + return null; + } + + /** + * See if a set of issue variables concern this component + * + * @param graph ReadGraph + * @param severity IssueResult.Severity of the issue + * @param issues Collection of issues of type severity + * @param component The component that is evaluated for issues + * @param transform AffineTransform of the diagram element + * @return IssueResult containing the severity and transform of the issue or null if no issue concerned component + * @throws DatabaseException + */ + private IssueResult getIssue(ReadGraph graph, IssueResult.Severity severity, Set issues, Resource component, AffineTransform transform) throws DatabaseException { + IssueResource ISSUE = IssueResource.getInstance(graph); + Resource list, issueResource; + for(Variable issue : issues) { + issueResource = issue.getRepresents(graph); + list = graph.getPossibleObject(issueResource, ISSUE.DependencyIssueSource2_Issue_HasContexts); + List contexts = ListUtils.toList(graph, list); + if(!contexts.isEmpty()) { + if(ListUtils.toList(graph, list).get(0).equals(component)) { + return new IssueResult(severity, transform); + } + } + } return null; } @Override public void applyStyleForNode(EvaluationContext observer, INode node, IssueResult result) { + + // If result == null, remove possible issue decoration if (result == null) { ProfileVariables.denyChild(node, "", DECORATION_NODE_NAME); return; } + // Create issue decoration node SVGNode svgNode = ProfileVariables.claimChild(node, "", DECORATION_NODE_NAME, SVGNode.class, observer); + // Move the decoration to the upper right corner of the element 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)) + // Apply the corresponding svg graphics to the node + IssueResult.Severity sev = result.getSeverity(); + if (IssueResult.Severity.FATAL.equals(sev)) svgNode.setData(Activator.FATAL_SVG_TEXT); - else if (Severity.ERROR.equals(sev)) + else if (IssueResult.Severity.ERROR.equals(sev)) svgNode.setData(Activator.ERROR_SVG_TEXT); - else if (Severity.WARNING.equals(sev)) + else if (IssueResult.Severity.WARNING.equals(sev)) svgNode.setData(Activator.WARNING_SVG_TEXT); } @@ -122,6 +170,9 @@ public class IssueDecorationStyle extends StyleBase { * element moves. */ class IssueResult extends Tuple { + + public enum Severity{FATAL, ERROR, WARNING}; + public IssueResult(Severity severity, AffineTransform transform) { super(severity, transform); } 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 ebd5f7ad..8c17feb9 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 @@ -11,210 +11,162 @@ *******************************************************************************/ package org.simantics.sysdyn.ui.validation; -import java.util.Collection; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Set; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.issues.common.Issue; +import org.simantics.issues.common.StandardIssue; 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; +/** + * Evaluates issues related to Dependencies (arrows) + * + * @author Teemu Lempinen + * + */ public class DependencyFunction { - - private static String getMissingLinkLabel(String name, String dependency) throws DatabaseException { - return "Missing link " + dependency + " in " + name; - } - - private static String getNoSuchVariableLabel(String name, String dependency) throws DatabaseException { - return name + " refers to variable " + dependency + " that does not exist"; - } - - private static String getUnusedDependencyLabel(String name, String dependency) throws DatabaseException { - return "Unused dependency " + dependency + " in " + name; - } - /** + * Evaluates dependency-related issues for a component. * - * One issue is enough. The first encounter of a new issue returns Boolean.FALSE. + * Issues include: + * Missing link + * No such variable + * Unused dependency * - * @param _graph - * @param _resource - * @param _existing - * @return + * @param graph ReadGraph + * @param component Evaluated component (Variable) + * @return list of issues related to component * @throws DatabaseException */ - @SCLValue(type = "a -> b -> c -> d") - public static Object dependencyValidator(Object _graph, Object _resource, Object _existing) throws DatabaseException { - - ReadGraph graph = (ReadGraph)_graph; - Resource variable = (Resource)_resource; - Collection existing = (Collection)_existing; - - IssueResource ISSUE = IssueResource.getInstance(graph); + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List dependencyValidator(ReadGraph graph, Resource component) throws DatabaseException { 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); + if(!graph.isInstanceOf(component, sr.IndependentVariable)) + return Collections.emptyList(); - Set dependencies = ValidationUtils.getDependencies(graph, variable); + if(!graph.hasStatement(component) || !graph.hasStatement(component, l0.PartOf)) + return Collections.emptyList(); + // Find all variables that are linked to component with arrows + Set dependencies = ValidationUtils.getDependencies(graph, component); Set references = null; + + // Find all references in equations of component try { - references = ValidationUtils.getReferences(graph, variable); + references = ValidationUtils.getReferences(graph, component); } 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 == null || - (!references.contains(dependency) && - match(graph, existing, variable, getUnusedDependencyLabel(name, dependency)) == null)) - return Boolean.FALSE; - } - } - - Resource context; - for(Resource exist : existing) { - context = graph.getSingleObject(exist, ISSUE.HasIssueContext); - if(!graph.hasStatement(context) || graph.hasStatement(context, l0.PartOf)) - return Boolean.FALSE; - if(variable.equals(context) && graph.isInstanceOf(exist, sr.DependencyIssue)) { - return Boolean.FALSE; - } - } + ArrayList result = new ArrayList(); - return Boolean.TRUE; - } - - @SCLValue(type = "a -> b -> c -> d -> e -> f") - public static Object dependencySynchronizer(Object _graph, Object _resource, Object _source, Object _model, Object _existing) throws DatabaseException { - - WriteGraph graph = (WriteGraph)_graph; - Resource variable = (Resource)_resource; - Resource model = (Resource)_model; - Resource source = (Resource)_source; - Collection existing = (Collection)_existing; - Layer0 L0 = Layer0.getInstance(graph); - IssueResource ISSUE = IssueResource.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - - String name = graph.getRelatedValue(variable, L0.HasName, Bindings.STRING); - - Set labels = new HashSet(); - String label; - - Set dependencies = ValidationUtils.getDependencies(graph, variable); - Set references = null; - try { - references = ValidationUtils.getReferences(graph, variable); - } catch (SyntaxErrorException e) { - } catch (UnsupportedCharactersException e) { - } catch (UndefinedExpressionException e) { - } - + // Check that all references have corresponding arrows if(references != null && dependencies != null) { for(String reference : references) { if(!dependencies.contains(reference)) { - if(ValidationUtils.isReachable(graph, variable, reference)) { - label = getMissingLinkLabel(name, reference); - labels.add(label); - if(match(graph, existing, variable, label) == null) { - ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Warning, sr.DependencyIssue); - } + Resource variable = null; + if((variable = ValidationUtils.reach(graph, component, reference)) != null) { + result.add(new StandardIssue(sr.Validations_MissingLinkIssue, component, variable)); } else { - label = getNoSuchVariableLabel(name, reference); - labels.add(label); - if(match(graph, existing, variable, label) == null) { - ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Error, sr.DependencyIssue); - } + result.add(new NoSuchVariableIssue(sr.Validations_NoSuchVariableIssue, reference, component)); } } } } + // Check that all arrow dependencies are used in equations if(dependencies != null) { for(String dependency : dependencies) { - label = getUnusedDependencyLabel(name, 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); - } + Resource variable = ValidationUtils.reach(graph, component, dependency); + result.add(new StandardIssue(sr.Validations_UnusedDependencyIssue, component, variable)); } } } - Set toBeRemoved = new HashSet(); - Resource context; - for(Resource exist : existing) { - context = graph.getSingleObject(exist, ISSUE.HasIssueContext); - if(!graph.hasStatement(context) || !graph.hasStatement(context, L0.PartOf)) - toBeRemoved.add(exist); - if(graph.isInstanceOf(exist, sr.DependencyIssue) && variable.equals(context)) { - String l = graph.getRelatedValue(exist, L0.HasLabel); - if(!labels.contains(l)) - toBeRemoved.add(exist); - } - } - - for(Resource r : toBeRemoved) { - ValidationUtils.removeIssue(graph, model, source, variable, r, existing); - } - - - return Boolean.TRUE; - + return result; } - @SCLValue(type = "a -> b -> c") - public static Object dependencyBaseRealizationFunction(Object _graph, Object _model) throws DatabaseException { - ReadGraph graph = (ReadGraph)_graph; - Resource model = (Resource)_model; - 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; - } - - private static Resource match(ReadGraph graph, Collection existing, Resource variable, String description) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); + /** + * Missing link description + * + * @param graph ReadGraph + * @param converter + * @param issue Issue + * @return issue description + * @throws DatabaseException + */ + @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") + public static String missingLinkIssueDescription(ReadGraph graph, Resource converter, Variable issue) throws DatabaseException { + IssueResource ISSUE = IssueResource.getInstance(graph); + Resource issueResource = issue.getRepresents(graph); + Resource list = graph.getSingleObject(issueResource, ISSUE.DependencyIssueSource2_Issue_HasContexts); + List contexts = ListUtils.toList(graph, list); + String result = "Missing a link to "; + if(contexts.size() > 0) { + Resource component = contexts.get(1); + String name = NameUtils.getSafeName(graph, component); + result = result + name; + } + return result; + } + + /** + * Unused dependency description + * + * @param graph ReadGraph + * @param converter + * @param issue Issue + * @return issue description + * @throws DatabaseException + */ + @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") + public static String unusedDependencyIssueDescription(ReadGraph graph, Resource converter, Variable issue) throws DatabaseException { IssueResource ISSUE = IssueResource.getInstance(graph); - for(Resource exist : existing) { - Resource source = graph.getSingleObject(exist, ISSUE.HasIssueContext); - String desc = graph.getRelatedValue(exist, L0.HasLabel); -// if(source.equals(variable) && desc.startsWith(description.substring(0, description.lastIndexOf(" ")))) return exist; - if(source.equals(variable) && desc.equals(description)) return exist; + Resource issueResource = issue.getRepresents(graph); + Resource list = graph.getSingleObject(issueResource, ISSUE.DependencyIssueSource2_Issue_HasContexts); + List contexts = ListUtils.toList(graph, list); + String result = "Unused dependency: "; + if(contexts.size() > 0) { + Resource component = contexts.get(1); + String name = NameUtils.getSafeName(graph, component); + result = result + name; } - return null; + return result; } + /** + * No such variable description + * @param graph ReadGraph + * @param converter + * @param issue Issue + * @return issue description + * @throws DatabaseException + */ + @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") + public static String noSuchVariableIssueDescription(ReadGraph graph, Resource converter, Variable issue) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource issueResource = issue.getRepresents(graph); + String variable = graph.getPossibleRelatedValue(issueResource, sr.Validations_NoSuchVariableIssue_variableName, Bindings.STRING); + return "Refers to variable " + variable + " that does not exist"; + } } 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 483f2d74..0cbbe11f 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 @@ -11,20 +11,18 @@ *******************************************************************************/ package org.simantics.sysdyn.ui.validation; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import java.util.Collections; +import java.util.List; -import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.issues.common.Issue; +import org.simantics.issues.common.StandardIssue; 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; /** @@ -35,139 +33,47 @@ import org.simantics.sysdyn.SysdynResource; */ public class ExpressionIssueFunction { - private static String getSyntaxErrorLabel(String name) throws DatabaseException { - return "Syntax error in " + name; - } - - private static String getUnsupportedCharacterLabel(String name) throws DatabaseException { - return "Unsupported character(s) in " + name; - } - - private static String getUndefinedExpressionLabel(String name) throws DatabaseException { - return "Undefined expression in " + name; - } + private static String SYNTAX_ERROR = "Syntax error"; + private static String UNSUPPORTED_CHARACTERS = "Unsupported characters"; + private static String UNDEFINED_EXPRESSION = "Undefined expression"; - @SCLValue(type = "a -> b -> c -> d") - public static Object expressionValidator(Object _graph, Object _resource, Object _existing) throws DatabaseException { - - ReadGraph graph = (ReadGraph)_graph; - Resource variable = (Resource)_resource; - Collection existing = (Collection)_existing; + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List expressionValidator(ReadGraph graph, Resource component) throws DatabaseException { SysdynResource sr = SysdynResource.getInstance(graph); - IssueResource ISSUE = IssueResource.getInstance(graph); - Layer0 l0 = Layer0.getInstance(graph); - if(!graph.isInstanceOf(variable, sr.IndependentVariable)) { - return Boolean.TRUE; + if(!graph.isInstanceOf(component, sr.IndependentVariable)) { + return Collections.emptyList(); } - 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); - } catch (SyntaxErrorException e) { - if(match(graph, existing, variable, getSyntaxErrorLabel(name)) == null) - return Boolean.FALSE; - } catch (UnsupportedCharactersException e) { - if(match(graph, existing, variable, getUnsupportedCharacterLabel(name)) == null) - return Boolean.FALSE; - } catch (UndefinedExpressionException e) { - if(match(graph, existing, variable, getUndefinedExpressionLabel(name)) == null) - return Boolean.FALSE; - } - - Resource context; - // There were no errors -> There should be no expression issues for this variable - for(Resource exist : existing) { - context = graph.getSingleObject(exist, ISSUE.HasIssueContext); - if(!graph.hasStatement(context) || graph.hasStatement(context, l0.PartOf)) - return Boolean.FALSE; - if(variable.equals(context) && graph.isInstanceOf(exist, sr.ExpressionIssue)) { - return Boolean.FALSE; - } + ValidationUtils.getReferences(graph, component); + } catch (Exception e) { + return Collections.singletonList(new StandardIssue(sr.Validations_ExpressionIssue, component)); } - - - return Boolean.TRUE; + return Collections.emptyList(); } - - @SCLValue(type = "a -> b -> c -> d -> e -> f") - public static Object expressionSynchronizer(Object _graph, Object _resource, Object _source, Object _model, Object _existing) throws DatabaseException { - WriteGraph graph = (WriteGraph)_graph; - Resource variable = (Resource)_resource; - Resource model = (Resource)_model; - Resource source = (Resource)_source; - Collection existing = (Collection)_existing; - Layer0 L0 = Layer0.getInstance(graph); + @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") + public static String expressionIssueDescription(ReadGraph graph, Resource converter, Variable issue) throws DatabaseException { IssueResource ISSUE = IssueResource.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); + Resource issueResource = issue.getRepresents(graph); + Resource list = graph.getSingleObject(issueResource, ISSUE.DependencyIssueSource2_Issue_HasContexts); + List contexts = ListUtils.toList(graph, list); + Resource component = contexts.get(0); - String name = graph.getRelatedValue(variable, L0.HasName, Bindings.STRING); - String label = null; - Resource issue = null; + // There should be an error try { - ValidationUtils.getReferences(graph, variable); + ValidationUtils.getReferences(graph, component); } catch (SyntaxErrorException e) { - label = getSyntaxErrorLabel(name); - if(match(graph, existing, variable, label) == null) - issue = ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Error, sr.ExpressionIssue); + return SYNTAX_ERROR; } catch (UnsupportedCharactersException e) { - label = getUnsupportedCharacterLabel(name); - if(match(graph, existing, variable, label) == null) - issue = ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Error, sr.ExpressionIssue); + return UNSUPPORTED_CHARACTERS; } catch (UndefinedExpressionException e) { - label = getUndefinedExpressionLabel(name); - if(match(graph, existing, variable, label) == null) - issue = ValidationUtils.createIssue(graph, model, source, variable, label, ISSUE.Severity_Error, sr.ExpressionIssue); - } - - Resource context; - Set toBeRemoved = new HashSet(); - for(Resource exist : existing) { - context = graph.getSingleObject(exist, ISSUE.HasIssueContext); - if(!graph.hasStatement(context) || !graph.hasStatement(context, L0.PartOf)) - toBeRemoved.add(exist); - else if(!exist.equals(issue) && graph.isInstanceOf(exist, sr.ExpressionIssue) && variable.equals(context)) { - String l = graph.getRelatedValue(exist, L0.HasLabel); - if(!l.equals(label)) { - toBeRemoved.add(exist); - } - } - } - - for(Resource r : toBeRemoved) { - ValidationUtils.removeIssue(graph, model, source, variable, r, existing); - } - - return Boolean.TRUE; - } - - - @SCLValue(type = "a -> b -> c") - public static Object expressionBaseRealizationFunction(Object _graph, Object _model) throws DatabaseException { - ReadGraph graph = (ReadGraph)_graph; - Resource model = (Resource)_model; - 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; - } - - - private static Resource match(ReadGraph graph, Collection existing, Resource variable, String description) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - IssueResource ISSUE = IssueResource.getInstance(graph); - for(Resource exist : existing) { - Resource source = graph.getSingleObject(exist, ISSUE.HasIssueContext); - String desc = graph.getRelatedValue(exist, L0.HasLabel); - if(source.equals(variable) && desc.equals(description)) return exist; - } - return null; + return UNDEFINED_EXPRESSION; + } + return "Erroneus error"; } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableIssue.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableIssue.java new file mode 100644 index 00000000..8368e095 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/NoSuchVariableIssue.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.UUID; + +import org.simantics.databoard.Bindings; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.issues.common.StandardIssue; +import org.simantics.issues.ontology.IssueResource; +import org.simantics.layer0.Layer0; +import org.simantics.sysdyn.SysdynResource; + +/** + * Issue class for NoSuchVariableIssues. Extended from StandardIssue to allow + * a string parameter containing the name of the variable in an equation that + * does not correspond to any existing and reachable variable. + * + * @author Teemu Lempinen + * + */ +public class NoSuchVariableIssue extends StandardIssue { + + public String missingVariable; + + public NoSuchVariableIssue(Resource type, String missingVariable, Resource ... contexts) { + super(type, contexts); + this.missingVariable = missingVariable; + } + + /** + * Same as in StandardIssue. Added Validations_NoSuchVariableIssue_variableName. + */ + @Override + public void write(WriteGraph graph, Resource model, Resource source) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + IssueResource IR = IssueResource.getInstance(graph); + Resource issue = graph.newResource(); + graph.claim(issue, L0.InstanceOf, null, type); + graph.claimLiteral(issue, L0.HasName, UUID.randomUUID().toString(), Bindings.STRING); + graph.claim(issue, IR.DependencyIssueSource2_Issue_HasContexts, ListUtils.create(graph, L0.List, contexts)); + DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); + String created = format.format(Calendar.getInstance().getTime()); + graph.claimLiteral(issue, IR.HasCreationTime, created, Bindings.STRING); + graph.claim(source, IR.Manages, issue); + graph.claim(model, L0.ConsistsOf, issue); + + // Modification to standard issue: + graph.claimLiteral(issue, SysdynResource.getInstance(graph).Validations_NoSuchVariableIssue_variableName, this.missingVariable, Bindings.STRING); + } + + @Override + public String toString() { + return Arrays.toString(contexts) + " + missing: " + missingVariable; + } + +} 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 d81d186e..11eb5f04 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 @@ -12,66 +12,39 @@ package org.simantics.sysdyn.ui.validation; import java.io.StringReader; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.UUID; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.util.RemoverUtil; -import org.simantics.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.expressionParser.ExpressionParser; import org.simantics.sysdyn.expressionParser.ParseException; import org.simantics.sysdyn.expressionParser.TokenMgrError; +/** + * + * @author Teemu Lempinen + * + */ public class ValidationUtils { - public static void removeIssue(WriteGraph graph, Resource model, Resource source, Resource variable, Resource issue, Collection existing) throws DatabaseException { - graph.deny(issue, Layer0.getInstance(graph).PartOf); - graph.deny(source, IssueResource.getInstance(graph).Manages, issue); - RemoverUtil.remove(graph, issue); - existing.remove(issue); - } - - public static Resource createIssue(WriteGraph graph, Resource model, Resource source, Resource variable, String label) throws DatabaseException { - return createIssue(graph, model, source, variable, label, IssueResource.getInstance(graph).Severity_Error); - } - - - public static Resource createIssue(WriteGraph graph, Resource model, Resource source, Resource variable, String label, Resource severity) throws DatabaseException { - return createIssue(graph, model, source, variable, label, severity, SysdynResource.getInstance(graph).SysdynIssue); - } - - - public static Resource createIssue(WriteGraph graph, Resource model, Resource source, Resource variable, String label, Resource severity, Resource type) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - IssueResource ISSUE = IssueResource.getInstance(graph); - - Resource issue = graph.newResource(); - graph.claim(issue, L0.InstanceOf, null, type); - graph.claim(issue, ISSUE.HasIssueContext, null, variable); - graph.claim(issue, ISSUE.HasSeverity, severity); - graph.claimLiteral(issue, L0.HasLabel, label, Bindings.STRING); - graph.claimLiteral(issue, L0.HasName, UUID.randomUUID().toString(), Bindings.STRING); - DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); - String created = format.format(Calendar.getInstance().getTime()); - graph.claimLiteral(issue, ISSUE.HasCreationTime, created, Bindings.STRING); - graph.claim(source, ISSUE.Manages, issue); - graph.claim(model, L0.ConsistsOf, issue); - return issue; - } - + /** + * Find all variables that are referred to in the expressions of variable r + * @param graph ReadGraph + * @param r Variable resource + * @return All names of the variables that are referred to in the expressions of r + * @throws DatabaseException + * @throws SyntaxErrorException + * @throws UnsupportedCharactersException + * @throws UndefinedExpressionException + */ public static HashSet getReferences(ReadGraph graph, Resource r) throws DatabaseException, SyntaxErrorException, UnsupportedCharactersException, UndefinedExpressionException { HashSet references = new HashSet(); ExpressionParser parser = new ExpressionParser(new StringReader("")); @@ -105,6 +78,13 @@ public class ValidationUtils { return references; } + /** + * Get all expressions of a variable r + * @param graph ReadGraph + * @param r Variable with expressions + * @return List of expression (resources) + * @throws DatabaseException + */ private static List getExpressions(ReadGraph graph, Resource r) throws DatabaseException { SysdynResource sr = SysdynResource.getInstance(graph); Resource hasExpressions = graph.getPossibleObject(r, sr.HasExpressions); @@ -155,6 +135,22 @@ public class ValidationUtils { * @throws DatabaseException */ public static boolean isReachable(ReadGraph graph, Resource variable, String reference) throws DatabaseException { + if(reach(graph, variable, reference) != null) + return true; + else + return false; + } + + /** + * Find a resource starting from variable and using reference path + * + * @param graph ReadGraph + * @param variable starting point + * @param reference path to another variable + * @return found variable or null + * @throws DatabaseException + */ + public static Resource reach(ReadGraph graph, Resource variable, String reference) throws DatabaseException { Layer0 l0 = Layer0.getInstance(graph); SysdynResource sr = SysdynResource.getInstance(graph); Resource configuration = graph.getSingleObject(variable, l0.PartOf); @@ -162,8 +158,9 @@ public class ValidationUtils { for(Resource var : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Variable))) { varName = graph.getRelatedValue(var, l0.HasName, Bindings.STRING); if(varName != null && reference.equals(varName)) - return true; + return var; } - return false; + return null; } + } -- 2.47.1