]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Vensim import almost complete, needs cleanup
authorjkauttio <jkauttio@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 17 Apr 2014 11:47:45 +0000 (11:47 +0000)
committerjkauttio <jkauttio@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 17 Apr 2014 11:47:45 +0000 (11:47 +0000)
refs #2924

git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches@29300 ac1ea38d-2e2b-0410-8846-a27921b304fc

23 files changed:
dev-jkauttio/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/imports/ImportMdlHandler.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java [new file with mode: 0644]
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java [new file with mode: 0644]
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java [new file with mode: 0644]
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/LookupVariable.java [deleted file]
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlModel.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Sketch.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchComment.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchConnection.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchElement.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchObject.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchValve.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Subscript.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Variable.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/EnumerationExpression.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/LookupExpression.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Enumeration.java
dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java [new file with mode: 0644]

index 9aa51437a3c4f83935064367197ba3374ebd3917..ae11a1fadde44179eca15b0c82cbfeb79c1b0315 100644 (file)
@@ -66,7 +66,14 @@ public class ImportMdlHandler extends AbstractHandler {
                Activator.getDefault().getPreferenceStore().setValue(IMPORTMDLTPATH, (new File(selected)).getParent());\r
                \r
                // Convert Vensim model to Simantics SysDyn format using MdlParser\r
-               final Model model = MdlParser.parse(file);\r
+               final Model model;\r
+               try {\r
+               model = MdlParser.parse(file);\r
+               }\r
+               catch (Exception e) {\r
+                       e.printStackTrace();\r
+                       return null;\r
+               }\r
                \r
                SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
                        \r
index a26110b6a86cc8ae745085687fa19e93585efd5e..2d51eeef219d0a0fbcf3b749d932242d4c7afb3b 100644 (file)
@@ -18,9 +18,11 @@ import java.io.IOException;
 import java.io.InputStreamReader;\r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
 \r
-import org.simantics.sysdyn.modelImport.MdlUtil.CommentIcon;\r
-import org.simantics.sysdyn.modelImport.mdl.LookupVariable;\r
+import org.simantics.sysdyn.modelImport.mdl.Declaration;\r
+import org.simantics.sysdyn.modelImport.mdl.Lookup;\r
 import org.simantics.sysdyn.modelImport.mdl.MdlModel;\r
 import org.simantics.sysdyn.modelImport.mdl.Sketch;\r
 import org.simantics.sysdyn.modelImport.mdl.SketchComment;\r
@@ -59,21 +61,24 @@ public class MdlParser {
                        return null;\r
                }\r
                \r
+               System.err.println("model parsed");\r
+               \r
                // generate a sysdyn model from the mdl model\r
                \r
                Model model = new Model(mdl.getName());\r
 \r
                double offset = 0;\r
-               \r
-               // add anumerations\r
+\r
                for (Subscript subscript : mdl.getAllSubscripts()) {\r
-                       if (subscript.isSuperSet()) {\r
-                               Enumeration enumeration = new Enumeration(subscript.getName(), subscript.getValues());\r
-                               subscript.setEnumeration(enumeration);\r
-                               model.addEnumeration(enumeration);\r
-                       }\r
+                       System.err.println("added subscript "+subscript.getName()+" "+subscript.isEquivalent());\r
+                       model.addEnumeration(subscript.getEnumeration(mdl));\r
                }\r
                \r
+               for (Lookup lookup : mdl.getAllLookups()) {\r
+                       //model.addFunction(lookup.getFunction());\r
+               }\r
+               \r
+               try {\r
                // add sketch labels and independent elements\r
                for (Sketch sketch : mdl.getSketches()) {\r
                        \r
@@ -81,26 +86,49 @@ public class MdlParser {
 \r
                        //model.addSymbol(new Comment(0, offset, -1, -1, sketch.getName()));\r
                        \r
-                       for (SketchElement element : sketch.getIndependentElements()) {\r
-                               Symbol symbol = element.getSymbol(mdl, sketch);\r
-                               element.setModelObject(symbol);\r
-                               model.addSymbol(symbol);\r
+                       for (SketchComment comment : sketch.getComments()) {\r
+                               Symbol symbol = comment.getSymbol(mdl, sketch);\r
+                               if (symbol != null) {\r
+                                       comment.setModelObject(symbol);\r
+                                       model.addSymbol(symbol);\r
+                               }\r
+                       }\r
+                       \r
+                       for (SketchValve valve : sketch.getValves()) {\r
+                               Valve symbol = valve.getSymbol(mdl, sketch);\r
+                               if (symbol != null) {\r
+                                       valve.setModelObject(symbol);\r
+                                       model.addSymbol(symbol);\r
+                               }\r
+                       }\r
+                       \r
+                       for (SketchVariable variable : sketch.getNonShadowVariables()) {\r
+                               ModelVariable symbol = variable.getSymbol(mdl, sketch);\r
+                               if (symbol != null) {\r
+                                       variable.setModelObject(symbol);\r
+                                       model.addSymbol(symbol);\r
+                               }\r
                        }\r
                        \r
                        offset += 200;\r
                }\r
                \r
+               }\r
+               catch (NullPointerException e) {\r
+                       e.printStackTrace();\r
+               }\r
+               \r
                // add dependent elements\r
                for (Sketch sketch : mdl.getSketches()) {\r
                        for (SketchVariable variable : sketch.getShadowVariables()) {\r
-                               if (variable.getVariable() == null) {\r
-                                       continue;\r
-                               }\r
-                               ModelVariable original = model.getVariable(variable.getVariable().getName());\r
-                               System.err.println("original variable "+original);\r
+                               ModelVariable original = model.getVariable(variable.getName());\r
+                               if (original == null)\r
+                                       System.err.println("original variable not found for "+variable.getName());\r
                                Symbol symbol = original != null ? new Shadow(variable.getDimensions(sketch), original) : variable.getSymbol(mdl, sketch);\r
-                               variable.setModelObject(symbol);\r
-                               model.addSymbol(symbol);\r
+                               if (symbol != null) {\r
+                                       variable.setModelObject(symbol);\r
+                                       model.addSymbol(symbol);\r
+                               }\r
                        }\r
 \r
                        for (SketchConnection connection : sketch.getConnections()) {\r
@@ -113,6 +141,8 @@ public class MdlParser {
                }\r
                \r
                // Set simulation parameters\r
+               \r
+               System.err.println("DONE");\r
 \r
                return model;\r
        }\r
@@ -121,10 +151,15 @@ public class MdlParser {
        private static final String SKETCH_VERSION = "V300";\r
        private static final String SKETCH_START = "\\\\\\---///";\r
        private static final String SKETCH_END = "///---\\\\\\";\r
-\r
+       \r
        private static MdlModel parseFile(File file) \r
                        throws Exception {\r
-               String name = file.getName().substring(0, file.getName().length()-4);\r
+               \r
+               // strip the file suffix from file name\r
+               String name = file.getName();\r
+               if (file.getName().contains(".")) {\r
+                       name = name.substring(0, name.indexOf('.'));\r
+               }\r
                \r
                MdlModel mdl = new MdlModel(name);\r
                \r
@@ -167,29 +202,26 @@ public class MdlParser {
                        } while ((line = reader.readLine()) != null);\r
                        String str = buffer.toString();\r
 \r
-                       ArrayList<Variable> variables = new ArrayList<Variable>();\r
-                       \r
                        String cat;\r
                        Variable var;\r
-                       SubscriptVariable svar;\r
-                       LookupVariable lvar;\r
-                       Subscript subs;\r
-\r
+                       Lookup lookup;\r
+                       Subscript subscript;\r
+                       \r
                        // parse the (possible) variable declaration\r
-                       if ((cat = MdlUtil.getPossibleCategory(str)) != null) {\r
+                       if ((cat = Declaration.parseCategory(str)) != null) {\r
                                category = cat;\r
                        }\r
-                       else if ((var = Variable.getPossibleVariable(str)) != null) {\r
+                       else if ((var = Variable.getPossible(str)) != null) {\r
                                mdl.addVariable(var, category);\r
                        }\r
-                       else if ((svar = SubscriptVariable.getPossibleSubscriptVariable(str)) != null) {\r
-                               mdl.addVariable(svar, category);\r
+                       else if ((var = SubscriptVariable.getPossible(str)) != null) {\r
+                               mdl.addSubscriptVariable((SubscriptVariable)var, category);\r
                        }\r
-                       else if ((lvar = LookupVariable.getPossibleLookUpVariable(str)) != null) {\r
-                               mdl.addVariable(lvar, category);\r
+                       else if ((lookup = Lookup.getPossible(str)) != null) {\r
+                               mdl.addLookup(lookup);\r
                        }\r
-                       else if ((subs = Subscript.getPossibleSubscript(str, mdl)) != null) {\r
-                               mdl.addSubscript(subs);\r
+                       else if ((subscript = Subscript.getPossible(str)) != null) {\r
+                               mdl.addSubscript(subscript);\r
                        }\r
                        else {\r
                                // if we got this far, the variable could not be parsed\r
@@ -214,8 +246,6 @@ public class MdlParser {
                        if (line.isEmpty())\r
                                continue;\r
                        \r
-                       ArrayList<SketchConnection> connections = new ArrayList<SketchConnection>();\r
-\r
                        SketchObject so;\r
 \r
                        if (line.startsWith(SKETCH_START)) {\r
@@ -231,23 +261,23 @@ public class MdlParser {
                        else if (line.startsWith("$")) {\r
                                // font declaration, nothing to do here\r
                        }\r
-                       else if ((so = MdlUtil.getPossibleSketchConnection(line, sketch)) != null) {\r
+                       else if ((so = SketchConnection.getPossible(line)) != null) {\r
                                sketch.addConnection((SketchConnection)so);\r
                        }\r
-                       else if ((so = MdlUtil.getPossibleSketchVariable(line, mdl)) != null) {\r
+                       else if ((so = SketchVariable.getPossible(line)) != null) {\r
                                sketch.addVariable((SketchVariable)so);\r
                        }\r
-                       else if ((so = MdlUtil.getPossibleSketchValve(line)) != null) {\r
+                       else if ((so = SketchValve.getPossible(line)) != null) {\r
                                SketchValve valve = (SketchValve)so;\r
                                // the next row after a valve should always the variable associated with the valve\r
-                               SketchVariable attached = MdlUtil.getPossibleSketchVariable(reader.readLine(), mdl);\r
+                               SketchVariable attached = SketchVariable.getPossible(reader.readLine());\r
                                if (attached == null || !attached.isAttached()) {\r
                                        throw new Exception("attached variable not found for valve");\r
                                }\r
-                               valve.setAttachedVariable(attached);\r
+                               valve.setAttached(attached);\r
                                sketch.addValve(valve);\r
                        }\r
-                       else if ((so = MdlUtil.getPossibleSketchComment(line)) != null) {\r
+                       else if ((so = SketchComment.getPossible(line)) != null) {\r
                                SketchComment comment = (SketchComment)so;\r
                                if (comment.hasTextLine()) {\r
                                        comment.setText(reader.readLine());\r
index 7b547672f5248af6a8b91f13962aca56a1d42424..cdf019de1ed0f5a3a4a3be13ec61fc190c7b1656 100644 (file)
 package org.simantics.sysdyn.modelImport;\r
 \r
 import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.HashSet;\r
+import java.util.List;\r
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
-import org.simantics.sysdyn.modelImport.mdl.LookupVariable;\r
 import org.simantics.sysdyn.modelImport.mdl.MdlModel;\r
-import org.simantics.sysdyn.modelImport.mdl.Sketch;\r
-import org.simantics.sysdyn.modelImport.mdl.SketchComment;\r
-import org.simantics.sysdyn.modelImport.mdl.SketchConnection;\r
-import org.simantics.sysdyn.modelImport.mdl.SketchElement;\r
-import org.simantics.sysdyn.modelImport.mdl.SketchValve;\r
-import org.simantics.sysdyn.modelImport.mdl.SketchVariable;\r
-import org.simantics.sysdyn.modelImport.mdl.Subscript;\r
-import org.simantics.sysdyn.modelImport.mdl.SubscriptVariable;\r
-import org.simantics.sysdyn.modelImport.mdl.Variable;\r
-import org.simantics.sysdyn.modelImport.model.element.Auxiliary;\r
-import org.simantics.sysdyn.modelImport.model.element.Cloud;\r
-import org.simantics.sysdyn.modelImport.model.element.Comment;\r
-import org.simantics.sysdyn.modelImport.model.element.Connection;\r
-import org.simantics.sysdyn.modelImport.model.element.Dependency;\r
-import org.simantics.sysdyn.modelImport.model.element.Flow;\r
-import org.simantics.sysdyn.modelImport.model.element.ModelVariable;\r
-import org.simantics.sysdyn.modelImport.model.element.Stock;\r
-import org.simantics.sysdyn.modelImport.model.element.Symbol;\r
-import org.simantics.sysdyn.modelImport.model.element.Valve;\r
-import org.simantics.sysdyn.modelImport.model.element.Valve.Orientation;\r
-import org.simantics.sysdyn.modelImport.model.element.Valve.TextPosition;\r
-import org.simantics.sysdyn.modelImport.model.expression.DelayExpression;\r
-import org.simantics.sysdyn.modelImport.model.expression.Expression;\r
-import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression;\r
-import org.simantics.sysdyn.modelImport.model.expression.LookupExpression;\r
-import org.simantics.sysdyn.modelImport.model.expression.NormalExpression;\r
-import org.simantics.sysdyn.modelImport.model.expression.EnumerationExpression;\r
-import org.simantics.sysdyn.modelImport.model.support.Enumeration;\r
-import org.simantics.sysdyn.modelImport.model.support.Range;\r
 \r
 public class MdlUtil {\r
        \r
-       public enum ConnectionType {\r
-               ARROW, LINE_ARROW, LINE_SEGMENT, OTHER\r
-       }\r
-       \r
-       public enum CommentIcon {\r
-               CLOUD, OTHER\r
-       }\r
-       \r
-       private static final String NUMBER = \r
-                       "-?\\d+(?:\\.\\d+)?";\r
-\r
-       // most of this data is from the documentation of the .mdl file format \r
+       // most of this is based on the documentation of the .mdl file format \r
        // available in http://www.vensim.com/documentation/24305.htm\r
-\r
-       // a Vensim variable name is either a plain string that contains letters, \r
-       // numbers and whitespace, or a quoted string that can also contain any \r
-       // special characters (including other quotation marks that must be escaped)\r
-       private static final String VAR_NAME_QUOTED =\r
-                       "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"";\r
-       private static final String VAR_NAME_SIMPLE =\r
-                       "[A-Za-z](?![ \\w]*\\()(?: *\\w+)*";\r
-       private static final String VAR_NAME_NORMAL =\r
-                       "("+VAR_NAME_QUOTED+"|"+VAR_NAME_SIMPLE+")";\r
-       \r
-       // a subscript variable is a variable that has a different equation\r
-       // depending on the value of the subscript it references\r
-       private static final String VAR_NAME_SUBSCRIPT =\r
-                       "("+VAR_NAME_SIMPLE+")\\[("+VAR_NAME_SIMPLE+"(?:,"+VAR_NAME_SIMPLE+")*)\\]";\r
-       \r
-       // a lookup variable contains a set of points\r
-       private static final String LOOKUP_NAME =\r
-                       "([A-Za-z](?: *\\w+)*)";\r
-       private static final String LOOKUP_RANGE =\r
-                       "\\[\\(("+NUMBER+"),("+NUMBER+")\\)-\\(("+NUMBER+"),("+NUMBER+")\\)\\]";\r
-       private static final String LOOKUP_POINTS =\r
-                       "(\\("+NUMBER+","+NUMBER+"\\)(?:,\\("+NUMBER+","+NUMBER+"\\))*)";\r
-       \r
-       private static final String NORMAL_NAME_PATTERN =\r
-                       VAR_NAME_NORMAL+"\\s*=\\s*";\r
-       public static final String NO_EXPRESSION_NAME_PATTERN = \r
-                       VAR_NAME_NORMAL+"\\s*~\\s*";\r
-       private static final String SUBSCRIPT_NAME_PATTERN =\r
-                       VAR_NAME_SUBSCRIPT+"\\s*=\\s*";\r
-       private static final String LOOKUP_NAME_PATTERN =\r
-                       LOOKUP_NAME+"\\s*\\(\\s*"+LOOKUP_RANGE+","+LOOKUP_POINTS+"\\s*\\)\\s*~\\s*";\r
-       \r
-       private static final String EXPRESSION_PATTERN =\r
-                       "([^~]*?(?:"+VAR_NAME_QUOTED+"[^~]*?)*)\\s*~\\s*";\r
-       \r
-       private static final String UNIT_PATTERN =\r
-                       "([^~]*?)\\s*~\\s*";\r
-       private static final String DESC_PATTERN =\r
-                       "([^\\|]*?)\\s*\\|";\r
-       \r
-       public static final String normalVariablePattern = \r
-                       NORMAL_NAME_PATTERN   +EXPRESSION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
-       public static final String noExpressionVariablePattern = \r
-                       NO_EXPRESSION_NAME_PATTERN               +UNIT_PATTERN+DESC_PATTERN;\r
-       public static final String subscriptVariablePattern = \r
-                       SUBSCRIPT_NAME_PATTERN+EXPRESSION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
-       public static final String lookupVariablePattern = \r
-                       LOOKUP_NAME_PATTERN                      +UNIT_PATTERN+DESC_PATTERN;\r
-       \r
-       private static final int normalVariableName = 1;\r
-       private static final int normalVariableExpression = 2;\r
-       private static final int normalVariableUnit = 3;\r
-       private static final int normalVariableDesc = 4;\r
-       \r
-       private static final int noExpressionVariableName = 1;\r
-       private static final int noExpressionVariableUnit = 2;\r
-       private static final int noExpressionVariableDesc = 3;\r
-       \r
-       private static final int subscriptVariableName = 1;\r
-       private static final int subscriptVariableIndices = 2;\r
-       private static final int subscriptVariableExpression = 3;\r
-       private static final int subscriptVariableUnit = 4;\r
-       private static final int subscriptVariableDesc = 5;\r
-       \r
-       private static final int lookupVariableName = 1;\r
-       private static final int lookupVariableRangeXMin = 2;\r
-       private static final int lookupVariableRangeYMin = 3;\r
-       private static final int lookupVariableRangeXMax = 4;\r
-       private static final int lookupVariableRangeYMax = 5;\r
-       private static final int lookupVariablePoints = 6;\r
-       private static final int lookupVariableUnit = 7;\r
-       private static final int lookupVariableDesc = 8;\r
-       \r
-       public static Variable getPossibleNormalVariable(String line) {\r
-               Matcher matcher = Pattern.compile(normalVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = matcher.group(normalVariableName);\r
-               String expression = matcher.group(normalVariableExpression);\r
-               String unit = matcher.group(normalVariableUnit);\r
-               String desc = matcher.group(normalVariableDesc);\r
-               \r
-               return new Variable(name, expression, unit, desc);\r
-       }\r
-       \r
-       public static Variable getPossibleNoExpressionVariable(String line) {\r
-               Matcher matcher = Pattern.compile(noExpressionVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = matcher.group(noExpressionVariableName);\r
-               String unit = matcher.group(noExpressionVariableUnit);\r
-               String desc = matcher.group(noExpressionVariableDesc);\r
-               \r
-               return new Variable(name, null, unit, desc);\r
-       }\r
-       \r
-       public static SubscriptVariable getPossibleSubscriptVariable(String line) {\r
-               Matcher matcher = Pattern.compile(subscriptVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = matcher.group(subscriptVariableName);\r
-               String[] subscript = matcher.group(subscriptVariableIndices).split(",");\r
-               String expression = matcher.group(subscriptVariableExpression);\r
-               String unit = matcher.group(subscriptVariableUnit);\r
-               String desc = matcher.group(subscriptVariableDesc);\r
-               \r
-               return new SubscriptVariable(name, expression, unit, desc, subscript);\r
-       }\r
-       \r
-       public static LookupVariable getPossibleLookUpVariable(String line) {\r
-               Matcher matcher = Pattern.compile(lookupVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = matcher.group(lookupVariableName);\r
-               double xMin = Double.parseDouble(matcher.group(lookupVariableRangeXMin));\r
-               double yMin = Double.parseDouble(matcher.group(lookupVariableRangeYMin));\r
-               double xMax = Double.parseDouble(matcher.group(lookupVariableRangeXMax));\r
-               double yMax = Double.parseDouble(matcher.group(lookupVariableRangeYMax));\r
-               String expression = matcher.group(lookupVariablePoints);\r
-               String unit = matcher.group(lookupVariableUnit);\r
-               String desc = matcher.group(lookupVariableDesc);\r
-               \r
-               return new LookupVariable(name, expression, unit, desc, xMin, yMin, xMax, yMax);\r
-       }\r
-\r
-       private static final String SUBSCRIPT_PATTERN =\r
-                       "("+VAR_NAME_SIMPLE+")\\s*(:|<->)\\s*";\r
-       \r
-       public static final String subscriptPattern = \r
-                       SUBSCRIPT_PATTERN+EXPRESSION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
-       \r
-       private static final int subscriptName = 1;\r
-       private static final int subscriptType = 2;\r
-       private static final int subscriptExpression = 3;\r
-       \r
-       public static Subscript getPossibleSubscript(String line, MdlModel mdl) {\r
-               Matcher matcher = Pattern.compile(subscriptPattern).matcher(line);              \r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = matcher.group(subscriptName);\r
-               boolean equivalent = matcher.group(subscriptType).equals("<->");\r
-               String expression = matcher.group(subscriptExpression);\r
-               \r
-               if (equivalent) {\r
-                       Subscript parent = mdl.getSubscript(expression);\r
-                       if (parent == null) {\r
-                               System.err.println("equivalent subscript not found for "+name);\r
-                               return null;\r
-                       }\r
-                       return new Subscript(name, parent.getValues());\r
-               }\r
-               else {\r
-                       return new Subscript(name, new HashSet<String>(Arrays.asList(expression.split(","))));\r
-               }\r
-       }\r
-       \r
-       public static String getPossibleCategory(String line) {\r
-               Matcher matcher = Pattern.compile("\\*{56}\\s*\\.(\\S+)\\s*\\*{56}.*").matcher(line);           \r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               return matcher.group(1);\r
-       }\r
        \r
-       // sketch object data is defined similarly\r
-       \r
-       private static final String SAVE = "(-?\\d+),";\r
-       private static final String SKIP = "-?\\d+,";\r
-       private static final String POINTS = "(\\d+\\|(?:\\(-?\\d+,-?\\d+\\)\\|)+)";\r
-       \r
-       public static final String sketchConnection =\r
-               //   1,  id,  from,to,  shape,hid, pol, thick,hasf,dtype,res, color,font,np|plist\r
-                       "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ SKIP+"[^,]*,[^,]*,"+POINTS;\r
-       \r
-       // group indices for later use\r
-       private static final int connectionId = 1;\r
-       private static final int connectionFrom = 2;\r
-       private static final int connectionTo = 3;\r
-       private static final int connectionShape = 4;\r
-       private static final int connectionPoints = 5;\r
-       \r
-       public static int getConnectionId(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(connectionId));\r
-       }\r
-       \r
-       public static int getConnectionFrom(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(connectionFrom));\r
-       }\r
-       \r
-       public static int getConnectionTo(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(connectionTo));\r
-       }\r
-       \r
-       public static SketchConnection getPossibleSketchConnection(String line, Sketch sketch) {\r
-               Matcher matcher = Pattern.compile(sketchConnection).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               int id = Integer.parseInt(matcher.group(connectionId));\r
-               int from = Integer.parseInt(matcher.group(connectionFrom));\r
-               int to = Integer.parseInt(matcher.group(connectionTo));\r
-               ConnectionType type = getConnectionType(matcher);\r
-               int[] points = parsePoints(matcher.group(connectionPoints));\r
-               \r
-               return new SketchConnection(id, from, to, type, points);\r
-       }\r
-       \r
-       private static int[] parsePoints(String points) {\r
-               // points should be a well formed points string\r
-               int sep = points.indexOf('|');\r
-               int count = Integer.parseInt(points.substring(0, sep));\r
-               int[] array = new int[count*2];\r
-               for (int i = 0; i < count; i++) {\r
-                       int start = sep + 1;\r
-                       sep = points.indexOf('|', start);\r
-                       String[] pair = points.substring(start+1, sep-1).split(",");\r
-                       array[i*2] = Integer.parseInt(pair[0]);\r
-                       array[i*2+1] = Integer.parseInt(pair[1]);\r
-               }\r
-               return array;\r
-       }\r
-       \r
-       private static final String COMMON =\r
-               //  x,   y,   w,   h,   sh,  bits,hid, hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
-                       SAVE+SAVE+SAVE+SAVE+SAVE+SAVE+SKIP+SKIP+SAVE+".*";\r
-       \r
-       public static final String sketchVariable =\r
-               //   n,   id,  name,        x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
-                       "10,"+SAVE+VAR_NAME_NORMAL+","+COMMON;\r
-       public static final String sketchValve =\r
-                       "11,"+SAVE+SAVE+        COMMON;\r
-       public static final String sketchComment =\r
-                       "12,"+SAVE+SAVE+        COMMON;\r
-       \r
-       // group indices for later use\r
-       private static final int elementId = 1;\r
-       private static final int elementName = 2;\r
-       private static final int elementX = 3;\r
-       private static final int elementY = 4;\r
-       private static final int elementWidth = 5;\r
-       private static final int elementHeight = 6;\r
-       private static final int elementShape = 7;\r
-       private static final int elementBits = 8;\r
-       private static final int elementTextPos = 9;\r
-       \r
-       public static SketchVariable getPossibleSketchVariable(String line, MdlModel mdl) {\r
-               Matcher matcher = Pattern.compile(sketchVariable).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               int id = Integer.parseInt(matcher.group(elementId));\r
-               Variable var = mdl.getVariable(normalize(matcher.group(elementName)));\r
-               if (var == null) {\r
-                       System.err.println("could not find variable corresponding to "+matcher.group(elementName));\r
-               }\r
-               \r
-               SketchVariable variable = new SketchVariable(id, var);\r
-               \r
-               initializeElement(variable, matcher);\r
-               \r
-               return variable;\r
-       }\r
-       \r
-       public static SketchValve getPossibleSketchValve(String line) {\r
-               Matcher matcher = Pattern.compile(sketchValve).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               int id = Integer.parseInt(matcher.group(elementId));\r
-               TextPosition pos = getTextPos(matcher);\r
-               \r
-               SketchValve valve = new SketchValve(id, pos);\r
-               \r
-               initializeElement(valve, matcher);\r
-               \r
-               return valve;\r
-       }\r
-       \r
-       public static SketchComment getPossibleSketchComment(String line) {\r
-               Matcher matcher = Pattern.compile(sketchComment).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               int id = Integer.parseInt(matcher.group(elementId));\r
-               CommentIcon icon = getCommentIcon(matcher);\r
-               \r
-               SketchComment comment = new SketchComment(id, icon);\r
-               \r
-               initializeElement(comment, matcher);\r
-               \r
-               return comment;\r
-       }\r
-       \r
-       public static int getElementX(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(elementX));\r
-       }\r
-       \r
-       public static int getElementY(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(elementY));\r
-       }\r
-       \r
-       public static int getElementWidth(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(elementWidth));\r
-       }\r
-       \r
-       public static int getElementHeight(Matcher matcher) {\r
-               return Integer.parseInt(matcher.group(elementHeight));\r
-       }\r
-       \r
-       public static void initializeElement(SketchElement element, Matcher matcher) {\r
-               int x = Integer.parseInt(matcher.group(elementX));\r
-               int y = Integer.parseInt(matcher.group(elementY));\r
-               int w = Integer.parseInt(matcher.group(elementWidth));\r
-               int h = Integer.parseInt(matcher.group(elementHeight));\r
-               boolean attached = elementIsAttached(matcher);\r
-               boolean in = elementAllowsInBound(matcher);\r
-               boolean out = elementAllowsOutBound(matcher);\r
-               boolean inputOutput = elementIsInputOutput(matcher);\r
-               boolean textLine = elementhasTextLine(matcher);\r
-               \r
-               element.init(x, y, w, h, attached, in, out, inputOutput, textLine);\r
-       }\r
-       \r
-       public static ConnectionType getConnectionType(Matcher matcher) {\r
-               switch(Integer.parseInt(matcher.group(connectionShape))) {\r
-               case 0: \r
-               case 1: return ConnectionType.ARROW;\r
-               case 4: return ConnectionType.LINE_ARROW;\r
-               case 100: return ConnectionType.LINE_SEGMENT;\r
-               default: System.err.println("connection type "+Integer.parseInt(matcher.group(connectionShape))); return ConnectionType.OTHER;\r
-               }\r
-       }\r
-       \r
-       public static CommentIcon getCommentIcon(Matcher matcher) {\r
-               switch(Integer.parseInt(matcher.group(elementName))) {\r
-               case 48: return CommentIcon.CLOUD;\r
-               default: return CommentIcon.OTHER;\r
-               }\r
-       }\r
-       \r
-       public static TextPosition getTextPos(Matcher matcher) {\r
-               switch (Integer.parseInt(matcher.group(elementTextPos))) {\r
-               case 0: return TextPosition.INSIDE;\r
-               case 1: return TextPosition.BELOW;\r
-               case 2: return TextPosition.LEFT;\r
-               case 3: return TextPosition.ABOVE;\r
-               case 4: return TextPosition.RIGHT;\r
-               default: return TextPosition.UNSET;\r
-               }\r
-       }\r
-       \r
-       public static boolean elementIsAttached(Matcher matcher) {\r
-               return (Integer.parseInt(matcher.group(elementShape)) & 1<<5) != 0;\r
-       }\r
-       \r
-       public static boolean elementAllowsInBound(Matcher matcher) {\r
-               return (Integer.parseInt(matcher.group(elementBits)) & 1) != 0;\r
-       }\r
-       \r
-       public static boolean elementAllowsOutBound(Matcher matcher) {\r
-               return (Integer.parseInt(matcher.group(elementBits)) & 1<<1) != 0;\r
-       }\r
+       // some regular expressions that are used commonly in the parser\r
+       public static final String DBL = "-?\\d+(?:\\.\\d+)?";\r
+       public static final String DBL_G = "("+DBL+")";\r
+       public static final String INT = "-?\\d+";\r
+       public static final String INT_G = "("+INT+")";\r
+       \r
+       // matches a basic vensim name (starts with a letter, may contain any word \r
+       // characters and white space)\r
+       public static final String BASIC_NAME =\r
+                       "[A-Za-z]\\w*(?:\\s+\\w+)*";\r
+       // matches a special vensim name (starts and ends with a quotation mark, \r
+       // may contain escaped special characters)\r
+       public static final String SPECIAL_NAME =\r
+                       "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"";\r
        \r
-       public static boolean elementhasTextLine(Matcher matcher) {\r
-               return (Integer.parseInt(matcher.group(elementBits)) & 1<<2) != 0;\r
-       }\r
-       \r
-       public static boolean elementIsInputOutput(Matcher matcher) {\r
-               return (Integer.parseInt(matcher.group(elementBits)) & 1<<3) != 0;\r
-       }\r
+       // matches a vensim variable (either basic name or special name)\r
+       public static final String VARIABLE =\r
+                               "("+BASIC_NAME+"|"+SPECIAL_NAME+")";\r
+       // matches a vensim variable inside an expression (basic name not followed \r
+       // by an open parenthesis or a special name)\r
+       public static final String VARIABLE_EXPRESSION =\r
+                       "([A-Za-z](?![\\s\\w]*\\()\\w*(?:\\s+\\w+)*|"+SPECIAL_NAME+")";\r
+       // matches a vensim subscript variable (basic name with a list of indices)\r
+       public static final String SUBSCRIPT =\r
+                       "("+BASIC_NAME+")\\[("+BASIC_NAME+"\\!?(?:,"+BASIC_NAME+"\\!?)*)\\]";\r
+       // matches a vensim function (basic name followed by an open parenthesis)\r
+       public static final String FUNCTION =\r
+                       "([A-Za-z]\\w*(?:\\s+\\w+)*)\\s*\\(";\r
        \r
        public static String normalize(String str) {\r
                // start by removing all tabs from the string, not really necessary \r
-               // but does make the equation cleaner (could also be done in the read \r
-               // method above)\r
+               // but does make the equation cleaner\r
                str = str.replaceAll("\t", "");\r
 \r
-               // remove inline operations\r
-               str = removeInlineOperation(str, "AND");\r
-               str = removeInlineOperation(str, "OR");\r
-               \r
-               // rename vensim method calls to sysdyn equivalents\r
-               str = str.replaceAll("IF THEN ELSE", "IFTHENELSE");\r
+               // inline operations could be removed here if it can be done reliablty\r
                \r
-               // TODO: replace array slice operations\r
-\r
-               // normalize variable names\r
-               str = processVariables(str);\r
+               // normalize functions\r
+               str = normalizeFunctions(str);\r
+               // normalize variables\r
+               str = normalizeVariables(str);\r
 \r
                return str;\r
        }\r
        \r
-       private static String removeInlineOperation(String str, String op) {\r
-               while (str.contains(":"+op+":")) {\r
-                       // this should work in most cases, even with nested parentheses \r
-                       // in the left and right hand side expression\r
-                       \r
-                       // TODO: does not work in all cases\r
-                       \r
-                       // the regular expression can be split into 5 parts:\r
-                       // 1. delimiter character on the left (either start of string, ',' or '(':\r
-                       //    (?:^|[(,])\r
-                       // 2. left hand side expression, anything except ',' unless it is \r
-                       //    enclosed in parentheses which is allowed:\r
-                       //    ([^(,]*(?:\\(.*\\)[^(,])*)\r
-                       // 3. the inlined operation:\r
-                       //    :OPERATION:\r
-                       // 4. right hand side expression, similar to left hand side expression\r
-                       //    but with ')' instead of '(':\r
-                       //    ([^),]*(?:\\(.*\\)[^),])*)\r
-                       // 5. delimiter character on the right (either end of string, ',' or ')'):\r
-                       //    (?:$|[),])\r
-                       \r
-                       // note that the expression also makes heavy use of both non-capturing and\r
-                       // capturing groups ("(?:)" and "()")\r
-                       Matcher matcher = Pattern.compile(\r
-                                       "(?:^|[(,])([^(,]*(?:\\(.*\\)[^(,])*):" + op + ":([^),]*(?:\\(.*\\)[^),])*)(?:$|[),])").matcher(str);\r
-                       \r
-                       if (!matcher.find()) {\r
-                               System.err.println("inlined operation not found");\r
-                               return str;\r
-                       }\r
-                       \r
-                       StringBuilder buf = new StringBuilder();\r
-                       \r
-                       // part before left hand side\r
-                       buf.append(str.substring(0, matcher.start(1)));\r
-                       // operation open\r
-                       buf.append(op);\r
-                       buf.append('(');\r
-                       // left hand side\r
-                       buf.append(matcher.group(1).trim());\r
-                       // delimiter\r
-                       buf.append(',');\r
-                       // right hand side\r
-                       buf.append(matcher.group(2).trim());\r
-                       // operation close\r
-                       buf.append(')');\r
-                       // part after right hand side\r
-                       buf.append(str.substring(matcher.end(2)));\r
-                       \r
-                       str = buf.toString();\r
-               }\r
-               return str;\r
-       }\r
-       \r
-       private static String processVariables(String str) {\r
+       // construct a replacement string from expression where each variable\r
+       // name is normalized to a sysdyn-friendly format\r
+       private static String normalizeVariables(String expression) {\r
                StringBuilder result = new StringBuilder();\r
-               \r
                int offset = 0;\r
 \r
-               Matcher matcher = Pattern.compile(VAR_NAME_NORMAL).matcher(str);\r
+               Matcher matcher = Pattern.compile(VARIABLE_EXPRESSION).matcher(expression);\r
                while (matcher.find()) {\r
-                       result.append(str.substring(offset, matcher.start()));\r
+                       result.append(expression.substring(offset, matcher.start()));\r
 \r
-                       String replacement = matcher.group();\r
+                       String variable = matcher.group(1);\r
                        \r
-                       // TODO: comment this\r
-                       if (replacement.equalsIgnoreCase("time")) {\r
-                               replacement = "time";\r
+                       if (variable.equalsIgnoreCase("time")) {\r
+                               result.append("time");\r
                        }\r
-                       else if (replacement.startsWith("\"")) {\r
-                               // if the variable name is quoted, change the quotes to modelica syntax\r
-                               replacement = "'" + replacement.substring(1, replacement.length() - 1) + "'";\r
+                       else if (variable.startsWith("\"") && variable.endsWith("\"")) {\r
+                               result.append('\'');\r
+                               result.append(variable.substring(1, variable.length() - 1));\r
+                               result.append('\'');\r
                        }\r
-                       else if (Pattern.compile("[-+*/]").matcher(replacement).find()) {\r
-                               // if the variable name contains "bad" characters, quote it\r
-                               replacement = "'" + replacement + "'";\r
+                       else if (variable.contains("-")) {\r
+                               result.append('\'');\r
+                               result.append(variable);\r
+                               result.append('\'');\r
                        }\r
                        else {\r
-                               // otherwise simply capitalize the variable name properly\r
-                               String[] parts = replacement.split("\\s+");\r
-                               StringBuilder buf = new StringBuilder();\r
-                               for (String part : parts) {\r
-                                       part = part.substring(0, 1).toUpperCase() + part.substring(1);\r
-                                       if (buf.length() > 0)\r
-                                               buf.append(' ');\r
-                                       buf.append(part);\r
+                               String[] parts = variable.split("\\s+");\r
+                               for (int i = 0; i < parts.length; i++) {\r
+                                       if (i > 0)\r
+                                               result.append(' ');\r
+                                       result.append(parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1));\r
                                }\r
-                               replacement = buf.toString();\r
                        }\r
-\r
-                       result.append(replacement);\r
-\r
+                       \r
                        offset = matcher.end();\r
                }\r
-               if (offset < str.length()) {\r
-                       result.append(str.substring(offset));\r
+               if (offset < expression.length()) {\r
+                       result.append(expression.substring(offset));\r
                }\r
                \r
                return result.toString();\r
        }\r
        \r
-       \r
-       \r
-       public static void initializeVariable(MdlModel mdl, ModelVariable variable, Variable mdlVariable) {\r
-               variable.setName(mdlVariable.getName());\r
-               variable.setExpression(mdlVariable.getModelExpression(mdl));\r
-               \r
-               String unit = mdlVariable.getUnit();\r
-               Range range = parseRange(unit);\r
-               if (range != null)\r
-                       unit = unit.substring(0, unit.indexOf('[')).trim();\r
-               variable.setUnit(unit);\r
-               variable.setRange(range);\r
-               \r
-               variable.setDescription(mdlVariable.getDescription());\r
-       }\r
-       \r
-       private static Range parseRange(String unit) {\r
-               Matcher matcher = Pattern.compile("\\[("+NUMBER+"),(\\?|("+NUMBER+")|("+NUMBER+"),("+NUMBER+"))\\]").matcher(unit);\r
-               if (matcher.find()) {\r
-                       Double start, end, step;\r
-                       start = Double.parseDouble(matcher.group(1));\r
-                       if (matcher.group(2).equals("?")) {\r
-                               end = null;\r
-                               step = null;\r
-                       }\r
-                       else if (matcher.group(2).contains(",")){\r
-                               end = Double.parseDouble(matcher.group(4));\r
-                               step = Double.parseDouble(matcher.group(5));\r
+       // construct a replacement string from expression where each variable\r
+       // name is normalized to a sysdyn-friendly format\r
+       private static String normalizeFunctions(String expression) {\r
+               StringBuilder result = new StringBuilder();\r
+               int offset = 0;\r
+\r
+               Matcher matcher = Pattern.compile(FUNCTION).matcher(expression);\r
+               while (matcher.find()) {\r
+                       result.append(expression.substring(offset, matcher.start()));\r
+\r
+                       String function = matcher.group(1);\r
+                       \r
+                       if (function.equalsIgnoreCase("IF THEN ELSE")) {\r
+                               result.append("IFTHENELSE");\r
                        }\r
                        else {\r
-                               end = Double.parseDouble(matcher.group(3));\r
-                               step = null;\r
+                               // this will also capitalize lookups, is this ok?\r
+                               result.append(function.toUpperCase());\r
                        }\r
-                       return new Range(start, end, step);\r
+                       result.append('(');\r
+\r
+                       offset = matcher.end();\r
                }\r
-               else {\r
-                       return null;\r
+               if (offset < expression.length()) {\r
+                       result.append(expression.substring(offset));\r
                }\r
+               \r
+               return result.toString();\r
        }\r
        \r
-       public static double[] parseLookup(String lookup) {\r
-               // a hack to remove the leading empty string otherwise produced by split()\r
-               lookup = lookup.replaceFirst("[(),]+", "");\r
-               String[] parts = lookup.split("[(),]+");\r
-               double[] points = new double[parts.length];\r
-               for (int i = 0; i < parts.length; i++) {\r
-                       points[i] = Double.parseDouble(parts[i]);\r
+       public static String expandIterations(String expression, MdlModel mdl) {\r
+               if (!expression.contains("[")) {\r
+                       return expression;\r
                }\r
-               return points;\r
-       }\r
-       \r
-       public static Expression parseExpression(String expression) {\r
-               Matcher matcher = Pattern.compile("([A-Za-z](?: *\\w+)*)\\s*\\((.*)\\)").matcher(expression);\r
-               if (!matcher.matches())\r
-                       return new NormalExpression(normalize(expression));\r
-               \r
-               String function = matcher.group(1);\r
-               String[] parameters = splitParameters(matcher.group(2));\r
                \r
-               if (function.startsWith("INTEG")) {\r
-                       if (parameters.length != 2) {\r
-                               System.err.println("malformed integral expression: "+expression);\r
-                               return null;\r
+               StringBuilder result = new StringBuilder();\r
+               int offset = 0;\r
+\r
+               Matcher matcher = Pattern.compile(SUBSCRIPT).matcher(expression);\r
+               while (matcher.find()) {\r
+                       result.append(expression.substring(offset, matcher.start()));\r
+                       \r
+                       String name = matcher.group(1);\r
+                       String[] indices = matcher.group(2).split(",");\r
+                       \r
+                       result.append(name);\r
+                       \r
+                       result.append('[');\r
+                       for (int i = 0; i < indices.length; i++) {\r
+                               if (i > 0)\r
+                                       result.append(',');\r
+                               \r
+                               if (indices[i].endsWith("!")) {\r
+                                       String subscript = indices[i].substring(0, indices[i].length() - 1);\r
+                                       List<String> values = mdl.getSubscript(subscript).getValues(mdl);\r
+                                       result.append('{');\r
+                                       for (int j = 0; j < values.size(); j++) {\r
+                                               if (j > 0)\r
+                                                       result.append(',');\r
+                                               result.append(values.get(j));\r
+                                       }\r
+                                       result.append('}');\r
+                               }\r
+                               else {\r
+                                       result.append(indices[i]);\r
+                               }\r
                        }\r
-                       String integral = normalize(parameters[0]);\r
-                       String initial = normalize(parameters[1]);\r
-                       return new IntegralExpression(integral, initial);\r
+                       result.append(']');\r
+                       \r
+                       offset = matcher.end();\r
                }\r
-               else if (function.startsWith("DELAY N")) {\r
-                       if (parameters.length != 4) {\r
-                               System.err.println("malformed delay expression: "+expression);\r
-                               return null;\r
-                       }\r
-                       String expr = normalize(parameters[0]);\r
-                       String time = normalize(parameters[1]);\r
-                       String initial = normalize(parameters[2]);\r
-                       int degree = Integer.parseInt(parameters[3]);\r
-                       return new DelayExpression(expr, time, initial, degree);\r
+               if (offset < expression.length()) {\r
+                       result.append(expression.substring(offset));\r
                }\r
-               else if (function.startsWith("GAME")) {\r
-                       if (parameters.length != 1) {\r
-                               System.err.println("malformed game expression: "+expression);\r
-                               return null;\r
+               \r
+               return result.toString();\r
+       }\r
+       \r
+       public static String replaceSubscripts(String expression, String subscript, String replacement) {\r
+               StringBuilder result = new StringBuilder();\r
+               int offset = 0;\r
+               \r
+               System.err.println("replace subscripts "+subscript+" with "+replacement+" in "+expression);\r
+\r
+               Matcher matcher = Pattern.compile(SUBSCRIPT).matcher(expression);\r
+               while (matcher.find()) {\r
+                       result.append(expression.substring(offset, matcher.start()));\r
+                       \r
+                       String name = matcher.group(1);\r
+                       String[] indices = matcher.group(2).split(",");\r
+                       \r
+                       result.append(name);\r
+                       \r
+                       result.append('[');\r
+                       for (int i = 0; i < indices.length; i++) {\r
+                               if (i > 0)\r
+                                       result.append(',');\r
+                               \r
+                               if (indices[i].equals(subscript)) {\r
+                                       result.append(replacement);\r
+                               }\r
+                               else {\r
+                                       result.append(indices[i]);\r
+                               }\r
                        }\r
-                       // game expressions are currently treated as normal expressions\r
-                       return new NormalExpression(normalize(parameters[0]));\r
+                       result.append(']');\r
+                       \r
+                       offset = matcher.end();\r
                }\r
-               else {\r
-                       // the function does not require special handling\r
-                       return new NormalExpression(normalize(expression));\r
+               if (offset < expression.length()) {\r
+                       result.append(expression.substring(offset));\r
                }\r
+               \r
+               return result.toString();\r
        }\r
        \r
-       public static String[] splitParameters(String str) {\r
+       public static String[] splitFunctionParameters(String str) {\r
                ArrayList<String> list = new ArrayList<String>();\r
 \r
                int i;\r
@@ -678,5 +248,4 @@ public class MdlUtil {
                \r
                return list.toArray(new String[list.size()]);\r
        }\r
-       \r
 }\r
diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java
new file mode 100644 (file)
index 0000000..4c3a1e1
--- /dev/null
@@ -0,0 +1,58 @@
+package org.simantics.sysdyn.modelImport.mdl;\r
+\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+public abstract class Declaration {\r
+\r
+       private static final String CATEGORY = "\\*{56}\\s*\\.(\\S+)\\s*\\*{56}.*";\r
+       \r
+       protected static final String DECL_DELIM = "\\s*~\\s*";\r
+       protected static final String DECL_END = "\\s*\\|";\r
+       protected static final String DECL_UNIT = "([^~]*?)";\r
+       protected static final String DECL_DESC = "([^\\|]*?)";\r
+\r
+       protected static final String DECL_SUFFIX = \r
+                       DECL_DELIM + DECL_UNIT + DECL_DELIM + DECL_DESC + DECL_END;\r
+       protected static final int declarationUnit = 1;\r
+       protected static final int declarationDescription = 2;\r
+       \r
+       private String name;\r
+       private String unit;\r
+       private String description;\r
+       \r
+       protected Declaration(String name) {\r
+               this.name = name;\r
+       }\r
+       \r
+       protected void parseSuffix(String suffix) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(DECL_SUFFIX).matcher(suffix);\r
+               if (!matcher.matches()) {\r
+                       // this should not happen unless subclasses fail to construct their\r
+                       // regular expressions properly\r
+                       throw new Exception("could not parse declaration suffix "+suffix);\r
+               }\r
+               \r
+               unit = matcher.group(declarationUnit);\r
+               description = matcher.group(declarationDescription);\r
+       }\r
+       \r
+       public String getName() {\r
+               return name;\r
+       }\r
+       \r
+       public String getUnit() {\r
+               return unit;\r
+       }\r
+       \r
+       public String getDescription() {\r
+               return description;\r
+       }\r
+\r
+       public static String parseCategory(String line) {\r
+               Matcher matcher = Pattern.compile(CATEGORY).matcher(line);\r
+               return matcher.matches() ? matcher.group(1) : null;\r
+       }\r
+\r
+}\r
diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java
new file mode 100644 (file)
index 0000000..cfa4129
--- /dev/null
@@ -0,0 +1,5 @@
+package org.simantics.sysdyn.modelImport.mdl;\r
+\r
+public interface IMdlObject {\r
+       \r
+}\r
diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java
new file mode 100644 (file)
index 0000000..ae22514
--- /dev/null
@@ -0,0 +1,107 @@
+package org.simantics.sysdyn.modelImport.mdl;\r
+\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.sysdyn.modelImport.MdlUtil;\r
+import org.simantics.sysdyn.modelImport.model.expression.LookupExpression;\r
+import org.simantics.sysdyn.modelImport.model.support.Function;\r
+\r
+public class Lookup extends Declaration {\r
+       \r
+       private static final String LOOKUP_RANGE =\r
+                       "\\[\\("+MdlUtil.DBL_G+","+MdlUtil.DBL_G+"\\)-\\("+MdlUtil.DBL_G+","+MdlUtil.DBL_G+"\\)\\]";\r
+       private static final String LOOKUP_POINTS =\r
+                       "(\\("+MdlUtil.DBL+","+MdlUtil.DBL+"\\)(?:,\\("+MdlUtil.DBL+","+MdlUtil.DBL+"\\))*)";\r
+       private static final String LOOKUP =\r
+                       "("+MdlUtil.BASIC_NAME+")\\s*\\(\\s*"+LOOKUP_RANGE+","+LOOKUP_POINTS+"\\s*\\)";\r
+       \r
+       private static final String LOOKUP_DECL = \r
+                       LOOKUP+"("+DECL_SUFFIX+")";     \r
+       private static final int lookupName = 1;\r
+       private static final int lookupRangeXMin = 2;\r
+       private static final int lookupRangeYMin = 3;\r
+       private static final int lookupRangeXMax = 4;\r
+       private static final int lookupRangeYMax = 5;\r
+       private static final int lookupPoints = 6;\r
+       private static final int lookupSuffix = 7;\r
+       \r
+       private double xMin;\r
+       private double yMin;\r
+       private double xMax;\r
+       private double yMax;\r
+       private double[] points;\r
+       \r
+       private Function function;\r
+       \r
+       // TODO: generate functions from lookup variables\r
+\r
+       protected Lookup(String name, double xMin, double yMin, double xMax, double yMax, double[] points) {\r
+               super(name);\r
+               this.xMin = xMin;\r
+               this.yMin = yMin;\r
+               this.xMax = xMax;\r
+               this.yMax = yMax;\r
+               this.points = points;\r
+       }\r
+       \r
+       public static Lookup getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(LOOKUP_DECL).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       return null;\r
+               }\r
+               \r
+               // TODO: capitalize this?\r
+               String name = MdlUtil.normalize(matcher.group(lookupName));\r
+               double xMin = Double.parseDouble(matcher.group(lookupRangeXMin));\r
+               double yMin = Double.parseDouble(matcher.group(lookupRangeYMin));\r
+               double xMax = Double.parseDouble(matcher.group(lookupRangeXMax));\r
+               double yMax = Double.parseDouble(matcher.group(lookupRangeYMax));\r
+               double[] points = parsePoints(matcher.group(lookupPoints));\r
+               \r
+               Lookup lookup = new Lookup(name, xMin, yMin, xMax, yMax, points);\r
+               lookup.parseSuffix(matcher.group(lookupSuffix));\r
+               return lookup;\r
+       }\r
+       \r
+       private static double[] parsePoints(String str) {\r
+               // a hack to remove the leading empty string otherwise produced by split()\r
+               str = str.replaceFirst("[(),]+", "");\r
+               String[] parts = str.split("[(),]+");\r
+               double[] points = new double[parts.length];\r
+               for (int i = 0; i < parts.length; i++) {\r
+                       points[i] = Double.parseDouble(parts[i]);\r
+               }\r
+               return points;\r
+       }\r
+\r
+       public double getxMin() {\r
+               return xMin;\r
+       }\r
+\r
+       public double getyMin() {\r
+               return yMin;\r
+       }\r
+\r
+       public double getxMax() {\r
+               return xMax;\r
+       }\r
+\r
+       public double getyMax() {\r
+               return yMax;\r
+       }\r
+       \r
+       public double[] getPoints() {\r
+               return points;\r
+       }\r
+       \r
+       public Function getFunction() {\r
+               if (function == null) {\r
+                       function = null;\r
+               }\r
+               \r
+               return function;\r
+       }\r
+       \r
+}\r
diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/LookupVariable.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/LookupVariable.java
deleted file mode 100644 (file)
index 441e360..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.simantics.sysdyn.modelImport.mdl;\r
-\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import org.simantics.sysdyn.modelImport.MdlUtil;\r
-import org.simantics.sysdyn.modelImport.model.expression.LookupExpression;\r
-\r
-public class LookupVariable extends Variable {\r
-       \r
-       // a lookup variable contains a set of points\r
-       private static final String LOOKUP_NAME =\r
-                       "([A-Za-z](?: *\\w+)*)";\r
-       private static final String LOOKUP_RANGE =\r
-                       "\\[\\(("+NUMBER+"),("+NUMBER+")\\)-\\(("+NUMBER+"),("+NUMBER+")\\)\\]";\r
-       private static final String LOOKUP_POINTS =\r
-                       "(\\("+NUMBER+","+NUMBER+"\\)(?:,\\("+NUMBER+","+NUMBER+"\\))*)";\r
-       private static final String LOOKUP_VARIABLE =\r
-                       LOOKUP_NAME+"\\s*\\(\\s*"+LOOKUP_RANGE+","+LOOKUP_POINTS+"\\s*\\)";\r
-       \r
-       public static final String lookupVariablePattern = \r
-                       LOOKUP_VARIABLE+DELIM+UNIT+DELIM+DESCRIPTION+END;\r
-       private static final int lookupVariableName = 1;\r
-       private static final int lookupVariableRangeXMin = 2;\r
-       private static final int lookupVariableRangeYMin = 3;\r
-       private static final int lookupVariableRangeXMax = 4;\r
-       private static final int lookupVariableRangeYMax = 5;\r
-       private static final int lookupVariablePoints = 6;\r
-       private static final int lookupVariableUnit = 7;\r
-       private static final int lookupVariableDesc = 8;\r
-       \r
-       private double xMin;\r
-       private double yMin;\r
-       private double xMax;\r
-       private double yMax;\r
-\r
-       public LookupVariable(String name, String expression, String unit, String description, \r
-                       double xMin, double yMin, double xMax, double yMax) {\r
-               super(name, expression, unit, description);\r
-               this.xMin = xMin;\r
-               this.yMin = yMin;\r
-               this.xMax = xMax;\r
-               this.yMax = yMax;\r
-       }\r
-       \r
-       public static LookupVariable getPossibleLookUpVariable(String line) {\r
-               Matcher matcher = Pattern.compile(lookupVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
-                       return null;\r
-               \r
-               String name = MdlUtil.normalize(matcher.group(lookupVariableName));\r
-               double xMin = Double.parseDouble(matcher.group(lookupVariableRangeXMin));\r
-               double yMin = Double.parseDouble(matcher.group(lookupVariableRangeYMin));\r
-               double xMax = Double.parseDouble(matcher.group(lookupVariableRangeXMax));\r
-               double yMax = Double.parseDouble(matcher.group(lookupVariableRangeYMax));\r
-               String expression = matcher.group(lookupVariablePoints);\r
-               String unit = matcher.group(lookupVariableUnit);\r
-               String desc = matcher.group(lookupVariableDesc);\r
-               \r
-               return new LookupVariable(name, expression, unit, desc, xMin, yMin, xMax, yMax);\r
-       }\r
-\r
-       public double getxMin() {\r
-               return xMin;\r
-       }\r
-\r
-       public double getyMin() {\r
-               return yMin;\r
-       }\r
-\r
-       public double getxMax() {\r
-               return xMax;\r
-       }\r
-\r
-       public double getyMax() {\r
-               return yMax;\r
-       }\r
-       \r
-       @Override\r
-       public LookupExpression getModelExpression(MdlModel mdl) {\r
-               return new LookupExpression(xMin, yMin, xMax, yMax, MdlUtil.parseLookup(getExpression()));\r
-       }\r
-       \r
-}\r
index b86b2a03554f5b72434686c65b38750744294ef0..202dcad816bc355f1c415ba0e960ff3616502632 100644 (file)
@@ -4,25 +4,26 @@ import java.util.ArrayList;
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.List;\r
+import java.util.Map;\r
 import java.util.Set;\r
 \r
 public class MdlModel {\r
        \r
        private String name;\r
        \r
-       private HashMap<String, Variable> variables;\r
-       private HashMap<String, ArrayList<Variable>> groups;\r
-       private HashMap<String, Subscript> subscripts;\r
-       private HashMap<String, Subscript> subscriptValues;\r
-       private ArrayList<Sketch> sketches;\r
+       private Map<String, Variable> variables;\r
+       private Map<String, ArrayList<Variable>> groups;\r
+       private Map<String, Lookup> lookups;\r
+       private Map<String, Subscript> subscripts;\r
+       private List<Sketch> sketches;\r
        \r
        public MdlModel(String name) {\r
                this.name = name;\r
                \r
                this.variables = new HashMap<String, Variable>();\r
                this.groups = new HashMap<String, ArrayList<Variable>>();\r
+               this.lookups = new HashMap<String, Lookup>();\r
                this.subscripts = new HashMap<String, Subscript>();\r
-               this.subscriptValues = new HashMap<String, Subscript>();\r
                this.sketches = new ArrayList<Sketch>();\r
        }\r
        \r
@@ -30,31 +31,32 @@ public class MdlModel {
                return name;\r
        }\r
        \r
-       public void addVariable(SubscriptVariable variable, String group) {\r
-               SubscriptVariable original = (SubscriptVariable)variables.get(variable.getName());\r
+       public void addVariable(Variable variable, String group) \r
+                       throws Exception {\r
+               if (variables.get(variable.getName()) != null) {\r
+                       throw new Exception("duplicate variable "+variable.getName());\r
+               }\r
+               \r
+               variables.put(variable.getName(), variable);\r
+               addGroup(variable, group);\r
+       }\r
+       \r
+       public void addSubscriptVariable(SubscriptVariable variable, String group) \r
+                       throws Exception {\r
+               Variable original = variables.get(variable.getName());\r
                if (original != null) {\r
-                       original.addLast(variable);\r
+                       if (!(original instanceof SubscriptVariable)) {\r
+                               throw new Exception("incompatible type for variable "+variable.getName());\r
+                       }\r
+                       ((SubscriptVariable)original).addSubscriptVariable(variable);\r
                }\r
                else {\r
                        variables.put(variable.getName(), variable);\r
-                       \r
-                       if (group != null) {\r
-                               if (groups.get(group) == null) {\r
-                                       groups.put(group, new ArrayList<Variable>());\r
-                               }\r
-                               groups.get(group).add(variable);\r
-                       }\r
+                       addGroup(variable, group);\r
                }\r
        }\r
        \r
-       public void addVariable(Variable variable, String group) {\r
-               if (variables.get(variable.getName()) != null) {\r
-                       System.err.println("duplicate variable "+variable.getName());\r
-                       return;\r
-               }\r
-               \r
-               variables.put(variable.getName(), variable);\r
-               \r
+       private void addGroup(Variable variable, String group) {\r
                if (group != null) {\r
                        if (groups.get(group) == null) {\r
                                groups.put(group, new ArrayList<Variable>());\r
@@ -70,17 +72,33 @@ public class MdlModel {
        public Set<Variable> getAllVariables() {\r
                return new HashSet<Variable>(variables.values());\r
        }\r
-\r
-       public void addSubscript(Subscript subscript) {\r
-               Subscript duplicate = resolveSubscript(subscript.getValues());\r
-               if (duplicate != null) {\r
-                       subscripts.put(subscript.getName(), duplicate);\r
-                       System.err.println("dublicate subscript "+subscript.getName()+" added");\r
+       \r
+       public void addLookup(Lookup lookup) \r
+                       throws Exception {\r
+               if (lookups.get(lookup.getName()) != null) {\r
+                       throw new Exception("duplicate lookup "+lookup.getName());\r
                }\r
-               else {\r
-                       subscripts.put(subscript.getName(), subscript);\r
-                       System.err.println("subscript "+subscript.getName()+" added");\r
+               \r
+               lookups.put(lookup.getName(), lookup);\r
+       }\r
+       \r
+       public Lookup getLookup(String name) {\r
+               return lookups.get(name);\r
+       }\r
+       \r
+       public Set<Lookup> getAllLookups() {\r
+               return new HashSet<Lookup>(lookups.values());\r
+       }\r
+       \r
+       public void addSubscript(Subscript subscript) \r
+                       throws Exception {\r
+               if (subscripts.get(subscript.getName()) != null) {\r
+                       throw new Exception("duplicate subscript "+subscript.getName());\r
                }\r
+               \r
+               // TODO: check if a subscript with the same values already exists\r
+               \r
+               subscripts.put(subscript.getName(), subscript);\r
        }\r
        \r
        public Subscript getSubscript(String key) {\r
@@ -91,50 +109,32 @@ public class MdlModel {
                return new HashSet<Subscript>(subscripts.values());\r
        }\r
        \r
-       private Subscript getSuperSet(Subscript subscript) {\r
-               for (Subscript potential : getAllSubscripts()) {\r
-                       if (potential.isSuperSet() && \r
-                                       potential.getValues().containsAll(subscript.getValues())) {\r
-                               return potential;\r
-                       }\r
-               }\r
-               return null;\r
-       }\r
-       \r
-       private Set<Subscript> getSubSets(Subscript subscript) {\r
-               Set<Subscript> subsets = new HashSet<Subscript>();\r
-               for (Subscript potential : getAllSubscripts()) {\r
-                       if (subscript.getValues().size() > potential.getValues().size() &&\r
-                                       subscript.getValues().containsAll(potential.getValues())) {\r
-                               subsets.add(potential);\r
-                       }\r
-               }\r
-               return subsets;\r
+       public Subscript resolveSubscript(List<String> values) {\r
+               return resolveSubscript(new HashSet<String>(values));\r
        }\r
        \r
-       // return a subscript that contains precisely the requested values\r
        public Subscript resolveSubscript(Set<String> values) {\r
-               Set<String> allValues = new HashSet<String>();\r
+               // if one value is actually a subscript, expand it to its values\r
+               Set<String> all = new HashSet<String>();\r
                for (String value : values) {\r
-                       if (subscripts.get(value) != null) {\r
-                               allValues.addAll(subscripts.get(value).getValues());\r
+                       Subscript potential = subscripts.get(value);\r
+                       if (potential != null) {\r
+                               all.addAll(potential.getValues(this));\r
                        }\r
                        else {\r
-                               allValues.add(value);\r
+                               all.add(value);\r
                        }\r
                }\r
                \r
+               // find the subscript that contains exactly the given set of values.\r
+               // only consider original subscripts (ignore equivalent subscripts)\r
                for (Subscript subscript : getAllSubscripts()) {\r
-                       if (allValues.equals(subscript.getValues())) {\r
+                       if (!subscript.isEquivalent() && subscript.getValues(this).containsAll(all) && all.containsAll(subscript.getValues(this))) {\r
                                return subscript;\r
                        }\r
                }\r
                \r
-               System.err.print("ASDF subscript not found for value set:");\r
-               for (String s : allValues)\r
-                       System.err.print(" "+s);\r
-               System.err.println();\r
-               \r
+               // if an exact match could not be found, return null\r
                return null;\r
        }\r
        \r
index 28405d647d2a48393205f11a1d83ef31030dd5af..865f8da2692e7710c5226c07cc7ffb10a07fd0c4 100644 (file)
@@ -17,10 +17,10 @@ public class Sketch {
        public double leftEdge = 0;\r
        public double rightEdge = 0;\r
 \r
-       private ArrayList<SketchComment> comments;\r
-       private ArrayList<SketchConnection> connections;\r
-       private ArrayList<SketchValve> valves;\r
-       private ArrayList<SketchVariable> variables;\r
+       private List<SketchComment> comments;\r
+       private List<SketchConnection> connections;\r
+       private List<SketchValve> valves;\r
+       private List<SketchVariable> variables;\r
        \r
        private HashMap<Integer, SketchObject> objects;\r
        \r
@@ -44,17 +44,17 @@ public class Sketch {
        }\r
        \r
        private void updateEdges() {\r
-               if (edgesOutOfDate) {\r
-                       boolean first = true;\r
-                       for (SketchElement e : getAllElements()) {\r
-                               topEdge    = first ? e.getSysdynTopEdge()    : Math.min(topEdge, e.getSysdynTopEdge());\r
-                               bottomEdge = first ? e.getSysdynBottomEdge() : Math.max(bottomEdge, e.getSysdynBottomEdge());\r
-                               leftEdge   = first ? e.getSysdynLeftEdge()   : Math.min(leftEdge, e.getSysdynLeftEdge());\r
-                               rightEdge  = first ? e.getSysdynRightEdge()  : Math.max(rightEdge, e.getSysdynRightEdge());\r
-                               first = false;\r
-                       }\r
-                       edgesOutOfDate = false;\r
-               }\r
+//             if (edgesOutOfDate) {\r
+//                     boolean first = true;\r
+//                     for (SketchElement e : getAllElements()) {\r
+//                             topEdge    = first ? e.getSysdynTopEdge()    : Math.min(topEdge, e.getSysdynTopEdge());\r
+//                             bottomEdge = first ? e.getSysdynBottomEdge() : Math.max(bottomEdge, e.getSysdynBottomEdge());\r
+//                             leftEdge   = first ? e.getSysdynLeftEdge()   : Math.min(leftEdge, e.getSysdynLeftEdge());\r
+//                             rightEdge  = first ? e.getSysdynRightEdge()  : Math.max(rightEdge, e.getSysdynRightEdge());\r
+//                             first = false;\r
+//                     }\r
+//                     edgesOutOfDate = false;\r
+//             }\r
        }\r
        \r
        public double getTopEdge() {\r
@@ -92,6 +92,8 @@ public class Sketch {
                vOffset = vertical;\r
        }\r
        \r
+       private double hOffset, vOffset;\r
+       \r
        public double getHorizontalOffset() {\r
                return hOffset;\r
        }\r
@@ -123,7 +125,7 @@ public class Sketch {
                objects.put(valve.getId(), valve);\r
                // replace the attached variable with the valve in order to redirect \r
                // possible connections to the variable to the valve\r
-               objects.put(valve.getAttachedVariable().getId(), valve);\r
+               objects.put(valve.getAttached().getId(), valve);\r
        }\r
        \r
        public List<SketchValve> getValves() {\r
@@ -143,16 +145,6 @@ public class Sketch {
                return objects.get(id);\r
        }\r
        \r
-       public List<SketchVariable> getShadowVariables() {\r
-               List<SketchVariable> variables = new ArrayList<SketchVariable>();\r
-               for (SketchVariable var : getVariables()) {\r
-                       if (!var.allowsIn()) {\r
-                               variables.add(var);\r
-                       }\r
-               }\r
-               return variables;\r
-       }\r
-       \r
        public List<SketchElement> getAllElements() {\r
                ArrayList<SketchElement> list = new ArrayList<SketchElement>();\r
                list.addAll(getComments());\r
@@ -161,38 +153,21 @@ public class Sketch {
                return list;\r
        }\r
        \r
-       public List<SketchElement> getIndependentElements() {\r
-               List<SketchElement> elements = new ArrayList<SketchElement>();\r
-               elements.addAll(getAllElements());\r
-               elements.removeAll(getShadowVariables());\r
-               return elements;\r
-       }\r
-       \r
-       // relevant for sysdyn model creation, this is not the cleanest place to\r
-       // store this information but it works\r
-       \r
-       public double hOffset = 0;\r
-       public double vOffset = 0;\r
-       \r
-       public HashMap<Integer, Symbol> elements = new HashMap<Integer, Symbol>();\r
-       \r
-       public void setEdges() {\r
-               boolean first = true;\r
-               for (SketchElement e : getAllElements()) {\r
-                       if (first) {\r
-                               topEdge = e.getSysdynTopEdge();\r
-                               bottomEdge = e.getSysdynBottomEdge();\r
-                               leftEdge = e.getSysdynLeftEdge();\r
-                               rightEdge = e.getSysdynRightEdge();\r
-                               first = false;\r
-                       }\r
-                       else {\r
-                               topEdge = Math.min(topEdge, e.getSysdynTopEdge());\r
-                               bottomEdge = Math.max(bottomEdge, e.getSysdynBottomEdge());\r
-                               leftEdge = Math.min(leftEdge, e.getSysdynLeftEdge());\r
-                               rightEdge = Math.max(rightEdge, e.getSysdynRightEdge());\r
+       public List<SketchVariable> getShadowVariables() {\r
+               List<SketchVariable> variables = new ArrayList<SketchVariable>();\r
+               for (SketchVariable var : getVariables()) {\r
+                       if (!var.allowsIn()) {\r
+                               variables.add(var);\r
                        }\r
                }\r
+               return variables;\r
+       }\r
+       \r
+       public List<SketchVariable> getNonShadowVariables() {\r
+               List<SketchVariable> variables = new ArrayList<SketchVariable>();\r
+               variables.addAll(getVariables());\r
+               variables.removeAll(getShadowVariables());\r
+               return variables;\r
        }\r
 \r
 }\r
index 6e7a8c8e4f73e0e5cbac285531ee36c7ee514710..0fc0d91c61c279075e6dd96dc16d0292dbe61de6 100644 (file)
@@ -1,19 +1,51 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
-import org.simantics.sysdyn.modelImport.MdlUtil.CommentIcon;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
 import org.simantics.sysdyn.modelImport.model.element.Cloud;\r
 import org.simantics.sysdyn.modelImport.model.element.Comment;\r
 import org.simantics.sysdyn.modelImport.model.element.Symbol;\r
 \r
 public class SketchComment extends SketchElement {\r
        \r
+       private static final String SKETCH_COMMENT =\r
+                       "12,"+KEEP_I+KEEP_I+"("+ELEMENT_SUFFIX+")";\r
+       private static final int commentId = 1;\r
+       private static final int commentIcon = 2;\r
+       private static final int commentSuffix = 3;\r
+       \r
+       public enum CommentIcon {\r
+               CLOUD, OTHER\r
+       }\r
+       \r
        private String text;\r
        private CommentIcon icon;\r
 \r
-       public SketchComment(int id, CommentIcon icon) {\r
+       protected SketchComment(int id, CommentIcon icon) {\r
                super(id);\r
                this.icon = icon;\r
        }\r
+       \r
+       public static SketchComment getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SKETCH_COMMENT).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       return null;\r
+               }\r
+               \r
+               int id = Integer.parseInt(matcher.group(commentId));\r
+               \r
+               CommentIcon icon;\r
+               switch (Integer.parseInt(matcher.group(commentIcon))) {\r
+               case 48: icon = CommentIcon.CLOUD; break;\r
+               default: icon = CommentIcon.OTHER; break;\r
+               }\r
+               \r
+               SketchComment element = new SketchComment(id, icon);\r
+               element.parseSuffix(matcher.group(commentSuffix));\r
+               return element;\r
+       }\r
 \r
        public String getText() {\r
                return text;\r
index 8d6e1c1cfa9511cf46a6ed812d46f99201e31a73..74cb1bf70a912f8e0041f1d1cb3b145c6719416f 100644 (file)
@@ -4,26 +4,99 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;\r
 \r
 import org.simantics.sysdyn.modelImport.MdlUtil;\r
-import org.simantics.sysdyn.modelImport.MdlUtil.ConnectionType;\r
 import org.simantics.sysdyn.modelImport.model.element.Connection;\r
 import org.simantics.sysdyn.modelImport.model.element.Dependency;\r
 import org.simantics.sysdyn.modelImport.model.element.Symbol;\r
 import org.simantics.sysdyn.modelImport.model.element.Flow;\r
 \r
 public class SketchConnection extends SketchObject {\r
+       \r
+       public enum ConnectionType {\r
+               ARROW, LINE_ARROW, LINE_SEGMENT, OTHER\r
+       }\r
+       \r
+       // some shorthands\r
+       private static final String KEEP_I = MdlUtil.INT_G+",";\r
+       private static final String SKIP_I = MdlUtil.INT+",";\r
+       private static final String SKIP_ANY = "[^,]*,";\r
+       \r
+       private static final String POINTS = "(\\d+\\|(?:\\(-?\\d+,-?\\d+\\)\\|)+)";\r
+       \r
+       // each sketch connection is declared with a string:\r
+       // 1,id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist\r
+       \r
+       // the following regular expression matches a connection declaration and \r
+       // extracts the useful information from it\r
+       private static final String SKETCH_CONNECTION = \r
+                       "1,"+KEEP_I+KEEP_I+KEEP_I+KEEP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_ANY+SKIP_ANY+POINTS;\r
+       // corresponding group indices\r
+       private static final int connectionId = 1;\r
+       private static final int connectionFrom = 2;\r
+       private static final int connectionTo = 3;\r
+       private static final int connectionShape = 4;\r
+       private static final int connectionPoints = 5;\r
+       \r
+       private static final String SAVE = "(-?\\d+),";\r
+       private static final String SKIP = "-?\\d+,";\r
+       \r
+       public static final String sketchConnection =\r
+               //   1,  id,  from,to,  shape,hid, pol, thick,hasf,dtype,res, color,font,np|plist\r
+                       "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ SKIP+"[^,]*,[^,]*,"+POINTS;\r
 \r
        private int from;\r
        private int to;\r
        private ConnectionType type;\r
        int[] points;\r
 \r
-       public SketchConnection(int id, int from, int to, ConnectionType type, int[] points) {\r
+       protected SketchConnection(int id, int from, int to, ConnectionType type, int[] points) {\r
                super(id);\r
                this.from = from;\r
                this.to = to;\r
                this.type = type;\r
                this.points = points;\r
        }\r
+       \r
+       public static SketchConnection getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SKETCH_CONNECTION).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       return null;\r
+               }\r
+               \r
+               int id = Integer.parseInt(matcher.group(connectionId));\r
+               int from = Integer.parseInt(matcher.group(connectionFrom));\r
+               int to = Integer.parseInt(matcher.group(connectionTo));\r
+               int connType = Integer.parseInt(matcher.group(connectionShape));\r
+               \r
+               ConnectionType type;\r
+               switch (Integer.parseInt(matcher.group(connectionShape))) {\r
+               case 0: \r
+               case 1: type = ConnectionType.ARROW; break;\r
+               case 4: type = ConnectionType.LINE_ARROW; break;\r
+               case 100: type = ConnectionType.LINE_SEGMENT; break;\r
+               default: \r
+                       System.err.println("connection type "+connType+" not recognized"); \r
+                       type = ConnectionType.OTHER; break;\r
+               }\r
+               \r
+               int[] points = parsePoints(matcher.group(connectionPoints));\r
+               \r
+               return new SketchConnection(id, from, to, type, points);\r
+       }\r
+       \r
+       private static int[] parsePoints(String str) {\r
+               int sep = str.indexOf('|');\r
+               int count = Integer.parseInt(str.substring(0, sep));\r
+               int[] points = new int[count*2];\r
+               for (int i = 0; i < count; i++) {\r
+                       int start = sep + 1;\r
+                       sep = str.indexOf('|', start);\r
+                       String[] pair = str.substring(start+1, sep-1).split(",");\r
+                       points[i*2] = Integer.parseInt(pair[0]);\r
+                       points[i*2+1] = Integer.parseInt(pair[1]);\r
+               }\r
+               return points;\r
+       }\r
 \r
        public int getFrom() {\r
                return from;\r
@@ -44,12 +117,10 @@ public class SketchConnection extends SketchObject {
        public Connection getConnection(Sketch sketch) {\r
                Symbol tail = (Symbol)sketch.getObject(from).getModelObject();\r
                if (tail == null) {\r
-                       System.err.println("connection tail not created");\r
                        return null;\r
                }\r
                Symbol head = (Symbol)sketch.getObject(to).getModelObject();\r
                if (head == null) {\r
-                       System.err.println("connection head not created");\r
                        return null;\r
                }\r
                \r
index c1f3486c4b47ead88733144cd6b13ce3dfab59bf..b041864691df9983b04ca6b2eb5b4c68c78b3a8c 100644 (file)
@@ -1,8 +1,36 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.sysdyn.modelImport.MdlUtil;\r
 import org.simantics.sysdyn.modelImport.model.element.Symbol;\r
+import org.simantics.sysdyn.modelImport.model.element.Valve.TextPosition;\r
 \r
 public abstract class SketchElement extends SketchObject {\r
+       \r
+       // some shorthands\r
+       protected static final String KEEP_I = MdlUtil.INT_G+",";\r
+       protected static final String SKIP_I = MdlUtil.INT+",";\r
+       \r
+       // each sketch element is declared with a string:\r
+       // n,id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+       \r
+       // n, id and name depend on the type of the sketch element, and some\r
+       // of the fields in the suffix do not contain useful information\r
+       \r
+       // the following regular expression matches the suffix of an element\r
+       // declaration and extracts the useful information from it\r
+       protected static final String ELEMENT_SUFFIX =\r
+                       KEEP_I+KEEP_I+KEEP_I+KEEP_I+KEEP_I+KEEP_I+SKIP_I+SKIP_I+KEEP_I+".*";\r
+       // corresponding group indices\r
+       protected static final int elementX = 1;\r
+       protected static final int elementY = 2;\r
+       protected static final int elementWidth = 3;\r
+       protected static final int elementHeight = 4;\r
+       protected static final int elementShape = 5;\r
+       protected static final int elementBits = 6;\r
+       protected static final int elementTextPos = 7;\r
 \r
        private int x;\r
        private int y;\r
@@ -13,38 +41,40 @@ public abstract class SketchElement extends SketchObject {
        private boolean allowsOut;\r
        private boolean inputOutput;\r
        private boolean textLine;\r
-       \r
-       public SketchElement(int id) {\r
-               super(id);\r
-       }\r
-       \r
-       public SketchElement(int id, int x, int y, int width, int height, \r
-                       boolean attached, boolean allowsIn, boolean allowsOut, \r
-                       boolean inputOutput, boolean textLine) {\r
+       private TextPosition textPosition;\r
+\r
+       protected SketchElement(int id) {\r
                super(id);\r
-               this.x = x;\r
-               this.y = y;\r
-               this.width = width;\r
-               this.height = height;\r
-               this.attached = attached;\r
-               this.allowsIn = allowsIn;\r
-               this.allowsOut = allowsOut;\r
-               this.inputOutput = inputOutput;\r
-               this.textLine = textLine;\r
        }\r
        \r
-       public void init(int x, int y, int width, int height, \r
-                       boolean attached, boolean allowsIn, boolean allowsOut, \r
-                       boolean inputOutput, boolean textLine) {\r
-               this.x = x;\r
-               this.y = y;\r
-               this.width = width;\r
-               this.height = height;\r
-               this.attached = attached;\r
-               this.allowsIn = allowsIn;\r
-               this.allowsOut = allowsOut;\r
-               this.inputOutput = inputOutput;\r
-               this.textLine = textLine;\r
+       protected void parseSuffix(String suffix) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(ELEMENT_SUFFIX).matcher(suffix);\r
+               if (!matcher.matches()) {\r
+                       // this should not happen unless subclasses fail to construct their\r
+                       // regular expressions properly\r
+                       throw new Exception("could not parse element suffix "+suffix);\r
+               }\r
+               \r
+               x = Integer.parseInt(matcher.group(elementX));\r
+               y = Integer.parseInt(matcher.group(elementY));\r
+               width = Integer.parseInt(matcher.group(elementWidth));\r
+               height = Integer.parseInt(matcher.group(elementHeight));\r
+               attached = (Integer.parseInt(matcher.group(elementShape)) & 1<<5) != 0;\r
+               allowsIn = (Integer.parseInt(matcher.group(elementBits)) & 1) != 0;\r
+               allowsOut = (Integer.parseInt(matcher.group(elementBits)) & 1<<1) != 0;\r
+               inputOutput = (Integer.parseInt(matcher.group(elementBits)) & 1<<3) != 0;\r
+               textLine = (Integer.parseInt(matcher.group(elementBits)) & 1<<2) != 0;\r
+               \r
+               switch (Integer.parseInt(matcher.group(elementTextPos))) {\r
+               case 0: textPosition = TextPosition.INSIDE; break;\r
+               case 1: textPosition = TextPosition.BELOW; break;\r
+               case 2: textPosition = TextPosition.LEFT; break;\r
+               case 3: textPosition = TextPosition.ABOVE; break;\r
+               case 4: textPosition = TextPosition.RIGHT; break;\r
+               default: textPosition = TextPosition.UNSET; break;\r
+               }\r
+               \r
        }\r
 \r
        public int getX() {\r
@@ -63,43 +93,6 @@ public abstract class SketchElement extends SketchObject {
                return height;\r
        }\r
        \r
-       // in vensim the coordinates refer to the center of the element with \r
-       // width and height being the distances between the center and the edges,\r
-       // whereas in sysdyn the coordinates refer to the top-left corner of the\r
-       // element\r
-       \r
-       public double getSysdyndX() {\r
-               return getSysdynLeftEdge();\r
-       }\r
-       \r
-       public double getSysdyndY() {\r
-               return getSysdynTopEdge();\r
-       }\r
-       \r
-       public double getSysdynWidth() {\r
-               return ((double)width) * 2 * SCALE_MULTIPLIER;\r
-       }\r
-       \r
-       public double getSysdynHeight() {\r
-               return ((double)height) * 2 * SCALE_MULTIPLIER;\r
-       }\r
-       \r
-       public double getSysdynTopEdge() {\r
-               return (double)(y - height) * SCALE_MULTIPLIER;\r
-       }\r
-       \r
-       public double getSysdynBottomEdge() {\r
-               return (double)(y + height) * SCALE_MULTIPLIER;\r
-       }\r
-\r
-       public double getSysdynLeftEdge() {\r
-               return (double)(x - width) * SCALE_MULTIPLIER;\r
-       }\r
-\r
-       public double getSysdynRightEdge() {\r
-               return (double)(x + width) * SCALE_MULTIPLIER;\r
-       }\r
-       \r
        public boolean isAttached() {\r
                return attached;\r
        }\r
@@ -119,6 +112,10 @@ public abstract class SketchElement extends SketchObject {
        public boolean hasTextLine() {\r
                return textLine;\r
        }\r
+       \r
+       public TextPosition getTextPosition() {\r
+               return textPosition;\r
+       }\r
 \r
        public abstract Symbol getSymbol(MdlModel mdl, Sketch sketch);\r
        \r
index 62eba88089b30a583ec31683831505f4da941409..8bf5105509c5ef1cd19839536d984dbda1b9a177 100644 (file)
@@ -7,7 +7,7 @@ public abstract class SketchObject {
        private int id;\r
        private IWriteableObject modelObject;\r
        \r
-       public SketchObject(int id) {\r
+       protected SketchObject(int id) {\r
                this.id = id;\r
        }\r
        \r
@@ -22,5 +22,5 @@ public abstract class SketchObject {
        public IWriteableObject getModelObject() {\r
                return modelObject;\r
        }\r
-       \r
+\r
 }\r
index fb4c613534a36cf3a3bfbb40cb820f92339878b2..1a27e8739351004d081c6173cbfe6637560fc9d4 100644 (file)
@@ -1,43 +1,56 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
-import org.simantics.sysdyn.modelImport.MdlUtil;\r
-import org.simantics.sysdyn.modelImport.model.IWriteableObject;\r
-import org.simantics.sysdyn.modelImport.model.element.ModelVariable;\r
-import org.simantics.sysdyn.modelImport.model.element.Symbol;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
 import org.simantics.sysdyn.modelImport.model.element.Valve;\r
 import org.simantics.sysdyn.modelImport.model.element.Valve.Orientation;\r
-import org.simantics.sysdyn.modelImport.model.element.Valve.TextPosition;\r
 \r
 public class SketchValve extends SketchElement {\r
        \r
-       private SketchVariable variable;\r
-       private TextPosition textPosition;\r
+       private static final String SKETCH_VALVE =\r
+                       "11,"+KEEP_I+SKIP_I+"("+ELEMENT_SUFFIX+")";\r
+       private static final int valveId = 1;\r
+       private static final int valveSuffix = 2;\r
+       \r
+       private SketchVariable attached;\r
        \r
-       public SketchValve(int id, TextPosition textPosition) {\r
+       protected SketchValve(int id) {\r
                super(id);\r
-               this.textPosition = textPosition;\r
        }\r
-\r
-       public SketchVariable getAttachedVariable() {\r
-               return variable;\r
+       \r
+       public static SketchValve getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SKETCH_VALVE).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       return null;\r
+               }\r
+               \r
+               int id = Integer.parseInt(matcher.group(valveId));\r
+               \r
+               SketchValve element = new SketchValve(id);\r
+               element.parseSuffix(matcher.group(valveSuffix));\r
+               return element;\r
        }\r
 \r
-       public void setAttachedVariable(SketchVariable variable) {\r
-               this.variable = variable;\r
+       public SketchVariable getAttached() {\r
+               return attached;\r
        }\r
-       \r
-       public TextPosition getTextPosition() {\r
-               return textPosition;\r
+\r
+       public void setAttached(SketchVariable attached) {\r
+               this.attached = attached;\r
        }\r
        \r
        @Override\r
        public Valve getSymbol(MdlModel mdl, Sketch sketch) {\r
-               Valve valve = new Valve(Orientation.HORIZONTAL, textPosition);\r
+               Variable variable = mdl.getVariable(attached.getName());\r
+               if (variable == null) {\r
+                       return null;\r
+               }\r
                \r
-               variable.getVariable().initializeModelVariable(valve, mdl);\r
-               valve.setDimensions(getDimensions(sketch));\r
+               Valve valve = new Valve(Orientation.HORIZONTAL, getTextPosition());\r
                \r
-               return valve;\r
+               return variable.setUpModelVariable(valve, getDimensions(), mdl);\r
        }\r
 \r
 }\r
index b73afe7618af12a44c1ce3db21c23e3476d6faae..5137203e2bf9d58a467452d1d1a0267f9a71a661 100644 (file)
@@ -1,5 +1,8 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
 import org.simantics.sysdyn.modelImport.MdlUtil;\r
 import org.simantics.sysdyn.modelImport.model.element.Auxiliary;\r
 import org.simantics.sysdyn.modelImport.model.element.ModelVariable;\r
@@ -9,30 +12,53 @@ import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression;
 \r
 public class SketchVariable extends SketchElement {\r
        \r
-       private Variable variable;\r
+       private static final String SKETCH_VARIABLE =\r
+                       "10,"+KEEP_I+MdlUtil.VARIABLE+",("+ELEMENT_SUFFIX+")";\r
+       private static final int variableId = 1;\r
+       private static final int variableName = 2;\r
+       private static final int variableSuffix = 3;\r
+       \r
+       private String name;\r
 \r
-       public SketchVariable(int id, Variable variable) {\r
+       protected SketchVariable(int id, String name) {\r
                super(id);\r
-               this.variable = variable;\r
+               this.name = name;\r
+       }\r
+       \r
+       public static SketchVariable getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SKETCH_VARIABLE).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       return null;\r
+               }\r
+               \r
+               int id = Integer.parseInt(matcher.group(variableId));\r
+               String name = MdlUtil.normalize(matcher.group(variableName));\r
+               \r
+               SketchVariable element = new SketchVariable(id, name);\r
+               element.parseSuffix(matcher.group(variableSuffix));\r
+               return element;\r
        }\r
        \r
-       public Variable getVariable() {\r
-               return variable;\r
+       public String getName() {\r
+               return name;\r
        }\r
        \r
        @Override\r
-       public Symbol getSymbol(MdlModel mdl, Sketch sketch) {\r
+       public ModelVariable getSymbol(MdlModel mdl, Sketch sketch) {\r
+               Variable variable = mdl.getVariable(name);\r
+               if (variable == null) {\r
+                       return null;\r
+               }\r
+               \r
                ModelVariable var;\r
                \r
-               if (variable.getModelExpression(mdl) instanceof IntegralExpression)\r
+               if (variable.getExpressionString() != null && variable.getExpressionString().startsWith("INTEG"))\r
                        var = new Stock();\r
                else\r
                        var = new Auxiliary();\r
                \r
-               variable.initializeModelVariable(var, mdl);\r
-               var.setDimensions(getDimensions(sketch));\r
-               \r
-               return var;\r
+               return variable.setUpModelVariable(var, getDimensions(sketch), mdl);\r
        }\r
        \r
 }
\ No newline at end of file
index 587d9428b0f2271ec71c4248ac58a9aa8b23a612..820a608ffccd60f29c3d2eae66bd275b1f17e433 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.sysdyn.modelImport.mdl;
 \r
 import java.util.Arrays;\r
 import java.util.HashSet;\r
+import java.util.List;\r
 import java.util.Set;\r
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
@@ -9,29 +10,35 @@ import java.util.regex.Pattern;
 import org.simantics.sysdyn.modelImport.MdlUtil;\r
 import org.simantics.sysdyn.modelImport.model.support.Enumeration;\r
 \r
-public class Subscript  {\r
+public class Subscript extends Declaration {\r
        \r
-       // tODO: might need some rework\r
-       private static final String subscriptPattern = \r
-                       "([A-Za-z]\\w*)\\s*(:|<->)\\s*([^~]*?)\\s*~\\s*~\\s*\\|";\r
+       private static final String SUBSCRIPT_DECL = \r
+                       "("+MdlUtil.BASIC_NAME+")\\s*(:|<->)\\s*([^~]*?)("+DECL_SUFFIX+")";\r
        private static final int subscriptName = 1;\r
        private static final int subscriptType = 2;\r
        private static final int subscriptExpression = 3;\r
+       private static final int subscriptSuffix = 4;\r
        \r
-       private String name;\r
-       private Set<String> values;\r
-       \r
-       private Subscript superSet;\r
+       private String original;\r
+       private List<String> values;\r
        \r
        private Enumeration enumeration;\r
        \r
-       public Subscript(String name, Set<String>values) {\r
-               this.name = name;\r
+       protected Subscript(String name, List<String> values) {\r
+               super(name);\r
+               this.original = null;\r
                this.values = values;\r
        }\r
        \r
-       public static Subscript getPossibleSubscript(String line, MdlModel mdl) {\r
-               Matcher matcher = Pattern.compile(subscriptPattern).matcher(line);              \r
+       protected Subscript(String name, String original) {\r
+               super(name);\r
+               this.original = original;\r
+               this.values = null;\r
+       }\r
+       \r
+       public static Subscript getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SUBSCRIPT_DECL).matcher(line);                \r
                if (!matcher.matches())\r
                        return null;\r
                \r
@@ -39,58 +46,36 @@ public class Subscript  {
                boolean equivalent = matcher.group(subscriptType).equals("<->");\r
                String expression = MdlUtil.normalize(matcher.group(subscriptExpression));\r
                \r
-               if (equivalent) {\r
-                       Subscript parent = mdl.getSubscript(expression);\r
-                       if (parent == null) {\r
-                               System.err.println("equivalent subscript not found for "+name);\r
-                               return null;\r
-                       }\r
-                       return new Subscript(name, parent.getValues());\r
-               }\r
-               else {\r
-                       return new Subscript(name, new HashSet<String>(Arrays.asList(expression.split(","))));\r
-               }\r
-       }\r
-       \r
-       public String getName() {\r
-               return name;\r
+               Subscript subscript;\r
+               if (equivalent)\r
+                       subscript = new Subscript(name, expression);\r
+               else\r
+                       subscript = new Subscript(name, Arrays.asList(expression.split(",")));\r
+               subscript.parseSuffix(matcher.group(subscriptSuffix));\r
+               return subscript;\r
        }\r
        \r
-       public Set<String> getValues() {\r
-               return values;\r
+       public String getOriginal() {\r
+               return original;\r
        }\r
        \r
-       public Subscript getSuperSet() {\r
-               return superSet;\r
+       public List<String> getValues(MdlModel mdl) {\r
+               if (values != null)\r
+                       return values;\r
+               else\r
+                       return mdl.getSubscript(original).getValues(mdl);\r
        }\r
        \r
-       public void setSuperSet(Subscript superSet) {\r
-               this.superSet = superSet;\r
+       public boolean isEquivalent() {\r
+               return original != null;\r
        }\r
        \r
-       public boolean isSuperSet() {\r
-               return superSet == null;\r
-       }\r
-       \r
-       public String getRepresentation() {\r
-               StringBuilder buffer = new StringBuilder();\r
-               buffer.append('{');\r
-               for (String value : values) {\r
-                       if (buffer.length() > 1) {\r
-                               buffer.append(',');\r
-                       }\r
-                       buffer.append(value);\r
+       public Enumeration getEnumeration(MdlModel mdl) {\r
+               if (enumeration == null) {\r
+                       enumeration = new Enumeration(getName(), getValues(mdl));\r
                }\r
-               buffer.append('}');\r
-               return buffer.toString();\r
-       }\r
-       \r
-       public void setEnumeration(Enumeration enumeration) {\r
-               this.enumeration = enumeration;\r
-       }\r
-       \r
-       public Enumeration getEnumeration() {\r
-               return enumeration != null ? enumeration : superSet.getEnumeration();\r
+               \r
+               return enumeration;\r
        }\r
 \r
 }\r
index 78b18675f4ccf065575b6ef76ce4f32bc58a226f..bed7ca725bd319ba72252f5549f6b21d58e32adb 100644 (file)
@@ -1,6 +1,9 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
+import java.util.ArrayDeque;\r
 import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Deque;\r
 import java.util.HashSet;\r
 import java.util.List;\r
 import java.util.Set;\r
@@ -9,60 +12,59 @@ import java.util.regex.Pattern;
 \r
 import org.simantics.sysdyn.modelImport.MdlUtil;\r
 import org.simantics.sysdyn.modelImport.model.expression.EnumerationExpression;\r
-import org.simantics.sysdyn.modelImport.model.expression.Expression;\r
 import org.simantics.sysdyn.modelImport.model.support.Enumeration;\r
 \r
 public class SubscriptVariable extends Variable {\r
        \r
        // a subscript variable is a variable that has a different equation\r
        // depending on the value of the subscript it references\r
-       private static final String SUBSCRIPT_VARIABLE =\r
-                       "("+VARIABLE_SIMPLE+")\\[("+VARIABLE_SIMPLE+"(?:,"+VARIABLE_SIMPLE+")*)\\]";\r
-       \r
-       public static final String subscriptVariablePattern = \r
-                       SUBSCRIPT_VARIABLE+EXPRESSION+DELIM+UNIT+DELIM+DESCRIPTION+END;\r
+       private static final String SUBSCRIPT_VARIABLE_DECL = \r
+                       MdlUtil.SUBSCRIPT+EXPRESSION+"("+DECL_SUFFIX+")";;\r
        private static final int subscriptVariableName = 1;\r
        private static final int subscriptVariableIndices = 2;\r
        private static final int subscriptVariableExpression = 3;\r
-       private static final int subscriptVariableUnit = 4;\r
-       private static final int subscriptVariableDesc = 5;\r
+       private static final int subscriptVariableSuffix = 4;\r
 \r
-       private String[] subscript;\r
+       private String[] indices;\r
        private SubscriptVariable next;\r
        \r
-       public SubscriptVariable(String name, String expression, String unit, String description, String[] subscript) {\r
-               super(name, expression, unit, description);\r
-               this.subscript = subscript;\r
+       protected SubscriptVariable(String name, String expression, String[] indices) {\r
+               super(name, expression);\r
+               this.indices = indices;\r
                this.next = null;\r
        }\r
        \r
-       public static SubscriptVariable getPossibleSubscriptVariable(String line) {\r
-               Matcher matcher = Pattern.compile(subscriptVariablePattern).matcher(line);\r
-               if (!matcher.matches())\r
+       public static SubscriptVariable getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(SUBSCRIPT_VARIABLE_DECL).matcher(line);\r
+               if (!matcher.matches()) {\r
                        return null;\r
+               }\r
                \r
                String name = MdlUtil.normalize(matcher.group(subscriptVariableName));\r
-               String[] subscript = MdlUtil.normalize(matcher.group(subscriptVariableIndices)).split(",");\r
-               String expression = MdlUtil.normalize(matcher.group(subscriptVariableExpression));\r
-               String unit = matcher.group(subscriptVariableUnit);\r
-               String desc = matcher.group(subscriptVariableDesc);\r
+               String[] indices = MdlUtil.normalize(matcher.group(subscriptVariableIndices)).split(",");\r
+               String expression = matcher.group(subscriptVariableExpression);\r
+               if (expression != null)\r
+                       expression = MdlUtil.normalize(expression);\r
                \r
-               return new SubscriptVariable(name, expression, unit, desc, subscript);\r
+               SubscriptVariable subVar = new SubscriptVariable(name, expression, indices);\r
+               subVar.parseSuffix(matcher.group(subscriptVariableSuffix));\r
+               return subVar;\r
        }\r
        \r
-       public String[] getSubscript() {\r
-               return subscript;\r
+       public String[] getIndices() {\r
+               return indices;\r
        }\r
        \r
-       public SubscriptVariable getNext() {\r
+       private SubscriptVariable getNext() {\r
                return next;\r
        }\r
        \r
-       public void setNext(SubscriptVariable next) {\r
+       private void setNext(SubscriptVariable next) {\r
                this.next = next;\r
        }\r
        \r
-       public void addLast(SubscriptVariable variable) {\r
+       public void addSubscriptVariable(SubscriptVariable variable) {\r
                // find the last variable in the list and add the new variable after it\r
                SubscriptVariable last = this;\r
                while (last.getNext() != null)\r
@@ -71,57 +73,94 @@ public class SubscriptVariable extends Variable {
        }\r
        \r
        @Override\r
-       public EnumerationExpression getModelExpression(MdlModel mdl) {\r
+       public EnumerationExpression getExpression(MdlModel mdl) {\r
                SubscriptVariable var;\r
-               // combine the list of subscript expressions into an enumeration \r
-               // expression\r
                \r
-               List<Set<String>> indices = new ArrayList<Set<String>>();\r
-               for (int i = 0; i < subscript.length; i++) {\r
-                       indices.add(new HashSet<String>());\r
+               // find out what subscripts the combined expression uses by collecting\r
+               // all subscript indices from individual expressions into a list of\r
+               // sets (one set for each "position" in the indices)\r
+               \r
+               List<Set<String>> subscripts = new ArrayList<Set<String>>();\r
+               for (int i = 0; i < indices.length; i++) {\r
+                       subscripts.add(new HashSet<String>());\r
                }\r
                \r
                var = this;\r
                while (var != null) {\r
-                       for (int i = 0; i < var.getSubscript().length; i++) {\r
-                               indices.get(i).add(var.getSubscript()[i]);\r
+                       for (int i = 0; i < var.getIndices().length; i++) {\r
+                               subscripts.get(i).add(var.getIndices()[i]);\r
                        }\r
                        \r
                        var = var.getNext();\r
                }\r
                \r
+               // turn the aforementioned list of sets into a list of enumeration\r
+               // by finding the enumerations that correspond to the sets of subscript\r
+               // indices\r
+               \r
                List<Enumeration> enumerations = new ArrayList<Enumeration>();\r
-               for (Set<String> values : indices) {\r
-                       if (mdl.resolveSubscript(values) == null) {\r
-                               System.err.print("subscript not found for value set:");\r
-                               for (String s : values)\r
-                                       System.err.print(" "+s);\r
+               for (Set<String> values : subscripts) {\r
+                       Subscript potential = mdl.resolveSubscript(values);\r
+                       if (potential == null) {\r
+                               System.err.println("subscript indices could not be resolved ");\r
+                               for (String value : values) {\r
+                                       System.err.println("  "+value);\r
+                               }\r
                                System.err.println();\r
                        }\r
-                       enumerations.add(mdl.resolveSubscript(values).getEnumeration());\r
+                       enumerations.add(potential.getEnumeration(mdl));\r
                }\r
                \r
                EnumerationExpression expr = new EnumerationExpression(enumerations);\r
                \r
+               // populate the created expression (this is very complicated)\r
+               \r
+               System.err.println("populate subscripts for variable "+getName());\r
+               \r
                var = this;\r
                while (var != null) {\r
-                       String[] array = new String[var.getSubscript().length];\r
-                       for (int i = 0; i < var.getSubscript().length; i++) {\r
-                               String value = var.getSubscript()[i];\r
-                               Subscript script = mdl.getSubscript(value);\r
-                               if (script == null || script.getValues().equals(enumerations.get(i).getValues())) {\r
-                                       array[i] = value;\r
-                               }\r
-                               else {\r
-                                       array[i] = script.getRepresentation();\r
+                       \r
+                       Deque<WorkExpression> workqueue = new ArrayDeque<WorkExpression>();\r
+                       workqueue.add(new WorkExpression(var.getIndices(), var.getExpressionString()));\r
+                       \r
+                       for (int i = 0; i < var.getIndices().length; i++) {\r
+                               int limit = workqueue.size();\r
+                               for (int j = 0; j < limit; j++) {\r
+                                       WorkExpression current = workqueue.pollFirst();\r
+                                       Subscript potential = mdl.getSubscript(current.indices[i]);\r
+                                       if (potential != null) {\r
+                                               for (String value : potential.getValues(mdl)) {\r
+                                                       String[] newindices = Arrays.copyOf(current.indices, current.indices.length);\r
+                                                       newindices[i] = value;\r
+                                                       String newexpression = current.expression;\r
+                                                       newexpression = MdlUtil.replaceSubscripts(newexpression, potential.getName(), value);\r
+                                                       workqueue.addLast(new WorkExpression(newindices, newexpression));\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               workqueue.addLast(current);\r
+                                       }\r
                                }\r
                        }\r
-                       expr.addExpression(super.getModelExpression(mdl), array);\r
+                       \r
+                       for (WorkExpression we : workqueue) {\r
+                               expr.addExpression(parseExpression(MdlUtil.expandIterations(we.expression, mdl)), we.indices);\r
+                       }\r
                        \r
                        var = var.getNext();\r
                }\r
                \r
                return expr;\r
        }\r
+       \r
+       private class WorkExpression {\r
+               String[] indices;\r
+               String expression;\r
+               \r
+               private WorkExpression(String[] indices, String expression) {\r
+                       this.indices = indices;\r
+                       this.expression = expression;\r
+               }\r
+       }\r
 \r
 }\r
index bbfc849c1bccf109290209af6d35ecb0900d7055..f93e707526a3fe50de1e9e0a94836e8dba8b527b 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.sysdyn.modelImport.mdl;\r
 \r
+import java.util.ArrayList;\r
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
@@ -11,110 +12,81 @@ import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression;
 import org.simantics.sysdyn.modelImport.model.expression.NormalExpression;\r
 import org.simantics.sysdyn.modelImport.model.support.Range;\r
 \r
-public class Variable {\r
+public class Variable extends Declaration {\r
        \r
-       protected static final String NUMBER = "-?\\d+(?:\\.\\d+)?";\r
-       protected static final String DELIM = "\\s*~\\s*";\r
-       protected static final String END = "\\s*\\|";\r
-       \r
-       // a Vensim variable name is either a plain string that contains letters, \r
-       // numbers and whitespace, or a quoted string that can also contain any \r
-       // special characters (including other quotation marks that must be escaped)\r
-       protected static final String VARIABLE_QUOTED =\r
-                       "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"";\r
-       protected static final String VARIABLE_SIMPLE =\r
-                       "[A-Za-z](?![ \\w]*\\()(?: *\\w+)*";\r
-       \r
-       protected static final String NORMAL_VARIABLE =\r
-                       "("+VARIABLE_QUOTED+"|"+VARIABLE_SIMPLE+")";\r
-       // the expression does not necessarily exist\r
        protected static final String EXPRESSION =\r
-                       "(?:\\s*=\\s*([^~]*?(?:"+VARIABLE_QUOTED+"[^~]*?)*))?";\r
-       protected static final String UNIT =\r
-                       "([^~]*?)";\r
-       protected static final String DESCRIPTION =\r
-                       "([^\\|]*?)";\r
+                       "(?:\\s*=\\s*([^~]*?(?:"+MdlUtil.SPECIAL_NAME+"[^~]*?)*))?";\r
        \r
-       private static final String variablePattern = \r
-                       NORMAL_VARIABLE+EXPRESSION+DELIM+UNIT+DELIM+DESCRIPTION+END;\r
+       private static final String VARIABLE_DECL =\r
+                       MdlUtil.VARIABLE+EXPRESSION+"("+DECL_SUFFIX+")";\r
        private static final int variableName = 1;\r
        private static final int variableExpression = 2;\r
-       private static final int variableUnit = 3;\r
-       private static final int variableDesc = 4;\r
+       private static final int variableSuffix = 3;\r
        \r
-       private String name;\r
        private String expression;\r
-       private String unit;\r
-       private String description;\r
        \r
-       public Variable(String name, String expression, String unit, String description) {\r
-               this.name = name;\r
+       protected Variable(String name, String expression) {\r
+               super(name);\r
                this.expression = expression;\r
-               this.unit = unit;\r
-               this.description = description;\r
        }\r
        \r
-       public static Variable getPossibleVariable(String line) {\r
-               Matcher matcher = Pattern.compile(variablePattern).matcher(line);\r
-               if (!matcher.matches())\r
+       public static Variable getPossible(String line) \r
+                       throws Exception {\r
+               Matcher matcher = Pattern.compile(VARIABLE_DECL).matcher(line);\r
+               if (!matcher.matches()) {\r
                        return null;\r
+               }\r
                \r
                String name = MdlUtil.normalize(matcher.group(variableName));\r
                String expression = matcher.group(variableExpression);\r
-               if (expression != null) {\r
+               if (expression != null)\r
                        expression = MdlUtil.normalize(expression);\r
-               }\r
-               String unit = matcher.group(variableUnit);\r
-               String desc = matcher.group(variableDesc);\r
                \r
-               return new Variable(name, expression, unit, desc);\r
+               Variable var = new Variable(name, expression);\r
+               var.parseSuffix(matcher.group(variableSuffix));\r
+               return var;\r
        }\r
        \r
-       public String getName() {\r
-               return name;\r
-       }\r
-       \r
-       public String getExpression() {\r
+       public String getExpressionString() {\r
                return expression;\r
        }\r
-\r
-       public String getUnit() {\r
-               return unit;\r
-       }\r
-\r
-       public String getDescription() {\r
-               return description;\r
-       }\r
        \r
-       public void initializeModelVariable(ModelVariable variable, MdlModel mdl) {\r
+       public <T extends ModelVariable> T setUpModelVariable(T variable, \r
+                       double[] dimensions, MdlModel mdl) {\r
                variable.setName(getName());\r
-               variable.setExpression(getModelExpression(mdl));\r
+               if (expression != null)\r
+                       variable.setExpression(getExpression(mdl));\r
                \r
                String unit = getUnit();\r
                Range range = parseRange(unit);\r
                if (range != null)\r
                        unit = unit.substring(0, unit.indexOf('[')).trim();\r
-               variable.setUnit(unit);\r
-               variable.setRange(range);\r
                \r
+               variable.setUnit(unit);\r
+               if (range != null)\r
+                       variable.setRange(range);\r
                variable.setDescription(getDescription());\r
+               \r
+               variable.setDimensions(dimensions);\r
+               \r
+               return variable;\r
        }\r
        \r
-       public Expression getModelExpression(MdlModel mdl) {\r
-               if (expression == null) {\r
-                       // if the expression has not been defined, return an empty expression\r
-                       return new NormalExpression("");\r
-               }\r
-\r
-               // the type of the returned expression object depends on the expression\r
-               Matcher matcher = Pattern.compile("([A-Za-z](?: *\\w+)*)\\s*\\((.*)\\)").matcher(expression);\r
+       public Expression getExpression(MdlModel mdl) {\r
+               return parseExpression(MdlUtil.expandIterations(expression, mdl));\r
+       }\r
+       \r
+       protected static Expression parseExpression(String expression) {\r
+               Matcher matcher = Pattern.compile(\r
+                       MdlUtil.FUNCTION+"(.*)\\)"\r
+                               ).matcher(expression);\r
                if (!matcher.matches()) {\r
                        // the expression is not one of the special function calls\r
-                       return new NormalExpression(MdlUtil.normalize(expression));\r
+                       return new NormalExpression(expression);\r
                }\r
                \r
                String function = matcher.group(1);\r
-               String[] parameters = MdlUtil.splitParameters(matcher.group(2));\r
+               String[] parameters = MdlUtil.splitFunctionParameters(matcher.group(2));\r
                \r
                if (function.startsWith("INTEG")) {\r
                        // an integral expression\r
@@ -122,9 +94,7 @@ public class Variable {
                                System.err.println("malformed integral expression: "+expression);\r
                                return null;\r
                        }\r
-                       String integral = MdlUtil.normalize(parameters[0]);\r
-                       String initial = MdlUtil.normalize(parameters[1]);\r
-                       return new IntegralExpression(integral, initial);\r
+                       return new IntegralExpression(parameters[0], parameters[1]);\r
                }\r
                else if (function.startsWith("DELAY N")) {\r
                        // a delay expression\r
@@ -132,11 +102,7 @@ public class Variable {
                                System.err.println("malformed delay expression: "+expression);\r
                                return null;\r
                        }\r
-                       String expr = MdlUtil.normalize(parameters[0]);\r
-                       String time = MdlUtil.normalize(parameters[1]);\r
-                       String initial = MdlUtil.normalize(parameters[2]);\r
-                       int degree = Integer.parseInt(parameters[3]);\r
-                       return new DelayExpression(expr, time, initial, degree);\r
+                       return new DelayExpression(parameters[0], parameters[1], parameters[2], Integer.parseInt(parameters[3]));\r
                }\r
                else if (function.startsWith("GAME")) {\r
                        // a game expression, currently treated as a normal expression\r
@@ -144,15 +110,17 @@ public class Variable {
                                System.err.println("malformed game expression: "+expression);\r
                                return null;\r
                        }\r
-                       return new NormalExpression(MdlUtil.normalize(parameters[0]));\r
+                       return new NormalExpression(parameters[0]);\r
                }\r
                else {\r
-                       return new NormalExpression(MdlUtil.normalize(expression));\r
+                       return new NormalExpression(expression);\r
                }\r
        }\r
        \r
        private static Range parseRange(String unit) {\r
-               Matcher matcher = Pattern.compile("\\[("+NUMBER+"),(\\?|("+NUMBER+")|("+NUMBER+"),("+NUMBER+"))\\]").matcher(unit);\r
+               Matcher matcher = Pattern.compile(\r
+                       "\\["+MdlUtil.DBL_G+",(\\?|"+MdlUtil.DBL_G+"|"+MdlUtil.DBL_G+","+MdlUtil.DBL_G+")\\]"\r
+                               ).matcher(unit);\r
                if (matcher.find()) {\r
                        Double start, end, step;\r
                        start = Double.parseDouble(matcher.group(1));\r
index a0727b8810502ffe7e262411c35ad39f0ccb2761..38bde81be22f86dc4a9b8d587552a5f10d9c2460 100644 (file)
@@ -29,6 +29,7 @@ import org.simantics.sysdyn.modelImport.model.element.Symbol;
 import org.simantics.sysdyn.modelImport.model.element.ModelVariable;\r
 import org.simantics.sysdyn.modelImport.model.element.Shadow;\r
 import org.simantics.sysdyn.modelImport.model.support.Enumeration;\r
+import org.simantics.sysdyn.modelImport.model.support.Function;\r
 import org.simantics.sysdyn.utils.ModelUtils;\r
 \r
 public class Model implements IWriteableObject {\r
@@ -40,6 +41,7 @@ public class Model implements IWriteableObject {
        // the structure of the model\r
        private HashMap<String, ModelVariable> variables;\r
        private HashMap<String, Enumeration> enumerations;\r
+       private HashMap<String, Function> functions;\r
        \r
        private ArrayList<Symbol> symbols;\r
        private ArrayList<Shadow> shadows;\r
@@ -52,6 +54,7 @@ public class Model implements IWriteableObject {
                \r
                variables = new HashMap<String, ModelVariable>();\r
                enumerations = new HashMap<String, Enumeration>();\r
+               functions = new HashMap<String, Function>();\r
                \r
                symbols = new ArrayList<Symbol>();\r
                shadows = new ArrayList<Shadow>();\r
@@ -82,12 +85,14 @@ public class Model implements IWriteableObject {
                this.step = step;\r
        }\r
        \r
-       public Enumeration getEnumeration(String name) {\r
-               return enumerations.get(name);\r
-       }\r
-       \r
-       public Collection<Enumeration> getEnumerations() {\r
-               return enumerations.values();\r
+       public void addSymbol(ModelVariable variable) {\r
+               if (variables.get(variable.getName()) != null) {\r
+                       System.err.println("variable "+variable.getName()+" already defined");\r
+               }\r
+               \r
+               variables.put(variable.getName(), variable);\r
+               \r
+               symbols.add(variable);\r
        }\r
        \r
        public ModelVariable getVariable(String name) {\r
@@ -98,17 +103,6 @@ public class Model implements IWriteableObject {
                return variables.values();\r
        }\r
        \r
-       public void addSymbol(ModelVariable variable) {\r
-               if (variables.get(variable.getName()) != null) {\r
-                       System.err.println("variable "+variable.getName()+" already defined");\r
-               }\r
-               variables.put(variable.getName(), variable);\r
-               \r
-               System.err.println("variable added "+variable.getName());\r
-               \r
-               symbols.add(variable);\r
-       }\r
-       \r
        public void addSymbol(Shadow shadow) {\r
                shadows.add(shadow);\r
        }\r
@@ -128,6 +122,29 @@ public class Model implements IWriteableObject {
                }\r
                enumerations.put(enumeration.getName(), enumeration);\r
        }\r
+       \r
+       public Enumeration getEnumeration(String name) {\r
+               return enumerations.get(name);\r
+       }\r
+       \r
+       public Collection<Enumeration> getEnumerations() {\r
+               return enumerations.values();\r
+       }\r
+       \r
+       public void addFunction(Function function) {\r
+               if (functions.get(function.getName()) != null) {\r
+                       System.err.println("function "+function.getName()+" already defined");\r
+               }\r
+               functions.put(function.getName(), function);\r
+       }\r
+       \r
+       public Function getEFunction(String name) {\r
+               return functions.get(name);\r
+       }\r
+       \r
+       public Collection<Function> getFunctions() {\r
+               return functions.values();\r
+       }\r
 \r
        @Override\r
        public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException {\r
@@ -147,6 +164,10 @@ public class Model implements IWriteableObject {
                        e.write(graph, configuration, context);\r
                }\r
                \r
+               for (Function f : getFunctions()) {\r
+                       f.write(graph, configuration, context);\r
+               }\r
+               \r
                for (Symbol e : symbols) {\r
                        e.write(graph, configuration, context);\r
                }\r
index 4b08a6712fbe8ea8e41755c584efa1f94a8bf04b..00d99797934ab3273afbb29060e3c694c42884c1 100644 (file)
@@ -18,36 +18,24 @@ import org.simantics.sysdyn.modelImport.model.support.Enumeration;
 public class EnumerationExpression extends Expression {\r
        \r
        private List<Enumeration> enumerations;\r
-       private List<SubscriptSubExpression> subExpressions;\r
+       private List<EnumerationSubExpression> subExpressions;\r
        \r
        public EnumerationExpression(List<Enumeration> enumerations) {\r
                this.enumerations = enumerations;\r
-               this.subExpressions = new ArrayList<SubscriptSubExpression>();\r
-               \r
-               System.err.print("create enumeration expression for ");\r
-               for (Enumeration e : enumerations) {\r
-                       System.err.print(e.getName()+" ");\r
-               }\r
-               System.err.println();\r
+               this.subExpressions = new ArrayList<EnumerationSubExpression>();\r
        }\r
        \r
        public void addExpression(Expression expression, String...indices) {\r
-               System.err.print("  add expression for indices ");\r
-               for (String s : indices) {\r
-                       System.err.print(s+" ");\r
-               }\r
-               System.err.println();\r
-               \r
 //             for (int i = 0; i < indices.length; i++) {\r
 //                     if (!enumerations.get(i).getValues().contains(indices)) {\r
 //                             System.err.println("tried adding an enumeration expression with incorrect indices");\r
 //                             return;\r
 //                     }\r
 //             }\r
-               subExpressions.add(new SubscriptSubExpression(expression, indices));\r
+               subExpressions.add(new EnumerationSubExpression(expression, indices));\r
        }\r
        \r
-       public List<SubscriptSubExpression> getExpressions() {\r
+       public List<EnumerationSubExpression> getExpressions() {\r
                return subExpressions;\r
        }\r
        \r
@@ -55,7 +43,7 @@ public class EnumerationExpression extends Expression {
        public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException {\r
                SysdynResource sr = SysdynResource.getInstance(graph);\r
                \r
-               for (SubscriptSubExpression subexpr : subExpressions) {\r
+               for (EnumerationSubExpression subexpr : subExpressions) {\r
                        StringBuilder range = new StringBuilder();\r
                        range.append('[');\r
                        for (int i = 0; i < subexpr.indices.length; i++) {\r
@@ -83,12 +71,12 @@ public class EnumerationExpression extends Expression {
                return getResource();\r
        }\r
        \r
-       private class SubscriptSubExpression {\r
+       private class EnumerationSubExpression {\r
                \r
                Expression expression;\r
                String[] indices;\r
                \r
-               public SubscriptSubExpression(Expression expression, String...indices) {\r
+               public EnumerationSubExpression(Expression expression, String...indices) {\r
                        this.expression = expression;\r
                        this.indices = indices;\r
                }\r
index c94b715552149083ce7ddf895789c70e6d5fddae..f2f84ebab2c002fffc112b7ff98e77c8622d7be1 100644 (file)
@@ -10,13 +10,15 @@ import org.simantics.sysdyn.modelImport.model.WriteContext;
 \r
 public class LookupExpression extends Expression {\r
        \r
+       private String expression;\r
        private double xMin;\r
        private double yMin;\r
        private double xMax;\r
        private double yMax;\r
        private double[] points;\r
        \r
-       public LookupExpression(double xMin, double yMin, double xMax, double yMax, double[] points) {\r
+       public LookupExpression(String expression, double xMin, double yMin, double xMax, double yMax, double[] points) {\r
+               this.expression = expression;\r
                this.xMin = xMin;\r
                this.yMin = yMin;\r
                this.xMax = xMax;\r
@@ -40,7 +42,7 @@ public class LookupExpression extends Expression {
                Resource expr = super.write(graph, parent, context);\r
                \r
                // TODO: fix this\r
-               graph.claimLiteral(expr, sr.WithLookupExpression_expression, "", Bindings.STRING);\r
+               graph.claimLiteral(expr, sr.WithLookupExpression_expression, expression, Bindings.STRING);\r
                graph.claimLiteral(expr, sr.WithLookupExpression_lookup, lookup.toString(), Bindings.STRING);\r
                graph.claimLiteral(expr, sr.WithLookupExpression_minX, xMin, Bindings.DOUBLE);\r
                graph.claimLiteral(expr, sr.WithLookupExpression_minY, yMin, Bindings.DOUBLE);\r
index 8b571f815c99bc6dfe80a31d3e2caff1b61b240a..5ea53010fe417aa578688f2604693e4a44698604 100644 (file)
@@ -1,6 +1,8 @@
 package org.simantics.sysdyn.modelImport.model.support;\r
 \r
+import java.util.ArrayList;\r
 import java.util.HashSet;\r
+import java.util.List;\r
 import java.util.Set;\r
 \r
 import org.simantics.db.Resource;\r
@@ -16,11 +18,11 @@ import org.simantics.sysdyn.modelImport.model.WriteContext;
 public class Enumeration implements IWriteableObject {\r
        \r
        private String name;\r
-       private Set<String> values;\r
+       private List<String> values;\r
        \r
        private Resource enumeration;\r
        \r
-       public Enumeration(String name, Set<String> values) {\r
+       public Enumeration(String name, List<String> values) {\r
                this.name = name;\r
                this.values = values;\r
        }\r
@@ -29,7 +31,7 @@ public class Enumeration implements IWriteableObject {
                return name;\r
        }\r
        \r
-       public Set<String> getValues() {\r
+       public List<String> getValues() {\r
                return values;\r
        }\r
 \r
@@ -43,7 +45,7 @@ public class Enumeration implements IWriteableObject {
                                l0.HasName, name,\r
                                l0.PartOf, parent);\r
                \r
-               Set<Resource> indices = new HashSet<Resource>();\r
+               List<Resource> indices = new ArrayList<Resource>();\r
                for (String index : values) {\r
                        indices.add(GraphUtils.create2(graph, sr.EnumerationIndex,\r
                                        l0.HasName, index));\r
diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java
new file mode 100644 (file)
index 0000000..7f086e9
--- /dev/null
@@ -0,0 +1,35 @@
+package org.simantics.sysdyn.modelImport.model.support;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.modelImport.model.IWriteableObject;\r
+import org.simantics.sysdyn.modelImport.model.WriteContext;\r
+\r
+public class Function implements IWriteableObject {\r
+\r
+       private String name;\r
+       \r
+       public Function(String name, List<String> inputs, List<String> outputs, String code) {\r
+               this.name = name;\r
+       }\r
+       \r
+       public String getName() {\r
+               return name;\r
+       }\r
+       \r
+       @Override\r
+       public Resource write(WriteGraph graph, Resource parent, WriteContext context) \r
+                       throws DatabaseException {\r
+               System.err.println("write function");\r
+               return null;\r
+       }\r
+\r
+       @Override\r
+       public Resource getResource() {\r
+               return null;\r
+       }\r
+       \r
+}\r