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