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