From a380fe35c9eacd272297e7ec56e7f03e3e44e632 Mon Sep 17 00:00:00 2001 From: jkauttio Date: Tue, 1 Apr 2014 11:09:30 +0000 Subject: [PATCH] Update vensim import, parser now supports most elements commonly found in .mdl files refs #2924 git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches@29230 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/modelImport/MdlParser2.java | 69 ++++++----- .../sysdyn/modelImport/MdlUtils.java | 111 +++++++++++++++++- .../modelImport/model/LookupExpression.java | 14 +++ .../sysdyn/modelImport/model/MdlModel.java | 1 - 4 files changed, 161 insertions(+), 34 deletions(-) diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser2.java index 7b0b1cd1..2cd600b3 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser2.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser2.java @@ -33,6 +33,7 @@ import org.simantics.sysdyn.modelImport.model.Sketch2; import org.simantics.sysdyn.modelImport.model.SketchComment; import org.simantics.sysdyn.modelImport.model.SketchConnection; import org.simantics.sysdyn.modelImport.model.SketchElement; +import org.simantics.sysdyn.modelImport.model.SketchObject; import org.simantics.sysdyn.modelImport.model.SketchValve; import org.simantics.sysdyn.modelImport.model.SketchVariable; import org.simantics.sysdyn.modelImport.model.Stock2; @@ -221,6 +222,7 @@ public class MdlParser2 { continue; StringBuilder buffer = new StringBuilder(); + do { if (line.endsWith("\\")) buffer.append(line.substring(0, line.length()-1)); @@ -245,6 +247,30 @@ public class MdlParser2 { continue; } + Variable2 ss = MdlUtils.getPossibleSubscriptVariable(str, category, mdl); + if (ss != null) { + Variable2 original = mdl.getVariable(ss.getName()); + if (original == null) { + mdl.addVariable(ss, category); + } + else { + original.mergeExpression(ss); + } + continue; + } + + Variable2 lu = MdlUtils.getPossibleLookUpVariable(str, category); + if (lu != null) { + System.err.println("found lookup variable "+lu.getName()); + continue; + } + + Variable2 plain = MdlUtils.getPossibleNoExpressionVariable(str); + if (plain != null) { + System.err.println("found plain variable "+plain.getName()); + continue; + } + Subscript2 subscript = MdlUtils.getPossibleSubscript(str, mdl); if (subscript != null) { mdl.addSubscript(subscript); @@ -266,61 +292,50 @@ public class MdlParser2 { if (line.isEmpty()) continue; + SketchObject so; + if (line.startsWith(SKETCH_START)) { sketch = new Sketch2(); mdl.addSketch(sketch); - continue; } else if (line.startsWith(SKETCH_VERSION)) { // version declaration, nothing to do here - continue; } else if (line.startsWith("*")) { sketch.setName(line.substring(1)); - continue; } else if (line.startsWith("$")) { // font declaration, nothing to do here - continue; } - - SketchConnection connection = MdlUtils.getPossibleSketchConnection(line); - if (connection != null) { - sketch.addConnection(connection); - continue; + else if ((so = MdlUtils.getPossibleSketchConnection(line)) != null) { + sketch.addConnection((SketchConnection)so); } - - SketchVariable variable = MdlUtils.getPossibleSketchVariable(line, mdl); - if (variable != null) { - sketch.addVariable(variable); - continue; + else if ((so = MdlUtils.getPossibleSketchVariable(line, mdl)) != null) { + sketch.addVariable((SketchVariable)so); } - - SketchValve valve = MdlUtils.getPossibleSketchValve(line); - if (valve != null) { + else if ((so = MdlUtils.getPossibleSketchValve(line)) != null) { + SketchValve valve = (SketchValve)so; // the next row after a valve should always the variable associated with the valve SketchVariable attached = MdlUtils.getPossibleSketchVariable(reader.readLine(), mdl); if (attached == null || !attached.isAttached()) { System.err.println("attached variable not found for valve"); - continue; } valve.setAttachedVariable(attached); - sketch.addValve(valve); + sketch.addValve((SketchValve)valve); sketch.addVariable(attached); - continue; } - - SketchComment comment = MdlUtils.getPossibleSketchComment(line); - if (comment != null) { + else if ((so = MdlUtils.getPossibleSketchComment(line)) != null) { + SketchComment comment = (SketchComment)so; if (comment.hasTextLine()) { comment.setText(reader.readLine()); } sketch.addComment(comment); - continue; } - - // if we got this far, the element could not be parsed - System.err.println("unrecognized element "+line); + else { + // if we got this far, the element could not be parsed + System.err.println("unrecognized element "+line); + } + } while ((line = reader.readLine()) != null && !line.startsWith(SKETCH_END)); return line; diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtils.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtils.java index d825fc3e..d9eb5455 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtils.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtils.java @@ -6,6 +6,7 @@ import java.util.regex.Pattern; import org.simantics.sysdyn.modelImport.model.DelayExpression; import org.simantics.sysdyn.modelImport.model.IExpression; import org.simantics.sysdyn.modelImport.model.IntegralExpression; +import org.simantics.sysdyn.modelImport.model.LookupExpression; import org.simantics.sysdyn.modelImport.model.MdlModel; import org.simantics.sysdyn.modelImport.model.NormalExpression; import org.simantics.sysdyn.modelImport.model.Range; @@ -15,6 +16,7 @@ import org.simantics.sysdyn.modelImport.model.SketchElement; import org.simantics.sysdyn.modelImport.model.SketchValve; import org.simantics.sysdyn.modelImport.model.SketchVariable; import org.simantics.sysdyn.modelImport.model.Subscript2; +import org.simantics.sysdyn.modelImport.model.SubscriptExpression; import org.simantics.sysdyn.modelImport.model.Variable2; import org.simantics.sysdyn.modelImport.model.Valve2.TextPosition; @@ -27,6 +29,9 @@ public class MdlUtils { public enum CommentIcon { CLOUD, OTHER } + + private static final String NUMBER = + "-?\\d+(?:.\\d+)?"; // most of this data is from the documentation of the .mdl file format // available in http://www.vensim.com/documentation/24305.htm @@ -95,8 +100,105 @@ public class MdlUtils { private static final int subscriptVariableUnit = 4; private static final int subscriptVariableDesc = 5; - public static Variable2 getPossibleSubscriptVariable(String line, String category) { - return null; + public static Variable2 getPossibleSubscriptVariable(String line, String category, MdlModel mdl) { + Matcher matcher = Pattern.compile(subscriptVariablePattern).matcher(line); + + if (!matcher.matches()) { + return null; + } + + String name = matcher.group(subscriptVariableName); + // TODO: find out if subscript indices can contain commas and update + // this method accordingly + String[] indices = matcher.group(subscriptVariableIndices).split(","); + IExpression expression = parseEquation(matcher.group(subscriptVariableEquation)); + SubscriptExpression e = new SubscriptExpression(indices, expression); + + String unit = matcher.group(subscriptVariableUnit); + Range range = parseRange(unit); + if (range != null) { + unit = unit.substring(0, unit.indexOf(range.originalString())).trim(); + } + String description = matcher.group(subscriptVariableDesc); + + return new Variable2(name, e, unit, range, description); + } + + private static final String LOOKUP_NAME = + "([A-Za-z](?: *\\w+)*)"; + private static final String LOOKUP_RANGE = + "\\[\\(("+NUMBER+"),("+NUMBER+")\\)-\\(("+NUMBER+"),("+NUMBER+")\\)\\]"; + private static final String LOOKUP_POINTS = + "(\\("+NUMBER+","+NUMBER+"\\)(?:,\\("+NUMBER+","+NUMBER+"\\))*)"; + + private static final String LOOKUP_PATTERN = + LOOKUP_NAME+"\\s*\\(\\s*"+LOOKUP_RANGE+","+LOOKUP_POINTS+"\\s*\\)\\s*~\\s*"; + + public static final String lookupVariablePattern = + LOOKUP_PATTERN+UNIT_PATTERN+DESC_PATTERN; + + private static final int lookupVariableName = 1; + private static final int lookupVariableRangeXMin = 2; + private static final int lookupVariableRangeYMin = 3; + private static final int lookupVariableRangeXMax = 4; + private static final int lookupVariableRangeYMax = 5; + private static final int lookupVariablePoints = 6; + private static final int lookupVariableUnit = 7; + private static final int lookupVariableDesc = 8; + + public static Variable2 getPossibleLookUpVariable(String line, String category) { + Matcher matcher = Pattern.compile(lookupVariablePattern).matcher(line); + + if (!matcher.matches()) { + return null; + } + + String name = matcher.group(lookupVariableName); + double xMin = Double.parseDouble(matcher.group(lookupVariableRangeXMin)); + double xMax = Double.parseDouble(matcher.group(lookupVariableRangeYMin)); + double yMin = Double.parseDouble(matcher.group(lookupVariableRangeXMax)); + double yMax = Double.parseDouble(matcher.group(lookupVariableRangeYMax)); + String points = matcher.group(lookupVariablePoints); + + LookupExpression e = new LookupExpression(xMin, yMin, xMax, yMax, points); + + String unit = matcher.group(lookupVariableUnit); + Range range = parseRange(unit); + if (range != null) { + unit = unit.substring(0, unit.indexOf(range.originalString())).trim(); + } + String description = matcher.group(lookupVariableDesc); + + return new Variable2(name, e, unit, range, description); + } + + public static final String NO_EXP_PATTERN = + VAR_NAME+"\\s*~\\s*"; + + public static final String noExpressionVariablePattern = + NO_EXP_PATTERN+UNIT_PATTERN+DESC_PATTERN; + + private static final int noExpVariableName = 1; + private static final int noExpVariableUnit = 2; + private static final int noExpVariableDesc = 3; + + public static Variable2 getPossibleNoExpressionVariable(String line) { + Matcher matcher = Pattern.compile(noExpressionVariablePattern).matcher(line); + + if (!matcher.matches()) { + return null; + } + + String name = normalize(matcher.group(noExpVariableName)); + + String unit = matcher.group(noExpVariableUnit); + Range range = parseRange(unit); + if (range != null) { + unit = unit.substring(0, unit.indexOf(range.originalString())).trim(); + } + String description = matcher.group(noExpVariableDesc); + + return new Variable2(name, null, unit, range, description); } private static final String SUBSCRIPT_PATTERN = @@ -163,9 +265,6 @@ public class MdlUtils { return new NormalExpression(normalize(equation)); } - private static final String NUMBER = - "-?\\d+(?:.\\d+)?"; - private static Range parseRange(String unit) { Matcher matcher = Pattern.compile("\\[("+NUMBER+"),(("+NUMBER+"),("+NUMBER+")|\\?)\\]").matcher(unit); if (matcher.find()) { @@ -186,7 +285,7 @@ public class MdlUtils { } } - private static final String categoryPattern = "\\*{56}\\s+\\.(\\S+)\\s+\\*{56}.*"; + private static final String categoryPattern = "\\*{56}\\s*\\.(\\S+)\\s*\\*{56}.*"; public static String getPossibleCategory(String line) { Matcher matcher = Pattern.compile(categoryPattern).matcher(line); diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/LookupExpression.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/LookupExpression.java index 1ee58312..cc2052f7 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/LookupExpression.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/LookupExpression.java @@ -5,6 +5,20 @@ import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; public class LookupExpression implements IExpression { + + private double xMin; + private double yMin; + private double xMax; + private double yMax; + private String points; + + public LookupExpression(double xMin, double yMin, double xMax, double yMax, String points) { + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.points = points; + } @Override public void write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/MdlModel.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/MdlModel.java index 43f8fa64..7f211623 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/MdlModel.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/MdlModel.java @@ -48,7 +48,6 @@ public class MdlModel { } public void addSubscript(Subscript2 subscript) { - System.err.println("SUBSCRIPT "+subscript.getName()+": "+subscript.getValues()); subscripts.put(subscript.getName(), subscript); } -- 2.47.1