]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
initial version of new vensim import (does not work)
authorjkauttio <jkauttio@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Fri, 14 Feb 2014 13:36:53 +0000 (13:36 +0000)
committerjkauttio <jkauttio@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Fri, 14 Feb 2014 13:36:53 +0000 (13:36 +0000)
refs #2924

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

org.simantics.sysdyn.ui/plugin.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/imports/ImportMdlHandler.java
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlFile.java
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlParser.java
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlUtils.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Expression.java
org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/View.java

index e90bae08b3142174ba207d57f7ef630e74d89b79..4d0dfc2438b0eb00fe026f95a1fa58d1e76ab434 100644 (file)
                      checkEnabled="true">\r
                </visibleWhen>\r
             </command>\r
+            <command\r
+                  commandId="org.simantics.sysdyn.ui.importMdl"\r
+                  label="vensim import test"\r
+                  style="push">\r
+            </command>\r
          </menu>\r
          <menu\r
                id="org.simantics.export"\r
index 2ce39ec68466fffcd0fe29d97c54653c1de5e041..3ae5d14563584e3a85e71d1629ae5c12992acc4d 100644 (file)
@@ -71,7 +71,7 @@ public class ImportMdlHandler extends AbstractHandler {
                        \r
                        @Override\r
                        public void perform(WriteGraph graph) throws DatabaseException {\r
-                               model.write(graph, project);\r
+                               //model.write(graph, project);\r
                        }\r
                });\r
                \r
