]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Unit analysis for expressions. (refs #4093)
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 29 Apr 2013 06:36:29 +0000 (06:36 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 29 Apr 2013 06:36:29 +0000 (06:36 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@27296 ac1ea38d-2e2b-0410-8846-a27921b304fc

50 files changed:
org.simantics.sysdyn.ontology/graph.tg
org.simantics.sysdyn.ontology/graph/Migration.pgraph
org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph
org.simantics.sysdyn.ontology/graph/Validation.pgraph
org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java
org.simantics.sysdyn.ui/plugin.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ConfigurationTab.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/modules/ModuleParameterOverrideUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ModelUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/imports/ImportUtils.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/values/ValueView.java
org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Variable.java
org.simantics.sysdyn/src/org/simantics/sysdyn/modelParser/ModelicaParser.jj
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variability.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variable.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ConstantExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/Expression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingException.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentIdentity.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReference.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Condition.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java [new file with mode: 0644]

index 6d1e0b6a1541a8f8f422e870a78555c10b3366ca..4442534245cbb6d7d9b53ef67561f94f71d360b4 100644 (file)
Binary files a/org.simantics.sysdyn.ontology/graph.tg and b/org.simantics.sysdyn.ontology/graph.tg differ
index 7d1354690328cb2e734050526bcb8575aea24ffe..c52fecbcab078a48813cb195873ba6d7b3ded573 100644 (file)
@@ -119,6 +119,8 @@ FROM16TO17.SysdynChanges : L0.NamespaceMigrationStep
       @move "http://www.simantics.org/Sysdyn-1.1/" "HasHead" "Variable/HasHead"\r
     _\r
       @move "http://www.simantics.org/Sysdyn-1.1/" "SharedModuleOntolofgy" "SharedModuleOntology"\r
+    _\r
+      @move "http://www.simantics.org/Sysdyn-1.1/" "HasUnit" "Variable/unit"\r
       \r
                   \r
 FROM16TO17.OrderedSetsToLists : L0.OrderedSetToListMigrationStep\r
index 76fd48dd396a22f258d1c129fcb4b113cac4bb33..f04d001f78643ad961c1c58ba9ee3cd49f72433e 100644 (file)
@@ -137,10 +137,6 @@ SYSDYN.Variable <T STR.Component
     
 FUNCTIONS.runChildren : L0.ExternalValue
     
-
-SYSDYN.HasUnit <R L0.HasProperty
-    L0.HasRange L0.String
-
 SYSDYN.HasRangeStart <R L0.HasProperty
     L0.HasRange L0.Double    
 
index 2932a309622c0b47719562c8a2060ed10d9ed834..3cf2d18d781de582f9a889d0fa729699a8aa99c2 100644 (file)
@@ -27,6 +27,10 @@ VALIDATIONS.Expressions.expressionValidator : L0.Function
 VALIDATIONS.Enumerations : L0.Library\r
 VALIDATIONS.Enumerations.enumerationIndexValidator : L0.Function\r
 \r
+// ENUMERATIONS\r
+VALIDATIONS.Units : L0.Library\r
+VALIDATIONS.Units.unitValidator : L0.Function\r
+\r
 SYSDYN.Variable\r
     @VALIDATIONS.constraint\r
         VALIDATIONS.ExpressionConstraint\r
@@ -59,6 +63,14 @@ SYSDYN.Variable
         VALIDATIONS.Dependencies.missingDependencyValidator  \r
         VALIDATIONS.Functions.baseRealizationFunction \r
         \r
+SYSDYN.IndependentVariable\r
+    @VALIDATIONS.listeningConstraint\r
+        VALIDATIONS.UnitConstraint\r
+        VALIDATIONS.Units.UnitIssueSource\r
+            @L0.assert L0.HasName "UnitIssueSource"\r
+        VALIDATIONS.Units.unitValidator  \r
+        VALIDATIONS.Functions.baseRealizationFunction\r
+        \r
 VALIDATIONS.ExpressionIssue\r
     @VALIDATIONS.issue\r
         ISSUE.Severity.Error\r
@@ -115,7 +127,13 @@ VALIDATIONS.EmptyEnumerationIssue
             L0.HasValueType "String"\r
         VALIDATIONS.Functions.path     \r
         \r
-        \r
+VALIDATIONS.UnitWarning\r
+    @VALIDATIONS.issue\r
+        ISSUE.Severity.Warning\r
+        VALIDATIONS.Units.unitWarningDescription : L0.Function\r
+            L0.HasValueType "String"\r
+        VALIDATIONS.Functions.path        \r
+\r
         \r
 // IssueSource template\r
 VALIDATIONS.constraint : L0.Template\r
index 85c37f49d6dc65a7d457a9851f1fb3f927ddb623..875728d6470ff2b48e80a8fd8854dc24fa4a68cb 100644 (file)
@@ -390,8 +390,6 @@ public class SysdynResource {
     public final Resource HasRangeStep;\r
     public final Resource HasRangeStep_Inverse;\r
     public final Resource HasTailTerminal;\r
-    public final Resource HasUnit;\r
-    public final Resource HasUnit_Inverse;\r
     public final Resource HistoryDataset;\r
     public final Resource HistoryDataset_FoundVariableNameNode;\r
     public final Resource HistoryDataset_HistoryDatasetVariablesBrowseContext;\r
@@ -635,6 +633,12 @@ public class SysdynResource {
     public final Resource Validations_NoSuchVariableIssue;\r
     public final Resource Validations_RangeIssue;\r
     public final Resource Validations_RangeWarning;\r
+    public final Resource Validations_UnitConstraint;\r
+    public final Resource Validations_UnitWarning;\r
+    public final Resource Validations_Units;\r
+    public final Resource Validations_Units_UnitIssueSource;\r
+    public final Resource Validations_Units_unitValidator;\r
+    public final Resource Validations_Units_unitWarningDescription;\r
     public final Resource Validations_UnusedDependencyIssue;\r
     public final Resource Validations_constraint;\r
     public final Resource Validations_issue;\r
@@ -1067,8 +1071,6 @@ public class SysdynResource {
         public static final String HasRangeStep = "http://www.simantics.org/Sysdyn-1.1/HasRangeStep";\r
         public static final String HasRangeStep_Inverse = "http://www.simantics.org/Sysdyn-1.1/HasRangeStep/Inverse";\r
         public static final String HasTailTerminal = "http://www.simantics.org/Sysdyn-1.1/HasTailTerminal";\r
-        public static final String HasUnit = "http://www.simantics.org/Sysdyn-1.1/HasUnit";\r
-        public static final String HasUnit_Inverse = "http://www.simantics.org/Sysdyn-1.1/HasUnit/Inverse";\r
         public static final String HistoryDataset = "http://www.simantics.org/Sysdyn-1.1/HistoryDataset";\r
         public static final String HistoryDataset_FoundVariableNameNode = "http://www.simantics.org/Sysdyn-1.1/HistoryDataset/FoundVariableNameNode";\r
         public static final String HistoryDataset_HistoryDatasetVariablesBrowseContext = "http://www.simantics.org/Sysdyn-1.1/HistoryDataset/HistoryDatasetVariablesBrowseContext";\r
@@ -1312,6 +1314,12 @@ public class SysdynResource {
         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_UnitConstraint = "http://www.simantics.org/Sysdyn-1.1/Validations/UnitConstraint";\r
+        public static final String Validations_UnitWarning = "http://www.simantics.org/Sysdyn-1.1/Validations/UnitWarning";\r
+        public static final String Validations_Units = "http://www.simantics.org/Sysdyn-1.1/Validations/Units";\r
+        public static final String Validations_Units_UnitIssueSource = "http://www.simantics.org/Sysdyn-1.1/Validations/Units/UnitIssueSource";\r
+        public static final String Validations_Units_unitValidator = "http://www.simantics.org/Sysdyn-1.1/Validations/Units/unitValidator";\r
+        public static final String Validations_Units_unitWarningDescription = "http://www.simantics.org/Sysdyn-1.1/Validations/Units/unitWarningDescription";\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
@@ -1754,8 +1762,6 @@ public class SysdynResource {
         HasRangeStep = getResourceOrNull(graph, URIs.HasRangeStep);\r
         HasRangeStep_Inverse = getResourceOrNull(graph, URIs.HasRangeStep_Inverse);\r
         HasTailTerminal = getResourceOrNull(graph, URIs.HasTailTerminal);\r
-        HasUnit = getResourceOrNull(graph, URIs.HasUnit);\r
-        HasUnit_Inverse = getResourceOrNull(graph, URIs.HasUnit_Inverse);\r
         HistoryDataset = getResourceOrNull(graph, URIs.HistoryDataset);\r
         HistoryDataset_FoundVariableNameNode = getResourceOrNull(graph, URIs.HistoryDataset_FoundVariableNameNode);\r
         HistoryDataset_HistoryDatasetVariablesBrowseContext = getResourceOrNull(graph, URIs.HistoryDataset_HistoryDatasetVariablesBrowseContext);\r
@@ -1999,6 +2005,12 @@ public class SysdynResource {
         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_UnitConstraint = getResourceOrNull(graph, URIs.Validations_UnitConstraint);\r
+        Validations_UnitWarning = getResourceOrNull(graph, URIs.Validations_UnitWarning);\r
+        Validations_Units = getResourceOrNull(graph, URIs.Validations_Units);\r
+        Validations_Units_UnitIssueSource = getResourceOrNull(graph, URIs.Validations_Units_UnitIssueSource);\r
+        Validations_Units_unitValidator = getResourceOrNull(graph, URIs.Validations_Units_unitValidator);\r
+        Validations_Units_unitWarningDescription = getResourceOrNull(graph, URIs.Validations_Units_unitWarningDescription);\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 b03868c116dfe0c64b47893a40690125940a899f..f838fc80c03c323950643a106e4357d1cf045742 100644 (file)
             <externalClass className="org.simantics.db.WriteGraph"/>\r
             <class className="org.simantics.sysdyn.ui.validation.EnumerationFunction"/>\r
         </namespace>        \r
+        <namespace path="Units">\r
+            <externalClass className="org.simantics.db.Resource"/>\r
+            <externalClass className="org.simantics.db.layer0.variable.Variable"/>\r
+            <externalClass className="org.simantics.db.ReadGraph"/>\r
+            <externalClass className="org.simantics.db.WriteGraph"/>\r
+            <class className="org.simantics.sysdyn.ui.validation.UnitFunction"/>\r
+        </namespace>             \r
       </namespace>\r
    </extension>\r
    <extension\r
index 540eda469d90100f65687fef9f6fa10e99a7c8ef..e5e154f3e96e95f817936729016ce9c6112d4aff 100644 (file)
@@ -22,20 +22,26 @@ import org.eclipse.swt.custom.ScrolledComposite;
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.Label;\r
 import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
 import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
 import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
 import org.simantics.browsing.ui.swt.widgets.TrackedCombo;\r
 import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
 import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl;\r
 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\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.request.PossibleObjectWithType;\r
 import org.simantics.db.common.utils.NameUtils;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.management.ISessionContext;\r
+import org.simantics.issues.ontology.IssueResource;\r
 import org.simantics.layer0.Layer0;\r
+import org.simantics.operation.Layer0X;\r
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.ui.properties.widgets.factories.ComboStringPropertyModifier;\r
 import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory;\r
@@ -193,6 +199,40 @@ public class ConfigurationTab extends LabelPropertyTabContributor {
                 "or\n" +\r
                 "Auxiliary1|Auxiliary2|Auxiliary3");\r
         \r
+        \r
+        Button validateUnits = new Button(composite, support, SWT.CHECK);\r
+        validateUnits.setText("Validate units");\r
+        validateUnits.setSelectionFactory(new ReadFactoryImpl<Resource, Boolean>() {\r
+\r
+            @Override\r
+            public Boolean perform(ReadGraph graph, Resource model) throws DatabaseException {\r
+                Resource unitIssueSource = graph.syncRequest(\r
+                        new PossibleObjectWithType(model, \r
+                                Layer0X.getInstance(graph).Activates, \r
+                                SysdynResource.getInstance(graph).Validations_Units_UnitIssueSource));\r
+                Boolean result = graph.getPossibleRelatedValue(unitIssueSource, IssueResource.getInstance(graph).IssueSource_active, Bindings.BOOLEAN);\r
+                return Boolean.TRUE.equals(result);\r
+            }\r
+        });\r
+        \r
+        validateUnits.addSelectionListener(new SelectionListenerImpl<Resource>(context){\r
+\r
+            @Override\r
+            public void apply(WriteGraph graph, Resource model) throws DatabaseException {\r
+                Resource unitIssueSource = graph.syncRequest(\r
+                        new PossibleObjectWithType(model, \r
+                                Layer0X.getInstance(graph).Activates, \r
+                                SysdynResource.getInstance(graph).Validations_Units_UnitIssueSource));\r
+                IssueResource ISSUE = IssueResource.getInstance(graph);\r
+                Boolean result = graph.getPossibleRelatedValue(unitIssueSource, ISSUE.IssueSource_active, Bindings.BOOLEAN);\r
+                if(result == null)\r
+                    result = false;\r
+                graph.claimLiteral(unitIssueSource, ISSUE.IssueSource_active, Boolean.FALSE.equals(result));\r
+            }\r
+            \r
+        });\r
+  \r
+        \r
         // Scrolled composite settings\r
         sc.setContent(composite);\r
         sc.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
index eab753cb396580415111a8aed9fc48a7d0b036e6..358ee0d195a1009623fca95d8a29e9e137165feb 100644 (file)
@@ -64,6 +64,8 @@ import org.simantics.db.request.Read;
 import org.simantics.db.service.VirtualGraphSupport;\r
 import org.simantics.layer0.Layer0;\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.ui.properties.widgets.ArrayExpressionCombo;\r
 import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes;\r
 import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType;\r
@@ -529,7 +531,7 @@ public class EquationTab extends LabelPropertyTabContributor implements Widget {
                                if (model != null) {\r
                                        Collection<Resource> variables = graph.getObjects(model, l0.ConsistsOf);\r
                                        for(Resource v : variables) {\r
-                                               Object unit = graph.getPossibleRelatedValue(v, sr.HasUnit);\r
+                                               Object unit = graph.getPossibleRelatedValue(v, sr.Variable_unit);\r
                                                if (unit != null && !map.keySet().contains(unit)) {\r
                                                        map.put((String)unit, (String)unit);\r
 \r
@@ -545,7 +547,7 @@ public class EquationTab extends LabelPropertyTabContributor implements Widget {
 \r
                        @Override\r
                        public String perform(ReadGraph graph, final Resource input) throws DatabaseException {\r
-                               String unit = graph.getPossibleRelatedValue(input, SysdynResource.getInstance(graph).HasUnit);\r
+                               String unit = graph.getPossibleRelatedValue(input, SysdynResource.getInstance(graph).Variable_unit);\r
                                if(unit == null)\r
                                        return "";\r
                                else \r
@@ -558,7 +560,14 @@ public class EquationTab extends LabelPropertyTabContributor implements Widget {
 \r
                        @Override\r
                        public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException {\r
-                               graph.claimLiteral(input, SysdynResource.getInstance(graph).HasUnit, text);\r
+                           graph.denyValue(input, SysdynResource.getInstance(graph).Variable_unit);\r
+                               graph.claimLiteral(input, SysdynResource.getInstance(graph).Variable_unit, text);\r
+                               \r
+                               Resource conf = graph.getPossibleObject(input, Layer0.getInstance(graph).PartOf);\r
+                               SysdynModelManager smm = SysdynModelManager.getInstance(graph.getSession());\r
+                               SysdynModel sm = smm.getModel(graph, conf);\r
+                               sm.getMapping().domainModified(input);\r
+                               sm.update(graph);\r
                        }\r
                });\r
 \r
index b4d5521e16056011bc87ccf0f0f97a8434549c06..06a9e2bbea6ef7f642a4b24eaf97c835e3c9265f 100644 (file)
@@ -42,7 +42,7 @@ public class ModuleParameterOverrideUtils {
     public static String getParameterExpression(IndependentVariable variable) throws DatabaseException {\r
         String result = null;\r
         try {\r
-            result = variable.getExpressions().get(0).getExpression(variable);\r
+            result = variable.getExpressions().get(0).getExpression();\r
         if(result.contains("/* Actual value read from init file */"))\r
             result = result.substring(0, result.indexOf("/* Actual value read from init file */"));\r
         } catch (NullPointerException e) {\r
index c6a513d17fc0825702712dc998fe90d8606ced1b..7682db35364092b3238cacb8ef53e3c45c295d95 100644 (file)
@@ -199,11 +199,11 @@ public class ExpressionUtils {
         // 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
+//        try {\r
+//            model.update();\r
+//        } catch (DatabaseException e1) {\r
+//            e1.printStackTrace();\r
+//        }\r
         Configuration conf = model.getConfiguration();\r
         \r
         // Check variable references\r
index 60b4280de5bdfdaf9b73eadacfc6805e1b6a53d2..8e4833b3b8cd6ff16662216341d322bbf46d4772 100644 (file)
@@ -11,6 +11,7 @@ import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.layer0.adapter.Template;\r
 import org.simantics.document.DocumentResource;\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.modeling.ModelingResources;\r
@@ -95,7 +96,14 @@ public class ModelUtils {
                     sr.Validations_Enumerations_EnumerationIssueSource,\r
                     L0X.IsActivatedBy, model,\r
                     l0.PartOf, model\r
-                    );            \r
+                    );     \r
+            \r
+            GraphUtils.create2(g,\r
+                    sr.Validations_Units_UnitIssueSource,\r
+                    L0X.IsActivatedBy, model,\r
+                    l0.PartOf, model,\r
+                    IssueResource.getInstance(g).IssueSource_active, false\r
+                    );               \r
 \r
             Resource conf = GraphUtils.create2(g,\r
                     sr.Configuration,\r
index eee9b25d7b3848ff01d758aff41ee9097d3cade6..d7fae469215f8e05ae7238f9cbd60a5d36a5fbea 100644 (file)
@@ -143,7 +143,7 @@ public class ImportUtils {
         final Resource project = SimanticsUI.getProject().get();\r
         if(project == null) return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import model: project not found", null);\r
 \r
-        beginTask(monitor, "Import model", 8);\r
+        beginTask(monitor, "Import model", 9);\r
 \r
         Activator.getDefault().getPreferenceStore().setValue(IMPORTMODELTPATH, (new File(path)).getParent());\r
 \r
@@ -192,6 +192,9 @@ public class ImportUtils {
                             subTask(monitor, "Add enumeration issue source");\r
                             addEnumerationIssueSource(graph, ModelRoot);\r
                             worked(monitor, 1);\r
+                            subTask(monitor, "Add unit issue source");\r
+                            addUnitIssueSource(graph, ModelRoot);\r
+                            worked(monitor, 1);\r
                             subTask(monitor, "Add shadow profile");\r
                             addShadowProfile(graph, ModelRoot);\r
                             worked(monitor, 1);                            \r
@@ -203,6 +206,7 @@ public class ImportUtils {
 \r
                     }\r
 \r
+\r
                 });\r
 \r
                 if(status != null)\r
@@ -328,6 +332,22 @@ public class ImportUtils {
         }   \r
     }\r
     \r
+\r
+    private static void addUnitIssueSource(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        Layer0X L0X = Layer0X.getInstance(graph); \r
+        SysdynResource sr = SysdynResource.getInstance(graph);\r
+        Collection<Resource> unitIssueSources = graph.syncRequest(new ObjectsWithType(modelRoot, L0.ConsistsOf, sr.Validations_Units_UnitIssueSource));\r
+        if(unitIssueSources.isEmpty()) {\r
+            GraphUtils.create2(graph,\r
+                    sr.Validations_Units_UnitIssueSource,\r
+                    L0X.IsActivatedBy, modelRoot,\r
+                    L0.PartOf, modelRoot,\r
+                    IssueResource.getInstance(graph).IssueSource_active, false\r
+                    );  \r
+        }    \r
+    }\r
+    \r
     private static void addShadowProfile(WriteGraph graph, Resource modelRoot) throws DatabaseException {\r
         DiagramResource DIA = DiagramResource.getInstance(graph);\r
         SysdynResource SR = SysdynResource.getInstance(graph);\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java
new file mode 100644 (file)
index 0000000..de8b9ee
--- /dev/null
@@ -0,0 +1,124 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - 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.db.Issue;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.issue.StandardIssue;\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.IssueUtils;\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.IndependentVariable;\r
+import org.simantics.sysdyn.representation.expressions.IExpression;\r
+\r
+public class UnitFunction {\r
+    \r
+    @SCLValue(type = "ReadGraph -> Resource -> [Issue]")\r
+    public static List<Issue> unitValidator(ReadGraph graph, Resource independentVariable) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        SysdynResource SR = SysdynResource.getInstance(graph);\r
+\r
+        \r
+        if(independentVariable == null)\r
+            return Collections.emptyList();\r
+        \r
+        Resource configuration = graph.getPossibleObject(independentVariable, L0.PartOf);\r
+        if(configuration == null)\r
+            return Collections.emptyList();\r
+        \r
+        // Make sure unit updates are listened to\r
+        Resource unitResource = graph.getPossibleObject(independentVariable, SR.Variable_unit);\r
+        String unit = graph.getPossibleRelatedValue(independentVariable, SR.Variable_unit);\r
+        if(unit == null || unit.trim().length() == 0)\r
+            return Collections.<Issue>singletonList(new StandardIssue(SR.Validations_UnitWarning, independentVariable));\r
+        \r
+        Resource expressionList = graph.getPossibleObject(independentVariable, SR.Variable_expressionList);\r
+        \r
+        if(expressionList == null)\r
+            return Collections.emptyList();\r
+\r
+        \r
+        SysdynModelManager smm = SysdynModelManager.getInstance(graph.getSession());\r
+        SysdynModel sm = smm.getModel(graph, configuration);\r
+        sm.getMapping().domainModified(independentVariable);\r
+\r
+        sm.update(graph);\r
+        Object var = sm.getMapping().get(independentVariable);\r
+\r
+        ArrayList<Issue> issues = new ArrayList<Issue>();\r
+\r
+        for(Resource expression : ListUtils.toList(graph, expressionList)) {\r
+            for(Resource r : graph.getObjects(expression, SR.Expression_equation)) {\r
+                graph.getValue(r);\r
+            }\r
+            \r
+            sm.getMapping().domainModified(expression);\r
+            sm.update(graph);\r
+            \r
+            Object expr = sm.getMapping().get(expression);\r
+\r
+            if(expr != null && var != null && expr instanceof IExpression && var instanceof IndependentVariable) {\r
+                String result = ((IExpression)expr).matchUnits(graph, sm.getMapping());\r
+                if(result != null) {\r
+                    Issue issue = new StandardIssue(SR.Validations_UnitWarning, independentVariable, expression, unitResource);\r
+                    issues.add(issue);\r
+                }\r
+            }\r
+        }\r
+\r
+        return issues;\r
+    }\r
+\r
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
+    public static String unitWarningDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {\r
+        List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
+        \r
+        if(contexts.size() == 0)\r
+            return "Error, No contexts";\r
+        \r
+        Resource variable = contexts.get(0);\r
+        String unit = graph.getPossibleRelatedValue(variable, SysdynResource.getInstance(graph).Variable_unit);\r
+\r
+        if(unit == null || unit.length() == 0)\r
+            return "No unit defined";\r
+        \r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        Resource configuration = graph.getPossibleObject(variable, L0.PartOf);\r
+        if(configuration == null)\r
+            return "Error, No Confiugration";\r
+        \r
+\r
+        SysdynModelManager smm = SysdynModelManager.getInstance(graph.getSession());\r
+        SysdynModel sm = smm.getModel(graph, configuration);\r
+        \r
+        SysdynResource SR = SysdynResource.getInstance(graph);\r
+        for(Resource r : graph.getObjects(contexts.get(1), SR.Expression_equation)) {\r
+            graph.getValue(r);\r
+        }\r
+        \r
+        Object expr = sm.getMapping().get(contexts.get(1));\r
+        String result = ((IExpression)expr).matchUnits(graph, sm.getMapping());\r
+        return result;\r
+    }\r
+\r
+}
\ No newline at end of file
index 5cfca79e5d41f3b351974ec718b398b5666008c2..049bcb809e83a2fe8c270ab83d3e797e9e89ddaf 100644 (file)
@@ -296,7 +296,7 @@ public class ValueView  extends ViewPart {
        private String approximate(Double time, int index, SysdynDataSet dataset) {\r
                \r
                // time out of datasets range\r
-               if(time > dataset.times[dataset.times.length - 1] ||\r
+               if(dataset.times.length == 0 || time > dataset.times[dataset.times.length - 1] ||\r
                                time < dataset.times[0]) {\r
                        return "---";\r
                }\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java
new file mode 100644 (file)
index 0000000..f12f828
--- /dev/null
@@ -0,0 +1,230 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn;\r
+\r
+import java.io.StringReader;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.ParseException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.UnitParser;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult;\r
+\r
+public class TestParser {\r
+    \r
+    /**\r
+     * @param args\r
+     */\r
+    public static void main(String[] args) {\r
+\r
+        HashMap<String, String> units = new HashMap<String, String>();\r
+        \r
+        doScenario(scenario1(units), units);\r
+        doScenario(scenario2(units), units);\r
+        doScenario(scenario3(units), units);\r
+        doScenario(scenario4(units), units);\r
+        doScenario(scenario5(units), units);\r
+        doScenario(scenario6(units), units);\r
+        doScenario(scenario7(units), units);\r
+        doScenario(scenario8(units), units);\r
+        doScenario(scenario9(units), units);\r
+        doScenario(scenario10(units), units);\r
+        doScenario(scenario11(units), units);\r
+        doScenario(scenario12(units), units);\r
+        doScenario(scenario13(units), units);\r
+\r
+    }\r
+    \r
+    private static void doScenario(String expression, HashMap<String, String> units) {\r
+        System.out.println("-----------------------------------");\r
+        System.out.println("Expression: " + expression);\r
+        System.out.println("Units: ");\r
+        for(String key : units.keySet()) {\r
+            System.out.println("   " + key + " -> " + units.get(key));\r
+        }\r
+        StringReader sr = new StringReader(expression);\r
+        UnitParser parser = new UnitParser(sr);\r
+        try {\r
+            UnitCheckingNode node = (UnitCheckingNode) parser.expr();\r
+            \r
+            try {\r
+                UnitResult u = node.getUnits(units);\r
+                System.out.println("Result: " + u.getCleanFullUnit());\r
+            } catch (UnitCheckingException e) {\r
+                e.printStackTrace();\r
+            }\r
+            \r
+//            node.dump("");\r
+        } catch (ParseException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+    \r
+    private static String scenario1(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        units.put("c", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("a*b*c");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario2(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        units.put("c", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("a+b+c");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario3(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        units.put("c", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("a/b+b/c");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario4(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        units.put("c", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("if a == b then a+b else b + c + a");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario5(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "s");\r
+        units.put("c", "m");\r
+        units.put("d", "s");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+//        sb.append("a / b + (c*a)/(b*a)");\r
+        sb.append("c/(b*a)");\r
+\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario6(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "s");\r
+        units.put("c", "m");\r
+        units.put("d", "m/s");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("if a > c then c*a/b else a*d");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario7(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m/s");\r
+        units.put("b.e", "s");\r
+        units.put("c", "m");\r
+        units.put("d", "s");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("a[1] + c[1] / b.e[1]");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario8(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "s");\r
+        units.put("c", "s*m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("c + {a[i] * b[i] for i in 1:3}");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario9(HashMap<String, String> units) {\r
+        units.clear();\r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("1+a+1+b");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario10(HashMap<String, String> units) {\r
+        units.clear();\r
+        units.put("a", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("1*a*1*a");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario11(HashMap<String, String> units) {\r
+        units.clear();\r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("-a+b");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario12(HashMap<String, String> units) {\r
+        units.clear();\r
+        units.put("a", "m");\r
+        units.put("b", "s");\r
+        units.put("c", "m/s");\r
+\r
+\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("1/a/b + 1/c");\r
+        return sb.toString();\r
+    }\r
+    \r
+    private static String scenario13(HashMap<String, String> units) {\r
+        units.clear();\r
+        \r
+        units.put("a", "m");\r
+        units.put("b", "m");\r
+        units.put("c", "m");\r
+        units.put("d", "s");\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("(a/b+b/c)/d");\r
+        return sb.toString();\r
+    }\r
+    \r
+}\r
+\r
+\r
index 29f9fc7291ebe1e74ce2ef830826476c67380d72..91378b2b2a8592dce844c5cb05c12d087da2071e 100644 (file)
@@ -272,9 +272,6 @@ public class SysdynModel implements IMappingListener, IModel, VariableSubscripti
      */\r
     public synchronized boolean update(ReadGraph graph) throws DatabaseException {\r
         if(mapping.isDomainModified()) {\r
-            \r
-\r
-            \r
             try {\r
                 Collection<Object> updated = mapping.updateRange(graph);\r
                 \r
index ad27b79b2100b0e2d1c1bfe5cfe7944a4208de2c..f2fc13bfd127568462acfe7ca266f58d9b5fc75e 100644 (file)
@@ -81,7 +81,7 @@ public abstract class Variable extends Element {
                }\r
                \r
                if(units != null && units.length() > 0)\r
-                       graph.claimLiteral(variable, sr.HasUnit, units);\r
+                       graph.claimLiteral(variable, sr.Variable_unit, units);\r
                if(comments != null && comments.length() > 0)\r
                        graph.claimLiteral(variable, l0.HasDescription, comments);\r
                if(rangeStart != null)\r
index 8cf3a5b7f97af5e9ccd4fe70d3462d7bec6603fe..fe483fe1290dfd7e2f18c52e1548d7519d6583d4 100644 (file)
@@ -396,7 +396,7 @@ void component_declaration1() : {
 void equation_section() : {\r
 } {\r
 //     [ initial ] equation { equation ";" }\r
-       ( "initial" )? "equation" ( equation() ";" )*\r
+       ( "initial" )? "equation" ( LOOKAHEAD(2) equation() ";" )*\r
 }\r
 \r
 void algorithm_section() : {\r
index bf4f2ad7a7dcce47de317a59e37f4b4c5584f3c2..ef85624930deaaad53404ef1a99d7c3e1834cb1f 100644 (file)
@@ -50,7 +50,7 @@ public abstract class IndependentVariable extends Variable {
         // [= expression]\r
         if(variability == Variability.PARAMETER || variability == Variability.CONSTANT) {\r
             // parameters and constants are guaranteed to have only one expression\r
-            String equation = FormatUtils.formatExpressionForModelica(this, getExpressions().get(0).getExpression(this));\r
+            String equation = FormatUtils.formatExpressionForModelica(this, getExpressions().get(0).getExpression());\r
             sb.append(" = " + equation);\r
         }\r
 \r
@@ -61,7 +61,7 @@ public abstract class IndependentVariable extends Variable {
         if(getExpressions() != null) {\r
             String addition;\r
             for(IExpression e : getExpressions()) {\r
-                addition = e.getDeclarationAddition(this);\r
+                addition = e.getDeclarationAddition();\r
                 if(addition != null)\r
                     sb.append(addition);\r
             }\r
@@ -103,7 +103,7 @@ public abstract class IndependentVariable extends Variable {
         StringBuilder sb = new StringBuilder();                \r
 \r
         for(IExpression expression : getExpressions()) {\r
-            String initialEquation = expression.getInitialEquation(this);\r
+            String initialEquation = expression.getInitialEquation();\r
             if(initialEquation != null)\r
                 sb.append(initialEquation);\r
         }\r
@@ -140,12 +140,12 @@ public abstract class IndependentVariable extends Variable {
             if(firstExpression == null)\r
                 return null;\r
             else\r
-                return firstExpression.getEquation(this);\r
+                return firstExpression.getEquation();\r
         } else {\r
             // ARRAY variable. Create all equations for the variable\r
             StringBuilder sb = new StringBuilder();         \r
             for(IExpression expression : expressions) {\r
-                sb.append(expression.getEquation(this));\r
+                sb.append(expression.getEquation());\r
             }\r
             return sb.toString();\r
         }\r
index 7b740633f4983fde71a2e0800e8ca892e8cafaa3..8e259bbf143102238cb96348a01b6e715097e4f7 100644 (file)
@@ -66,7 +66,7 @@ public class Stock extends IndependentVariable {
         } else {\r
             // Start parameter is used. Parameter guarantees that there is only one expression.\r
             StockExpression e = (StockExpression)getExpressions().get(0);\r
-            String initialEquation = e.getExpression(this);\r
+            String initialEquation = e.getExpression();\r
             initialEquation = SheetFormatUtils.reformatSheetReferences(this, initialEquation);\r
 \r
             if(getArrayIndexes() != null && !getArrayIndexes().isEmpty())\r
@@ -79,7 +79,7 @@ public class Stock extends IndependentVariable {
             getName() + \r
             getRange() + \r
             "(" + \r
-            (e.getStartValue(this) != null ? each : "") + \r
+            (e.getStartValue() != null ? each : "") + \r
             " start=" + \r
             initialEquation + \r
             ", " + \r
index c5d0a34015b43f273f7d83f2f551737f3250a904..27f33a69b79ce4df484e41d2e5799fc52a170f3d 100644 (file)
@@ -202,7 +202,7 @@ public enum Variability {
 \r
         org.simantics.sysdyn.representation.expressions.IExpression ie  = expressions.get(0);\r
 \r
-        String expression = ie.getExpression(variable);\r
+        String expression = ie.getExpression();\r
 \r
         return getVariability(variable, expression, allowVariableReferences, configuration);\r
     }\r
index b5109d9d276bea6cebfa379600e44197af4d4d14..131246548cfaacf061b459a739610d79aa26b7f5 100644 (file)
@@ -45,6 +45,9 @@ public abstract class Variable implements IElement {
     @RelatedValue(SysdynResource.URIs.Variable_variability)\r
     protected String variability;\r
     \r
+    @RelatedValue(SysdynResource.URIs.Variable_unit)\r
+    protected String unit;\r
+    \r
     /**\r
      * Return the variability of this variable (Used in practice only with Input variables)\r
      * @return Variability\r
@@ -99,4 +102,12 @@ public abstract class Variable implements IElement {
         return this.expressions;\r
     }\r
     \r
+    /**\r
+     * \r
+     * @return Units of this variable\r
+     */\r
+    public String getUnit() {\r
+        return this.unit;\r
+    }\r
+    \r
 }\r
index 5490f308ab0672d801a2d98e778ad10271717714..2e4a5dadba340efdc06e249b7d8ef00de553b103 100644 (file)
@@ -14,7 +14,6 @@ package org.simantics.sysdyn.representation.expressions;
 import org.simantics.objmap.annotations.GraphType;\r
 import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
 \r
 /**\r
  * Represents a constant expression\r
@@ -29,7 +28,7 @@ public class ConstantExpression extends Expression {
     private String equation;\r
 \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return equation;\r
     }\r
 }\r
index 1c63ec0d99b6bf8086100f7275fa26bbcee31549..6a296c800a64ae04e203a01932197100ef76204a 100644 (file)
@@ -16,7 +16,6 @@ import org.simantics.objmap.annotations.RelatedValue;
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.representation.IndependentVariable;\r
 import org.simantics.sysdyn.representation.Variability;\r
-import org.simantics.sysdyn.representation.Variable;\r
 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
 \r
@@ -61,27 +60,27 @@ public class DelayExpression extends Expression {
     private String equation;\r
 \r
     @Override\r
-    public String getDeclarationAddition(IndependentVariable variable) {\r
+    public String getDeclarationAddition() {\r
 \r
-        String delayTime = FormatUtils.formatExpressionForModelica(variable, this.delayTime);\r
-        String initialValue = FormatUtils.formatExpressionForModelica(variable, this.initialValue);\r
-        Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, delayTime);\r
+        String delayTime = FormatUtils.formatExpressionForModelica(parent, this.delayTime);\r
+        String initialValue = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
+        Variability delayTimeVariability = Variability.getVariability((IndependentVariable)parent, delayTime);\r
         Variability initialVariability = Variability.CONTINUOUS;\r
         if(initialValue != null && initialValue.length() > 0) {\r
             /*\r
              *  By default, initial value variability is continuous.\r
              *  If initial value has been set, it can be some other. \r
              */\r
-            initialVariability = Variability.getVariability(variable, initialValue);\r
+            initialVariability = Variability.getVariability(parent, initialValue);\r
         }\r
 \r
 \r
         StringBuilder declaration = new StringBuilder();\r
 \r
-        String range = variable.getRange();\r
+        String range = parent.getRange();\r
 \r
         // Delay declaration\r
-        declaration.append("    " + variable.getName() + "_delayClass " + variable.getName() + "_delayClass_instance");\r
+        declaration.append("    " + parent.getName() + "_delayClass " + parent.getName() + "_delayClass_instance");\r
 \r
         // Change enumeration sizes from the delay class. Supports overridden enumerations in modules.\r
         if(range.length() > 0 || !initialVariability.equals(Variability.CONTINUOUS) || !delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
@@ -120,7 +119,7 @@ public class DelayExpression extends Expression {
         declaration.append(";\n");\r
 \r
         // Write the delay class\r
-        declaration.append(getDelayClass(variable, range, order));\r
+        declaration.append(getDelayClass(range, order));\r
         return declaration.toString();\r
     }\r
 \r
@@ -134,10 +133,10 @@ public class DelayExpression extends Expression {
      * @param n Order of the delay\r
      * @return\r
      */\r
-    private String getDelayClass(Variable variable, String range, int n) {\r
+    private String getDelayClass(String range, int n) {\r
         StringBuilder sb = new StringBuilder();\r
 \r
-        sb.append("class " + variable.getName() + "_delayClass\n");\r
+        sb.append("class " + parent.getName() + "_delayClass\n");\r
 \r
         // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable\r
         if(range.length() > 0) {\r
@@ -147,8 +146,8 @@ public class DelayExpression extends Expression {
             }\r
         }\r
 \r
-        String dt = FormatUtils.formatExpressionForModelica(variable,delayTime);\r
-        Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, dt);\r
+        String dt = FormatUtils.formatExpressionForModelica(parent,delayTime);\r
+        Variability delayTimeVariability = Variability.getVariability(parent, dt);\r
         if(!delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
             // Auxiliary variable\r
             sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " DL = delayTime/" + n + ";\n");\r
@@ -164,9 +163,9 @@ public class DelayExpression extends Expression {
 \r
         // Get initial value variability\r
         Variability initialValueVariability = Variability.CONTINUOUS;\r
-        String initEquation = FormatUtils.formatExpressionForModelica(variable, this.initialValue);\r
+        String initEquation = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
         if(initialValue != null && initialValue.length() > 0) {\r
-            initialValueVariability = Variability.getVariability((IndependentVariable)variable, initEquation);\r
+            initialValueVariability = Variability.getVariability(parent, initEquation);\r
         }\r
 \r
         // Declare initial value (continuous or other)\r
@@ -209,47 +208,47 @@ public class DelayExpression extends Expression {
             sb.append("\tdelay" + i + " = LV" + i + " " + (range.isEmpty() ? "/" : "./") + "DL;\n");\r
         }\r
 \r
-        sb.append("end " + variable.getName() + "_delayClass;\n");\r
+        sb.append("end " + parent.getName() + "_delayClass;\n");\r
         return sb.toString();\r
     }\r
 \r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
+    public String getEquation() {\r
         StringBuilder sb = new StringBuilder();\r
 \r
-        String equation = FormatUtils.formatExpressionForModelica(variable, this.equation);\r
-        String delayTime = FormatUtils.formatExpressionForModelica(variable, this.delayTime);\r
-        String initialValue = FormatUtils.formatExpressionForModelica(variable, this.initialValue);\r
+        String equation = FormatUtils.formatExpressionForModelica(parent, this.equation);\r
+        String delayTime = FormatUtils.formatExpressionForModelica(parent, this.delayTime);\r
+        String initialValue = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
 \r
         // First "valve" in the delay\r
-        sb.append("    " + variable.getName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
+        sb.append("    " + parent.getName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
 \r
         // Delay time (if continuous)\r
-        Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, delayTime);\r
+        Variability delayTimeVariability = Variability.getVariability(parent, delayTime);\r
         if(delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
-            sb.append("    " + variable.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
+            sb.append("    " + parent.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
         }\r
 \r
         // Initial value\r
         if(initialValue == null || initialValue.length() == 0) {\r
             // No initial value set, use delay0 (the first "valve")\r
-            sb.append("    " + variable.getName() + "_delayClass_instance.initialValue = " + variable.getName() + "_delayClass_instance.delay0;\n");\r
+            sb.append("    " + parent.getName() + "_delayClass_instance.initialValue = " + parent.getName() + "_delayClass_instance.delay0;\n");\r
         } else {\r
             // Continuous initial value\r
-            Variability initialVariability = Variability.getVariability(variable, initialValue);\r
+            Variability initialVariability = Variability.getVariability(parent, initialValue);\r
             if(initialVariability.equals(Variability.CONTINUOUS)) {\r
-                sb.append("    " + variable.getName() + "_delayClass_instance.initialValue = " + initialValue + ";\n");\r
+                sb.append("    " + parent.getName() + "_delayClass_instance.initialValue = " + initialValue + ";\n");\r
             }\r
         }\r
 \r
         // The value of the actual variable\r
-        String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
-        sb.append("    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + variable.getName() + "_delayClass_instance.delay" + order + ";\n");\r
+        String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
+        sb.append("    " + parent.getName() + (range.equals("[:]") ? "" : range) + " = " + parent.getName() + "_delayClass_instance.delay" + order + ";\n");\r
         return sb.toString();\r
     }\r
 \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return "This + is + not + a + parameter + at + any + time";\r
     }\r
 \r
index 1d9d77fa5a6d10bcd5faa42470d6e2d82cab4efb..9f5f28f06219aef28e46860ce94178ca43eac6e8 100644 (file)
  *******************************************************************************/\r
 package org.simantics.sysdyn.representation.expressions;\r
 \r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.IMapping;\r
+import org.simantics.objmap.annotations.RelatedElement;\r
 import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.representation.IndependentVariable;\r
+import org.simantics.sysdyn.representation.utils.UnitUtils;\r
 \r
 /**\r
  * Abstract class for any expression\r
@@ -25,24 +30,27 @@ public abstract class Expression implements IExpression {
         \r
     @RelatedValue(SysdynResource.URIs.Expression_arrayRange)\r
     private String range;\r
+    \r
+    @RelatedElement(Layer0.URIs.PartOf)\r
+    protected IndependentVariable parent;\r
 \r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
+    public String getEquation() {\r
         return null;\r
     }\r
 \r
     @Override\r
-    public String getInitialEquation(IndependentVariable variable) {\r
+    public String getInitialEquation() {\r
         return null;\r
     }\r
     \r
     @Override\r
-    public String getDeclarationAddition(IndependentVariable variable) {\r
+    public String getDeclarationAddition() {\r
         return null;\r
     }\r
 \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return null;\r
     }\r
     \r
@@ -54,4 +62,13 @@ public abstract class Expression implements IExpression {
                return range;\r
     }\r
 \r
+    @Override\r
+    public String matchUnits() {\r
+        return UnitUtils.matchUnits(null, null, parent, getExpression());\r
+    }\r
+    \r
+    @Override\r
+    public String matchUnits(ReadGraph graph, IMapping mapping) {\r
+        return UnitUtils.matchUnits(graph, mapping, parent, getExpression());\r
+    }\r
 }\r
index c3f7ae77b2ce8bf57abb9db9dd1b9eedcf797056..48ecdaa47f361cdc89ddf0410b92f74b5c6c911b 100644 (file)
@@ -11,7 +11,9 @@
  *******************************************************************************/\r
 package org.simantics.sysdyn.representation.expressions;\r
 \r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.IMapping;\r
+\r
 \r
 /**\r
  * Interface for all expressions in System Dynamics models\r
@@ -27,21 +29,21 @@ public interface IExpression {
      * @param variable Declared independent variable\r
      * @return additions or null\r
      */\r
-    String getDeclarationAddition(IndependentVariable variable);\r
+    String getDeclarationAddition();\r
     \r
     /**\r
      * Initial value for this variable and expression\r
      * @param variable IndependentVariable\r
      * @return initial value or null\r
      */\r
-    String getInitialEquation(IndependentVariable variable);\r
+    String getInitialEquation();\r
     \r
     /**\r
      * Get the actual equation of this expression\r
      * @param variable IndependentVariable\r
      * @return equation or null\r
      */\r
-    String getEquation(IndependentVariable variable);\r
+    String getEquation();\r
     \r
     /**\r
      * Get the range of this expression\r
@@ -54,6 +56,22 @@ public interface IExpression {
      * @param variable\r
      * @return\r
      */\r
-    String getExpression(IndependentVariable variable);\r
-\r
+    String getExpression();\r
+    \r
+    \r
+    /**\r
+     * Match the units of this expression to units of its variable\r
+     * @return null if match, Error message otherwise\r
+     */\r
+    String matchUnits();\r
+    \r
+    /**\r
+     * Match the units of this expression to units of its variable. \r
+     * \r
+     * Requests units of referred variables for request listening\r
+     * @param graph ReadGraph\r
+     * @param mapping ObjMap mapping\r
+     * @return null if match, ERror message otherwise\r
+     */\r
+    String matchUnits(ReadGraph graph, IMapping mapping);\r
 }\r
index a0501b4796161d7417144a39fb2e2979a16a119e..a8d4d6676f3f99a4604b4917063fd9446cfe5bf0 100644 (file)
@@ -14,7 +14,6 @@ package org.simantics.sysdyn.representation.expressions;
 import org.simantics.objmap.annotations.GraphType;\r
 import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
 \r
@@ -31,15 +30,15 @@ public class NormalExpression extends Expression {
     private String equation;\r
     \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return equation;\r
     }\r
 \r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
-       String equation = FormatUtils.formatExpressionForModelica(variable, this.equation);\r
-       String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
-        return "    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + equation + ";\n";\r
+    public String getEquation() {\r
+       String equation = FormatUtils.formatExpressionForModelica(parent, this.equation);\r
+       String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
+        return "    " + parent.getName() + (range.equals("[:]") ? "" : range) + " = " + equation + ";\n";\r
     }\r
 \r
 }\r
index 874de79a68746c0f9eb9549bf009849964c523d1..96ba68991fb582d34ae67ca5e966a3dd72c5b84f 100644 (file)
@@ -14,7 +14,6 @@ package org.simantics.sysdyn.representation.expressions;
 import org.simantics.objmap.annotations.GraphType;\r
 import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
 \r
 /**\r
@@ -30,12 +29,12 @@ public class ParameterExpression extends Expression {
     private String equation;\r
     \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return equation + " /* Actual value read from init file */";\r
     }\r
     \r
     @Override\r
-    public String getDeclarationAddition(IndependentVariable variable) {\r
+    public String getDeclarationAddition() {\r
         return ""; \r
     }\r
 \r
@@ -44,9 +43,9 @@ public class ParameterExpression extends Expression {
      * Used when the expression is a part of an array variable. Then it is like a normal auxiliary.\r
      */\r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
-       String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
-       return "    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + equation + ";\n";\r
+    public String getEquation() {\r
+       String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
+       return "    " + parent.getName() + (range.equals("[:]") ? "" : range) + " = " + equation + ";\n";\r
     };\r
     \r
     public Double getValue() {\r
index 13ee73eace567622bb36da4dbb05d7eb39260431..17e1a78e6c3cd049134d2367d315114992662a20 100644 (file)
@@ -23,7 +23,6 @@ import org.simantics.sysdyn.expressionParser.ParseException;
 import org.simantics.sysdyn.representation.Book;\r
 import org.simantics.sysdyn.representation.Enumeration;\r
 import org.simantics.sysdyn.representation.IElement;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
 import org.simantics.sysdyn.representation.Sheet;\r
 import org.simantics.sysdyn.representation.Stock;\r
 import org.simantics.sysdyn.representation.Valve;\r
@@ -43,29 +42,29 @@ public class StockExpression extends Expression {
     private String initialEquation;\r
 \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return initialEquation;\r
     }\r
     \r
 \r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
+    public String getEquation() {\r
         \r
         // Build range e.g. Stock[2,3]\r
-       String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
+       String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
        \r
        // Stock equation is always der(Stock)\r
         StringBuilder b = new StringBuilder();\r
         b.append("    der(")\r
-        .append(variable.getName() + range)\r
+        .append(parent.getName() + range)\r
         .append(") =");\r
         \r
         // Stock equation is formed automatically using incoming and outgoing flows (actually the nearest valves in those flows)\r
-        ArrayList<Valve> incoming = ((Stock)variable).getIncomingValves();\r
-        ArrayList<Valve> outgoing = ((Stock)variable).getOutgoingValves();\r
+        ArrayList<Valve> incoming = ((Stock)parent).getIncomingValves();\r
+        ArrayList<Valve> outgoing = ((Stock)parent).getOutgoingValves();\r
         if(incoming.isEmpty() && outgoing.isEmpty()) {\r
             // No connections, add 0 for each array index if any.\r
-            ArrayList<Enumeration> enumerations = variable.getArrayIndexes();\r
+            ArrayList<Enumeration> enumerations = parent.getArrayIndexes();\r
             if(enumerations == null || enumerations.isEmpty()) {\r
                 b.append(" 0.0");\r
             } else {\r
@@ -93,11 +92,11 @@ public class StockExpression extends Expression {
      * Check whether to use fixed=true and start=... in Modelica code\r
      * @return\r
      */\r
-    private boolean useStartValue(IndependentVariable variable) {\r
+    private boolean useStartValue() {\r
         // If no variables are used in the equation, start value is used\r
         \r
         // First the equation is formatted and parsed\r
-        String equation = FormatUtils.formatExpressionForModelica(variable, initialEquation);\r
+        String equation = FormatUtils.formatExpressionForModelica(parent, initialEquation);\r
         ExpressionParser parser = new ExpressionParser(new StringReader(equation));\r
         try {\r
             parser.expr();\r
@@ -115,7 +114,7 @@ public class StockExpression extends Expression {
                     // We only need the first element to know that it is a Sheet (SheetName.CellOrRange)\r
                     reference = reference.split("\\.")[0]; \r
                     found = false;\r
-                    for(IElement element : variable.getParentConfiguration().getElements()) {\r
+                    for(IElement element : parent.getParentConfiguration().getElements()) {\r
                         if(element instanceof Book) {\r
                             for(Sheet sheet : ((Book)element).getSheets()) {\r
                                 if(reference.equals(sheet.getName())) {\r
@@ -140,16 +139,16 @@ public class StockExpression extends Expression {
     }\r
 \r
     @Override\r
-    public String getInitialEquation(IndependentVariable variable) {\r
+    public String getInitialEquation() {\r
         // if start value is used, no initial equation is returned\r
-        if(useStartValue(variable))\r
+        if(useStartValue())\r
             return null;\r
         // format the initial equation for modelica execution \r
-        String equation = FormatUtils.formatExpressionForModelica(variable, initialEquation, false);\r
-       String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
+        String equation = FormatUtils.formatExpressionForModelica(parent, initialEquation, false);\r
+       String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
        if(range == null)\r
                range = "";\r
-       return "    " + variable.getName() + range + " = " + equation + ";\n";\r
+       return "    " + parent.getName() + range + " = " + equation + ";\n";\r
     }\r
     \r
     \r
@@ -159,12 +158,12 @@ public class StockExpression extends Expression {
      * @param variable\r
      * @return Double representing the initial equation or null if initial equation is not a double\r
      */\r
-    public Double getStartValue(IndependentVariable variable) {\r
+    public Double getStartValue() {\r
        Double value = null;\r
-       ArrayList<IExpression> expressions = variable.getExpressions();\r
+       ArrayList<IExpression> expressions = parent.getExpressions();\r
        if(expressions.size() == 1) {\r
                IExpression e = expressions.get(0);\r
-            if(e.getInitialEquation(variable) == null) {\r
+            if(e.getInitialEquation() == null) {\r
                 try {\r
                     value = Double.parseDouble(initialEquation);\r
                 } catch(NumberFormatException e1) {\r
index f40cc43e35c1ea8886e18829142b1b16b7d8bb9e..c98ee79a9e6e60bfc7ce7f6988d3f9bfa06090ef 100644 (file)
@@ -14,7 +14,6 @@ package org.simantics.sysdyn.representation.expressions;
 import org.simantics.objmap.annotations.GraphType;\r
 import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
 import org.simantics.sysdyn.representation.utils.SheetFormatUtils;\r
@@ -34,16 +33,16 @@ public class WithLookupExpression extends Expression {
     private String equation;\r
 \r
     @Override\r
-    public String getEquation(IndependentVariable variable) {\r
-        String equation = FormatUtils.formatExpressionForModelica(variable, this.equation);\r
-       String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
+    public String getEquation() {\r
+        String equation = FormatUtils.formatExpressionForModelica(parent, this.equation);\r
+       String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
 \r
         return \r
-        "    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = interpolate(" + equation + ", " + SheetFormatUtils.reformatSheetReferences(variable, lookupTable) + ");\n";\r
+        "    " + parent.getName() + (range.equals("[:]") ? "" : range) + " = interpolate(" + equation + ", " + SheetFormatUtils.reformatSheetReferences(parent, lookupTable) + ");\n";\r
     }\r
     \r
     @Override\r
-    public String getExpression(IndependentVariable variable) {\r
+    public String getExpression() {\r
         return "interpolate(" + equation + ", " + lookupTable + ")";\r
     }\r
 \r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java
new file mode 100644 (file)
index 0000000..8536576
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.representation.utils;\r
+\r
+import java.io.StringReader;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.objmap.IMapping;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.representation.Configuration;\r
+import org.simantics.sysdyn.representation.IElement;\r
+import org.simantics.sysdyn.representation.Module;\r
+import org.simantics.sysdyn.representation.Variable;\r
+import org.simantics.sysdyn.unitParser.ParseException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.UnitParser;\r
+import org.simantics.sysdyn.unitParser.nodes.ComponentReferenceFull;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult;\r
+\r
+public class UnitUtils {\r
+    \r
+    public static String matchUnits(ReadGraph graph, IMapping mapping, Variable variable, String expression) {\r
+        if(variable.getUnit() == null)\r
+            return "Unit not defined for " + variable.getName();\r
+        try {\r
+            \r
+            StringReader rightReader = new StringReader(expression);\r
+            UnitParser rightParser = new UnitParser(rightReader);\r
+            UnitCheckingNode right = (UnitCheckingNode) rightParser.expr();\r
+            rightReader.close();\r
+            Set<String> components = findComponents(right);\r
+            HashMap<String, String> units = findUnits(graph, mapping, variable, components);\r
+            \r
+            StringReader leftReader = new StringReader(variable.getUnit());\r
+            UnitParser leftParser = new UnitParser(leftReader);\r
+            UnitCheckingNode left = (UnitCheckingNode) leftParser.expr();\r
+            leftReader.close();\r
+            \r
+            try {\r
+                UnitResult rightUnits = right.getUnits(units);\r
+                UnitResult leftUnits = left.getUnits(null);\r
+                \r
+                if(!rightUnits.equals(leftUnits))\r
+                    return leftUnits.getCleanFullUnit() + " != " + rightUnits.getCleanFullUnit();\r
+            } catch (UnitCheckingException e) {\r
+                return e.getMessage();\r
+            }\r
+            \r
+//            node.dump("");\r
+        } catch (ParseException e) {\r
+            e.printStackTrace();\r
+        }\r
+        \r
+        return null;\r
+    }\r
+    \r
+    \r
+    private static HashMap<String, String> findUnits(ReadGraph graph, IMapping mapping, Variable variable, Set<String> components) {\r
+        HashMap<String, String> units = new HashMap<String, String>();\r
+        Configuration configuration = variable.getParentConfiguration();\r
+        for(String component : components) {\r
+            Variable var = getElement(configuration, component);\r
+            if(var != null) {\r
+                \r
+                // Support listening, if graph and mapping exists\r
+                if(graph != null && mapping != null) {\r
+                    Resource varResource = mapping.inverseGet(var);\r
+                    if(varResource != null) {\r
+                        try {\r
+                            graph.getPossibleRelatedValue(varResource, SysdynResource.getInstance(graph).Variable_unit);\r
+                        } catch (ManyObjectsForFunctionalRelationException e) {\r
+                            e.printStackTrace();\r
+                        } catch (ServiceException e) {\r
+                            e.printStackTrace();\r
+                        }\r
+                    }\r
+                }\r
+                \r
+                String unit = var.getUnit();\r
+                if(unit != null) {\r
+                    units.put(component, unit);\r
+                }\r
+            }\r
+        }\r
+        \r
+        \r
+        \r
+        return units;\r
+    }\r
+    \r
+    private static Variable getElement(Configuration configuration, String name) {\r
+        String[] elements = name.split("\\.");\r
+        String element = elements[0];\r
+        for(IElement e : configuration.getElements()) {\r
+            if(e instanceof Variable) {\r
+                Variable var = (Variable)e;\r
+                if(var.getName().equals(element))\r
+                    return var;\r
+            } else if(e instanceof Module && elements.length > 1) {\r
+                Module mod = (Module)e;\r
+                if(mod.getName().equals(element)) {\r
+                    return getElement(mod.getType().getConfiguration(), name.substring(name.indexOf(".") + 1));\r
+                }\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    private static Set<String> findComponents(UnitCheckingNode node) {\r
+        HashSet<String> components = new HashSet<String>();\r
+        addComponents(node, components);\r
+        return components;\r
+        \r
+    }\r
+    \r
+    private static void addComponents(UnitCheckingNode node, HashSet<String> components) {\r
+        if(node instanceof ComponentReferenceFull) {\r
+            components.add(node.printNode());\r
+        } else {\r
+            for(int i = 0; i < node.jjtGetNumChildren(); i++) {\r
+                addComponents((UnitCheckingNode)node.jjtGetChild(i), components);\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingException.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingException.java
new file mode 100644 (file)
index 0000000..481004c
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser;\r
+\r
+public class UnitCheckingException extends Exception {\r
+    public UnitCheckingException(String string) {\r
+        super(string);\r
+    }\r
+\r
+    private static final long serialVersionUID = -5828012051088095625L;\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java
new file mode 100644 (file)
index 0000000..e80e60f
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult;\r
+\r
+\r
+public class UnitCheckingNode extends SimpleNode {\r
+\r
+    public UnitCheckingNode(int id) {\r
+        super(id);\r
+    }\r
+\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException{\r
+        UnitResult result = new UnitResult();\r
+\r
+        if(jjtGetNumChildren() == 0){\r
+            String node = printNode();\r
+            result.append(node);\r
+        } else {\r
+            for(UnitCheckingNode node : getChildren()) {\r
+                result.appendResult(node.getUnits(units));\r
+            }\r
+        }\r
+        return result; \r
+    }\r
+    \r
+    protected ArrayList<UnitCheckingNode> getChildren() {\r
+        ArrayList<UnitCheckingNode> children = new ArrayList<UnitCheckingNode>();\r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            children.add((UnitCheckingNode)jjtGetChild(i));\r
+        }\r
+        return children;\r
+    }\r
+\r
+\r
+    public String printNode() {\r
+        StringBuilder sb = new StringBuilder();\r
+        Token token = jjtGetFirstToken();\r
+        sb.append(token.image);\r
+\r
+        while(token != null && !token.equals(jjtGetLastToken())) {\r
+            token = token.next;\r
+            sb.append(token.image);\r
+        }\r
+\r
+        return sb.toString();\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNodeFactory.java
new file mode 100644 (file)
index 0000000..434b982
--- /dev/null
@@ -0,0 +1,86 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.nodes.AddOp;\r
+import org.simantics.sysdyn.unitParser.nodes.Arithmetic;\r
+import org.simantics.sysdyn.unitParser.nodes.ComponentIdentity;\r
+import org.simantics.sysdyn.unitParser.nodes.ComponentReference;\r
+import org.simantics.sysdyn.unitParser.nodes.ComponentReferenceFull;\r
+import org.simantics.sysdyn.unitParser.nodes.Condition;\r
+import org.simantics.sysdyn.unitParser.nodes.Divide;\r
+import org.simantics.sysdyn.unitParser.nodes.ForIndex;\r
+import org.simantics.sysdyn.unitParser.nodes.IfThenElse;\r
+import org.simantics.sysdyn.unitParser.nodes.Multiplication;\r
+import org.simantics.sysdyn.unitParser.nodes.RelOp;\r
+import org.simantics.sysdyn.unitParser.nodes.Relation;\r
+import org.simantics.sysdyn.unitParser.nodes.Term;\r
+import org.simantics.sysdyn.unitParser.nodes.Value;\r
+\r
+public class UnitCheckingNodeFactory {\r
+    \r
+    private static HashMap<String, Class<?>> constructors = new HashMap<String, Class<?>>();\r
+    \r
+    static {\r
+        constructors.put("relation", Relation.class);\r
+        constructors.put("term", Term.class);\r
+        constructors.put("arithmetic_expression", Arithmetic.class);\r
+        constructors.put("ifthenelse", IfThenElse.class);\r
+        \r
+        constructors.put("component_reference_full", ComponentReferenceFull.class);\r
+        constructors.put("value", Value.class);\r
+\r
+\r
+        constructors.put("divide", Divide.class);\r
+        constructors.put("multiplication", Multiplication.class);\r
+        constructors.put("add_op", AddOp.class);\r
+        constructors.put("rel_op", RelOp.class);\r
+\r
+        \r
+        \r
+        constructors.put("component_reference", ComponentReference.class);\r
+        constructors.put("component_identity", ComponentIdentity.class);\r
+        constructors.put("condition", Condition.class);\r
+        constructors.put("for_index", ForIndex.class);\r
+        \r
+    }\r
+    \r
+    private static Class<?> getConstructor(int id) {\r
+        String name = UnitParserTreeConstants.jjtNodeName[id];\r
+        Class<?> constructor = constructors.get(name);\r
+        if(constructor == null)\r
+            return UnitCheckingNode.class;\r
+        else\r
+            return constructor;\r
+    }\r
+    \r
+    public static Node jjtCreate(int id) {\r
+        try {\r
+            return (Node) getConstructor(id).getConstructors()[0].newInstance(id);\r
+        } catch (IllegalArgumentException e) {\r
+            e.printStackTrace();\r
+        } catch (SecurityException e) {\r
+            e.printStackTrace();\r
+        } catch (InstantiationException e) {\r
+            e.printStackTrace();\r
+        } catch (IllegalAccessException e) {\r
+            e.printStackTrace();\r
+        } catch (InvocationTargetException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt
new file mode 100644 (file)
index 0000000..e7f8793
--- /dev/null
@@ -0,0 +1,275 @@
+options {\r
+  JDK_VERSION = "1.6";\r
+  STATIC = false;\r
+  TRACK_TOKENS=true;\r
+  NODE_CLASS="UnitCheckingNode";\r
+  NODE_FACTORY="UnitCheckingNodeFactory";\r
+}\r
+\r
+PARSER_BEGIN(UnitParser)\r
+package org.simantics.sysdyn.unitParser;\r
+\r
+public class UnitParser {\r
+\r
+  \r
+    \r
+}\r
+PARSER_END(UnitParser)\r
+\r
+/*** Lexer *********************************************************/\r
+\r
+SKIP:\r
+{ <WHITESPACE: " " | "\n" | "\r" | "\t" > \r
+| <COMMENT1: "/*" (~["*"] | "*" ~["/"])* "*/" >  \r
+| <COMMENT2: "//" (~["\n"])* >\r
+}\r
+\r
+TOKEN:\r
+{\r
+"algorithm"    | "discrete"    | "false"       | "model"       | "redeclare"\r
+| "and"                | "each"                | "final"       | "not"         | "replaceable"\r
+| "annotation" | "else"                | "flow"        | "operator" | "return"\r
+|"assert"              | "elseif"              | "for"         | "or"          | "stream"\r
+| "block"              | "elsewhen"    | "function" | "outer"  | "then"\r
+| "break"              | "encapsulated" | "if"         | "output"      | "true"\r
+| "class"              | "end"                 | "import"      | "package" | "type"\r
+| "connect"    | "enumeration" | "in"          | "parameter" | "when"\r
+| "connector"  | "equation"    | /*"initial" |*/ "partial" | "while"\r
+| "constant"   | "expandable"  | "inner"       | "protected" | "within"\r
+| "constrainedby" | "extends"  | "input"       | "public"\r
+| /*"der"              |*/ "external"  | "loop"        | "record"\r
+| "(" | ")" | "{" | "}" | "[" | "]" | "." | ":" | ";" | ","\r
+| "<" | "<=" | ">" | ">=" | "==" | "<>"\r
+| "+" | "-" | ".+" | ".-"\r
+| "*" | "/" | ".*" | "./"\r
+| "^" | ".^"\r
+| "=" | ":=" \r
+| <IDENT: ["a"-"z","A"-"Z","_"] (["a"-"z","A"-"Z","_","0"-"9"])* >\r
+| <STRING: "\"" (~["\"", "\\", "\n"] | "\\" ~["\n"])* "\"">\r
+    { matchedToken.image = matchedToken.image.substring(1,matchedToken.image.length()-1); }\r
+| <UNSIGNED_INTEGER: (["0"-"9"])+ >\r
+| <UNSIGNED_NUMBER:  \r
+    ( <UNSIGNED_INTEGER> "." (<UNSIGNED_INTEGER>)? (["e","E"] <UNSIGNED_INTEGER>)?\r
+    | "." <UNSIGNED_INTEGER> (["e","E"] <UNSIGNED_INTEGER>)?\r
+    | <UNSIGNED_INTEGER> ["e","E"] <UNSIGNED_INTEGER>\r
+    ) >\r
+}\r
+\r
+/*** Parser ********************************************************/\r
+\r
+// https://javacc.dev.java.net/doc/javaccgrm.html\r
+// add_op -> add_op()\r
+// [ add_op ] -> ( add_op() )?\r
+// { add_op term } -> ( add_op() term() )*\r
+\r
+SimpleNode expr() : {\r
+} {\r
+       (simple_expression())? <EOF>\r
+       {\r
+       return jjtThis;\r
+    }\r
+       |\r
+       ifthenelse() <EOF>\r
+       {\r
+       return jjtThis;\r
+    }\r
+}\r
+\r
+void expression() : {\r
+} {\r
+       simple_expression()\r
+       | ifthenelse()\r
+}\r
+\r
+void ifthenelse() : {\r} {\r
+  "if" condition() "then" expression() ( "elseif" condition() "then" expression() )* "else" expression()\r
+}\r
+\r\r
+void condition() : {\r
+} {\r
+  expression()\r
+}\r  \r  \r
+\r
+void simple_expression() : {\r
+} {\r
+       logical_expression() ( ":" logical_expression() ( ":" logical_expression() )? )?\r
+}      \r
+\r
+void logical_expression() : {\r
+} {\r
+       logical_term() ( "or" logical_term() )*\r
+}      \r
+\r
+void logical_term() : {\r
+} {\r
+       logical_factor() ( "and" logical_factor() )*\r
+}\r
+\r
+void logical_factor() : {\r
+} {\r
+       ( "not" )? relation()\r
+}\r
+\r
+void relation() : {\r
+} {\r
+       arithmetic_expression() ( rel_op() arithmetic_expression() )?\r
+}\r
+\r
+void rel_op() : {\r
+} {\r
+       "<" | "<=" | ">" | ">=" | "==" | "<>"\r
+}\r
+\r
+void arithmetic_expression() : {\r
+} {\r
+    (add_op())? term() (add_op() term())*\r
+}\r
+\r
+void add_op() : {\r
+} {\r
+    "+" | "-" | ".+" | ".-"\r
+}\r
+\r
+void term() : {\r
+} {\r
+    factor() ( (multiplication() | divide()) factor() )*\r
+}\r
+\r
+void factor() : {\r
+} {\r
+       primary() ( "^" primary() | ".^" primary() )?\r
+}\r
+\r
+void multiplication() : {\r
+} {\r
+    "*" | ".*"\r
+}\r
+\r
+void divide() : {\r
+} {\r
+    "/" | "./"\r
+}\r
+\r
+void primary() : {\r
+} {\r
+  value()\r
+  | LOOKAHEAD( name() parenthesis_open() ) function_call()   \r
+  | component_reference_full()\r
+  /*| "(" output_expression_list() ")"*/ // Not needed, replaced with following:\r
+  | parenthesis_expression()\r
+  | "[" expression_list() ( ";" expression_list() )* "]"\r
+  | "{" function_arguments() "}"\r
+  | "end"\r
+}\r
+\r
+void component_reference_full() : {\r
+} {\r
+    component_reference()\r
+}\r
+\r
+void function_call() : {\r
+} {\r
+    name() function_call_args()\r
+}\r
+\r
+void parenthesis_expression() : {\r} {\r    parenthesis_open() expression() parenthesis_close()\r
+}\r
+\r
+void value() : {\r} {\r
+       <UNSIGNED_NUMBER>\r
+  | <UNSIGNED_INTEGER>\r
+  | <STRING>\r
+  | "false"\r
+  | "true"\r
+}\r  \r
+\r
+void parenthesis_open() : {\r
+} {\r
+    "("\r
+}\r
+\r
+void parenthesis_close() : {\r
+} {\r
+   ")"\r
+}\r
+\r
+void name() : {\r
+} {\r
+       <IDENT> ( "." name() )?\r
+}\r
+\r
+void component_reference() : {\r
+} {\r
+       //IDENT [ array_subscripts ] [ "." component_reference ]\r
+       component_identity() ( array_subscripts() )? ( "." component_reference() )?\r
+}\r
+\r
+void component_identity() : {\r
+} {\r  <IDENT>\r
+}\r  \r
+\r
+void function_call_args() : {\r
+} {\r
+       parenthesis_open() ( function_arguments() )? parenthesis_close()\r
+}\r
+\r
+void function_arguments() : {\r
+} {\r
+       //expression [ "," function_arguments | for for_indices ]\r
+       //| named_arguments\r
+       LOOKAHEAD(2) named_argument()  ( "," function_arguments() )?\r
+       | expression() ( "," function_arguments() | "for" for_indices() )?\r
+       \r
+}\r
+\r
+void for_indices() : {\r
+} {\r
+       //for_index {"," for_index}\r
+       for_index() ("," for_index())*\r
+}\r
+\r
+void for_index() : {\r
+} {\r
+       //IDENT [ in expression ]\r
+       <IDENT> ( "in" expression() )?\r
+}\r
+\r
+/* Removed by Teemu. Refactored in function_arguments)\r
+void named_arguments() : {\r
+} {\r
+       named_argument() ( "," named_arguments() )?\r
+}\r
+*/\r
+\r
+void named_argument() : {\r
+} {    \r
+       <IDENT> "=" expression()\r
+}\r
+\r
+void output_expression_list() : {\r
+} {\r
+       ( expression() )? ( "," ( expression() )? )*\r
+}\r
+\r
+\r
+void expression_list() : {\r
+} {\r
+    expression() ( "," expression() )*\r
+}\r
+\r
+void array_subscripts() : {\r
+} {\r
+       "[" subscript() ( "," subscript() )* "]"\r
+}\r
+\r
+void subscript() : {\r
+} {\r   ":"\r
+       |   LOOKAHEAD( name() parenthesis_open() ) name() function_call_args()\r
+       | rangeIndex() ( ":" rangeIndex())?\r
+}\r
+\r
+void rangeIndex() : {\r
+} {\r   <UNSIGNED_INTEGER>\r
+               | <IDENT>\r
+}\r  \r
+\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java
new file mode 100644 (file)
index 0000000..9c3374c
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AddOp extends UnitCheckingNode {\r
+\r
+    public AddOp(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = super.getUnits(units);\r
+        result.setUnitType(UnitType.OPERATOR);\r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java
new file mode 100644 (file)
index 0000000..a24ef52
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Arithmetic extends UnitCheckingNode {\r
+\r
+    public Arithmetic(int id) {\r
+        super(id);\r
+    }\r
+\r
+\r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = new UnitResult();\r
+\r
+        UnitCheckingNode base = null;\r
+        UnitCheckingNode operator = null;\r
+        UnitCheckingNode candidateNode = null;\r
+\r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            candidateNode = ((UnitCheckingNode)jjtGetChild(i));\r
+            UnitResult candidateUnits = candidateNode.getUnits(units);\r
+            if(candidateUnits.getUnitType() == UnitType.OPERATOR || candidateUnits.getUnitType() == UnitType.ANY) {\r
+                result.setUnitType(candidateUnits.getUnitType());\r
+                continue;\r
+            } else if(base == null) {\r
+                base = ((UnitCheckingNode)jjtGetChild(i));\r
+                result.appendResult(base.getUnits(units));\r
+                continue;\r
+            } else {\r
+                operator = ((UnitCheckingNode)jjtGetChild(i-1));\r
+                if(!result.equals(candidateUnits)) {\r
+                    throw new UnitCheckingException("Not equals exception: " +\r
+                            base.printNode() + " [" + result.getCleanFullUnit() + "] " + operator.printNode() + " " +\r
+                            candidateNode.printNode() + " [" + candidateUnits.getCleanFullUnit() + "]"\r
+                            );\r
+                }\r
+            }\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentIdentity.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentIdentity.java
new file mode 100644 (file)
index 0000000..c32b47f
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ComponentIdentity extends UnitCheckingNode {\r
+\r
+    public ComponentIdentity(int id) {\r
+        super(id);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReference.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReference.java
new file mode 100644 (file)
index 0000000..b9541bb
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ComponentReference extends UnitCheckingNode {\r
+\r
+    public ComponentReference(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public String printNode() {\r
+        StringBuilder sb = new StringBuilder();\r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            UnitCheckingNode node = (UnitCheckingNode) jjtGetChild(i);\r
+            if(node instanceof ComponentIdentity || node instanceof ComponentReference) {\r
+                if(sb.length() > 0)\r
+                    sb.append(".");\r
+                sb.append(node.printNode());\r
+            }\r
+        }\r
+        return sb.toString();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java
new file mode 100644 (file)
index 0000000..d771dc3
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.io.StringReader;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.ParseException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.UnitParser;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ComponentReferenceFull extends UnitCheckingNode {\r
+\r
+    public ComponentReferenceFull(int id) {\r
+        super(id);\r
+    }\r
+\r
+    protected UnitResult parseUnits(String units) {\r
+        StringReader sr = new StringReader(units);\r
+        UnitParser parser = new UnitParser(sr);\r
+        try {\r
+            UnitCheckingNode node = (UnitCheckingNode) parser.expr();\r
+            return node.getUnits(null);\r
+        } catch (ParseException e) {\r
+            e.printStackTrace();\r
+        } catch (UnitCheckingException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        String node = printNode();\r
+        node = printNode();\r
+        if(units != null) {\r
+            if(!units.containsKey(node))\r
+                throw new UnitCheckingException("No units defined for " + node);\r
+            else {\r
+                return parseUnits(units.get(node));\r
+            }\r
+        } else {\r
+            UnitResult result = new UnitResult();\r
+            result.addDivident(node);\r
+            result.append(node);\r
+            return result; \r
+        }\r
+    }\r
+\r
+    @Override\r
+    public String printNode() {\r
+        StringBuilder sb = new StringBuilder();\r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            UnitCheckingNode node = (UnitCheckingNode) jjtGetChild(i);\r
+            sb.append(node.printNode());\r
+        }\r
+        return sb.toString();\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Condition.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Condition.java
new file mode 100644 (file)
index 0000000..c382cda
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Condition extends UnitCheckingNode {\r
+\r
+    public Condition(int id) {\r
+        super(id);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java
new file mode 100644 (file)
index 0000000..4c2ec48
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Divide extends UnitCheckingNode {\r
+\r
+    public Divide(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = super.getUnits(units);\r
+        result.setUnitType(UnitType.OPERATOR);\r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java
new file mode 100644 (file)
index 0000000..0d934f1
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ForIndex extends UnitCheckingNode {\r
+\r
+    public ForIndex(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        return new UnitResult();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java
new file mode 100644 (file)
index 0000000..f5942e4
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class IfThenElse extends UnitCheckingNode {\r
+\r
+    public IfThenElse(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult base = null;\r
+        UnitCheckingNode baseNode = null;\r
+        UnitCheckingNode candidateNode = null;\r
+        \r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            candidateNode = ((UnitCheckingNode)jjtGetChild(i));\r
+            UnitResult candidateUnits = candidateNode.getUnits(units);\r
+            \r
+            if(!(candidateNode instanceof Condition)) {\r
+                \r
+                if(base == null) {\r
+                    base = candidateUnits;\r
+                    baseNode = candidateNode;\r
+                } else {\r
+                    if(!base.equals(candidateUnits)) {\r
+                        base.equals(candidateUnits);\r
+                        throw new UnitCheckingException("Conditional results do not have same units: \n" +\r
+                        printNode() + "\n" + \r
+                                baseNode.printNode() + " [" + base.getFullUnit() + "] <-> " +\r
+                                candidateNode.printNode() + " [" + candidateUnits.getFullUnit() + "]"\r
+                                );\r
+                    }\r
+                }\r
+            }\r
+\r
+\r
+        }\r
+        \r
+        return base;\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java
new file mode 100644 (file)
index 0000000..53cdc78
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Multiplication extends UnitCheckingNode {\r
+\r
+    public Multiplication(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = super.getUnits(units);\r
+        result.setUnitType(UnitType.OPERATOR);\r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java
new file mode 100644 (file)
index 0000000..57098ba
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class RelOp extends UnitCheckingNode {\r
+\r
+    public RelOp(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = super.getUnits(units);\r
+        result.setUnitType(UnitType.OPERATOR);\r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java
new file mode 100644 (file)
index 0000000..6d8711c
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Relation extends UnitCheckingNode {\r
+\r
+    public Relation(int id) {\r
+        super(id);\r
+    }\r
+\r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = new UnitResult();\r
+        \r
+        UnitCheckingNode base = null;\r
+        UnitCheckingNode operator = null;\r
+        UnitCheckingNode candidateNode = null;\r
+        \r
+        base = ((UnitCheckingNode)jjtGetChild(0));\r
+        if(!(base instanceof Arithmetic) && jjtGetNumChildren() > 1)\r
+            base = ((UnitCheckingNode)jjtGetChild(1));\r
+            \r
+        if(base instanceof Arithmetic) {\r
+            result.appendResult(base.getUnits(units));\r
+\r
+            for(int i = 2; i < jjtGetNumChildren(); i = i + 2) {\r
+                candidateNode = ((UnitCheckingNode)jjtGetChild(i));\r
+\r
+                if(!(candidateNode instanceof Value)) {\r
+                    operator = ((UnitCheckingNode)jjtGetChild(i-1));\r
+                    UnitResult candidateUnits = candidateNode.getUnits(units);\r
+                    if(!result.equals(candidateUnits)) {\r
+                        result.equals(candidateUnits);\r
+                        throw new UnitCheckingException("Not equals exception: " +\r
+                                base.printNode() + " [" + result.getFullUnit() + "] " + operator.printNode() + " " +\r
+                                candidateNode.printNode() + " [" + candidateUnits.getFullUnit() + "]"\r
+                                );\r
+                    }\r
+                }\r
+\r
+            }\r
+        }\r
+        \r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java
new file mode 100644 (file)
index 0000000..77408c0
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Term extends UnitCheckingNode {\r
+\r
+    public Term(int id) {\r
+        super(id);\r
+    }\r
+    \r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = new UnitResult();\r
+        \r
+        UnitCheckingNode current = null;\r
+        UnitCheckingNode operator = null;\r
+        UnitCheckingNode base = null;\r
+        \r
+        for(int i = 0; i < jjtGetNumChildren(); i++) {\r
+            current = ((UnitCheckingNode)jjtGetChild(i));\r
+            UnitResult currentUnits = current.getUnits(units);\r
+\r
+            if(currentUnits.getUnitType() == UnitType.OPERATOR) {\r
+                continue;\r
+            } else if(base == null) {\r
+                base = current;\r
+                result.appendResult(currentUnits);\r
+                continue;\r
+            } else {\r
+                operator = ((UnitCheckingNode)jjtGetChild(i-1));\r
+\r
+                if(operator instanceof Multiplication) {\r
+                    if(currentUnits.getUnitType() != UnitType.ANY) {\r
+                        result.append(operator.printNode());\r
+                        result.appendResult(currentUnits);\r
+                    }\r
+                } else if(operator instanceof Divide){\r
+                    result.append(operator.printNode());\r
+                    result.addAllDividers(currentUnits.getDividers());\r
+                    result.addAllDividers(currentUnits.getDividents());\r
+                    result.setUnitType(currentUnits.getUnitType());\r
+                    \r
+                    if(currentUnits.getUnitType() == UnitType.ANY)\r
+                        result.append("1");\r
+                    else\r
+                        result.append(currentUnits.getFullUnit());\r
+                }\r
+            }\r
+        }\r
+        \r
+        return result;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java
new file mode 100644 (file)
index 0000000..2785134
--- /dev/null
@@ -0,0 +1,193 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * Result of getUnits() request for Unit Parser nodes. \r
+ * \r
+ * Result is built of dividers and dividents. ( divident / divider )\r
+ * \r
+ * UnitType may provide information for handling this unit result\r
+ * \r
+ * fullUnit is the print of this unit in the order it is created.\r
+ * \r
+ * getCleanFullUnit reduces all unnecessary units and provides the most\r
+ * clean representation of the unit. ( e.g. m * s / m  -> s )\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class UnitResult {\r
+    \r
+    public enum UnitType {NORMAL, ANY, DMNL, OPERATOR};\r
+    \r
+    private ArrayList<String> dividers = new ArrayList<String>();\r
+    private ArrayList<String> dividents = new ArrayList<String>();\r
+    private StringBuilder fullUnit = new StringBuilder();\r
+    private UnitType unitType = UnitType.NORMAL;\r
+    \r
+    public void appendResult(UnitResult result) {\r
+        addAllDividents(result.getDividents());\r
+        addAllDividers(result.getDividers());\r
+        append(result.getFullUnit());\r
+        setUnitType(result.getUnitType());\r
+    }\r
+    \r
+    public void addDivider(String divider) {\r
+        this.dividers.add(divider);\r
+        Collections.sort(this.dividers);\r
+    }\r
+    \r
+    public void addAllDividers(ArrayList<String> dividers) {\r
+        this.dividers.addAll(dividers);\r
+        Collections.sort(this.dividers);\r
+    }\r
+    \r
+    public void addDivident(String divident) {\r
+        this.dividents.add(divident);\r
+        Collections.sort(this.dividents);\r
+    }\r
+    \r
+    public void addAllDividents(ArrayList<String> dividents) {\r
+        this.dividents.addAll(dividents);\r
+        Collections.sort(this.dividents);\r
+    }\r
+    \r
+    public void append(String text) {\r
+        this.fullUnit.append(text);\r
+    }\r
+    \r
+    public ArrayList<String> getDividers() {\r
+        return this.dividers;\r
+    }\r
+    \r
+    public ArrayList<String> getDividents() {\r
+        return this.dividents;\r
+    }\r
+    \r
+    public String getFullUnit() {\r
+        return fullUnit.toString();\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Get clean representation of this unit. All redundant \r
+     * units are cleanend out and the unit is represented\r
+     * with max one '/' character.\r
+     * @return\r
+     */\r
+    public String getCleanFullUnit() {\r
+        if(dividers.size() == 0 && dividents.size() == 0)\r
+            return "";\r
+        \r
+        if(dividers.size() > 0 && dividents.size() == 0)\r
+            dividents.add("1");\r
+        \r
+        ArrayList<String> copyDividers1 = new ArrayList<String>(dividers);\r
+        ArrayList<String> copyDividents1 = new ArrayList<String>(dividents);\r
+        reduceUnitLists(dividents, copyDividents1, copyDividers1);\r
+        \r
+        StringBuilder sb = new StringBuilder();\r
+        Iterator<String> iterator = copyDividents1.iterator();\r
+        while(iterator.hasNext()) {\r
+            String s = iterator.next();\r
+            sb.append(s);\r
+            if(iterator.hasNext())\r
+                sb.append("*");\r
+        }\r
+        \r
+        if(copyDividers1.size() > 0) {\r
+            sb.append("/");\r
+            if(copyDividers1.size() > 1)\r
+                sb.append("(");\r
+            \r
+            iterator = copyDividers1.iterator();\r
+            while(iterator.hasNext()) {\r
+                String s = iterator.next();\r
+                sb.append(s);\r
+                if(iterator.hasNext())\r
+                    sb.append("*");\r
+            }\r
+            \r
+            if(copyDividers1.size() > 1)\r
+                sb.append(")");\r
+        }\r
+        \r
+        return sb.toString();\r
+    }\r
+    \r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if(!(obj instanceof UnitResult))\r
+            return false;\r
+        \r
+        UnitResult other = (UnitResult)obj;\r
+        \r
+        if(getUnitType() == UnitType.ANY || other.getUnitType() == UnitType.ANY)\r
+            return true;\r
+        \r
+        ArrayList<String> copyDividers1 = new ArrayList<String>(dividers);\r
+        ArrayList<String> copyDividents1 = new ArrayList<String>(dividents);\r
+        reduceUnitLists(dividents, copyDividents1, copyDividers1);\r
+\r
+        ArrayList<String> copyDividers2 = new ArrayList<String>(other.dividers);\r
+        ArrayList<String> copyDividents2 = new ArrayList<String>(other.dividents);    \r
+        reduceUnitLists(other.dividents, copyDividents2, copyDividers2);\r
+\r
+        if(copyDividents1.size() != copyDividents2.size())\r
+            return false;\r
+        if(copyDividers1.size() != copyDividers2.size())\r
+            return false;\r
+        \r
+        for(int i = 0; i < copyDividents1.size(); i++) {\r
+            String a = copyDividents1.get(i);\r
+            String b = copyDividents2.get(i);\r
+            if(!a.equals(b)) {\r
+                return false;\r
+            }\r
+        }\r
+        \r
+        for(int i = 0; i < copyDividers1.size(); i++) {\r
+            String a = copyDividers1.get(i);\r
+            String b = copyDividers2.get(i);\r
+            if(!a.equals(b)) {\r
+                return false;\r
+            }\r
+        }\r
+        \r
+        return true;\r
+    }\r
+    \r
+    public void reduceUnitLists(ArrayList<String> originalDividents, ArrayList<String> copyDividents, ArrayList<String> copyDividers) {\r
+        for(String s : originalDividents) {\r
+            if(copyDividers.contains(s)) {\r
+                copyDividers.remove(s);\r
+                copyDividents.remove(s);\r
+            }\r
+        }\r
+        \r
+        if(copyDividents.isEmpty())\r
+            copyDividents.add("1");\r
+    }\r
+\r
+    public UnitType getUnitType() {\r
+        return unitType;\r
+    }\r
+\r
+    public void setUnitType(UnitType unitType) {\r
+        this.unitType = unitType;\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java
new file mode 100644 (file)
index 0000000..3da4c14
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.unitParser.nodes;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.unitParser.UnitCheckingException;\r
+import org.simantics.sysdyn.unitParser.UnitCheckingNode;\r
+import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType;\r
+\r
+/**\r
+ * See UnitCheckingNodeFactory for mapping\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class Value extends UnitCheckingNode {\r
+\r
+    public Value(int id) {\r
+        super(id);\r
+    }\r
+\r
+    @Override\r
+    public UnitResult getUnits(HashMap<String, String> units) throws UnitCheckingException {\r
+        UnitResult result = super.getUnits(units);\r
+        result.setUnitType(UnitType.ANY);\r
+        return result;\r
+    }\r
+}\r