]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Better issues. Added new issue types and remove issue sources from module types....
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 15 Oct 2012 12:31:49 +0000 (12:31 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 15 Oct 2012 12:31:49 +0000 (12:31 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@26014 ac1ea38d-2e2b-0410-8846-a27921b304fc

16 files changed:
org.simantics.sysdyn.ontology/graph.tg
org.simantics.sysdyn.ontology/graph/Validation.pgraph
org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/imports/ImportModelHandler.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/functions/FunctionCodeWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ArrayVariableUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SyntaxError.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/DependencyFunction.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/Functions.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/References.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java

index 0475c6b5589ce60083775c487e276ca8a6701b57..6e0ebb774c87dc8294e41ef075f0f858092d68f2 100644 (file)
Binary files a/org.simantics.sysdyn.ontology/graph.tg and b/org.simantics.sysdyn.ontology/graph.tg differ
index 363c9d29ffe398eab743b4ee2d4bb1e5add97430..2932a309622c0b47719562c8a2060ed10d9ed834 100644 (file)
@@ -5,8 +5,9 @@ SYSDYN = <http://www.simantics.org/Sysdyn-1.1>
 \r
 VALIDATIONS = SYSDYN.Validations : L0.Library\r
 \r
-SYSDYN.SysdynIssue <T ISSUE.Issue\r
-\r
+VALIDATIONS.Issue <T ISSUE.Sources.DependencyTracker.Issue\r
+    >-- VALIDATIONS.Issue.stringContexts --> L0.List <R L0.DependsOn  \r
+    \r
 // BASEFUNCTION\r
 VALIDATIONS.Functions : L0.Library\r
 VALIDATIONS.Functions.baseRealizationFunction : L0.Function\r
@@ -29,7 +30,8 @@ VALIDATIONS.Enumerations.enumerationIndexValidator : L0.Function
 SYSDYN.Variable\r
     @VALIDATIONS.constraint\r
         VALIDATIONS.ExpressionConstraint\r
-        VALIDATIONS.Expressions.ExpressionIssueSource \r
+        VALIDATIONS.Expressions.ExpressionIssueSource\r
+            @L0.assert L0.HasName "ExpressionIssueSource" \r
         VALIDATIONS.Expressions.expressionValidator \r
         VALIDATIONS.Functions.baseRealizationFunction \r
         \r
@@ -37,13 +39,15 @@ SYSDYN.Variable
     @VALIDATIONS.constraint\r
         VALIDATIONS.DependencyConstraint\r
         VALIDATIONS.Dependencies.DependencyConnectionsIssueSource\r
+            @L0.assert L0.HasName "DependencyConnectionsIssueSource"\r
         VALIDATIONS.Dependencies.dependencyValidator \r
         VALIDATIONS.Functions.baseRealizationFunction \r
         \r
 SYSDYN.Enumeration\r
     @VALIDATIONS.constraint\r
         VALIDATIONS.EnumerationConstraint\r
-        VALIDATIONS.Enumerations.EnumerationIssueSource \r
+        VALIDATIONS.Enumerations.EnumerationIssueSource\r
+            @L0.assert L0.HasName "EnumerationIssueSource" \r
         VALIDATIONS.Enumerations.enumerationIndexValidator \r
         VALIDATIONS.Functions.baseRealizationFunction         \r
 \r
@@ -51,6 +55,7 @@ SYSDYN.Variable
     @VALIDATIONS.listeningConstraint\r
         VALIDATIONS.MissingDependencyConstraint\r
         VALIDATIONS.Dependencies.MissingDependencyConnectionsIssueSource\r
+            @L0.assert L0.HasName "MissingDependencyConnectionsIssueSource"\r
         VALIDATIONS.Dependencies.missingDependencyValidator  \r
         VALIDATIONS.Functions.baseRealizationFunction \r
         \r
@@ -60,35 +65,58 @@ VALIDATIONS.ExpressionIssue
         VALIDATIONS.Expressions.expressionIssueDescription : L0.Function\r
             L0.HasValueType "String"\r
         VALIDATIONS.Functions.path\r
-                    \r
+        \r
 VALIDATIONS.MissingLinkIssue\r
     @VALIDATIONS.issue\r
         ISSUE.Severity.Warning\r
         VALIDATIONS.Dependencies.missingLinkIssueDescription : L0.Function\r
             L0.HasValueType "String"\r
         VALIDATIONS.Functions.path\r
-                    \r
+                        \r
 VALIDATIONS.UnusedDependencyIssue\r
     @VALIDATIONS.issue\r
         ISSUE.Severity.Warning\r
         VALIDATIONS.Dependencies.unusedDependencyIssueDescription : L0.Function   \r
             L0.HasValueType "String"\r
         VALIDATIONS.Functions.path\r
-                    \r
+        \r
 VALIDATIONS.NoSuchVariableIssue\r
     @VALIDATIONS.issue\r
         ISSUE.Severity.Error\r
         VALIDATIONS.Dependencies.noSuchVariableIssueDescription : L0.Function     \r
             L0.HasValueType "String"\r
         VALIDATIONS.Functions.path\r
-            \r
+\r
+VALIDATIONS.RangeIssue\r
+    @VALIDATIONS.issue\r
+        ISSUE.Severity.Error\r
+        VALIDATIONS.Dependencies.rangeIssueDescription : L0.Function\r
+            L0.HasValueType "String"\r
+        VALIDATIONS.Functions.path        \r
+        \r
+VALIDATIONS.RangeWarning\r
+    @VALIDATIONS.issue\r
+        ISSUE.Severity.Warning\r
+        VALIDATIONS.Dependencies.rangeWarningDescription : L0.Function\r
+            L0.HasValueType "String"\r
+        VALIDATIONS.Functions.path                   \r
+        \r
+VALIDATIONS.InvalidSheetReferenceIssue\r
+    @VALIDATIONS.issue\r
+        ISSUE.Severity.Error\r
+        VALIDATIONS.Dependencies.invalidSheetReferenceIssueDescription : L0.Function\r
+            L0.HasValueType "String"\r
+        VALIDATIONS.Functions.path \r
+                    \r
 VALIDATIONS.EmptyEnumerationIssue\r
     @VALIDATIONS.issue\r
         ISSUE.Severity.Error\r
         VALIDATIONS.Enumerations.emptyEnumerationIssueDescription : L0.Function\r
             L0.HasValueType "String"\r
-        VALIDATIONS.Functions.path                 \r
-\r
+        VALIDATIONS.Functions.path     \r
+        \r
+        \r
+        \r
 // IssueSource template\r
 VALIDATIONS.constraint : L0.Template\r
     @template %type %constraint %source %validator %baseFunction\r
@@ -126,7 +154,7 @@ VALIDATIONS.listeningConstraint : L0.Template
 // Issue template\r
 VALIDATIONS.issue : L0.Template\r
     @template %issue %severity %description %path\r
-        %issue <T ISSUE.Sources.DependencyTracker.Issue\r
+        %issue <T SYSDYN.Validations.Issue\r
             L0.Asserts _ : L0.Assertion\r
                 L0.HasPredicate ISSUE.Issue.HasSeverity\r
                 L0.HasObject %severity\r
index 4f061c5198fe9bc482704c842ff4319dca121ca4..1b13475afee7920f26994d31e928c1663a9cd0ad 100644 (file)
@@ -291,7 +291,6 @@ public class SysdynResource {
     public final Resource Symbols;\r
     public final Resource SysdynConnectionType;\r
     public final Resource SysdynDiagramModelingRules;\r
-    public final Resource SysdynIssue;\r
     public final Resource SysdynModel;\r
     public final Resource SysdynModel_outputInterval;\r
     public final Resource SysdynModel_outputInterval_Inverse;\r
@@ -321,9 +320,12 @@ public class SysdynResource {
     public final Resource Validations_Dependencies_DependencyConnectionsIssueSource;\r
     public final Resource Validations_Dependencies_MissingDependencyConnectionsIssueSource;\r
     public final Resource Validations_Dependencies_dependencyValidator;\r
+    public final Resource Validations_Dependencies_invalidSheetReferenceIssueDescription;\r
     public final Resource Validations_Dependencies_missingDependencyValidator;\r
     public final Resource Validations_Dependencies_missingLinkIssueDescription;\r
     public final Resource Validations_Dependencies_noSuchVariableIssueDescription;\r
+    public final Resource Validations_Dependencies_rangeIssueDescription;\r
+    public final Resource Validations_Dependencies_rangeWarningDescription;\r
     public final Resource Validations_Dependencies_unusedDependencyIssueDescription;\r
     public final Resource Validations_DependencyConstraint;\r
     public final Resource Validations_EmptyEnumerationIssue;\r
@@ -341,9 +343,15 @@ public class SysdynResource {
     public final Resource Validations_Functions;\r
     public final Resource Validations_Functions_baseRealizationFunction;\r
     public final Resource Validations_Functions_path;\r
+    public final Resource Validations_InvalidSheetReferenceIssue;\r
+    public final Resource Validations_Issue;\r
+    public final Resource Validations_Issue_stringContexts;\r
+    public final Resource Validations_Issue_stringContexts_Inverse;\r
     public final Resource Validations_MissingDependencyConstraint;\r
     public final Resource Validations_MissingLinkIssue;\r
     public final Resource Validations_NoSuchVariableIssue;\r
+    public final Resource Validations_RangeIssue;\r
+    public final Resource Validations_RangeWarning;\r
     public final Resource Validations_UnusedDependencyIssue;\r
     public final Resource Validations_constraint;\r
     public final Resource Validations_issue;\r
@@ -673,7 +681,6 @@ public class SysdynResource {
         public static final String Symbols = "http://www.simantics.org/Sysdyn-1.1/Symbols";\r
         public static final String SysdynConnectionType = "http://www.simantics.org/Sysdyn-1.1/SysdynConnectionType";\r
         public static final String SysdynDiagramModelingRules = "http://www.simantics.org/Sysdyn-1.1/SysdynDiagramModelingRules";\r
-        public static final String SysdynIssue = "http://www.simantics.org/Sysdyn-1.1/SysdynIssue";\r
         public static final String SysdynModel = "http://www.simantics.org/Sysdyn-1.1/SysdynModel";\r
         public static final String SysdynModel_outputInterval = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/outputInterval";\r
         public static final String SysdynModel_outputInterval_Inverse = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/outputInterval/Inverse";\r
@@ -703,9 +710,12 @@ public class SysdynResource {
         public static final String Validations_Dependencies_DependencyConnectionsIssueSource = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/DependencyConnectionsIssueSource";\r
         public static final String Validations_Dependencies_MissingDependencyConnectionsIssueSource = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/MissingDependencyConnectionsIssueSource";\r
         public static final String Validations_Dependencies_dependencyValidator = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/dependencyValidator";\r
+        public static final String Validations_Dependencies_invalidSheetReferenceIssueDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/invalidSheetReferenceIssueDescription";\r
         public static final String Validations_Dependencies_missingDependencyValidator = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/missingDependencyValidator";\r
         public static final String Validations_Dependencies_missingLinkIssueDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/missingLinkIssueDescription";\r
         public static final String Validations_Dependencies_noSuchVariableIssueDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/noSuchVariableIssueDescription";\r
+        public static final String Validations_Dependencies_rangeIssueDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/rangeIssueDescription";\r
+        public static final String Validations_Dependencies_rangeWarningDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/rangeWarningDescription";\r
         public static final String Validations_Dependencies_unusedDependencyIssueDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Dependencies/unusedDependencyIssueDescription";\r
         public static final String Validations_DependencyConstraint = "http://www.simantics.org/Sysdyn-1.1/Validations/DependencyConstraint";\r
         public static final String Validations_EmptyEnumerationIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/EmptyEnumerationIssue";\r
@@ -723,9 +733,15 @@ public class SysdynResource {
         public static final String Validations_Functions = "http://www.simantics.org/Sysdyn-1.1/Validations/Functions";\r
         public static final String Validations_Functions_baseRealizationFunction = "http://www.simantics.org/Sysdyn-1.1/Validations/Functions/baseRealizationFunction";\r
         public static final String Validations_Functions_path = "http://www.simantics.org/Sysdyn-1.1/Validations/Functions/path";\r
+        public static final String Validations_InvalidSheetReferenceIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/InvalidSheetReferenceIssue";\r
+        public static final String Validations_Issue = "http://www.simantics.org/Sysdyn-1.1/Validations/Issue";\r
+        public static final String Validations_Issue_stringContexts = "http://www.simantics.org/Sysdyn-1.1/Validations/Issue/stringContexts";\r
+        public static final String Validations_Issue_stringContexts_Inverse = "http://www.simantics.org/Sysdyn-1.1/Validations/Issue/stringContexts/Inverse";\r
         public static final String Validations_MissingDependencyConstraint = "http://www.simantics.org/Sysdyn-1.1/Validations/MissingDependencyConstraint";\r
         public static final String Validations_MissingLinkIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/MissingLinkIssue";\r
         public static final String Validations_NoSuchVariableIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/NoSuchVariableIssue";\r
+        public static final String Validations_RangeIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/RangeIssue";\r
+        public static final String Validations_RangeWarning = "http://www.simantics.org/Sysdyn-1.1/Validations/RangeWarning";\r
         public static final String Validations_UnusedDependencyIssue = "http://www.simantics.org/Sysdyn-1.1/Validations/UnusedDependencyIssue";\r
         public static final String Validations_constraint = "http://www.simantics.org/Sysdyn-1.1/Validations/constraint";\r
         public static final String Validations_issue = "http://www.simantics.org/Sysdyn-1.1/Validations/issue";\r
@@ -1065,7 +1081,6 @@ public class SysdynResource {
         Symbols = getResourceOrNull(graph, URIs.Symbols);\r
         SysdynConnectionType = getResourceOrNull(graph, URIs.SysdynConnectionType);\r
         SysdynDiagramModelingRules = getResourceOrNull(graph, URIs.SysdynDiagramModelingRules);\r
-        SysdynIssue = getResourceOrNull(graph, URIs.SysdynIssue);\r
         SysdynModel = getResourceOrNull(graph, URIs.SysdynModel);\r
         SysdynModel_outputInterval = getResourceOrNull(graph, URIs.SysdynModel_outputInterval);\r
         SysdynModel_outputInterval_Inverse = getResourceOrNull(graph, URIs.SysdynModel_outputInterval_Inverse);\r
@@ -1095,9 +1110,12 @@ public class SysdynResource {
         Validations_Dependencies_DependencyConnectionsIssueSource = getResourceOrNull(graph, URIs.Validations_Dependencies_DependencyConnectionsIssueSource);\r
         Validations_Dependencies_MissingDependencyConnectionsIssueSource = getResourceOrNull(graph, URIs.Validations_Dependencies_MissingDependencyConnectionsIssueSource);\r
         Validations_Dependencies_dependencyValidator = getResourceOrNull(graph, URIs.Validations_Dependencies_dependencyValidator);\r
+        Validations_Dependencies_invalidSheetReferenceIssueDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_invalidSheetReferenceIssueDescription);\r
         Validations_Dependencies_missingDependencyValidator = getResourceOrNull(graph, URIs.Validations_Dependencies_missingDependencyValidator);\r
         Validations_Dependencies_missingLinkIssueDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_missingLinkIssueDescription);\r
         Validations_Dependencies_noSuchVariableIssueDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_noSuchVariableIssueDescription);\r
+        Validations_Dependencies_rangeIssueDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_rangeIssueDescription);\r
+        Validations_Dependencies_rangeWarningDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_rangeWarningDescription);\r
         Validations_Dependencies_unusedDependencyIssueDescription = getResourceOrNull(graph, URIs.Validations_Dependencies_unusedDependencyIssueDescription);\r
         Validations_DependencyConstraint = getResourceOrNull(graph, URIs.Validations_DependencyConstraint);\r
         Validations_EmptyEnumerationIssue = getResourceOrNull(graph, URIs.Validations_EmptyEnumerationIssue);\r
@@ -1115,9 +1133,15 @@ public class SysdynResource {
         Validations_Functions = getResourceOrNull(graph, URIs.Validations_Functions);\r
         Validations_Functions_baseRealizationFunction = getResourceOrNull(graph, URIs.Validations_Functions_baseRealizationFunction);\r
         Validations_Functions_path = getResourceOrNull(graph, URIs.Validations_Functions_path);\r
+        Validations_InvalidSheetReferenceIssue = getResourceOrNull(graph, URIs.Validations_InvalidSheetReferenceIssue);\r
+        Validations_Issue = getResourceOrNull(graph, URIs.Validations_Issue);\r
+        Validations_Issue_stringContexts = getResourceOrNull(graph, URIs.Validations_Issue_stringContexts);\r
+        Validations_Issue_stringContexts_Inverse = getResourceOrNull(graph, URIs.Validations_Issue_stringContexts_Inverse);\r
         Validations_MissingDependencyConstraint = getResourceOrNull(graph, URIs.Validations_MissingDependencyConstraint);\r
         Validations_MissingLinkIssue = getResourceOrNull(graph, URIs.Validations_MissingLinkIssue);\r
         Validations_NoSuchVariableIssue = getResourceOrNull(graph, URIs.Validations_NoSuchVariableIssue);\r
+        Validations_RangeIssue = getResourceOrNull(graph, URIs.Validations_RangeIssue);\r
+        Validations_RangeWarning = getResourceOrNull(graph, URIs.Validations_RangeWarning);\r
         Validations_UnusedDependencyIssue = getResourceOrNull(graph, URIs.Validations_UnusedDependencyIssue);\r
         Validations_constraint = getResourceOrNull(graph, URIs.Validations_constraint);\r
         Validations_issue = getResourceOrNull(graph, URIs.Validations_issue);\r
index 2a1296e7377e98959a266bf75c8a2c1b5c783e03..024bb2291a8104b337fc2a249c47785560ff9851 100644 (file)
@@ -40,7 +40,9 @@ import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler;\r
 import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
 import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.issues.ontology.IssueResource;\r
 import org.simantics.layer0.Layer0;\r
 import org.simantics.layer0.utils.direct.GraphUtils;\r
 import org.simantics.operation.Layer0X;\r
@@ -159,7 +161,10 @@ public class ImportModelHandler extends AbstractHandler {
                                                } else {\r
                                                        fixHasTailAndHasHead(graph, ModelRoot);\r
                                                        addDependencies(graph, ModelRoot);\r
+                                                       removeIssueSourcesFromModules(graph, ModelRoot);\r
                                                        addEnumerationIssueSource(graph, ModelRoot);\r
+                                                       \r
+                                                       activateModel(graph, ModelRoot);\r
                                                }\r
                                        }\r
 \r
@@ -173,7 +178,40 @@ public class ImportModelHandler extends AbstractHandler {
 \r
        }\r
        \r
-       protected void addDependencies(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
+       protected void removeIssueSourcesFromModules(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        IssueResource ISSUE = IssueResource.getInstance(graph);\r
+        \r
+        for(Resource m : findAllModelsAndModules(graph, modelRoot)) {\r
+            if(m.equals(modelRoot))\r
+                continue;\r
+            \r
+            // Module may contain issue sources due to legacy reasons. Remove these. \r
+            for(Resource issueSource : graph.syncRequest(new ObjectsWithType(m, L0.ConsistsOf, ISSUE.IssueSource))) {\r
+                // Issues are created to virtual graphs, so they should not need to be removed. Just in case they are created, remove them first\r
+                for(Resource issue : graph.getObjects(issueSource, ISSUE.IssueSource_Manages)) {\r
+                    RemoverUtil.remove(graph, issue);\r
+                }\r
+                \r
+                // finally remove the issue source\r
+                RemoverUtil.remove(graph, issueSource);\r
+            }\r
+        }\r
+           \r
+    }\r
+\r
+    protected void activateModel(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        Layer0X L0X = Layer0X.getInstance(graph);\r
+        if(!graph.hasStatement(modelRoot, L0X.IsActivatedBy)) {\r
+            Resource project = graph.getPossibleObject(modelRoot, L0.PartOf);\r
+            if(project != null) {\r
+                graph.claim(modelRoot, L0X.IsActivatedBy, project);\r
+            }\r
+        }\r
+    }\r
+\r
+    protected void addDependencies(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
                Layer0 L0 = Layer0.getInstance(graph);\r
 \r
                ArrayList<String> links = new ArrayList<String>();\r
index 39e7381d955862507c718a1d50b108ea41cdffcc..24c02b7eeed58eb9e7c530f820932fc4399f1057 100644 (file)
@@ -15,7 +15,6 @@ import java.util.List;
 \r
 import org.eclipse.jface.layout.GridDataFactory;\r
 import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.text.BadLocationException;\r
 import org.eclipse.jface.text.Document;\r
 import org.eclipse.jface.text.IDocument;\r
 import org.eclipse.jface.text.PaintManager;\r
@@ -36,13 +35,13 @@ import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.KeyListener;\r
 import org.eclipse.swt.events.VerifyEvent;\r
 import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Point;\r
 import org.eclipse.swt.graphics.RGB;\r
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.Display;\r
 import org.eclipse.swt.widgets.Table;\r
 import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.simantics.sysdyn.expressionParser.Token;\r
+import org.simantics.sysdyn.ui.utils.SyntaxError;\r
 \r
 /**\r
  * Field for displaying a part of an expression. Expression field uses SourceViewer\r
@@ -62,7 +61,8 @@ public class ExpressionField extends Composite {
     public static final String MISSING_LINK = "MissingLink";\r
     public static final String NO_SUCH_VARIABLE = "NoSuchVariable";\r
     public static final String SYNTAX_ERROR = "SyntaxError";\r
-    \r
+    public static final String SYNTAX_WARNING = "SyntaxWarning";\r
+\r
     String oldExpression;\r
 \r
     ColorManager cManager = new ColorManager();\r
@@ -112,6 +112,8 @@ public class ExpressionField extends Composite {
         painter.setAnnotationTypeColor(NO_SUCH_VARIABLE, new Color(this.getDisplay(), 255,0,0));\r
         painter.addAnnotationType(SYNTAX_ERROR);\r
         painter.setAnnotationTypeColor(SYNTAX_ERROR, new Color(this.getDisplay(), 255,0,0));        \r
+        painter.addAnnotationType(SYNTAX_WARNING);\r
+        painter.setAnnotationTypeColor(SYNTAX_WARNING, new Color(this.getDisplay(), 255,215,0));\r
         \r
         _sourceViewer.setDocument(_document, _annotationModel);\r
 \r
@@ -221,59 +223,16 @@ public class ExpressionField extends Composite {
         }\r
     }\r
 \r
-    /**\r
-     * Sets syntax error for the given token\r
-     * @param token Token with syntax error\r
-     * @param message Message to be displayed in tool tips\r
-     */\r
-    public void setSyntaxError(Token token, String message){\r
-       setSyntaxError(token.image, message, token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
-    }\r
-    \r
-    /**\r
-     * Sets syntax error for the given token\r
-     * @param token Token with syntax error\r
-     * @param message Message to be displayed in tool tips\r
-     */\r
-    public void setSyntaxError(org.simantics.sysdyn.tableParser.Token token, String message){\r
-       setSyntaxError(token.image, message, token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
-    }\r
-    \r
-    /**\r
-     * Sets syntax error to given location\r
-     * @param image Token image\r
-     * @param message Message to be displayed in tool tips\r
-     * @param beginLine Begin line\r
-     * @param beginColumn Begin column\r
-     * @param endLine End line\r
-     * @param endColumn End column\r
-     */\r
-    public void setSyntaxError(String image, String message, int beginLine, int beginColumn, int endLine, int endColumn) {\r
-        int start = 0;\r
-        int offset = this._document.getLength();\r
-        if(image != null && this._document.getLength() > 0) {\r
-            try {\r
-                start = this._document.getLineOffset(beginLine - 1) + beginColumn - 1;\r
-                offset = this._document.getLineOffset(endLine - 1) + endColumn - start;\r
-            } catch (BadLocationException e) {\r
-                e.printStackTrace();\r
-            }\r
-        }\r
-        setSyntaxError(start, offset, SYNTAX_ERROR, message == null ? "Syntax Error" : message);\r
-    }\r
     \r
     /**\r
-     * Sets syntax error to given start and offset\r
-     * @param start Start location\r
-     * @param offset Offset\r
-     * @param type Error type (SYNTAX_ERROR, MISSING_LINK, NO_SUCH_VARIABLE)\r
-     * @param text Message to be displayedin tool tips\r
+     * Sets a syntax error annoattion to the expression field\r
+     * @param syntaxError\r
      */\r
-    public void setSyntaxError(int start, int offset, String type, String text) {\r
+    public void setSyntaxError(SyntaxError syntaxError) {\r
         Annotation annotation = new Annotation(false);\r
-        annotation.setType(type);\r
-        annotation.setText(text);\r
-        Position p = new Position(start, offset);\r
+        annotation.setType(syntaxError.getType());\r
+        annotation.setText(syntaxError.getMessage());\r
+        Position p = new Position(syntaxError.getStart(_document), syntaxError.getOffset(_document));\r
         _annotationModel.addAnnotation(annotation, p);      \r
     }\r
 \r
index 5d2fa12e6e34932f958cd518b0dbd42bf7e7fed7..8da88f5ddaabdd5c9e349283d494bc7d20dfcfba 100644 (file)
@@ -64,6 +64,7 @@ import org.simantics.sysdyn.SysdynResource;
 import org.simantics.sysdyn.tableParser.ParseException;\r
 import org.simantics.sysdyn.tableParser.TableParser;\r
 import org.simantics.sysdyn.tableParser.Token;\r
+import org.simantics.sysdyn.ui.utils.SyntaxError;\r
 import org.simantics.ui.SimanticsUI;\r
 \r
 public class WithLookupExpression implements IExpression {\r
@@ -392,7 +393,7 @@ public class WithLookupExpression implements IExpression {
                         Double.parseDouble(yTokens.get(i).image)));\r
             }\r
         } catch (ParseException e1) {\r
-            this.lookup.setSyntaxError(e1.currentToken, "Syntax Error");\r
+            this.lookup.setSyntaxError(new SyntaxError(e1.currentToken, "Syntax Error"));\r
             System.out.println("MESSAGE: " + e1.getMessage());\r
             return;\r
         }\r
index 8fd7bdb8ba73dfbce7dcf47524892782dc7dca58..2d0cb58d077c624ade9f338a04f65dfe5434aff4 100644 (file)
@@ -43,6 +43,7 @@ import org.simantics.sysdyn.modelParser.ParseException;
 import org.simantics.sysdyn.modelParser.Token;\r
 import org.simantics.sysdyn.modelParser.TokenMgrError;\r
 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionField;\r
+import org.simantics.sysdyn.ui.utils.SyntaxError;\r
 import org.simantics.ui.SimanticsUI;\r
 import org.simantics.ui.utils.AdaptionUtils;\r
 \r
@@ -164,7 +165,7 @@ public class FunctionCodeWidget implements Widget {
                        modelParser.parse_composition();\r
                } catch (ParseException e1) {\r
                        Token token = e1.currentToken;\r
-                       modelicaCode.setSyntaxError(token.image, "Syntax error", token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
+                       modelicaCode.setSyntaxError(new SyntaxError(token.image, "Syntax error", token.beginLine, token.beginColumn, token.endLine, token.endColumn));\r
                } catch (TokenMgrError err) {\r
                        String message = err.getMessage();\r
                        String line = message.substring(0, message.indexOf(","));\r
@@ -175,7 +176,7 @@ public class FunctionCodeWidget implements Widget {
                                Integer endLine = Integer.parseInt(line);\r
                                Integer endColumn = Integer.parseInt(column);\r
                                Token token = modelParser.token;\r
-                               modelicaCode.setSyntaxError(token.image, "Syntax error", token.endLine, token.endColumn, endLine, endColumn);\r
+                               modelicaCode.setSyntaxError(new SyntaxError(token.image, "Syntax error", token.endLine, token.endColumn, endLine, endColumn));\r
                        } catch (NumberFormatException e) {\r
                                \r
                        }\r
index 574f71b8f3d7a35d6907ee5faeccd150c84ac89a..88cc72299143839aaabb8efd745867cca2925e13 100644 (file)
@@ -12,102 +12,143 @@ import org.simantics.sysdyn.representation.Enumeration;
 import org.simantics.sysdyn.representation.EnumerationIndex;\r
 import org.simantics.sysdyn.representation.IElement;\r
 import org.simantics.sysdyn.representation.Variable;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionField;\r
 \r
 public class ArrayVariableUtils {\r
 \r
 \r
-       /**\r
-        * Checks if the given range elements can be applied to the given variable.\r
-        * \r
-        * @param graph ReadGraph\r
-        * @param variable Resource of the variable \r
-        * @param range Range elements in the correct order. Elements are separated in range definition by ',' \r
-        * @return true if range is valid, false if not\r
-        * @throws DatabaseException\r
-        */\r
-       public static Map<Integer, String> isRangeValid(ReadGraph graph, Variable variable, String[] elements) throws DatabaseException {\r
-               if(variable == null)\r
-                       return null;\r
-               Map<Integer, String> result = new HashMap<Integer, String>();\r
-               // Not an array variable\r
-               if(variable.getArrayIndexes() == null || \r
-                       variable.getArrayIndexes().getEnumerations() == null || \r
-                       variable.getArrayIndexes().getEnumerations().size() == 0) {\r
-                       for(int i = 0; i < elements.length ; i++)\r
-                               result.put(i, "Variable is not an array variable");\r
-                       return result;\r
-               }\r
-               ArrayList<Enumeration> enumerations = variable.getArrayIndexes().getEnumerations();\r
-               // Too many elements\r
-               if(elements.length > enumerations.size()) {\r
-                       result.put( enumerations.size(), "Too many elements");\r
-               } else if(elements.length < enumerations.size()) {\r
-                       result.put( elements.length > 0 ? elements.length - 1 : 0, "Too few elements");\r
-               }\r
-               \r
-               \r
-               for(int i = 0; i < elements.length && i < enumerations.size(); i++) {\r
-                       if(elements[i].trim().equals(":"))\r
-                               continue;\r
-                       if(elements[i].indexOf(":") != elements[i].lastIndexOf(":")) {\r
-                               result.put( i, "Too many ':' elements");\r
-                               continue;\r
-                       }\r
+    /**\r
+     * Checks if the given range elements can be applied to the given variable.\r
+     * \r
+     * @param graph ReadGraph\r
+     * @param variable Resource of the variable \r
+     * @param range Range elements in the correct order. Elements are separated in range definition by ',' \r
+     * @return true if range is valid, false if not\r
+     * @throws DatabaseException\r
+     */\r
+    public static Map<Integer, SyntaxError> isRangeValid(ReadGraph graph, Variable variable, String[] elements) throws DatabaseException {\r
+        SyntaxError error;\r
+        if(variable == null)\r
+            return null;\r
+        Map<Integer, SyntaxError> result = new HashMap<Integer, SyntaxError>();\r
+        // Not an array variable\r
+        if(variable.getArrayIndexes() == null || \r
+                variable.getArrayIndexes().getEnumerations() == null || \r
+                variable.getArrayIndexes().getEnumerations().size() == 0) {\r
+            for(int i = 0; i < elements.length ; i++) {\r
+                error = new SyntaxError();\r
+                error.setMessage("Variable is not an array variable");\r
+                error.setType(ExpressionField.SYNTAX_ERROR);\r
+                result.put(i, error);\r
+            }\r
 \r
-                       String[] rangeComponents = elements[i].split(":");\r
-                       if(rangeComponents.length > 2){\r
-                               result.put( i, "Too many ':' elements");\r
-                               continue;\r
-                       }\r
-                       // Single range component, equals to the enumeration at that index\r
-                       if(rangeComponents.length == 1 && rangeComponents[0].trim().equals(enumerations.get(i).getName()))\r
-                               continue;\r
-                       // one or two range components, they all equal to individual indexes in the enumeration\r
-                       for(String r : rangeComponents) {\r
-                               r = r.trim();\r
-                               boolean componentIsValid = false;\r
-                               for(EnumerationIndex ei : enumerations.get(i).getEnumerationIndexes()) {\r
-                                       if(ei.getName().equals(r)) {\r
-                                               componentIsValid = true;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               if(!componentIsValid)\r
-                                       result.put( i, "Invalid range");\r
-                       }\r
-               }\r
-               if(result.isEmpty())\r
-                       return null;\r
-               else\r
-                       return result;\r
-       }\r
+            return result;\r
+        }\r
+        ArrayList<Enumeration> enumerations = variable.getArrayIndexes().getEnumerations();\r
+        // Too many elements\r
+        if(elements.length > enumerations.size()) {\r
+            error = new SyntaxError();\r
+            error.setMessage( "Too many elements");\r
+            error.setType(ExpressionField.SYNTAX_ERROR);\r
+            result.put(enumerations.size(), error);\r
+        } else if(elements.length < enumerations.size()) {\r
+            error = new SyntaxError();\r
+            error.setMessage("Too few elements");\r
+            error.setType(ExpressionField.SYNTAX_ERROR);\r
+            result.put(elements.length > 0 ? elements.length - 1 : 0, error);\r
+        }\r
 \r
-       /**\r
-        * Checks if the given range can be applied to the given variable.\r
-        * \r
-        * @param graph ReadGraph\r
-        * @param variable Resource of the variable \r
-        * @param range Range WITHOUT [ and ] brackets\r
-        * @return true if range is valid, false if not\r
-        * @throws DatabaseException\r
-        */\r
-       public static boolean isRangeValid(ReadGraph graph, Resource variable, String range) throws DatabaseException {\r
-               if(variable == null)\r
-                       return true;\r
-               String[] elements = range.split(",");\r
-               SysdynModel model = ModelUtils.getModel(graph, variable);\r
-               if(model == null)\r
-                       return false;\r
-               IElement e = model.getElement(variable);\r
-               if(e != null && e instanceof Variable) {\r
-                       Variable v = (Variable) e;\r
-                       Map<Integer, String> result = isRangeValid(graph, v, elements);\r
-                       if(result == null)\r
-                               return true;\r
-                       else\r
-                               return false;\r
-               } else {\r
-                       return false;\r
-               }\r
-       }\r
+\r
+        for(int i = 0; i < elements.length && i < enumerations.size(); i++) {\r
+            if(elements[i].trim().equals(":"))\r
+                continue;\r
+            if(elements[i].indexOf(":") != elements[i].lastIndexOf(":")) {\r
+                error = new SyntaxError();\r
+                error.setMessage( "Too many ':' elements");\r
+                error.setType(ExpressionField.SYNTAX_ERROR);\r
+                result.put(i, error);\r
+                continue;\r
+            }\r
+\r
+            String[] rangeComponents = elements[i].split(":");\r
+            if(rangeComponents.length > 2){\r
+                error = new SyntaxError();\r
+                error.setMessage( "Too many ':' elements");\r
+                error.setType(ExpressionField.SYNTAX_ERROR);\r
+                result.put(i, error);\r
+                continue;\r
+            }\r
+            // Single range component, equals to the enumeration at that index\r
+            if(rangeComponents.length == 1 && rangeComponents[0].trim().equals(enumerations.get(i).getName()))\r
+                continue;\r
+            // one or two range components, they all equal to individual indexes in the enumeration\r
+            for(String r : rangeComponents) {\r
+                r = r.trim();\r
+                boolean componentIsValid = false;\r
+                for(EnumerationIndex ei : enumerations.get(i).getEnumerationIndexes()) {\r
+                    if(ei.getName().equals(r)) {\r
+                        componentIsValid = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if(!componentIsValid) {\r
+                    // Check if the range is an integer that is between 0 and enumeration indexes size\r
+                    try {\r
+                        int index = Integer.parseInt(r);\r
+                        int min = 1;\r
+                        int max = enumerations.get(i).getEnumerationIndexes().size();\r
+                        if(index >= min && index <= max) {\r
+                            componentIsValid = true;\r
+                            error = new SyntaxError();\r
+                            error.setMessage("Using numbers as array indexes is not encouraged");\r
+                            error.setType(ExpressionField.SYNTAX_WARNING);\r
+                            result.put(i, error);\r
+                        } else {\r
+                            error = new SyntaxError();\r
+                            error.setMessage("Invalid array index " + index + ". Numbered index must be between " + min + " and " + max + " unless the enumeration is overridden. In that case, ignore this warning.");\r
+                            error.setType(ExpressionField.SYNTAX_ERROR);\r
+                            result.put(i, error);\r
+                        }\r
+                    } catch (NumberFormatException e) {\r
+                        error = new SyntaxError();\r
+                        error.setMessage("Invalid range");\r
+                        error.setType(ExpressionField.SYNTAX_ERROR);\r
+                        result.put(i, error);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        if(result.isEmpty())\r
+            return null;\r
+        else\r
+            return result;\r
+    }\r
+\r
+    /**\r
+     * Checks if the given range can be applied to the given variable.\r
+     * \r
+     * @param graph ReadGraph\r
+     * @param variable Resource of the variable \r
+     * @param range Range WITHOUT [ and ] brackets\r
+     * @return true if range is valid, false if not\r
+     * @throws DatabaseException\r
+     */\r
+    public static boolean isRangeValid(ReadGraph graph, Resource variable, String range) throws DatabaseException {\r
+        if(variable == null)\r
+            return true;\r
+        String[] elements = range.split(",");\r
+        SysdynModel model = ModelUtils.getModel(graph, variable);\r
+        if(model == null)\r
+            return false;\r
+        IElement e = model.getElement(variable);\r
+        if(e != null && e instanceof Variable) {\r
+            Variable v = (Variable) e;\r
+            if(isRangeValid(graph, v, elements) == null)\r
+                return true;\r
+            else\r
+                return false;\r
+        } else {\r
+            return false;\r
+        }\r
+    }\r
 }\r
index c9419675b3b31088327ef0d2ab7248c73a414ef0..758b90f8d7616965a7b663c88f764e3589589c7a 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.sysdyn.ui.utils;
 \r
 import java.io.StringReader;\r
 import java.util.ArrayList;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.Iterator;\r
@@ -141,27 +142,28 @@ public class ExpressionUtils {
                 functionReferences.put(ef, parser.getFunctionCallReferences());\r
 \r
             } catch (ParseException e1) {\r
-                ef.setSyntaxError(e1.currentToken, "Syntax Error");\r
+                ef.setSyntaxError(new SyntaxError(e1.currentToken, "Syntax Error"));\r
             } catch (TokenMgrError err) {\r
-                ef.setSyntaxError(0, textString.length(), ExpressionField.SYNTAX_ERROR, "Expression contains unsupported characters");\r
+                ef.setSyntaxError(new SyntaxError(0, textString.length(), ExpressionField.SYNTAX_ERROR, "Expression contains unsupported characters"));\r
             }\r
         }\r
 \r
 \r
+        // Get model configuration\r
+        SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession());\r
+        SysdynModel model = sdm.getModel(configuration);\r
+        try {\r
+            model.update();\r
+        } catch (DatabaseException e1) {\r
+            e1.printStackTrace();\r
+        }\r
+        Configuration conf = model.getConfiguration();\r
+        \r
+        // Check variable references\r
         final HashMap<String, Variable> modelVariables = new HashMap<String, Variable>();\r
         HashSet<String> ignoreVariables = new HashSet<String>();\r
-\r
         if(!variables.isEmpty() || !functionReferences.isEmpty()) {\r
             Set<String> noSuchVariables = new HashSet<String>();\r
-            SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession());\r
-            SysdynModel model = sdm.getModel(configuration);\r
-            try {\r
-                model.update();\r
-            } catch (DatabaseException e1) {\r
-                e1.printStackTrace();\r
-            }\r
-\r
-            Configuration conf = model.getConfiguration();\r
             ArrayList<IElement> elements = conf.getElements();\r
             for(IElement e : elements) {\r
                 if(e instanceof Variable) {\r
@@ -180,71 +182,26 @@ public class ExpressionUtils {
             // Examine sheets\r
             for(ExpressionField ef : functionReferences.keySet()) {\r
                 for(String key : functionReferences.get(ef).keySet()) {\r
-                    String[] parts = key.split("\\.");\r
-                    Object current = conf;\r
-                    for(int i = 0; i < parts.length && current != null; i++) {\r
-                        current = getElement(current, parts[i]);\r
-                    }\r
                     \r
-                    if(current == null && conf.getModuleType() != null) {\r
-                       // Sheets are currently located in the model root. Try to find the sheet.\r
-                       current = conf.getModuleType().getParent(); // Get module type parent (should be a model)\r
-                       if(current instanceof Model)\r
-                               current = getElement(((Model)current).getModelConfiguration(), parts[0]); // Try to get the sheet\r
-                    }\r
-                    \r
-                    if(current != null && current instanceof Sheet) {\r
-                        Sheet sheet = (Sheet) current;\r
-                        String e = ef.getExpression();\r
-                        int start = 0, end = 0, call = 0;\r
-                        String cellOrRange = null;\r
-                        while((call = e.indexOf(key, end)) >= 0) {\r
-                            start = e.indexOf("(", call) +1;\r
-                            end = e.indexOf(")", start);\r
-                            if(start < 0 || end < 0 || end < start) {\r
-                                break;\r
-                            }\r
-                            Pattern p = Pattern.compile("[-\\+\\*\\/\\(\\)\\{\\}\\[\\],\\.\\t\\n\\r\\f]");\r
-                            cellOrRange = e.substring(start, end);\r
-                            Matcher m = p.matcher(cellOrRange);\r
-                            if (m.find() || cellOrRange.split(":").length > 2) {\r
-                                ef.setSyntaxError(start, end - start, ExpressionField.SYNTAX_ERROR, "Not a valid cell or range");\r
-                            }\r
-                        }\r
-\r
-                        List<Token> tokens = functionReferences.get(ef).get(key);\r
-                        for(Token cell : tokens) {\r
-                            List<Token> refs = references.get(ef).get(cell.image);\r
-                            if(refs != null)\r
-                                refs.remove(cell);\r
-                            if(!sheet.getCells().containsKey(cell.image))\r
-                                ef.setSyntaxError(cell.image, "Invalid cell", cell.beginLine, cell.beginColumn, cell.endLine, cell.endColumn); \r
-                        }\r
-\r
+                    List<SyntaxError> errors = examineSheetReferences(conf, key, functionReferences.get(ef).get(key), ef.getExpression(), references.get(ef));\r
+                    if(errors != null) {\r
+                        for(SyntaxError error : errors)\r
+                            ef.setSyntaxError(error);\r
                     }\r
                 }\r
             }\r
 \r
+            // Examine variable references\r
             for(String v : variables) {\r
-\r
-                if(modelVariables.get(v) instanceof Enumeration || modelVariables.get(v) instanceof Sheet) {\r
-                    ignoreVariables.add(v);\r
-                }\r
-\r
-                // Reference to some other module, spreadsheet or enumeration\r
-                if(v.contains(".")) {\r
-                    String[] parts = v.split("\\.");\r
-                    Object parent = conf;\r
-                    for(int i = 0; i < parts.length && parent != null; i++) {\r
-                        parent = getElement(parent, parts[i]);\r
-                    }\r
-                    if(parent == null) {\r
+                ReferenceOption option = getReferenceOption(conf, v);\r
+                switch(option) {\r
+                    case DOES_NOT_EXIST:\r
                         noSuchVariables.add(v);\r
-                    } else {\r
+                        break;\r
+                    case CANNOT_BE_CONNECTED:\r
                         ignoreVariables.add(v);\r
-                    }\r
-                } else if(!modelVariables.keySet().contains(v)) {\r
-                    noSuchVariables.add(v);\r
+                        break;\r
+                    case CAN_BE_CONNECTED:\r
                 }\r
             }\r
 \r
@@ -289,119 +246,252 @@ public class ExpressionUtils {
         } \r
 \r
 \r
+        for(final ExpressionField ef : ranges.keySet()) {\r
+            List<SyntaxError> errors = new ArrayList<SyntaxError>();\r
+            // RANGES\r
+            errors.addAll(examineArrayRanges(conf, ranges.get(ef), forIndices.get(ef)));\r
+            \r
+            // ENUMERATION REFERENCES IN FOR-LOOPS\r
+            errors.addAll(examineEnumerationReferences(conf, enumerationReferences.get(ef)));\r
 \r
-        HashMap<ExpressionField, HashMap<Token, String>> errors = new HashMap<ExpressionField, HashMap<Token, String>>();\r
-        HashMap<Token, String> result = null;\r
+            for(SyntaxError error : errors)\r
+                ef.setSyntaxError(error);\r
+        }                                      \r
+    }\r
+    \r
+    \r
+    static public List<SyntaxError> examineArrayRanges(\r
+            final Configuration configuration,\r
+            final HashMap<String, List<List<Token>>> ranges,\r
+            final HashMap<Token, List<Token>> forIndices) {\r
+        \r
+        List<SyntaxError> result = Collections.emptyList();\r
+        try {\r
+            result = SimanticsUI.getSession().syncRequest(new Read<List<SyntaxError>>() {\r
 \r
-        for(final ExpressionField ef : ranges.keySet()) {\r
+                @Override\r
+                public List<SyntaxError> perform(ReadGraph graph) throws DatabaseException {\r
+                    return examineArrayRanges(graph, configuration, ranges, forIndices);\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return result;\r
+    }\r
 \r
-            // RANGES\r
-            try {\r
-                result = SimanticsUI.getSession().syncRequest(new Read<HashMap<Token, String>>() {\r
-\r
-                    @Override\r
-                    public HashMap<Token, String> perform(ReadGraph graph) throws DatabaseException {\r
-                        HashMap<Token, String> result = new HashMap<Token, String>();\r
-                        for(String s : ranges.get(ef).keySet()) {\r
-                            if(ranges.get(ef).containsKey(s)) {\r
-                                for(List<Token> l : ranges.get(ef).get(s)) {\r
-                                    String[] ss = new String[l.size()];\r
-                                    for(int i = 0; i < l.size(); i++) {\r
-                                        ss[i] = l.get(i).image;\r
-                                    }\r
-                                    Map<Integer, String> invalidRanges = ArrayVariableUtils.isRangeValid(graph, modelVariables.get(s), ss);\r
-                                    if(invalidRanges != null && !invalidRanges.isEmpty()) {\r
-                                        for(Integer i : invalidRanges.keySet()) {\r
-                                            result.put(l.get(i), invalidRanges.get(i));\r
-                                        }\r
-                                    }\r
-                                }\r
+    static public List<SyntaxError> examineEnumerationReferences(Configuration configuration, HashMap<String, List<Token>> enumRefList) {\r
+        ArrayList<SyntaxError> result = new ArrayList<SyntaxError>();\r
+        for(String enumeration : enumRefList.keySet()) {\r
+            for(Token et : enumRefList.get(enumeration)) {\r
+                Object o = getElement(configuration, enumeration);\r
+                if(o != null && o instanceof Enumeration) {\r
+                    boolean isFound = false;\r
+                    Enumeration e = (Enumeration)o;\r
+\r
+                    if(enumeration.equals(et.image) ||\r
+                            "size".equals(et.image) || \r
+                            "elements".equals(et.image)){\r
+                        // The full enumeration\r
+                        isFound = true;\r
+                    } else {\r
+                        for(EnumerationIndex ei : e.getEnumerationIndexes()) {\r
+                            if(ei.getName().equals(et.image)) {\r
+                                isFound = true;\r
+                                break;\r
                             }\r
-                        }      \r
-                        return result;\r
+                        }\r
                     }\r
-                });\r
-            } catch (DatabaseException e) {\r
-                e.printStackTrace();\r
-            }\r
 \r
-            // FOR-INDICES\r
-\r
-            HashMap<Token, List<Token>> indexList = forIndices.get(ef);\r
-            for(Token t : indexList.keySet()) {\r
-                boolean isFound = false;\r
-                if(indexList.get(t) != null) {\r
-                    for(Token rt : indexList.get(t)) {\r
-                        if(rt.image.equals(t.image)) {\r
-                            isFound = true;\r
-                            // remove range token from invalid ranges\r
-                            result.remove(rt);\r
-                            break;\r
+                    if(!isFound) {\r
+                        StringBuilder sb = new StringBuilder();\r
+                        sb.append("Enumeration ");\r
+                        sb.append(enumeration);\r
+                        sb.append(" has no such index.\nAvailable indexes are: ");\r
+                        Iterator<EnumerationIndex> iterator = e.getEnumerationIndexes().iterator();\r
+                        while(iterator.hasNext()) {\r
+                            sb.append(iterator.next().getName());\r
+                            if(iterator.hasNext()) \r
+                                sb.append(", ");\r
                         }\r
+                        result.add(new SyntaxError(et, sb.toString()));\r
                     }\r
-                }\r
-                if(!isFound) {\r
-                    result.put(t, "Invalid index");\r
+\r
+\r
+                } else {\r
+                    result.add(new SyntaxError(et, "No such enumeration (" + enumeration + ")")); \r
                 }\r
             }\r
+        }\r
+        return result;\r
+    }\r
 \r
-            // ENUMERATION REFERENCES IN FOR-LOOPS\r
-            HashMap<String, List<Token>> enumRefList = enumerationReferences.get(ef);\r
-            for(String enumeration : enumRefList.keySet()) {\r
-                for(Token et : enumRefList.get(enumeration)) {\r
-                    Variable v = modelVariables.get(enumeration);\r
-                    if(v != null && v instanceof Enumeration) {\r
-                        boolean isFound = false;\r
-                        Enumeration e = (Enumeration)v;\r
-\r
-                        if(enumeration.equals(et.image) ||\r
-                                "size".equals(et.image) || \r
-                                "elements".equals(et.image)){\r
-                            // The full enumeration\r
-                            isFound = true;\r
-                        } else {\r
-                            for(EnumerationIndex ei : e.getEnumerationIndexes()) {\r
-                                if(ei.getName().equals(et.image)) {\r
-                                    isFound = true;\r
-                                    break;\r
-                                }\r
-                            }\r
-                        }\r
+    /**\r
+     * \r
+     * @param graph\r
+     * @param configuration\r
+     * @param ranges\r
+     * @param forIndices\r
+     * @return\r
+     * @throws DatabaseException\r
+     */\r
+    static public List<SyntaxError> examineArrayRanges(\r
+            ReadGraph graph, \r
+            Configuration configuration,\r
+            HashMap<String, List<List<Token>>> ranges,\r
+            HashMap<Token, List<Token>> forIndices) throws DatabaseException {\r
+        HashMap<Token, SyntaxError> errors = new HashMap<Token, SyntaxError>();\r
+        for(String name : ranges.keySet()) {\r
+            if(ranges.get(name) != null) {\r
+                for(List<Token> l : ranges.get(name)) {\r
+                    String[] rangeReferences = new String[l.size()];\r
+                    for(int i = 0; i < l.size(); i++) {\r
+                        rangeReferences[i] = l.get(i).image;\r
+                    }\r
 \r
-                        if(!isFound) {\r
-                            StringBuilder sb = new StringBuilder();\r
-                            sb.append("Enumeration ");\r
-                            sb.append(enumeration);\r
-                            sb.append(" has no such index.\nAvailable indexes are: ");\r
-                            Iterator<EnumerationIndex> iterator = e.getEnumerationIndexes().iterator();\r
-                            while(iterator.hasNext()) {\r
-                                sb.append(iterator.next().getName());\r
-                                if(iterator.hasNext()) \r
-                                    sb.append(", ");\r
+                    Object o = getElement(configuration, name);\r
+                    if(o != null && o instanceof Variable) {\r
+                        Map<Integer, SyntaxError> invalidRanges = ArrayVariableUtils.isRangeValid(graph, (Variable)o, rangeReferences);\r
+                        if(invalidRanges != null && !invalidRanges.isEmpty()) {\r
+                            for(Integer i : invalidRanges.keySet()) {\r
+                                SyntaxError error = invalidRanges.get(i);\r
+                                error.setToken(l.get(i));\r
+                                errors.put(l.get(i), error);\r
                             }\r
-                            result.put(et, sb.toString());\r
                         }\r
-\r
-\r
-                    } else {\r
-                        result.put(et, "No such enumeration (" + enumeration + ")");\r
                     }\r
                 }\r
             }\r
-\r
-            errors.put(ef, result);\r
+        } \r
 \r
 \r
-        }                                      \r
+        // FOR-INDICES\r
 \r
-        for(ExpressionField ef : ranges.keySet()) {\r
-            HashMap<Token, String> tokens = errors.get(ef);\r
-            if(tokens == null || tokens.isEmpty()) continue;\r
-            for(Token t : tokens.keySet()) {\r
-                ef.setSyntaxError(t, tokens.get(t));\r
+        HashSet<Token> removes = new HashSet<Token>();\r
+        for(Token t : forIndices.keySet()) {\r
+            boolean isFound = false;\r
+            for(Token rt : errors.keySet()) {\r
+                if(rt.image.equals(t.image)) {\r
+                    isFound = true;\r
+                    // remove range token from invalid ranges\r
+                    removes.add(rt);\r
+                }\r
             }\r
+            if(!isFound) {\r
+                SyntaxError error = new SyntaxError(t, "Invalid index");\r
+                errors.put(t, error);\r
+            }\r
+        }\r
+        \r
+        for(Token t : removes)\r
+            errors.remove(t);\r
+\r
+        return new ArrayList<SyntaxError>(errors.values());\r
+    }\r
+\r
+\r
+    /**\r
+     * Examine if a given functionKey is a sheet reference and whether all the tokens in the function ( Sheet1(token1, token2) )\r
+     * are valid.\r
+     *  \r
+     * @param configuration Configuration where the function is called\r
+     * @param functionKey Function name\r
+     * @param functionTokens Function parameters (sheet reference, either a cell or cell range)\r
+     * @param expression The whole expression where the function reference is\r
+     * @param expressionReferences All variable references, including function parameters\r
+     * @return A list of possible errors\r
+     */\r
+    static public List<SyntaxError> examineSheetReferences(\r
+            Configuration configuration, \r
+            String functionKey, \r
+            List<Token> functionTokens,\r
+            String expression, \r
+            HashMap<String, List<Token>> expressionReferences) {\r
+        \r
+        List<SyntaxError> result = new ArrayList<SyntaxError>();\r
+        \r
+        String[] parts = functionKey.split("\\.");\r
+        Object current = configuration;\r
+        for(int i = 0; i < parts.length && current != null; i++) {\r
+            current = getElement(current, parts[i]);\r
         }\r
+        \r
+        if(current == null && configuration.getModuleType() != null) {\r
+            // Sheets are currently located in the model root. Try to find the sheet.\r
+            current = configuration.getModuleType().getParent(); // Get module type parent (should be a model)\r
+            if(current instanceof Model)\r
+                current = getElement(((Model)current).getModelConfiguration(), parts[0]); // Try to get the sheet\r
+        }\r
+        \r
+        if(current != null && current instanceof Sheet) {\r
+            Sheet sheet = (Sheet) current;\r
+            int start = 0, end = 0, call = 0;\r
+            String cellOrRange = null;\r
+            while((call = expression.indexOf(functionKey, end)) >= 0) {\r
+                start = expression.indexOf("(", call) +1;\r
+                end = expression.indexOf(")", start);\r
+                if(start < 0 || end < 0 || end < start) {\r
+                    break;\r
+                }\r
+                Pattern p = Pattern.compile("[-\\+\\*\\/\\(\\)\\{\\}\\[\\],\\.\\t\\n\\r\\f]");\r
+                cellOrRange = expression.substring(start, end);\r
+                Matcher m = p.matcher(cellOrRange);\r
+                if (m.find() || cellOrRange.split(":").length > 2) {\r
+                    result.add(new SyntaxError(start, end - start, ExpressionField.SYNTAX_ERROR, "Not a valid cell or range", cellOrRange));\r
+                }\r
+            }\r
+            \r
+            \r
+            for(Token cell : functionTokens) {\r
+                List<Token> refs = expressionReferences.get(cell.image);\r
+                if(refs != null)\r
+                    refs.remove(cell);\r
+                if(!sheet.getCells().containsKey(cell.image))\r
+                    result.add(new SyntaxError(cell.image, "Invalid cell", cell.beginLine, cell.beginColumn, cell.endLine, cell.endColumn)); \r
+            }\r
 \r
+        }\r
+        \r
+        return result;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Option for a reference. Whether the reference does not exist, \r
+     * it can be connected (normal variable) or it cannot be \r
+     * connected even though it exists (e.g. enumeration index)\r
+     * \r
+     * @author Teemu Lempinen\r
+     *\r
+     */\r
+    static public enum ReferenceOption {DOES_NOT_EXIST, CAN_BE_CONNECTED, CANNOT_BE_CONNECTED};\r
+    \r
+    /**\r
+     * Get the reference option for a reference (name) in a configuration.\r
+     * \r
+     * @param conf Configuration\r
+     * @param name Referred variable\r
+     * @return The result tells does the referred name exist and can it be connected to \r
+     */\r
+    static public ReferenceOption getReferenceOption(Configuration conf, String name) {\r
+        \r
+        String[] parts = name.split("\\.");\r
+        Object element = conf;\r
+        for(int i = 0; i < parts.length && element != null; i++) {\r
+            element = getElement(element, parts[i]);\r
+        }\r
+        if(element == null)\r
+            return ReferenceOption.DOES_NOT_EXIST;\r
+        else if(Boolean.TRUE.equals(element))\r
+            return ReferenceOption.CANNOT_BE_CONNECTED;\r
+        else if(element instanceof Variable) {\r
+            if(element instanceof Enumeration || element instanceof Sheet)\r
+                return ReferenceOption.CANNOT_BE_CONNECTED;\r
+            else\r
+                return ReferenceOption.CAN_BE_CONNECTED;\r
+        }\r
+        else \r
+            return ReferenceOption.DOES_NOT_EXIST;\r
     }\r
 \r
     static private Object getElement(Object parent, String name) {\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SyntaxError.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SyntaxError.java
new file mode 100644 (file)
index 0000000..a2f86e7
--- /dev/null
@@ -0,0 +1,223 @@
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.utils;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.simantics.sysdyn.expressionParser.Token;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionField;\r
+\r
+/**\r
+ * Class for containing errors caught in expression validation\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class SyntaxError {\r
+    \r
+    private String type, message, image;\r
+    private int beginLine, beginColumn, endLine, endColumn;\r
+    private Integer start, offset;\r
+    \r
+    /**\r
+     * A syntax error without any info. Remember to assign location, \r
+     * type and message information.\r
+     */\r
+    public SyntaxError() {\r
+        \r
+    }\r
+    \r
+    /**\r
+     * Creates an error from expression parser token\r
+     * @param token expressionParser token\r
+     * @param message Error message\r
+     */\r
+    public SyntaxError(Token token, String message){\r
+        this(token.image, message, token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
+    }\r
+    \r
+    /**\r
+     * Creates an error from table parser token\r
+     * @param token tableParser token\r
+     * @param message Error message\r
+     */\r
+    public SyntaxError(org.simantics.sysdyn.tableParser.Token token, String message){\r
+        this(token.image, message, token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
+    }\r
+    \r
+    /**\r
+     * Create syntax error with full data\r
+     * @param image\r
+     * @param message\r
+     * @param beginLine\r
+     * @param beginColumn\r
+     * @param endLine\r
+     * @param endColumn\r
+     */\r
+    public SyntaxError(String image, String message, int beginLine, int beginColumn, int endLine, int endColumn) {\r
+        this.image = image;\r
+        this.message = message;\r
+        this.beginLine = beginLine;\r
+        this.beginColumn = beginColumn;\r
+        this.endLine = endLine;\r
+        this.endColumn = endColumn;\r
+        this.type = ExpressionField.SYNTAX_ERROR;\r
+    }\r
+    \r
+    /**\r
+     * Create syntax error with location, message and type data\r
+     * @param start\r
+     * @param offset\r
+     * @param type\r
+     * @param message\r
+     */\r
+    public SyntaxError(int start, int offset, String type, String message) {\r
+        this(start, offset, type, message, null);\r
+    }\r
+    \r
+    /**\r
+     * Create syntax error with location, message and type data\r
+     * @param start\r
+     * @param offset\r
+     * @param type\r
+     * @param message\r
+     */\r
+    public SyntaxError(int start, int offset, String type, String message, String image) {\r
+        this.image = image;\r
+        this.start = start;\r
+        this.offset = offset;\r
+        this.type = type;\r
+        this.message = message;\r
+    }\r
+    \r
+    /**\r
+     * Get start location of the issue. If start has not been set,\r
+     * document is used to calculate it.\r
+     * @param document\r
+     * @return\r
+     */\r
+    public int getStart(IDocument document) {\r
+        if(this.start != null)\r
+            return this.start;\r
+        else if(document != null){\r
+            int start = 0;\r
+            if(document.getLength() > 0) {\r
+                try {\r
+                    start = document.getLineOffset(beginLine - 1) + beginColumn - 1;\r
+                } catch (BadLocationException e) {\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+            return start;\r
+        } else {\r
+            return 0;\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Get offset data of the issue. If offset has not been set,\r
+     * document is used to calculate it.\r
+     * \r
+     * @param document\r
+     * @return\r
+     */\r
+    public int getOffset(IDocument document) {\r
+        if(this.offset != null) \r
+            return this.offset;\r
+        else if(document != null){\r
+            int start = getStart(document);\r
+            int offset = document.getLength();\r
+            if(document.getLength() > 0) {\r
+                try {\r
+                    offset = document.getLineOffset(endLine - 1) + endColumn - start;\r
+                } catch (BadLocationException e) {\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+            return offset;\r
+        } else {\r
+            return 0;\r
+        }\r
+    }\r
+    \r
+    public void setToken(Token token){\r
+       this.image = token.image;\r
+       this.beginLine = token.beginLine;\r
+       this.beginColumn = token.beginColumn;\r
+       this.endLine = token.endLine;\r
+       this.endColumn = token.endColumn;\r
+    }\r
+    \r
+    public void setToken(org.simantics.sysdyn.tableParser.Token token){\r
+        this.image = token.image;\r
+        this.beginLine = token.beginLine;\r
+        this.beginColumn = token.beginColumn;\r
+        this.endLine = token.endLine;\r
+        this.endColumn = token.endColumn;\r
+    }\r
+    \r
+    public String getType() {\r
+        return type;\r
+    }\r
+\r
+    public void setType(String type) {\r
+        this.type = type;\r
+    }\r
+\r
+    public String getMessage() {\r
+        return message;\r
+    }\r
+\r
+    public void setMessage(String message) {\r
+        this.message = message;\r
+    }\r
+\r
+    public String getImage() {\r
+        return image;\r
+    }\r
+\r
+    public void setImage(String image) {\r
+        this.image = image;\r
+    }\r
+\r
+    public int getBeginLine() {\r
+        return beginLine;\r
+    }\r
+\r
+    public void setBeginLine(int beginLine) {\r
+        this.beginLine = beginLine;\r
+    }\r
+\r
+    public int getBeginColumn() {\r
+        return beginColumn;\r
+    }\r
+\r
+    public void setBeginColumn(int beginColumn) {\r
+        this.beginColumn = beginColumn;\r
+    }\r
+\r
+    public int getEndLine() {\r
+        return endLine;\r
+    }\r
+\r
+    public void setEndLine(int endLine) {\r
+        this.endLine = endLine;\r
+    }\r
+\r
+    public int getEndColumn() {\r
+        return endColumn;\r
+    }\r
+\r
+    public void setEndColumn(int endColumn) {\r
+        this.endColumn = endColumn;\r
+    }\r
+\r
+}\r
index 25867476f2035f07d859cd134efaad1903604c5c..fce73fd76afecdf1af279e0a90b4ccc6b60b7a7b 100644 (file)
@@ -13,21 +13,24 @@ package org.simantics.sysdyn.ui.validation;
 \r
 import java.util.ArrayList;\r
 import java.util.Collections;\r
-import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Set;\r
 \r
 import org.simantics.db.Issue;\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
-import org.simantics.db.common.utils.NameUtils;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.issues.common.IssueUtils;\r
-import org.simantics.issues.common.StandardIssue;\r
 import org.simantics.layer0.Layer0;\r
 import org.simantics.scl.reflection.annotations.SCLValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.manager.SysdynModel;\r
+import org.simantics.sysdyn.manager.SysdynModelManager;\r
+import org.simantics.sysdyn.representation.Configuration;\r
+import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionField;\r
+import org.simantics.sysdyn.ui.utils.ExpressionUtils;\r
+import org.simantics.sysdyn.ui.utils.ExpressionUtils.ReferenceOption;\r
+import org.simantics.sysdyn.ui.utils.SyntaxError;\r
 import org.simantics.utils.datastructures.collections.CollectionUtils;\r
 \r
 /**\r
@@ -67,7 +70,7 @@ public class DependencyFunction {
         \r
         // Find all references in equations of component\r
         try {\r
-            references = ValidationUtils.getReferences(graph, component);\r
+            references = ValidationUtils.getAllReferences(graph, component).getVariableReferences();\r
         } catch (Exception e) {\r
             return result;\r
         } \r
@@ -79,14 +82,28 @@ public class DependencyFunction {
         if (dependencies != null) {\r
             for (String dependency : dependencies) {\r
                 if (references == null || !references.contains(dependency)) {\r
-                    Resource variable = ValidationUtils.reach(graph, component, dependency);\r
-                    result.add(new StandardIssue(sr.Validations_UnusedDependencyIssue, component, variable));\r
+                    result.add(new IssueWithStringContext(sr.Validations_UnusedDependencyIssue, component, dependency));\r
                 }\r
             }\r
         }\r
 \r
         return result;\r
     }\r
+    \r
+\r
+    private static Configuration getConfiguration(ReadGraph graph, Resource component) throws DatabaseException {\r
+        Resource configuration = graph.getPossibleObject(component, Layer0.getInstance(graph).PartOf);\r
+        \r
+        if(configuration == null)\r
+            return null;\r
+        \r
+        SysdynModelManager smm = SysdynModelManager.getInstance(graph.getSession());\r
+        SysdynModel sm = smm.getModel(graph, configuration);\r
+        if(sm == null)\r
+            return null;\r
+\r
+        return sm.getConfiguration();\r
+    }\r
 \r
     /**\r
      * Evaluates dependency-related issues for a component.\r
@@ -109,44 +126,86 @@ public class DependencyFunction {
         if (!graph.hasStatement(component) || !graph.hasStatement(component, l0.PartOf))\r
             return Collections.emptyList();\r
 \r
-        // Find all variables that are linked to component with arrows\r
-        Set<String> dependencies = ValidationUtils.getDependencies(graph, component);\r
-        Set<String> references = null;\r
-\r
         // Find all references in equations of component\r
+        References references = null;\r
         try {\r
-            references = ValidationUtils.getReferences(graph, component);\r
-        } catch (SyntaxErrorException e) {\r
-        } catch (UnsupportedCharactersException e) {\r
-        } catch (UndefinedExpressionException e) {\r
+            references = ValidationUtils.getAllReferences(graph, component);\r
+        } catch (Exception e) {\r
+            return Collections.emptyList();\r
         }\r
-\r
+        \r
+        Configuration configuration = getConfiguration(graph, component);\r
         ArrayList<Issue> result = new ArrayList<Issue>();\r
+        \r
+        // Examine Sheet references\r
+        for(Resource expressionResource : references.functionReferences.keySet()) {\r
+            for(String functionKey : references.functionReferences.get(expressionResource).keySet()) {\r
+                List<SyntaxError> sheetErrors = ExpressionUtils.examineSheetReferences(\r
+                        configuration, \r
+                        functionKey, \r
+                        references.functionReferences.get(expressionResource).get(functionKey), \r
+                        references.expressions.get(expressionResource), \r
+                        references.references.get(expressionResource));\r
+                if(sheetErrors != null) {\r
+                    for(SyntaxError error : sheetErrors)\r
+                        result.add(new IssueWithStringContext(sr.Validations_InvalidSheetReferenceIssue, component, error.getMessage(), error.getImage()));\r
+                }\r
+            }\r
+        }\r
+        \r
+        \r
+        // Examine dependencies\r
+        Set<String> variablesReferences = references.getVariableReferences();\r
+        if(variablesReferences == null || variablesReferences.isEmpty())\r
+            return result;\r
+        \r
+        // Find all variables that are linked to component with arrows\r
+        Set<String> dependencies = ValidationUtils.getDependencies(graph, component);\r
+        dependencies.addAll(GLOBAL_VARIABLES);\r
+        \r
+        // Remove all dependency variables from reference maps \r
+        for(String dependency : dependencies)\r
+            variablesReferences.remove(dependency);\r
 \r
         boolean isStock = isStock(graph, component);\r
-        StandardIssue noSuchVariableIssue = null;\r
-        // Check that all references have corresponding arrows\r
-        if (references != null && dependencies != null) {\r
-            for (String reference : references) {\r
-                if (!dependencies.contains(reference) && !GLOBAL_VARIABLES.contains(reference)) {\r
-                    Resource variable = null;\r
-                    if ((variable = ValidationUtils.reach(graph, component, reference)) != null) {\r
-                        if(isStock) {\r
-                            /* Stocks do not get incoming dependencies. They are allowed\r
-                            to have references without arrows */\r
-                        } else {\r
-                            result.add(new StandardIssue(sr.Validations_MissingLinkIssue, component, variable));\r
-                        }\r
+        ReferenceOption option;\r
+\r
+        for(String reference : variablesReferences) {\r
+            option = ExpressionUtils.getReferenceOption(configuration, reference);\r
+            switch(option) {\r
+                case DOES_NOT_EXIST:\r
+                    result.add(new IssueWithStringContext(sr.Validations_NoSuchVariableIssue, component, reference));\r
+                case CAN_BE_CONNECTED:\r
+                    if(isStock) {\r
+                        /* Stocks do not get incoming dependencies. They are allowed\r
+                        to have references without arrows */\r
                     } else {\r
-                        if (noSuchVariableIssue == null) {\r
-                            noSuchVariableIssue = new StandardIssue(sr.Validations_NoSuchVariableIssue, component);\r
-                            result.add(noSuchVariableIssue);\r
-                        }\r
+                        result.add(new IssueWithStringContext(sr.Validations_MissingLinkIssue, component, reference));\r
                     }\r
-                }\r
+                    break;\r
+                case CANNOT_BE_CONNECTED:\r
             }\r
         }\r
+        \r
+        \r
+        for(Resource expression : references.ranges.keySet()) {\r
+            List<SyntaxError> errors = new ArrayList<SyntaxError>();\r
+            // RANGES\r
+            errors.addAll(ExpressionUtils.examineArrayRanges(graph, configuration, references.ranges.get(expression), references.forIndices.get(expression)));\r
+            \r
+            // ENUMERATION REFERENCES IN FOR-LOOPS\r
+            errors.addAll(ExpressionUtils.examineEnumerationReferences(configuration, references.enumerationReferences.get(expression)));\r
+\r
+            for(SyntaxError error : errors) {\r
+                Resource type = sr.Validations_RangeIssue;\r
+                if(ExpressionField.SYNTAX_WARNING.equals(error.getType())) {\r
+                    type = sr.Validations_RangeWarning;\r
+                }\r
+                result.add(new IssueWithStringContext(type, component, error.getMessage()));\r
 \r
+            }\r
+        }   \r
+        \r
         return result;\r
 \r
     }\r
@@ -177,13 +236,12 @@ public class DependencyFunction {
     public static String missingLinkIssueDescription(ReadGraph graph, Resource converter, Variable property)\r
             throws DatabaseException {\r
        \r
-       List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
+        List<String> contexts = IssueWithStringContext.getStringContexts(graph, property);\r
         String result = "Missing a link to ";\r
         if (contexts.size() > 0) {\r
-            Resource component = contexts.get(1);\r
-            String name = NameUtils.getSafeName(graph, component);\r
-            result = result + name;\r
+            result = result + contexts.get(0);\r
         }\r
+\r
         return result;\r
         \r
     }\r
@@ -200,14 +258,13 @@ public class DependencyFunction {
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
     public static String unusedDependencyIssueDescription(ReadGraph graph, Resource converter, Variable property)\r
             throws DatabaseException {\r
-       \r
-       List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
+        \r
+        List<String> contexts = IssueWithStringContext.getStringContexts(graph, property);\r
         String result = "Unused dependency: ";\r
         if (contexts.size() > 0) {\r
-            Resource component = contexts.get(1);\r
-            String name = NameUtils.getSafeName(graph, component);\r
-            result = result + name;\r
+            result = result + contexts.get(0);\r
         }\r
+\r
         return result;\r
     }\r
 \r
@@ -224,49 +281,50 @@ public class DependencyFunction {
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
     public static String noSuchVariableIssueDescription(ReadGraph graph, Resource converter, Variable property)\r
             throws DatabaseException {\r
-       \r
-       List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
-        Resource component = contexts.get(0);\r
-\r
-        // Find all variables that are linked to component with arrows\r
-        Set<String> dependencies = ValidationUtils.getDependencies(graph, component);\r
-        Set<String> references = null;\r
-\r
-        // Find all references in equations of component\r
-        try {\r
-            references = ValidationUtils.getReferences(graph, component);\r
-        } catch (SyntaxErrorException e) {\r
-        } catch (UnsupportedCharactersException e) {\r
-        } catch (UndefinedExpressionException e) {\r
+        \r
+        List<String> contexts = IssueWithStringContext.getStringContexts(graph, property);\r
+        String result = "Refers to unexisting variable ";\r
+        if (contexts.size() > 0) {\r
+            result = result + contexts.get(0);\r
         }\r
+        \r
+        return result;\r
+    }\r
+    \r
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+    public static String invalidSheetReferenceIssueDescription(ReadGraph graph, Resource converter, Variable property)\r
+            throws DatabaseException {\r
+        \r
+        List<String> contexts = IssueWithStringContext.getStringContexts(graph, property);\r
+        String result = "";\r
+        \r
+        if(contexts.size() == 2)\r
+            result = contexts.get(0) + ": " + contexts.get(1);\r
+        else\r
+            result = "Spreadsheet reference error";\r
 \r
-        ArrayList<String> result = new ArrayList<String>();\r
-        // Loop all references\r
-        if (references != null && dependencies != null) {\r
-            for (String reference : references) {\r
-                // If dependencies does not contain reference and the reference\r
-               // is not reachable from component, add the name\r
-                if (!dependencies.contains(reference) && ValidationUtils.reach(graph, component, reference) == null) {\r
-                    result.add(reference);\r
-                }\r
-            }\r
-        }\r
-        if (result.size() == 0) {\r
-            return "Missing link";\r
-        } else if (result.size() == 1) {\r
-            return "Refers to unexisting variable " + result.get(0);\r
+        return result;\r
+    }\r
+    \r
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+    public static String rangeIssueDescription(ReadGraph graph, Resource converter, Variable property)\r
+            throws DatabaseException {\r
+        \r
+        List<String> contexts = IssueWithStringContext.getStringContexts(graph, property);\r
+        if (contexts.size() > 0) {\r
+            return contexts.get(0);\r
         } else {\r
-            StringBuilder sb = new StringBuilder();\r
-            sb.append("Refers to unexisting variables ");\r
-            Iterator<String> iterator = result.iterator();\r
-            String reference;\r
-            while (iterator.hasNext()) {\r
-                reference = iterator.next();\r
-                sb.append(reference);\r
-                if (iterator.hasNext())\r
-                    sb.append(", ");\r
-            }\r
-            return sb.toString();\r
+            return "Range Issue";\r
         }\r
     }\r
+    \r
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+    public static String rangeWarningDescription(ReadGraph graph, Resource converter, Variable property)\r
+            throws DatabaseException {\r
+        return rangeIssueDescription(graph, converter, property);\r
+    }\r
+    \r
+    \r
+    \r
+    \r
 }\r
index a027fce7cc76dc5c3745dd7d87c8b208929dece7..782fb3cfef3ac5c15b583ebedf229841593c7e83 100644 (file)
@@ -47,7 +47,7 @@ public class ExpressionIssueFunction {
         \r
         // Try if there are any errors while parsing the expressions\r
         try {\r
-            ValidationUtils.getReferences(graph, component);\r
+            ValidationUtils.getAllReferences(graph, component);\r
         } catch (Exception e) {\r
             return Collections.<Issue>singletonList(new StandardIssue(sr.Validations_ExpressionIssue, component));\r
         }\r
@@ -62,7 +62,7 @@ public class ExpressionIssueFunction {
         \r
         // There should be an error\r
         try {\r
-            ValidationUtils.getReferences(graph, component);\r
+            ValidationUtils.getAllReferences(graph, component);\r
         } catch (SyntaxErrorException e) {\r
             return SYNTAX_ERROR;\r
         } catch (UnsupportedCharactersException e) {\r
index d53a9128b2127af7c690a4af9d239365e65109ac..eca081088ae0b75bcbddfe114e35e55d3176f303 100644 (file)
@@ -22,8 +22,6 @@ import org.simantics.issues.common.IssueUtils;
 import org.simantics.layer0.Layer0;\r
 import org.simantics.project.ontology.ProjectResource;\r
 import org.simantics.scl.reflection.annotations.SCLValue;\r
-import org.simantics.simulation.ontology.SimulationResource;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
 import org.simantics.sysdyn.SysdynResource;\r
 \r
 /**\r
@@ -36,13 +34,7 @@ public class Functions {
 \r
     @SCLValue(type = "ReadGraph -> Resource -> Resource")\r
     public static Resource baseRealizationFunction(ReadGraph graph, Resource model) throws DatabaseException {\r
-        SysdynResource sr = SysdynResource.getInstance(graph);\r
-        if(graph.isInstanceOf(model, sr.SysdynModel))\r
-            return graph.getSingleObject(model, SimulationResource.getInstance(graph).HasConfiguration);\r
-        else if (graph.isInheritedFrom(model, sr.Module))\r
-            return graph.getSingleObject(model, StructuralResource2.getInstance(graph).IsDefinedBy);\r
-        else return null;\r
-\r
+        return model;\r
     }\r
 \r
 \r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java
new file mode 100644 (file)
index 0000000..a491add
--- /dev/null
@@ -0,0 +1,107 @@
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.validation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.issues.common.StandardIssue;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+/**\r
+ * Issue that can have string contexts.\r
+ * \r
+ * String contexts are written to a graph like resource contexts and can be accessed \r
+ * in issue description functions. This eliminates the need for making complex calculations \r
+ * for obtaining values that have already been calculated in the issue source function. \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class IssueWithStringContext extends StandardIssue {\r
+\r
+    String[] stringContexts;\r
+\r
+    /**\r
+     * Creates an issue with one resource context and an arbitrary number of string contexts\r
+     * @param type\r
+     * @param context\r
+     * @param stringContexts\r
+     */\r
+    public IssueWithStringContext(Resource type, Resource context, String... stringContexts) {\r
+        super(type, context);\r
+        this.stringContexts = stringContexts;\r
+    }\r
+    \r
+    /**\r
+     * Get the string contexts of this issue\r
+     * @return string contexts\r
+     */\r
+    public String[] getStringContexts() {\r
+        return stringContexts;\r
+    }\r
+    \r
+    /**\r
+     * Overridden function from StandardResource. This writes a list of string contexts to the database.\r
+     */\r
+    public void writeAdditionalContext(WriteGraph graph, Resource issue) throws DatabaseException {\r
+        super.writeAdditionalContext(graph, issue);\r
+        \r
+        // Add possible string contexts to the contexts array\r
+        if(stringContexts != null && stringContexts.length > 0) {\r
+            SysdynResource SR = SysdynResource.getInstance(graph);\r
+            Layer0 L0 = Layer0.getInstance(graph);\r
+            List<Resource> contexts = new ArrayList<Resource>();\r
+            for(String s : stringContexts) {\r
+                Resource r = graph.newResource();\r
+                graph.claim(r, L0.InstanceOf, L0.String);\r
+                graph.claimValue(r, s, Bindings.STRING);\r
+                contexts.add(r);\r
+            }\r
+            graph.claim(issue, SR.Validations_Issue_stringContexts, ListUtils.create(graph, L0.List, contexts));\r
+        }\r
+        \r
+    }\r
+    \r
+    /**\r
+     * Gets string contexts from IssueWithStringContexts\r
+     * @param graph ReadGraph\r
+     * @param property issue property\r
+     * @return String contexts of issue or empty list if none is found\r
+     * @throws DatabaseException\r
+     */\r
+    public static List<String> getStringContexts(ReadGraph graph, Variable property) throws DatabaseException {\r
+        SysdynResource SR = SysdynResource.getInstance(graph);\r
+        Variable issueVariable = property.getParent(graph);\r
+        Resource issueResource = issueVariable.getRepresents(graph);\r
+        Resource list = graph.getPossibleObject(issueResource, SR.Validations_Issue_stringContexts);\r
+        if(list == null) {\r
+            return Collections.emptyList();\r
+        } else {\r
+            List<Resource> stringResources = ListUtils.toList(graph, list);\r
+            ArrayList<String> result = new ArrayList<String>(stringResources.size());\r
+            for(Resource r : stringResources) {\r
+                result.add((String)graph.getValue(r, Bindings.STRING));\r
+            }\r
+            return result;\r
+        }\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/References.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/References.java
new file mode 100644 (file)
index 0000000..0d9ed3d
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.validation;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.sysdyn.expressionParser.Token;\r
+\r
+/**\r
+ * Container for different types of references got from expression parser\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class References {\r
+    public HashMap<Resource, String> expressions = new HashMap<Resource, String>();\r
+    public HashMap<Resource, HashMap<String, List<Token>>> references = new HashMap<Resource, HashMap<String, List<Token>>>();\r
+    public HashMap<Resource, HashMap<String, List<List<Token>>>> ranges = new HashMap<Resource, HashMap<String, List<List<Token>>>>();\r
+    public HashMap<Resource, HashMap<Token, List<Token>>> forIndices = new HashMap<Resource, HashMap<Token, List<Token>>>();\r
+    public HashMap<Resource, HashMap<String, List<Token>>> enumerationReferences = new HashMap<Resource, HashMap<String, List<Token>>>();\r
+    public HashMap<Resource, HashMap<String, List<Token>>> functionReferences = new HashMap<Resource, HashMap<String, List<Token>>>();\r
+    \r
+    \r
+    /**\r
+     * Get all variable references from all expressions of the variable in a single set\r
+     * @return All variable references\r
+     */\r
+    public Set<String> getVariableReferences() {\r
+        HashSet<String> result = new HashSet<String>();\r
+        for(HashMap<String, List<Token>> map : references.values()) {\r
+            for(String key : map.keySet()) {\r
+                if(!map.get(key).isEmpty())\r
+                    result.add(key);\r
+            }\r
+        }\r
+        \r
+        return result;\r
+    }\r
+}\r
index 79293b0b53b8ef4ad0662652fa5780d1ee69b254..e8f840687318371f7c6d48bfa43fbec4049e71e2 100644 (file)
@@ -13,20 +13,20 @@ package org.simantics.sysdyn.ui.validation;
 \r
 import java.io.StringReader;\r
 import java.util.Collection;\r
+import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.List;\r
 \r
-import org.simantics.databoard.Bindings;\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
 import org.simantics.db.Statement;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
 import org.simantics.db.common.utils.OrderedSetUtils;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.layer0.Layer0;\r
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.expressionParser.ExpressionParser;\r
 import org.simantics.sysdyn.expressionParser.ParseException;\r
+import org.simantics.sysdyn.expressionParser.Token;\r
 import org.simantics.sysdyn.expressionParser.TokenMgrError;\r
 \r
 /**\r
@@ -35,7 +35,7 @@ import org.simantics.sysdyn.expressionParser.TokenMgrError;
  *\r
  */\r
 public class ValidationUtils {\r
-\r
+    \r
     /**\r
      * Find all variables that are referred to in the expressions of variable r\r
      * @param graph ReadGraph\r
@@ -46,8 +46,9 @@ public class ValidationUtils {
      * @throws UnsupportedCharactersException\r
      * @throws UndefinedExpressionException\r
      */\r
-    public static HashSet<String> getReferences(ReadGraph graph, Resource r) throws DatabaseException, SyntaxErrorException, UnsupportedCharactersException, UndefinedExpressionException {\r
-        HashSet<String> references = new HashSet<String>();\r
+    public static References getAllReferences(ReadGraph graph, Resource r) throws DatabaseException, SyntaxErrorException, UnsupportedCharactersException, UndefinedExpressionException {\r
+        References result = new References();\r
+\r
         ExpressionParser parser = new ExpressionParser(new StringReader(""));\r
 \r
         SysdynResource sr = SysdynResource.getInstance(graph);\r
@@ -65,16 +66,22 @@ public class ValidationUtils {
                 \r
                 if(value.length() == 0) {\r
                     // Empty might be allowed\r
-                    if(graph.isSubrelationOf(statement.getPredicate(), sr.HasEquationOrEmpty))\r
-                        return references;\r
-                    else\r
+                    if(!graph.isSubrelationOf(statement.getPredicate(), sr.HasEquationOrEmpty))\r
                         throw new UndefinedExpressionException();\r
                 }\r
 \r
                 parser.ReInit(new StringReader(value));\r
                 try {\r
                     parser.expr();\r
-                    references.addAll(parser.getReferences().keySet());\r
+                    \r
+                    HashMap<String, List<Token>> refs = parser.getReferences();\r
+                    result.references.put(expression, refs);\r
+                    result.ranges.put(expression, parser.getRanges());\r
+                    result.forIndices.put(expression,  parser.getForIndices());\r
+                    result.enumerationReferences.put(expression, parser.getEnumerationReferences());\r
+                    result.functionReferences.put(expression, parser.getFunctionCallReferences());\r
+                    result.expressions.put(expression, value);\r
+                    \r
                 } catch (ParseException e1) {\r
                     throw new SyntaxErrorException();\r
                 } catch (TokenMgrError err) {\r
@@ -82,9 +89,9 @@ public class ValidationUtils {
                 }\r
             }\r
         }\r
-        return references;\r
+        return result;\r
     }\r
-\r
+    \r
     /**\r
      * Get all expressions of a variable r\r
      * @param graph ReadGraph\r
@@ -132,42 +139,4 @@ public class ValidationUtils {
         return variables;\r
     }\r
 \r
-    /**\r
-     * Is reference reachable from variable\r
-     * \r
-     * @param graph\r
-     * @param variable\r
-     * @param reference\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static boolean isReachable(ReadGraph graph, Resource variable, String reference) throws DatabaseException {\r
-        if(reach(graph, variable, reference) != null)\r
-            return true;\r
-        else \r
-            return false;\r
-    }\r
-\r
-    /**\r
-     * Find a resource starting from variable and using reference path\r
-     * \r
-     * @param graph ReadGraph\r
-     * @param variable starting point\r
-     * @param reference path to another variable\r
-     * @return found variable or null\r
-     * @throws DatabaseException\r
-     */\r
-    public static Resource reach(ReadGraph graph, Resource variable, String reference) throws DatabaseException {\r
-        Layer0 l0 = Layer0.getInstance(graph);\r
-        SysdynResource sr = SysdynResource.getInstance(graph);\r
-        Resource configuration = graph.getSingleObject(variable, l0.PartOf);\r
-        String varName;\r
-        for(Resource var : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Variable))) {\r
-            varName = graph.getRelatedValue(var, l0.HasName, Bindings.STRING);\r
-            if(varName != null && reference.equals(varName))\r
-                return var;\r
-        }\r
-        return null;\r
-    }\r
-\r
 }\r