From: jkauttio Date: Fri, 25 Apr 2014 14:29:05 +0000 (+0000) Subject: Merge changes from dev-jkauttio X-Git-Tag: 1.8.1~79 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=308f891430ed5fa3b50ffd0acb322cb07f07c00d;p=simantics%2Fsysdyn.git Merge changes from dev-jkauttio refs #2924 git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@29357 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index a588d8da..2a623324 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -1191,6 +1191,11 @@ checkEnabled="true"> + + variables = new ArrayList(); - private ArrayList controls = new ArrayList(); - private ArrayList sketchData = new ArrayList(); - private ArrayList otherData = new ArrayList(); - - - - public void addVariable(String variable) { - variables.add(variable); - } - - public ArrayList getVariables() { - return variables; - } - - public void addControl(String control) { - controls.add(control); - } - - public ArrayList getControls() { - return controls; - } - - public void addSketchData(String sketchRow) { - sketchData.add(sketchRow); - } - - public ArrayList getSketchData() { - return sketchData; - } - - public void addOtherData(String dataRow) { - otherData.add(dataRow); - } - - public ArrayList getOtherData() { - return otherData; - } - - -} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlParser.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlParser.java deleted file mode 100644 index 2f68f086..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/MdlParser.java +++ /dev/null @@ -1,622 +0,0 @@ -/******************************************************************************* - * 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 org.simantics.sysdyn.mdlImport.mdlElements.Auxiliary; -import org.simantics.sysdyn.mdlImport.mdlElements.Cloud; -import org.simantics.sysdyn.mdlImport.mdlElements.Connection; -import org.simantics.sysdyn.mdlImport.mdlElements.Dependency; -import org.simantics.sysdyn.mdlImport.mdlElements.Element; -import org.simantics.sysdyn.mdlImport.mdlElements.EquivalenceSubscript; -import org.simantics.sysdyn.mdlImport.mdlElements.Expression; -import org.simantics.sysdyn.mdlImport.mdlElements.Flow; -import org.simantics.sysdyn.mdlImport.mdlElements.Function; -import org.simantics.sysdyn.mdlImport.mdlElements.Model; -import org.simantics.sysdyn.mdlImport.mdlElements.Stock; -import org.simantics.sysdyn.mdlImport.mdlElements.Subscript; -import org.simantics.sysdyn.mdlImport.mdlElements.Valve; -import org.simantics.sysdyn.mdlImport.mdlElements.Variable; -import org.simantics.sysdyn.mdlImport.mdlElements.View; - -public class MdlParser { - - public static Model parse(File file) { - - Model model = new Model(); - - String[] name = file.getName().split("\\.mdl"); - model.setName(name[0]); - - MdlFile mdlFile = getMdlContents(file); - - getVariableData(model, mdlFile.getVariables()); - - getSketchData(model, mdlFile.getSketchData()); - - getControlData(model, mdlFile.getControls()); - -// getOthertData(model, mdlFile.getOtherData()); - - setAllSubscripts(model); - - return model; - } - - - 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 - - // 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.addControl(variable); - } else { - mdlFile.addVariable(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; - - for(String s : elementExpressions) { - // 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/mdlElements/Auxiliary.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Auxiliary.java deleted file mode 100644 index 62c3764b..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Auxiliary.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Cloud.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Cloud.java deleted file mode 100644 index 95a83811..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Cloud.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Connection.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Connection.java deleted file mode 100644 index ba3be264..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Connection.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Dependency.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Dependency.java deleted file mode 100644 index 1b5bdc8e..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Dependency.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Element.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Element.java deleted file mode 100644 index fb233346..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Element.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/EquivalenceSubscript.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/EquivalenceSubscript.java deleted file mode 100644 index 74741b30..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/EquivalenceSubscript.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Expression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Expression.java deleted file mode 100644 index e36ca60a..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Expression.java +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - - -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/mdlElements/Function.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Function.java deleted file mode 100644 index 43afed7e..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Function.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/IWriteableMDLElement.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/IWriteableMDLElement.java deleted file mode 100644 index 5f0a4250..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/IWriteableMDLElement.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/IWriteableMDLObject.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/IWriteableMDLObject.java deleted file mode 100644 index a464cfb0..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/IWriteableMDLObject.java +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Model.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Model.java deleted file mode 100644 index dcc7d0d1..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Model.java +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/ModelControl.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/ModelControl.java deleted file mode 100644 index 8197c773..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/ModelControl.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.exception.DatabaseException; - -public class ModelControl 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) { - // TODO Auto-generated method stub - - } - -} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Stock.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Stock.java deleted file mode 100644 index 61f3111b..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Stock.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Subscript.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Subscript.java deleted file mode 100644 index 5be6073e..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Subscript.java +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Valve.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Valve.java deleted file mode 100644 index 620ad56b..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Valve.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/Variable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Variable.java deleted file mode 100644 index f2fc13bf..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Variable.java +++ /dev/null @@ -1,211 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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/mdlElements/View.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/View.java deleted file mode 100644 index 88fe41e6..00000000 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/View.java +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * 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.mdlElements; - -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()maxX) - maxX = e.getX(); - 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/modelImport/MdlParser.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java new file mode 100644 index 00000000..b60deac5 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlParser.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * 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.modelImport; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; + +import org.simantics.sysdyn.modelImport.mdl.Declaration; +import org.simantics.sysdyn.modelImport.mdl.Lookup; +import org.simantics.sysdyn.modelImport.mdl.MdlModel; +import org.simantics.sysdyn.modelImport.mdl.Sketch; +import org.simantics.sysdyn.modelImport.mdl.SketchComment; +import org.simantics.sysdyn.modelImport.mdl.SketchConnection; +import org.simantics.sysdyn.modelImport.mdl.SketchObject; +import org.simantics.sysdyn.modelImport.mdl.SketchValve; +import org.simantics.sysdyn.modelImport.mdl.SketchVariable; +import org.simantics.sysdyn.modelImport.mdl.Subscript; +import org.simantics.sysdyn.modelImport.mdl.SubscriptVariable; +import org.simantics.sysdyn.modelImport.mdl.Variable; +import org.simantics.sysdyn.modelImport.model.Model; +import org.simantics.sysdyn.modelImport.model.element.Connection; +import org.simantics.sysdyn.modelImport.model.element.ModelVariable; +import org.simantics.sysdyn.modelImport.model.element.Symbol; +import org.simantics.sysdyn.modelImport.model.element.Shadow; +import org.simantics.sysdyn.modelImport.model.element.Valve; + +public class MdlParser { + + public static Model parse(File file) { + // generate a mdl model based on the contents of the file + MdlModel mdl; + try { + mdl = parseFile(file); + } + catch (Exception e) { + e.printStackTrace(); + return null; + } + + System.err.println("model parsed"); + + // generate a sysdyn model from the mdl model + + Model model = new Model(mdl.getName()); + + double offset = 0; + + for (Subscript subscript : mdl.getAllSubscripts()) { + if (!subscript.isEquivalent()) + model.addEnumeration(subscript.getEnumeration(mdl)); + } + + for (Lookup lookup : mdl.getAllLookups()) { + model.addFunction(lookup.getFunction()); + } + + try { + // add sketch labels and independent elements + for (Sketch sketch : mdl.getSketches()) { + + sketch.setOffset(0, offset); + + //model.addSymbol(new Comment(0, offset, -1, -1, sketch.getName())); + + for (SketchComment comment : sketch.getComments()) { + Symbol symbol = comment.getSymbol(mdl, sketch); + if (symbol != null) { + comment.setModelObject(symbol); + model.addSymbol(symbol); + } + } + + for (SketchValve valve : sketch.getValves()) { + Valve symbol = valve.getSymbol(mdl, sketch); + if (symbol != null) { + valve.setModelObject(symbol); + model.addSymbol(symbol); + } + } + + for (SketchVariable variable : sketch.getNonShadowVariables()) { + ModelVariable symbol = variable.getSymbol(mdl, sketch); + if (symbol != null) { + variable.setModelObject(symbol); + model.addSymbol(symbol); + } + } + + offset += 200; + } + + } + catch (NullPointerException e) { + e.printStackTrace(); + } + + // add dependent elements + for (Sketch sketch : mdl.getSketches()) { + for (SketchVariable variable : sketch.getShadowVariables()) { + ModelVariable original = model.getVariable(variable.getName()); + if (original == null) + System.err.println("original variable not found for "+variable.getName()); + Symbol symbol = original != null ? new Shadow(variable.getDimensions(sketch), original) : variable.getSymbol(mdl, sketch); + if (symbol != null) { + variable.setModelObject(symbol); + model.addSymbol(symbol); + } + } + + for (SketchConnection connection : sketch.getConnections()) { + Connection conn = connection.getConnection(sketch); + if (conn != null) { + connection.setModelObject(conn); + model.addConnection(conn); + } + } + } + + // Set simulation parameters + + System.err.println("DONE"); + + return model; + } + + private static final String UTF_8 = "{UTF-8}"; + private static final String SKETCH_VERSION = "V300"; + private static final String SKETCH_START = "\\\\\\---///"; + private static final String SKETCH_END = "///---\\\\\\"; + + private static MdlModel parseFile(File file) + throws Exception { + + // strip the file suffix from file name + String name = file.getName(); + if (file.getName().contains(".")) { + name = name.substring(0, name.indexOf('.')); + } + + MdlModel mdl = new MdlModel(name); + + // 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(); + } + + // START READING VARIABLE DATA + + // keep track of the current category + String category = null; + + do { + // skip empty lines + if (line.isEmpty()) + continue; + + // combine the (possible) variable declaration into one line + StringBuilder buffer = new StringBuilder(); + do { + // strip trailing '\' if present + buffer.append(line.endsWith("\\") ? line.substring(0, line.length()-1) : line); + // each variable declaration ends with '|' + if (line.endsWith("|")) + break; + } while ((line = reader.readLine()) != null); + String str = buffer.toString(); + + String cat; + Variable var; + Lookup lookup; + Subscript subscript; + + // parse the (possible) variable declaration + if ((cat = Declaration.parseCategory(str)) != null) { + category = cat; + } + else if ((var = Variable.getPossible(str)) != null) { + mdl.addVariable(var, category); + } + else if ((var = SubscriptVariable.getPossible(str)) != null) { + mdl.addSubscriptVariable((SubscriptVariable)var, category); + } + else if ((lookup = Lookup.getPossible(str)) != null) { + mdl.addLookup(lookup); + } + else if ((subscript = Subscript.getPossible(str)) != null) { + mdl.addSubscript(subscript); + } + else { + // if we got this far, the variable could not be parsed + throw new Exception("unrecognized variable "+str); + } + + } while ((line = reader.readLine()) != null && !line.startsWith(SKETCH_START)); + + // END READING VARIABLE DATA + + if (line == null) { + throw new Exception("unexpected end of file"); + } + + // START READING SKETCH DATA + + // keep track of the current sketch + Sketch sketch = null; + + do { + // skip empty lines + if (line.isEmpty()) + continue; + + SketchObject so; + + if (line.startsWith(SKETCH_START)) { + sketch = new Sketch(); + mdl.addSketch(sketch); + } + else if (line.startsWith(SKETCH_VERSION)) { + // version declaration, nothing to do here + } + else if (line.startsWith("*")) { + sketch.setName(line.substring(1)); + } + else if (line.startsWith("$")) { + // font declaration, nothing to do here + } + else if ((so = SketchConnection.getPossible(line)) != null) { + sketch.addConnection((SketchConnection)so); + } + else if ((so = SketchVariable.getPossible(line)) != null) { + sketch.addVariable((SketchVariable)so); + } + else if ((so = SketchValve.getPossible(line)) != null) { + SketchValve valve = (SketchValve)so; + // the next row after a valve should always the variable associated with the valve + SketchVariable attached = SketchVariable.getPossible(reader.readLine()); + if (attached == null || !attached.isAttached()) { + throw new Exception("attached variable not found for valve"); + } + valve.setAttached(attached); + sketch.addValve(valve); + } + else if ((so = SketchComment.getPossible(line)) != null) { + SketchComment comment = (SketchComment)so; + if (comment.hasTextLine()) { + comment.setText(reader.readLine()); + } + sketch.addComment(comment); + } + else { + // if we got this far, the element could not be parsed + throw new Exception("unrecognized element "+line); + } + + } while ((line = reader.readLine()) != null && !line.startsWith(SKETCH_END)); + + // END READING SKETCH DATA + + if (line == null) { + throw new Exception("unexpected end of file"); + } + + // START READING OTHER DATA + + do { + // TODO: is there anything relevant here? + } while ((line = reader.readLine()) != null); + + // END READING OTHER DATA + + reader.close(); + return mdl; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java new file mode 100644 index 00000000..b3546407 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/MdlUtil.java @@ -0,0 +1,288 @@ +package org.simantics.sysdyn.modelImport; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.mdl.Lookup; +import org.simantics.sysdyn.modelImport.mdl.MdlModel; + +public class MdlUtil { + + // most of this is based on the documentation of the .mdl file format + // available in http://www.vensim.com/documentation/24305.htm + + // some regular expressions that are used commonly in the parser + public static final String DBL = "-?\\d+(?:\\.\\d+)?"; + public static final String DBL_G = "("+DBL+")"; + public static final String INT = "-?\\d+"; + public static final String INT_G = "("+INT+")"; + + // matches a basic vensim name (starts with a letter, may contain any word + // characters and white space) + public static final String BASIC_NAME = + "[A-Za-z]\\w*(?:\\s+\\w+)*"; + // matches a special vensim name (starts and ends with a quotation mark, + // may contain escaped special characters) + public static final String SPECIAL_NAME = + "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\""; + + // matches a vensim variable (either basic name or special name) + public static final String VARIABLE = + "("+BASIC_NAME+"|"+SPECIAL_NAME+")"; + // matches a vensim variable inside an expression (basic name not followed + // by an open parenthesis or a special name) + public static final String VARIABLE_EXPRESSION = + "([A-Za-z](?![\\s\\w]*\\()\\w*(?:\\s+\\w+)*|"+SPECIAL_NAME+")"; + // matches a vensim subscript variable (basic name with a list of indices) + public static final String SUBSCRIPT = + "("+BASIC_NAME+")\\[("+BASIC_NAME+"\\!?(?:,"+BASIC_NAME+"\\!?)*)\\]"; + // matches a vensim function (basic name followed by an open parenthesis) + public static final String FUNCTION = + "("+BASIC_NAME+")\\s*\\("; + + public static String normalize(String str) { + // start by removing all tabs from the string, not really necessary + // but does make the equation cleaner + str = str.replaceAll("\t", ""); + + // normalize functions + str = normalizeFunctions(str); + // normalize variables + str = normalizeVariables(str); + + // replace inline operations + str = str.replaceAll(":AND:", " and "); + str = str.replaceAll(":OR:", " or "); + + return str; + } + + private static String normalizeVariables(String expression) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(VARIABLE_EXPRESSION).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + String variable = matcher.group(1); + + if (variable.equalsIgnoreCase("time")) { + result.append("time"); + } + else if (variable.startsWith("\"") && variable.endsWith("\"")) { + result.append('\''); + result.append(variable.substring(1, variable.length() - 1)); + result.append('\''); + } + else if (variable.contains("-")) { + result.append('\''); + result.append(variable); + result.append('\''); + } + else { + String[] parts = variable.split("\\s+"); + for (int i = 0; i < parts.length; i++) { + if (i > 0) + result.append(' '); + result.append(parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1)); + } + } + + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } + + private static String normalizeFunctions(String expression) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(FUNCTION).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + String function = matcher.group(1); + + if (function.equalsIgnoreCase("sum")) { + // vensim "sum" is similar to modelica "sum" if operations + // are replaced with dot-operations (e.g. * with .*) inside + // the parameters + result.append("sum("); + int closing = expression.indexOf(')', matcher.end()); + String parameters = expression.substring(matcher.end(), closing); + parameters = parameters.replaceAll("\\*", ".*"); + result.append(parameters); + offset = closing; + } + else if (function.equalsIgnoreCase("if then else")) { + result.append("IFTHENELSE("); + offset = matcher.end(); + } + else { + // this will also capitalize lookups, is this ok? + result.append(function.toUpperCase()+"("); + offset = matcher.end(); + } + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } + + public static String finalize(String expression, MdlModel mdl) { + expression = expandIterations(expression, mdl); + expression = renameLookups(expression, mdl); + + return expression; + } + + private static String expandIterations(String expression, MdlModel mdl) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(SUBSCRIPT).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + String name = matcher.group(1); + String[] indices = matcher.group(2).split(","); + + result.append(name); + + result.append('['); + for (int i = 0; i < indices.length; i++) { + if (i > 0) + result.append(','); + + if (indices[i].endsWith("!")) { + String subscript = indices[i].substring(0, indices[i].length() - 1); + List values = mdl.getSubscript(subscript).getValues(mdl); + result.append('{'); + for (int j = 0; j < values.size(); j++) { + if (j > 0) + result.append(','); + result.append(values.get(j)); + } + result.append('}'); + } + else { + result.append(indices[i]); + } + } + result.append(']'); + + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } + + private static String renameLookups(String expression, MdlModel mdl) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(FUNCTION).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + String name = matcher.group(1); + + Lookup potential = mdl.getLookup(name); + + if (potential != null) { + System.err.println("found lookup "+name); + name = name.replaceAll("\\s+", ""); + } + + result.append(name+"("); + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } + + public static String replaceSubscripts(String expression, String subscript, String replacement) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(SUBSCRIPT).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + String name = matcher.group(1); + String[] indices = matcher.group(2).split(","); + + result.append(name); + + result.append('['); + for (int i = 0; i < indices.length; i++) { + if (i > 0) + result.append(','); + + if (indices[i].equals(subscript)) { + result.append(replacement); + } + else { + result.append(indices[i]); + } + } + result.append(']'); + + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + return result.toString(); + } + + public static String[] splitFunctionParameters(String str) { + ArrayList list = new ArrayList(); + + int i; + int last = 0; + int level = 0; + boolean comment = false; + boolean brackets = false; + + for (i = 0; i < str.length(); i++) { + char current = str.charAt(i); + if (current == '"') + // note that this does not currently support escaped quotation marks inside quoted variable names + comment = !comment; + else if (current == '[' && !comment) + brackets = true; + else if (current == ']' && !comment) + brackets = false; + else if (current == '(' && !comment && !brackets) + level++; + else if (current == ')' && !comment && !brackets) + level--; + else if (current == ',' && !comment && !brackets && level == 0) { + list.add(str.substring(last, i).trim()); + last = i + 1; + } + } + if (last < i) { + list.add(str.substring(last, i).trim()); + } + + return list.toArray(new String[list.size()]); + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java new file mode 100644 index 00000000..4c3a1e1e --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Declaration.java @@ -0,0 +1,58 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class Declaration { + + private static final String CATEGORY = "\\*{56}\\s*\\.(\\S+)\\s*\\*{56}.*"; + + protected static final String DECL_DELIM = "\\s*~\\s*"; + protected static final String DECL_END = "\\s*\\|"; + protected static final String DECL_UNIT = "([^~]*?)"; + protected static final String DECL_DESC = "([^\\|]*?)"; + + protected static final String DECL_SUFFIX = + DECL_DELIM + DECL_UNIT + DECL_DELIM + DECL_DESC + DECL_END; + protected static final int declarationUnit = 1; + protected static final int declarationDescription = 2; + + private String name; + private String unit; + private String description; + + protected Declaration(String name) { + this.name = name; + } + + protected void parseSuffix(String suffix) + throws Exception { + Matcher matcher = Pattern.compile(DECL_SUFFIX).matcher(suffix); + if (!matcher.matches()) { + // this should not happen unless subclasses fail to construct their + // regular expressions properly + throw new Exception("could not parse declaration suffix "+suffix); + } + + unit = matcher.group(declarationUnit); + description = matcher.group(declarationDescription); + } + + public String getName() { + return name; + } + + public String getUnit() { + return unit; + } + + public String getDescription() { + return description; + } + + public static String parseCategory(String line) { + Matcher matcher = Pattern.compile(CATEGORY).matcher(line); + return matcher.matches() ? matcher.group(1) : null; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java new file mode 100644 index 00000000..cfa4129b --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/IMdlObject.java @@ -0,0 +1,5 @@ +package org.simantics.sysdyn.modelImport.mdl; + +public interface IMdlObject { + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java new file mode 100644 index 00000000..b166a32d --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Lookup.java @@ -0,0 +1,126 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.expression.LookupExpression; +import org.simantics.sysdyn.modelImport.model.support.Function; + +public class Lookup extends Declaration { + + private static final String LOOKUP_RANGE = + "\\[\\("+MdlUtil.DBL_G+","+MdlUtil.DBL_G+"\\)-\\("+MdlUtil.DBL_G+","+MdlUtil.DBL_G+"\\)\\]"; + private static final String LOOKUP_POINTS = + "(\\("+MdlUtil.DBL+","+MdlUtil.DBL+"\\)(?:,\\("+MdlUtil.DBL+","+MdlUtil.DBL+"\\))*)"; + private static final String LOOKUP = + "("+MdlUtil.BASIC_NAME+")\\s*\\(\\s*"+LOOKUP_RANGE+","+LOOKUP_POINTS+"\\s*\\)"; + + private static final String LOOKUP_DECL = + LOOKUP+"("+DECL_SUFFIX+")"; + private static final int lookupName = 1; + private static final int lookupRangeXMin = 2; + private static final int lookupRangeYMin = 3; + private static final int lookupRangeXMax = 4; + private static final int lookupRangeYMax = 5; + private static final int lookupPoints = 6; + private static final int lookupSuffix = 7; + + private double xMin; + private double yMin; + private double xMax; + private double yMax; + private double[] points; + + private Function function; + + // TODO: generate functions from lookup variables + + protected Lookup(String name, double xMin, double yMin, double xMax, double yMax, double[] points) { + super(name); + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.points = points; + } + + public static Lookup getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(LOOKUP_DECL).matcher(line); + if (!matcher.matches()) { + return null; + } + + String name = matcher.group(lookupName).toUpperCase(); + double xMin = Double.parseDouble(matcher.group(lookupRangeXMin)); + double yMin = Double.parseDouble(matcher.group(lookupRangeYMin)); + double xMax = Double.parseDouble(matcher.group(lookupRangeXMax)); + double yMax = Double.parseDouble(matcher.group(lookupRangeYMax)); + double[] points = parsePoints(matcher.group(lookupPoints)); + + Lookup lookup = new Lookup(name, xMin, yMin, xMax, yMax, points); + lookup.parseSuffix(matcher.group(lookupSuffix)); + return lookup; + } + + private static double[] parsePoints(String str) { + // a hack to remove the leading empty string otherwise produced by split() + str = str.replaceFirst("[(),]+", ""); + String[] parts = str.split("[(),]+"); + double[] points = new double[parts.length]; + for (int i = 0; i < parts.length; i++) { + points[i] = Double.parseDouble(parts[i]); + } + return points; + } + + public double getxMin() { + return xMin; + } + + public double getyMin() { + return yMin; + } + + public double getxMax() { + return xMax; + } + + public double getyMax() { + return yMax; + } + + public double[] getPoints() { + return points; + } + + public Function getFunction() { + if (function != null) { + return function; + } + + StringBuilder body = new StringBuilder(); + + // one input, one output + body.append("input Real i;\n"); + body.append("output Real o;\n"); + + // interpolate over the set of points + body.append("algorithm\n"); + + body.append("o := interpolate(i, {"); + for (int i = 0; i < points.length/2; i++) { + if (i > 0) { + body.append(','); + } + body.append('{').append(points[2*i]).append(',').append(points[2*i+1]).append('}'); + } + body.append("});\n"); + + function = new Function(getName().replaceAll("\\s+", ""), body.toString()); + + return function; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlModel.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlModel.java new file mode 100644 index 00000000..202dcad8 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/MdlModel.java @@ -0,0 +1,149 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class MdlModel { + + private String name; + + private Map variables; + private Map> groups; + private Map lookups; + private Map subscripts; + private List sketches; + + public MdlModel(String name) { + this.name = name; + + this.variables = new HashMap(); + this.groups = new HashMap>(); + this.lookups = new HashMap(); + this.subscripts = new HashMap(); + this.sketches = new ArrayList(); + } + + public String getName() { + return name; + } + + public void addVariable(Variable variable, String group) + throws Exception { + if (variables.get(variable.getName()) != null) { + throw new Exception("duplicate variable "+variable.getName()); + } + + variables.put(variable.getName(), variable); + addGroup(variable, group); + } + + public void addSubscriptVariable(SubscriptVariable variable, String group) + throws Exception { + Variable original = variables.get(variable.getName()); + if (original != null) { + if (!(original instanceof SubscriptVariable)) { + throw new Exception("incompatible type for variable "+variable.getName()); + } + ((SubscriptVariable)original).addSubscriptVariable(variable); + } + else { + variables.put(variable.getName(), variable); + addGroup(variable, group); + } + } + + private void addGroup(Variable variable, String group) { + if (group != null) { + if (groups.get(group) == null) { + groups.put(group, new ArrayList()); + } + groups.get(group).add(variable); + } + } + + public Variable getVariable(String name) { + return variables.get(name); + } + + public Set getAllVariables() { + return new HashSet(variables.values()); + } + + public void addLookup(Lookup lookup) + throws Exception { + if (lookups.get(lookup.getName()) != null) { + throw new Exception("duplicate lookup "+lookup.getName()); + } + + lookups.put(lookup.getName(), lookup); + } + + public Lookup getLookup(String name) { + return lookups.get(name); + } + + public Set getAllLookups() { + return new HashSet(lookups.values()); + } + + public void addSubscript(Subscript subscript) + throws Exception { + if (subscripts.get(subscript.getName()) != null) { + throw new Exception("duplicate subscript "+subscript.getName()); + } + + // TODO: check if a subscript with the same values already exists + + subscripts.put(subscript.getName(), subscript); + } + + public Subscript getSubscript(String key) { + return subscripts.get(key); + } + + public Set getAllSubscripts() { + return new HashSet(subscripts.values()); + } + + public Subscript resolveSubscript(List values) { + return resolveSubscript(new HashSet(values)); + } + + public Subscript resolveSubscript(Set values) { + // if one value is actually a subscript, expand it to its values + Set all = new HashSet(); + for (String value : values) { + Subscript potential = subscripts.get(value); + if (potential != null) { + all.addAll(potential.getValues(this)); + } + else { + all.add(value); + } + } + + // find the subscript that contains exactly the given set of values. + // only consider original subscripts (ignore equivalent subscripts) + for (Subscript subscript : getAllSubscripts()) { + if (!subscript.isEquivalent() && subscript.getValues(this).containsAll(all) && all.containsAll(subscript.getValues(this))) { + return subscript; + } + } + + // if an exact match could not be found, return null + return null; + } + + public void addSketch(Sketch sketch) { + sketches.add(sketch); + } + + public List getSketches() { + return sketches; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Sketch.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Sketch.java new file mode 100644 index 00000000..865f8da2 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Sketch.java @@ -0,0 +1,173 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.simantics.sysdyn.modelImport.model.element.Symbol; + +public class Sketch { + + private String name; + + private boolean edgesOutOfDate; + public double topEdge = 0; + public double bottomEdge = 0; + public double leftEdge = 0; + public double rightEdge = 0; + + private List comments; + private List connections; + private List valves; + private List variables; + + private HashMap objects; + + public Sketch() { + edgesOutOfDate = true; + + comments = new ArrayList(); + connections = new ArrayList(); + valves = new ArrayList(); + variables = new ArrayList(); + + objects = new HashMap(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + private void updateEdges() { +// if (edgesOutOfDate) { +// boolean first = true; +// for (SketchElement e : getAllElements()) { +// topEdge = first ? e.getSysdynTopEdge() : Math.min(topEdge, e.getSysdynTopEdge()); +// bottomEdge = first ? e.getSysdynBottomEdge() : Math.max(bottomEdge, e.getSysdynBottomEdge()); +// leftEdge = first ? e.getSysdynLeftEdge() : Math.min(leftEdge, e.getSysdynLeftEdge()); +// rightEdge = first ? e.getSysdynRightEdge() : Math.max(rightEdge, e.getSysdynRightEdge()); +// first = false; +// } +// edgesOutOfDate = false; +// } + } + + public double getTopEdge() { + updateEdges(); + return topEdge; + } + + public double getBottomEdge() { + updateEdges(); + return bottomEdge; + } + + public double getLeftEdge() { + updateEdges(); + return leftEdge; + } + + public double getRightEdge() { + updateEdges(); + return rightEdge; + } + + public double getWidth() { + updateEdges(); + return rightEdge - leftEdge; + } + + public double getHeight() { + updateEdges(); + return bottomEdge - topEdge; + } + + public void setOffset(double horizontal, double vertical) { + hOffset = horizontal; + vOffset = vertical; + } + + private double hOffset, vOffset; + + public double getHorizontalOffset() { + return hOffset; + } + + public double getVerticalOffset() { + return vOffset; + } + + public void addComment(SketchComment comment) { + comments.add(comment); + objects.put(comment.getId(), comment); + } + + public List getComments() { + return comments; + } + + public void addConnection(SketchConnection connection) { + connections.add(connection); + objects.put(connection.getId(), connection); + } + + public List getConnections() { + return connections; + } + + public void addValve(SketchValve valve) { + valves.add(valve); + objects.put(valve.getId(), valve); + // replace the attached variable with the valve in order to redirect + // possible connections to the variable to the valve + objects.put(valve.getAttached().getId(), valve); + } + + public List getValves() { + return valves; + } + + public void addVariable(SketchVariable variable) { + variables.add(variable); + objects.put(variable.getId(), variable); + } + + public List getVariables() { + return variables; + } + + public SketchObject getObject(int id) { + return objects.get(id); + } + + public List getAllElements() { + ArrayList list = new ArrayList(); + list.addAll(getComments()); + list.addAll(getValves()); + list.addAll(getVariables()); + return list; + } + + public List getShadowVariables() { + List variables = new ArrayList(); + for (SketchVariable var : getVariables()) { + if (!var.allowsIn()) { + variables.add(var); + } + } + return variables; + } + + public List getNonShadowVariables() { + List variables = new ArrayList(); + variables.addAll(getVariables()); + variables.removeAll(getShadowVariables()); + return variables; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchComment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchComment.java new file mode 100644 index 00000000..8cae21d9 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchComment.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.model.element.Cloud; +import org.simantics.sysdyn.modelImport.model.element.Comment; +import org.simantics.sysdyn.modelImport.model.element.Symbol; + +public class SketchComment extends SketchElement { + + private static final String SKETCH_COMMENT = + "12,"+KEEP_I+KEEP_I+"("+ELEMENT_SUFFIX+")"; + private static final int commentId = 1; + private static final int commentIcon = 2; + private static final int commentSuffix = 3; + + public enum CommentIcon { + CLOUD, OTHER + } + + private String text; + private CommentIcon icon; + + protected SketchComment(int id, CommentIcon icon) { + super(id); + this.icon = icon; + } + + public static SketchComment getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SKETCH_COMMENT).matcher(line); + if (!matcher.matches()) { + return null; + } + + int id = Integer.parseInt(matcher.group(commentId)); + + CommentIcon icon; + switch (Integer.parseInt(matcher.group(commentIcon))) { + case 48: icon = CommentIcon.CLOUD; break; + default: icon = CommentIcon.OTHER; break; + } + + SketchComment element = new SketchComment(id, icon); + element.parseSuffix(matcher.group(commentSuffix)); + return element; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public CommentIcon getIcon() { + return icon; + } + + @Override + public Symbol getSymbol(MdlModel mdl, Sketch sketch) { + if (isInputOutput()) + return new Comment(getDimensions(), "I/O objects are not supported"); + + switch(icon) { + case CLOUD: return new Cloud(getDimensions(sketch)); + case OTHER: return new Comment(getDimensions(sketch), text); + default: return null; + } + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchConnection.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchConnection.java new file mode 100644 index 00000000..74cb1bf7 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchConnection.java @@ -0,0 +1,179 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.element.Connection; +import org.simantics.sysdyn.modelImport.model.element.Dependency; +import org.simantics.sysdyn.modelImport.model.element.Symbol; +import org.simantics.sysdyn.modelImport.model.element.Flow; + +public class SketchConnection extends SketchObject { + + public enum ConnectionType { + ARROW, LINE_ARROW, LINE_SEGMENT, OTHER + } + + // some shorthands + private static final String KEEP_I = MdlUtil.INT_G+","; + private static final String SKIP_I = MdlUtil.INT+","; + private static final String SKIP_ANY = "[^,]*,"; + + private static final String POINTS = "(\\d+\\|(?:\\(-?\\d+,-?\\d+\\)\\|)+)"; + + // each sketch connection is declared with a string: + // 1,id,from,to,shape,hid,pol,thick,hasf,dtype,res,color,font,np|plist + + // the following regular expression matches a connection declaration and + // extracts the useful information from it + private static final String SKETCH_CONNECTION = + "1,"+KEEP_I+KEEP_I+KEEP_I+KEEP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_I+SKIP_ANY+SKIP_ANY+POINTS; + // corresponding group indices + private static final int connectionId = 1; + private static final int connectionFrom = 2; + private static final int connectionTo = 3; + private static final int connectionShape = 4; + private static final int connectionPoints = 5; + + private static final String SAVE = "(-?\\d+),"; + private static final String SKIP = "-?\\d+,"; + + public static final String sketchConnection = + // 1, id, from,to, shape,hid, pol, thick,hasf,dtype,res, color,font,np|plist + "1,"+SAVE+SAVE+SAVE+SAVE+ SKIP+SKIP+SKIP+ SKIP+SKIP+ SKIP+"[^,]*,[^,]*,"+POINTS; + + private int from; + private int to; + private ConnectionType type; + int[] points; + + protected SketchConnection(int id, int from, int to, ConnectionType type, int[] points) { + super(id); + this.from = from; + this.to = to; + this.type = type; + this.points = points; + } + + public static SketchConnection getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SKETCH_CONNECTION).matcher(line); + if (!matcher.matches()) { + return null; + } + + int id = Integer.parseInt(matcher.group(connectionId)); + int from = Integer.parseInt(matcher.group(connectionFrom)); + int to = Integer.parseInt(matcher.group(connectionTo)); + int connType = Integer.parseInt(matcher.group(connectionShape)); + + ConnectionType type; + switch (Integer.parseInt(matcher.group(connectionShape))) { + case 0: + case 1: type = ConnectionType.ARROW; break; + case 4: type = ConnectionType.LINE_ARROW; break; + case 100: type = ConnectionType.LINE_SEGMENT; break; + default: + System.err.println("connection type "+connType+" not recognized"); + type = ConnectionType.OTHER; break; + } + + int[] points = parsePoints(matcher.group(connectionPoints)); + + return new SketchConnection(id, from, to, type, points); + } + + private static int[] parsePoints(String str) { + int sep = str.indexOf('|'); + int count = Integer.parseInt(str.substring(0, sep)); + int[] points = new int[count*2]; + for (int i = 0; i < count; i++) { + int start = sep + 1; + sep = str.indexOf('|', start); + String[] pair = str.substring(start+1, sep-1).split(","); + points[i*2] = Integer.parseInt(pair[0]); + points[i*2+1] = Integer.parseInt(pair[1]); + } + return points; + } + + public int getFrom() { + return from; + } + + public int getTo() { + return to; + } + + public ConnectionType getType() { + return type; + } + + public int[] getPoints() { + return points; + } + + public Connection getConnection(Sketch sketch) { + Symbol tail = (Symbol)sketch.getObject(from).getModelObject(); + if (tail == null) { + return null; + } + Symbol head = (Symbol)sketch.getObject(to).getModelObject(); + if (head == null) { + return null; + } + + switch (type) { + case ARROW: return new Dependency(tail, head, true, false, getAngle(sketch)); + case LINE_ARROW: return new Flow(tail, head); + case LINE_SEGMENT: return new Flow(head, tail); + default: return null; + } + } + + public double getAngle(Sketch sketch) { + if (points == null || points.length < 2) { + return 0; + } + + SketchElement tail = (SketchElement)sketch.getObject(from); + SketchElement head = (SketchElement)sketch.getObject(to); + + // 'from' element is in (x0, y0) and 'to' element is in (x2, y2) + double x0 = tail.getX(); + double y0 = tail.getY(); + double x2 = head.getX(); + double y2 = head.getY(); + + // treat the first points in points as the control point (x1, y1) + double x1 = (double)points[0]; + double y1 = (double)points[1]; + + //System.err.println("("+x0+","+y0+") -> ("+x1+","+y1+") -> ("+x2+","+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 (p1-p0) x (p2-p0) + double dd = dx0*dy - dy0*dx; + + if (Math.abs(dd) < 0.01) { + // Points are (almost) collinear + return 0; + } + else { + // (p1-p0) * (p1-p2) / dd + double offset = (dx0*dx1 + dy0*dy1) / dd; + double angle = Math.PI/2 - Math.atan(offset); + if (dd > 0) + angle = angle - Math.PI; + return angle; + } + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchElement.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchElement.java new file mode 100644 index 00000000..b0418646 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchElement.java @@ -0,0 +1,141 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.element.Symbol; +import org.simantics.sysdyn.modelImport.model.element.Valve.TextPosition; + +public abstract class SketchElement extends SketchObject { + + // some shorthands + protected static final String KEEP_I = MdlUtil.INT_G+","; + protected static final String SKIP_I = MdlUtil.INT+","; + + // each sketch element is declared with a string: + // n,id,name,x,y,w,h,sh,bits,hid,hasf,tpos,bw,nav1,nav2(,box,fill,font) + + // n, id and name depend on the type of the sketch element, and some + // of the fields in the suffix do not contain useful information + + // the following regular expression matches the suffix of an element + // declaration and extracts the useful information from it + protected static final String ELEMENT_SUFFIX = + KEEP_I+KEEP_I+KEEP_I+KEEP_I+KEEP_I+KEEP_I+SKIP_I+SKIP_I+KEEP_I+".*"; + // corresponding group indices + protected static final int elementX = 1; + protected static final int elementY = 2; + protected static final int elementWidth = 3; + protected static final int elementHeight = 4; + protected static final int elementShape = 5; + protected static final int elementBits = 6; + protected static final int elementTextPos = 7; + + private int x; + private int y; + private int width; + private int height; + private boolean attached; + private boolean allowsIn; + private boolean allowsOut; + private boolean inputOutput; + private boolean textLine; + private TextPosition textPosition; + + protected SketchElement(int id) { + super(id); + } + + protected void parseSuffix(String suffix) + throws Exception { + Matcher matcher = Pattern.compile(ELEMENT_SUFFIX).matcher(suffix); + if (!matcher.matches()) { + // this should not happen unless subclasses fail to construct their + // regular expressions properly + throw new Exception("could not parse element suffix "+suffix); + } + + x = Integer.parseInt(matcher.group(elementX)); + y = Integer.parseInt(matcher.group(elementY)); + width = Integer.parseInt(matcher.group(elementWidth)); + height = Integer.parseInt(matcher.group(elementHeight)); + attached = (Integer.parseInt(matcher.group(elementShape)) & 1<<5) != 0; + allowsIn = (Integer.parseInt(matcher.group(elementBits)) & 1) != 0; + allowsOut = (Integer.parseInt(matcher.group(elementBits)) & 1<<1) != 0; + inputOutput = (Integer.parseInt(matcher.group(elementBits)) & 1<<3) != 0; + textLine = (Integer.parseInt(matcher.group(elementBits)) & 1<<2) != 0; + + switch (Integer.parseInt(matcher.group(elementTextPos))) { + case 0: textPosition = TextPosition.INSIDE; break; + case 1: textPosition = TextPosition.BELOW; break; + case 2: textPosition = TextPosition.LEFT; break; + case 3: textPosition = TextPosition.ABOVE; break; + case 4: textPosition = TextPosition.RIGHT; break; + default: textPosition = TextPosition.UNSET; break; + } + + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public boolean isAttached() { + return attached; + } + + public boolean allowsIn() { + return allowsIn; + } + + public boolean allowsOut() { + return allowsOut; + } + + public boolean isInputOutput() { + return inputOutput; + } + + public boolean hasTextLine() { + return textLine; + } + + public TextPosition getTextPosition() { + return textPosition; + } + + public abstract Symbol getSymbol(MdlModel mdl, Sketch sketch); + + private static final double SCALE_MULTIPLIER = 0.4; + + public double[] getDimensions(Sketch sketch) { + double[] dimensions = getDimensions(); + dimensions[0] = dimensions[0] + sketch.getHorizontalOffset(); + dimensions[1] = dimensions[1] + sketch.getVerticalOffset(); + return dimensions; + } + + // get element dimensions, [x, y, width, height] + public double[] getDimensions() { + double[] dimensions = new double[4]; + dimensions[0] = (getX() - getWidth()) * SCALE_MULTIPLIER; + dimensions[1] = (getY() - getHeight()) * SCALE_MULTIPLIER; + dimensions[2] = getWidth() * 2 * SCALE_MULTIPLIER; + dimensions[3] = getHeight() * 2 * SCALE_MULTIPLIER; + return dimensions; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchObject.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchObject.java new file mode 100644 index 00000000..8bf51055 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchObject.java @@ -0,0 +1,26 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import org.simantics.sysdyn.modelImport.model.IWriteableObject; + +public abstract class SketchObject { + + private int id; + private IWriteableObject modelObject; + + protected SketchObject(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public void setModelObject(IWriteableObject modelObject) { + this.modelObject = modelObject; + } + + public IWriteableObject getModelObject() { + return modelObject; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchValve.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchValve.java new file mode 100644 index 00000000..2d0c88ce --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchValve.java @@ -0,0 +1,56 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.model.element.Valve; +import org.simantics.sysdyn.modelImport.model.element.Valve.Orientation; + +public class SketchValve extends SketchElement { + + private static final String SKETCH_VALVE = + "11,"+KEEP_I+SKIP_I+"("+ELEMENT_SUFFIX+")"; + private static final int valveId = 1; + private static final int valveSuffix = 2; + + private SketchVariable attached; + + protected SketchValve(int id) { + super(id); + } + + public static SketchValve getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SKETCH_VALVE).matcher(line); + if (!matcher.matches()) { + return null; + } + + int id = Integer.parseInt(matcher.group(valveId)); + + SketchValve element = new SketchValve(id); + element.parseSuffix(matcher.group(valveSuffix)); + return element; + } + + public SketchVariable getAttached() { + return attached; + } + + public void setAttached(SketchVariable attached) { + this.attached = attached; + } + + @Override + public Valve getSymbol(MdlModel mdl, Sketch sketch) { + Variable variable = mdl.getVariable(attached.getName()); + if (variable == null) { + return null; + } + + Valve valve = new Valve(Orientation.HORIZONTAL, getTextPosition()); + + return variable.setUpModelVariable(valve, getDimensions(sketch), mdl); + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java new file mode 100644 index 00000000..5137203e --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SketchVariable.java @@ -0,0 +1,64 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.element.Auxiliary; +import org.simantics.sysdyn.modelImport.model.element.ModelVariable; +import org.simantics.sysdyn.modelImport.model.element.Symbol; +import org.simantics.sysdyn.modelImport.model.element.Stock; +import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression; + +public class SketchVariable extends SketchElement { + + private static final String SKETCH_VARIABLE = + "10,"+KEEP_I+MdlUtil.VARIABLE+",("+ELEMENT_SUFFIX+")"; + private static final int variableId = 1; + private static final int variableName = 2; + private static final int variableSuffix = 3; + + private String name; + + protected SketchVariable(int id, String name) { + super(id); + this.name = name; + } + + public static SketchVariable getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SKETCH_VARIABLE).matcher(line); + if (!matcher.matches()) { + return null; + } + + int id = Integer.parseInt(matcher.group(variableId)); + String name = MdlUtil.normalize(matcher.group(variableName)); + + SketchVariable element = new SketchVariable(id, name); + element.parseSuffix(matcher.group(variableSuffix)); + return element; + } + + public String getName() { + return name; + } + + @Override + public ModelVariable getSymbol(MdlModel mdl, Sketch sketch) { + Variable variable = mdl.getVariable(name); + if (variable == null) { + return null; + } + + ModelVariable var; + + if (variable.getExpressionString() != null && variable.getExpressionString().startsWith("INTEG")) + var = new Stock(); + else + var = new Auxiliary(); + + return variable.setUpModelVariable(var, getDimensions(sketch), mdl); + } + +} \ No newline at end of file diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Subscript.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Subscript.java new file mode 100644 index 00000000..820a608f --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Subscript.java @@ -0,0 +1,81 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.support.Enumeration; + +public class Subscript extends Declaration { + + private static final String SUBSCRIPT_DECL = + "("+MdlUtil.BASIC_NAME+")\\s*(:|<->)\\s*([^~]*?)("+DECL_SUFFIX+")"; + private static final int subscriptName = 1; + private static final int subscriptType = 2; + private static final int subscriptExpression = 3; + private static final int subscriptSuffix = 4; + + private String original; + private List values; + + private Enumeration enumeration; + + protected Subscript(String name, List values) { + super(name); + this.original = null; + this.values = values; + } + + protected Subscript(String name, String original) { + super(name); + this.original = original; + this.values = null; + } + + public static Subscript getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SUBSCRIPT_DECL).matcher(line); + if (!matcher.matches()) + return null; + + String name = MdlUtil.normalize(matcher.group(subscriptName)); + boolean equivalent = matcher.group(subscriptType).equals("<->"); + String expression = MdlUtil.normalize(matcher.group(subscriptExpression)); + + Subscript subscript; + if (equivalent) + subscript = new Subscript(name, expression); + else + subscript = new Subscript(name, Arrays.asList(expression.split(","))); + subscript.parseSuffix(matcher.group(subscriptSuffix)); + return subscript; + } + + public String getOriginal() { + return original; + } + + public List getValues(MdlModel mdl) { + if (values != null) + return values; + else + return mdl.getSubscript(original).getValues(mdl); + } + + public boolean isEquivalent() { + return original != null; + } + + public Enumeration getEnumeration(MdlModel mdl) { + if (enumeration == null) { + enumeration = new Enumeration(getName(), getValues(mdl)); + } + + return enumeration; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java new file mode 100644 index 00000000..23bf744e --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/SubscriptVariable.java @@ -0,0 +1,271 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.expression.EnumerationExpression; +import org.simantics.sysdyn.modelImport.model.expression.NormalExpression; +import org.simantics.sysdyn.modelImport.model.support.Enumeration; + +public class SubscriptVariable extends Variable { + + // a subscript variable is a variable that has a different equation + // depending on the value of the subscript it references + private static final String SUBSCRIPT_VARIABLE_DECL = + MdlUtil.SUBSCRIPT+EXPRESSION+"("+DECL_SUFFIX+")";; + private static final int subscriptVariableName = 1; + private static final int subscriptVariableIndices = 2; + private static final int subscriptVariableExpression = 3; + private static final int subscriptVariableSuffix = 4; + + private String[] indices; + private SubscriptVariable next; + + protected SubscriptVariable(String name, String expression, String[] indices) { + super(name, expression); + this.indices = indices; + this.next = null; + } + + public static SubscriptVariable getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(SUBSCRIPT_VARIABLE_DECL).matcher(line); + if (!matcher.matches()) { + return null; + } + + String name = MdlUtil.normalize(matcher.group(subscriptVariableName)); + String[] indices = MdlUtil.normalize(matcher.group(subscriptVariableIndices)).split(","); + String expression = matcher.group(subscriptVariableExpression); + if (expression != null) + expression = MdlUtil.normalize(expression); + + SubscriptVariable subVar = new SubscriptVariable(name, expression, indices); + subVar.parseSuffix(matcher.group(subscriptVariableSuffix)); + return subVar; + } + + public String[] getIndices() { + return indices; + } + + private SubscriptVariable getNext() { + return next; + } + + private void setNext(SubscriptVariable next) { + this.next = next; + } + + public void addSubscriptVariable(SubscriptVariable variable) { + // find the last variable in the list and add the new variable after it + SubscriptVariable last = this; + while (last.getNext() != null) + last = last.getNext(); + last.setNext(variable); + } + + @Override + public EnumerationExpression getExpression(MdlModel mdl) { + SubscriptVariable var; + + // find out what subscripts the combined expression uses by collecting + // all subscript indices from individual expressions into a list of + // sets (one set for each "position" in the indices) + + List> subscripts = new ArrayList>(); + for (int i = 0; i < indices.length; i++) { + subscripts.add(new HashSet()); + } + + var = this; + while (var != null) { + for (int i = 0; i < var.getIndices().length; i++) { + subscripts.get(i).add(var.getIndices()[i]); + } + + var = var.getNext(); + } + + // turn the aforementioned list of sets into a list of enumeration + // by finding the enumerations that correspond to the sets of subscript + // indices + + List enumerations = new ArrayList(); + for (Set values : subscripts) { + Subscript potential = mdl.resolveSubscript(values); + if (potential == null) { + System.err.println("subscript indices could not be resolved "); + for (String value : values) { + System.err.println(" "+value); + } + System.err.println(); + } + enumerations.add(potential.getEnumeration(mdl)); + } + + EnumerationExpression expr = new EnumerationExpression(enumerations); + + // populate the created expression (TODO: comment) + + // TODO: is this check correct, also does not work correctly yet + if (next == null && enumerations.size() == 2) { + // option a: +// StringBuilder buffer = new StringBuilder(); +// buffer.append('{'); +// for (int i = 0; i < values.length; i++) { +// if (i > 0) { +// buffer.append(','); +// } +// buffer.append('{'); +// for (int j = 0; j < values[i].length; j++) { +// if (j > 0) { +// buffer.append(','); +// } +// buffer.append(values[i][j]); +// } +// buffer.append('}'); +// } +// buffer.append('}'); +// +// String[] exprindices = new String[enumerations.size()]; +// for (int i = 0; i < exprindices.length; i++) { +// exprindices[i] = enumerations.get(i).getName(); +// } +// +// expr.addExpression(new NormalExpression(buffer.toString()), exprindices); +// return expr; + + // option b: (probably more sensible) + double[][] values = getPossibleValueArray(getExpressionString()); + if (values != null) { + for (int i = 0; i < values.length; i++) { + for (int j = 0; j < values[i].length; j++) { + expr.addExpression( + new NormalExpression(Double.toString(values[i][j])), + enumerations.get(0).getValues().get(i), + enumerations.get(1).getValues().get(j)); + } + } + return expr; + } + } + + var = this; + while (var != null) { + + Deque workqueue = new ArrayDeque(); + workqueue.add(new WorkExpression(var.getIndices(), var.getExpressionString())); + + for (int i = 0; i < var.getIndices().length; i++) { + int limit = workqueue.size(); + for (int j = 0; j < limit; j++) { + WorkExpression current = workqueue.pollFirst(); + Subscript potential = mdl.getSubscript(current.indices[i]); + if (potential != null) { + for (String value : potential.getValues(mdl)) { + String[] newindices = Arrays.copyOf(current.indices, current.indices.length); + newindices[i] = value; + String newexpression = current.expression; + newexpression = MdlUtil.replaceSubscripts(newexpression, potential.getName(), value); + workqueue.addLast(new WorkExpression(newindices, newexpression)); + } + } + else { + workqueue.addLast(current); + } + } + } + + for (WorkExpression we : workqueue) { + // TODO: is this check correct + String expression = MdlUtil.finalize(we.expression, mdl); + if (next == null) { + expression = removeComparisons(expression, indices, we.indices); + } + expr.addExpression(parseExpression(expression), we.indices); + } + + var = var.getNext(); + } + + return expr; + } + + private class WorkExpression { + String[] indices; + String expression; + + private WorkExpression(String[] indices, String expression) { + this.indices = indices; + this.expression = expression; + } + } + + private static double[][] getPossibleValueArray(String expression) { + // (number(,number)*;)* + Matcher matcher = Pattern.compile( + "("+MdlUtil.DBL+"(,"+MdlUtil.DBL+")*;)*" + ).matcher(expression); + + if (!matcher.matches()) { + return null; + } + + String[] rows = expression.split(";"); + double[][] result = new double[rows.length][]; + for (int i = 0; i < rows.length; i++) { + String[] columns = rows[i].split(","); + result[i] = new double[columns.length]; + for (int j = 0; j < columns.length; j++) { + result[i][j] = Double.parseDouble(columns[j]); + } + } + + return result; + } + + private static String removeComparisons(String expression, String[] subscripts, String[] values) { + + if (!expression.contains("=")) { + return expression; + } + + for (int i = 0; i < subscripts.length; i++) { + for (int j = 0; j < subscripts.length; j++) { + StringBuilder result = new StringBuilder(); + int offset = 0; + + Matcher matcher = Pattern.compile(subscripts[i]+"\\s*=\\s*"+subscripts[j]).matcher(expression); + while (matcher.find()) { + result.append(expression.substring(offset, matcher.start())); + + if (values[i].equals(values[j])) { + result.append("true"); + } + else { + result.append("false"); + } + + offset = matcher.end(); + } + if (offset < expression.length()) { + result.append(expression.substring(offset)); + } + + expression = result.toString(); + } + } + + return expression; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Variable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Variable.java new file mode 100644 index 00000000..7dceeaef --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/mdl/Variable.java @@ -0,0 +1,159 @@ +package org.simantics.sysdyn.modelImport.mdl; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.modelImport.MdlUtil; +import org.simantics.sysdyn.modelImport.model.element.ModelVariable; +import org.simantics.sysdyn.modelImport.model.expression.DelayExpression; +import org.simantics.sysdyn.modelImport.model.expression.Expression; +import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression; +import org.simantics.sysdyn.modelImport.model.expression.NormalExpression; +import org.simantics.sysdyn.modelImport.model.support.Range; + +public class Variable extends Declaration { + + protected static final String EXPRESSION = + "(?:\\s*=\\s*([^~]*?(?:"+MdlUtil.SPECIAL_NAME+"[^~]*?)*))?"; + + private static final String VARIABLE_DECL = + MdlUtil.VARIABLE+EXPRESSION+"("+DECL_SUFFIX+")"; + private static final int variableName = 1; + private static final int variableExpression = 2; + private static final int variableSuffix = 3; + + private String expression; + + protected Variable(String name, String expression) { + super(name); + this.expression = expression; + } + + public static Variable getPossible(String line) + throws Exception { + Matcher matcher = Pattern.compile(VARIABLE_DECL).matcher(line); + if (!matcher.matches()) { + return null; + } + + String name = MdlUtil.normalize(matcher.group(variableName)); + String expression = matcher.group(variableExpression); + if (expression != null) + expression = MdlUtil.normalize(expression); + + Variable var = new Variable(name, expression); + var.parseSuffix(matcher.group(variableSuffix)); + return var; + } + + public String getExpressionString() { + return expression; + } + + public T setUpModelVariable(T variable, + double[] dimensions, MdlModel mdl) { + variable.setName(getName()); + if (expression != null) + variable.setExpression(getExpression(mdl)); + + String unit = getUnit(); + Range range = parseRange(unit); + if (range != null) + unit = unit.substring(0, unit.indexOf('[')).trim(); + + variable.setUnit(unit); + if (range != null) + variable.setRange(range); + variable.setDescription(getDescription()); + + variable.setDimensions(dimensions); + + return variable; + } + + public Expression getExpression(MdlModel mdl) { + return parseExpression(MdlUtil.finalize(expression, mdl)); + } + + protected static Expression parseExpression(String expression) { + Matcher matcher = Pattern.compile( + MdlUtil.FUNCTION+"(.*)\\)" + ).matcher(expression); + if (!matcher.matches()) { + // the expression is not one of the special function calls + return new NormalExpression(expression); + } + + String function = matcher.group(1); + String[] parameters = MdlUtil.splitFunctionParameters(matcher.group(2)); + + if (function.startsWith("INTEG")) { + // an integral expression + if (parameters.length != 2) { + System.err.println("malformed integral expression: "+expression); + return null; + } + return new IntegralExpression(parameters[0], parameters[1]); + } + else if (function.startsWith("DELAY N")) { + // a delay expression + if (parameters.length != 4) { + System.err.println("malformed delay expression: "+expression); + return null; + } + return new DelayExpression(parameters[0], parameters[1], parameters[2], Integer.parseInt(parameters[3])); + } + else if (function.startsWith("SMOOTHI")) { + if (parameters.length != 3) { + System.err.println("malformed smoothi expression: "+expression); + } + // what is the correct degree for smooth? + return new DelayExpression(parameters[0], parameters[1], parameters[2], 1); + } + else if (function.startsWith("SMOOTH")) { + if (parameters.length != 2) { + System.err.println("malformed smooth expression: "+expression); + } + // what is the correct degree and initial value for smooth? + return new DelayExpression(parameters[0], parameters[1], parameters[0], 1); + } + else if (function.startsWith("GAME")) { + // a game expression, currently treated as a normal expression + if (parameters.length != 1) { + System.err.println("malformed game expression: "+expression); + return null; + } + return new NormalExpression(parameters[0]); + } + else { + return new NormalExpression(expression); + } + } + + private static Range parseRange(String unit) { + Matcher matcher = Pattern.compile( + "\\["+MdlUtil.DBL_G+",(\\?|"+MdlUtil.DBL_G+"|"+MdlUtil.DBL_G+","+MdlUtil.DBL_G+")\\]" + ).matcher(unit); + if (matcher.find()) { + Double start, end, step; + start = Double.parseDouble(matcher.group(1)); + if (matcher.group(2).equals("?")) { + end = null; + step = null; + } + else if (matcher.group(2).contains(",")){ + end = Double.parseDouble(matcher.group(4)); + step = Double.parseDouble(matcher.group(5)); + } + else { + end = Double.parseDouble(matcher.group(3)); + step = null; + } + return new Range(start, end, step); + } + else { + return null; + } + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Flow.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/IWriteableObject.java similarity index 55% rename from org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Flow.java rename to org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/IWriteableObject.java index b8e8e50f..0d327b0c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/mdlImport/mdlElements/Flow.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/IWriteableObject.java @@ -9,25 +9,29 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.sysdyn.mdlImport.mdlElements; +package org.simantics.sysdyn.modelImport.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(); - } - } +public interface IWriteableObject { + + /** + * Write this object to the graph and return the corresponding resource. + * + * @param graph + * @param parent + * @param context + * @return Resource + * @throws DatabaseException + */ + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException; + + /** + * Return the resource corresponding to this object or null if this object has not been written yet. + * + * @return Resource + */ + public Resource getResource(); } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java new file mode 100644 index 00000000..0b56e6e6 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/Model.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * 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.modelImport.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.simantics.databoard.Bindings; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.sysdyn.modelImport.model.element.Connection; +import org.simantics.sysdyn.modelImport.model.element.Symbol; +import org.simantics.sysdyn.modelImport.model.element.ModelVariable; +import org.simantics.sysdyn.modelImport.model.element.Shadow; +import org.simantics.sysdyn.modelImport.model.support.Enumeration; +import org.simantics.sysdyn.modelImport.model.support.Function; +import org.simantics.sysdyn.utils.ModelUtils; + +public class Model implements IWriteableObject { + + private String name; + // necessary simulation parameters + private double start, stop, step; + + // the structure of the model + private HashMap variables; + private HashMap enumerations; + private HashMap functions; + + private ArrayList symbols; + private ArrayList shadows; + private ArrayList connections; + + private Resource model; + + public Model(String name) { + this.name = name; + + variables = new HashMap(); + enumerations = new HashMap(); + functions = new HashMap(); + + symbols = new ArrayList(); + shadows = 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 addSymbol(ModelVariable variable) { + if (variables.get(variable.getName()) != null) { + System.err.println("variable "+variable.getName()+" already defined"); + } + + variables.put(variable.getName(), variable); + + symbols.add(variable); + } + + public ModelVariable getVariable(String name) { + return variables.get(name); + } + + public Collection getVariables() { + return variables.values(); + } + + public void addSymbol(Shadow shadow) { + shadows.add(shadow); + } + + public void addSymbol(Symbol element) { + symbols.add(element); + } + + public void addConnection(Connection connection) { + // TODO: make sure connection head and tail exist + connections.add(connection); + } + + public void addEnumeration(Enumeration enumeration) { + if (enumerations.get(enumeration.getName()) != null) { + System.err.println("enumeration "+enumeration.getName()+" already defined"); + } + enumerations.put(enumeration.getName(), enumeration); + } + + public Enumeration getEnumeration(String name) { + return enumerations.get(name); + } + + public Collection getEnumerations() { + return enumerations.values(); + } + + public void addFunction(Function function) { + if (functions.get(function.getName()) != null) { + System.err.println("function "+function.getName()+" already defined"); + } + functions.put(function.getName(), function); + } + + public Function getEFunction(String name) { + return functions.get(name); + } + + public Collection getFunctions() { + return functions.values(); + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + SimulationResource sim = SimulationResource.getInstance(graph); + + model = ModelUtils.createModel(graph); + graph.claimLiteral(model, l0.HasLabel, name, Bindings.STRING); + + // TODO: set simulation parameters + + Resource configuration = graph.getSingleObject(model, sim.HasConfiguration); + + for (Enumeration e : getEnumerations()) { + e.write(graph, configuration, context); + } + + for (Function f : getFunctions()) { + f.write(graph, model, context); + } + + for (Symbol e : symbols) { + e.write(graph, configuration, context); + } + + for (Shadow s : shadows) { + s.write(graph, configuration, context); + } + + for (Connection c : connections) { + c.write(graph, configuration, context); + } + + Resource diagram = graph.getSingleObject(configuration, mr.CompositeToDiagram); + graph.claimLiteral(diagram, dr.HasModCount, context.getObjectCount(), Bindings.LONG); + + return model; + } + + @Override + public Resource getResource() { + return model; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/WriteContext.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/WriteContext.java new file mode 100644 index 00000000..1cc4f3d2 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/WriteContext.java @@ -0,0 +1,105 @@ +package org.simantics.sysdyn.modelImport.model; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.simantics.db.Resource; +import org.simantics.sysdyn.modelImport.model.support.Enumeration; + +public class WriteContext { + + private long objectCount; + + private long cloudCount; + private long shadowCount; + private long dependencyCount; + private long flowCount; + + private HashMap enumerations; + private HashMap> enumerationValues; + + public WriteContext() { + objectCount = 0; + + cloudCount = 0; + shadowCount = 0; + dependencyCount = 0; + flowCount = 0; + + enumerations = new HashMap(); + enumerationValues = new HashMap>(); + } + + public String getNextObject() { + return Long.toString(objectCount++); + } + + public long getObjectCount() { + return objectCount; + } + + public String getNextCloud() { + return "Cloud" + cloudCount++; + } + + public String getNextShadow() { + return "Shadow" + shadowCount++; + } + + public String getNextDependency() { + return "Dependency" + dependencyCount++; + } + + public String getNextFlow() { + return "Flow" + flowCount++; + } + + public void registerEnumeration(Enumeration enumeration, boolean copy) { + enumerations.put(enumeration.getName(), enumeration); + if (enumerationValues.get(enumeration.getName()) == null) { + enumerationValues.put(enumeration.getName(), new HashSet()); + } + enumerationValues.get(enumeration.getName()).add(enumeration); + if (!copy) { + for (String value : enumeration.getValues()) { + if (enumerationValues.get(value) == null) { + enumerationValues.put(value, new HashSet()); + } + enumerationValues.get(value).add(enumeration); + } + } + } + + public Enumeration getEnumeration(Set indices) { + System.err.println("size is "+indices.size()); + if (indices.size() == 1) { + Enumeration enumeration = enumerations.get(indices.iterator().next()); + if (enumeration != null) { + return enumeration; + } + } + + // the set of potential matches is the intersection of all sets of + // enumerations that contain any of the given indices as elements + Set potential = new HashSet(enumerations.values()); + for (String index : indices) { + potential.retainAll(enumerationValues.get(index)); + } + + // if there is more than one potential match, the enumerations are not + // well defined (there are multiple enumerations with similar indices) + if (potential.size() == 1) { + return potential.iterator().next(); + } + else { + System.err.println("enumeration could not be resolved "+potential.size()); + for (String index : indices) + System.err.println(" "+index); + return null; + } + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Auxiliary.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Auxiliary.java new file mode 100644 index 00000000..e30545b6 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Auxiliary.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.expression.Expression; +import org.simantics.sysdyn.modelImport.model.support.Range; + +public class Auxiliary extends ModelVariable { + + public Auxiliary() { + + } + + public Auxiliary(double[] dim, String name, Expression expression, Range range, String unit, String description) { + super(dim, name, expression, range, unit, description); + } + + @Override + public Resource getVariableType(ReadGraph graph) { + return SysdynResource.getInstance(graph).Auxiliary; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).AuxiliarySymbol; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Cloud.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Cloud.java new file mode 100644 index 00000000..9687c533 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Cloud.java @@ -0,0 +1,51 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +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; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Cloud extends Symbol { + + private Resource cloud; + + public Cloud() { + + } + + public Cloud(double[] dim) { + super(dim); + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + cloud = GraphUtils.create2(graph, sr.Cloud, + l0.HasName, context.getNextCloud(), + l0.PartOf, parent); + + Resource symbol = super.write(graph, parent, context); + graph.claim(symbol, mr.ElementToComponent, cloud); + + return cloud; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).CloudSymbol; + } + + @Override + public Resource getResource() { + return cloud; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Comment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Comment.java new file mode 100644 index 00000000..b632ca1d --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Comment.java @@ -0,0 +1,58 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Comment extends Symbol { + + private String text; + + public Comment() { + + } + + public Comment(String text) { + this.text = text; + } + + public Comment(double[] dim, String text) { + super(dim); + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(graph); + + Resource symbol = super.write(graph, parent, context); + + graph.claimLiteral(symbol, dr.HasText, text, Bindings.STRING); + + return symbol; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).AdditionalSymbols_MultilineText; + } + + @Override + public Resource getResource() { + // comments only have diagram resources + return getDiagramResource(); + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Connection.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Connection.java new file mode 100644 index 00000000..dda8b59a --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Connection.java @@ -0,0 +1,98 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +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; +import org.simantics.sysdyn.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public abstract class Connection implements IWriteableObject { + + private Symbol head; + private Symbol tail; + + private Resource connection; + private Resource diagramConnection; + + public Connection() { + + } + + public Connection(Symbol tail, Symbol head) { + this.tail = tail; + this.head = head; + } + + public Symbol getHead() { + return head; + } + + public void setHead(Symbol head) { + this.head = head; + } + + public Symbol getTail() { + return tail; + } + + public void setTail(Symbol tail) { + this.tail = tail; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + connection = GraphUtils.create2(graph, getConnectionType(graph), + sr.Variable_HasHead, head.getResource(), + sr.Variable_HasTail, tail.getResource(), + l0.PartOf, parent); + graph.claim(connection, mr.Mapped, connection); + + Resource diagram = graph.getSingleObject(parent, mr.CompositeToDiagram); + + Resource tailConnector = GraphUtils.create2(graph, dr.Connector, + sr.HasTailTerminal, tail.getDiagramResource()); + + Resource headConnector = GraphUtils.create2(graph, dr.Connector, + sr.HasHeadTerminal, head.getDiagramResource(), + dr.AreConnected, tailConnector); + + diagramConnection = GraphUtils.create2(graph, getDiagramConnectionType(graph), + l0.HasName, context.getNextObject(), + l0.PartOf, diagram, + sr2.HasConnectionType, sr.SysdynConnectionType, + mr.DiagramConnectionToConnection, connection, + dr.HasArrowConnector, headConnector, + dr.HasPlainConnector, tailConnector); + + OrderedSetUtils.add(graph, diagram, diagramConnection); + + return connection; + } + + public abstract Resource getConnectionType(ReadGraph graph); + public abstract Resource getDiagramConnectionType(ReadGraph graph); + + @Override + public Resource getResource() { + return connection; + } + + public Resource getDiagramResource() { + return diagramConnection; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Dependency.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Dependency.java new file mode 100644 index 00000000..a2c486bb --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Dependency.java @@ -0,0 +1,88 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Dependency extends Connection { + + private boolean showArrow; + private boolean showDelay; + private double angle; + + public Dependency() { + + } + + public Dependency(boolean showArrow, boolean showDelay, double angle) { + this.showArrow = showArrow; + this.showDelay = showDelay; + this.angle = angle; + } + + public Dependency(Symbol tail, Symbol head, boolean showArrow, boolean showDelay, double angle) { + super(tail, head); + this.showArrow = showArrow; + this.showDelay = showDelay; + this.angle = angle; + } + + public boolean isShowArrow() { + return showArrow; + } + + public void setShowArrow(boolean showArrow) { + this.showArrow = showArrow; + } + + public boolean isShowDelay() { + return showDelay; + } + + public void setShowDelay(boolean showDelay) { + this.showDelay = showDelay; + } + + public double getAngle() { + return angle; + } + + public void setAngle(double angle) { + this.angle = angle; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + if (getHead() == null || getTail() == null) { + System.err.println("dependency missing head or tail"); + return null; + } + + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource dependency = super.write(graph, parent, context); + graph.claimLiteral(dependency, l0.HasName, context.getNextDependency(), Bindings.STRING); + + graph.claimLiteral(getDiagramResource(), sr.Dependency_angle, angle, Bindings.DOUBLE); + + return dependency; + } + + @Override + public Resource getConnectionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).Dependency; + } + + @Override + public Resource getDiagramConnectionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).DependencyConnection; + } + + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Flow.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Flow.java new file mode 100644 index 00000000..9e3b28d5 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Flow.java @@ -0,0 +1,47 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Flow extends Connection { + + public Flow() { + + } + + public Flow(Symbol tail, Symbol head) { + super(tail, head); + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + if (getHead() == null || getTail() == null) { + System.err.println("flow missing head or tail"); + return null; + } + + Layer0 l0 = Layer0.getInstance(graph); + + Resource flow = super.write(graph, parent, context); + graph.claimLiteral(flow, l0.HasName, context.getNextFlow(), Bindings.STRING); + + return flow; + } + + @Override + public Resource getConnectionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).Flow; + } + + @Override + public Resource getDiagramConnectionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).FlowConnection; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/ModelVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/ModelVariable.java new file mode 100644 index 00000000..d5e96f00 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/ModelVariable.java @@ -0,0 +1,126 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +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; +import org.simantics.sysdyn.modelImport.model.WriteContext; +import org.simantics.sysdyn.modelImport.model.expression.Expression; +import org.simantics.sysdyn.modelImport.model.support.Range; + +public abstract class ModelVariable extends Symbol { + + private String name; + private Expression expression; + private Range range; + private String unit; + private String description; + + private Resource variable; + + public ModelVariable() { + + } + + public ModelVariable(String name, Expression expression, Range range, String unit, String description) { + this.name = name; + this.expression = expression; + this.range = range; + this.unit = unit; + this.description = description; + } + + public ModelVariable(double[] dim, String name, Expression expression, Range range, String unit, String description) { + super(dim); + this.name = name; + this.expression = expression; + this.range = range; + this.unit = unit; + this.description = description; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public Range getRange() { + return range; + } + + public void setRange(Range range) { + this.range = range; + } + + 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; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + variable = GraphUtils.create2(graph, getVariableType(graph), + l0.HasName, name, + l0.PartOf, parent); + graph.claim(variable, mr.Mapped, variable); + + // TODO: write references to enumerations here? + + if (expression != null) { + expression.write(graph, variable, context); + } + if (range != null) { + range.write(graph, variable, context); + } + 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); + } + + Resource symbol = super.write(graph, parent, context); + graph.claim(symbol, mr.ElementToComponent, variable); + + return variable; + } + + public abstract Resource getVariableType(ReadGraph graph); + + @Override + public Resource getResource() { + return variable; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Shadow.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Shadow.java new file mode 100644 index 00000000..716c2aa7 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Shadow.java @@ -0,0 +1,68 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +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; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Shadow extends Symbol { + + private ModelVariable original; + + private Resource shadow; + + public Shadow() { + + } + + public Shadow(ModelVariable original) { + this.original = original; + } + + public Shadow(double[] dim, ModelVariable original) { + super(dim); + this.original = original; + } + + public ModelVariable getOriginal() { + return original; + } + + public void setOriginal(ModelVariable original) { + this.original = original; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + shadow = GraphUtils.create2(graph, sr.Shadow, + l0.HasName, context.getNextShadow(), + l0.PartOf, parent); + + graph.claim(shadow, sr.Shadow_original, original.getResource()); + + Resource symbol = super.write(graph, parent, context); + graph.claim(symbol, mr.ElementToComponent, shadow); + + return shadow; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).ShadowSymbol; + } + + @Override + public Resource getResource() { + return shadow; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Stock.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Stock.java new file mode 100644 index 00000000..9c4b11c2 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Stock.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.expression.IntegralExpression; +import org.simantics.sysdyn.modelImport.model.support.Range; + +public class Stock extends ModelVariable { + + public Stock() { + + } + + public Stock(double[] dim, String name, IntegralExpression expression, Range range, String unit, String description) { + super(dim, name, expression, range, unit, description); + } + + @Override + public Resource getVariableType(ReadGraph graph) { + return SysdynResource.getInstance(graph).Stock; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).StockSymbol; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Symbol.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Symbol.java new file mode 100644 index 00000000..e4f23be6 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Symbol.java @@ -0,0 +1,103 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +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.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public abstract class Symbol implements IWriteableObject { + + private double x; + private double y; + private double width; + private double height; + + private Resource symbol; + + public Symbol() { + + } + + public Symbol(double[] dim) { + x = dim[0]; + y = dim[1]; + width = dim[2]; + height = dim[3]; + } + + public void setDimensions(double[] dim) { + x = dim[0]; + y = dim[1]; + width = dim[2]; + height = dim[3]; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getWidth() { + return width; + } + + public void setWidth(double width) { + this.width = width; + } + + public double getHeight() { + return height; + } + + public void setHeight(double height) { + this.height = height; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + DiagramResource dr = DiagramResource.getInstance(graph); + G2DResource g2d = G2DResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + + Resource diagram = graph.getSingleObject(parent, mr.CompositeToDiagram); + + symbol = GraphUtils.create2(graph, getSymbolType(graph), + l0.HasName, context.getNextObject(), + l0.PartOf, diagram); + + double[] transform = { 1.0, 0.0, 0.0, 1.0, x, y }; + graph.claimLiteral(symbol, dr.HasTransform, g2d.Transform, transform, Bindings.DOUBLE_ARRAY); + + OrderedSetUtils.add(graph, diagram, symbol); + + return symbol; + } + + public abstract Resource getSymbolType(ReadGraph graph); + + public Resource getDiagramResource() { + return symbol; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Valve.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Valve.java new file mode 100644 index 00000000..f9451118 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/element/Valve.java @@ -0,0 +1,88 @@ +package org.simantics.sysdyn.modelImport.model.element; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; +import org.simantics.sysdyn.modelImport.model.expression.Expression; +import org.simantics.sysdyn.modelImport.model.support.Range; + +public class Valve extends ModelVariable { + + public enum Orientation { + HORIZONTAL, VERTICAL + } + + public enum TextPosition { + INSIDE, BELOW, LEFT, ABOVE, RIGHT, UNSET + } + + private Orientation orientation; + private TextPosition position; + + public Valve() { + + } + + public Valve(Orientation orientation, TextPosition position) { + this.orientation = orientation; + this.position = position; + } + + public Valve(double[] dim, String name, Expression expression, Range range, String unit, String description, + Orientation orientation, TextPosition position) { + super(dim, name, expression, range, unit, description); + this.orientation = orientation; + this.position = position; + } + + public Orientation getOrientation() { + return orientation; + } + + public void setOrientation(Orientation orientation) { + this.orientation = orientation; + } + + public TextPosition getPosition() { + return position; + } + + public void setPosition(TextPosition position) { + this.position = position; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource location = null; + switch (position) { + case BELOW: location = sr.Bottom; break; + case LEFT: location = sr.Left; break; + case ABOVE: location = sr.Top; break; + case RIGHT: location = sr.Right; break; + case UNSET: + default: System.err.println("valve text location not set"); location = sr.Bottom; break; + } + + Resource valve = super.write(graph, parent, context); + + graph.claim(getDiagramResource(), sr.ValveSymbol_textLocation, location); + + return valve; + } + + @Override + public Resource getVariableType(ReadGraph graph) { + return SysdynResource.getInstance(graph).Valve; + } + + @Override + public Resource getSymbolType(ReadGraph graph) { + return SysdynResource.getInstance(graph).ValveSymbol; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/DelayExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/DelayExpression.java new file mode 100644 index 00000000..f740d201 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/DelayExpression.java @@ -0,0 +1,43 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class DelayExpression extends Expression { + + private String expression; + private String time; + private String initial; + private int order; + + public DelayExpression(String expression, String time, String initial, int order) { + this.expression = expression; + this.time = time; + this.initial = initial; + this.order = order; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource expr = super.write(graph, parent, context); + + graph.claimLiteral(expr, sr.DelayExpression_expression, expression, Bindings.STRING); + graph.claimLiteral(expr, sr.DelayExpression_delayTime, time, Bindings.STRING); + graph.claimLiteral(expr, sr.DelayExpression_initialValue, initial, Bindings.STRING); + graph.claimLiteral(expr, sr.DelayExpression_order, order, Bindings.INTEGER); + + return expr; + } + + @Override + public Resource getExpressionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).DelayExpression; + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/EnumerationExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/EnumerationExpression.java new file mode 100644 index 00000000..00d99797 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/EnumerationExpression.java @@ -0,0 +1,94 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +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.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; +import org.simantics.sysdyn.modelImport.model.support.Enumeration; + +public class EnumerationExpression extends Expression { + + private List enumerations; + private List subExpressions; + + public EnumerationExpression(List enumerations) { + this.enumerations = enumerations; + this.subExpressions = new ArrayList(); + } + + public void addExpression(Expression expression, String...indices) { +// for (int i = 0; i < indices.length; i++) { +// if (!enumerations.get(i).getValues().contains(indices)) { +// System.err.println("tried adding an enumeration expression with incorrect indices"); +// return; +// } +// } + subExpressions.add(new EnumerationSubExpression(expression, indices)); + } + + public List getExpressions() { + return subExpressions; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + for (EnumerationSubExpression subexpr : subExpressions) { + StringBuilder range = new StringBuilder(); + range.append('['); + for (int i = 0; i < subexpr.indices.length; i++) { + if (i > 0) + range.append(','); + range.append(subexpr.indices[i]); + } + range.append(']'); + + Resource res = subexpr.expression.write(graph, parent, context); + + graph.claimLiteral(res, sr.Expression_arrayRange, range.toString(), Bindings.STRING); + } + + ArrayList indexlist = new ArrayList(); + for (Enumeration enumeration : enumerations) { + indexlist.add(enumeration.getResource()); + } + + // write array index list + graph.claim(parent, sr.Variable_arrayIndexesList, ListUtils.create(graph, indexlist)); + + // set active expression? + + return getResource(); + } + + private class EnumerationSubExpression { + + Expression expression; + String[] indices; + + public EnumerationSubExpression(Expression expression, String...indices) { + this.expression = expression; + this.indices = indices; + } + } + + @Override + public Resource getExpressionType(ReadGraph graph) { + return subExpressions.get(0).expression.getExpressionType(graph); + } + + @Override + public Resource getResource() { + return subExpressions.get(0).expression.getResource(); + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/Expression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/Expression.java new file mode 100644 index 00000000..84eac663 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/Expression.java @@ -0,0 +1,47 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import java.util.Arrays; + +import org.simantics.db.ReadGraph; +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.sysdyn.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public abstract class Expression implements IWriteableObject { + + private Resource expr; + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + expr = GraphUtils.create2(graph, getExpressionType(graph), + l0.PartOf, parent); + + // insert the expression into the expression list of the variable + // (necessary because of enumeration expressions) + Resource list = graph.getPossibleObject(parent, sr.Variable_expressionList); + if (list != null) { + ListUtils.insertBack(graph, list, Arrays.asList(expr)); + } + else { + graph.claim(parent, sr.Variable_expressionList, ListUtils.create(graph, Arrays.asList(expr))); + } + + return expr; + } + + public abstract Resource getExpressionType(ReadGraph graph); + + @Override + public Resource getResource() { + return expr; + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/IntegralExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/IntegralExpression.java new file mode 100644 index 00000000..bc75c359 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/IntegralExpression.java @@ -0,0 +1,38 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class IntegralExpression extends Expression { + + private String integral; + private String initial; + + public IntegralExpression(String integral, String initial) { + this.integral = integral; + this.initial = initial; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource expr = super.write(graph, parent, context); + + graph.claimLiteral(expr, sr.StockExpression_integralEquation, integral, Bindings.STRING); + graph.claimLiteral(expr, sr.StockExpression_initialEquation, initial, Bindings.STRING); + graph.claim(expr, sr.StockExpression_useCustomIntegral, expr); + + return expr; + } + + @Override + public Resource getExpressionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).StockExpression; + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/LookupExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/LookupExpression.java new file mode 100644 index 00000000..8f68915d --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/LookupExpression.java @@ -0,0 +1,61 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class LookupExpression extends Expression { + + private String expression; + private double xMin; + private double yMin; + private double xMax; + private double yMax; + private double[] points; + + public LookupExpression(String expression, double xMin, double yMin, double xMax, double yMax, double[] points) { + this.expression = expression; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.points = points; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + StringBuilder lookup = new StringBuilder(); + lookup.append('{'); + for (int i = 0; i < points.length / 2; i++) { + if (i > 0) { + lookup.append(','); + } + lookup.append('{').append(points[2*i]).append(',').append(points[2*i+1]).append('}'); + } + lookup.append('}'); + + Resource expr = super.write(graph, parent, context); + + // TODO: fix this + graph.claimLiteral(expr, sr.WithLookupExpression_expression, expression, Bindings.STRING); + graph.claimLiteral(expr, sr.WithLookupExpression_lookup, lookup.toString(), Bindings.STRING); + graph.claimLiteral(expr, sr.WithLookupExpression_minX, xMin, Bindings.DOUBLE); + graph.claimLiteral(expr, sr.WithLookupExpression_minY, yMin, Bindings.DOUBLE); + graph.claimLiteral(expr, sr.WithLookupExpression_maxX, xMax, Bindings.DOUBLE); + graph.claimLiteral(expr, sr.WithLookupExpression_maxY, yMax, Bindings.DOUBLE); + + return expr; + } + + @Override + public Resource getExpressionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).WithLookupExpression; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/NormalExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/NormalExpression.java new file mode 100644 index 00000000..a940a643 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/expression/NormalExpression.java @@ -0,0 +1,34 @@ +package org.simantics.sysdyn.modelImport.model.expression; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class NormalExpression extends Expression { + + private String expression; + + public NormalExpression(String expression) { + this.expression = expression; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource expr = super.write(graph, parent, context); + + graph.claimLiteral(expr, sr.Expression_equation, expression, Bindings.STRING); + + return expr; + } + + @Override + public Resource getExpressionType(ReadGraph graph) { + return SysdynResource.getInstance(graph).NormalExpression; + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Enumeration.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Enumeration.java new file mode 100644 index 00000000..5ea53010 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Enumeration.java @@ -0,0 +1,64 @@ +package org.simantics.sysdyn.modelImport.model.support; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.simantics.db.Resource; +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.sysdyn.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Enumeration implements IWriteableObject { + + private String name; + private List values; + + private Resource enumeration; + + public Enumeration(String name, List values) { + this.name = name; + this.values = values; + } + + public String getName() { + return name; + } + + public List getValues() { + return values; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) + throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + enumeration = GraphUtils.create2(graph, sr.Enumeration, + l0.HasName, name, + l0.PartOf, parent); + + List indices = new ArrayList(); + for (String index : values) { + indices.add(GraphUtils.create2(graph, sr.EnumerationIndex, + l0.HasName, index)); + } + + graph.claim(enumeration, sr.Enumeration_enumerationIndexList, ListUtils.create(graph, indices)); + + return enumeration; + } + + @Override + public Resource getResource() { + return enumeration; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java new file mode 100644 index 00000000..faa5f5a6 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Function.java @@ -0,0 +1,67 @@ +package org.simantics.sysdyn.modelImport.model.support; + +import java.util.List; + +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.sysdyn.SysdynResource; +import org.simantics.sysdyn.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Function implements IWriteableObject { + + private String name; + private String body; + private String description; + + private Resource function; + + public Function(String name, String body) { + this(name, body, null); + } + + public Function(String name, String body, String description) { + this.name = name; + this.body = body; + this.description = description; + } + + public String getName() { + return name; + } + + public String getBody() { + return body; + } + + @Override + public Resource write(WriteGraph graph, Resource parent, WriteContext context) + throws DatabaseException { + System.err.println("write function"); + + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + function = GraphUtils.create2(graph, sr.SysdynModelicaFunction, + l0.HasName, name, + l0.PartOf, parent); + + graph.claimLiteral(function, sr.SysdynModelicaFunction_modelicaFunctionCode, body, Bindings.STRING); + + if (description != null) { + graph.claimLiteral(function, l0.HasDescription, body, Bindings.STRING); + } + + return function; + } + + @Override + public Resource getResource() { + return function; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Range.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Range.java new file mode 100644 index 00000000..e28c6b68 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelImport/model/support/Range.java @@ -0,0 +1,45 @@ +package org.simantics.sysdyn.modelImport.model.support; + +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.modelImport.model.IWriteableObject; +import org.simantics.sysdyn.modelImport.model.WriteContext; + +public class Range implements IWriteableObject { + + private Double start; + private Double end; + private Double step; + + private Resource resource; + + public Range(Double start, Double end, Double step) { + this.start = start; + this.end = end; + this.step = step; + } + + public Double getStart() { + return start; + } + + public Double getEnd() { + return end; + } + + public Double getStep() { + return step; + } + + @Override + public Resource write(WriteGraph graph, Resource variable, WriteContext context) throws DatabaseException { + return null; + } + + @Override + public Resource getResource() { + return resource; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java index fc9415c7..1b191676 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java @@ -31,6 +31,8 @@ import org.simantics.sysdyn.representation.ModuleType; import org.simantics.sysdyn.representation.Sheet; import org.simantics.sysdyn.representation.Stock; import org.simantics.sysdyn.representation.Variable; +import org.simantics.sysdyn.representation.expressions.DelayExpression; +import org.simantics.sysdyn.representation.expressions.IExpression; /** * ModelicaWriter writes Sysdyn model representations (objmap) into Modelica code. @@ -41,387 +43,462 @@ import org.simantics.sysdyn.representation.Variable; */ public class ModelicaWriter { - /** - * Write a collection of configurations into a single Modelica code - * @param isGame - * - * @param Configurations Configurations, one main configuration and possible modules - * @return Complete Modelica code of a model - */ - public static String write(Collection _configurations, boolean isGame, String omVersion) { - - ArrayList configurations = new ArrayList(_configurations); - Collections.sort(configurations, new Comparator() { - - boolean uses(Configuration o1, Configuration o2) { - ModuleType type = o2.getModuleType(); - if(type == null) return false; - for(IElement e : o1.getElements()) { - if(e instanceof Module) { - Module m = (Module)e; - if(m.getType().equals(type)) { - return true; - } - } - } - return false; - } - + /** + * Write a collection of configurations into a single Modelica code + * @param isGame + * + * @param Configurations Configurations, one main configuration and possible modules + * @return Complete Modelica code of a model + */ + public static String write(Collection _configurations, boolean isGame, String omVersion) { + + ArrayList configurations = new ArrayList(_configurations); + Collections.sort(configurations, new Comparator() { + + boolean uses(Configuration o1, Configuration o2) { + ModuleType type = o2.getModuleType(); + if(type == null) return false; + for(IElement e : o1.getElements()) { + if(e instanceof Module) { + Module m = (Module)e; + if(m.getType().equals(type)) { + return true; + } + } + } + return false; + } + @Override public int compare(Configuration o1, Configuration o2) { - if(uses(o1, o2)) return 1; - else if(uses(o2, o1)) return -1; - else return 0; + if(uses(o1, o2)) return 1; + else if(uses(o2, o1)) return -1; + else return 0; } - + }); - - Configuration modelConf = null; - for(Configuration conf : configurations) { - if(conf.getModel() != null) { - modelConf = conf; - } - } - StringBuilder b = new StringBuilder(); - - int spreadsheetlocation = b.length(); - - String modelName = modelConf.getLabel().replace(" ", ""); - b.append("model " + modelName + "\n"); - - // Super class for enumerations - b.append("partial class Enumeration_class\n"); - b.append(" parameter Integer size;\n"); - b.append(" parameter Integer elements[:];\n"); - b.append("end Enumeration_class;\n\n"); - - - HashSet sheetNames = new HashSet(); - for(Sheet sheet : getSpreadSheets(configurations)) - sheetNames.add(sheet.getModelicaName()); - - // Write all module configurations to the declarations part (first) - for(Configuration conf : configurations) { - conf.setIsGameConfiguration(isGame); - if(!conf.equals(modelConf)) - writeConfiguration(conf, sheetNames, b); - } - - // Write model configuration last, so that equations-part does not contain module definitions - modelConf.setIsGameConfiguration(isGame); - writeConfiguration(modelConf, sheetNames, b); - - b.append("end " + modelName + ";\n\n"); - - // Insert spreadsheets - if(omVersion != null && omVersion.startsWith("1.9")) { - b.insert(spreadsheetlocation, getGlobalSpreadSheets(configurations)); - } else { - b.append(getGlobalSpreadSheets(configurations)); - } - - - return b.toString(); - } - - /** - * Get all spreadsheets that are found in the model - * @param configurations - * @return - */ - private static List getSpreadSheets(Collection configurations) { - for(Configuration conf : configurations) { - if(conf.getModel() != null) { - for(IElement e : conf.getElements()) { - if(e instanceof Book) { - return ((Book)e).getSheets(); - } - } - } - } - return Collections.emptyList(); - } - - /** - * - */ - private static String getGlobalSpreadSheets(Collection configurations) { - StringBuilder sheets = new StringBuilder(); - for(Configuration conf : configurations) { - if(conf.getModel() != null) { - for(IElement e : conf.getElements()) { - if(e instanceof Book) { - return ((Book)e).getBook(); - } - } - } - } - - return sheets.toString(); - } - - /** - * Write a single configuration to a given string builder - * - * @param configuration Model or module configuration - * @param b String builder - */ - private static void writeConfiguration(Configuration configuration, HashSet sheetNames, StringBuilder b) { - boolean defTime = true; - String app; - - // Lists for storing different configuration elements - ArrayList variables = new ArrayList(); - ArrayList inputs = new ArrayList(); - ArrayList modules = new ArrayList(); - ArrayList stocks = new ArrayList(); - ArrayList enumerations = new ArrayList(); - ArrayList inputDependencies = new ArrayList(); - ArrayList outputDependencies = new ArrayList(); - HashMap> moduleInputs = new HashMap>(); - - // Initialize lists - for(IElement element : configuration.getElements()) { - if(element instanceof IndependentVariable) { - // Normal variable - variables.add((IndependentVariable)element); - if(element instanceof Stock) - // Stock - stocks.add((Stock)element); - } else if (element instanceof Module) { - // Module - Module m = (Module)element; - modules.add(m); - moduleInputs.put(m.getName(), new ArrayList()); - for(IElement e : m.getType().getConfiguration().getElements()) - // Inputs inside the module - if(e instanceof Input && !((Input)e).isHeadOfDependency()) { - moduleInputs.get(m.getName()).add((Input)e); - } - } else if (element instanceof Input) { - // Input variables - inputs.add((Input)element); - } else if (element instanceof Enumeration) { - // Enumerations - enumerations.add((Enumeration)element); - } else if (element instanceof Dependency) { - Dependency dependency = (Dependency)element; - if(dependency.getHead() instanceof Module) { - // References given to child modules - outputDependencies.add(dependency); - } else if(dependency.getTail() instanceof Module){ - // References from child modules - inputDependencies.add(dependency); - } - } - } - - // Setup input references. (Input, String reference to another variable) - HashMap inputReferences = new HashMap(); - setupInputReferences(inputReferences, inputDependencies); - - - // If the configuration is model configuration, use model name. Otherwise, use configuration name. - ModuleType mt = configuration.getModuleType(); - - // className == null, if this is a model configuration. model configuration start and end are written in ModelicaWriter.write - String className = mt != null ? (mt.getName().replace(" ", "")) : null; - - if(className != null) - b.append("\nclass ").append(className); - - // Add spreadsheets to all modules and model. Model is "inner" and modules "outer" - String globalStatus = mt != null ? "outer" : "inner"; - for(String sheetName : sheetNames) - b.append("\n " + globalStatus + " " + sheetName + "_class" + " "+ sheetName + ";"); - - b.append("\n"); - - - if(!enumerations.isEmpty()) { - b.append("// Enumeration definitions\n"); - for(Enumeration e : enumerations) { - b.append(e.getDeclaration()); - } - } - - b.append("// Variable definitions\n"); - for(IndependentVariable variable : variables) { - app = variable.getDeclaration(); - if (app != null) b.append(app); - } - - if(defTime) { - // Time variable for FMU (game) simulations - if(configuration.isGameConfiguration()) { - if(configuration.getModel() != null) - // Parameter for model root. Values changed in FMU simulator - b.append(" parameter Real time = 0;\n"); - else - // Continuous variable for module instances - b.append(" Real time;\n"); - - } - } - - if(!modules.isEmpty()) { - b.append("// Module definitions\n"); - for(Module m : modules) { - b.append(m.getDeclaration()); - } - } - - - // Input definitions - inputDefinitions(b, configuration, inputs, inputReferences); - - boolean initialEquations = false; - for(Stock stock : stocks) { - app = stock.getInitialEquation(); - if (app != null) { - if(initialEquations == false) { - initialEquations = true; - b.append("// Initial Equations\n"); - b.append("initial equation\n"); - } - b.append(app); - } - } - - boolean equation = false; - b.append("// Equations\n"); - for(IndependentVariable variable : variables) { - app = variable.getEquation(); - if (app != null) { - if(!equation) { - b.append("equation\n"); - equation = true; - } - - b.append(app); - } - } - - // If "equation" has not been added but there are still equations to be defined, add "equation" - if(!equation && (!inputReferences.isEmpty() || !outputDependencies.isEmpty() || - !moduleInputs.isEmpty() || !modules.isEmpty())) - b.append("equation\n"); - - // Continous input references - continuousInputReferences(b, inputReferences); - - b.append("// Outputs\n"); - for(Dependency dependency : outputDependencies) { - Variable variable = (Variable)dependency.getTail(); - Module module = (Module)dependency.getHead(); - Input reference = (Input)dependency.refersTo(); - if(reference != null && reference.getName() != null && (reference.getVariability() == null || reference.getVariability().isEmpty())) { - b.append(" " + module.getName() + "." + reference.getModelicaName() + " = " + variable.getModelicaName() + ";\n"); - moduleInputs.get(module.getName()).remove(reference); - } - } - - b.append("// Default values for inputs in modules\n"); - for(String moduleLabel : moduleInputs.keySet()) { - for(Input input : moduleInputs.get(moduleLabel)) { - if(input.getVariability() == null || input.getVariability().isEmpty()) - b.append(" " + moduleLabel + "." + input.getModelicaName() + " = " + input.getDefaultInputValue(moduleLabel) + ";\n"); - } - } - - if(defTime) { - if(configuration.isGameConfiguration() && !modules.isEmpty()) { - b.append("// Time values for module\n"); - for(Module m : modules) { - b.append(" " + m.getName() + ".time = time;\n"); - } - } - } - - if(className != null) - b.append("end ").append(className).append(";\n\n"); - - } - + + Configuration modelConf = null; + for(Configuration conf : configurations) { + if(conf.getModel() != null) { + modelConf = conf; + } + } + StringBuilder b = new StringBuilder(); + + int spreadsheetlocation = b.length(); + + String modelName = modelConf.getLabel().replace(" ", ""); + b.append("model " + modelName + "\n"); + + // Super class for enumerations + b.append("partial class Enumeration_class\n"); + b.append(" parameter Integer size;\n"); + b.append(" parameter Integer elements[:];\n"); + b.append("end Enumeration_class;\n\n"); + + // find out which delays are used in the model and create the + // necessary classes + HashSet delays = new HashSet(); + for (Configuration configuration : configurations) { + for (IElement element : configuration.getElements()) { + if (element instanceof IndependentVariable) { + for (IExpression expression : ((IndependentVariable)element).getExpressions()) { + if (expression instanceof DelayExpression) { + delays.add(((DelayExpression)expression).getOrder()); + } + } + } + } + } + + for (Integer i : delays) { + b.append(getDelayClass(i)); + b.append("\n"); + } + + HashSet sheetNames = new HashSet(); + for(Sheet sheet : getSpreadSheets(configurations)) + sheetNames.add(sheet.getModelicaName()); + + // Write all module configurations to the declarations part (first) + for(Configuration conf : configurations) { + conf.setIsGameConfiguration(isGame); + if(!conf.equals(modelConf)) + writeConfiguration(conf, sheetNames, b); + } + + // Write model configuration last, so that equations-part does not contain module definitions + modelConf.setIsGameConfiguration(isGame); + writeConfiguration(modelConf, sheetNames, b); + + b.append("end " + modelName + ";\n\n"); + + // Insert spreadsheets + if(omVersion != null && omVersion.startsWith("1.9")) { + b.insert(spreadsheetlocation, getGlobalSpreadSheets(configurations)); + } else { + b.append(getGlobalSpreadSheets(configurations)); + } + + return b.toString(); + } + + /** + * Get all spreadsheets that are found in the model + * @param configurations + * @return + */ + private static List getSpreadSheets(Collection configurations) { + for(Configuration conf : configurations) { + if(conf.getModel() != null) { + for(IElement e : conf.getElements()) { + if(e instanceof Book) { + return ((Book)e).getSheets(); + } + } + } + } + return Collections.emptyList(); + } + + /** + * + */ + private static String getGlobalSpreadSheets(Collection configurations) { + StringBuilder sheets = new StringBuilder(); + for(Configuration conf : configurations) { + if(conf.getModel() != null) { + for(IElement e : conf.getElements()) { + if(e instanceof Book) { + return ((Book)e).getBook(); + } + } + } + } + + return sheets.toString(); + } + /** - * Define continuous input references - * @param b String builder - * @param inputReferences Input references - */ - private static void continuousInputReferences(StringBuilder b, HashMap inputReferences) { - b.append("// Inputs\n"); - for(Input i : inputReferences.keySet()) { - if(i.getVariability() == null || i.getVariability().isEmpty()) { - // Define only continuous variables here - b.append(" " + i.getModelicaName() + " = " + inputReferences.get(i)); - } - } - } - - /** - * Setup input references for all inputs that are defined in child modules - * - * @param inputReferences Map containing the references - * @param inputDependencies List of input dependencies - */ - private static void setupInputReferences(HashMap inputReferences, ArrayList inputDependencies) { - for(Dependency dependency : inputDependencies) { - Input input = (Input)dependency.getHead(); - Module module = (Module)dependency.getTail(); - Variable reference = (Variable)dependency.refersTo(); - String expression; - // If reference exists, use reference name. Otherwise, use default value. - if(reference != null && reference.getName() != null) - expression = module.getName() + "." + reference.getModelicaName() + ";\n"; - - else - expression = input.getDefaultInputValue() + ";\n"; - - inputReferences.put(input, expression); - } - } - - /** - * Build input definitions - * - * @param b String builder - * @param configuration Module configuration - * @param inputs All inputs of this module - * @param inputReferences - */ - private static void inputDefinitions(StringBuilder b, Configuration configuration, ArrayList inputs, HashMap inputReferences) { - if(inputs.isEmpty()) - return; - - b.append("// Input definitions\n"); - for(Input i : inputs) { - if(i.getVariability() != null && !i.getVariability().isEmpty()) { - // Input is NOT continuous - if(inputReferences.containsKey(i)) { - // Input is defined in a child module - String declaration = i.getDeclaration(); - declaration = declaration.substring(0, declaration.length() - 2); // remove ";\n" from the end - b.append(declaration + " = " + inputReferences.get(i)); - } else { - // Input is not defined in a child module, use default value - b.append(i.getDeclarationWithValue()); - } - } else if(configuration.getModel() != null && !i.isHeadOfDependency()) { - /* - * Input is in the top of the hierarchy, - * and it does not get value from anywhere else. - * => Declare it wit its default value - */ - b.append(i.getDeclarationWithValue()); - } else { - // Continuous => Parent module takes care of declaring a value for the input - b.append(i.getDeclaration()); - } - } - } - - public String escape(String name) { - return name.replace(' ', '_'); - } + * Write a single configuration to a given string builder + * + * @param configuration Model or module configuration + * @param b String builder + */ + private static void writeConfiguration(Configuration configuration, HashSet sheetNames, StringBuilder b) { + boolean defTime = true; + String app; + + // Lists for storing different configuration elements + ArrayList variables = new ArrayList(); + ArrayList inputs = new ArrayList(); + ArrayList modules = new ArrayList(); + ArrayList stocks = new ArrayList(); + ArrayList enumerations = new ArrayList(); + ArrayList inputDependencies = new ArrayList(); + ArrayList outputDependencies = new ArrayList(); + HashMap> moduleInputs = new HashMap>(); + + // Initialize lists + for(IElement element : configuration.getElements()) { + if(element instanceof IndependentVariable) { + // Normal variable + variables.add((IndependentVariable)element); + if(element instanceof Stock) + // Stock + stocks.add((Stock)element); + } else if (element instanceof Module) { + // Module + Module m = (Module)element; + modules.add(m); + moduleInputs.put(m.getName(), new ArrayList()); + for(IElement e : m.getType().getConfiguration().getElements()) + // Inputs inside the module + if(e instanceof Input && !((Input)e).isHeadOfDependency()) { + moduleInputs.get(m.getName()).add((Input)e); + } + } else if (element instanceof Input) { + // Input variables + inputs.add((Input)element); + } else if (element instanceof Enumeration) { + // Enumerations + enumerations.add((Enumeration)element); + } else if (element instanceof Dependency) { + Dependency dependency = (Dependency)element; + if(dependency.getHead() instanceof Module) { + // References given to child modules + outputDependencies.add(dependency); + } else if(dependency.getTail() instanceof Module){ + // References from child modules + inputDependencies.add(dependency); + } + } + } + + // Setup input references. (Input, String reference to another variable) + HashMap inputReferences = new HashMap(); + setupInputReferences(inputReferences, inputDependencies); + + + // If the configuration is model configuration, use model name. Otherwise, use configuration name. + ModuleType mt = configuration.getModuleType(); + + // className == null, if this is a model configuration. model configuration start and end are written in ModelicaWriter.write + String className = mt != null ? (mt.getName().replace(" ", "")) : null; + + if(className != null) + b.append("class "+className+"\n").append(className); + + // Add spreadsheets to all modules and model. Model is "inner" and modules "outer" + String globalStatus = mt != null ? "outer" : "inner"; + for(String sheetName : sheetNames) + b.append(" " + globalStatus + " " + sheetName + "_class" + " "+ sheetName + ";\n"); + + if(!enumerations.isEmpty()) { + b.append("// Enumeration definitions\n"); + for(Enumeration e : enumerations) { + b.append(e.getDeclaration()); + } + } + + b.append("// Variable definitions\n"); + for(IndependentVariable variable : variables) { + app = variable.getDeclaration(); + if (app != null) b.append(app); + } + + if(defTime) { + // Time variable for FMU (game) simulations + if(configuration.isGameConfiguration()) { + if(configuration.getModel() != null) + // Parameter for model root. Values changed in FMU simulator + b.append(" parameter Real time = 0;\n"); + else + // Continuous variable for module instances + b.append(" Real time;\n"); + + } + } + + if(!modules.isEmpty()) { + b.append("// Module definitions\n"); + for(Module m : modules) { + b.append(m.getDeclaration()); + } + } + + + // Input definitions + inputDefinitions(b, configuration, inputs, inputReferences); + + boolean initialEquations = false; + for(Stock stock : stocks) { + app = stock.getInitialEquation(); + if (app != null) { + if(initialEquations == false) { + initialEquations = true; + b.append("// Initial Equations\n"); + b.append("initial equation\n"); + } + b.append(app); + } + } + + boolean equation = false; + b.append("// Equations\n"); + for(IndependentVariable variable : variables) { + app = variable.getEquation(); + if (app != null) { + if(!equation) { + b.append("equation\n"); + equation = true; + } + + b.append(app); + } + } + + // If "equation" has not been added but there are still equations to be defined, add "equation" + if(!equation && (!inputReferences.isEmpty() || !outputDependencies.isEmpty() || + !moduleInputs.isEmpty() || !modules.isEmpty())) + b.append("equation\n"); + + // Continuous input references + continuousInputReferences(b, inputReferences); + + b.append("// Outputs\n"); + for(Dependency dependency : outputDependencies) { + Variable variable = (Variable)dependency.getTail(); + Module module = (Module)dependency.getHead(); + Input reference = (Input)dependency.refersTo(); + if(reference != null && reference.getName() != null && (reference.getVariability() == null || reference.getVariability().isEmpty())) { + b.append(" " + module.getName() + "." + reference.getModelicaName() + " = " + variable.getModelicaName() + ";\n"); + moduleInputs.get(module.getName()).remove(reference); + } + } + + b.append("// Default values for inputs in modules\n"); + for(String moduleLabel : moduleInputs.keySet()) { + for(Input input : moduleInputs.get(moduleLabel)) { + if(input.getVariability() == null || input.getVariability().isEmpty()) + b.append(" " + moduleLabel + "." + input.getModelicaName() + " = " + input.getDefaultInputValue(moduleLabel) + ";\n"); + } + } + + if(defTime) { + if(configuration.isGameConfiguration() && !modules.isEmpty()) { + b.append("// Time values for module\n"); + for(Module m : modules) { + b.append(" " + m.getName() + ".time = time;\n"); + } + } + } + + if(className != null) + b.append("end ").append(className).append(";\n\n"); + + } + + /** + * Define continuous input references + * @param b String builder + * @param inputReferences Input references + */ + private static void continuousInputReferences(StringBuilder b, HashMap inputReferences) { + b.append("// Inputs\n"); + for(Input i : inputReferences.keySet()) { + if(i.getVariability() == null || i.getVariability().isEmpty()) { + // Define only continuous variables here + b.append(" " + i.getModelicaName() + " = " + inputReferences.get(i)); + } + } + } + + /** + * Setup input references for all inputs that are defined in child modules + * + * @param inputReferences Map containing the references + * @param inputDependencies List of input dependencies + */ + private static void setupInputReferences(HashMap inputReferences, ArrayList inputDependencies) { + for(Dependency dependency : inputDependencies) { + Input input = (Input)dependency.getHead(); + Module module = (Module)dependency.getTail(); + Variable reference = (Variable)dependency.refersTo(); + String expression; + // If reference exists, use reference name. Otherwise, use default value. + if(reference != null && reference.getName() != null) + expression = module.getName() + "." + reference.getModelicaName() + ";\n"; + + else + expression = input.getDefaultInputValue() + ";\n"; + + inputReferences.put(input, expression); + } + } + + /** + * Build input definitions + * + * @param b String builder + * @param configuration Module configuration + * @param inputs All inputs of this module + * @param inputReferences + */ + private static void inputDefinitions(StringBuilder b, Configuration configuration, ArrayList inputs, HashMap inputReferences) { + if(inputs.isEmpty()) + return; + + b.append("// Input definitions\n"); + for(Input i : inputs) { + if(i.getVariability() != null && !i.getVariability().isEmpty()) { + // Input is NOT continuous + if(inputReferences.containsKey(i)) { + // Input is defined in a child module + String declaration = i.getDeclaration(); + declaration = declaration.substring(0, declaration.length() - 2); // remove ";\n" from the end + b.append(declaration + " = " + inputReferences.get(i)); + } else { + // Input is not defined in a child module, use default value + b.append(i.getDeclarationWithValue()); + } + } else if(configuration.getModel() != null && !i.isHeadOfDependency()) { + /* + * Input is in the top of the hierarchy, + * and it does not get value from anywhere else. + * => Declare it wit its default value + */ + b.append(i.getDeclarationWithValue()); + } else { + // Continuous => Parent module takes care of declaring a value for the input + b.append(i.getDeclaration()); + } + } + } + + public String escape(String name) { + return name.replace(' ', '_'); + } + + public static final String DELAY_TIME = "delayTime"; + public static final String DELAY_INITIAL = "initialValue"; + + private static String getDelayClass(int order) { + StringBuilder buffer = new StringBuilder(); + + buffer.append("class " + getDelayName(order) + "\n"); + + // variable block + + // (possibly) continuous auxiliary variable + buffer.append("\tReal DL;\n"); + // (possibly) continuous delay time + buffer.append("\tReal " + DELAY_TIME + ";\n"); + // (possibly) continuous initial value + buffer.append("\tReal " + DELAY_INITIAL + ";\n"); + + // first valve + buffer.append("\tReal " + getDelayValve(0) + ";\n"); + + // stocks and valves, valves are delayed values of the variable + for (int i = 1; i <= order; i++) { + buffer.append("\tReal LV"+i + "(fixed=false);\n"); + buffer.append("\tReal "+ getDelayValve(i) + ";\n"); + } + + // initial equation block + buffer.append("initial equation\n"); + + // Each stock gets the same initial value + for (int i = 1; i <= order; i++) { + buffer.append("\tLV"+i + " = DL * " + DELAY_INITIAL + ";\n"); + } + + // equation block + buffer.append("equation\n"); + + buffer.append("\tDL = " + DELAY_TIME + " / "+order+";\n"); + + // valves and stocks + for (int i = 1; i <= order; i++) { + buffer.append("\tder(LV"+i + ") = - " + getDelayValve(i) + " + " + getDelayValve(i-1) + ";\n"); + buffer.append("\t"+ getDelayValve(i) + " = LV"+i + " / DL;\n"); + } + + buffer.append("end "); + buffer.append(getDelayName(order)); + buffer.append(";\n"); + + return buffer.toString(); + } + + public static String getDelayName(int order) { + return "order_"+order+"_delay"; + } + + public static String getDelayValve(int order) { + return "delay"+order; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java index d61abcf0..3c0decd6 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java @@ -63,12 +63,11 @@ public abstract class IndependentVariable extends Variable { // ;\n sb.append(";\n"); - + // Possible additions to expressions. e.g. helper classes and variables if(getExpressions() != null) { - String addition; for(IExpression e : getExpressions()) { - addition = e.getDeclarationAddition(); + String addition = e.getDeclarationAddition(); if(addition != null) sb.append(addition); } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java index efa2f2db..54c1d29d 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java @@ -62,8 +62,8 @@ public class Stock extends IndependentVariable { if (Variability.getVariability(this) == Variability.CONTINUOUS) { // start parameter is not used, everything needs to be fixed=false if(getArrayIndexes() != null && !getArrayIndexes().isEmpty()) - each = "each"; - return " " + getType() + " " + getModelicaName() + getRange() + "(" + each + " fixed=false);\n"; + each = "each "; + return " " + getType() + " " + getModelicaName() + getRange() + "(" + each + "fixed=false);\n"; } else { // Start parameter is used. Parameter guarantees that there is only one expression. StockExpression e = (StockExpression)getExpressions().get(0); @@ -71,9 +71,9 @@ public class Stock extends IndependentVariable { initialEquation = SheetFormatUtils.reformatSheetReferences(this, initialEquation); if(getArrayIndexes() != null && !getArrayIndexes().isEmpty()) - each = "each"; - + each = "each "; + // TODO: there is probably a bug with startvalue here return " " + getType() + " " + @@ -81,11 +81,11 @@ public class Stock extends IndependentVariable { getRange() + "(" + (e.getStartValue() != null ? each : "") + - " start=" + + "start=" + initialEquation + ", " + each + - " fixed=true);\n"; + "fixed=true);\n"; } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java index 6409704b..4edf3089 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java @@ -16,8 +16,7 @@ import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.manager.SysdynModel; -import org.simantics.sysdyn.representation.IndependentVariable; -import org.simantics.sysdyn.representation.Variability; +import org.simantics.sysdyn.modelica.ModelicaWriter; import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; import org.simantics.sysdyn.representation.utils.UnitUtils; @@ -51,234 +50,97 @@ import org.simantics.sysdyn.representation.utils.UnitUtils; @GraphType(SysdynResource.URIs.DelayExpression) public class DelayExpression extends Expression { - @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue) - private String initialValue; - - @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime) - private String delayTime; - - @RelatedValue(SysdynResource.URIs.DelayExpression_order) - private Integer order; - - @RelatedValue(SysdynResource.URIs.DelayExpression_expression) - private String equation; - - @Override - public String getDeclarationAddition() { - String delayTime = FormatUtils.replaceWhitespace(this.delayTime); - delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime); - String initialValue = FormatUtils.replaceWhitespace(this.initialValue); - initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue); - Variability delayTimeVariability = Variability.getVariability((IndependentVariable)parent, delayTime); - Variability initialVariability = Variability.CONTINUOUS; - if(initialValue != null && initialValue.length() > 0) { - /* - * By default, initial value variability is continuous. - * If initial value has been set, it can be some other. - */ - initialVariability = Variability.getVariability(parent, initialValue); - } - - - StringBuilder declaration = new StringBuilder(); - - String range = parent.getRange(); - - // Delay declaration - declaration.append(" " + parent.getModelicaName() + "_delayClass " + parent.getModelicaName() + "_delayClass_instance"); - - // Change enumeration sizes from the delay class. Supports overridden enumerations in modules. - if(range.length() > 0 || !initialVariability.equals(Variability.CONTINUOUS) || !delayTimeVariability.equals(Variability.CONTINUOUS)) { - declaration.append("("); - - boolean started = false; - if(range.length() > 0) { - started = true; - String[] ranges = range.substring(1, range.length() - 1).split(","); - for(int i = 0; i < ranges.length; i++ ) { - String r = ranges[i]; - declaration.append(r.replace(".size", "size") + " = " + r); - if(i < ranges.length - 1) { - declaration.append(", "); - } - } - } - - // If initial value is not continuous, it is set in the module declaration - if(!initialVariability.equals(Variability.CONTINUOUS)) { - if(started) - declaration.append(", "); - started = true; - declaration.append("initialValue = " + initialValue); - } - - // If delay time is not continuous, it is set in the module declaration - if(!delayTimeVariability.equals(Variability.CONTINUOUS)) { - if(started) - declaration.append(", "); - declaration.append("delayTime = " + delayTime); - } - - declaration.append(")"); - } - declaration.append(";\n"); - - // Write the delay class - declaration.append(getDelayClass(range, order)); - return declaration.toString(); - } - - /** - * Creates a class that is used to implement the delay. Class contains - * a basic delay structure with "stocks and flows". The number of - * stocks and flows is determined by the order of the delay - * - * @param variable The variable for which the delay is created - * @param range Array range - * @param n Order of the delay - * @return - */ - private String getDelayClass(String range, int n) { - StringBuilder sb = new StringBuilder(); - - sb.append("class " + parent.getModelicaName() + "_delayClass\n"); - - // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable - if(range.length() > 0) { - range = range.replaceAll(".size", "size"); - for(String r : range.substring(1, range.length() - 1).split(",")) { - sb.append("\t parameter Integer " + r + ";\n"); - } - } - - String delayTime = FormatUtils.replaceWhitespace(this.delayTime); - String dt = FormatUtils.formatExpressionForModelica(parent,delayTime); - Variability delayTimeVariability = Variability.getVariability(parent, dt); - if(!delayTimeVariability.equals(Variability.CONTINUOUS)) { - // Auxiliary variable - sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " DL = delayTime/" + n + ";\n"); - // Delay time - sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " delayTime;\n"); - } else { - // Continuous auxiliary variable - sb.append("\tReal" + range + " DL;\n"); - // Continuous delay time - sb.append("\tReal" + range + " delayTime;\n"); - } - - - // Get initial value variability - Variability initialValueVariability = Variability.CONTINUOUS; - String initEquation = FormatUtils.replaceWhitespace(this.initialValue); - initEquation = FormatUtils.formatExpressionForModelica(parent, initEquation); - if(initialValue != null && initialValue.length() > 0) { - initialValueVariability = Variability.getVariability(parent, initEquation); - } - - // Declare initial value (continuous or other) - String ivv = !initialValueVariability.equals(Variability.CONTINUOUS) ? initialValueVariability.getText() + " " : ""; - sb.append("\t" + ivv + "Real" + range + " initialValue;\n"); - - // First valve - sb.append("\tReal" + range + " delay0;\n"); - - // Stocks and valves. Valves are the delayed values of the variable - for(int i = 1; i <= n; i++) { - if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) - // Continuous initial value or delay time - sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n"); - else - // initial value and delay time are not continuous - sb.append("\tReal" + range + " LV" + i + - "(" + (range.length() > 0 ? "each " : "") + "fixed=true, start=initialValue " + (range.isEmpty() ? "*" : ".*") + " DL);\n"); - sb.append("\tReal" + range + " delay" + i + ";\n"); - } - - // If initial value or delay time are continuous, use initial equation block - if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) { - sb.append("initial equation\n"); - - // Each stock gets the same initial value - for(int i = 1; i <= n; i++) - sb.append("\tLV" + i +" = DL " + (range.isEmpty() ? "*" : ".*") + " initialValue;\n"); - } - - // Equation block - sb.append("equation\n"); - - if(delayTimeVariability.equals(Variability.CONTINUOUS)) - sb.append("\tDL = delayTime/" + n + ";\n"); - - // Valves and stocks - for(int i = 1; i <= n; i++) { - sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n"); - sb.append("\tdelay" + i + " = LV" + i + " " + (range.isEmpty() ? "/" : "./") + "DL;\n"); - } - - sb.append("end " + parent.getModelicaName() + "_delayClass;\n"); - return sb.toString(); - } - - @Override - public String getEquation() { - StringBuilder sb = new StringBuilder(); - - String equation = FormatUtils.replaceWhitespace(this.equation); - equation = FormatUtils.formatExpressionForModelica(parent, equation); - String delayTime = FormatUtils.replaceWhitespace(this.delayTime); - delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime); - String initialValue = FormatUtils.replaceWhitespace(this.initialValue); - initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue); - - // First "valve" in the delay - sb.append(" " + parent.getModelicaName() + "_delayClass_instance.delay0 = " + equation + ";\n"); - - // Delay time (if continuous) - Variability delayTimeVariability = Variability.getVariability(parent, delayTime); - if(delayTimeVariability.equals(Variability.CONTINUOUS)) { - sb.append(" " + parent.getModelicaName() + "_delayClass_instance.delayTime = " + delayTime + ";\n"); - } - - // Initial value - if(initialValue == null || initialValue.length() == 0) { - // No initial value set, use delay0 (the first "valve") - sb.append(" " + parent.getModelicaName() + "_delayClass_instance.initialValue = " + parent.getModelicaName() + "_delayClass_instance.delay0;\n"); - } else { - // Continuous initial value - Variability initialVariability = Variability.getVariability(parent, initialValue); - if(initialVariability.equals(Variability.CONTINUOUS)) { - sb.append(" " + parent.getModelicaName() + "_delayClass_instance.initialValue = " + initialValue + ";\n"); - } - } - - // The value of the actual variable - String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange()); - sb.append(" " + parent.getModelicaName() + (range.equals("[:]") ? "" : range) + " = " + parent.getModelicaName() + "_delayClass_instance.delay" + order + ";\n"); - return sb.toString(); - } - - @Override - public String getExpression() { - return "This + is + not + a + parameter + at + any + time"; - } - - @Override - public String getModelicaExpression() { - return getExpression(); - } - - @Override - public String validateUnits(ReadGraph graph, SysdynModel model) { - if(parent.getUnit() == null) - return "Unit not defined for " + parent.getName(); - - String result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), equation); - if(result == null) - result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialValue); - if(result == null) - result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), UnitUtils.getTimeUnit(graph, model), delayTime); - - return result; - } + @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue) + private String initialValue; + + @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime) + private String delayTime; + + @RelatedValue(SysdynResource.URIs.DelayExpression_order) + private Integer order; + + @RelatedValue(SysdynResource.URIs.DelayExpression_expression) + private String equation; + + @Override + public String getDeclarationAddition() { + // instantiate the correct delay class for this expression + return "\t" + ModelicaWriter.getDelayName(order) + " " + instance() + ";\n"; + } + + @Override + public String getEquation() { + StringBuilder sb = new StringBuilder(); + + String equation = FormatUtils.replaceWhitespace(this.equation); + equation = FormatUtils.formatExpressionForModelica(parent, equation); + String delayTime = FormatUtils.replaceWhitespace(this.delayTime); + delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime); + String initialValue = FormatUtils.replaceWhitespace(this.initialValue); + initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue); + + sb.append("\t" + instance() + "." + ModelicaWriter.getDelayValve(0) + " = " + equation + ";\n"); + + sb.append("\t" + instance() + "." + ModelicaWriter.DELAY_TIME + " = " + delayTime + ";\n"); + + sb.append("\t" + instance() + "." + ModelicaWriter.DELAY_INITIAL + " = "); + if (initialValue != null && !initialValue.isEmpty()) { + sb.append(initialValue); + } + else { + // if an initial value is not set, use the value of the first valve + sb.append(instance() + "." + ModelicaWriter.getDelayValve(0)); + } + sb.append(";\n"); + + // set the value of the variable + String range = IndexUtils.rangeToIndexes(parent, getArrayRange()); + // TODO: this variable name thing here (and in other expressions) is a hack and should be fixed + sb.append("\t" + parent.getModelicaName() + (range.equals("[:]") ? "" : range) + " = " + + instance() + "." + ModelicaWriter.getDelayValve(order) + ";\n"); + + return sb.toString(); + } + + @Override + public String getExpression() { + return "This + is + not + a + parameter + at + any + time"; + } + + @Override + public String getModelicaExpression() { + return getExpression(); + } + + @Override + public String validateUnits(ReadGraph graph, SysdynModel model) { + if(parent.getUnit() == null) + return "Unit not defined for " + parent.getName(); + + String result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), equation); + if(result == null) + result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialValue); + if(result == null) + result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), UnitUtils.getTimeUnit(graph, model), delayTime); + + return result; + } + + public int getOrder() { + return order; + } + + private String instance() { + // construct an identifier for this expression based on the array + // indices if necessary + String identifier; + if (getArrayRange() != null && !getArrayRange().isEmpty()) { + identifier = IndexUtils.rangeToIndexes(parent, getArrayRange()).replaceAll("[\\[\\]{},]", "_"); + } + else { + identifier = "_"; + } + return parent.getModelicaName() + identifier + "instance"; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java index 94a119ce..58de03cc 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java @@ -27,22 +27,18 @@ public interface IExpression { /** * Get any possible additions to variable declaration. - * - * @param variable Declared independent variable * @return additions or null */ String getDeclarationAddition(); /** * Initial value for this variable and expression - * @param variable IndependentVariable * @return initial value or null */ String getInitialEquation(); /** * Get the actual equation of this expression - * @param variable IndependentVariable * @return equation or null */ String getEquation(); @@ -55,8 +51,7 @@ public interface IExpression { /** * Get the plain (possibly unformatted) expression from this expression. (type variable = EXPRESSION ;\n) - * @param variable - * @return + * @return */ String getExpression(); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java index 6723be47..5385212f 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java @@ -40,11 +40,6 @@ public class ParameterExpression extends Expression { String equation = FormatUtils.replaceWhitespace(this.equation); return equation + " /* Actual value read from init file */"; } - - @Override - public String getDeclarationAddition() { - return ""; - } /** diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java index 95a3a5bd..a6efc5e2 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java @@ -71,7 +71,7 @@ public class StockExpression extends Expression { // Stock equation is always der(Stock) StringBuilder b = new StringBuilder(); b.append(" der(") - .append(modelicaEquation ? parent.getModelicaName() : parent.getName() + range) + .append(parent.getModelicaName() + (range.equals("[:]") ? "" : range)) .append(") = "); if (integralEquation != null) { @@ -193,7 +193,7 @@ public class StockExpression extends Expression { try { value = Double.parseDouble(initialEquation); } catch(NumberFormatException e1) { - + return null; } } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java index 27c09439..82acd991 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java @@ -164,14 +164,14 @@ public class WithLookupExpression extends Expression { DefaultXYDataset dataset = new DefaultXYDataset(); dataset.addSeries("lookup", new double[][] {y, x}); JFreeChart chart = ChartFactory.createXYLineChart( - "", // chart title - "", // domain axis label - "", // range axis label - dataset, // data + "", // chart title + "", // domain axis label + "", // range axis label + dataset, // data PlotOrientation.HORIZONTAL, // Orientation - false, // include legend - false, // tooltips - false // urls + false, // include legend + false, // tooltips + false // urls ); StringWriter writer = new StringWriter(); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/RepresentationUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/RepresentationUtils.java index 09a9a202..6c5e3542 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/RepresentationUtils.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/RepresentationUtils.java @@ -31,7 +31,6 @@ import org.simantics.sysdyn.representation.Variable; public class RepresentationUtils { - /** * Returns true, if there is an active experiment and the active experiment * is a game experiment @@ -60,26 +59,26 @@ public class RepresentationUtils { * @return */ public static boolean isPartOfGameExperiment(Variable variable) { - Configuration conf = variable.getParentConfiguration(); - if(conf != null) - return conf.isGameConfiguration(); - else - return false; + Configuration conf = variable.getParentConfiguration(); + if(conf != null) + return conf.isGameConfiguration(); + else + return false; } - + /** - * Find out if a module is part of a game configuration. (This means that the module is a - * part of a game experiment) - * @param variable - * @return - */ - public static boolean isPartOfGameExperiment(Module module) { - Configuration conf = module.getParentConfiguration(); - if(conf != null) - return conf.isGameConfiguration(); - else - return false; - } + * Find out if a module is part of a game configuration. (This means that the module is a + * part of a game experiment) + * @param variable + * @return + */ + public static boolean isPartOfGameExperiment(Module module) { + Configuration conf = module.getParentConfiguration(); + if(conf != null) + return conf.isGameConfiguration(); + else + return false; + } /** @@ -138,18 +137,18 @@ public class RepresentationUtils { if(v.getName().equals(variable.getName())) { return null;// Reference to self. } else { - if(Variability.PARAMETER.equals(Variability.getVariability(v, false, null))) { - return v; - } else { - return null; - } - - /* + if(Variability.PARAMETER.equals(Variability.getVariability(v, false, null))) { + return v; + } else { + return null; + } + + /* if(v.getExpressions() == null || v.getExpressions().getExpressions().size() > 1) return null; - + IExpression e = v.getExpressions().getExpressions().get(0); - + if(e instanceof ParameterExpression) return v; */ @@ -162,36 +161,36 @@ public class RepresentationUtils { public static Variable getVariable(Configuration configuration, String name) { - Configuration conf = configuration; - // This function seems to be used with both whitespaced and - // underscored versions of the variable name. - String whitespacedName = name.replace('_', ' '); - String[] components = whitespacedName.split("\\."); - - for(String component : components) { - - Configuration newConf = null; - - for(IElement element : conf.getElements()) { - if(element instanceof Variable) { - Variable variable = (Variable) element; - if(variable.getName().equals(component)) { - return variable; - } - } else if(element instanceof Module) { - Module m = (Module)element; - if(m.getName().equals(component)) { - newConf = m.getType().getConfiguration(); - } - } - } - - // If variable or configuration has not been found, return null - if(newConf == null) - return null; - } - - return null; + Configuration conf = configuration; + // This function seems to be used with both whitespaced and + // underscored versions of the variable name. + String whitespacedName = name.replace('_', ' '); + String[] components = whitespacedName.split("\\."); + + for(String component : components) { + + Configuration newConf = null; + + for(IElement element : conf.getElements()) { + if(element instanceof Variable) { + Variable variable = (Variable) element; + if(variable.getName().equals(component)) { + return variable; + } + } else if(element instanceof Module) { + Module m = (Module)element; + if(m.getName().equals(component)) { + newConf = m.getType().getConfiguration(); + } + } + } + + // If variable or configuration has not been found, return null + if(newConf == null) + return null; + } + + return null; } } 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 e9c05fd4..e3212aba 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);