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
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
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
\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
}\r
\r
// Set simulation parameters\r
+ \r
+ System.err.println("DONE");\r
\r
return model;\r
}\r
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
} 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
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
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
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
\r
return list.toArray(new String[list.size()]);\r
}\r
- \r
}\r
--- /dev/null
+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
--- /dev/null
+package org.simantics.sysdyn.modelImport.mdl;\r
+\r
+public interface IMdlObject {\r
+ \r
+}\r
--- /dev/null
+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
+++ /dev/null
-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
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
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
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
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
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
}\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
vOffset = vertical;\r
}\r
\r
+ private double hOffset, vOffset;\r
+ \r
public double getHorizontalOffset() {\r
return hOffset;\r
}\r
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
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
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
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
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
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
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
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
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
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
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
public IWriteableObject getModelObject() {\r
return modelObject;\r
}\r
- \r
+\r
}\r
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
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
\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
\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
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
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
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
\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
}\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
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
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
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
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
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
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
// 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
\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
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
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
}\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
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
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
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
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
\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
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
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
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
return name;\r
}\r
\r
- public Set<String> getValues() {\r
+ public List<String> getValues() {\r
return values;\r
}\r
\r
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
--- /dev/null
+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