index 5711a759f9f1ae332e50adce0cc7561d21003896..d0811de98edaab16690edfee2225cfb80bd06325 100644 (file)
@@ -14,45 +14,55 @@ package org.simantics.sysdyn.mdlImport;
 import java.util.ArrayList;\r
 \r
 public class MdlFile {\r
-       \r
-       private ArrayList<String> variables = new ArrayList<String>();\r
-       private ArrayList<String> controls = new ArrayList<String>();\r
-       private ArrayList<String> sketchData = new ArrayList<String>();\r
-       private ArrayList<String> otherData = new ArrayList<String>();\r
-\r
-\r
 \r
-       public void addVariable(String variable) {\r
-               variables.add(variable);\r
-       }\r
+       private ArrayList<String> variableData;\r
+       private ArrayList<String> controlData;\r
+       private ArrayList<String> otherData;\r
+       private ArrayList<ArrayList<String>> sketchData;\r
+       private ArrayList<String> currentSketch;\r
        \r
-       public ArrayList<String> getVariables() {\r
-               return variables;\r
+       public MdlFile() {\r
+               variableData = new ArrayList<String>();\r
+               controlData = new ArrayList<String>();\r
+               otherData = new ArrayList<String>();\r
+               sketchData = new ArrayList<ArrayList<String>>();\r
        }\r
-       \r
-       public void addControl(String control) {\r
-               controls.add(control);\r
+\r
+       public void addVariableData(String line) {\r
+               variableData.add(line);\r
        }\r
-       \r
-       public ArrayList<String> getControls() {\r
-               return controls;\r
+\r
+       public ArrayList<String> getVariableData() {\r
+               return variableData;\r
        }\r
-       \r
-       public void addSketchData(String sketchRow) {\r
-               sketchData.add(sketchRow);\r
+\r
+       public void addControlData(String line) {\r
+               controlData.add(line);\r
        }\r
 \r
-       public ArrayList<String> getSketchData() {\r
-               return sketchData;\r
+       public ArrayList<String> getControlData() {\r
+               return controlData;\r
        }\r
 \r
-       public void addOtherData(String dataRow) {\r
-               otherData.add(dataRow);\r
+       public void addOtherData(String line) {\r
+               otherData.add(line);\r
        }\r
 \r
        public ArrayList<String> getOtherData() {\r
                return otherData;\r
        }\r
+       \r
+       public void startSketch() {\r
+               currentSketch = new ArrayList<String>();\r
+               sketchData.add(currentSketch);\r
+       }\r
 \r
+       public void addSketchData(String line) {\r
+               currentSketch.add(line);\r
+       }\r
+\r
+       public ArrayList<ArrayList<String>> getSketchData() {\r
+               return sketchData;\r
+       }\r
 \r
 }\r
index 2f68f086a63cfa6fcb4dc39632766019023b36a5..207d286f9b2b8d13cb57327723014e6b89ac5a5a 100644 (file)
@@ -21,6 +21,8 @@ import java.io.InputStreamReader;
 import java.io.Reader;\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.mdlImport.mdlElements.Auxiliary;\r
 import org.simantics.sysdyn.mdlImport.mdlElements.Cloud;\r
@@ -38,58 +40,354 @@ import org.simantics.sysdyn.mdlImport.mdlElements.Valve;
 import org.simantics.sysdyn.mdlImport.mdlElements.Variable;\r
 import org.simantics.sysdyn.mdlImport.mdlElements.View;\r
 \r
+/*\r
+ * THINGS TO FIX:\r
+ * - vensim apparently supports infix operators (:AND: instead of AND()), these must be handled\r
+ * - "public" seems to be a keyboard of some sort which causes a problem in certain variable names\r
+ * - something is seriously wrong with the sketch import\r
+ * - how should models with multiple sketches be handled (this might already work)\r
+ * - instead of splitting the file into blocks, the parser could already process the data further which would greatly simplify later methods\r
+ */\r
+\r
 public class MdlParser {\r
-       \r
+\r
+       private enum State {\r
+               VARIABLE, CONTROL, SKETCH, OTHER\r
+       }\r
+\r
        public static Model parse(File file) {\r
-               \r
+\r
                Model model = new Model();\r
-               \r
+\r
                String[] name = file.getName().split("\\.mdl");\r
                model.setName(name[0]);\r
+\r
+               MdlFile mdlFile = getMdlFile(file);\r
+\r
+               for (String variable : mdlFile.getVariableData()) {\r
+                       parseElement(variable);\r
+               }\r
+\r
+               for (ArrayList<String> sketch : mdlFile.getSketchData()) {\r
+                       parseSketch(sketch);\r
+               }\r
+\r
+               //MdlFile test = getMdlContents(file);\r
+\r
+               //getVariableData(model, test.getVariableData());\r
+\r
+               //getSketchData(model, mdlFile.getSketchData());\r
+\r
+               //getControlData(model, mdlFile.getControlData());\r
+\r
+               //getOthertData(model, mdlFile.getOtherData());\r
+\r
+               //setAllSubscripts(model);\r
+\r
+               return null;\r
+       }\r
+\r
+       private static final String UTF_8 = "{UTF-8}";\r
+       private static final String CONTROL_STR = ".Control";\r
+       private static final String SKETCH_START = "\\\\\\---///";\r
+       private static final String SKETCH_END = "///---\\\\\\";\r
+\r
+       private static MdlFile getMdlFile(File file) {\r
+               MdlFile mdl = new MdlFile();\r
+\r
+               try {\r
+                       BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));\r
+                       String line = reader.readLine();\r
+\r
+                       if (line != null && line.startsWith(UTF_8)) {\r
+                               reader.close();\r
+                               reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));\r
+                               // skip the "{UTF-8}" line\r
+                               reader.readLine();\r
+                               line = reader.readLine();\r
+                       }\r
+\r
+                       State state = State.VARIABLE;\r
+\r
+                       while (line != null) {\r
+                               line = line.trim();\r
+\r
+                               if (line.isEmpty()) {\r
+                                       line = reader.readLine();\r
+                                       continue;\r
+                               }\r
+\r
+                               switch (state) {\r
+                               case VARIABLE:\r
+                                       if (line.startsWith(SKETCH_START)) {\r
+                                               state = State.SKETCH;\r
+                                               continue;       \r
+                                       }\r
+\r
+                                       String variable = readElement(reader, line);\r
+\r
+                                       if (variable.contains(CONTROL_STR)) {\r
+                                               state = State.CONTROL;\r
+                                               break;\r
+                                       }\r
+\r
+                                       mdl.addVariableData(variable);\r
+                                       break;\r
+\r
+                               case CONTROL:\r
+                                       if (line.startsWith(SKETCH_START)) {\r
+                                               state = State.SKETCH;\r
+                                               continue;       \r
+                                       }\r
+\r
+                                       String control = readElement(reader, line);\r
+                                       mdl.addControlData(control);\r
+                                       break;\r
+\r
+\r
+                               case SKETCH:\r
+                                       if (line.startsWith(SKETCH_END)) {\r
+                                               state = State.OTHER;\r
+                                               break;\r
+                                       }\r
+\r
+                                       if (line.startsWith(SKETCH_START)) {\r
+                                               mdl.startSketch();\r
+                                               break;\r
+                                       }\r
+\r
+                                       mdl.addSketchData(line);\r
+                                       break;\r
+\r
+                               case OTHER:\r
+                                       mdl.addOtherData(line);\r
+                                       break;\r
+\r
+                               default: break; // should not get this far\r
+                               }\r
+\r
+                               line = reader.readLine();\r
+                       }\r
+\r
+                       reader.close();\r
+               }\r
+               catch (IOException e) {\r
+                       e.printStackTrace();\r
+               }\r
+\r
+               return mdl;\r
+       }\r
+\r
+       private static String readElement(BufferedReader reader, String current) \r
+                       throws IOException {\r
+               // TODO: does not support subscript stuff at all currently\r
+               StringBuilder element = new StringBuilder();\r
+\r
+               while (current != null) {\r
+                       current = current.trim().replace('\t', ' ');\r
+\r
+                       if (current.endsWith("|")) {\r
+                               element.append(current.substring(0, current.length() - 1));\r
+                               break;\r
+                       }\r
+                       else if (current.endsWith("\\")) {\r
+                               element.append(current.substring(0, current.length() - 1));\r
+                       }\r
+                       else {\r
+                               element.append(current);\r
+                       }\r
+\r
+                       current = reader.readLine();\r
+               }\r
+\r
+               return element.toString();\r
+       }\r
+\r
+       private static void parseElement(String element) {\r
+               String left, right, unit, desc;\r
+\r
+               String[] data = element.split("~");\r
+\r
+               if (data.length != 3) {\r
+                       System.err.println("INVALID ELEMENT DATA "+element);\r
+                       return;\r
+               }\r
+\r
+               String equation = sanitize(data[0]);\r
+\r
+               left = equation.substring(0, equation.indexOf('=')).trim();\r
+               right = equation.substring(equation.indexOf('=') + 1).trim();\r
+               unit = data[1].trim();\r
+               desc = data[2].trim();\r
+\r
+               //System.err.println("FOUND VARIABLE "+left);\r
+               //System.err.println("  EQUATION "+right);\r
+               //System.err.println("  UNIT "+unit);\r
+               //System.err.println("  DESC "+desc);\r
+\r
+       }\r
+\r
+       // matches a quoted string that may contain escaped special characters \r
+       // (which includes other quotation marks)\r
+       private static final String QUOTED_PATTERN = "\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\"";\r
+       // matches (possibly escaped) unsupported characters\r
+       private static final String BADCHARS_PATTERN = "\\\\?[-+*/()=<>\"]";\r
+       // matches a substring that should be capitalized (see below for details)\r
+       private static final String NAMEPART_PATTERN = "([A-Za-z])[A-Za-z]*";\r
+\r
+       private static String sanitize(String str) {\r
+               //TODO: fix this to produce quoted modelica strings instead\r
+               StringBuilder result = new StringBuilder(str);\r
+\r
+               Matcher matcher;\r
+\r
+               matcher = Pattern.compile(QUOTED_PATTERN).matcher(str);\r
+               while (matcher.find()) {\r
+                       // TODO: could do something more clever than just an underscore\r
+                       String replacement = Pattern.compile(BADCHARS_PATTERN).matcher(matcher.group(1)).replaceAll("_");\r
+                       result.replace(matcher.start(), matcher.end(), replacement);\r
+               }\r
+\r
+               // also capitalize all variable names to remove certain openmodelica \r
+               // keywords such as "public" or "private", this might not seem like\r
+               // the most sane variable name handling scheme possible, but it is\r
+               // nevertheless the one we are forced to use            \r
+               matcher = Pattern.compile(NAMEPART_PATTERN).matcher(result.toString());\r
+               while (matcher.find()) {\r
+                       // replace the first character of the match with the same \r
+                       // character in upper case\r
+                       result.replace(matcher.start(1), matcher.end(1), matcher.group(1).toUpperCase());\r
+               }\r
+\r
+               return result.toString();\r
+       }\r
+\r
+       private static void parseSketch(ArrayList<String> sketch) {\r
+               // the sketch should have at least three lines, version, name and font\r
+               if (sketch.size() < 3 || \r
+                               !sketch.get(0).startsWith("V300") || \r
+                               !sketch.get(1).startsWith("*") || \r
+                               !sketch.get(2).startsWith("$")) {\r
+                       System.err.println("INVALID SKETCH DATA");\r
+                       return;\r
+               }\r
+\r
+               // parse name\r
+               String name = sketch.get(1).substring(1);\r
+               // parse font\r
+               String font = sketch.get(2).substring(2);\r
+\r
+               for (int i = 3; i < sketch.size(); i++) {\r
+                       String line = sketch.get(i);\r
+                       if (line.startsWith(CONNECTION_PREFIX)) {\r
+                               parseConnection(line.substring(2));\r
+                       }\r
+                       else if (line.startsWith(VARIABLE_PREFIX)) {\r
+                               parseVariable(line.substring(3));\r
+                       }\r
+                       else if (line.startsWith(VALVE_PREFIX)) {\r
+                               //parseValve(line.substring(3));\r
+                       }\r
+                       else if (line.startsWith(COMMENT_PREFIX)) {\r
+                               //parseComment(line.substring(3));\r
+                       }\r
+                       else {\r
+                               //System.err.println("UNSUPPORTED SKETCH OBJECT "+line);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // these methods are implemented according to the documentation on the .mdl\r
+       // file format available in http://www.vensim.com/documentation/24305.htm\r
+\r
+       // (1,)id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist\r
+       private static final String CONNECTION_PREFIX = "1,";\r
+       private static final String CONNECTION_PATTERN = \r
+                       "(\\d+),(\\d+),(\\d+).*";\r
+       // (n,)id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+       private static final String VARIABLE_PREFIX = "10,";\r
+       private static final String VALVE_PREFIX = "11,";\r
+       private static final String COMMENT_PREFIX = "12,";\r
+       private static final String ELEMENT_PATTERN = \r
+                       "(\\d+),(\".*\"|[^\",]*),(-?\\d+),(-?\\d+),(\\d+),(\\d+).*";\r
+\r
+       private static void parseConnection(String line) {\r
+               Matcher matcher = Pattern.compile(CONNECTION_PATTERN).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       System.err.println("MALFORMED CONNECTION");\r
+                       return;\r
+               }\r
+\r
+               // the fields of interest are: id, from, to, ... (TODO)\r
+               int id = Integer.parseInt(matcher.group(1));\r
+               int from = Integer.parseInt(matcher.group(2));\r
+               int to = Integer.parseInt(matcher.group(3));\r
+\r
+               System.err.println("connection "+id+": "+from+" -> "+to);\r
+       }\r
+\r
+       private static void parseVariable(String line) {\r
+               Matcher matcher = Pattern.compile(ELEMENT_PATTERN).matcher(line);\r
+               if (!matcher.matches()) {\r
+                       System.err.println("MALFORMED VARIABLE "+line);\r
+                       return;\r
+               }\r
                \r
-               MdlFile mdlFile = getMdlContents(file);\r
-               \r
-               getVariableData(model, mdlFile.getVariables());\r
-               \r
-               getSketchData(model, mdlFile.getSketchData());\r
-               \r
-               getControlData(model, mdlFile.getControls());\r
+               int id = Integer.parseInt(matcher.group(1));\r
+               String name = sanitize(matcher.group(2));\r
+               int x = Integer.parseInt(matcher.group(3));\r
+               int y = Integer.parseInt(matcher.group(4));\r
+               int width = Integer.parseInt(matcher.group(5));\r
+               int height = Integer.parseInt(matcher.group(6));\r
                \r
-//             getOthertData(model, mdlFile.getOtherData());\r
+               System.err.println("variable "+id+": "+name+" ("+x+","+y+")");\r
+       }\r
+\r
+       private static void parseValve(String line) {\r
                \r
-               setAllSubscripts(model);\r
+       }\r
+\r
+       private static void parseComment(String line) { \r
                \r
-               return model;\r
        }\r
-       \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 \r
        private static MdlFile getMdlContents(File aFile) {\r
                MdlFile mdlFile = new MdlFile();\r
-               \r
+\r
                try {\r
                        BufferedReader input =  new BufferedReader(new FileReader(aFile));\r
-                       \r
+\r
                        try {\r
-                               String line = null; //not declared within while loop\r
+                               String line = null; // not declared within while loop\r
                                \r
+                               mdlFile.startSketch();\r
+\r
                                // See if the document is encoded with UTF-8. It will be marked with {UTF-8} on the first line\r
                                input.mark(30);\r
-                               if (( line = input.readLine()) != null &&\r
-                                               line.contains("{UTF-8}")){\r
+                               if ((line = input.readLine()) != null && line.contains("{UTF-8}")){\r
                                        Reader in = new InputStreamReader(new FileInputStream(aFile), "UTF-8");\r
                                        input =  new BufferedReader(in);\r
                                        line = input.readLine();\r
                                } else {\r
                                        input.reset();\r
                                }\r
-                               \r
-                               \r
+\r
+\r
                                boolean isControl = false;\r
-                               \r
-                               while (( line = input.readLine()) != null){\r
+\r
+                               while ((line = input.readLine()) != null) {\r
                                        // Build an element (combine the lines to one string)\r
                                        StringBuilder elementBuilder = new StringBuilder();\r
-                                       while(line != null && !line.contains("\\\\\\---///")) {\r
+                                       while (line != null && !line.contains("\\\\\\---///")) {\r
                                                // Add a new line for the element\r
                                                elementBuilder.append(line);\r
                                                if(line.endsWith("|") && !line.endsWith("~~|")) {\r
@@ -98,13 +396,13 @@ public class MdlParser {
                                                }\r
                                                line = input.readLine();\r
                                        }\r
-                                       \r
-                                       if(line.contains("\\\\\\---///"))\r
+\r
+                                       if (line.contains("\\\\\\---///"))\r
                                                break;\r
-                                       \r
+\r
                                        String variable = elementBuilder.toString();\r
 \r
-                                       if(variable.trim().matches("[\\*]{46}.+[\\*]{46}.+")) {\r
+                                       if (variable.trim().matches("[\\*]{46}.+[\\*]{46}.+")) {\r
                                                if(variable.contains(".Control")) {\r
                                                        isControl = true;\r
                                                } else {\r
@@ -115,17 +413,17 @@ public class MdlParser {
 \r
                                        // Add element string to model\r
                                        if(isControl) {\r
-                                               mdlFile.addControl(variable);\r
+                                               mdlFile.addControlData(variable);\r
                                        } else {\r
-                                       mdlFile.addVariable(variable);\r
+                                               mdlFile.addVariableData(variable);\r
                                        }\r
                                }\r
-                               \r
-                               while (( line = input.readLine()) != null && !line.contains("///---\\\\\\")){\r
+\r
+                               while ((line = input.readLine()) != null && !line.contains("///---\\\\\\")) {\r
                                        mdlFile.addSketchData(line);\r
                                }\r
-                               \r
-                               while (( line = input.readLine()) != null){\r
+\r
+                               while ((line = input.readLine()) != null){\r
                                        mdlFile.addOtherData(line);\r
                                }\r
                        }\r
@@ -136,10 +434,10 @@ public class MdlParser {
                catch (IOException ex){\r
                        ex.printStackTrace();\r
                }\r
-               \r
+\r
                return mdlFile;\r
        }\r
-       \r
+\r
        private static void getVariableData(Model model, ArrayList<String> elements) {\r
                ArrayList<EquivalenceSubscript> equivalenceSubscripts = new ArrayList<EquivalenceSubscript>();\r
                for(String elementString : elements) {\r
@@ -148,7 +446,7 @@ public class MdlParser {
                                equivalenceSubscripts.add((EquivalenceSubscript) v);\r
                        }\r
                }\r
-               \r
+\r
                // All variables are ready, determine subscript equivalences\r
                for(EquivalenceSubscript es : equivalenceSubscripts) {\r
                        Element e = model.getElement(es.getEquivalentToName());\r
@@ -157,13 +455,13 @@ public class MdlParser {
                        }\r
                }\r
        }\r
-       \r
-       \r
+\r
+\r
        private static void getControlData(Model model, ArrayList<String> controls) {\r
                for(String controlString : controls) {\r
                        String[] nameAndData = controlString.split("=");        \r
                        String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
-                       \r
+\r
                        if(nameAndData[0].trim().equals("FINAL TIME")) {\r
                                model.setEndTime(Double.parseDouble(expressionUnitsAndComments[0]));\r
                        } else if(nameAndData[0].trim().equals("INITIAL TIME")) {\r
@@ -175,9 +473,9 @@ public class MdlParser {
                                model.setTimeUnit(expressionUnitsAndComments[1]);\r
                        }\r
                }\r
-               \r
+\r
        }\r
-       \r
+\r
        private static Variable getVariable(Model model, String name) {\r
                Element e = model.getElement(name);\r
                Variable variable = null;\r
@@ -185,7 +483,7 @@ public class MdlParser {
                        variable = (Variable)e;\r
                return variable;\r
        }\r
-       \r
+\r
        private static String[] getNormalVariableNameDataAndRange(String element) {\r
                String[] nameAndData = element.split("=", 2);\r
                String[] nameAndRange = nameAndData[0].trim().split("[\\[|\\]]");\r
@@ -193,21 +491,21 @@ public class MdlParser {
                        return new String[] {nameAndRange[0], nameAndData[1], nameAndRange.length == 2 ? nameAndRange[1] : null};\r
                return null;\r
        }\r
-       \r
+\r
        private static String[] getSubscriptNameAndData(String element) {\r
                String[] nameAndData = element.split(":");\r
                if(nameAndData.length == 2)\r
                        return nameAndData;\r
                return null;\r
        }       \r
-       \r
+\r
        private static String[] getEquivalenceSubscriptNameAndData(String element) {\r
                String[] nameAndData = element.split("\\<\\-\\>");\r
                if(nameAndData.length == 2)\r
                        return nameAndData;\r
                return null;\r
        }\r
-       \r
+\r
        private static String[] getTableNameDataAndRange(String element) {\r
                String[] parts = element.split("\\~"); \r
                if(!parts[0].contains("(") || !parts[0].contains(")"))\r
@@ -220,33 +518,37 @@ public class MdlParser {
                        return new String[] {nameAndRange[0], nameAndData[1], nameAndRange.length == 2 ? nameAndRange[1] : null};\r
                return nameAndData;\r
        }\r
-       \r
+\r
        private static String[] getDataVariableNameAndData(String element) {\r
                String[] nameAndData = {\r
                                element.substring(0, element.indexOf("~")),\r
                                " " + element.substring(element.indexOf("~"))};\r
                return nameAndData;\r
        }\r
-       \r
+\r
        private static Variable createVariable(Model model, String elementString) {\r
 \r
                String[] elementExpressions = elementString.split("\\~\\~\\|");\r
-               \r
+\r
                Variable variable = null;\r
                \r
+               System.err.println("CREATE VARIABLE "+elementString);\r
+\r
                for(String s : elementExpressions) {\r
+                       System.err.println("  INSIDE FOR");\r
+                       \r
                        // Skip these definitions at least for now\r
                        if(elementExpressions.length > 1 && s.contains("A FUNCTION OF"))\r
                                continue;\r
-                       \r
+\r
                        Expression expression = new Expression();\r
 \r
                        String[] nameAndData = null;\r
                        String name;\r
-                       \r
+\r
                        // Create the expression based on the expression string\r
                        if((nameAndData = getNormalVariableNameDataAndRange(s)) != null) {\r
-                               \r
+\r
                                name = nameAndData[0].replace("\"", "");\r
                                variable = getVariable(model, name);\r
                                if(variable == null) {\r
@@ -254,7 +556,7 @@ public class MdlParser {
                                        variable.setName(name);\r
                                        model.addElement(variable);\r
                                }\r
-                               \r
+\r
                                if(!nameAndData[1].trim().endsWith("|")) {\r
                                        // Multiple expressions\r
                                        expression.setExpression(nameAndData[1].trim());\r
@@ -262,9 +564,9 @@ public class MdlParser {
                                        String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
                                        expression.setExpression(expressionUnitsAndComments[0].trim());\r
                                }\r
-                               \r
+\r
                        } else if((nameAndData = getSubscriptNameAndData(s)) != null) {\r
-                               \r
+\r
                                name = nameAndData[0].replace("\"", "");\r
                                variable = getVariable(model, name);\r
                                if(variable == null) {\r
@@ -272,15 +574,15 @@ public class MdlParser {
                                        variable.setName(name);\r
                                        model.addElement(variable);\r
                                }\r
-                               \r
+\r
                                // No support for multidimensional variables. Don't know what that would mean\r
                                String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
                                expression.setExpression(expressionUnitsAndComments[0].trim());\r
                                variable.setUnits(expressionUnitsAndComments[1].trim());\r
                                variable.setComments(expressionUnitsAndComments[2].trim());\r
-                               \r
+\r
                        } else if((nameAndData = getEquivalenceSubscriptNameAndData(s)) != null) {\r
-                               \r
+\r
                                name = nameAndData[0].replace("\"", "");\r
                                variable = getVariable(model, name);\r
                                if(variable == null) {\r
@@ -288,15 +590,15 @@ public class MdlParser {
                                        variable.setName(name);\r
                                        model.addElement(variable);\r
                                }\r
-                               \r
+\r
                                // No support for multidimensional variables. Don't know what that would mean\r
                                String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
                                expression.setExpression(expressionUnitsAndComments[0].trim());\r
                                variable.setUnits(expressionUnitsAndComments[1].trim());\r
                                variable.setComments(expressionUnitsAndComments[2].trim());\r
-                               \r
+\r
                        } else if((nameAndData = getTableNameDataAndRange(s)) != null) {\r
-                               \r
+\r
                                name =(nameAndData[0].replace("\"", ""));\r
                                variable = getVariable(model, name);\r
                                if(variable == null) {\r
@@ -304,7 +606,7 @@ public class MdlParser {
                                        variable.setName(name);\r
                                        model.addElement(variable);\r
                                }\r
-                               \r
+\r
                                String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
                                // ([(0,0)-(2,5)],(0,5),(0.5,3),(1,0.5),(2,0.5) => ( ; (0,0)-(2,5) ; ,(0,5),(0.5,3),(1,0.5),(2,0.5)\r
                                String table = expressionUnitsAndComments[0].trim().split("[\\[|\\]]")[2];\r
@@ -314,10 +616,10 @@ public class MdlParser {
                                table = table.replace("(", "{");\r
                                table = table.replace(")", "}");\r
                                expression.setExpression(table);                \r
-                               \r
-                               \r
+\r
+\r
                        }  else if((nameAndData = getDataVariableNameAndData(s)) != null) {\r
-                               \r
+\r
                                name = nameAndData[0].replace("\"", "");\r
                                variable = getVariable(model, name);\r
                                if(variable == null) {\r
@@ -325,17 +627,17 @@ public class MdlParser {
                                        variable.setName(name);\r
                                        model.addElement(variable);\r
                                }\r
-                               \r
+\r
                                expression.setExpression("");\r
                        } \r
-                       \r
+\r
                        if(nameAndData == null || variable == null)\r
                                continue;\r
-                       \r
+\r
                        // Set possible range for the expression\r
                        if(nameAndData.length == 3)\r
                                expression.setRange(nameAndData[2]);\r
-                       \r
+\r
                        // Set units and comments for the variable \r
                        if(nameAndData[1].trim().endsWith("|")) {\r
                                String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
@@ -348,7 +650,7 @@ public class MdlParser {
                                                        units.lastIndexOf("[") + 1, \r
                                                        units.length() - 1);\r
                                        String[] rangeParts = range.split(",");\r
-                                       \r
+\r
                                        try {\r
                                                variable.setRangeStart(Double.parseDouble(rangeParts[0]));\r
                                                if(rangeParts.length >= 2)\r
@@ -363,25 +665,27 @@ public class MdlParser {
                                variable.setUnits(expressionUnitsAndComments[1].trim());\r
                                variable.setComments(expressionUnitsAndComments[2].trim());\r
                        }\r
-                       \r
+\r
                        // Finally add the expression to element\r
                        variable.getExpressions().add(expression);\r
                }\r
                return variable;\r
        }\r
-       \r
+\r
        private static int SCALE = 4;\r
-       private static void getSketchData(Model model, ArrayList<String> sketchData) {\r
 \r
+       private static void getSketchData(Model model, ArrayList<String> sketchData) {\r
                String line = null;\r
                View view = null;\r
+\r
                int i = 0;\r
+\r
                while(i < sketchData.size()) {\r
                        line = sketchData.get(i);\r
                        if(line.startsWith("*")) {\r
                                view = new View();\r
                                model.addView(view);\r
-                               \r
+\r
                                view.setName(line.substring(1));\r
 \r
                                // STARTED A NEW VIEW\r
@@ -390,26 +694,26 @@ public class MdlParser {
                                ArrayList<String> ghostNumbers = new ArrayList<String>();\r
                                ArrayList<String[]> connections = new ArrayList<String[]>();\r
                                HashMap<String, String[]> emptyValves = new HashMap<String, String[]>(); // map for valves that don't have an element \r
-                               \r
-                               \r
+\r
+\r
                                i++;\r
                                line = sketchData.get(i);\r
                                while(i < sketchData.size() && !sketchData.get(i).startsWith("*")) {\r
                                        line = sketchData.get(i);\r
-                                       \r
+\r
                                        if(line.startsWith("$")) {\r
                                                view.setFontParameters(line);\r
                                                i++;\r
                                                continue;\r
                                        }\r
-                                               \r
+\r
                                        String[] data = line.split(",");\r
-                                       if(data[0].equals("1")) {\r
+                                       if (data[0].equals("1")) {\r
                                                // Connections are handled after all elements\r
                                                String[] connectionData = line.split(",");\r
                                                connections.add(connectionData);\r
-                                               \r
-                                       } else if(data[0].equals("11")){\r
+\r
+                                       } else if (data[0].equals("11")){\r
                                                // Valve\r
                                                i = i + 1;\r
                                                String elementLine = sketchData.get(i);\r
@@ -417,7 +721,7 @@ public class MdlParser {
                                                // FIXME: Assumes that element is always attached to the valve\r
                                                Element element = model.getElement(elementData[2].replace("\"", ""));\r
                                                Valve valve = new Valve();\r
-                                               if(element != null && element instanceof Variable) {\r
+                                               if (element != null && element instanceof Variable) {\r
                                                        Variable v = (Variable) element;\r
                                                        valve.setName(v.getName());\r
                                                        valve.setExpressions(v.getExpressions());\r
@@ -425,10 +729,10 @@ public class MdlParser {
                                                        valve.setComments(v.getComments());\r
                                                        valve.setX(Integer.parseInt(data[3]) / SCALE);\r
                                                        valve.setY(Integer.parseInt(data[4]) / SCALE);\r
-                                                       \r
+\r
                                                        model.removeElement(element);\r
                                                        model.addElement(view, valve);\r
-                                                       \r
+\r
                                                        // Add valve to the element list with both valve and variable symbol numbers\r
                                                        elementNumbers.put(elementData[1], valve);\r
                                                        elementNumbers.put(data[1], valve);\r
@@ -436,19 +740,20 @@ public class MdlParser {
                                                        i = i - 1;\r
                                                        emptyValves.put(data[1], data);\r
                                                }\r
-                                       } else if(data[0].equals("12")){\r
+                                       } else if (data[0].equals("12")){\r
                                                // Cloud\r
                                                Cloud cloud = new Cloud();\r
                                                cloud.setX(Integer.parseInt(data[3]) / SCALE); \r
                                                cloud.setY(Integer.parseInt(data[4]) / SCALE); \r
                                                elementNumbers.put(data[1], cloud);\r
                                                model.addElement(view, cloud);\r
-                                       } else if(data[0].equals("10") && data.length <= 15){\r
+                                       } else if (data[0].equals("10") && data.length <= 15){\r
                                                // Some variable\r
                                                Element e = model.getElement(data[2].replace("\"", "").trim());\r
-                                               if(e != null && e instanceof Variable) {\r
+\r
+                                               if (e != null && e instanceof Variable) {\r
                                                        Variable v = (Variable) e;\r
-                                                       if(v.getExpressions().get(0).getExpression().startsWith("INTEG (") && !(e instanceof Stock)) {\r
+                                                       if (v.getExpressions().get(0).getExpression().startsWith("INTEG (") && !(e instanceof Stock)) {\r
                                                                // Stock\r
                                                                Stock s = new Stock();\r
                                                                s.setName(v.getName());\r
@@ -465,7 +770,7 @@ public class MdlParser {
                                                e.setY(Integer.parseInt(data[4]) / SCALE); \r
                                                elementNumbers.put(data[1], e);\r
                                                model.relocateElement(view, e);\r
-                                       } else if(data[0].equals("10") && data.length > 15){\r
+                                       } else if (data[0].equals("10") && data.length > 15){\r
                                                // TODO: Ghost\r
                                                // for now, direct back to the original element\r
                                                Element originalElement = model.getElement(data[2].replace("\"", ""));\r
@@ -474,45 +779,46 @@ public class MdlParser {
                                                        ghostNumbers.add(data[1]);\r
                                                }\r
                                        }\r
-                                       \r
+\r
                                        i++;\r
                                }\r
+\r
                                i--;\r
-                               \r
+\r
                                // Find the first variable that is connected to an empty valve\r
                                for(String[] connectionData : connections) {\r
                                        if(!connectionData[9].equals("64"))\r
                                                continue; // not dependency\r
                                        String[] end = emptyValves.get(connectionData[3]);\r
-                                       if(end != null && elementNumbers.get(connectionData[3]) == null) {\r
+                                       if (end != null && elementNumbers.get(connectionData[3]) == null) {\r
                                                // Use the connected element to create a valve and give it a name \r
                                                Element start = elementNumbers.get(connectionData[2]);\r
-                                               if(start == null)\r
+                                               if (start == null)\r
                                                        continue;\r
-                                               \r
+\r
                                                Valve valve = new Valve();\r
                                                valve.setName(start.getName() + " Rate");\r
                                                valve.setX(Integer.parseInt(end[3]) / SCALE); \r
                                                valve.setY(Integer.parseInt(end[4]) / SCALE);\r
-                                               \r
+\r
                                                model.addElement(view, valve);\r
                                                elementNumbers.put(connectionData[3], valve);\r
                                                valve.setUnits("");\r
                                                valve.setComments("");\r
                                        }\r
                                }\r
-                               \r
-                               \r
-                               \r
+\r
+\r
+\r
                                for(String[] connectionData : connections) {\r
-                                       \r
+\r
                                        Element start = elementNumbers.get(connectionData[2]);\r
                                        Element end = elementNumbers.get(connectionData[3]);\r
                                        // Discard connection if one of the ends is null\r
                                        if(start == null || end == null)\r
                                                continue;\r
-                                       \r
-                                       \r
+\r
+\r
                                        Connection connection;          \r
                                        if(connectionData[9].equals("64")) {\r
                                                // Dependency\r
@@ -521,7 +827,7 @@ public class MdlParser {
                                                String controlX = connectionData[13].substring(connectionData[13].indexOf("(") + 1);\r
                                                String controlY = connectionData[14].substring(0, connectionData[14].indexOf(")"));\r
                                                Point2D controlPoint = new Point2D.Double(Double.parseDouble(controlX) / SCALE, Double.parseDouble(controlY) / SCALE);\r
-                                               \r
+\r
                                                if(ghostNumbers.contains(connectionData[2]) ||\r
                                                                ghostNumbers.contains(connectionData[3])) {\r
                                                        connection = new Dependency();\r
@@ -533,7 +839,7 @@ public class MdlParser {
 \r
                                                        connection = new Dependency(angle);\r
                                                }\r
-                                               \r
+\r
                                        } else {\r
                                                // Flow\r
                                                connection = new Flow();\r
@@ -548,8 +854,8 @@ public class MdlParser {
                                        connection.setEnd(end);\r
                                        model.addConnection(connection);\r
                                }\r
-                               \r
-                               \r
+\r
+\r
                                // Generate expressions for empty valves                \r
                                for(String key : emptyValves.keySet()) {\r
                                        Element e = elementNumbers.get(key);\r
@@ -566,14 +872,14 @@ public class MdlParser {
                                                                break;\r
                                                        }\r
                                                }\r
-                                               \r
+\r
                                                // Create the expression. Use the expression of the stock, and undo the effect of other valves\r
                                                if(stock != null && stock instanceof Stock) {\r
                                                        Expression expression = new Expression();\r
-                                                       \r
+\r
                                                        StringBuilder sb = new StringBuilder();\r
                                                        sb.append(((Stock)stock).getIntegralParts(stock.getExpressions().get(0))[0]);\r
-                                                       \r
+\r
                                                        for(Connection c : stock.getConnections()) {\r
                                                                if(c instanceof Flow) {\r
                                                                        if(c.getStart().equals(stock) && !c.getEnd().equals(valve)) {\r
@@ -593,24 +899,25 @@ public class MdlParser {
                                        }\r
                                }\r
                        }\r
+\r
                        i++;\r
                }\r
 \r
        }\r
-       \r
+\r
        private static void getOthertData(Model model, String otherData) {\r
-               \r
+\r
        }\r
-       \r
+\r
        private static void setAllSubscripts(Model model) {\r
-               \r
+\r
                // Set subscripts for all elements\r
                ArrayList<Element> elements = new ArrayList<Element>();\r
                elements.addAll(model.getUnlocatedElements());\r
                for(View view : model.getViews()) {\r
                        elements.addAll(view.getElements());\r
                }\r
-               \r
+\r
                for(Element e : elements) {             \r
                        if(!(e instanceof Variable))\r
                                continue;\r
@@ -618,5 +925,5 @@ public class MdlParser {
                        v.initializeSubscripts(model);\r
                }\r
        }\r
-       \r
+\r
 }\r
diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlUtils.java
new file mode 100644 (file)
index 0000000..e5505a6
--- /dev/null
@@ -0,0 +1,45 @@
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+public class MdlUtils {\r
+       \r
+       /*\r
+        * the utils in this file are written based on the documentation of .mdl \r
+        * file format available in http://www.vensim.com/documentation/24305.htm\r
+        */\r
+\r
+       public static void parseSketchObject(String line) {\r
+               // 1,id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist\r
+\r
+               // the specification also contains "box,fill,font" at the end of the \r
+               // pattern but it does not seem to appear in any of our models \r
+               // so that is probably optional (or not used if the font is defined)\r
+               \r
+               // n,id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+               \r
+               String type = line.substring(0, line.indexOf(','));\r
+               \r
+               if (type.equals("1")) {\r
+                       // a connection\r
+                       parseConnection(line);\r
+               }\r
+               else if (type.equals("10") || type.equals("11") || type.equals("12")) {\r
+                       // an element\r
+                       parseElement(line);\r
+               }\r
+               else {\r
+                       // not supported\r
+               }\r
+       }\r
+       \r
+       private static void parseConnection(String line) {\r
+               // 1,id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist\r
+               \r
+       }\r
+       \r
+       private static void parseElement(String line) {\r
+               // n,id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+       }\r
+       \r
+}\r
index e36ca60adac64562e772571bbb384b26942a6c27..adff3bab11a860383f609462adcda7eb83674a58 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.sysdyn.mdlImport.mdlElements;
 \r
 \r
 public class Expression {\r
+       \r
        private String range, expression;\r
        \r
        @Override\r
@@ -29,7 +30,7 @@ public class Expression {
        }\r
 \r
        public String getExpression() {\r
-               if(expression == null)\r
+               if (expression == null)\r
                        return "";\r
                return expression;\r
        }\r
index 88fe41e63d16a8665c168283711324c84d1def1e..89fcc20346ac688983be1c38b23833cb109cd067 100644 (file)
@@ -23,7 +23,6 @@ public class View implements IWriteableMDLObject {
        private String name, fontParameters;\r
        \r
        private ArrayList<Element> elements = new ArrayList<Element>();\r
-       \r
 \r
        @Override\r
        public void write(WriteGraph graph, Resource parent) {\r
@@ -35,18 +34,18 @@ public class View implements IWriteableMDLObject {
        }\r
        \r
        public void addElement(Element e) {\r
-               if(e instanceof Subscript ||\r
-                               e instanceof Function)\r
+               if (e instanceof Subscript || e instanceof Function)\r
                        return;\r
                \r
-               if(e.getX()<minX)\r
+               if (e.getX() < minX)\r
                        minX = e.getX();\r
-               if(e.getX()>maxX)\r
+               if (e.getX() > maxX)\r
                        maxX = e.getX();\r
-               if(e.getY()<minY)\r
+               if (e.getY() < minY)\r
                        minY = e.getY();\r
-               if(e.getY()>maxY)\r
+               if (e.getY() > maxY)\r
                        maxY = e.getY();\r
+               \r
                this.elements.add(e);\r
        }\r
        \r