From 4986e5c583b68b48b691b2a421d37da3bce50c32 Mon Sep 17 00:00:00 2001 From: lempinen Date: Mon, 8 Aug 2011 10:46:51 +0000 Subject: [PATCH] Spreadsheets to sysdyn. Syntax in equations: SheetName(CellRange) git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@21688 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../modelica/data/CSVSimulationResult.java | 13 +- org.simantics.sysdyn.ui/plugin.xml | 29 +++- .../sysdyn/ui/browser/nodes/BookNode.java | 8 - .../sysdyn/ui/editor/DiagramViewer.java | 2 + .../ui/handlers/ImportModelHandler.java | 66 +------- .../ui/handlers/NewSpreadSheetHandler.java | 34 ++++ .../sysdyn/ui/project/SysdynProject.java | 55 +------ .../sysdyn/ui/utils/ExpressionUtils.java | 55 ++++++- .../simantics/sysdyn/ui/utils/SheetUtils.java | 65 ++++++++ .../expressionParser/ExpressionParser.jj | 64 +++++--- .../simantics/sysdyn/manager/SysdynModel.java | 4 +- .../sysdyn/modelica/ModelicaWriter.java | 11 +- .../simantics/sysdyn/representation/Book.java | 4 + .../sysdyn/representation/Sheet.java | 145 +++++++++++++++--- .../expressions/NormalExpression.java | 3 +- .../expressions/StockExpression.java | 35 ++++- .../expressions/WithLookupExpression.java | 3 +- .../representation/utils/FormatUtils.java | 14 ++ .../utils/SheetFormatUtils.java | 92 +++++++++++ 19 files changed, 509 insertions(+), 193 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewSpreadSheetHandler.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/FormatUtils.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/SheetFormatUtils.java diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java b/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java index 19043005..742beeb3 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java @@ -14,12 +14,11 @@ package org.simantics.modelica.data; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; public class CSVSimulationResult extends SimulationResult { - HashMap> valueMap = new HashMap>(); + HashMap valueMap = new HashMap(); @Override public void read(InputStream stream) { @@ -36,7 +35,7 @@ public class CSVSimulationResult extends SimulationResult { // Create lists for receiving values for each variable. Names still with quotes. for(String name : names) { if(!name.isEmpty()) - valueMap.put(name, new ArrayList()); + valueMap.put(name, new DataSet(name, new ArrayList(), new ArrayList())); } // Data sets @@ -47,7 +46,7 @@ public class CSVSimulationResult extends SimulationResult { for(int i = 0; i list = errors.get(names[i]); if(list == null) { @@ -60,9 +59,9 @@ public class CSVSimulationResult extends SimulationResult { } } - // Create datasets for variables. Substring quotes from variable names. - for(String key : valueMap.keySet()) { - DataSet ds = new DataSet(key, valueMap.get("time"), valueMap.get(key)); + // Add time values for each dataset and add them to variables. + for(DataSet ds : valueMap.values()) { + ds.times = valueMap.get("time").values; variables.add(ds); } } diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index a28e6e24..32a37942 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -385,6 +385,21 @@ + + + + + + + + + + @@ -716,6 +735,10 @@ args="org.simantics.sysdyn.ui.browser.nodes.FunctionLibraryNode" property="org.simantics.sysdyn.ui.nodeClass"> + + @@ -933,6 +956,10 @@ + + @@ -1292,7 +1319,7 @@ value="plugin_customization.ini"/> + value="icons/sysdyn.png"> diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/BookNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/BookNode.java index 325d7774..02f5bc51 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/BookNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/BookNode.java @@ -8,12 +8,4 @@ public class BookNode extends AbstractNode { public BookNode(Resource data) { super(data); } - - @SuppressWarnings("rawtypes") - @Override - public Object getAdapter(Class adapter) { - if(clazz == adapter) // There is no resource for this node.. - return null; - return super.getAdapter(adapter); - } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java index 8e412512..ab093a37 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java @@ -133,6 +133,8 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr IHintContext h = ctx.getDefaultHintContext(); h.setHint(GridPainter.KEY_GRID_ENABLED, Boolean.FALSE); h.setHint(RulerPainter.KEY_RULER_ENABLED, Boolean.FALSE); + h.setHint(Hints.KEY_DISPLAY_MARGINS, Boolean.FALSE); + h.setHint(Hints.KEY_DISPLAY_PAGE, Boolean.FALSE); return ctx; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ImportModelHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ImportModelHandler.java index 0faf71bd..36870aa5 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ImportModelHandler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ImportModelHandler.java @@ -46,6 +46,7 @@ import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.Activator; import org.simantics.sysdyn.ui.utils.OldTransferableGraph1; +import org.simantics.sysdyn.ui.utils.SheetUtils; import org.simantics.ui.SimanticsUI; public class ImportModelHandler extends AbstractHandler { @@ -246,74 +247,11 @@ public class ImportModelHandler extends AbstractHandler { graph.addLiteral(book, l0.HasName, l0.NameOf, l0.String, "Book" + UUID.randomUUID().toString(), Bindings.STRING); graph.claim(conf, l0.ConsistsOf, l0.PartOf, book); - createSheet(graph, book, "Sheet1", new String[] { }, new int[] { 50 }); + SheetUtils.createSheet(graph, book, "Sheet1", new String[] { }, new int[] { 50 }); } } catch (DatabaseException e) { e.printStackTrace(); } } - /** - * Create a sheet (Copied from SysdynProject) - * - * @param graph - * @param book - * @param name - * @param colNames - * @param colWidths - * @return - * @throws DatabaseException - */ - private static Resource createSheet(WriteGraph graph, Resource book, String name, String[] colNames, int[] colWidths) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); - - Resource result = graph.newResource(); - graph.claim(result, L0.InstanceOf, null, sr.Spreadsheet); - - if(name == null) { - name = NameUtils.findFreshEscapedName(graph, "Sheet", book, sr.HasSheet); - } - graph.claimLiteral(result, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - graph.claim(book, L0.ConsistsOf, L0.PartOf, result); - - { - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.Cell); - graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Dimensions", Bindings.STRING); - graph.addLiteral(newCell, sr.FitColumns, sr.FitColumnsOf, L0.Boolean, false, Bindings.BOOLEAN); - graph.addLiteral(newCell, sr.FitRows, sr.FitRowsOf, L0.Boolean, false, Bindings.BOOLEAN); - graph.addLiteral(newCell, sr.ColumnCount, sr.ColumnCountOf, L0.Integer, 128, Bindings.INTEGER); - graph.addLiteral(newCell, sr.RowCount, sr.RowCountOf, L0.Integer, 256, Bindings.INTEGER); - graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); - } - - { - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.Cell); - graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Headers", Bindings.STRING); - graph.addLiteral(newCell, sr.ColumnLabels, sr.ColumnLabelsOf, L0.StringArray, colNames, Bindings.STRING_ARRAY); - graph.addLiteral(newCell, sr.ColumnWidths, sr.ColumnWidthsOf, L0.IntegerArray, colWidths, Bindings.INT_ARRAY); - graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); - } - - { - - double[] doubles = new double[10*2]; - for(int i=0;i<10*2;i++) doubles[i] = i; - - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.DoubleArrayCell); - graph.addLiteral(newCell, sr.DoubleArrayCell_HasWidth, sr.DoubleArrayCell_HasWidth_Inverse, L0.Integer, 10, Bindings.INTEGER); - graph.addLiteral(newCell, sr.HasLocation, sr.HasLocation_Inverse, L0.String, "B2", Bindings.STRING); - graph.addLiteral(newCell, sr.DoubleArrayCell_HasDoubleArray, sr.DoubleArrayCell_HasDoubleArray_Inverse, L0.DoubleArray, doubles, Bindings.DOUBLE_ARRAY); - graph.claim(result, L0.HasChildVariables, L0.HasChildVariables_Inverse, newCell); - - } - - return result; - - } - } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewSpreadSheetHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewSpreadSheetHandler.java new file mode 100644 index 00000000..3f467ea5 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewSpreadSheetHandler.java @@ -0,0 +1,34 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.utils.SheetUtils; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; + +public class NewSpreadSheetHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection sel = HandlerUtil.getCurrentSelection(event); + final Resource book = ResourceAdaptionUtils.toSingleResource(sel); + if(book == null) return null; + + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SheetUtils.createSheet(graph, book, null, new String[] {}, new int[] {50}); + } + }); + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java index f5720d8b..aef878b6 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java @@ -59,6 +59,7 @@ import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.Activator; import org.simantics.sysdyn.ui.editor.SysdynEditorNamingService; +import org.simantics.sysdyn.ui.utils.SheetUtils; import org.simantics.ui.SimanticsUI; import org.simantics.ui.workbench.IEditorNamingService; import org.simantics.ui.workbench.action.ChooseActionRequest; @@ -107,58 +108,6 @@ public class SysdynProject extends AbstractProjectFeature { private final WriteRunnable CREATE_MODEL = new WriteRunnable() { - Resource createSheet(WriteGraph graph, Resource book, String name, String[] colNames, int[] colWidths) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); - - Resource result = graph.newResource(); - graph.claim(result, L0.InstanceOf, null, sr.Spreadsheet); - - if(name == null) { - name = NameUtils.findFreshEscapedName(graph, "Sheet", book, sr.HasSheet); - } - graph.claimLiteral(result, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); - graph.claim(book, L0.ConsistsOf, L0.PartOf, result); - - { - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.Cell); - graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Dimensions", Bindings.STRING); - graph.addLiteral(newCell, sr.FitColumns, sr.FitColumnsOf, L0.Boolean, false, Bindings.BOOLEAN); - graph.addLiteral(newCell, sr.FitRows, sr.FitRowsOf, L0.Boolean, false, Bindings.BOOLEAN); - graph.addLiteral(newCell, sr.ColumnCount, sr.ColumnCountOf, L0.Integer, 128, Bindings.INTEGER); - graph.addLiteral(newCell, sr.RowCount, sr.RowCountOf, L0.Integer, 256, Bindings.INTEGER); - graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); - } - - { - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.Cell); - graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Headers", Bindings.STRING); - graph.addLiteral(newCell, sr.ColumnLabels, sr.ColumnLabelsOf, L0.StringArray, colNames, Bindings.STRING_ARRAY); - graph.addLiteral(newCell, sr.ColumnWidths, sr.ColumnWidthsOf, L0.IntegerArray, colWidths, Bindings.INT_ARRAY); - graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); - } - - { - - double[] doubles = new double[10*2]; - for(int i=0;i<10*2;i++) doubles[i] = i; - - Resource newCell = graph.newResource(); - graph.claim(newCell, L0.InstanceOf, null, sr.DoubleArrayCell); - graph.addLiteral(newCell, sr.DoubleArrayCell_HasWidth, sr.DoubleArrayCell_HasWidth_Inverse, L0.Integer, 10, Bindings.INTEGER); - graph.addLiteral(newCell, sr.HasLocation, sr.HasLocation_Inverse, L0.String, "B2", Bindings.STRING); - graph.addLiteral(newCell, sr.DoubleArrayCell_HasDoubleArray, sr.DoubleArrayCell_HasDoubleArray_Inverse, L0.DoubleArray, doubles, Bindings.DOUBLE_ARRAY); - graph.claim(result, L0.HasChildVariables, L0.HasChildVariables_Inverse, newCell); - - } - - return result; - - } - @Override public void run(WriteGraph g, Resource library, Callback callback, Callback errorCallback) { try { @@ -196,7 +145,7 @@ public class SysdynProject extends AbstractProjectFeature { g.addLiteral(book, l0.HasName, l0.NameOf, l0.String, "Book" + UUID.randomUUID().toString(), Bindings.STRING); g.claim(conf, l0.ConsistsOf, l0.PartOf, book); - createSheet(g, book, "Sheet1", new String[] { "ARG" }, new int[] { 50 }); + SheetUtils.createSheet(g, book, "Sheet1", new String[] { }, new int[] { 50 }); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java index c35cd3a2..bb0a96ac 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java @@ -19,6 +19,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jface.text.Position; import org.eclipse.swt.custom.StyledText; @@ -114,6 +116,7 @@ public class ExpressionUtils { final HashMap>>> ranges = new HashMap>>>(); HashMap>> forIndices = new HashMap>>(); HashMap>> enumerationReferences = new HashMap>>(); + HashMap>> functionReferences = new HashMap>>(); // Build references and variable array for(ExpressionField ef : expression.getExpressionFields()) { @@ -126,15 +129,13 @@ public class ExpressionUtils { references.put(ef, refs); variables.addAll(refs.keySet()); - HashMap>> rangs = parser.getRanges(); - ranges.put(ef, rangs); + ranges.put(ef, parser.getRanges()); - HashMap> fInds = parser.getForIndices(); - forIndices.put(ef, fInds); + forIndices.put(ef, parser.getForIndices()); + enumerationReferences.put(ef, parser.getEnumerationReferences()); - HashMap> enumRefs = parser.getEnumerationReferences(); - enumerationReferences.put(ef, enumRefs); + functionReferences.put(ef, parser.getFunctionCallReferences()); } catch (ParseException e1) { ef.setSyntaxError(e1.currentToken, "Syntax Error"); @@ -147,7 +148,7 @@ public class ExpressionUtils { final HashMap modelVariables = new HashMap(); HashSet ignoreVariables = new HashSet(); - if(!variables.isEmpty()) { + if(!variables.isEmpty() || !functionReferences.isEmpty()) { Set noSuchVariables = new HashSet(); SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); SysdynModel model = sdm.getModel(configuration); @@ -172,6 +173,46 @@ public class ExpressionUtils { if(variables.contains("time")) variables.remove("time"); + + // Examine sheets + for(ExpressionField ef : functionReferences.keySet()) { + for(String key : functionReferences.get(ef).keySet()) { + String[] parts = key.split("\\."); + Object current = conf; + for(int i = 0; i < parts.length && current != null; i++) { + current = getElement(current, parts[i]); + } + if(current != null && current instanceof Sheet) { + Sheet sheet = (Sheet) current; + String e = ef.getExpression(); + int start = 0, end = 0, call = 0; + String cellOrRange = null; + while((call = e.indexOf(key, end)) >= 0) { + start = e.indexOf("(", call) +1; + end = e.indexOf(")", start); + if(start < 0 || end < 0 || end < start) { + break; + } + Pattern p = Pattern.compile("[-\\+\\*\\/\\(\\)\\{\\}\\[\\],\\.\\t\\n\\r\\f]"); + cellOrRange = e.substring(start, end); + Matcher m = p.matcher(cellOrRange); + if (m.find() || cellOrRange.split(":").length > 2) { + ef.setSyntaxError(start, end - start, ExpressionField.SYNTAX_ERROR, "Not a valid cell or range"); + } + } + + List tokens = functionReferences.get(ef).get(key); + for(Token cell : tokens) { + List refs = references.get(ef).get(cell.image); + if(refs != null) + refs.remove(cell); + if(!sheet.getCells().containsKey(cell.image)) + ef.setSyntaxError(cell.image, "Invalid cell", cell.beginLine, cell.beginColumn, cell.endLine, cell.endColumn); + } + + } + } + } for(String v : variables) { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java new file mode 100644 index 00000000..5360fd83 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/SheetUtils.java @@ -0,0 +1,65 @@ +package org.simantics.sysdyn.ui.utils; + +import org.simantics.databoard.Bindings; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.spreadsheet.resource.SpreadsheetResource; + +public class SheetUtils { + + public static Resource createSheet(WriteGraph graph, Resource book, String name, String[] colNames, int[] colWidths) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); + + Resource result = graph.newResource(); + graph.claim(result, L0.InstanceOf, null, sr.Spreadsheet); + + if(name == null) { + name = NameUtils.findFreshEscapedName(graph, "Sheet", book, L0.ConsistsOf); + } + graph.claimLiteral(result, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING); + graph.claim(book, L0.ConsistsOf, L0.PartOf, result); + + { + Resource newCell = graph.newResource(); + graph.claim(newCell, L0.InstanceOf, null, sr.Cell); + graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Dimensions", Bindings.STRING); + graph.addLiteral(newCell, sr.FitColumns, sr.FitColumnsOf, L0.Boolean, false, Bindings.BOOLEAN); + graph.addLiteral(newCell, sr.FitRows, sr.FitRowsOf, L0.Boolean, false, Bindings.BOOLEAN); + graph.addLiteral(newCell, sr.ColumnCount, sr.ColumnCountOf, L0.Integer, 128, Bindings.INTEGER); + graph.addLiteral(newCell, sr.RowCount, sr.RowCountOf, L0.Integer, 256, Bindings.INTEGER); + graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); + } + + { + Resource newCell = graph.newResource(); + graph.claim(newCell, L0.InstanceOf, null, sr.Cell); + graph.claimLiteral(newCell, L0.HasName, L0.NameOf, L0.String, "Headers", Bindings.STRING); + graph.addLiteral(newCell, sr.ColumnLabels, sr.ColumnLabelsOf, L0.StringArray, colNames, Bindings.STRING_ARRAY); + graph.addLiteral(newCell, sr.ColumnWidths, sr.ColumnWidthsOf, L0.IntegerArray, colWidths, Bindings.INT_ARRAY); + graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); + } + +// { +// +// double[] doubles = new double[10*2]; +// for(int i=0;i<10*2;i++) doubles[i] = i; +// +// Resource newCell = graph.newResource(); +// graph.claim(newCell, L0.InstanceOf, null, sr.DoubleArrayCell); +// graph.addLiteral(newCell, sr.DoubleArrayCell_HasWidth, sr.DoubleArrayCell_HasWidth_Inverse, L0.Integer, 10, Bindings.INTEGER); +// graph.addLiteral(newCell, sr.HasLocation, sr.HasLocation_Inverse, L0.String, "B2", Bindings.STRING); +// graph.addLiteral(newCell, sr.DoubleArrayCell_HasDoubleArray, sr.DoubleArrayCell_HasDoubleArray_Inverse, L0.DoubleArray, doubles, Bindings.DOUBLE_ARRAY); +// graph.claim(result, L0.HasChildVariables, L0.HasChildVariables_Inverse, newCell); +// +// } + + return result; + + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj b/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj index 3685cdaa..df82b2c8 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj @@ -55,6 +55,17 @@ public class ExpressionParser { public HashMap> getEnumerationReferences() { return enumerationReferences; } + +/* + Collect EACH function call and all references that are inside the call brackets. + These are later used to exclude spread sheet references out of the normal functions. +*/ + String functionCall = null; + HashMap> functionCallReferences = new HashMap>(); + + public HashMap> getFunctionCallReferences() { + return functionCallReferences; + } } @@ -189,7 +200,10 @@ void primary() : { | | "false" | "true" - | LOOKAHEAD( name() "(" ) name() function_call_args() + | LOOKAHEAD( name() "(" ) { functionCall = null; + } + name() function_call_args() { functionCall = null; + } | component_reference(null) | "(" output_expression_list() ")" | "[" expression_list() ( ";" expression_list() )* "]" @@ -199,7 +213,12 @@ void primary() : { void name() : { } { - ( "." name() )? + { if (functionCall == null) + functionCall = token.image; + else + functionCall += "." + token.image; + } + ( "." name() )? } void component_reference(String prevToken) : { @@ -208,19 +227,20 @@ void component_reference(String prevToken) : { { String name = token.image; // forIndex == true and prevToken != null => this is the second part of an enumeration in for-index - if(forIndex == true && prevToken != null) { - if(enumerationReferences.get(prevToken) == null) { enumerationReferences.put(prevToken, new ArrayList()); - } - List list = enumerationReferences.get(prevToken); - list.add(token); - - // forIndex == true and prevToken == null => this is the enumeration in for-index - } else if(forIndex == true && prevToken == null) { - if(enumerationReferences.get(name) == null) { - enumerationReferences.put(name, new ArrayList()); - } - List list = enumerationReferences.get(name); - list.add(token); + if(forIndex == true) { if(prevToken != null) { + if(enumerationReferences.get(prevToken) == null) { enumerationReferences.put(prevToken, new ArrayList()); + } + List list = enumerationReferences.get(prevToken); + list.add(token); + + // forIndex == true and prevToken == null => this is the enumeration in for-index + } else { + if(enumerationReferences.get(name) == null) { + enumerationReferences.put(name, new ArrayList()); + } + List list = enumerationReferences.get(name); + list.add(token); + } } else { if(prevToken != null) name = prevToken + "." + name; if(references.get(name) == null) { @@ -228,6 +248,12 @@ void component_reference(String prevToken) : { } List list = references.get(name); list.add(token); + + if(functionCall != null) { + if(!functionCallReferences.containsKey(functionCall)) + functionCallReferences.put(functionCall, new ArrayList()); + List functionReferencelist = getFunctionCallReferences().get(functionCall); + functionReferencelist.add(token); } } } @@ -235,7 +261,6 @@ void component_reference(String prevToken) : { ( array_subscripts() )? ( "." component_reference(name) )? } - void function_call_args() : { } { "(" ( function_arguments() )? ")" @@ -245,8 +270,9 @@ void function_arguments() : { } { //expression [ "," function_arguments | for for_indices ] //| named_arguments - LOOKAHEAD(2) expression() ( "," function_arguments() | "for" for_indices() )? - | named_arguments() + LOOKAHEAD(2) named_argument() ( "," function_arguments() )? + | expression() ( "," function_arguments() | "for" for_indices() )? + } void for_indices() : { @@ -273,10 +299,12 @@ void for_index() : { } } +/* Removed by Teemu. Refactored in function_arguments) void named_arguments() : { } { named_argument() ( "," named_arguments() )? } +*/ void named_argument() : { } { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java index 40bbf5ae..c6f74ef0 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -131,7 +131,7 @@ public class SysdynModel implements IMappingListener, IModel { for(Resource config : readModules(g, configurationResource)) { modules.add((Configuration)mapping.map(g, config)); } - System.out.println("Loaded model with " + modules.size() + " modules."); +// System.out.println("Loaded model with " + modules.size() + " modules."); } public SysdynModel(ReadGraph g, Resource configurationResource) { @@ -208,7 +208,7 @@ public class SysdynModel implements IMappingListener, IModel { progressMonitor.subTask("Build model"); previousModelStructure = modelText; System.out.println("== Modelica == "); - System.out.println(writer.toString()); +// System.out.println(writer.toString()); System.out.println("== Modelica ends == "); try { 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 484e1955..ec94c803 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java @@ -120,7 +120,7 @@ public class ModelicaWriter { if(book != null) { b.append("// Spreadsheet definition\n"); - b.append(book.getBook()); + b.append(book.markBook()); } boolean initialEquations = false; @@ -177,10 +177,11 @@ public class ModelicaWriter { b.append("end ").append(className).append(";\n\n"); -// for(Module m : modules) { -// writeConfiguration(m.getConfiguration()); -// } - + // Update sheet definitions to contain the elements that were used. + if(book != null) { + int s = b.indexOf(book.markBook()); + b.replace(s, s + book.markBook().length(), book.getBook()); + } } public String escape(String name) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Book.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Book.java index 7a306f4e..556dfe1e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Book.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Book.java @@ -24,6 +24,10 @@ public class Book extends Variable { return sheets; } + public String markBook() { + return "BOOK " + this.getName(); + } + public String getBook() { StringBuilder book = new StringBuilder(); for(Sheet sheet : sheets) diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java index 542df9df..2d6157ce 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java @@ -1,23 +1,26 @@ package org.simantics.sysdyn.representation; import java.util.HashMap; +import java.util.HashSet; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.databoard.primitives.MutableString; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.request.ReadRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.exception.MissingVariableException; +import org.simantics.db.layer0.util.Simantics; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.layer0.Layer0; import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedElement; import org.simantics.objmap.annotations.UpdateMethod; -import org.simantics.spreadsheet.Range; import org.simantics.spreadsheet.SheetVariables; import org.simantics.spreadsheet.common.exception.CellParseException; +import org.simantics.spreadsheet.common.matrix.VariantMatrix; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; @@ -28,6 +31,9 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { protected Book book; HashMap cells = new HashMap(); + HashSet usedRanges = new HashSet(); + + Resource resource; public String getSheet() { return "Sheet"; @@ -35,15 +41,17 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { @UpdateMethod public boolean updateCells(ReadGraph g, Resource r) throws DatabaseException { + this.resource = r; g.getObjects(r, Layer0.getInstance(g).ConsistsOf); Variable v = g.adapt(r, Variable.class); cells.clear(); + usedRanges.clear(); for(Variable child : v.browseChildren(g)) { String name = child.getPropertyValue(g, Variables.NAME); try { - Range range = SpreadsheetUtils.decodeCellAbsolute(name); + SpreadsheetUtils.decodeCellAbsolute(name); Variant value = child.getPropertyValue(g, SheetVariables.CONTENT, Bindings.VARIANT); cells.put(name, value.getValue()); } catch (CellParseException e) { @@ -55,36 +63,120 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { } public String getStringRepresentation() { - StringBuilder clazz = new StringBuilder(); - + final StringBuilder clazz = new StringBuilder(); + final HashSet possibleRanges = new HashSet(); + clazz.append(" class " + name + "_class\n "); + // Write all doubles that have been used in expressions int counter = 0; - for(String key : cells.keySet()) { - Object value = cells.get(key); - if(value instanceof String || value instanceof MutableString) { - try { - Double d = Double.parseDouble(value.toString()); - value = d; - } catch (NumberFormatException e) { - } - } - - if(value instanceof Double) { - Double d = (Double)value; - clazz.append("constant Real " + key + " = " + d + "; "); - counter++; - if(counter > 10) { - counter = 0; - clazz.append("\n "); + for(String key : usedRanges) { + if(cells.containsKey(key)) { + Object value = cells.get(key); + if(value instanceof String || value instanceof MutableString) { + try { + Double d = Double.parseDouble(value.toString()); + value = d; + } catch (NumberFormatException e) { + } + } + + if(value instanceof Double) { + Double d = (Double)value; + clazz.append("constant Real " + key + " = " + d + "; "); + counter++; + if(counter > 10) { + counter = 0; + clazz.append("\n "); + } } + } else { + possibleRanges.add(key); } } + + try { + Simantics.getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + Variable v = graph.adapt(resource, Variable.class); + for(String possibleRange : possibleRanges) { + String[] parts = possibleRange.split(":"); + if(parts.length != 2 || !cells.containsKey(parts[0]) || !cells.containsKey(parts[1])) + continue; + Variable range = v.getChild(graph, possibleRange); + if(range == null) + continue; + Variant content = range.getPropertyValue(graph, SheetVariables.CONTENT, Bindings.VARIANT); + Object matrixValue = content.getValue(); + if(matrixValue instanceof VariantMatrix) { + VariantMatrix vm = (VariantMatrix)matrixValue; + Double[][] array = toDoubleMatrix(vm); + + if(array[0].length > 1) { + // Has two dimensions + clazz.append("Real[" + array.length + ", " + array[0].length + "] "); + clazz.append(possibleRange.replace(":", "_") + " = {"); + for(int i = 0; i < array.length; i++) { + clazz.append("{"); + for(int j = 0; j < array[i].length; j++) { + clazz.append(array[i][j]); + if(j < array[i].length - 1) + clazz.append(", "); + } + clazz.append("}"); + if(i < array.length - 1) + clazz.append(", "); + } + clazz.append("};\n"); + } else { + // Has one dimension + clazz.append("Real[" + array.length + "] "); + clazz.append(possibleRange.replace(":", "_") + " = {"); + for(int i = 0; i < array.length; i++) { + clazz.append(array[i][0]); + if(i < array.length - 1) + clazz.append(", "); + } + clazz.append("};\n"); + } + + } + } + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + clazz.append("\n end " + name + "_class;\n"); clazz.append(" " + name + "_class " + name + ";\n"); return clazz.toString(); } + private Double[][] toDoubleMatrix(VariantMatrix matrix) { + Double[][] array = new Double[matrix.getRowCount()][matrix.getColumnCount()]; + for(int i = 0; i < matrix.getRowCount(); i++) { + for(int j = 0; j < matrix.getColumnCount(); j++) { + Variant cell = matrix.get(i, j); + if(cell.getBinding().equals(Bindings.DOUBLE)) { + array[i][j] = (Double)cell.getValue(); + } else if (cell.getBinding().equals(Bindings.MUTABLE_STRING)) { + try { + array[i][j] = Double.parseDouble(cell.getValue().toString()); + } catch (NumberFormatException e) { + array[i][j] = 0.0; + } + } else { + array[i][j] = 0.0; + } + } + } + return array; + } + public HashMap getCells() { return cells; } @@ -94,6 +186,17 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { } + /** + * Add a range that has been used for this sheet. + * + * Used ranges help to reduce code sent to Modelica. + * + * @param range range of cell/cells. (e.g. B2 or B4:B6) + */ + public void use(String range) { + usedRanges.add(range); + } + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java index a528afae..aaf00192 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java @@ -19,6 +19,7 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.representation.ArrayIndexes; import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; @GraphType("http://www.simantics.org/Sysdyn-1.0/NormalExpression") @@ -55,7 +56,7 @@ public class NormalExpression extends Expression { @Override public String getEquation(IndependentVariable variable) { - String equation = IndexUtils.equationRangesToIndexes(variable, this.equation); + String equation = FormatUtils.formatExpressionForModelica(variable, this.equation); String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange()); return " " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + equation + ";\n"; } 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 968041b3..dcf0887a 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 @@ -21,6 +21,7 @@ import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.Stock; import org.simantics.sysdyn.representation.Valve; +import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; @GraphType("http://www.simantics.org/Sysdyn-1.0/StockExpression") @@ -70,10 +71,33 @@ public class StockExpression extends Expression { b.append(" der(") .append(variable.getName() + range) .append(") ="); - for(Valve valve : ((Stock)variable).getIncomingValves()) - b.append("\n + ").append(valve.getName() + range); - for(Valve valve : ((Stock)variable).getOutgoingValves()) - b.append("\n - ").append(valve.getName() + range); + ArrayList incoming = ((Stock)variable).getIncomingValves(); + ArrayList outgoing = ((Stock)variable).getOutgoingValves(); + if(incoming.isEmpty() && outgoing.isEmpty()) { + // No connections, add 0 for each array index if any. + ArrayIndexes ai = variable.getArrayIndexes(); + ArrayList enumerations = null; + if(ai != null) + enumerations = ai.getEnumerations(); + + if(ai == null || enumerations == null || enumerations.isEmpty()) { + b.append(" 0.0"); + } else { + b.append(" zeros("); + for(int i = 0; i < enumerations.size(); i++) { + b.append(enumerations.get(i).getEnumerationIndexes().size()); + if(i != enumerations.size() - 1) + b.append(", "); + } + b.append(")"); + } + + } else { + for(Valve valve : incoming) + b.append("\n + ").append(valve.getName() + range); + for(Valve valve : outgoing) + b.append("\n - ").append(valve.getName() + range); + } b.append(";\n"); return b.toString(); } @@ -86,10 +110,11 @@ public class StockExpression extends Expression { } catch (Exception e){ // Has an initial equation } + String equation = FormatUtils.formatExpressionForModelica(variable, initialEquation); String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange()); if(range == null) range = ""; - return " " + variable.getName() + range + " = " + initialEquation + ";\n"; + return " " + variable.getName() + range + " = " + equation + ";\n"; } 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 5eb54fdb..c15eb7cd 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 @@ -19,6 +19,7 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.representation.ArrayIndexes; import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; @@ -58,7 +59,7 @@ public class WithLookupExpression extends Expression { @Override public String getEquation(IndependentVariable variable) { - String equation = IndexUtils.equationRangesToIndexes(variable, this.equation); + String equation = FormatUtils.formatExpressionForModelica(variable, this.equation); String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange()); return diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/FormatUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/FormatUtils.java new file mode 100644 index 00000000..68bd0f19 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/FormatUtils.java @@ -0,0 +1,14 @@ +package org.simantics.sysdyn.representation.utils; + +import org.simantics.sysdyn.representation.Variable; + +public class FormatUtils { + + public static String formatExpressionForModelica(Variable variable, String expression) { + String modified = expression; + modified = IndexUtils.equationRangesToIndexes(variable, modified); + modified = SheetFormatUtils.reformatSheetReferences(variable, modified); + return modified; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/SheetFormatUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/SheetFormatUtils.java new file mode 100644 index 00000000..fd04c6c0 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/SheetFormatUtils.java @@ -0,0 +1,92 @@ +package org.simantics.sysdyn.representation.utils; + +import java.io.StringReader; +import java.util.HashMap; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.simantics.sysdyn.expressionParser.ExpressionParser; +import org.simantics.sysdyn.expressionParser.ParseException; +import org.simantics.sysdyn.expressionParser.Token; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.Sheet; +import org.simantics.sysdyn.representation.Variable; + +public class SheetFormatUtils { + + public static String reformatSheetReferences(Variable v, String expression) { + if(!expression.contains("(")) + return expression; + ExpressionParser parser = new ExpressionParser(new StringReader(expression)); + try { + parser.expr(); + + HashMap> functionCalls = parser.getFunctionCallReferences(); + for(String key : functionCalls.keySet()) { + String[] parts = key.split("\\."); + Object current = v.getParentConfiguration(); + Object found = null; + for(int i = 0; i < parts.length && current != null; i++) { + found = null; + if(current instanceof Configuration) { + for(IElement e : ((Configuration)current).getElements()) { + if(e instanceof Configuration && + ((Variable)e).getName().equals(parts[i])) { + found = e; + break; + } else if(e instanceof Variable && + ((Variable)e).getName().equals(parts[i])) { + found = e; + break; + } + } + } + current = found; + } + + if(current != null && current instanceof Sheet) { + + String tmp = ""; + int start = 0, end = 0, call = 0; + String cellOrRange = null; + while((call = expression.indexOf(key, end)) >= 0) { + start = expression.indexOf("(", call); + + tmp += expression.substring(end, start); + + end = expression.indexOf(")", start) + 1; + if(start < 0 || end < 0 || end < start) { + break; + } + cellOrRange = expression.substring(start, end); + cellOrRange = cellOrRange.substring(1, cellOrRange.length() - 1); + cellOrRange = cellOrRange.trim(); + cellOrRange = cellOrRange.replace(" ", ""); + + Pattern p = Pattern.compile("[-\\+\\*\\/\\(\\)\\{\\}\\[\\],\\.\\t\\n\\r\\f]"); + Matcher m = p.matcher(cellOrRange); + if (m.find() || cellOrRange.split(":").length > 2 || cellOrRange.length() == 0) { + continue; + } + + // Use the cell or range in the sheet. + ((Sheet)current).use(cellOrRange); + + cellOrRange = cellOrRange.replace(":", "_"); + + tmp += "." + cellOrRange; + } + tmp += expression.substring(end, expression.length()); + return tmp; + } + } + + } catch (ParseException e) { + e.printStackTrace(); + } + return expression; + } + +} -- 2.47.1