import org.simantics.db.common.request.WriteRequest;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.sysdyn.mdlImport.MdlParser;\r
-import org.simantics.sysdyn.mdlImport.mdlElements.Model;\r
+import org.simantics.sysdyn.mdlImport.MdlParser2;\r
+import org.simantics.sysdyn.mdlImport.model.Model;\r
import org.simantics.sysdyn.ui.Activator;\r
import org.simantics.ui.SimanticsUI;\r
\r
Activator.getDefault().getPreferenceStore().setValue(IMPORTMDLTPATH, (new File(selected)).getParent());\r
\r
// Convert Vensim model to Simantics SysDyn format using MdlParser\r
- final Model model = MdlParser.parse(file);\r
+ MdlParser2 parser = new MdlParser2();\r
+ parser.parse(file);\r
\r
SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
\r
import org.simantics.db.common.request.WriteRequest;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.sysdyn.mdlImport.MdlParser;\r
-import org.simantics.sysdyn.mdlImport.mdlElements.Model;\r
+import org.simantics.sysdyn.mdlImport.model.Model;\r
import org.simantics.ui.SimanticsUI;\r
\r
public class WizardMdlImportPage extends WizardPage{\r
org.simantics.sysdyn.expressionParser,
org.simantics.sysdyn.manager,
org.simantics.sysdyn.mdlImport,
- org.simantics.sysdyn.mdlImport.mdlElements,
+ org.simantics.sysdyn.mdlImport.model,
org.simantics.sysdyn.modelParser,
org.simantics.sysdyn.modelica,
org.simantics.sysdyn.representation,
@Override\r
public void perform(WriteGraph graph) throws DatabaseException {\r
SimulationResource SIMU = SimulationResource.getInstance(graph);\r
- System.err.println("CHANGE ACTIVE STATE OF EXPERIMENT");\r
if(activate)\r
graph.claim(experiment, SIMU.IsActive, experiment);\r
else\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.StringReader;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+public class ImportUtils {\r
+ \r
+ public static String escapeExpression(String string) {\r
+ string = string.replace("Ä", "A");\r
+ string = string.replace("ä", "a");\r
+ string = string.replace("ö", "o");\r
+ string = string.replace("Ö", "O");\r
+ string = string.replace("\\", "\n");\r
+ \r
+ StringBuilder sb = new StringBuilder();\r
+ \r
+ if(string.contains("\"")) {\r
+ boolean startedQuote = false;\r
+ StringBuilder var = new StringBuilder();\r
+ for(char c : string.toCharArray()) {\r
+ if(c == '"') {\r
+ if(!startedQuote) {\r
+ startedQuote = true;\r
+ var = new StringBuilder();\r
+ continue;\r
+ } else {\r
+ startedQuote = false;\r
+ sb.append(var.toString().replaceAll("[^a-zA-Z 0-9]+", ""));\r
+ continue;\r
+ }\r
+ }\r
+ if(startedQuote) {\r
+ var.append(c);\r
+ } else {\r
+ sb.append(c);\r
+ }\r
+ }\r
+ \r
+ string = sb.toString();\r
+ }\r
+ \r
+ return string;\r
+\r
+ }\r
+ \r
+ public static String escapeName(String string) {\r
+ string = string.replace("Ä", "A");\r
+ string = string.replace("ä", "a");\r
+ string = string.replace("ö", "o");\r
+ string = string.replace("Ö", "O");\r
+ string = string.replaceAll("[^a-zA-Z 0-9]+", "");\r
+ return string;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.util.ArrayList;\r
+\r
+public class MdlFile {\r
+\r
+ private ArrayList<String> variableData;\r
+ private ArrayList<String> controlData;\r
+ private ArrayList<String> otherData;\r
+ private ArrayList<ArrayList<String>> sketchData;\r
+ private ArrayList<String> currentSketch;\r
+ \r
+ public MdlFile() {\r
+ variableData = new ArrayList<String>();\r
+ controlData = new ArrayList<String>();\r
+ otherData = new ArrayList<String>();\r
+ sketchData = new ArrayList<ArrayList<String>>();\r
+ }\r
+\r
+ public void addVariableData(String line) {\r
+ variableData.add(line);\r
+ }\r
+\r
+ public ArrayList<String> getVariableData() {\r
+ return variableData;\r
+ }\r
+\r
+ public void addControlData(String line) {\r
+ controlData.add(line);\r
+ }\r
+\r
+ public ArrayList<String> getControlData() {\r
+ return controlData;\r
+ }\r
+\r
+ public void addOtherData(String line) {\r
+ otherData.add(line);\r
+ }\r
+\r
+ public ArrayList<String> getOtherData() {\r
+ return otherData;\r
+ }\r
+ \r
+ public void startSketch() {\r
+ currentSketch = new ArrayList<String>();\r
+ sketchData.add(currentSketch);\r
+ }\r
+\r
+ public void addSketchData(String line) {\r
+ currentSketch.add(line);\r
+ }\r
+\r
+ public ArrayList<ArrayList<String>> getSketchData() {\r
+ return sketchData;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.awt.geom.Point2D;\r
+import java.io.BufferedReader;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileReader;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.io.Reader;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.sysdyn.mdlImport.model.Auxiliary;\r
+import org.simantics.sysdyn.mdlImport.model.Cloud;\r
+import org.simantics.sysdyn.mdlImport.model.Connection;\r
+import org.simantics.sysdyn.mdlImport.model.Dependency;\r
+import org.simantics.sysdyn.mdlImport.model.Element;\r
+import org.simantics.sysdyn.mdlImport.model.EquivalenceSubscript;\r
+import org.simantics.sysdyn.mdlImport.model.Expression;\r
+import org.simantics.sysdyn.mdlImport.model.Flow;\r
+import org.simantics.sysdyn.mdlImport.model.Function;\r
+import org.simantics.sysdyn.mdlImport.model.Model;\r
+import org.simantics.sysdyn.mdlImport.model.Model2;\r
+import org.simantics.sysdyn.mdlImport.model.Stock;\r
+import org.simantics.sysdyn.mdlImport.model.Subscript;\r
+import org.simantics.sysdyn.mdlImport.model.Valve;\r
+import org.simantics.sysdyn.mdlImport.model.Variable;\r
+import org.simantics.sysdyn.mdlImport.model.View;\r
+\r
+/*\r
+ * THINGS TO FIX:\r
+ * - vensim apparently supports infix operators (:AND: instead of AND()), these must be handled\r
+ * - "public" seems to be a keyboard of some sort which causes a problem in certain variable names\r
+ * - something is seriously wrong with the sketch import\r
+ * - how should models with multiple sketches be handled (this might already work)\r
+ * - instead of splitting the file into blocks, the parser could already process the data further which would greatly simplify later methods\r
+ */\r
+\r
+public class MdlParser {\r
+\r
+ private enum State {\r
+ VARIABLE, CONTROL, SKETCH, OTHER\r
+ }\r
+ \r
+ public static Model parse(File file) {\r
+ \r
+ Model2 model = new Model2(file.getName());\r
+ \r
+ try {\r
+ // peek at the first line to see if we need to use UTF-8\r
+ BufferedReader reader = new BufferedReader(new FileReader(file));\r
+ String line = reader.readLine();\r
+ reader.close();\r
+ \r
+ if (line == null) {\r
+ // file is empty, nothing to do here\r
+ return null;\r
+ }\r
+ \r
+ if (line.startsWith(UTF_8)) {\r
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));\r
+ // skip the first line\r
+ reader.readLine();\r
+ }\r
+ else {\r
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));\r
+ }\r
+ \r
+ // read the model structure from the file contents\r
+ readVariables(reader, model);\r
+ readControls(reader, model);\r
+ readSketches(reader, model);\r
+ readOthers(reader, model);\r
+ }\r
+ catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ return null;\r
+ }\r
+\r
+ public static Model parse2(File file) {\r
+\r
+ Model2 model = new Model2(file.getName());\r
+\r
+ //String[] name = file.getName().split("\\.mdl");\r
+ //model.setName(name[0]);\r
+\r
+ MdlFile mdlFile = getMdlFile(file);\r
+\r
+ for (String variable : mdlFile.getVariableData()) {\r
+ parseElement(variable);\r
+ }\r
+\r
+ for (ArrayList<String> sketch : mdlFile.getSketchData()) {\r
+ parseSketch(sketch);\r
+ }\r
+\r
+ //MdlFile test = getMdlContents(file);\r
+\r
+ //getVariableData(model, test.getVariableData());\r
+\r
+ //getSketchData(model, mdlFile.getSketchData());\r
+\r
+ //getControlData(model, mdlFile.getControlData());\r
+\r
+ //getOthertData(model, mdlFile.getOtherData());\r
+\r
+ //setAllSubscripts(model);\r
+\r
+ return null;\r
+ }\r
+\r
+ private static final String UTF_8 = "{UTF-8}";\r
+ private static final String CONTROL_STR = ".Control";\r
+ private static final String SKETCH_START = "\\\\\\---///";\r
+ private static final String SKETCH_END = "///---\\\\\\";\r
+\r
+ private static MdlFile getMdlFile(File file) {\r
+ MdlFile mdl = new MdlFile();\r
+\r
+ try {\r
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));\r
+ String line = reader.readLine();\r
+\r
+ if (line != null && line.startsWith(UTF_8)) {\r
+ reader.close();\r
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));\r
+ // skip the "{UTF-8}" line\r
+ reader.readLine();\r
+ line = reader.readLine();\r
+ }\r
+\r
+ State state = State.VARIABLE;\r
+\r
+ while (line != null) {\r
+ line = line.trim();\r
+\r
+ // skip all empty lines\r
+ if (line.isEmpty()) {\r
+ line = reader.readLine();\r
+ continue;\r
+ }\r
+\r
+ switch (state) {\r
+ // the file starts with variable declarations that always \r
+ // start with a variable name and end with a '|'\r
+ case VARIABLE:\r
+ if (line.startsWith(SKETCH_START)) {\r
+ state = State.SKETCH;\r
+ continue; \r
+ }\r
+\r
+ String variable = readVariable(reader, line);\r
+\r
+ // simulation control variables are separated from model \r
+ // variables with a control block that looks basically\r
+ // like a variable but can be safely ignored\r
+ if (variable.contains(CONTROL_STR)) {\r
+ state = State.CONTROL;\r
+ break;\r
+ }\r
+\r
+ mdl.addVariableData(variable);\r
+ break;\r
+\r
+ // simulation control variables look like model variables but\r
+ // are handled differently\r
+ case CONTROL:\r
+ if (line.startsWith(SKETCH_START)) {\r
+ state = State.SKETCH;\r
+ continue; \r
+ }\r
+\r
+ String control = readVariable(reader, line);\r
+ mdl.addControlData(control);\r
+ break;\r
+\r
+ // sketch information contains the details on the structure\r
+ // and the visual representation of the model and is situated\r
+ // in the file after variable declarations\r
+ case SKETCH:\r
+ if (line.startsWith(SKETCH_END)) {\r
+ state = State.OTHER;\r
+ break;\r
+ }\r
+\r
+ if (line.startsWith(SKETCH_START)) {\r
+ mdl.startSketch();\r
+ break;\r
+ }\r
+\r
+ mdl.addSketchData(line);\r
+ break;\r
+\r
+ // the file ends with a section of data that contains some\r
+ // additional information which is not handled currently\r
+ case OTHER:\r
+ mdl.addOtherData(line);\r
+ break;\r
+\r
+ default: break; // should not get this far\r
+ }\r
+\r
+ line = reader.readLine();\r
+ }\r
+\r
+ reader.close();\r
+ }\r
+ catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ return mdl;\r
+ }\r
+ \r
+ private static void readVariables(BufferedReader reader, Model2 model) \r
+ throws IOException {\r
+ StringBuilder buffer = new StringBuilder();\r
+ \r
+ String line = reader.readLine();\r
+ while (line != null && !line.startsWith(SKETCH_START)) {\r
+ if (line.endsWith("\\")) {\r
+ buffer.append(line.substring(0, line.length()-1));\r
+ }\r
+ else {\r
+ buffer.append(line);\r
+ }\r
+ \r
+ if (line.endsWith("|")) {\r
+ parseElement(buffer.toString());\r
+ buffer.setLength(0);\r
+ }\r
+ }\r
+ }\r
+ \r
+ private static void readControls(BufferedReader reader, Model2 model) \r
+ throws IOException {\r
+ String line = reader.readLine();\r
+ while (line != null && !line.startsWith(SKETCH_START)) {\r
+ \r
+ }\r
+ }\r
+ \r
+ private static void readSketches(BufferedReader reader, Model2 model) \r
+ throws IOException {\r
+ \r
+ }\r
+ \r
+ private static void readOthers(BufferedReader reader, Model2 model) \r
+ throws IOException {\r
+ \r
+ }\r
+ \r
+\r
+ private static String readVariable(BufferedReader reader, String current) \r
+ throws IOException {\r
+ // TODO: does not support subscript stuff at all currently\r
+ StringBuilder element = new StringBuilder();\r
+\r
+ while (current != null) {\r
+ current = current.trim().replace('\t', ' ');\r
+\r
+ if (current.endsWith("|")) {\r
+ element.append(current.substring(0, current.length() - 1));\r
+ break;\r
+ }\r
+ else if (current.endsWith("\\")) {\r
+ element.append(current.substring(0, current.length() - 1));\r
+ }\r
+ else {\r
+ element.append(current);\r
+ }\r
+\r
+ current = reader.readLine();\r
+ }\r
+\r
+ return element.toString();\r
+ }\r
+\r
+ private static void parseElement(String element) {\r
+ String left, right, unit, desc;\r
+\r
+ String[] data = element.split("~");\r
+\r
+ if (data.length != 3) {\r
+ System.err.println("INVALID ELEMENT DATA "+element);\r
+ return;\r
+ }\r
+\r
+ String equation = normalize(data[0]);\r
+\r
+ left = equation.substring(0, equation.indexOf('=')).trim();\r
+ right = equation.substring(equation.indexOf('=') + 1).trim();\r
+ unit = data[1].trim();\r
+ desc = data[2].trim();\r
+\r
+ //System.err.println("FOUND VARIABLE "+left);\r
+ //System.err.println(" EQUATION "+right);\r
+ //System.err.println(" UNIT "+unit);\r
+ //System.err.println(" DESC "+desc);\r
+\r
+ }\r
+\r
+ // TODO: name should probably be escaped just before writing to graph\r
+ \r
+ // matches a quoted string that may contain escaped special characters \r
+ // (which includes other quotation marks)\r
+ private static final String QUOTED_PATTERN = "\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\"";\r
+ // matches (possibly escaped) unsupported characters\r
+ private static final String BADCHARS_PATTERN = "\\\\?[-+*/()=<>\"]";\r
+ // matches a substring that should be capitalized (see below for details)\r
+ private static final String NAMEPART_PATTERN = "([A-Za-z])[A-Za-z]*";\r
+\r
+ // normalize a variable name\r
+ private static String normalize(String str) {\r
+ StringBuilder result = new StringBuilder(str);\r
+\r
+ Matcher matcher;\r
+\r
+ matcher = Pattern.compile(QUOTED_PATTERN).matcher(str);\r
+ while (matcher.find()) {\r
+ // TODO: could do something more clever than just an underscore\r
+ String replacement = Pattern.compile(BADCHARS_PATTERN).matcher(matcher.group(1)).replaceAll("_");\r
+ result.replace(matcher.start(), matcher.end(), replacement);\r
+ }\r
+\r
+ // also capitalize all variable names to remove certain openmodelica \r
+ // keywords such as "public" or "private", this might not seem like\r
+ // the most sane variable name handling scheme possible, but it is\r
+ // nevertheless the one we are forced to use \r
+ matcher = Pattern.compile(NAMEPART_PATTERN).matcher(result.toString());\r
+ while (matcher.find()) {\r
+ // replace the first character of the match with the same \r
+ // character in upper case\r
+ result.replace(matcher.start(1), matcher.end(1), matcher.group(1).toUpperCase());\r
+ }\r
+\r
+ return result.toString();\r
+ }\r
+\r
+ private static void parseSketch(ArrayList<String> sketch) {\r
+ // the sketch should have at least three lines, version, name and font\r
+ if (sketch.size() < 3 || \r
+ !sketch.get(0).startsWith("V300") || \r
+ !sketch.get(1).startsWith("*") || \r
+ !sketch.get(2).startsWith("$")) {\r
+ System.err.println("INVALID SKETCH DATA");\r
+ return;\r
+ }\r
+\r
+ // parse name\r
+ String name = sketch.get(1).substring(1);\r
+ // parse font\r
+ String font = sketch.get(2).substring(2);\r
+\r
+ for (int i = 3; i < sketch.size(); i++) {\r
+ String line = sketch.get(i);\r
+ if (line.startsWith(CONNECTION_PREFIX)) {\r
+ parseConnection(line.substring(2));\r
+ }\r
+ else if (line.startsWith(VARIABLE_PREFIX)) {\r
+ parseVariable(line.substring(3));\r
+ }\r
+ else if (line.startsWith(VALVE_PREFIX)) {\r
+ //parseValve(line.substring(3));\r
+ }\r
+ else if (line.startsWith(COMMENT_PREFIX)) {\r
+ //parseComment(line.substring(3));\r
+ }\r
+ else {\r
+ //System.err.println("UNSUPPORTED SKETCH OBJECT "+line);\r
+ }\r
+ }\r
+ }\r
+\r
+ // these methods are implemented according to the documentation on the .mdl\r
+ // file format available in http://www.vensim.com/documentation/24305.htm\r
+\r
+ // (1,)id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist\r
+ private static final String CONNECTION_PREFIX = "1,";\r
+ private static final String CONNECTION_PATTERN = \r
+ "(\\d+),(\\d+),(\\d+).*";\r
+ // (n,)id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+ private static final String VARIABLE_PREFIX = "10,";\r
+ private static final String VALVE_PREFIX = "11,";\r
+ private static final String COMMENT_PREFIX = "12,";\r
+ private static final String ELEMENT_PATTERN = \r
+ "(\\d+),(\".*\"|[^\",]*),(-?\\d+),(-?\\d+),(\\d+),(\\d+).*";\r
+\r
+ private static void parseConnection(String line) {\r
+ Matcher matcher = Pattern.compile(CONNECTION_PATTERN).matcher(line);\r
+ if (!matcher.matches()) {\r
+ System.err.println("MALFORMED CONNECTION");\r
+ return;\r
+ }\r
+\r
+ // the fields of interest are: id, from, to, ... (TODO)\r
+ int id = Integer.parseInt(matcher.group(1));\r
+ int from = Integer.parseInt(matcher.group(2));\r
+ int to = Integer.parseInt(matcher.group(3));\r
+\r
+ System.err.println("connection "+id+": "+from+" -> "+to);\r
+ }\r
+\r
+ private static void parseVariable(String line) {\r
+ Matcher matcher = Pattern.compile(ELEMENT_PATTERN).matcher(line);\r
+ if (!matcher.matches()) {\r
+ System.err.println("MALFORMED VARIABLE "+line);\r
+ return;\r
+ }\r
+ \r
+ int id = Integer.parseInt(matcher.group(1));\r
+ String name = normalize(matcher.group(2));\r
+ int x = Integer.parseInt(matcher.group(3));\r
+ int y = Integer.parseInt(matcher.group(4));\r
+ int width = Integer.parseInt(matcher.group(5));\r
+ int height = Integer.parseInt(matcher.group(6));\r
+ \r
+ System.err.println("variable "+id+": "+name+" ("+x+","+y+")");\r
+ }\r
+\r
+ private static void parseValve(String line) {\r
+ \r
+ }\r
+\r
+ private static void parseComment(String line) { \r
+ \r
+ }\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ private static MdlFile getMdlContents(File aFile) {\r
+ MdlFile mdlFile = new MdlFile();\r
+\r
+ try {\r
+ BufferedReader input = new BufferedReader(new FileReader(aFile));\r
+\r
+ try {\r
+ String line = null; // not declared within while loop\r
+ \r
+ mdlFile.startSketch();\r
+\r
+ // See if the document is encoded with UTF-8. It will be marked with {UTF-8} on the first line\r
+ input.mark(30);\r
+ if ((line = input.readLine()) != null && line.contains("{UTF-8}")){\r
+ Reader in = new InputStreamReader(new FileInputStream(aFile), "UTF-8");\r
+ input = new BufferedReader(in);\r
+ line = input.readLine();\r
+ } else {\r
+ input.reset();\r
+ }\r
+\r
+\r
+ boolean isControl = false;\r
+\r
+ while ((line = input.readLine()) != null) {\r
+ // Build an element (combine the lines to one string)\r
+ StringBuilder elementBuilder = new StringBuilder();\r
+ while (line != null && !line.contains("\\\\\\---///")) {\r
+ // Add a new line for the element\r
+ elementBuilder.append(line);\r
+ if(line.endsWith("|") && !line.endsWith("~~|")) {\r
+ //Element definition has ended\r
+ break;\r
+ }\r
+ line = input.readLine();\r
+ }\r
+\r
+ if (line.contains("\\\\\\---///"))\r
+ break;\r
+\r
+ String variable = elementBuilder.toString();\r
+\r
+ if (variable.trim().matches("[\\*]{46}.+[\\*]{46}.+")) {\r
+ if(variable.contains(".Control")) {\r
+ isControl = true;\r
+ } else {\r
+ isControl = false;\r
+ }\r
+ continue;\r
+ }\r
+\r
+ // Add element string to model\r
+ if(isControl) {\r
+ mdlFile.addControlData(variable);\r
+ } else {\r
+ mdlFile.addVariableData(variable);\r
+ }\r
+ }\r
+\r
+ while ((line = input.readLine()) != null && !line.contains("///---\\\\\\")) {\r
+ mdlFile.addSketchData(line);\r
+ }\r
+\r
+ while ((line = input.readLine()) != null){\r
+ mdlFile.addOtherData(line);\r
+ }\r
+ }\r
+ finally {\r
+ input.close();\r
+ }\r
+ }\r
+ catch (IOException ex){\r
+ ex.printStackTrace();\r
+ }\r
+\r
+ return mdlFile;\r
+ }\r
+\r
+ private static void getVariableData(Model model, ArrayList<String> elements) {\r
+ ArrayList<EquivalenceSubscript> equivalenceSubscripts = new ArrayList<EquivalenceSubscript>();\r
+ for(String elementString : elements) {\r
+ Variable v = createVariable(model, elementString);\r
+ if(v instanceof EquivalenceSubscript){\r
+ equivalenceSubscripts.add((EquivalenceSubscript) v);\r
+ }\r
+ }\r
+\r
+ // All variables are ready, determine subscript equivalences\r
+ for(EquivalenceSubscript es : equivalenceSubscripts) {\r
+ Element e = model.getElement(es.getEquivalentToName());\r
+ if(e != null && e instanceof Subscript) {\r
+ es.setEquivalentTo((Subscript)e);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ private static void getControlData(Model model, ArrayList<String> controls) {\r
+ for(String controlString : controls) {\r
+ String[] nameAndData = controlString.split("="); \r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+\r
+ if(nameAndData[0].trim().equals("FINAL TIME")) {\r
+ model.setEndTime(Double.parseDouble(expressionUnitsAndComments[0]));\r
+ } else if(nameAndData[0].trim().equals("INITIAL TIME")) {\r
+ model.setStartTime(Double.parseDouble(expressionUnitsAndComments[0]));\r
+ } else if(nameAndData[0].trim().equals("TIME STEP")) {\r
+ model.setTimeStep(Double.parseDouble(expressionUnitsAndComments[0]));\r
+ } else if(nameAndData[0].trim().equals("SAVEPER")) {\r
+ model.setSaveper(expressionUnitsAndComments[0]);\r
+ model.setTimeUnit(expressionUnitsAndComments[1]);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ private static Variable getVariable(Model model, String name) {\r
+ Element e = model.getElement(name);\r
+ Variable variable = null;\r
+ if(e != null && e instanceof Variable)\r
+ variable = (Variable)e;\r
+ return variable;\r
+ }\r
+\r
+ private static String[] getNormalVariableNameDataAndRange(String element) {\r
+ String[] nameAndData = element.split("=", 2);\r
+ String[] nameAndRange = nameAndData[0].trim().split("[\\[|\\]]");\r
+ if(nameAndData.length == 2)\r
+ return new String[] {nameAndRange[0], nameAndData[1], nameAndRange.length == 2 ? nameAndRange[1] : null};\r
+ return null;\r
+ }\r
+\r
+ private static String[] getSubscriptNameAndData(String element) {\r
+ String[] nameAndData = element.split(":");\r
+ if(nameAndData.length == 2)\r
+ return nameAndData;\r
+ return null;\r
+ } \r
+\r
+ private static String[] getEquivalenceSubscriptNameAndData(String element) {\r
+ String[] nameAndData = element.split("\\<\\-\\>");\r
+ if(nameAndData.length == 2)\r
+ return nameAndData;\r
+ return null;\r
+ }\r
+\r
+ private static String[] getTableNameDataAndRange(String element) {\r
+ String[] parts = element.split("\\~"); \r
+ if(!parts[0].contains("(") || !parts[0].contains(")"))\r
+ return null;\r
+ String name = element.substring(0, element.indexOf("("));\r
+ String theRest = element.substring(element.indexOf("("));\r
+ String[] nameAndData = {name, theRest};\r
+ String[] nameAndRange = nameAndData[0].trim().split("[\\[|\\]]");\r
+ if(nameAndData.length == 2)\r
+ return new String[] {nameAndRange[0], nameAndData[1], nameAndRange.length == 2 ? nameAndRange[1] : null};\r
+ return nameAndData;\r
+ }\r
+\r
+ private static String[] getDataVariableNameAndData(String element) {\r
+ String[] nameAndData = {\r
+ element.substring(0, element.indexOf("~")),\r
+ " " + element.substring(element.indexOf("~"))};\r
+ return nameAndData;\r
+ }\r
+\r
+ private static Variable createVariable(Model model, String elementString) {\r
+\r
+ String[] elementExpressions = elementString.split("\\~\\~\\|");\r
+\r
+ Variable variable = null;\r
+ \r
+ System.err.println("CREATE VARIABLE "+elementString);\r
+\r
+ for(String s : elementExpressions) {\r
+ System.err.println(" INSIDE FOR");\r
+ \r
+ // Skip these definitions at least for now\r
+ if(elementExpressions.length > 1 && s.contains("A FUNCTION OF"))\r
+ continue;\r
+\r
+ Expression expression = new Expression();\r
+\r
+ String[] nameAndData = null;\r
+ String name;\r
+\r
+ // Create the expression based on the expression string\r
+ if((nameAndData = getNormalVariableNameDataAndRange(s)) != null) {\r
+\r
+ name = nameAndData[0].replace("\"", "");\r
+ variable = getVariable(model, name);\r
+ if(variable == null) {\r
+ variable = new Auxiliary();\r
+ variable.setName(name);\r
+ model.addElement(variable);\r
+ }\r
+\r
+ if(!nameAndData[1].trim().endsWith("|")) {\r
+ // Multiple expressions\r
+ expression.setExpression(nameAndData[1].trim());\r
+ } else {\r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+ expression.setExpression(expressionUnitsAndComments[0].trim());\r
+ }\r
+\r
+ } else if((nameAndData = getSubscriptNameAndData(s)) != null) {\r
+\r
+ name = nameAndData[0].replace("\"", "");\r
+ variable = getVariable(model, name);\r
+ if(variable == null) {\r
+ variable = new Subscript();\r
+ variable.setName(name);\r
+ model.addElement(variable);\r
+ }\r
+\r
+ // No support for multidimensional variables. Don't know what that would mean\r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+ expression.setExpression(expressionUnitsAndComments[0].trim());\r
+ variable.setUnits(expressionUnitsAndComments[1].trim());\r
+ variable.setComments(expressionUnitsAndComments[2].trim());\r
+\r
+ } else if((nameAndData = getEquivalenceSubscriptNameAndData(s)) != null) {\r
+\r
+ name = nameAndData[0].replace("\"", "");\r
+ variable = getVariable(model, name);\r
+ if(variable == null) {\r
+ variable = new EquivalenceSubscript();\r
+ variable.setName(name);\r
+ model.addElement(variable);\r
+ }\r
+\r
+ // No support for multidimensional variables. Don't know what that would mean\r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+ expression.setExpression(expressionUnitsAndComments[0].trim());\r
+ variable.setUnits(expressionUnitsAndComments[1].trim());\r
+ variable.setComments(expressionUnitsAndComments[2].trim());\r
+\r
+ } else if((nameAndData = getTableNameDataAndRange(s)) != null) {\r
+\r
+ name =(nameAndData[0].replace("\"", ""));\r
+ variable = getVariable(model, name);\r
+ if(variable == null) {\r
+ variable = new Function();\r
+ variable.setName(name);\r
+ model.addElement(variable);\r
+ }\r
+\r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+ // ([(0,0)-(2,5)],(0,5),(0.5,3),(1,0.5),(2,0.5) => ( ; (0,0)-(2,5) ; ,(0,5),(0.5,3),(1,0.5),(2,0.5)\r
+ String table = expressionUnitsAndComments[0].trim().split("[\\[|\\]]")[2];\r
+ // ,(0,5),(0.5,3),(1,0.5),(2,0.5) => (0,5),(0.5,3),(1,0.5),(2,0.5)\r
+ table = table.substring(table.indexOf(",") + 1, table.lastIndexOf(")"));\r
+ table = "{" + table + "}";\r
+ table = table.replace("(", "{");\r
+ table = table.replace(")", "}");\r
+ expression.setExpression(table); \r
+\r
+\r
+ } else if((nameAndData = getDataVariableNameAndData(s)) != null) {\r
+\r
+ name = nameAndData[0].replace("\"", "");\r
+ variable = getVariable(model, name);\r
+ if(variable == null) {\r
+ variable = new Auxiliary();\r
+ variable.setName(name);\r
+ model.addElement(variable);\r
+ }\r
+\r
+ expression.setExpression("");\r
+ } \r
+\r
+ if(nameAndData == null || variable == null)\r
+ continue;\r
+\r
+ // Set possible range for the expression\r
+ if(nameAndData.length == 3)\r
+ expression.setRange(nameAndData[2]);\r
+\r
+ // Set units and comments for the variable \r
+ if(nameAndData[1].trim().endsWith("|")) {\r
+ String[] expressionUnitsAndComments = nameAndData[1].split("[\\~|\\|]");\r
+ String units = expressionUnitsAndComments[1].trim();\r
+ if(units.contains("[") &&\r
+ units.contains("]") &&\r
+ units.lastIndexOf("]") == units.length() - 1) {\r
+ // Range definitions are at the end\r
+ String range = units.substring(\r
+ units.lastIndexOf("[") + 1, \r
+ units.length() - 1);\r
+ String[] rangeParts = range.split(",");\r
+\r
+ try {\r
+ variable.setRangeStart(Double.parseDouble(rangeParts[0]));\r
+ if(rangeParts.length >= 2)\r
+ variable.setRangeEnd(Double.parseDouble(rangeParts[1]));\r
+ if(rangeParts.length >= 3)\r
+ variable.setRangeStep(Double.parseDouble(rangeParts[2]));\r
+ } catch (NumberFormatException e) {\r
+ // Not a double\r
+ }\r
+ expressionUnitsAndComments[1] = units.substring(0, units.lastIndexOf("["));\r
+ }\r
+ variable.setUnits(expressionUnitsAndComments[1].trim());\r
+ variable.setComments(expressionUnitsAndComments[2].trim());\r
+ }\r
+\r
+ // Finally add the expression to element\r
+ variable.getExpressions().add(expression);\r
+ }\r
+ return variable;\r
+ }\r
+\r
+ private static int SCALE = 4;\r
+\r
+ private static void getSketchData(Model model, ArrayList<String> sketchData) {\r
+ String line = null;\r
+ View view = null;\r
+\r
+ int i = 0;\r
+\r
+ while(i < sketchData.size()) {\r
+ line = sketchData.get(i);\r
+ if(line.startsWith("*")) {\r
+ view = new View();\r
+ model.addView(view);\r
+\r
+ view.setName(line.substring(1));\r
+\r
+ // STARTED A NEW VIEW\r
+\r
+ HashMap<String, Element> elementNumbers = new HashMap<String, Element>();\r
+ ArrayList<String> ghostNumbers = new ArrayList<String>();\r
+ ArrayList<String[]> connections = new ArrayList<String[]>();\r
+ HashMap<String, String[]> emptyValves = new HashMap<String, String[]>(); // map for valves that don't have an element \r
+\r
+\r
+ i++;\r
+ line = sketchData.get(i);\r
+ while(i < sketchData.size() && !sketchData.get(i).startsWith("*")) {\r
+ line = sketchData.get(i);\r
+\r
+ if(line.startsWith("$")) {\r
+ view.setFontParameters(line);\r
+ i++;\r
+ continue;\r
+ }\r
+\r
+ String[] data = line.split(",");\r
+ if (data[0].equals("1")) {\r
+ // Connections are handled after all elements\r
+ String[] connectionData = line.split(",");\r
+ connections.add(connectionData);\r
+\r
+ } else if (data[0].equals("11")){\r
+ // Valve\r
+ i = i + 1;\r
+ String elementLine = sketchData.get(i);\r
+ String[] elementData = elementLine.split(",");\r
+ // FIXME: Assumes that element is always attached to the valve\r
+ Element element = model.getElement(elementData[2].replace("\"", ""));\r
+ Valve valve = new Valve();\r
+ if (element != null && element instanceof Variable) {\r
+ Variable v = (Variable) element;\r
+ valve.setName(v.getName());\r
+ valve.setExpressions(v.getExpressions());\r
+ valve.setUnits(v.getUnits());\r
+ valve.setComments(v.getComments());\r
+ valve.setX(Integer.parseInt(data[3]) / SCALE);\r
+ valve.setY(Integer.parseInt(data[4]) / SCALE);\r
+\r
+ model.removeElement(element);\r
+ model.addElement(view, valve);\r
+\r
+ // Add valve to the element list with both valve and variable symbol numbers\r
+ elementNumbers.put(elementData[1], valve);\r
+ elementNumbers.put(data[1], valve);\r
+ } else {\r
+ i = i - 1;\r
+ emptyValves.put(data[1], data);\r
+ }\r
+ } else if (data[0].equals("12")){\r
+ // Cloud\r
+ Cloud cloud = new Cloud();\r
+ cloud.setX(Integer.parseInt(data[3]) / SCALE); \r
+ cloud.setY(Integer.parseInt(data[4]) / SCALE); \r
+ elementNumbers.put(data[1], cloud);\r
+ model.addElement(view, cloud);\r
+ } else if (data[0].equals("10") && data.length <= 15){\r
+ // Some variable\r
+ Element e = model.getElement(data[2].replace("\"", "").trim());\r
+\r
+ if (e != null && e instanceof Variable) {\r
+ Variable v = (Variable) e;\r
+ if (v.getExpressions().get(0).getExpression().startsWith("INTEG (") && !(e instanceof Stock)) {\r
+ // Stock\r
+ Stock s = new Stock();\r
+ s.setName(v.getName());\r
+ s.setUnits(v.getUnits());\r
+ s.setComments(v.getComments());\r
+ s.setExpressions(v.getExpressions());\r
+ model.removeElement(e);\r
+ e = s;\r
+ model.addElement(view, e);\r
+ }\r
+ }\r
+\r
+ e.setX(Integer.parseInt(data[3]) / SCALE); \r
+ e.setY(Integer.parseInt(data[4]) / SCALE); \r
+ elementNumbers.put(data[1], e);\r
+ model.relocateElement(view, e);\r
+ } else if (data[0].equals("10") && data.length > 15){\r
+ // TODO: Ghost\r
+ // for now, direct back to the original element\r
+ Element originalElement = model.getElement(data[2].replace("\"", ""));\r
+ if(originalElement != null) {\r
+ elementNumbers.put(data[1], originalElement);\r
+ ghostNumbers.add(data[1]);\r
+ }\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ i--;\r
+\r
+ // Find the first variable that is connected to an empty valve\r
+ for(String[] connectionData : connections) {\r
+ if(!connectionData[9].equals("64"))\r
+ continue; // not dependency\r
+ String[] end = emptyValves.get(connectionData[3]);\r
+ if (end != null && elementNumbers.get(connectionData[3]) == null) {\r
+ // Use the connected element to create a valve and give it a name \r
+ Element start = elementNumbers.get(connectionData[2]);\r
+ if (start == null)\r
+ continue;\r
+\r
+ Valve valve = new Valve();\r
+ valve.setName(start.getName() + " Rate");\r
+ valve.setX(Integer.parseInt(end[3]) / SCALE); \r
+ valve.setY(Integer.parseInt(end[4]) / SCALE);\r
+\r
+ model.addElement(view, valve);\r
+ elementNumbers.put(connectionData[3], valve);\r
+ valve.setUnits("");\r
+ valve.setComments("");\r
+ }\r
+ }\r
+\r
+\r
+\r
+ for(String[] connectionData : connections) {\r
+\r
+ Element start = elementNumbers.get(connectionData[2]);\r
+ Element end = elementNumbers.get(connectionData[3]);\r
+ // Discard connection if one of the ends is null\r
+ if(start == null || end == null)\r
+ continue;\r
+\r
+\r
+ Connection connection; \r
+ if(connectionData[9].equals("64")) {\r
+ // Dependency\r
+ Point2D startPoint = new Point2D.Double(start.getX(), start.getY());\r
+ Point2D endPoint = new Point2D.Double(end.getX(), end.getY());\r
+ String controlX = connectionData[13].substring(connectionData[13].indexOf("(") + 1);\r
+ String controlY = connectionData[14].substring(0, connectionData[14].indexOf(")"));\r
+ Point2D controlPoint = new Point2D.Double(Double.parseDouble(controlX) / SCALE, Double.parseDouble(controlY) / SCALE);\r
+\r
+ if(ghostNumbers.contains(connectionData[2]) ||\r
+ ghostNumbers.contains(connectionData[3])) {\r
+ connection = new Dependency();\r
+ } else {\r
+ double angle = Dependency.angleOfArc(\r
+ startPoint.getX(), startPoint.getY(),\r
+ controlPoint.getX(), controlPoint.getY(),\r
+ endPoint.getX(), endPoint.getY());\r
+\r
+ connection = new Dependency(angle);\r
+ }\r
+\r
+ } else {\r
+ // Flow\r
+ connection = new Flow();\r
+ if(connectionData[4].equals("100")) {\r
+ // Flip the flow\r
+ Element temp = start;\r
+ start = end;\r
+ end = temp;\r
+ }\r
+ }\r
+ connection.setStart(start);\r
+ connection.setEnd(end);\r
+ model.addConnection(connection);\r
+ }\r
+\r
+\r
+ // Generate expressions for empty valves \r
+ for(String key : emptyValves.keySet()) {\r
+ Element e = elementNumbers.get(key);\r
+ if(e instanceof Valve && ((Valve)e).getExpressions().isEmpty()) {\r
+ Valve valve = (Valve)e;\r
+ // Find the stock\r
+ Stock stock = null;\r
+ for(Connection connection : valve.getConnections()) {\r
+ if(!(connection instanceof Flow))\r
+ continue;\r
+ if(connection.getStart().equals(valve) &&\r
+ connection.getEnd() instanceof Stock) {\r
+ stock = (Stock)connection.getEnd();\r
+ break;\r
+ }\r
+ }\r
+\r
+ // Create the expression. Use the expression of the stock, and undo the effect of other valves\r
+ if(stock != null && stock instanceof Stock) {\r
+ Expression expression = new Expression();\r
+\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(((Stock)stock).getIntegralParts(stock.getExpressions().get(0))[0]);\r
+\r
+ for(Connection c : stock.getConnections()) {\r
+ if(c instanceof Flow) {\r
+ if(c.getStart().equals(stock) && !c.getEnd().equals(valve)) {\r
+ sb.append("+");\r
+ sb.append(c.getEnd().getName());\r
+ } else if(!c.getStart().equals(valve)){\r
+ sb.append("-");\r
+ sb.append(c.getStart().getName());\r
+ }\r
+ }\r
+ }\r
+ expression.setExpression(sb.toString());\r
+ ArrayList<Expression> expressions = new ArrayList<Expression>();\r
+ expressions.add(expression);\r
+ valve.setExpressions(expressions);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ }\r
+\r
+ private static void getOthertData(Model model, String otherData) {\r
+\r
+ }\r
+\r
+ private static void setAllSubscripts(Model model) {\r
+\r
+ // Set subscripts for all elements\r
+ ArrayList<Element> elements = new ArrayList<Element>();\r
+ elements.addAll(model.getUnlocatedElements());\r
+ for(View view : model.getViews()) {\r
+ elements.addAll(view.getElements());\r
+ }\r
+\r
+ for(Element e : elements) { \r
+ if(!(e instanceof Variable))\r
+ continue;\r
+ Variable v = (Variable)e;\r
+ v.initializeSubscripts(model);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.sysdyn.mdlImport.model.Connection2;\r
+import org.simantics.sysdyn.mdlImport.model.Element2;\r
+import org.simantics.sysdyn.mdlImport.model.Model;\r
+import org.simantics.sysdyn.mdlImport.model.Model2;\r
+import org.simantics.sysdyn.mdlImport.model.Sketch2;\r
+import org.simantics.sysdyn.mdlImport.model.SketchComment;\r
+import org.simantics.sysdyn.mdlImport.model.SketchConnection;\r
+import org.simantics.sysdyn.mdlImport.model.SketchElement;\r
+import org.simantics.sysdyn.mdlImport.model.SketchValve;\r
+import org.simantics.sysdyn.mdlImport.model.SketchVariable;\r
+import org.simantics.sysdyn.mdlImport.model.Variable2;\r
+\r
+/*\r
+ * THINGS TO FIX:\r
+ * - vensim apparently supports infix operators (:AND: instead of AND()), these must be handled\r
+ * - "public" seems to be a keyboard of some sort which causes a problem in certain variable names\r
+ * - something is seriously wrong with the sketch import\r
+ * - how should models with multiple sketches be handled (this might already work)\r
+ * - instead of splitting the file into blocks, the parser could already process the data further which would greatly simplify later methods\r
+ */\r
+\r
+public class MdlParser2 {\r
+\r
+ private static final String UTF_8 = "{UTF-8}";\r
+ private static final String CONTROL_STR = ".Control";\r
+ private static final String SKETCH_VERSION = "V300";\r
+ \r
+ // each .mdl is divided into three sections, these are the the delimiter\r
+ // strings used to identify where each section starts\r
+ private static final String SKETCH_START = "\\\\\\---///";\r
+ private static final String SKETCH_END = "///---\\\\\\";\r
+\r
+ private HashMap<String, Variable2> variables;\r
+ private HashMap<String, Variable2> controls;\r
+ private ArrayList<Sketch2> sketches;\r
+\r
+ public MdlParser2() {\r
+ variables = new HashMap<String, Variable2>();\r
+ controls = new HashMap<String, Variable2>();\r
+ sketches = new ArrayList<Sketch2>();\r
+ }\r
+\r
+ public Model parse(File file) {\r
+ try {\r
+ // peek at the first line to see if we need to use UTF-8\r
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));\r
+ String line = reader.readLine();\r
+\r
+ if (line == null) {\r
+ // file is empty, nothing to do here\r
+ reader.close();\r
+ return null;\r
+ }\r
+\r
+ if (line.startsWith(UTF_8)) {\r
+ reader.close();\r
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));\r
+ // skip the first line\r
+ reader.readLine();\r
+ line = reader.readLine();\r
+ }\r
+ \r
+ // read variable data\r
+ line = readVariables(reader, line);\r
+ \r
+ if (line == null) {\r
+ // unexpected end of file\r
+ System.err.println("unexpected end of file");\r
+ reader.close();\r
+ return null;\r
+ }\r
+ \r
+ // read sketch data\r
+ line = readSketches(reader, line);\r
+ \r
+ if (line == null) {\r
+ // unexpected end of file\r
+ System.err.println("unexpected end of file");\r
+ reader.close();\r
+ return null;\r
+ }\r
+ \r
+ // read other data\r
+ \r
+ do {\r
+ // ignore other data for now\r
+ } while ((line = reader.readLine()) != null);\r
+\r
+ reader.close();\r
+ }\r
+ catch (IOException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+ \r
+ // create new model\r
+\r
+ Model2 model = new Model2(file.getName());\r
+ \r
+ int offset = 0;\r
+ \r
+ for (Sketch2 sketch : sketches) {\r
+ // must keep track of which elements in the sketch correspond to \r
+ // which elements in the model so connections can be constructed \r
+ // accurately\r
+ HashMap<SketchElement, Element2> elementMap = new HashMap<SketchElement, Element2>();\r
+ \r
+ for (SketchElement element : sketch.getElements()) {\r
+ Element2 e = element.getWriteableElement(0, 0);\r
+ //model.addElement(e);\r
+ //elementMap.put(element, e);\r
+ }\r
+ \r
+ for (SketchConnection connection : sketch.getConnections()) {\r
+ Connection2 c = connection.getWriteableConnection();\r
+ //model.addConnection(c);\r
+ }\r
+ \r
+ offset += sketch.getWidth() + 100;\r
+ }\r
+ \r
+ return null;\r
+ }\r
+ \r
+ private String readVariables(BufferedReader reader, String line) \r
+ throws IOException {\r
+ \r
+ String category = null;\r
+ \r
+ do {\r
+ if (line.isEmpty()) {\r
+ continue;\r
+ }\r
+ \r
+ StringBuilder buffer = new StringBuilder(line);\r
+ \r
+ while ((line = reader.readLine()) != null) {\r
+ if (line.endsWith("\\"))\r
+ buffer.append(line.substring(0, line.length()-1));\r
+ else\r
+ buffer.append(line);\r
+ \r
+ if (line.endsWith("|"))\r
+ break;\r
+ }\r
+ \r
+ String str = buffer.toString();\r
+ \r
+ // TODO: must handle categories other than .Control\r
+ \r
+ Variable2 var = MdlUtils.getPossibleVariable(str, category);\r
+ if (var != null) {\r
+ variables.put(var.getName(), var);\r
+ continue;\r
+ }\r
+ \r
+ System.err.println("unrecognized variable "+str);\r
+ \r
+ } while ((line = reader.readLine()) != null && !line.startsWith(SKETCH_START));\r
+ \r
+ return line;\r
+ }\r
+ \r
+ private String readSketches(BufferedReader reader, String line) \r
+ throws IOException {\r
+ \r
+ Sketch2 sketch = null;\r
+ \r
+ do {\r
+ if (line.startsWith(SKETCH_START)) {\r
+ sketch = new Sketch2();\r
+ sketches.add(sketch);\r
+ continue;\r
+ }\r
+ else if (line.startsWith(SKETCH_VERSION)) {\r
+ // version declaration, nothing to do here\r
+ continue;\r
+ }\r
+ else if (line.startsWith("*")) {\r
+ sketch.setName(line.substring(1));\r
+ continue;\r
+ }\r
+ else if (line.startsWith("$")) {\r
+ // font declaration, nothing to do here\r
+ continue;\r
+ }\r
+ \r
+ SketchConnection connection = MdlUtils.getPossibleSketchConnection(line);\r
+ if (connection != null) {\r
+ sketch.addSketchObject(connection);\r
+ continue;\r
+ }\r
+ \r
+ SketchVariable variable = MdlUtils.getPossibleSketchVariable(line, variables);\r
+ if (variable != null) {\r
+ sketch.addSketchObject(variable);\r
+ continue;\r
+ }\r
+ \r
+ SketchValve valve = MdlUtils.getPossibleSketchValve(line);\r
+ if (valve != null) {\r
+ // the next row after a valve should always the variable associated with the valve\r
+ SketchVariable attached = MdlUtils.getPossibleSketchVariable(reader.readLine(), variables);\r
+ if (attached == null || !attached.isAttached()) {\r
+ // TODO: should also verify that the variable is in fact attached\r
+ System.err.println("attached variable not found for valve");\r
+ continue;\r
+ }\r
+ valve.setAttachedVariable(attached);\r
+ sketch.addSketchObject(valve);\r
+ sketch.addSketchObject(attached);\r
+ continue;\r
+ }\r
+ \r
+ SketchComment comment = MdlUtils.getPossibleSketchComment(line);\r
+ if (comment != null) {\r
+ if (comment.hasTextNextLine()) {\r
+ comment.setText(reader.readLine());\r
+ }\r
+ \r
+ if (comment.isIOElement()) {\r
+ System.err.println("IO elements are not currently supported");\r
+ continue;\r
+ }\r
+ \r
+ sketch.addSketchObject(comment);\r
+ continue;\r
+ }\r
+ \r
+ // if we got this far, the element was not recognized\r
+ System.err.println("unrecognized element "+line);\r
+ \r
+ } while ((line = reader.readLine()) != null && !line.startsWith(SKETCH_END));\r
+ \r
+ return line;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport;\r
+\r
+import java.util.HashMap;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.sysdyn.mdlImport.model.SketchComment;\r
+import org.simantics.sysdyn.mdlImport.model.SketchConnection;\r
+import org.simantics.sysdyn.mdlImport.model.SketchElement;\r
+import org.simantics.sysdyn.mdlImport.model.SketchValve;\r
+import org.simantics.sysdyn.mdlImport.model.SketchVariable;\r
+import org.simantics.sysdyn.mdlImport.model.Variable2;\r
+import org.simantics.sysdyn.mdlImport.model.Valve2.TextPosition;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class MdlUtils {\r
+ \r
+ public enum ConnectionType {\r
+ ARROW, LINE_ARROW, LINE_SEGMENT, OTHER\r
+ }\r
+ \r
+ public enum CommentIcon {\r
+ CLOUD, OTHER\r
+ }\r
+\r
+ // most of this data is from the documentation of the .mdl file format \r
+ // available in http://www.vensim.com/documentation/24305.htm\r
+\r
+ // a Vensim variable name is either a plain string that contains letters, \r
+ // numbers and whitespace, or a quoted string that can also contain any \r
+ // special characters (including other quotation marks that must be escaped)\r
+ private static final String VAR_NAME_QUOTED =\r
+ "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"";\r
+ private static final String VAR_NAME_SIMPLE =\r
+ "[A-Za-z](?![ \\w]*\\()(?: *\\w+)*";\r
+ private static final String VAR_NAME =\r
+ "("+VAR_NAME_QUOTED+"|"+VAR_NAME_SIMPLE+")";\r
+ \r
+ private static final String SUBSCRIPT =\r
+ "("+VAR_NAME_SIMPLE+")\\[("+VAR_NAME_SIMPLE+"(?:,"+VAR_NAME_SIMPLE+")*)\\]";\r
+\r
+ // the first part of the variable string is the variable name \r
+ // followed by a delimiter which depends on the type of the declaration\r
+ private static final String VARIABLE_PATTERN =\r
+ VAR_NAME+"\\s*=\\s*";\r
+ private static final String SUBSCRIPT_PATTERN =\r
+ SUBSCRIPT+"\\s*=\\s*";\r
+ private static final String VALUE_NEW_PATTERN =\r
+ VAR_NAME+"\\s*:\\s*";\r
+ private static final String VALUE_EQUALS_PATTERN =\r
+ VAR_NAME+"\\s*<->\\s*";\r
+ \r
+ // the second part is the equation followed by '~'\r
+ private static final String EQUATION_PATTERN =\r
+ "([^~]*?(?:"+VAR_NAME_QUOTED+"[^~]*?)*)\\s*~\\s*";\r
+ \r
+ // the third part is the unit followed by '~'\r
+ private static final String UNIT_PATTERN =\r
+ "([^~]*?)\\s*~\\s*";\r
+ \r
+ // the last part is the description followed by '|'\r
+ private static final String DESC_PATTERN =\r
+ "([^\\|]*?)\\s*\\|";\r
+\r
+ public static final String variablePattern = \r
+ VARIABLE_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
+ public static final String subscriptPattern =\r
+ SUBSCRIPT_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
+ public static final String valueNewPattern = \r
+ VALUE_NEW_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
+ public static final String valueEqualsPattern = \r
+ VALUE_EQUALS_PATTERN+EQUATION_PATTERN+UNIT_PATTERN+DESC_PATTERN;\r
+ \r
+ private static final int variableName = 1;\r
+ private static final int variableEquation = 2;\r
+ private static final int variableUnit = 3;\r
+ private static final int variableDesc = 4;\r
+ \r
+ public static Variable2 getPossibleVariable(String line, String category) {\r
+ Matcher matcher = Pattern.compile(variablePattern).matcher(line);\r
+ \r
+ if (!matcher.matches()) {\r
+ return null;\r
+ }\r
+ \r
+ String name = matcher.group(variableName);\r
+ String equation = matcher.group(variableEquation);\r
+ String unit = matcher.group(variableUnit);\r
+ String description = matcher.group(variableDesc);\r
+ \r
+ return new Variable2(name, equation, unit, description);\r
+ }\r
+ \r
+ public static Pair<String, String> getPossibleIntegral(String equation) {\r
+ \r
+ Matcher matcher = Pattern.compile("INTEG\\s*\\((.*),(.*)\\)").matcher(equation);\r
+ if (matcher.matches()) {\r
+ return new Pair<String, String>(matcher.group(1), matcher.group(2));\r
+ }\r
+ \r
+ return null;\r
+ }\r
+ \r
+ // sketch object data is defined similarly\r
+ \r
+ private static final String SAVE = "(-?\\d+),";\r
+ private static final String SKIP = "-?\\d+,";\r
+ private static final String POINTS = "(\\d+\\|(?:\\(-?\\d+,-?\\d+\\)\\|)+)";\r
+ \r
+ public static final String sketchConnection =\r
+ // 1, id, from,to, shape,hid, pol, thick,hasf,dtype,res,color,font,np|plist\r
+ "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ "0,-1--1--1,.*,"+POINTS;\r
+ \r
+ // group indices for later use\r
+ private static final int connectionId = 1;\r
+ private static final int connectionFrom = 2;\r
+ private static final int connectionTo = 3;\r
+ private static final int connectionShape = 4;\r
+ private static final int connectionPoints = 5;\r
+ \r
+ private static final String COMMON =\r
+ // x, y, w, h, sh, bits,hid, hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+ SAVE+SAVE+SAVE+SAVE+SAVE+SAVE+SKIP+SKIP+SAVE+".*";\r
+ \r
+ public static final String sketchVariable =\r
+ // n, id, name, x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font)\r
+ "10,"+SAVE+VAR_NAME+","+COMMON;\r
+ public static final String sketchValve =\r
+ "11,"+SAVE+SAVE+ COMMON;\r
+ public static final String sketchComment =\r
+ "12,"+SAVE+SAVE+ COMMON;\r
+ \r
+ // group indices for later use\r
+ private static final int elementId = 1;\r
+ private static final int elementName = 2;\r
+ private static final int elementX = 3;\r
+ private static final int elementY = 4;\r
+ private static final int elementWidth = 5;\r
+ private static final int elementHeight = 6;\r
+ private static final int elementShape = 7;\r
+ private static final int elementBits = 8;\r
+ private static final int elementTextPos = 9;\r
+ \r
+ public static SketchConnection getPossibleSketchConnection(String line) {\r
+ Matcher matcher = Pattern.compile(sketchConnection).matcher(line);\r
+ \r
+ if (!matcher.matches()) {\r
+ return null;\r
+ }\r
+ \r
+ int id = Integer.parseInt(matcher.group(connectionId));\r
+ int from = Integer.parseInt(matcher.group(connectionFrom));\r
+ int to = Integer.parseInt(matcher.group(connectionTo));\r
+ ConnectionType type = getConnectionType(matcher);\r
+ \r
+ return new SketchConnection(id, from, to, type);\r
+ }\r
+ \r
+ public static SketchVariable getPossibleSketchVariable(String line, HashMap<String, Variable2> variables) {\r
+ Matcher matcher = Pattern.compile(sketchVariable).matcher(line);\r
+ \r
+ if (!matcher.matches()) {\r
+ return null;\r
+ }\r
+ \r
+ int id = Integer.parseInt(matcher.group(elementId));\r
+ Variable2 var = variables.get(matcher.group(elementName));\r
+ boolean attached = elementIsAttached(matcher);\r
+ boolean in = elementAllowsInBound(matcher);\r
+ boolean out = elementAllowsOutBound(matcher);\r
+ \r
+ SketchVariable variable = new SketchVariable(id, var, attached, in, out);\r
+ \r
+ initializeElement(variable, matcher);\r
+ \r
+ return variable;\r
+ }\r
+ \r
+ public static SketchValve getPossibleSketchValve(String line) {\r
+ Matcher matcher = Pattern.compile(sketchValve).matcher(line);\r
+ \r
+ if (!matcher.matches()) {\r
+ return null;\r
+ }\r
+ \r
+ int id = Integer.parseInt(matcher.group(elementId));\r
+ \r
+ SketchValve valve = new SketchValve(id);\r
+ \r
+ initializeElement(valve, matcher);\r
+ \r
+ return valve;\r
+ }\r
+ \r
+ public static SketchComment getPossibleSketchComment(String line) {\r
+ Matcher matcher = Pattern.compile(sketchComment).matcher(line);\r
+ \r
+ if (!matcher.matches()) {\r
+ return null;\r
+ }\r
+ \r
+ int id = Integer.parseInt(matcher.group(elementId));\r
+ CommentIcon icon = getCommentIcon(matcher);\r
+ boolean nextLine = elementHasCommentLine(matcher);\r
+ boolean isIO = elementIsIO(matcher);\r
+ \r
+ SketchComment comment = new SketchComment(id, icon, nextLine, isIO);\r
+ \r
+ initializeElement(comment, matcher);\r
+ \r
+ return comment;\r
+ }\r
+ \r
+ public static void initializeElement(SketchElement element, Matcher matcher) {\r
+ int x = Integer.parseInt(matcher.group(elementX));\r
+ int y = Integer.parseInt(matcher.group(elementY));\r
+ int w = Integer.parseInt(matcher.group(elementWidth));\r
+ int h = Integer.parseInt(matcher.group(elementHeight));\r
+ \r
+ element.setLocationAndSize(x, y, w, h);\r
+ }\r
+ \r
+ public static ConnectionType getConnectionType(Matcher matcher) {\r
+ switch(Integer.parseInt(matcher.group(connectionShape))) {\r
+ case 0: return ConnectionType.ARROW;\r
+ case 4: return ConnectionType.LINE_ARROW;\r
+ case 100: return ConnectionType.LINE_SEGMENT;\r
+ default: return ConnectionType.OTHER;\r
+ }\r
+ }\r
+ \r
+ public static CommentIcon getCommentIcon(Matcher matcher) {\r
+ switch(Integer.parseInt(matcher.group(elementName))) {\r
+ case 48: return CommentIcon.CLOUD;\r
+ default: return CommentIcon.OTHER;\r
+ }\r
+ }\r
+ \r
+ public static TextPosition getTextPos(Matcher matcher) {\r
+ switch (Integer.parseInt(matcher.group(elementTextPos))) {\r
+ case 0: return TextPosition.INSIDE;\r
+ case 1: return TextPosition.BELOW;\r
+ case 2: return TextPosition.LEFT;\r
+ case 3: return TextPosition.ABOVE;\r
+ case 4: return TextPosition.RIGHT;\r
+ default: return TextPosition.UNSET;\r
+ }\r
+ }\r
+ \r
+ public static boolean elementIsAttached(Matcher matcher) {\r
+ return (Integer.parseInt(matcher.group(elementShape)) & 1<<5) != 0;\r
+ }\r
+ \r
+ public static boolean elementAllowsInBound(Matcher matcher) {\r
+ return (Integer.parseInt(matcher.group(elementBits)) & 1) != 0;\r
+ }\r
+ \r
+ public static boolean elementAllowsOutBound(Matcher matcher) {\r
+ return (Integer.parseInt(matcher.group(elementBits)) & 1<<1) != 0;\r
+ }\r
+ \r
+ public static boolean elementHasCommentLine(Matcher matcher) {\r
+ return (Integer.parseInt(matcher.group(elementBits)) & 1<<2) != 0;\r
+ }\r
+ \r
+ public static boolean elementIsIO(Matcher matcher) {\r
+ return (Integer.parseInt(matcher.group(elementBits)) & 1<<3) != 0;\r
+ }\r
+ \r
+ public static String normalize(String str) {\r
+ // start by removing all tabs from the string, not really necessary \r
+ // but does make the equation cleaner (could also be done in the read \r
+ // method above)\r
+ str = str.replaceAll("\t", "");\r
+\r
+ // remove inline :AND: and :OR: etc (not done currently)\r
+\r
+ // transform all variable names to (single-)quoted modelica syntax\r
+ StringBuilder result = new StringBuilder();\r
+ int offset = 0;\r
+\r
+ Matcher matcher = Pattern.compile(VAR_NAME).matcher(str);\r
+ while (matcher.find()) {\r
+ result.append(str.substring(offset, matcher.start()));\r
+\r
+ String replacement = matcher.group();\r
+\r
+ if (replacement.startsWith("\"")) {\r
+ replacement = replacement.substring(1, replacement.length() - 1);\r
+ }\r
+\r
+ result.append('\'');\r
+ result.append(replacement);\r
+ result.append('\'');\r
+\r
+ offset = matcher.end();\r
+ }\r
+ if (offset < str.length()) {\r
+ result.append(str.substring(offset));\r
+ }\r
+\r
+ str = result.toString();\r
+\r
+ return str;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.mdlImport.ImportUtils;\r
+\r
+public class Auxiliary extends Variable {\r
+\r
+ @Override\r
+ public Resource getExpression(WriteGraph graph, Expression expression) throws DatabaseException {\r
+ \r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Resource e = GraphUtils.create2(graph, \r
+ sr.NormalExpression,\r
+ sr.Expression_equation, ImportUtils.escapeExpression(expression.getExpression()).trim());\r
+ return e;\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(!graph.isInstanceOf(parent, sr.Configuration))\r
+ return;\r
+ createVariable(graph, parent, sr.Auxiliary, sr.AuxiliarySymbol, xOffset, yOffset);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.Arrays;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class Auxiliary2 extends ModelVariable {\r
+ \r
+ protected String equation;\r
+\r
+ public Auxiliary2(double x, double y, \r
+ String name, String unit, Range range, String description, \r
+ String equation) {\r
+ this.equation = equation;\r
+ }\r
+ \r
+ public Auxiliary2(double x, double y, Variable2 variable, String equation) {\r
+ this.equation = equation;\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+\r
+ Resource variable = createVariable(graph, sr.Auxiliary, parent);\r
+\r
+ Resource expression = GraphUtils.create2(graph, sr.NormalExpression,\r
+ sr.Expression_equation, equation,\r
+ l0.PartOf, variable);\r
+ // TODO: why is the expressoin stored in two places?\r
+ graph.claim(variable, sr.Variable_expressionList, ListUtils.create(graph, Arrays.asList(expression)));\r
+\r
+ createSymbol(graph, sr.AuxiliarySymbol, variable, parent);\r
+\r
+ setResource(variable);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class Cloud extends Element {\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph); \r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ \r
+ if(!graph.isInstanceOf(parent, sr.Configuration))\r
+ return;\r
+ \r
+ Resource diagram = graph.getSingleObject(parent, mr.CompositeToDiagram);\r
+\r
+ if(diagram == null)\r
+ return;\r
+ \r
+ Resource cloud = GraphUtils.create2(graph, \r
+ sr.Cloud);\r
+\r
+ graph.claim(parent, l0.ConsistsOf, cloud);\r
+\r
+ \r
+\r
+ Resource symbol = GraphUtils.create2(graph, \r
+ sr.CloudSymbol,\r
+ mr.ElementToComponent, cloud);\r
+\r
+ double[] transform = {1.0, 0.0, 0.0, 1.0, getX() + xOffset, getY() + yOffset};\r
+ graph.claimLiteral(symbol, dr.HasTransform, g2d.Transform, transform);\r
+\r
+ OrderedSetUtils.add(graph, diagram, symbol);\r
+\r
+ setResource(cloud);\r
+\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Cloud2 extends Element2 {\r
+ \r
+ public Cloud2() {\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Comment2 extends Element2 {\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public abstract class Connection implements IWriteableMDLObject {\r
+ protected Element start, end;\r
+ \r
+ public Resource writeConnection(WriteGraph graph, Resource configuration, Resource connectionType, Resource connectionSymbol) throws DatabaseException {\r
+ if(configuration == null || graph == null \r
+ || start.getResource() == null || end.getResource() == null) {\r
+ return null;\r
+ }\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph); \r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ StructuralResource2 sr2 = StructuralResource2.getInstance(graph);\r
+ \r
+ Resource diagram = graph.getPossibleObject(configuration, mr.CompositeToDiagram);\r
+ Resource startElement = graph.getPossibleObject(start.getResource(), mr.ComponentToElement);\r
+ Resource endElement = graph.getPossibleObject(end.getResource(), mr.ComponentToElement);\r
+ if(diagram == null || startElement == null || endElement == null)\r
+ return null;\r
+ \r
+ \r
+ if(connectionType == null)\r
+ connectionType = sr.Dependency;\r
+ \r
+ if(connectionSymbol == null)\r
+ connectionSymbol = sr.DependencyConnection;\r
+ \r
+ // Build the connection to configuration\r
+ Resource connection = GraphUtils.create2(graph, \r
+ connectionType,\r
+ sr.Variable_HasHead, end.getResource(),\r
+ sr.Variable_HasTail, start.getResource(),\r
+ l0.PartOf, configuration);\r
+ graph.claim(connection, mr.Mapped, connection);\r
+ \r
+ \r
+ // Build diagram connectors and connection\r
+ Resource tailConnector = GraphUtils.create2(graph, \r
+ dr.Connector,\r
+ sr.HasTailTerminal, startElement);\r
+ \r
+ Resource headConnector = GraphUtils.create2(graph,\r
+ dr.Connector,\r
+ sr.HasHeadTerminal, endElement,\r
+ dr.AreConnected, tailConnector);\r
+ \r
+ Resource diagramConnection = GraphUtils.create2(graph, \r
+ connectionSymbol,\r
+ sr2.HasConnectionType, sr.SysdynConnectionType,\r
+ mr.DiagramConnectionToConnection, connection,\r
+ dr.HasArrowConnector, headConnector,\r
+ dr.HasPlainConnector, tailConnector);\r
+ \r
+ OrderedSetUtils.add(graph, diagram, diagramConnection);\r
+ \r
+ return connection;\r
+ }\r
+\r
+ public Element getStart() {\r
+ return start;\r
+ }\r
+\r
+ public void setStart(Element start) {\r
+ this.start = start;\r
+ }\r
+\r
+ public Element getEnd() {\r
+ return end;\r
+ }\r
+\r
+ public void setEnd(Element end) {\r
+ this.end = end;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+public abstract class Connection2 implements IWriteableObject {\r
+ \r
+ protected Element2 head;\r
+ protected Element2 tail;\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException {\r
+ System.err.println("Writing connection");\r
+ }\r
+ \r
+ protected void writeConnection() {\r
+ \r
+ }\r
+ \r
+ public void setHead(Element2 head) {\r
+ this.head = head;\r
+ }\r
+ \r
+ public void setTail(Element2 tail) {\r
+ this.tail = tail;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class Dependency extends Connection {\r
+ \r
+ private double angle;\r
+ \r
+ public Dependency() {\r
+ this(-0.1);\r
+ }\r
+ \r
+ public Dependency(double angle) {\r
+ this.angle = angle; \r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) {\r
+ if(parent == null || graph == null || start == null || end == null)\r
+ return;\r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Resource connection = writeConnection(graph, parent, sr.Dependency, sr.DependencyConnection);\r
+\r
+ if(connection != null) {\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ Resource diagramConnection = graph.getSingleObject(connection, mr.ConnectionToDiagramConnection);\r
+ graph.claimLiteral(diagramConnection, sr.Dependency_angle, angle);\r
+ }\r
+\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ }\r
+\r
+ public double getAngle() {\r
+ return angle;\r
+ }\r
+\r
+ public void setAngle(double angle) {\r
+ this.angle = angle;\r
+ }\r
+ \r
+ \r
+ \r
+ /**\r
+ * Returns an angle in radians between straight line from (x0,y0) to (x2,y2)\r
+ * and an arc from (x0,y0) to (x2,y2) thru (x1,y1). The angle\r
+ * is measured at (x0,y0) and is between -PI and PI.\r
+ */\r
+ public static double angleOfArc(\r
+ double x0, double y0, \r
+ double x1, double y1,\r
+ double x2, double y2) {\r
+ double dx0 = x1-x0;\r
+ double dy0 = y1-y0;\r
+ double dx1 = x1-x2;\r
+ double dy1 = y1-y2;\r
+ double dx = x2-x0;\r
+ double dy = y2-y0;\r
+ // Length of cross product (p1-p0)x(p2-p0)\r
+ double dd = dx0*dy - dy0*dx; \r
+ \r
+ if(Math.abs(dd) < 1e-6) // Points are (almost) collinear\r
+ return 0.0;\r
+ else { \r
+ // (p1-p0)*(p1-p2) / dd\r
+ double offset = (dx0*dx1 + dy0*dy1) / dd;\r
+ double angle = Math.PI*0.5 - Math.atan(offset);\r
+ if(dd > 0.0)\r
+ angle = angle-Math.PI;\r
+ return angle;\r
+ \r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Dependency2 extends Connection2 {\r
+ \r
+ private boolean showArrow;\r
+ private boolean showDelay;\r
+ \r
+ public Dependency2(boolean showArrow, boolean showDelay) {\r
+ this.showArrow = showArrow;\r
+ this.showDelay = showDelay;\r
+ }\r
+\r
+ @Override\r
+ public void setHead(Element2 head) {\r
+ // TODO: make sure head is of the right type\r
+ super.setHead(head);\r
+ }\r
+\r
+ @Override\r
+ public void setTail(Element2 Tail) {\r
+ // TODO: make sure tail is of the right type\r
+ super.setTail(tail);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+public abstract class Element implements IWriteableMDLElement {\r
+ \r
+ protected int x, y;\r
+ protected Resource resource;\r
+ protected String name;\r
+ protected ArrayList<Connection> connections;\r
+ \r
+ protected Resource getExpression(WriteGraph graph, Expression expression)\r
+ throws DatabaseException {\r
+ return null;\r
+ } \r
+ \r
+ public int getX() {\r
+ return x;\r
+ }\r
+\r
+ public void setX(int x) {\r
+ this.x = x;\r
+ }\r
+\r
+ public int getY() {\r
+ return y;\r
+ }\r
+\r
+ public void setY(int y) {\r
+ this.y = y;\r
+ }\r
+\r
+ public String getName() {\r
+ if(name == null)\r
+ return "Name";\r
+ return name;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+\r
+ public void setResource(Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+ \r
+ public ArrayList<Connection> getConnections() {\r
+ if(connections == null)\r
+ connections = new ArrayList<Connection>();\r
+ return connections;\r
+ }\r
+\r
+ public void setConnections(ArrayList<Connection> connections) {\r
+ this.connections = connections;\r
+ }\r
+ \r
+ public void addConnection(Connection connection) {\r
+ getConnections().add(connection);\r
+ }\r
+}\r
+\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+\r
+public class Element2 implements IWriteableObject {\r
+\r
+ private int x;\r
+ private int y;\r
+\r
+ private Resource resource;\r
+\r
+ public Element2() {\r
+\r
+ }\r
+\r
+ // public Element2(int x, int y, int width, int height) {\r
+ // this.x = x;\r
+ // this.y = y;\r
+ // this.width = width;\r
+ // this.height = height;\r
+ // \r
+ // this.resource = null;\r
+ // }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException {\r
+ System.err.println("Writing element");\r
+ }\r
+\r
+ // TODO: is this the right place for this?\r
+\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+\r
+ public void setResource(Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+\r
+ public Resource createSymbol(WriteGraph graph, Resource type, Resource variable, Resource parent) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+\r
+ Resource symbol = GraphUtils.create2(graph, type, \r
+ mr.ElementToComponent, variable);\r
+\r
+ double[] transform = { 1.0, 0.0, 0.0, 1.0, x, y };\r
+ graph.claimLiteral(symbol, dr.HasTransform, g2d.Transform, transform, Bindings.DOUBLE_ARRAY);\r
+\r
+ Resource diagram = graph.getSingleObject(parent, mr.CompositeToDiagram);\r
+ OrderedSetUtils.add(graph, diagram, symbol);\r
+\r
+ return symbol;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+\r
+public class EquivalenceSubscript extends Subscript {\r
+ \r
+ public String getEquivalentToName() {\r
+ String name = "";\r
+ if(expressions != null && expressions.get(0) != null) {\r
+ name = expressions.get(0).getExpression().trim();\r
+ }\r
+ return name;\r
+ }\r
+\r
+ public void setEquivalentTo(Subscript equivalentTo) {\r
+ setExpressions(equivalentTo.getExpressions());\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ super.write(graph, parent, xOffset, yOffset);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+\r
+public class Expression {\r
+ \r
+ private String range, expression;\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return (range != null ? "[" + range + "]: " : "") + expression; \r
+ }\r
+\r
+ public String getRange() {\r
+ return range;\r
+ }\r
+\r
+ public void setRange(String range) {\r
+ this.range = range;\r
+ }\r
+\r
+ public String getExpression() {\r
+ if (expression == null)\r
+ return "";\r
+ return expression;\r
+ }\r
+\r
+ public void setExpression(String expression) {\r
+ this.expression = expression;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class Flow extends Connection {\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ writeConnection(graph, parent, sr.Flow, sr.FlowConnection);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Flow2 extends Connection2 {\r
+ \r
+ public Flow2() {\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void setHead(Element2 head) {\r
+ // TODO: make sure head is of the right type\r
+ super.setHead(head);\r
+ }\r
+\r
+ @Override\r
+ public void setTail(Element2 tail) {\r
+ // TODO: make sure tail is of the right type\r
+ super.setTail(tail);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.mdlImport.ImportUtils;\r
+\r
+public class Function extends Variable {\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(!graph.isInstanceOf(parent, sr.SysdynModel))\r
+ return;\r
+ Layer0 l0 = Layer0.getInstance(graph); \r
+ \r
+ Resource function = GraphUtils.create2(graph, \r
+ sr.SysdynModelicaFunction,\r
+ l0.HasName, ImportUtils.escapeName(this.getName()));\r
+ \r
+ if(comments != null && comments.length() > 0)\r
+ graph.claimLiteral(function, l0.HasDescription, comments);\r
+ \r
+ if(expressions != null && expressions.get(0) != null) {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(" input Real a;\n");\r
+ sb.append(" output Real result;\n");\r
+ sb.append("algorithm\n");\r
+ sb.append(" result := interpolate(a, " + expressions.get(0).getExpression() + ");");\r
+ graph.claimLiteral(function, sr.SysdynModelicaFunction_modelicaFunctionCode, sb.toString());\r
+ }\r
+\r
+ graph.claim(parent, l0.ConsistsOf, function);\r
+ resource = function;\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+\r
+public interface IWriteableMDLElement {\r
+\r
+ /**\r
+ * Writes an element with coordinates (variable, cloud) to the given resource.\r
+ * \r
+ * Offsets determine where the parent view is located in the combined diagram\r
+ * \r
+ * @param graph WriteGraph\r
+ * @param parent The resource where the object is located\r
+ * @param xOffset xOffset of the view in the diagram\r
+ * @param yOffset yOffset of the view in the diagram\r
+ */\r
+ public void write(WriteGraph graph, Resource parent, double xOffset, double yOffset);\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+\r
+public interface IWriteableMDLObject {\r
+ \r
+ /**\r
+ * Writes an object with no coordinates (connection, model, view) to the given resource\r
+ * \r
+ * @param graph WriteGraph\r
+ * @param parent The resource where the object is located\r
+ */\r
+ public void write(WriteGraph graph, Resource parent);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+public interface IWriteableObject {\r
+ \r
+ /**\r
+ * @param graph WriteGraph\r
+ * @param parent The resource where the object is located\r
+ * @throws DatabaseException \r
+ */\r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.utils.ModelUtils;\r
+\r
+public class Model implements IWriteableMDLObject {\r
+\r
+ private String name, timeUnit, saveper;\r
+ private double startTime = 0, endTime = 10, timeStep = 1;\r
+ \r
+ private HashMap<String, Element> elementMap = new HashMap<String, Element>();\r
+ private ArrayList<Subscript> subscripts = new ArrayList<Subscript>();\r
+ private ArrayList<Function> functions = new ArrayList<Function>();\r
+ private ArrayList<Connection> connections = new ArrayList<Connection>();\r
+ private ArrayList<View> views = new ArrayList<View>();\r
+ private ArrayList<Element> unlocatedElements = new ArrayList<Element>();\r
+ \r
+ public void addElement(Element element) {\r
+ if(element instanceof Subscript)\r
+ addSubscript((Subscript)element);\r
+ else if(element instanceof Function)\r
+ addFunction((Function)element);\r
+ else\r
+ unlocatedElements.add(element);\r
+ if(element.getName() != null)\r
+ elementMap.put(element.getName(), element);\r
+ }\r
+ \r
+ public void addSubscript(Subscript subscript) {\r
+ subscripts.add(subscript);\r
+ }\r
+ \r
+ public void addFunction(Function function) {\r
+ functions.add(function);\r
+ }\r
+ \r
+ public void addElement(View view, Element element) {\r
+ if(element instanceof Subscript)\r
+ addSubscript((Subscript)element);\r
+ else {\r
+ if(unlocatedElements.contains(element))\r
+ unlocatedElements.remove(element);\r
+ view.addElement(element);\r
+ }\r
+ if(element.getName() != null)\r
+ elementMap.put(element.getName(), element);\r
+ }\r
+ \r
+ public void relocateElement(View view, Element element) {\r
+ if(unlocatedElements.contains(element))\r
+ unlocatedElements.remove(element);\r
+ for(View v : views) {\r
+ if(v.getElements().contains(element))\r
+ v.getElements().remove(element);\r
+ }\r
+ view.addElement(element);\r
+ }\r
+ \r
+ public void removeElement(Element element) {\r
+ if(unlocatedElements.contains(element))\r
+ unlocatedElements.remove(element);\r
+ \r
+ for(View view : views) {\r
+ if(view.getElements().contains(element)) {\r
+ view.getElements().remove(element);\r
+ }\r
+ }\r
+ \r
+ // just to be sure: loop the whole elementMap and don't trust the element's name\r
+ String toBeRemoved = null;\r
+ for(String key : elementMap.keySet()) {\r
+ if(element.equals(elementMap.get(key))) {\r
+ toBeRemoved = key;\r
+ break;\r
+ }\r
+ }\r
+ if(toBeRemoved != null)\r
+ elementMap.remove(toBeRemoved);\r
+ }\r
+ \r
+ public ArrayList<Element> getUnlocatedElements() {\r
+ return unlocatedElements;\r
+ }\r
+ \r
+ public Element getElement(String name) {\r
+ return elementMap.get(name);\r
+ }\r
+ \r
+ public void addConnection(Connection connection) {\r
+ connections.add(connection);\r
+ if(connection.getStart() != null &&\r
+ !connection.getStart().getConnections().contains(connection)) {\r
+ connection.getStart().addConnection(connection);\r
+ }\r
+ if(connection.getEnd() != null &&\r
+ !connection.getEnd().getConnections().contains(connection)) {\r
+ connection.getEnd().addConnection(connection);\r
+ }\r
+ }\r
+ \r
+ public ArrayList<Connection> getConnections() {\r
+ return connections;\r
+ }\r
+ \r
+ public ArrayList<Subscript> getSubscripts() {\r
+ return subscripts;\r
+ }\r
+\r
+ public String getName() {\r
+ if(name == null)\r
+ return "ModelName";\r
+ return name;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public String getTimeUnit() {\r
+ return timeUnit;\r
+ }\r
+\r
+ public void setTimeUnit(String timeUnit) {\r
+ this.timeUnit = timeUnit;\r
+ }\r
+\r
+ public String getSaveper() {\r
+ return saveper;\r
+ }\r
+\r
+ public void setSaveper(String saveper) {\r
+ this.saveper = saveper;\r
+ }\r
+\r
+ public double getStartTime() {\r
+ return startTime;\r
+ }\r
+\r
+ public void setStartTime(double startTime) {\r
+ this.startTime = startTime;\r
+ }\r
+\r
+ public double getEndTime() {\r
+ return endTime;\r
+ }\r
+\r
+ public void setEndTime(double endTime) {\r
+ this.endTime = endTime;\r
+ }\r
+\r
+ public double getTimeStep() {\r
+ return timeStep;\r
+ }\r
+\r
+ public void setTimeStep(double timeStep) {\r
+ this.timeStep = timeStep;\r
+ }\r
+\r
+ public HashMap<String, Element> getElementMap() {\r
+ return elementMap;\r
+ }\r
+\r
+ public void setElementMap(HashMap<String, Element> elementMap) {\r
+ this.elementMap = elementMap;\r
+ }\r
+\r
+ public void setSubscripts(ArrayList<Subscript> subscripts) {\r
+ this.subscripts = subscripts;\r
+ }\r
+\r
+ public void setConnections(ArrayList<Connection> connections) {\r
+ this.connections = connections;\r
+ }\r
+ \r
+ public void addView(View view) {\r
+ views.add(view);\r
+ }\r
+ \r
+ public ArrayList<View> getViews() {\r
+ return views;\r
+ }\r
+\r
+ /**\r
+ * Write the model to a project\r
+ * @param graph WriteGraph\r
+ * @param parent Project resource\r
+ */\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ \r
+ \r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SimulationResource simu = SimulationResource.getInstance(graph);\r
+\r
+ Resource model = ModelUtils.createModelAt(graph, parent);\r
+ graph.claimLiteral(model, l0.HasLabel, getName());\r
+ graph.claimLiteral(model, sr.SysdynModel_startTime, startTime);\r
+ graph.claimLiteral(model, sr.SysdynModel_stopTime, endTime);\r
+
+\r
+ Resource conf = graph.getSingleObject(model, simu.HasConfiguration);\r
+ \r
+ for(Subscript s : subscripts) {\r
+ s.write(graph, conf, 0, 0);\r
+ }\r
+\r
+ // Create the grid n*n of views:\r
+ \r
+ double n = Math.sqrt(views.size());\r
+ n = Math.ceil(n);\r
+ \r
+ int width = 0, height = 0;\r
+ for(View v : views) {\r
+ if(v.getWidth() > width)\r
+ width = v.getWidth();\r
+ if(v.getHeight() > height)\r
+ height = v.getHeight();\r
+ }\r
+\r
+ for(int i = 0; i < n; i++) {\r
+ for(int j = 0; j < n; j++) {\r
+ int index = i * (int)n + j;\r
+ if(index < views.size()) {\r
+ View v = views.get(index);\r
+ v.setxOffset(width * j);\r
+ v.setyOffset(height * i);\r
+ v.write(graph, conf);\r
+ }\r
+ }\r
+ }\r
+ \r
+ for(Element e : unlocatedElements) {\r
+ e.write(graph, conf, 0, 0);\r
+ }\r
+\r
+ for(Connection c : connections) {\r
+ c.write(graph, conf);\r
+ }\r
+ \r
+ for(Function f : functions) {\r
+ f.write(graph, model, 0, 0);\r
+ }\r
+\r
+\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.sysdyn.utils.ModelUtils;\r
+\r
+public class Model2 implements IWriteableObject {\r
+ \r
+ private String name;\r
+ // necessary simulation parameters\r
+ private double start, stop, step;\r
+ \r
+ // the structure of the model\r
+ private ArrayList<Element2> elements;\r
+ private ArrayList<Connection2> connections;\r
+ \r
+ public Model2(String name) {\r
+ this.name = name;\r
+ \r
+ elements = new ArrayList<Element2>();\r
+ connections = new ArrayList<Connection2>();\r
+ }\r
+\r
+ public double getStart() {\r
+ return start;\r
+ }\r
+\r
+ public void setStart(double start) {\r
+ this.start = start;\r
+ }\r
+\r
+ public double getStop() {\r
+ return stop;\r
+ }\r
+\r
+ public void setStop(double stop) {\r
+ this.stop = stop;\r
+ }\r
+\r
+ public double getStep() {\r
+ return step;\r
+ }\r
+\r
+ public void setStep(double step) {\r
+ this.step = step;\r
+ }\r
+ \r
+ public void addElement(Element2 element) {\r
+ elements.add(element);\r
+ }\r
+ \r
+ public void addConnection(Connection2 connection) {\r
+ connections.add(connection);\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException { \r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SimulationResource sim = SimulationResource.getInstance(graph);\r
+ \r
+ Resource model = ModelUtils.createModel(graph);\r
+ graph.claimLiteral(model, l0.HasLabel, name, Bindings.STRING);\r
+ \r
+ // TODO: set simulatin parameters\r
+ \r
+ Resource configuration = graph.getSingleObject(model, sim.HasConfiguration);\r
+ \r
+ for (Element2 e : elements) {\r
+ e.write(graph, configuration);\r
+ }\r
+ \r
+ for (Connection2 c : connections) {\r
+ c.write(graph, configuration);\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class ModelVariable extends Element2 {\r
+\r
+ protected String name;\r
+ protected Range range;\r
+ protected String unit;\r
+ protected String description;\r
+\r
+ public ModelVariable() {\r
+\r
+ }\r
+\r
+ public Resource createVariable(WriteGraph graph, Resource type, Resource parent) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+\r
+ Resource variable = GraphUtils.create2(graph, type, \r
+ l0.HasName, name,\r
+ l0.PartOf, parent);\r
+ graph.claim(variable, mr.Mapped, variable);\r
+ \r
+ if (unit != null && !unit.isEmpty()) {\r
+ graph.claimLiteral(variable, sr.Variable_unit, unit, Bindings.STRING);\r
+ }\r
+ if (description != null && !description.isEmpty()) {\r
+ graph.claimLiteral(variable, l0.HasDescription, description, Bindings.STRING);\r
+ }\r
+ if (range != null) {\r
+ //graph.claimLiteral(variable, sr.HasRangeStart, rangeStart);\r
+ //graph.claimLiteral(variable, sr.HasRangeEnd, rangeEnd);\r
+ //graph.claimLiteral(variable, sr.HasRangeStep, rangeStep);\r
+ }\r
+\r
+ return variable;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Range {\r
+ \r
+ private double start;\r
+ private double end;\r
+ private double step;\r
+ \r
+ public Range(double start, double end, double step) {\r
+ this.start = start;\r
+ this.end = end;\r
+ this.step = step;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+public class Sketch2 {\r
+ \r
+ private String name;\r
+ \r
+ private HashMap<Integer, SketchObject> objectMap;\r
+ private ArrayList<SketchConnection> unfinished;\r
+ \r
+ public Sketch2() {\r
+ objectMap = new HashMap<Integer, SketchObject>();\r
+ unfinished = new ArrayList<SketchConnection>();\r
+ }\r
+ \r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+ \r
+ public SketchObject getSketchObject(int index) {\r
+ return objectMap.get(index);\r
+ }\r
+\r
+ public void addSketchObject(SketchConnection object) {\r
+ unfinished.add(object);\r
+ \r
+ addSketchObject((SketchObject)object);\r
+ }\r
+ \r
+ public void addSketchObject(SketchObject object) {\r
+ if (objectMap.get(object.getId()) != null) {\r
+ System.err.println("duplicate object with id "+object.getId());\r
+ return;\r
+ }\r
+ objectMap.put(object.getId(), object);\r
+ \r
+ // NOTE: could just do another pass to update connections at the end \r
+ // or just use a priority queue or something but the number of \r
+ // unfinished connections at any given time should be relatively \r
+ // small in practice so it does not matter that this is inefficient\r
+ Iterator<SketchConnection> i = unfinished.iterator();\r
+ while (i.hasNext()) {\r
+ SketchConnection connection = i.next();\r
+ \r
+ SketchObject from = objectMap.get(connection.getFromId());\r
+ SketchObject to = objectMap.get(connection.getToId());\r
+ \r
+ if (from != null && to != null) {\r
+ // connections can only connect elements so if this is not the \r
+ // case something has gone wrong with the indexing\r
+ assert from instanceof SketchElement;\r
+ assert to instanceof SketchElement;\r
+ \r
+ connection.setFrom((SketchElement)from);\r
+ connection.setTo((SketchElement)to);\r
+ \r
+ i.remove();\r
+ }\r
+ }\r
+ }\r
+\r
+ // TODO: ugly and inefficient\r
+ \r
+ public List<SketchElement> getElements() {\r
+ ArrayList<SketchElement> list = new ArrayList<SketchElement>();\r
+ for (SketchObject o : objectMap.values()) {\r
+ if (o instanceof SketchElement) {\r
+ list.add((SketchElement)o);\r
+ }\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ public List<SketchConnection> getConnections() {\r
+ ArrayList<SketchConnection> list = new ArrayList<SketchConnection>();\r
+ for (SketchObject o : objectMap.values()) {\r
+ if (o instanceof SketchConnection) {\r
+ list.add((SketchConnection)o);\r
+ }\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ public int getWidth() {\r
+ int width = 0;\r
+ for (SketchElement e : getElements()) {\r
+ width = Math.max(width, e.getX()+e.getWidth());\r
+ }\r
+ return width;\r
+ }\r
+ \r
+ public int getHeight() {\r
+ int height = 0;\r
+ for (SketchElement e : getElements()) {\r
+ height = Math.max(height, e.getY()+e.getHeight());\r
+ }\r
+ return height;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.sysdyn.mdlImport.MdlUtils.CommentIcon;\r
+\r
+public class SketchComment extends SketchElement {\r
+ \r
+ private String text;\r
+ private CommentIcon icon;\r
+ private boolean nextLine;\r
+ private boolean isIO;\r
+\r
+ public SketchComment(int id, CommentIcon icon, boolean nextLine, boolean isIO) {\r
+ super(id);\r
+ this.icon = icon;\r
+ this.nextLine = nextLine;\r
+ this.isIO = isIO;\r
+ }\r
+\r
+ public String getText() {\r
+ return text;\r
+ }\r
+ \r
+ public void setText(String text) {\r
+ this.text = text;\r
+ }\r
+ \r
+ public CommentIcon getIcon() {\r
+ return this.icon;\r
+ }\r
+ \r
+ public boolean isCloud() {\r
+ return this.icon.equals(CommentIcon.CLOUD);\r
+ }\r
+ \r
+ public boolean hasTextNextLine() {\r
+ return nextLine;\r
+ }\r
+ \r
+ public boolean isIOElement() {\r
+ return this.isIO;\r
+ }\r
+ \r
+ public Comment2 getWriteableElement(int xOffset, int yOffset) {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return text != null ? "\""+text+"\"" : "(empty comment)";\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.sysdyn.mdlImport.MdlUtils.ConnectionType;\r
+\r
+public class SketchConnection extends SketchObject {\r
+\r
+ private int fromId;\r
+ private SketchElement from;\r
+ private int toId;\r
+ private SketchElement to;\r
+ private ConnectionType type;\r
+ \r
+ public SketchConnection(int id, int fromId, int toId, ConnectionType type) {\r
+ super(id);\r
+ this.fromId = fromId;\r
+ this.toId = toId;\r
+ this.type = type;\r
+ }\r
+ \r
+ public int getFromId() {\r
+ return fromId;\r
+ }\r
+ \r
+ public int getToId() {\r
+ return toId;\r
+ }\r
+\r
+ public SketchElement getFrom() {\r
+ if (from == null) {\r
+ System.err.println("endpoint "+fromId+" for connection "+getId()+" is unset");\r
+ }\r
+ return from;\r
+ }\r
+\r
+ public void setFrom(SketchElement from) {\r
+ this.from = from;\r
+ }\r
+\r
+ public SketchElement getTo() {\r
+ if (to == null) {\r
+ System.err.println("endpoint "+toId+" for connection "+getId()+" is unset");\r
+ }\r
+ return to;\r
+ }\r
+\r
+ public void setTo(SketchElement to) {\r
+ this.to = to;\r
+ }\r
+ \r
+ public ConnectionType getType() {\r
+ return type;\r
+ }\r
+ \r
+ public Connection2 getWriteableConnection() {\r
+ // return dependency or flow\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return from.toString() + " --> " + to.toString();\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public abstract class SketchElement extends SketchObject {\r
+\r
+ private int x;\r
+ private int y;\r
+ private int width;\r
+ private int height;\r
+ \r
+ public SketchElement(int id) {\r
+ super(id);\r
+ }\r
+ \r
+ public void setLocationAndSize(int x, int y, int width, int height) {\r
+ this.x = x;\r
+ this.y = y;\r
+ this.width = width;\r
+ this.height = height;\r
+ }\r
+\r
+ public int getX() {\r
+ return x;\r
+ }\r
+\r
+ public int getY() {\r
+ return y;\r
+ }\r
+\r
+ public int getWidth() {\r
+ return width;\r
+ }\r
+\r
+ public int getHeight() {\r
+ return height;\r
+ }\r
+ \r
+ public abstract Element2 getWriteableElement(int xOffset, int yOffset);\r
+ \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public abstract class SketchObject {\r
+ \r
+ // TODO: some type stuff here maybe?\r
+ \r
+ private int id;\r
+ \r
+ SketchObject(int id) {\r
+ this.id = id;\r
+ }\r
+ \r
+ public int getId() {\r
+ return id;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class SketchValve extends SketchElement {\r
+ \r
+ private SketchVariable variable;\r
+ \r
+ public SketchValve(int id) {\r
+ super(id);\r
+ }\r
+\r
+ public SketchVariable getAttachedVariable() {\r
+ return variable;\r
+ }\r
+\r
+ public void setAttachedVariable(SketchVariable variable) {\r
+ this.variable = variable;\r
+ }\r
+ \r
+ @Override\r
+ public Valve2 getWriteableElement(int xOffset, int yOffset) {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return "X("+variable.toString()+")";\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.sysdyn.mdlImport.MdlUtils;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class SketchVariable extends SketchElement {\r
+ \r
+ private Variable2 variable;\r
+ boolean isAttached;\r
+ boolean allowsInBound;\r
+ boolean allowsOutBound;\r
+\r
+ public SketchVariable(int id, Variable2 variable, boolean isAttached, boolean in, boolean out) {\r
+ super(id);\r
+ this.variable = variable;\r
+ this.isAttached = isAttached;\r
+ this.allowsInBound = in;\r
+ this.allowsOutBound = out;\r
+ }\r
+ \r
+ public Variable2 getVariable() {\r
+ return this.variable;\r
+ }\r
+ \r
+ public boolean isAttached() {\r
+ return isAttached;\r
+ }\r
+ \r
+ public boolean allowsInBound() {\r
+ return allowsInBound;\r
+ }\r
+ \r
+ public boolean allowsOutBound() {\r
+ return allowsOutBound;\r
+ }\r
+ \r
+ @Override\r
+ public Element2 getWriteableElement(int xOffset, int yOffset) {\r
+ Pair<String, String> integral = MdlUtils.getPossibleIntegral(variable.getEquation());\r
+ if (integral != null) {\r
+ return new Stock2(getX(), getY(), variable, integral);\r
+ }\r
+ else {\r
+ return new Auxiliary2(getX(), getY(), variable, variable.getEquation());\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return (allowsInBound?"":"<")+variable.getName()+(allowsInBound?"":">");\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.mdlImport.ImportUtils;\r
+\r
+public class Stock extends Variable {\r
+\r
+ @Override\r
+ public Resource getExpression(WriteGraph graph, Expression expression) throws DatabaseException { \r
+\r
+ String integralEquation = ImportUtils.escapeExpression(getIntegralParts(expression)[1]);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Resource e = GraphUtils.create2(graph, \r
+ sr.StockExpression,\r
+ sr.StockExpression_initialEquation, integralEquation);\r
+ \r
+ return e;\r
+ }\r
+ \r
+ public String[] getIntegralParts(Expression expression) {\r
+ // Does not work, if the integral has some other logic than +inflows -outflows!\r
+ \r
+ // Parsing the possible functions. Searching ',' that divides the INTEG -function\r
+ int parenthesiscount = 0;\r
+ int location = 0;\r
+ char[] charArray = expression.getExpression().toCharArray();\r
+ for(int i = 0; i < charArray.length; i++) {\r
+ char c = charArray[i];\r
+ if(c == '(')\r
+ parenthesiscount++;\r
+ else if(c == ')')\r
+ parenthesiscount--;\r
+ else if(c == ',' && parenthesiscount == 1) {\r
+ location = i + 1;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ String exp = expression.getExpression();\r
+ String initialEquation = exp.substring(location, exp.lastIndexOf(')')).trim();\r
+ String integral = exp.substring(exp.indexOf("(") + 1, location - 1).trim();\r
+ \r
+ \r
+ return new String[] {integral, initialEquation};\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(!graph.isInstanceOf(parent, sr.Configuration))\r
+ return;\r
+ createVariable(graph, parent, sr.Stock, sr.StockSymbol, xOffset, yOffset);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.Arrays;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class Stock2 extends ModelVariable {\r
+ \r
+ protected String integral;\r
+ protected String initial;\r
+\r
+ public Stock2(double x, double y, \r
+ String name, String unit, Range range, String description, \r
+ String integral, String initial) {\r
+ this.integral = integral;\r
+ this.initial = initial;\r
+ }\r
+ \r
+ public Stock2(double x, double y, Variable2 variable, Pair<String, String> equation) {\r
+ this.integral = equation.first;\r
+ this.initial = equation.second;\r
+ }\r
+ \r
+ public void write(WriteGraph graph, Resource parent) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+\r
+ Resource stock = createVariable(graph, sr.Stock, parent);\r
+\r
+ Resource expression = GraphUtils.create2(graph, sr.StockExpression,\r
+ sr.StockExpression_integralEquation, integral,\r
+ sr.StockExpression_initialEquation, initial,\r
+ l0.PartOf, stock);\r
+ // TODO: why is the expressoin stored in two places?\r
+ graph.claim(stock, sr.Variable_expressionList, ListUtils.create(graph, Arrays.asList(expression)));\r
+\r
+ createSymbol(graph, sr.StockSymbol, stock, parent);\r
+\r
+ setResource(stock);\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+public class Subscript extends Variable {\r
+\r
+ @Override\r
+ public Resource getExpression(WriteGraph graph, Expression expression)\r
+ throws DatabaseException {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ if(parent == null || graph == null)\r
+ return;\r
+ \r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(!graph.isInstanceOf(parent, sr.Configuration))\r
+ return;\r
+ Layer0 l0 = Layer0.getInstance(graph); \r
+ ArrayList<Resource> enumerationIndexes = new ArrayList<Resource>();\r
+ if(expressions != null && expressions.get(0) != null) {\r
+ String[] indexes = expressions.get(0).getExpression().split(",");\r
+ for(String s : indexes) {\r
+ Resource ei = GraphUtils.create2(graph, \r
+ sr.EnumerationIndex,\r
+ l0.HasName, s.trim());\r
+ enumerationIndexes.add(ei);\r
+ }\r
+ }\r
+\r
+ Resource enumeration = GraphUtils.create2(graph, \r
+ sr.Enumeration,\r
+ l0.HasName, this.getName(),\r
+ sr.Enumeration_enumerationIndexList, ListUtils.create(graph, enumerationIndexes));\r
+\r
+ graph.claim(parent, l0.ConsistsOf, enumeration);\r
+\r
+ resource = enumeration;\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.mdlImport.ImportUtils;\r
+\r
+public class Valve extends Variable {\r
+\r
+ @Override\r
+ public Resource getExpression(WriteGraph graph, Expression expression) throws DatabaseException {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ String expressionString = ImportUtils.escapeExpression(expression.getExpression());\r
+ Resource e = GraphUtils.create2(graph, \r
+ sr.NormalExpression,\r
+ sr.Expression_equation, expressionString.trim());\r
+ return e;\r
+ }\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent, double xOffset,\r
+ double yOffset) {\r
+ try {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(!graph.isInstanceOf(parent, sr.Configuration))\r
+ return;\r
+ createVariable(graph, parent, sr.Valve, sr.ValveSymbol, xOffset, yOffset);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Valve2 extends Element2 {\r
+ \r
+ public enum Orientation {\r
+ HORIZONTAL, VERTICAL\r
+ }\r
+ \r
+ public enum TextPosition {\r
+ INSIDE, BELOW, LEFT, ABOVE, RIGHT, UNSET\r
+ }\r
+ \r
+ public Valve2(String equation, Orientation orientation, TextPosition position, String unit, Range range, String description) {\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.mdlImport.ImportUtils;\r
+\r
+public abstract class Variable extends Element {\r
+ protected String units;\r
+ protected String comments;\r
+ protected ArrayList<Expression> expressions;\r
+ protected ArrayList<Subscript> subscripts;\r
+\r
+ private Double rangeStart, rangeEnd, rangeStep;\r
+ \r
+ protected void createVariable(WriteGraph graph, Resource configuration, Resource variableType, Resource symbolType, double xOffset, double yOffset) throws DatabaseException {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph); \r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ \r
+ Resource diagram = graph.getSingleObject(configuration, mr.CompositeToDiagram);\r
+ if(diagram == null)\r
+ return;\r
+ \r
+ // Make sure at least one expression exist\r
+ if(getExpressions().isEmpty()) {\r
+ Expression e = new Expression();\r
+ e.setExpression("");\r
+ getExpressions().add(e);\r
+ }\r
+ \r
+ Resource variable = GraphUtils.create2(graph, \r
+ variableType,\r
+ l0.HasName, ImportUtils.escapeName(name));\r
+ graph.claim(variable, mr.Mapped, variable);\r
+\r
+ ArrayList<Resource> expressions = new ArrayList<Resource>();\r
+ for(Expression e : getExpressions()) {\r
+\r
+ // Get expression from the variable. They have different types\r
+ Resource expression = getExpression(graph, e);\r
+\r
+ if(e.getRange() != null) {\r
+ graph.claimLiteral(expression, sr.Expression_arrayRange, "[" + e.getRange().trim() + "]");\r
+ }\r
+ expressions.add(expression);\r
+ graph.claim(variable, l0.ConsistsOf, expression);\r
+ }\r
+ graph.claim(variable, sr.Variable_expressionList, ListUtils.create(graph, expressions));\r
+\r
+ if(subscripts != null) {\r
+ ArrayList<Resource> arrayIndexes = new ArrayList<Resource>();\r
+ for(Subscript sub : subscripts) {\r
+ if(sub.getResource() != null)\r
+ arrayIndexes.add(sub.getResource());\r
+ }\r
+ graph.claim(variable, sr.Variable_arrayIndexesList, ListUtils.create(graph, arrayIndexes));\r
+ }\r
+ \r
+ if(units != null && units.length() > 0)\r
+ graph.claimLiteral(variable, sr.Variable_unit, units);\r
+ if(comments != null && comments.length() > 0)\r
+ graph.claimLiteral(variable, l0.HasDescription, comments);\r
+ if(rangeStart != null)\r
+ graph.claimLiteral(variable, sr.HasRangeStart, rangeStart);\r
+ if(rangeEnd != null)\r
+ graph.claimLiteral(variable, sr.HasRangeEnd, rangeEnd);\r
+ if(rangeStep != null)\r
+ graph.claimLiteral(variable, sr.HasRangeStep, rangeStep);\r
+ \r
+ graph.claim(configuration, l0.ConsistsOf, variable);\r
+ \r
+ \r
+ Resource symbol = GraphUtils.create2(graph, \r
+ symbolType,\r
+ mr.ElementToComponent, variable);\r
+ \r
+ double[] transform = {1.0, 0.0, 0.0, 1.0, x + xOffset, y + yOffset};\r
+ graph.claimLiteral(symbol, dr.HasTransform, g2d.Transform, transform);\r
+ \r
+ OrderedSetUtils.add(graph, diagram, symbol);\r
+ \r
+ resource = variable;\r
+ }\r
+ \r
+ \r
+ public String getUnits() {\r
+ return units;\r
+ }\r
+\r
+ public void setUnits(String units) {\r
+ this.units = units;\r
+ }\r
+\r
+ public String getComments() {\r
+ return comments;\r
+ }\r
+\r
+ public void setComments(String comments) {\r
+ this.comments = comments;\r
+ }\r
+\r
+ public ArrayList<Expression> getExpressions() {\r
+ if(expressions == null) {\r
+ expressions = new ArrayList<Expression>();\r
+ }\r
+ return expressions;\r
+ }\r
+\r
+ public void setExpressions(ArrayList<Expression> expressions) {\r
+ this.expressions = expressions;\r
+ }\r
+\r
+ public ArrayList<Subscript> getSubscripts() {\r
+ if(subscripts == null)\r
+ subscripts = new ArrayList<Subscript>();\r
+ return subscripts;\r
+ }\r
+\r
+ public void setSubscripts(ArrayList<Subscript> subscripts) {\r
+ this.subscripts = subscripts;\r
+ }\r
+ \r
+\r
+ public Double getRangeStart() {\r
+ return rangeStart;\r
+ }\r
+\r
+ public void setRangeStart(Double rangeStart) {\r
+ this.rangeStart = rangeStart;\r
+ }\r
+\r
+ public Double getRangeEnd() {\r
+ return rangeEnd;\r
+ }\r
+\r
+ public void setRangeEnd(Double rangeEnd) {\r
+ this.rangeEnd = rangeEnd;\r
+ }\r
+\r
+ public Double getRangeStep() {\r
+ return rangeStep;\r
+ }\r
+\r
+ public void setRangeStep(Double rangeStep) {\r
+ this.rangeStep = rangeStep;\r
+ }\r
+ \r
+ /**\r
+ * Use this to set subscripts after all elements have been read\r
+ * \r
+ * @param model The model where the variable is located\r
+ */\r
+ public void initializeSubscripts(Model model) {\r
+ for(Expression ex : getExpressions()) {\r
+ if(ex.getRange() != null) {\r
+ \r
+ // Subscripts exist, check that subscripts -array is initialized\r
+ getSubscripts();\r
+ \r
+ String[] elements = ex.getRange().split(",");\r
+ // Search the corresponding subscript for each element, if it has not been searched already\r
+ for(int i = 0; i < elements.length; i++) {\r
+ // The subscript has been defined, move to next\r
+ if(subscripts.size() > i)\r
+ continue;\r
+ \r
+ String element = elements[i].trim();\r
+ for(Subscript sub : model.getSubscripts()) {\r
+ if(sub.getName().equals(element)) {\r
+ subscripts.add(sub);\r
+ break;\r
+ }\r
+ for(String index : sub.getExpressions().get(0).getExpression().split(",")) {\r
+ if(index.trim().equals(element)) {\r
+ subscripts.add(sub);\r
+ break;\r
+ }\r
+ }\r
+ // Subscript was defined for this index in previous for-loop\r
+ if(subscripts.size() == i + 1)\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+public class Variable2 {\r
+ \r
+ private String name;\r
+ private String equation;\r
+ private String unit;\r
+ private String description;\r
+ \r
+ public Variable2(String name, String equation, String unit, String description) {\r
+ this.name = name;\r
+ this.equation = equation;\r
+ this.unit = unit;\r
+ this.description = description;\r
+ }\r
+ \r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+ \r
+ public String getEquation() {\r
+ return equation;\r
+ }\r
+\r
+ public void setEquation(String equation) {\r
+ this.equation = equation;\r
+ }\r
+\r
+ public String getUnit() {\r
+ return unit;\r
+ }\r
+\r
+ public void setUnit(String unit) {\r
+ this.unit = unit;\r
+ }\r
+\r
+ public String getDescription() {\r
+ return description;\r
+ }\r
+\r
+ public void setDescription(String description) {\r
+ this.description = description;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.mdlImport.model;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+\r
+public class View implements IWriteableMDLObject {\r
+ \r
+ private int minX = 0, maxX = 0, minY = 0, maxY = 0;\r
+ private double xOffset = 0, yOffset = 0;\r
+ private String name, fontParameters;\r
+ \r
+ private ArrayList<Element> elements = new ArrayList<Element>();\r
+\r
+ @Override\r
+ public void write(WriteGraph graph, Resource parent) {\r
+ xOffset = xOffset - minX;\r
+ yOffset = yOffset - minY;\r
+ for(Element e : elements) {\r
+ e.write(graph, parent, xOffset, yOffset);\r
+ }\r
+ }\r
+ \r
+ public void addElement(Element e) {\r
+ if (e instanceof Subscript || e instanceof Function)\r
+ return;\r
+ \r
+ if (e.getX() < minX)\r
+ minX = e.getX();\r
+ if (e.getX() > maxX)\r
+ maxX = e.getX();\r
+ if (e.getY() < minY)\r
+ minY = e.getY();\r
+ if (e.getY() > maxY)\r
+ maxY = e.getY();\r
+ \r
+ this.elements.add(e);\r
+ }\r
+ \r
+ public ArrayList<Element> getElements() {\r
+ return elements;\r
+ }\r
+\r
+ public void setElements(ArrayList<Element> elements) {\r
+ this.elements = elements;\r
+ }\r
+ \r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+\r
+ public String getFontParameters() {\r
+ return fontParameters;\r
+ }\r
+\r
+\r
+ public void setFontParameters(String fontParameters) {\r
+ this.fontParameters = fontParameters;\r
+ }\r
+\r
+\r
+ public int getMinX() {\r
+ return minX;\r
+ }\r
+\r
+ public void setMinX(int minX) {\r
+ this.minX = minX;\r
+ }\r
+\r
+ public int getMaxX() {\r
+ return maxX;\r
+ }\r
+\r
+ public void setMaxX(int maxX) {\r
+ this.maxX = maxX;\r
+ }\r
+\r
+ public int getMinY() {\r
+ return minY;\r
+ }\r
+\r
+ public void setMinY(int minY) {\r
+ this.minY = minY;\r
+ }\r
+\r
+ public int getMaxY() {\r
+ return maxY;\r
+ }\r
+\r
+ public void setMaxY(int maxY) {\r
+ this.maxY = maxY;\r
+ }\r
+\r
+ public double getxOffset() {\r
+ return xOffset;\r
+ }\r
+\r
+ public void setxOffset(double xOffset) {\r
+ this.xOffset = xOffset;\r
+ }\r
+\r
+ public double getyOffset() {\r
+ return yOffset;\r
+ }\r
+\r
+ public void setyOffset(double yOffset) {\r
+ this.yOffset = yOffset;\r
+ }\r
+ \r
+ public int getWidth() {\r
+ return maxX - minX;\r
+ }\r
+ \r
+ public int getHeight() {\r
+ return maxY - minY;\r
+ }\r
+}\r
return model;\r
}\r
\r
- public static void createModel(WriteGraph graph) {\r
- createModelAt(graph, Simantics.getProject().get());\r
+ public static Resource createModel(WriteGraph graph) {\r
+ return createModelAt(graph, Simantics.getProject().get());\r
}\r
\r
+ // TODO: remove this\r
public static Resource createModelAt(WriteGraph g, Resource library) {\r
try {\r
Layer0 l0 = Layer0.getInstance(g);\r