From 563c175c8c0e3d13df8f65a9ede5b65ea6f9beec Mon Sep 17 00:00:00 2001 From: jkauttio Date: Mon, 31 Mar 2014 13:28:14 +0000 Subject: [PATCH] Update vensim import, partial subscript support refs #2924 git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches@29226 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/modelImport/MdlParser2.java | 21 ++-- .../sysdyn/modelImport/MdlUtils.java | 107 +++++++++++------- .../sysdyn/modelImport/model/Element2.java | 2 +- .../modelImport/model/Enumeration2.java | 37 ++++++ .../sysdyn/modelImport/model/MdlModel.java | 21 ++++ .../sysdyn/modelImport/model/Model2.java | 45 ++++++++ .../modelImport/model/ModelVariable.java | 10 ++ .../sysdyn/modelImport/model/Subscript2.java | 29 +++++ .../model/SubscriptExpression.java | 45 ++++++++ .../sysdyn/modelImport/model/Variable2.java | 6 + 10 files changed, 275 insertions(+), 48 deletions(-) create mode 100644 dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Enumeration2.java create mode 100644 dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Subscript2.java create mode 100644 dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/SubscriptExpression.java 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 aa667ca1..7b0b1cd1 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 @@ -36,18 +36,10 @@ 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.Stock2; +import org.simantics.sysdyn.modelImport.model.Subscript2; import org.simantics.sysdyn.modelImport.model.Valve2; import org.simantics.sysdyn.modelImport.model.Variable2; -/* - * THINGS TO FIX: - * - vensim apparently supports infix operators (:AND: instead of AND()), these must be handled - * - "public" seems to be a keyboard of some sort which causes a problem in certain variable names - * - something is seriously wrong with the sketch import - * - how should models with multiple sketches be handled (this might already work) - * - instead of splitting the file into blocks, the parser could already process the data further which would greatly simplify later methods - */ - public class MdlParser2 { private static final String UTF_8 = "{UTF-8}"; @@ -84,6 +76,10 @@ public class MdlParser2 { HashMap variableToElement = new HashMap(); ArrayList shadows = new ArrayList(); + for (Subscript2 ss : mdl.getSubscripts()) { + System.err.println("SUBSCRIPT "+ss.getName()+": "+ss.getValues()); + } + // add sketch labels and independent elements for (Sketch2 sketch : mdl.getSketches()) { sketch.setEdges(); @@ -234,6 +230,7 @@ public class MdlParser2 { if (line.endsWith("|")) break; } while ((line = reader.readLine()) != null); + String str = buffer.toString(); String cat = MdlUtils.getPossibleCategory(str); @@ -247,6 +244,12 @@ public class MdlParser2 { mdl.addVariable(var, category); continue; } + + Subscript2 subscript = MdlUtils.getPossibleSubscript(str, mdl); + if (subscript != null) { + mdl.addSubscript(subscript); + continue; + } // if we got this far, the variable could not be parsed System.err.println("unrecognized variable "+str); 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 eda44c42..d825fc3e 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 @@ -14,6 +14,7 @@ import org.simantics.sysdyn.modelImport.model.SketchConnection; 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.Variable2; import org.simantics.sysdyn.modelImport.model.Valve2.TextPosition; @@ -40,49 +41,23 @@ public class MdlUtils { private static final String VAR_NAME = "("+VAR_NAME_QUOTED+"|"+VAR_NAME_SIMPLE+")"; - private static final String SUBSCRIPT = - "("+VAR_NAME_SIMPLE+")\\[("+VAR_NAME_SIMPLE+"(?:,"+VAR_NAME_SIMPLE+")*)\\]"; - - // the first part of the variable string is the variable name - // followed by a delimiter which depends on the type of the declaration private static final String VARIABLE_PATTERN = VAR_NAME+"\\s*=\\s*"; - private static final String SUBSCRIPT_PATTERN = - SUBSCRIPT+"\\s*=\\s*"; - private static final String VALUE_NEW_PATTERN = - VAR_NAME+"\\s*:\\s*"; - private static final String VALUE_EQUALS_PATTERN = - VAR_NAME+"\\s*<->\\s*"; - - // the second part is the equation followed by '~' private static final String EQUATION_PATTERN = "([^~]*?(?:"+VAR_NAME_QUOTED+"[^~]*?)*)\\s*~\\s*"; - - // the third part is the unit followed by '~' private static final String UNIT_PATTERN = "([^~]*?)\\s*~\\s*"; - - // the last part is the description followed by '|' private static final String DESC_PATTERN = "([^\\|]*?)\\s*\\|"; - + public static final String variablePattern = VARIABLE_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; - public static final String subscriptPattern = - SUBSCRIPT_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; - public static final String valueNewPattern = - VALUE_NEW_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; - public static final String valueEqualsPattern = - VALUE_EQUALS_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; private static final int variableName = 1; private static final int variableEquation = 2; private static final int variableUnit = 3; private static final int variableDesc = 4; - private static final String NUMBER = - "-?\\d+(?:.\\d+)?"; - public static Variable2 getPossibleVariable(String line, String category) { Matcher matcher = Pattern.compile(variablePattern).matcher(line); @@ -103,6 +78,56 @@ public class MdlUtils { return new Variable2(name, expression, unit, range, description); } + // a subscript variable is a variable that has a different equation + // depending on the value of the subscript it references + private static final String VAR_NAME_SUBSCRIPT = + "("+VAR_NAME_SIMPLE+")\\[("+VAR_NAME_SIMPLE+"(?:,"+VAR_NAME_SIMPLE+")*)\\]"; + + private static final String SUBSCRIPT_VARIABLE_PATTERN = + VAR_NAME_SUBSCRIPT+"\\s*=\\s*"; + + public static final String subscriptVariablePattern = + SUBSCRIPT_VARIABLE_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; + + private static final int subscriptVariableName = 1; + private static final int subscriptVariableIndices = 2; + private static final int subscriptVariableEquation = 3; + private static final int subscriptVariableUnit = 4; + private static final int subscriptVariableDesc = 5; + + public static Variable2 getPossibleSubscriptVariable(String line, String category) { + return null; + } + + private static final String SUBSCRIPT_PATTERN = + "("+VAR_NAME_SIMPLE+")\\s*(:|<->)\\s*"; + + public static final String subscriptPattern = + SUBSCRIPT_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN; + + private static final int subscriptName = 1; + private static final int subscriptType = 2; + private static final int subscriptEquation = 3; + + public static Subscript2 getPossibleSubscript(String line, MdlModel mdl) { + Matcher matcher = Pattern.compile(subscriptPattern).matcher(line); + + if (!matcher.matches()) { + return null; + } + + String name = matcher.group(subscriptName); + boolean equivalence = matcher.group(subscriptType).equals("<->"); + String expression = matcher.group(subscriptEquation); + + if (equivalence) { + return new Subscript2(name, mdl.getSubscript(expression)); + } + else { + return new Subscript2(name, expression.split(",")); + } + } + private static IExpression parseEquation(String equation) { if (equation.startsWith("INTEG")) { return parseIntegralExpression(equation); @@ -138,17 +163,23 @@ 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+"|\\?)\\]").matcher(unit); + Matcher matcher = Pattern.compile("\\[("+NUMBER+"),(("+NUMBER+"),("+NUMBER+")|\\?)\\]").matcher(unit); if (matcher.find()) { - String start = matcher.group(1); - String end = matcher.group(2); - // TODO: and step is? - return new Range( - Double.parseDouble(start), - end.equals("?") ? null : Double.parseDouble(end), - null, - matcher.group()); + Double start, end, step; + start = Double.parseDouble(matcher.group(1)); + if (matcher.group(2).equals("?")) { + end = null; + step = null; + } + else { + end = Double.parseDouble(matcher.group(3)); + step = Double.parseDouble(matcher.group(4)); + } + return new Range(start, end, step, matcher.group()); } else { return null; @@ -174,8 +205,8 @@ public class MdlUtils { private static final String POINTS = "(\\d+\\|(?:\\(-?\\d+,-?\\d+\\)\\|)+)"; public static final String sketchConnection = - // 1, id, from,to, shape,hid, pol, thick,hasf,dtype,res,color,font,np|plist - "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ "0,-1--1--1,.*,"+POINTS; + // 1, id, from,to, shape,hid, pol, thick,hasf,dtype,res, color,font,np|plist + "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ SKIP+"[^,]*,[^,]*,"+POINTS; // group indices for later use private static final int connectionId = 1; diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Element2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Element2.java index 005ca18c..d24e5551 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Element2.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Element2.java @@ -38,7 +38,7 @@ public abstract class Element2 implements IWriteableObject { return resource; } - public void setResource(Resource resource) { + protected void setResource(Resource resource) { this.resource = resource; } diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Enumeration2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Enumeration2.java new file mode 100644 index 00000000..00e0b1ed --- /dev/null +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Enumeration2.java @@ -0,0 +1,37 @@ +package org.simantics.sysdyn.modelImport.model; + +import java.util.ArrayList; + +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; + +public class Enumeration2 implements IWriteableObject { + + private String name; + private ArrayList values; + + private Resource resource; + + public Enumeration2(String name, ArrayList values) { + this.name = name; + this.values = values; + } + + public String getName() { + return name; + } + + public Resource getResource() { + return resource; + } + + @Override + public void write(WriteGraph graph, Resource parent, WriteContext context) + throws DatabaseException { + System.err.println("write enumeration"); + + resource = null; + } + +} 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 1a5519e8..43f8fa64 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 @@ -1,6 +1,7 @@ package org.simantics.sysdyn.modelImport.model; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -11,12 +12,15 @@ public class MdlModel { private HashMap variables; private HashMap> groups; + private HashMap subscripts; + private ArrayList sketches; public MdlModel(String name) { this.name = name; this.variables = new HashMap(); this.groups = new HashMap>(); + this.subscripts = new HashMap(); this.sketches = new ArrayList(); } @@ -39,6 +43,23 @@ public class MdlModel { return variables.get(name); } + public List getVariables() { + return new ArrayList(variables.values()); + } + + public void addSubscript(Subscript2 subscript) { + System.err.println("SUBSCRIPT "+subscript.getName()+": "+subscript.getValues()); + subscripts.put(subscript.getName(), subscript); + } + + public Subscript2 getSubscript(String name) { + return subscripts.get(name); + } + + public List getSubscripts() { + return new ArrayList(subscripts.values()); + } + public void addSketch(Sketch2 sketch) { sketches.add(sketch); } diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model2.java index 4189cd19..ca68dad5 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model2.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model2.java @@ -12,6 +12,9 @@ package org.simantics.sysdyn.modelImport.model; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; @@ -30,6 +33,9 @@ public class Model2 implements IWriteableObject { private double start, stop, step; // the structure of the model + private HashMap enumerations; + private HashMap variables; + private ArrayList elements; private ArrayList shadows; private ArrayList connections; @@ -37,6 +43,9 @@ public class Model2 implements IWriteableObject { public Model2(String name) { this.name = name; + enumerations = new HashMap(); + variables = new HashMap(); + elements = new ArrayList(); shadows = new ArrayList(); connections = new ArrayList(); @@ -65,6 +74,38 @@ public class Model2 implements IWriteableObject { public void setStep(double step) { this.step = step; } + + public void addEnumeration(Enumeration2 enumeration) { + if (enumerations.get(enumeration.getName()) != null) { + System.err.println("enumeration "+enumeration.getName()+" already defined"); + } + enumerations.put(enumeration.getName(), enumeration); + } + + public Enumeration2 getEnumeration(String name) { + return enumerations.get(name); + } + + public Collection getEnumerations() { + return enumerations.values(); + } + + public void addVariable(ModelVariable variable) { + if (enumerations.get(variable.getName()) != null) { + System.err.println("variable "+variable.getName()+" already defined"); + } + variables.put(variable.getName(), variable); + + addElement(variable); + } + + public ModelVariable getVariable(String name) { + return variables.get(name); + } + + public Collection getVariables() { + return variables.values(); + } public void addElement(Element2 element) { elements.add(element); @@ -92,6 +133,10 @@ public class Model2 implements IWriteableObject { Resource configuration = graph.getSingleObject(model, sim.HasConfiguration); + for (Enumeration2 e : getEnumerations()) { + e.write(graph, configuration, context); + } + for (Element2 e : elements) { e.write(graph, configuration, context); } diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/ModelVariable.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/ModelVariable.java index 1a5c496d..bfa0651a 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/ModelVariable.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/ModelVariable.java @@ -1,5 +1,7 @@ package org.simantics.sysdyn.modelImport.model; +import java.util.List; + import org.simantics.databoard.Bindings; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; @@ -16,6 +18,8 @@ public abstract class ModelVariable extends Element2 { protected Range range; protected String unit; protected String description; + + protected List enumerations; public ModelVariable(double x, double y, double w, double h, String name, IExpression expression, Range range, String unit, String description) { super(x, y, w, h); @@ -34,6 +38,10 @@ public abstract class ModelVariable extends Element2 { this.unit = variable.getUnit(); this.description = variable.getDescription(); } + + public String getName() { + return name; + } public Resource createVariable(WriteGraph graph, Resource type, Resource parent, WriteContext context) throws DatabaseException { @@ -48,6 +56,8 @@ public abstract class ModelVariable extends Element2 { expression.write(graph, variable, context); + // TODO: write references to enumerations here? + if (range != null) { range.write(graph, variable, context); } diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Subscript2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Subscript2.java new file mode 100644 index 00000000..f2a549e4 --- /dev/null +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Subscript2.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.modelImport.model; + +import java.util.ArrayList; +import java.util.Arrays; + +public class Subscript2 { + + private String name; + private ArrayList values; + + public Subscript2(String name, String...values) { + this.name = name; + this.values = new ArrayList(Arrays.asList(values)); + } + + public Subscript2(String name, Subscript2 other) { + this.name = name; + this.values = other.getValues(); + } + + public String getName() { + return name; + } + + public ArrayList getValues() { + return values; + } + +} diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/SubscriptExpression.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/SubscriptExpression.java new file mode 100644 index 00000000..6a64637a --- /dev/null +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/SubscriptExpression.java @@ -0,0 +1,45 @@ +package org.simantics.sysdyn.modelImport.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; + +public class SubscriptExpression implements IExpression { + + private ArrayList elements; + + public SubscriptExpression(String[] indices, IExpression expression) { + elements = new ArrayList(); + elements.add(new SubscriptExpressionElement(indices, expression)); + } + + public List getElements() { + return elements; + } + + public void merge(SubscriptExpression other) { + elements.addAll(other.getElements()); + } + + @Override + public void write(WriteGraph graph, Resource parent, WriteContext context) + throws DatabaseException { + System.err.println("write subscript expression"); + } + + private class SubscriptExpressionElement { + + String[] indices; + IExpression expression; + + public SubscriptExpressionElement(String[] indices, IExpression expression) { + this.indices = indices; + this.expression = expression; + } + } + +} diff --git a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Variable2.java b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Variable2.java index f1d365c6..698ad7ec 100644 --- a/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Variable2.java +++ b/dev-jkauttio/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Variable2.java @@ -36,4 +36,10 @@ public class Variable2 { return description; } + public void mergeExpression(Variable2 variable) { + if (expression instanceof SubscriptExpression) { + ((SubscriptExpression)expression).merge((SubscriptExpression)variable.getExpression()); + } + } + } -- 2.47.1