From: Antti Villberg Date: Thu, 28 Nov 2019 10:55:52 +0000 (+0200) Subject: Adopt spreadsheet changes made in Balas development X-Git-Tag: v1.43.0~136^2~27 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=5c67a96d34fe904b8c4b0375cd08ff1d543bf369;p=simantics%2Fplatform.git Adopt spreadsheet changes made in Balas development gitlab #427 Change-Id: Idfcc4da578dcfa03e9e88f88a2e5012f17fc1f1d --- diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariables.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariables.java index ddfe108cb..cd38064a8 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariables.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/ProxyVariables.java @@ -52,25 +52,9 @@ public class ProxyVariables { } public static Variable proxySessionVariable(ReadGraph graph, Variable variable) throws DatabaseException { - - try { - - Variable child = variable.getParent(graph); - Variable parent = child.getParent(graph); - if(parent instanceof ProxyChildVariable) { - Variable var = ((ProxyChildVariable)parent).other(); - if(var.getParent(graph) == null) { - return null; - } - return var; - } else { - Variable input = parent.getPossiblePropertyValue(graph, "session"); - if(input == null) { - System.out.println("null input for: " + parent.getURI(graph)); - } - return input; - } + try { + return proxyVariableInput(graph, variable); } catch (Throwable t) { LOGGER.error("proxySessionVariable failed", t); return null; @@ -109,7 +93,7 @@ public class ProxyVariables { } else { Variable parent = variable.getParent(graph); if(parent == null) return null; - else return proxyVariableBase(graph, parent); + else return proxyVariableInput(graph, parent); } } diff --git a/bundles/org.simantics.modeling.ontology/graph/ModelingViewpoint.pgraph b/bundles/org.simantics.modeling.ontology/graph/ModelingViewpoint.pgraph index b97753e5f..10e9146d0 100644 --- a/bundles/org.simantics.modeling.ontology/graph/ModelingViewpoint.pgraph +++ b/bundles/org.simantics.modeling.ontology/graph/ModelingViewpoint.pgraph @@ -450,6 +450,13 @@ MOD.Contributions.NewSheetBook : VP.ActionContribution VP.ActionContribution.HasNodeType L0.Library VP.ActionContribution.HasAction ACTIONS.NewSheetBook +MOD.Contributions.ImportSheetBook : VP.ActionContribution + L0.HasLabel "Spreadsheet" + VP.ActionContribution.HasImage SILK.star + VP.ActionContribution.HasCategory VP.ImportActionCategory + VP.ActionContribution.HasNodeType L0.Library + VP.ActionContribution.HasAction ACTIONS.ImportSheetBook + MOD.Contributions.ActivateModel : VP.ActionContribution L0.HasLabel "Activate" VP.ActionContribution.HasImage SILK.bullet_go @@ -693,6 +700,7 @@ MAC VP.BrowseContext.SupportsRenamingOf MBC.Symbol VP.BrowseContext.HasActionContribution MOD.Contributions.NewSheetBook + MOD.Contributions.ImportSheetBook @VP.renamingTestContribution L0.SharedOntology @@ -732,6 +740,8 @@ ACTIONS.NewSCLQueryType @MOD.sclAction "createSCLQueryTypeAction" ACTIONS.NewSheetBook @MOD.sclAction "createSpreadsheetBookAction" +ACTIONS.ImportSheetBook + @MOD.sclAction "importSpreadsheetBookAction" ACTIONS.ActivateModel @MOD.sclAction "activateModelAction" ACTIONS.ActivateExperiment diff --git a/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF b/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF index eab319b3a..8d195df0c 100644 --- a/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF @@ -18,7 +18,6 @@ Export-Package: org.simantics.spreadsheet.common, org.simantics.spreadsheet.common.cell, org.simantics.spreadsheet.common.cell.handler, org.simantics.spreadsheet.common.client, - org.simantics.spreadsheet.common.exception, org.simantics.spreadsheet.common.expression.analysis, org.simantics.spreadsheet.common.expression.lexer, org.simantics.spreadsheet.common.expression.node, diff --git a/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/util/SpreadsheetUtils.java b/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/util/SpreadsheetUtils.java index 4d6715dc5..a784ccf9e 100644 --- a/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/util/SpreadsheetUtils.java +++ b/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/util/SpreadsheetUtils.java @@ -46,291 +46,17 @@ import org.simantics.document.server.io.SimpleFont; import org.simantics.layer0.Layer0; import org.simantics.scl.runtime.function.Function1; import org.simantics.scl.runtime.tuple.Tuple; -import org.simantics.spreadsheet.CellEditor; -import org.simantics.spreadsheet.CellEditor.Transaction; import org.simantics.spreadsheet.ClientModel; -import org.simantics.spreadsheet.ClientModel.OperationMode; +import org.simantics.spreadsheet.OperationMode; import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.Transaction; import org.simantics.spreadsheet.common.TableCell; import org.simantics.spreadsheet.common.cell.StringCellParser; -import org.simantics.spreadsheet.common.exception.CellParseException; import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.utils.datastructures.Pair; public class SpreadsheetUtils { - - public static final int SPREADSHEET_BTREE_SIZE = 100; - - public static String offset(String location, int rowOffset, int columnOffset) { - - Range range = decodeCellAbsolute(location); - String result = cellName(range.startRow + rowOffset, range.startColumn + columnOffset); - // System.err.println("offset " + location + "(" + rowOffset + " " + columnOffset + ") = >" + result); - return result; - - } - - public static Object extract(Object object, int row, int column) { - if(object instanceof List) { - List list = (List)object; - if(list.size() <= row) return null; - Object item = list.get(row); - if(item instanceof Tuple) { - Tuple tuple = (Tuple)item; - if(tuple.length() <= column) return null; - return tuple.get(column); - } - } - return null; - } - - // 1 kirjain, 'A' + column - // 2 kirjainta, 'A' + column % 26 , 'A' + int((column-26)/26) - // 3 kirjainta 'A' + column % 26 , 'A' + int(column-(26*(26+1)) / 26) % 26 - - // 0 26 - // 26 26 + 26*26 - // 26 + 26*26 26 + 26*26 + 26*26*26 - - public static String columnName(int column, int current, int limit, int chars) { - - if(column < limit) { - - char[] buf = new char[chars]; - column -= current; - for(int i=chars-1;i>=0;i--) { - char rem = (char)(column % 26); - column = (column / 26); - buf[i] = (char)('A' + rem); - } - return new String(buf); - - } else return columnName(column, limit, 26*(limit+1), chars+1); - - } - - public static String columnName(int column) { - return columnName(column, 0, 26, 1); - } - - public static String cellName(int row, int column) { - - String result = columnName(column); - result += (row+1); - return result; - - } - - public static Range decodeCellAbsolute(String identifier) { - long l = decodeCellCoded(identifier); - int row = (int)(l & 0xffffffff) - 1; - int column = (int)((l>>32) & 0xffffffff); - return new Range(row, row, column, column); - } - - public static Range decodePossibleCellAbsolute(String identifier) { - try { - return decodeCellAbsolute(identifier); - } catch (CellParseException e) { - return null; - } - } - - public static long decodeCellCoded(String identifier) { - - // System.out.println("decodecellabsolute " + identifier); - - int row = 0; - int column = 0; - -// identifier. - - int position = 0; - - // We skip $ here - if(identifier.charAt(position) == '$') position++; - - int length = identifier.length(); - - while(position < length) { - char b = identifier.charAt(position); - if(b >= 'A' && b <= 'Z') column = column * 26 + (b-'A' + 1); - else break; - position++; - } - - // We skip $ here - if(position < length) - if(identifier.charAt(position) == '$') - position++; - - while(position < length) { - char b = identifier.charAt(position); - if(b >= '0' && b <= '9'){ - row = row * 10 + b-'0'; - } - else if(b=='-' && position < (length-1)){//identify use of full row range here. - position++; - char b2 = identifier.charAt(position); - if(b2=='1'){ - row = 0; - position++; - break; - } - } - else { - break; - } - position++; - } - - if(position == length) { - - // We need to be able to express -1 in row => report row + 1 here - column--; - // System.err.println("ra " + identifier + " => " + row + " " + column); - return row + (((long)column)<<32); - - } else { - - throw new CellParseException("Cell identifier '" + identifier + "' is not a valid cell reference."); - - } - - } - - public static Range decodeCellRelative(String identifier, int row, int column) { - - int offset = Integer.valueOf(identifier.substring(1).trim()); - // System.out.println("offset=" + offset); - - if(identifier.startsWith("L") || identifier.startsWith("l")) { - return new Range(row, row, column-offset, column-offset); - } else if(identifier.startsWith("R") || identifier.startsWith("r")) { - return new Range(row, row, column+offset, column+offset); - } else if(identifier.startsWith("U") || identifier.startsWith("u")) { - return new Range(row-offset, row-offset, column, column); - } else if(identifier.startsWith("D") || identifier.startsWith("d")) { - return new Range(row+offset, row+offset, column, column); - } else { - throw new CellParseException("Relative cell syntax must begin with L|R|U|D."); - } - - } - - public static Range decodeCell(String identifier, int row, int column) { - - if(identifier.startsWith("_")) { - return decodeCellRelative(identifier.substring(1), row, column); - } else { - return decodeCellAbsolute(identifier); - } - - } - - public static Range decodeReference(String identifier, int row, int column) { - if(!identifier.startsWith("&")) throw new CellParseException("A reference cell was expected."); - return decodeRange(identifier.substring(1), row, column); - } - - public static List decodeRanges(String ranges){ - String[] splitted = ranges.split(","); - List result = new ArrayList<>(); - for(String split : splitted){ - result.add(decodeRange(split)); - } - return result; - } - - public static int startRow(List ranges){ - int s = -1; - for(Range r : ranges){ - if(r.startRow ranges){ - int s = -1; - for(Range r : ranges){ - if(r.startColumnendRow){ - endRow = r.endRow; - } - return endRow - startRow +1; - } - - public static int amountOfColumns(Range r){ - int endColumn = -2; - int startColumn = -2; - if(r.isFullColumns()){ - return Range.MAXCOLUMNSPEC; - } - if(endColumn == -2 && startColumn == -2){ - endColumn = r.endColumn; - startColumn = r.startColumn; - } - if(r.startColumnendColumn){ - endColumn = r.endColumn; - } - return endColumn - startColumn +1; - } - - public static Range decodeRange(String rangeOrCell) { - if(rangeOrCell.isEmpty()) return fullRange(); - return decodeRange(rangeOrCell, 0, 0); - } - - public static Range fullRange() { - return new Range(0, -1, 0, -1); - } - - public static Range decodeRange(String rangeOrCell, int row, int column) { - - String[] parts = rangeOrCell.split(":"); - if(parts.length == 1) { - - return decodeCell(rangeOrCell, row, column); - - } else if (parts.length == 2) { - - Range from = decodeCell(parts[0].trim(), row, column); - // System.out.println("decodefrom=" + from); - Range to = decodeCell(parts[1].trim(), row, column); - // System.out.println("decodeto=" + to); - return Range.combine(from, to); - - } else { - - throw new CellParseException("The reference cell syntax was invalid. At most 1 occurrence of ':' is expected."); - - } - - } public static Pair> parse(String text, StringCellParser[] parsers) { @@ -410,15 +136,15 @@ public class SpreadsheetUtils { public static void main(String[] args) { for(int i=0;i<16384;i++) { - String name = columnName(i); - Range r = decodeCellAbsolute(name + "1"); + String name = Spreadsheets.columnName(i); + Range r = Spreadsheets.decodeCellAbsolute(name + "1"); System.err.println(i + " " + name + " " + r); } } public static String getLabel(ClientModel model, int row, int column) { try { - String location = SpreadsheetUtils.cellName(row, column); + String location = Spreadsheets.cellName(row, column); String label = model.getPropertyAt(location, ClientModel.LABEL); if(label != null) return label; Variant content = SpreadsheetUtils.getSafeClientVariant(model, location, ClientModel.CONTENT); @@ -435,8 +161,8 @@ public class SpreadsheetUtils { } public static boolean isInBounds(String base, String location, int wBounds, int hBounds) { - Range baseRange = decodeCellAbsolute(base); - Range locationRange = decodeCellAbsolute(location); + Range baseRange = Spreadsheets.decodeCellAbsolute(base); + Range locationRange = Spreadsheets.decodeCellAbsolute(location); if(locationRange.startColumn < baseRange.startColumn) return false; if(locationRange.startRow < baseRange.startRow) return false; int wb = wBounds == -1 ? (Integer.MAX_VALUE / 3) : wBounds; @@ -446,7 +172,7 @@ public class SpreadsheetUtils { return true; } - public static void schedule(CellEditor.Transaction transaction, Write write) { + public static void schedule(Transaction transaction, Write write) { if(transaction == null) { @@ -471,7 +197,7 @@ public class SpreadsheetUtils { return new TransactionImpl(mode); } - static class TransactionImpl implements CellEditor.Transaction { + static class TransactionImpl implements Transaction { private ArrayList writes = new ArrayList<>(); private final OperationMode mode; @@ -577,7 +303,7 @@ public class SpreadsheetUtils { // graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell); // BTree bt = new BTree(graph, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, SR.Lines, SR.LineNode, L0.PartOf, true); - BTree bt = new BTree(graph, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, sr.Lines, sr.LineNode, L0.PartOf, false); + BTree bt = new BTree(graph, Spreadsheets.SPREADSHEET_BTREE_SIZE, sr.Lines, sr.LineNode, L0.PartOf, false); // BTree bt = BTreeUtils.create(graph, sr.Lines, sr.LineNode, L0.PartOf, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, false); Resource lines = bt.rootOfBTree(); @@ -807,7 +533,7 @@ public class SpreadsheetUtils { if (formatString == null) return getLabel(model, row, column); try { - String location = SpreadsheetUtils.cellName(row, column); + String location = Spreadsheets.cellName(row, column); Variant content = SpreadsheetUtils.getSafeClientVariant(model, location, ClientModel.CONTENT); if(content != null) { @@ -830,5 +556,78 @@ public class SpreadsheetUtils { return null; } } + + /* + * Please use Spreadsheets.cellName instead + */ + @Deprecated + public static String cellName(int row, int column) { + return Spreadsheets.cellName(row, column); + } + + /* + * Please use Spreadsheets.columnName instead + */ + @Deprecated + public static String columnName(int column) { + return Spreadsheets.columnName(column); + } + + /* + * Please use Spreadsheets.decodeCellAbsolute instead + */ + @Deprecated + public static Range decodeCellAbsolute(String identifier) { + return Spreadsheets.decodeCellAbsolute(identifier); + } + + /* + * Please use Spreadsheets.decodePossibleCellAbsolute instead + */ + @Deprecated + public static Range decodePossibleCellAbsolute(String identifier) { + return Spreadsheets.decodePossibleCellAbsolute(identifier); + } + + /* + * Please use Spreadsheets.decodeRange instead + */ + @Deprecated + public static Range decodeRange(String rangeOrCell) { + return Spreadsheets.decodeRange(rangeOrCell); + } + + /* + * Please use Spreadsheets.decodeRanges instead + */ + @Deprecated + public static List decodeRanges(String ranges) { + return Spreadsheets.decodeRanges(ranges); + } + + /* + * Please use Spreadsheets.startColumn instead + */ + @Deprecated + public static int startColumn(List ranges) { + return Spreadsheets.startColumn(ranges); + } + + /* + * Please use Spreadsheets.startRow instead + */ + @Deprecated + public static int startRow(List ranges) { + return Spreadsheets.startRow(ranges); + } + + /* + * Please use Spreadsheets.offset instead + */ + @Deprecated + public static String offset(String location, int rowOffset, int columnOffset) { + return Spreadsheets.offset(location, rowOffset, columnOffset); + } + } diff --git a/bundles/org.simantics.spreadsheet.graph/plugin.xml b/bundles/org.simantics.spreadsheet.graph/plugin.xml index 187388929..6088f678d 100644 --- a/bundles/org.simantics.spreadsheet.graph/plugin.xml +++ b/bundles/org.simantics.spreadsheet.graph/plugin.xml @@ -12,7 +12,7 @@ - + diff --git a/bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl b/bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl index 8898ce10a..aa58a7f73 100644 --- a/bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl +++ b/bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl @@ -1,12 +1,45 @@ include "Simantics/DB" include "Simantics/Ontologies" include "Simantics/SCL" +include "Simantics/UI" include "Document/All" include "File" + +effect SpreadsheetTransaction + "spreadsheetTransaction" + "org.simantics.spreadsheet.Transaction" + +importJava "org.simantics.spreadsheet.graph.ExternalRef" where + data ExternalRef + importJava "org.simantics.spreadsheet.common.TableCell" where data TableCell +importJava "java.util.function.Consumer" where + data Consumer + +importJava "org.simantics.spreadsheet.CellEditor" where + data CellEditor + startTransaction :: CellEditor -> OperationMode -> Transaction + @JavaName "edit" + editProperty_ :: CellEditor -> String -> String -> a -> Binding a -> Maybe Consumer -> () + @JavaName "edit" + editContent :: CellEditor -> String -> Variant -> Maybe Consumer -> () + +@inline +editProperty :: Serializable a => CellEditor -> String -> String -> a -> Maybe Consumer -> () +editProperty editor location property value consumer = editProperty_ editor location property value binding consumer + +importJava "org.simantics.spreadsheet.OperationMode" where + data OperationMode + OPERATION :: OperationMode + EDIT_MODE :: OperationMode + +importJava "org.simantics.spreadsheet.Transaction" where + data Transaction + commit :: Transaction -> () + importJava "org.simantics.spreadsheet.common.TreeTableCell" where data TreeTableCell @@ -41,6 +74,14 @@ importJava "org.simantics.spreadsheet.graph.SpreadsheetGraphUtils" where saveInitialCondition :: Variable -> Resource -> String -> Resource findCell :: Variable -> String -> Maybe Variable invalidateAll :: Variable -> () + extRefVariable :: Variable -> Variant + extRefActiveVariable :: Variable -> Variant + cellEditor :: Resource -> CellEditor + syncExec :: CellEditor -> OperationMode -> ( a) -> a + cellColumn :: Variable -> Integer + +importJava "org.simantics.spreadsheet.Spreadsheets" where + cellName :: Integer -> Integer -> String importJava "org.simantics.spreadsheet.util.SpreadsheetUtils" where createSheet :: Resource -> String -> Resource @@ -58,6 +99,11 @@ importJava "org.simantics.spreadsheet.util.SpreadsheetUtils" where selectColumn :: Integer -> TableCell -> Boolean setSCLLine :: Resource -> Integer -> String -> () sheetRun :: Resource -> Variable -> Variable + @JavaName "sheetRun" + bookRun :: Resource -> Variable -> Variable + +sheetRunDefault :: Resource -> Variable +sheetRunDefault sheet = sheetRun sheet (resourceVariable sheet) importJava "org.simantics.spreadsheet.graph.SpreadsheetSessionManager" where removeSpreadsheetSession :: Variable -> () @@ -65,6 +111,11 @@ importJava "org.simantics.spreadsheet.graph.SpreadsheetSessionManager" where importJava "org.simantics.spreadsheet.graph.ExcelImport" where importBook :: Resource -> File -> () +importSpreadsheetBookAction :: Resource -> () +importSpreadsheetBookAction res = match fileDialog "foo" [("Excel file", "*.xls"), ("Excel File", "*.xlsx")] with + Nothing -> () + Just file -> importBook res file + createSpreadsheetBookAction :: Resource -> () createSpreadsheetBookAction res = do syncWrite (\() -> createSpreadsheetBookDefault res) diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java deleted file mode 100644 index 8880085e3..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public interface CellFormulaFunction { - - T evaluate(CellValueVisitor visitor, AstArgList args); - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java deleted file mode 100644 index 8150b4dba..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java +++ /dev/null @@ -1,478 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.graph.formula.FormulaError2; -import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment; -import org.simantics.spreadsheet.graph.parser.ast.AstApply; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstArithmeticExpression; -import org.simantics.spreadsheet.graph.parser.ast.AstArray; -import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference; -import org.simantics.spreadsheet.graph.parser.ast.AstBoolean; -import org.simantics.spreadsheet.graph.parser.ast.AstDouble; -import org.simantics.spreadsheet.graph.parser.ast.AstFactor; -import org.simantics.spreadsheet.graph.parser.ast.AstIdentifier; -import org.simantics.spreadsheet.graph.parser.ast.AstInteger; -import org.simantics.spreadsheet.graph.parser.ast.AstNothing; -import org.simantics.spreadsheet.graph.parser.ast.AstNull; -import org.simantics.spreadsheet.graph.parser.ast.AstRange; -import org.simantics.spreadsheet.graph.parser.ast.AstRelation; -import org.simantics.spreadsheet.graph.parser.ast.AstString; -import org.simantics.spreadsheet.graph.parser.ast.AstTerm; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; -import org.simantics.spreadsheet.graph.parser.ast.AstValueVisitor; -import org.simantics.spreadsheet.util.SpreadsheetUtils; - -import it.unimi.dsi.fastutil.longs.AbstractLongList; -import it.unimi.dsi.fastutil.longs.LongArrayList; - -public class CellValueVisitor implements AstValueVisitor { - - final public SpreadsheetBook book; - final private SpreadsheetEvaluationEnvironment env; - final private SpreadsheetCell thisCell; - final private LongArrayList references = new LongArrayList(); - - public CellValueVisitor(SpreadsheetEvaluationEnvironment env, SpreadsheetCell thisCell) { - this.book = env.getBook(); - this.env = env; - this.thisCell = thisCell; - } - - public void addReference(long ref) { - references.add(ref); - } - - public AbstractLongList getReferences() { - return references; - } - - @Override - public Object visit(AstBoolean astBoolean) { - return astBoolean.value; - } - - @Override - public Object visit(AstDouble astFloat) { - return astFloat.value; - } - - @Override - public Object visit(AstInteger astInteger) { - return astInteger.value; - } - - @Override - public Object visit(AstNull astNull) { - throw new IllegalStateException(); - } - - @Override - public Object visit(AstString astString) { - return astString.value; - } - - @Override - public Object visit(AstRange astRange) { - - if(astRange.isRef()){ - return FormulaError2.REF.getString(); - } - - if(astRange.isCell()) { - String ref = astRange.first; - Range r = SpreadsheetUtils.decodeCell(ref, 0, 0); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetCell cell = thisCell.getBook().get(sheetName, r.startRow, r.startColumn); - if(cell == null) { - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - SpreadsheetLine line = eng.getLine(r.startRow); - - if (line == null) { - line = new SpreadsheetLine(eng.lines, r.startRow); - eng.lines.lines.put(-r.startRow, line); - } - cell = SpreadsheetCell.empty(line, r.startColumn); - } - return cell.evaluate(env, this); - - } else { - - Object cached = thisCell.getEngine().getCachedRange(astRange); - if(cached != null) { - - Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - Range r = eng.actualRange(r_); - for(int row=0; row < r.height();row++) { - SpreadsheetLine line = eng.getLine(r.startRow + row); - if(line != null) { - for(int column=0; column < r.width();column++) { - int col = r.startColumn + column; - if(line.cells.size() > col) { - SpreadsheetCell cell = line.cells.get(r.startColumn + column); - //Add references, but do not evaluate if there exists a cached range. - addReference(cell.makeReferenceKey()); - } - } - } - } - return cached; - } - - Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - // Full ranges are resolved here - Range r = eng.actualRange(r_); - SpreadsheetMatrix result = new SpreadsheetMatrix(r.width(), r.height()); - for(int row=0; row < r.height();row++) { - SpreadsheetLine line = eng.getLine(r.startRow + row); - if(line != null) { - for(int column=0; column < r.width();column++) { - int col = r.startColumn + column; - if(line.cells.size() > col) { - SpreadsheetCell cell = line.cells.get(r.startColumn + column); - result.values[r.width()*row + column] = cell.evaluate(env, this); - } - } - } - } - thisCell.getEngine().cacheRange(astRange, result); - return result; - } - } - - @Override - public Object visit(AstArgList astArgList) { - throw new IllegalStateException(); - } - - @Override - public Object visit(AstApply astApply) { - CellFormulaFunction fn = env.getFunction(astApply.value); - if(fn != null) { - return fn.evaluate(this, astApply.args); - } else { - return FormulaError2.NAME.getString(); - } - } - - @Override - public Object visit(AstRelation astRelation) { - - Object leftResult = astRelation.left.accept(this); - Object rightResult = astRelation.right.accept(this); - - FormulaError2 err = FormulaError2.forObject(leftResult); - if(err!=null) return err.getString(); - FormulaError2 err2 = FormulaError2.forObject(rightResult); - if(err2!=null) return err2.getString(); - - if(leftResult instanceof Variant){ - Object leftTemp = ((Variant)leftResult).getValue(); - Double leftVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftTemp); - if(leftVal==null) leftResult = leftTemp.toString(); - else leftResult = leftVal; - } - if(rightResult instanceof Variant){ - Object rightTemp = ((Variant)rightResult).getValue(); - Double rightVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightTemp); - if(rightVal==null) rightResult = rightTemp.toString(); - else rightResult = rightVal; - } - if ((leftResult instanceof String) && (rightResult instanceof String)) { - String leftString = (leftResult.toString()).toLowerCase(); - String rightString = (rightResult.toString()).toLowerCase(); - if("<".equals(astRelation.op.trim())) return leftString.compareTo(rightString) < 0; - else if(">".equals(astRelation.op.trim())) return leftString.compareTo(rightString) > 0; - else if("=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) == 0; - else if("<>".equals(astRelation.op.trim())) return leftString.compareTo(rightString) != 0 ; - else if("<=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) <= 0 ; - else if(">=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) >= 0 ; - else throw new IllegalStateException(); - } else { - Number leftNumber = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftResult); - Number rightNumber = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightResult); - if(leftNumber==null || rightNumber==null) return false; - if("<".equals(astRelation.op.trim())) return leftNumber.doubleValue() < rightNumber.doubleValue(); - else if(">".equals(astRelation.op.trim())) return leftNumber.doubleValue() > rightNumber.doubleValue(); - else if("=".equals(astRelation.op.trim())) return leftNumber.doubleValue() == rightNumber.doubleValue(); - else if("<>".equals(astRelation.op.trim())) return leftNumber.doubleValue() != rightNumber.doubleValue(); - else if("<=".equals(astRelation.op.trim())) return leftNumber.doubleValue() <= rightNumber.doubleValue(); - else if(">=".equals(astRelation.op.trim())) return leftNumber.doubleValue() >= rightNumber.doubleValue(); - else throw new IllegalStateException(); - } - } - - Object leftValueWithPrefix(Object result, AstValue value, String prefix, boolean forceNumber) { - if(result == null) { - Object obj = value.accept(this); - FormulaError2 err = FormulaError2.forObject(obj); - if(err!=null) return err.getString(); - - if("-".equals(prefix)) { - result = SpreadsheetGraphUtils.asNumber(obj); - return -((Number)result).doubleValue(); - } else { - if(forceNumber) return SpreadsheetGraphUtils.asNumber(obj); - else return obj; - } - } - try{ - return (Number)Double.parseDouble(result.toString()); - } catch (NumberFormatException e){ - return result; - } - } - - @Override - public Object visit(AstArithmeticExpression exp) { - Object result = null; - Object other = null; - AstValue value = null; - Object acceptedValue = null; - - for(int i=0;i 0) b.append(";"); - b.append(astArgList.values.get(i).accept(this)); - } - return b.toString(); - } - - @Override - public String visit(AstApply astApply) { - if(astApply.args == null) { - return astApply.value + "()"; - } else { - return astApply.value + "(" + astApply.args.accept(this) + ")"; - } - } - - @Override - public String visit(AstRelation astRelation) { - - StringBuilder b = new StringBuilder(); - b.append(astRelation.left.accept(this)); - b.append(astRelation.op.trim()); - b.append(astRelation.right.accept(this)); - return b.toString(); - - } - - @Override - public String visit(AstArithmeticExpression exp) { - - StringBuilder b = new StringBuilder(); - if(exp.prefix != null) b.append(exp.prefix); - - b.append(exp.left.accept(this)); - - for(int i=0;i 0) b.append(";"); - b.append(array.values.get(i).accept(this)); - } - return b.toString(); - } - - @Override - public String visit(AstNothing array) { - return "AstNothing"; - } - - @Override - public String visit(AstArrayFormulaReference ref) { - return "{" + ref.value.accept(this) + "}"; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java deleted file mode 100644 index d741d4c7a..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java +++ /dev/null @@ -1,450 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import org.simantics.databoard.Bindings; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.db.exception.DatabaseException; -import org.simantics.simulator.toolkit.StandardNodeManagerSupport; -import org.simantics.simulator.variable.exceptions.NodeManagerException; -import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment; -import org.simantics.spreadsheet.graph.synchronization.LineNodeUpdater; -import org.simantics.spreadsheet.graph.synchronization.LineUpdater; -import org.simantics.spreadsheet.graph.synchronization.NullUpdater; -import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent; -import org.simantics.spreadsheet.graph.synchronization.StyleUpdater; -import org.simantics.structural.synchronization.base.ModuleUpdaterBase; -import org.simantics.structural.synchronization.base.ModuleUpdaterFactoryBase; -import org.simantics.structural.synchronization.base.SolverNameUtil; -import org.simantics.structural.synchronization.utils.ComponentFactory; -import org.simantics.structural.synchronization.utils.MappingBase; -import org.simantics.structural.synchronization.utils.Solver; - -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.longs.AbstractLongList; -import it.unimi.dsi.fastutil.longs.AbstractLongSet; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet; - -public class SpreadsheetBook implements StandardNodeManagerSupport, SpreadsheetElement, Serializable, SheetNode, Solver, SolverNameUtil, ComponentFactory, ModuleUpdaterFactoryBase { - - private static final long serialVersionUID = 7417208688311691396L; - - public Serializable NotAvailableError = new Serializable() { - private static final long serialVersionUID = 2535371785498129460L; - }; - - public Long2ObjectOpenHashMap referenceMap = new Long2ObjectOpenHashMap<>(); - - private Int2ObjectArrayMap styles = new Int2ObjectArrayMap<>(); -// public ObjectArrayList styles = new ObjectArrayList(); - public ArrayList sheets = new ArrayList(); - - private SpreadsheetMapping mapping; - - - private int idCounter = 1; - - public SpreadsheetBook() { - getNewId(this); - mapping = new SpreadsheetMapping(new SheetLineComponent("")); - } - - public Map children = new HashMap<>(); - - private boolean iterationEnabled; - - public int getNewId(SpreadsheetElement element) { - int result = idCounter++; - children.put(result, element); - return result; - } - - public long getEngineIndex(SpreadsheetEngine engine) { - for(int i=0;i getChildren(SheetNode node) { - return node.getChildren(); - } - - @Override - public Map getProperties(SheetNode node) { - return node.getProperties(); - } - - @Override - public String getName() { - return ""; - } - - @Override - public Map getChildren() { - Map result = new HashMap(); - for(SpreadsheetEngine engine : sheets) - result.put(engine.getName(), engine); - return result; - } - - @Override - public Map getProperties() { - return Collections.emptyMap(); - } - - public SpreadsheetCell get(String sheet, int row, int column) { - SpreadsheetEngine engine = getEngine(sheet); - if(engine == null) return null; - SpreadsheetLine line = engine.getLine(row); - if(line == null) return null; - if(line.cells.size() <= column) return null; - return line.cells.get(column); - } - - public SpreadsheetCell get(SpreadsheetEngine engine, int row, int column) { - SpreadsheetLine line = engine.getLine(row); - if(line == null) return null; - if(line.cells.size() <= column) return null; - return line.cells.get(column); - } - - public SpreadsheetEngine getEngine(String sheet) { - for(SpreadsheetEngine engine : sheets) - if(sheet.equals(engine.getName())) return engine; - return null; - } - - @Override - public ModuleUpdaterBase createUpdater(String id) throws DatabaseException { - if("http://www.simantics.org/Spreadsheet-1.2/Line".equals(id)) - return new LineUpdater(id); - else if("http://www.simantics.org/Spreadsheet-1.2/LineNode".equals(id)) - return new LineNodeUpdater(id); - else if ("http://www.simantics.org/Spreadsheet-1.2/Style".equals(id)) - return new StyleUpdater(id); - else if("http://www.simantics.org/Spreadsheet-1.2/Lines".equals(id)) - return new NullUpdater(id); - else if("http://www.simantics.org/Spreadsheet-1.2/Spreadsheet".equals(id)) - return new NullUpdater(id); - else if("http://www.simantics.org/Spreadsheet-1.2/Book".equals(id)) - return new NullUpdater(id); - else - throw new IllegalStateException("createUpdater " + id); - } - - @Override - public SheetLineComponent create(String uid) { - return new SheetLineComponent(uid); - } - - @Override - public String getFreshName(String parentName, String name) { - return parentName + "/" + name; - } - - @Override - public String ensureNameIsVariationOf(String parentName, int id, String name) { - if (parentName.isEmpty()) - return name; - return parentName + "/" + name; - } - - final static int COMP_ROOT_POS = "COMP_ROOT/".length(); - - @Override - public int getId(String name) { - - if("COMP_ROOT".equals(name)) return 1; - - String path = name.substring(COMP_ROOT_POS); - String[] parts = path.split("/"); - Object o = resolve(parts, 0); - if(o instanceof SpreadsheetLines) { - return ((SpreadsheetLines)o).getId(); - } else if(o instanceof SpreadsheetLine) { - return ((SpreadsheetLine)o).getId(); - } else if(o instanceof SpreadsheetEngine) { - return ((SpreadsheetEngine)o).getId(); - } else if (o instanceof SpreadsheetStyle) { - return ((SpreadsheetStyle) o).getId(); - } - - throw new IllegalStateException("Resolved object for parts " + Arrays.toString(parts) + " is not the right type! It is " + o); - - } - - Object resolve(String[] parts, int index) { - String part = parts[index]; - if (part.startsWith("Style")) { - for (SpreadsheetStyle style : styles.values()) { - if (style.name.equals(part)) { - return style; - } - } - } - SpreadsheetEngine engine = getEngine(part); - if(engine == null) return 0; - if(index == parts.length-1) return engine; - else return engine.resolve(parts, index+1); - } - - @Override - public String getName(int id) { - if(id == -2) return "http://www.simantics.org/Spreadsheet-1.2/Book"; - else if(id == -3) return "http://www.simantics.org/Spreadsheet-1.2/Spreadsheet"; - else if(id == -4) return "http://www.simantics.org/Spreadsheet-1.2/Lines"; - else if(id == -5) - return "http://www.simantics.org/Spreadsheet-1.2/LineNode"; - else if (id == -6) - return "http://www.simantics.org/Spreadsheet-1.2/Line"; - else if(id == -7) - return "http://www.simantics.org/Spreadsheet-1.2/Style"; - else return "" + id; - } - - @Override - public int getModuleType(int id) { - Serializable s = children.get(id); - if(s instanceof SpreadsheetBook) return -2; - else if(s instanceof SpreadsheetEngine) return -3; - else if(s instanceof SpreadsheetLines) { - if("Lines".equals(((SpreadsheetLines) s).getName())) - return -4; - else - return -5; - } - else if(s instanceof SpreadsheetLine) - return -6; - else if (s instanceof SpreadsheetStyle) - return -7; - else throw new IllegalStateException(); - } - - @Override - public void remove(int id) { - - SpreadsheetElement child = children.get(id); - Optional parent = child.getParent(); - - if (parent.isPresent()) { - parent.get().remove(child); - children.remove(id); - } - } - - @Override - public void addSubprocess(String name, String subprocessType) { - ensureSubprocess(name); - } - - public T ensureSubprocess(String name) { - String[] parts = name.split("/"); - if(parts.length == 2) { - SpreadsheetEngine engine = getEngine(parts[1]); - if(engine == null) { - engine = new SpreadsheetEngine(this, parts[1]); - sheets.add(engine); - } - return (T)engine; - } else if (parts.length > 2) { - SpreadsheetEngine engine = getEngine(parts[1]); - return (T)engine.ensureSubprocess(parts, 2); - } - throw new IllegalStateException(); - } - - - @Override - public void includeSubprocess(String parentName, String subprocessName) { - // Nop - } - - @Override - public T getConcreteSolver() { - return (T)this; - } - - @Override - public void accept(SpreadsheetVisitor v) { - v.visit(this); - } - - //Recursively find all SpreadsheetCells, invalidate them and return them all as a set - public Set invalidate(SpreadsheetCell cell) { - Set result = new HashSet<>(); - result.add(cell); - cell.invalidate(); - long refKey = cell.makeReferenceKey(); - AbstractLongSet refs = referenceMap.remove(refKey); - if(refs == null) return result; - for(long ref : refs) { - long sheet = ref >> 40; - long row = (ref >> 20) & 0xFFFFF; - long col = (ref) & 0xFFFFF; - SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col); - result.addAll(invalidate(referer)); - } - return result; - } - - @Deprecated - public List invalidateShallow(SpreadsheetCell cell) { - ArrayList result = new ArrayList<>(); - result.add(cell); - cell.invalidate(); - long refKey = cell.makeReferenceKey(); - AbstractLongSet refs = referenceMap.remove(refKey); - if(refs == null) return result; - for(long ref : refs) { - long sheet = ref >> 40; - long row = (ref >> 20) & 0xFFFFF; - long col = (ref) & 0xFFFFF; - SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col); - invalidate(referer); - result.add(referer); - } - return result; - } - - public void addStyle(SpreadsheetStyle style) { - if (style.name == null) { - new Exception("Trying to add style to book without name!!").printStackTrace(); - return; - } - style.setSynchronizationId(getNewId(style)); - styles.put(style.getStyleId(), style); - } - - public SpreadsheetStyle getStyle(int styleId) { - return styles.get(styleId); - } - - public MappingBase getMapping() { - return mapping; - } - - @Override - public Optional getParent() { - return Optional.empty(); - } - - @Override - public Collection getSpreadsheetChildren() { - return children.values(); - } - - @Override - public void remove(SpreadsheetElement child) { - // TODO Auto-generated method stub - - } - - public void setIterationEnabled(boolean value) { - this.iterationEnabled = value; - } - - public boolean isIterationEnabled() { - return iterationEnabled; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java deleted file mode 100644 index 0ee66cf07..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java +++ /dev/null @@ -1,224 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.simantics.spreadsheet.graph.formula.FormulaError2; -import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; -import org.simantics.spreadsheet.resource.SpreadsheetResource; -import org.simantics.spreadsheet.util.SpreadsheetUtils; - -public class SpreadsheetCell implements SpreadsheetElement, SheetNode { - - private static final long serialVersionUID = 6616793596542239339L; - - public static SpreadsheetCell EMPTY; - - static { - EMPTY = new SpreadsheetCell(null, -1); - EMPTY.setContent(""); - EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId()); - } - - private boolean inProgress = false; - private int iterations = 0; - - final private SpreadsheetLine line; - final private int column; - int style; - Object content; - final private Map properties; - - public SpreadsheetCell(SpreadsheetLine line, int column) { - this.properties = createProperties(); - this.line = line; - this.column = column; - } - - //All SpreadsheetCells have these properties - create them when object is created - private Map createProperties() { - Map p = new HashMap<>(); - p.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell)); - p.put("content", new SpreadsheetCellContent(this)); - p.put("style", new SpreadsheetCellStyle(this)); - p.put("editable", new SpreadsheetCellEditable(this)); - return p; - } - - public boolean hasExpression() { - return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; - } - - public void setContent(Object newContent) { -// if(newContent != null) { -// if (!(newContent instanceof Serializable)) { -// throw new AssertionError("content not instanceof Serializable but it is " + newContent.getClass().getSimpleName()); -// } -// } - if (GraphUI.DEBUG) - System.out.println("SpreadsheetCell.setContent "+ this + " " + newContent); - this.content = newContent; - } - - @Override - public String getName() { - return SpreadsheetUtils.cellName(line.row, column); - } - - @Override - public Map getChildren() { - return Collections.emptyMap(); - } - - private static String[] keys = { "typeURI", "content" }; - - @Override - public Map getProperties() { - if (GraphUI.DEBUG) - System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style); - return properties; //Return this SpreadsheetCells's properties, rather than a new HashMap - } - - public SpreadsheetBook getBook() { - return line.getEngine().getBook(); - } - - public SpreadsheetEngine getEngine() { - return line.getEngine(); - } - - public T evaluate(SpreadsheetEvaluationEnvironment env) { - return evaluate(env, null); - } - - public T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) { -// System.err.println(getEngine().getName() + ":" + getName() + ": evaluate"); - if(caller != null) - caller.addReference(makeReferenceKey()); - if(content instanceof SpreadsheetFormula) { - SpreadsheetFormula f = (SpreadsheetFormula)content; - if(f.result == null) { - CellValueVisitor visitor = new CellValueVisitor(env, this); - AstValue value = ((SpreadsheetFormula)content).value; - if(this.inProgress == true) this.iterations++; - - if(!env.getBook().isIterationEnabled()){ - if(this.inProgress == false){ - this.inProgress = true; - f.result = value.accept(visitor); - } - else f.result = FormulaError2.CIRCULAR_REF.getString(); - } - else if(this.iterations getParent() { - return Optional.of(line); - } - - @Override - public List getSpreadsheetChildren() { - return Collections.emptyList(); - } - - @Override - public void remove(SpreadsheetElement child) { - // TODO Auto-generated method stub - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + column; - result = prime * result + ((line == null) ? 0 : line.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SpreadsheetCell other = (SpreadsheetCell) obj; - if (column != other.column) - return false; - if (line == null) { - if (other.line != null) - return false; - } else if (!line.equals(other.line)) - return false; - return true; - } - - public void setStyle(int styleId) { - this.style = styleId; - } - - public int getStyle() { - return style; - } - - public Object getContent() { - return content; - } - - public static SpreadsheetCell empty(SpreadsheetLine line, int column) { - SpreadsheetCell cell = new SpreadsheetCell(line, column); - cell.setContent(""); - cell.setStyle(SpreadsheetStyle.empty().getStyleId()); - return cell; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java deleted file mode 100644 index 364e9261b..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.graph.parser.ast.AstRange; - -@SuppressWarnings("rawtypes") -public class SpreadsheetEngine implements SpreadsheetElement, SheetNode { - - private static final long serialVersionUID = -5246063647558595642L; - - private static final String LINES = "Lines"; - - private final SpreadsheetBook book; - private final String name; - private final int id; - - public SpreadsheetLines lines; - - transient public Map rangeCache; - - public Map getRangeCache() { - if(rangeCache == null) rangeCache = new HashMap(); - return rangeCache; - } - - public Object getCachedRange(AstRange range) { - if(range.sheetName != null) return null; - return getRangeCache().get(range.first + ":" + range.second); - } - - public void cacheRange(AstRange range, Object value) { - if(range.sheetName != null) return; - getRangeCache().put(range.first + ":" + range.second, value); - } - - public SpreadsheetEngine(SpreadsheetBook book, String name) { - this.book = book; - this.name = name; - this.id = book.getNewId(this); - this.lines = new SpreadsheetLines(this, LINES); - } - - public SpreadsheetBook getBook() { - return book; - } - - public int getId() { - return id; - } - - Object resolve(String[] parts, int index) { - - String part = parts[index]; - if(!part.equals(LINES)) return null; - - if(index == parts.length-1) return lines; - - return lines.resolve(parts, index+1); - - } - - @Override - public String getName() { - return name; - } - - @Override - public Map getChildren() { - return Collections.singletonMap(LINES, lines); - } - - @Override - public Map getProperties() { - return Collections.emptyMap(); - } - - public Object ensureSubprocess(String[] path, int index) { - - String name = path[index]; - if(!LINES.equals(name)) throw new IllegalStateException(); - if(index == path.length - 1) return lines; - return lines.ensureSubprocess(path, index+1); - - } - - public SpreadsheetLine getLine(int row) { - assert(lines.nodes.size() == 1); - SpreadsheetLines root = lines.nodes.values().iterator().next(); - return root.getLine(row); - } - - @Override - public void accept(SpreadsheetVisitor v) { - v.visit(this); - } - - public Range actualRange(Range r) { - if(r.isFullRows()) { - SpreadsheetLines root = lines.nodes.values().iterator().next(); - Range result = new Range(r); - result.startRow = 0; - result.endRow = root.getMaxRow(); - return result; - } else { - return r; - } - } - - @Override - public Optional getParent() { - return Optional.of(book); - } - - @Override - public List getSpreadsheetChildren() { - return Collections.singletonList(lines); - } - - @Override - public void remove(SpreadsheetElement child) { - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((book == null) ? 0 : book.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SpreadsheetEngine other = (SpreadsheetEngine) obj; - if (book == null) { - if (other.book != null) - return false; - } else if (!book.equals(other.book)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java index 032acfcfc..35a05d7aa 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java @@ -23,28 +23,52 @@ import org.simantics.datatypes.utils.BTree; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.BinaryRead; import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.LiteralFileUtil; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ServiceException; import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.procedure.Listener; import org.simantics.db.service.ClusteringSupport; import org.simantics.layer0.Layer0; +import org.simantics.scl.compiler.commands.CommandSession; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function; +import org.simantics.scl.runtime.tuple.Tuple0; import org.simantics.scl.runtime.tuple.Tuple2; import org.simantics.simulator.toolkit.StandardRealm; +import org.simantics.spreadsheet.CellEditor; +import org.simantics.spreadsheet.ExternalRef; +import org.simantics.spreadsheet.OperationMode; import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.Transaction; import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler; import org.simantics.spreadsheet.resource.SpreadsheetResource; +import org.simantics.spreadsheet.solver.SheetNode; +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetCell; +import org.simantics.spreadsheet.solver.SpreadsheetEngine; +import org.simantics.spreadsheet.solver.SpreadsheetLine; +import org.simantics.spreadsheet.solver.SpreadsheetStyle; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.structural.synchronization.client.Synchronizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.iterator.TObjectIntIterator; import gnu.trove.map.hash.TObjectIntHashMap; public class SpreadsheetGraphUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetGraphUtils.class); + public static File extractInitialCondition(ReadGraph graph, Resource ic) throws DatabaseException, IOException { SpreadsheetResource SR = SpreadsheetResource.getInstance(graph); @@ -168,12 +192,6 @@ public class SpreadsheetGraphUtils { SpreadsheetSynchronizationEventHandler handler = new SpreadsheetSynchronizationEventHandler(graph, book); -// System.err.println("sessionName : " + sessionName); -// System.err.println("bookResource : " + graph.getURI(bookResource)); -// System.err.println("configuration : " + configuration.getURI(graph)); -// System.err.println("realm : " + realm); -// System.err.println("book : " + book); - if (changeFlags == null) { synchronizer.fullSynchronization(configuration, handler); } else { @@ -193,14 +211,6 @@ public class SpreadsheetGraphUtils { synchronizer.partialSynchronization(configuration, handler, changeFlags); } -// book.accept(new InvalidateAll()); -// realm.getNodeManager().refreshVariables(); -// mapping.currentRevision = synchronizer.getHeadRevisionId(); -// mapping.setTrustUids(true); - // Clean up queries -// QueryControl qc = g.getService(QueryControl.class); -// qc.flush(g); -// TimeLogger.log("Finished full synchronization"); realm.getNodeManager().fireNodeListeners(); return handler.getDidChanges(); @@ -218,7 +228,7 @@ public class SpreadsheetGraphUtils { SpreadsheetEngine engine = book.getEngine(sheetName); if(engine == null) return null; - Range r = SpreadsheetUtils.decodeCellAbsolute(cellName); + Range r = Spreadsheets.decodeCellAbsolute(cellName); SpreadsheetLine line = engine.getLine(r.startRow); if(line == null) return null; @@ -233,200 +243,6 @@ public class SpreadsheetGraphUtils { } - public static boolean asBoolean(Object object) { - if(object instanceof Boolean) return (Boolean)object; - else if(object instanceof Number) return ((Number)object).doubleValue() != 0; - else if(object instanceof Variant) return asBoolean(((Variant)object).getValue()); - else if(object instanceof String) { - Double d = asDoubleWhereEmptyStringIsZero((String)object); - if(d==null) return false; - else return d != 0; - } - return false; - } - - public static String asString(Object object) { - if(object == null) return ""; - if(object instanceof String) return (String)object; - if(object instanceof Number) { - double dVal = ((Number)object).doubleValue(); - if(dVal == Math.floor(dVal)){ - return ""+((Number)object).intValue(); - } else { - return object.toString(); - } - } - else if(object instanceof Variant) { - Object o = ((Variant) object).getValue(); - if(o instanceof String) return (String)o; - else if(o instanceof Number) asString((Number)o); - else return o.toString(); - } - return object.toString(); - } - - public static Double asDoubleWhereEmptyStringIsZero(Object object){ - if(object instanceof Number) - return ((Number)object).doubleValue(); - else if(object instanceof String) { - try { - if(((String)object).isEmpty()) - return 0.0; - return Double.parseDouble((String)object); - } catch (NumberFormatException e) { - return null; - } - } else if(object instanceof Variant) { - Object o = ((Variant) object).getValue(); - return asDoubleWhereEmptyStringIsZero(o); - } else if (SpreadsheetCell.EMPTY == object) { - return null; - } - return null; - } - - public static double asNumber(Object object) { - if(object instanceof Number) { - return ((Number)object).doubleValue(); - } else if(object instanceof String) { - try { - String str = (String)object; - if(str.isEmpty()) return 0; - return Double.parseDouble((String)object); - } catch (NumberFormatException e) { - return 0; - } - } else if(object instanceof Variant) { - Object o = ((Variant) object).getValue(); - return asNumber(o); - } else if (SpreadsheetCell.EMPTY == object) { - return 0.0; - } - - return 0.0; - - } - - public static Number asValidNumber(Object object) { - if(object instanceof Number) { - return (Number)object; - } else if(object instanceof String) { - try { - return Double.parseDouble((String)object); - } catch (NumberFormatException e) { - return null; - } - } else if(object instanceof Variant) { - Object o = ((Variant) object).getValue(); - return asNumber(o); - } else if (SpreadsheetCell.EMPTY == object) { - return null; - } - - return null; - - } - - public static boolean matchCriteria(Object value, Object criteria) { - if(value==null || criteria==null) return false; - - if(value instanceof Variant){ - Double dVal = asDoubleWhereEmptyStringIsZero(value); - if(dVal==null) value = ((Variant)value).getValue(); - else value = dVal; - } - if(criteria instanceof Variant){ - Double dVal = asDoubleWhereEmptyStringIsZero(criteria); - if(dVal==null) criteria = ((Variant)criteria).getValue(); - else criteria = dVal; - } - - if(criteria instanceof Number && value instanceof Number) { - Number nc = (asNumber(criteria)); - Number nv = (asNumber(value)); - return nc.equals(nv); - } - if(criteria instanceof String){ - boolean nums = false; - Object valueObj = null; - if(value instanceof Number){ - valueObj = ((Number)value).doubleValue(); - nums = true; - } - else valueObj = value.toString(); - - String sc = criteria.toString(); - if(sc.length() >= 3){ - String oper = sc.substring(0, 2); - String criteriaStr = sc.substring(2); - Double criteriaNum = null; - try { - criteriaNum = Double.parseDouble(criteriaStr); - if(oper.equals("<>")){ - if(!nums) return true; - } - else if(!nums) return false; - nums = true; - } catch (NumberFormatException e){ - if(oper.equals("<>")){ - if(nums) return true; - } - else if(nums) return false; - nums = false; - } - - if(oper.equals(">=")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) >= 0 ; - else return ((Number)valueObj).doubleValue() >= criteriaNum; - } else if(oper.equals("<=")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) <= 0 ; - else return ((Number)valueObj).doubleValue() <= criteriaNum; - } else if(oper.equals("<>")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) != 0 ; - else return ((Number)valueObj).doubleValue() != criteriaNum; - } - } - if(sc.length() >= 2){ - String oper = sc.substring(0, 1); - String criteriaStr = sc.substring(1); - Double criteriaNum = null; - - try { - criteriaNum = Double.parseDouble(criteriaStr); - if(!nums) return false; - nums = true; - } catch (NumberFormatException e){ - if(nums) return false; - nums = false; - } - if(oper.equals("<")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) < 0; - else return ((Number)valueObj).doubleValue() < criteriaNum; - } else if(oper.equals(">")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) > 0; - else return ((Number)valueObj).doubleValue() > criteriaNum; - } else if(oper.equals("=")){ - if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) == 0; - else return ((Number)valueObj).doubleValue() == criteriaNum; - } - } - return sc.equals(valueObj); - } - else if (criteria instanceof Number){ - return false; - } - throw new IllegalStateException(); - } - - public static boolean excelEquals(Object left, Object right) { - if(left instanceof String) { - if(right instanceof String) { - return ((String) left).toLowerCase().equals(((String) right).toLowerCase()); - } - } - return left.equals(right); - } - public static List possibleConfigurationCellVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException { List rowVariables = possibleConfigurationLineVariables(graph, sheet, range); @@ -521,7 +337,7 @@ public class SpreadsheetGraphUtils { private static boolean variableInRange(ReadGraph graph, Variable child, Range range) throws DatabaseException { String name = child.getName(graph); - Range childRange = SpreadsheetUtils.decodeCellAbsolute(name); + Range childRange = Spreadsheets.decodeCellAbsolute(name); // System.out.print(" and range " + childRange); if (childRange != null && range.contains(childRange)) { // System.out.println(" => range.contains(childRange) = true"); @@ -566,7 +382,7 @@ public class SpreadsheetGraphUtils { for (int rowNumber = range.startRow; rowNumber <= range.endRow; rowNumber++) { Variable row = rowIterator.next(); for (int colNumber = range.startColumn; colNumber <= range.endColumn; colNumber++) { - String location = SpreadsheetUtils.cellName(rowNumber, colNumber); + String location = Spreadsheets.cellName(rowNumber, colNumber); defaultCreateCell(graph, row, location, new Variant(Bindings.STRING, "")); } } @@ -670,5 +486,169 @@ public class SpreadsheetGraphUtils { SpreadsheetGraphUtils.saveInitialCondition(graph, run, root, "Initial"); return run; } + + public static Variant extRefVariable(ReadGraph graph, Variable var) throws DatabaseException { + return new Variant(Bindings.VOID, new ExternalRefVariable(graph, var)); + } + + static class ExternalRefVariable implements ExternalRef { + + final private String uri; + + public ExternalRefVariable(ReadGraph graph, Variable variable) throws DatabaseException { + this.uri = variable.getURI(graph); + } + + @Override + public void listen(Object context, ExternalRefListener listener) { + Simantics.getSession().asyncRequest(new UnaryRead(uri) { + + @Override + public Variant perform(ReadGraph graph) throws DatabaseException { + Variable variable = Variables.getVariable(graph, parameter); + return variable.getVariantValue(graph); + } + + }, new Listener() { + + @Override + public void execute(Variant result) { + listener.newValue(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Error while evaluating variable value", t); + } + + @Override + public boolean isDisposed() { + return listener.isDisposed(); + } + + }); + } + + @Override + public void modify(Object context, Variant newValue) { + + Simantics.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Variable variable = Variables.getVariable(graph, uri); + variable.setValue(graph, newValue); + } + }); + + } + + } + + public static Variant extRefActiveVariable(ReadGraph graph, Variable var) throws DatabaseException { + return new Variant(Bindings.VOID, new ExternalRefActiveVariable(graph, var)); + } + + static class ExternalRefActiveVariable implements ExternalRef { + + final private String uri; + + public ExternalRefActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException { + this.uri = variable.getURI(graph); + } + + @Override + public void listen(Object context, ExternalRefListener listener) { + Simantics.getSession().asyncRequest(new BinaryRead((String)context, uri) { + + @Override + public Variant perform(ReadGraph graph) throws DatabaseException { + Variable contextVariable = Variables.getVariable(graph, parameter); + Variable configVariable = Variables.getVariable(graph, parameter2); + Variable activeVariable = Variables.switchPossibleContext(graph, configVariable, contextVariable.getRepresents(graph)); + if(activeVariable == null) return Variant.ofInstance("Could not resolve " + configVariable.getURI(graph) + " for " + contextVariable.getURI(graph)); + return activeVariable.getVariantValue(graph); + } + }, new Listener() { + + @Override + public void execute(Variant result) { + listener.newValue(result); + } + + @Override + public void exception(Throwable t) { + LOGGER.error("Error while evaluating variable value, context = " + context + " uri=" + uri, t); + } + + @Override + public boolean isDisposed() { + return listener.isDisposed(); + } + + }); + } + + @Override + public void modify(Object context, Variant newValue) { + + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Variable contextVariable = Variables.getVariable(graph, (String)context); + Variable configVariable = Variables.getVariable(graph,uri); + Variable activeVariable = Variables.switchPossibleContext(graph, configVariable, contextVariable.getRepresents(graph)); + if(activeVariable == null) return; + activeVariable.setValue(graph, newValue.getValue(), newValue.getBinding()); + } + }); + + } + + } + + public static CellEditor cellEditor(ReadGraph graph, Resource sheet) throws DatabaseException { + SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph); + Variable sheetVariable = Variables.getVariable(graph, sheet); + return sheetVariable.getPropertyValue(graph, SHEET.cellEditor); + } + + public static final String SPREADSHEET_TRANSACTION = "spreadsheetTransaction"; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Object syncExec(CellEditor editor, OperationMode mode, Function fun) throws InterruptedException { + + Transaction tr = editor.startTransaction(mode); + + SCLContext context = SCLContext.getCurrent(); + Transaction oldTransaction = (Transaction)context.put(SPREADSHEET_TRANSACTION, tr); + + Object result = null; + + try { + + result = fun.apply(Tuple0.INSTANCE); + + } finally { + + tr.commit(); + + context.put(SPREADSHEET_TRANSACTION, oldTransaction); + + } + + return result; + + } + + public static int cellColumn(ReadGraph graph, Variable cell) { + if(cell instanceof StandardGraphChildVariable) { + StandardGraphChildVariable sgcv = (StandardGraphChildVariable)cell; + SpreadsheetCell sc = (SpreadsheetCell)sgcv.node.node; + return sc.getColumn(); + } + throw new IllegalStateException("Expected StandardGraphChildVariable, got " + cell.getClass().getName()); + } + } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java deleted file mode 100644 index ef6937ff5..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.resource.SpreadsheetResource; -import org.simantics.spreadsheet.util.SpreadsheetUtils; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -public class SpreadsheetLine implements SpreadsheetElement, SheetNode { - - private static final long serialVersionUID = -304574098117404663L; - - final private SpreadsheetLines parent; - final public int row; - int id; - - public ObjectArrayList cells = new ObjectArrayList<>(); - - public SpreadsheetLine(SpreadsheetLines parent, int row) { - this.parent = parent; - this.row = row; - this.id = getEngine().getBook().getNewId(this); -// getEngine().registerRow(row, this); - } - - public int getId() { - return id; - } - - public SpreadsheetEngine getEngine() { -// if(parent instanceof SpreadsheetEngine) -// return (SpreadsheetEngine)parent; - return ((SpreadsheetLines)parent).getEngine(); - } - - @Override - public String getName() { - return "Row"+row; - } - - @Override - public Map getChildren() { - String rowName = ""+row; - Map result = new HashMap<>(); - for(int i=0;i getParent() { - return Optional.of(parent); - } - - @Override - public List getSpreadsheetChildren() { - return cells; - } - - @Override - public void remove(SpreadsheetCell child) { - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((parent == null) ? 0 : parent.hashCode()); - result = prime * result + row; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SpreadsheetLine other = (SpreadsheetLine) obj; - if (parent == null) { - if (other.parent != null) - return false; - } else if (!parent.equals(other.parent)) - return false; - if (row != other.row) - return false; - return true; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java deleted file mode 100644 index b3d6f0973..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Optional; - -import org.simantics.spreadsheet.resource.SpreadsheetResource; - -import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap; - -public class SpreadsheetLines implements SpreadsheetElement, SheetNode { - - private static final long serialVersionUID = -3615335969248723486L; - - private final int id; - private SpreadsheetEngine parent; - private String name; - public Int2ObjectAVLTreeMap nodes = new Int2ObjectAVLTreeMap(); - public Int2ObjectAVLTreeMap lines = new Int2ObjectAVLTreeMap(); - public int[] keys; - - public SpreadsheetLines(SpreadsheetEngine parent, String name) { - this.parent = parent; - this.name = name; - id = getEngine().getBook().getNewId(this); - } - - public SpreadsheetEngine getEngine() { - return parent; - } - - public int getId() { - return id; - } - - @Override - public String getName() { - return name; - } - - @Override - public Map getChildren() { - Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap(); - result.putAll(nodes); - result.putAll(lines); - return result; - } - - @Override - public Map getProperties() { - return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Lines)); - } - - Object resolve(String[] parts, int index) { - - String part = parts[index]; - if(part.charAt(0) == 'R') { - int indx = Integer.parseInt(part.substring(3)); - SpreadsheetLine line = lines.get(-indx); - if(line != null) { - if(index == parts.length-1) return line; - else return line.resolve(parts, index+1); - } - } else { - int indx = Integer.parseInt(part); - SpreadsheetLines node = nodes.get(indx); - if(node != null) { - if(index == parts.length-1) return node; - else return node.resolve(parts, index+1); - } - } - - return null; - - } - - public Object ensureSubprocess(String[] path, int index) { - - String name = path[index]; - - int i = Integer.parseInt(name); - SpreadsheetLines line = nodes.get(i); - if(line == null) { - line = new SpreadsheetLines(parent, "" + i); - nodes.put(i, line); - } - - if(index == path.length - 1) { - return line; - } else { - return line.ensureSubprocess(path, index+1); - } - - } - - public void setKeys(int[] keys) { - this.keys = keys; - } - - @Override - public void accept(SpreadsheetVisitor v) { - v.visit(this); - } - - public String getPath() { - return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName(); - } - - private int getKey(int index) { - return keys[2*index+1]; - } - - private int getChild(int index) { - return keys[2*index]; - } - - /* - * [(child,key),...,key) - * - */ - public SpreadsheetLine getLine(int k) { - - int i=1; - int n = (keys.length - 1) / 2; - - while(i <= n && k > getKey(i-1)) i++; - - if(i <= n && k == getKey(i-1)) { - return lines.get(-k); - } - - int nodeName = getChild(i-1); - SpreadsheetLines node = nodes.get(nodeName); - if(node == null) return null; - return node.getLine(k); - - } - - public int getMaxRow() { - // if keys == null then this is the root of BTree which has only one child - if (keys == null) { - int maxRow = 0; - for (SpreadsheetLines node : nodes.values()) { - int row = node.getMaxRow(); - if (row > maxRow) - maxRow = row; - } - return maxRow; - } - int largestChild = keys[keys.length-1]; - if(largestChild > 0) { - SpreadsheetLines child = nodes.get(largestChild); - return child.getMaxRow(); - } else { - return keys[keys.length-2]; - } - } - - @Override - public Optional getParent() { - return Optional.of(parent); - } - - @Override - public Collection getSpreadsheetChildren() { - return lines.values(); - } - - @Override - public void remove(SpreadsheetLine child) { - lines.remove(-child.row); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((parent == null) ? 0 : parent.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SpreadsheetLines other = (SpreadsheetLines) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (parent == null) { - if (other.parent != null) - return false; - } else if (!parent.equals(other.parent)) - return false; - return true; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java deleted file mode 100644 index 64079d2b0..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.io.Serializable; - -import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent; -import org.simantics.structural.synchronization.utils.ComponentFactory; -import org.simantics.structural.synchronization.utils.MappingBase; -import org.simantics.structural.synchronization.utils.Solver; -import org.simantics.structural.synchronization.utils.StateUndoContextBase; - -public class SpreadsheetMapping extends MappingBase implements Serializable { - - private static final long serialVersionUID = -7556699663877911393L; - - final SheetLineComponent configuration; - - public SpreadsheetMapping(SheetLineComponent configuration) { - super(configuration, true); - this.configuration = configuration; - } - - @Override - public SheetLineComponent getConfiguration() { - return configuration; - } - - @Override - public StateUndoContextBase createUndoContext() { - return new StateUndoContextBase() { - - @Override - public void saveState(Solver solver, int componentId, String uid) { - } - - @Override - public boolean loadState(Solver solver, int componentId, String uid) { - return false; - } - }; - } - - @Override - public ComponentFactory createComponentFactory() { - return new ComponentFactory() { - - @Override - public SheetLineComponent create(String uid) { - return new SheetLineComponent(uid); - } - - }; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java deleted file mode 100644 index b9a4f95cf..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.simantics.spreadsheet.graph; - -import java.io.Serializable; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.formula.FormulaError2; - -public class SpreadsheetMatrix implements Serializable { - - private static final long serialVersionUID = 5729700370527844640L; - - private int w; - private int h; - public Object[] values; - - public SpreadsheetMatrix(int w, int h) { - this.w = w; - this.h = h; - this.values = new Object[w*h]; - } - - public Object get(int row, int column) { - return values[w*row+column]; - } - - public void set(int row, int column, Object value) { - values[w*row+column] = value; - } - - public int getWidth() { - return w; - } - - public int getHeight() { - return h; - } - - public double sum() { - double result = 0; - for(int i=0;i { +public class SpreadsheetNodeManager extends StandardVariableNodeManager { public SpreadsheetNodeManager(SpreadsheetRealm realm) { super(realm, realm.getEngine()); + realm.getEngine().registerListener(new SpreadsheetBookListener() { + + @Override + public void cellsChanged(Collection cells) { + realm.asyncExec(new Runnable() { + @Override + public void run() { + for(SpreadsheetCell cell : cells) { + refreshVariable(new SpreadsheetCellContent(cell)); + Object content = cell.getContent(); + if(content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant) + refreshVariable(new SpreadsheetCellContentExpression(cell)); + } + } + }); + } + }); } static final Set COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component); @@ -52,6 +82,12 @@ public class SpreadsheetNodeManager extends StandardNodeManager dirtyNodeContents = findDirtyNodeContents(node); super.setValueAndFireSelectedListeners(node, value, binding, dirtyNodeContents); + if(value instanceof SpreadsheetFormula) { + SpreadsheetCellContent scc = (SpreadsheetCellContent)node; + SpreadsheetCellContentExpression scce = new SpreadsheetCellContentExpression(scc.cell); + // We need to also refresh the expression variable in this case + refreshVariable(scce); + } } //Find the cells that are used by this cell and their SpreadsheetContents, so that they can be marked as dirty later @@ -78,4 +114,18 @@ public class SpreadsheetNodeManager extends StandardNodeManager { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java deleted file mode 100644 index 4152188cd..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public class AndFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() == 0) - throw new IllegalStateException(); - Boolean finalResult = Boolean.TRUE; - for (int i = 0; i < args.values.size(); i++) { - Object res = (args.values.get(i).accept(visitor)); - FormulaError2 err = FormulaError2.forObject(res); - if(err!=null) return err.getString(); - - if ((res instanceof Boolean && !((Boolean)res)) || !SpreadsheetGraphUtils.asBoolean(res)) - finalResult = Boolean.FALSE; - } - return finalResult; - } -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java deleted file mode 100644 index b8ca32e7f..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; - -public class AverageFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() == 0) - throw new IllegalStateException(); - Double sum = 0.0; - double count = 0.0; - for(AstValue value : args.values){ - Object res = value.accept(visitor); - if (res instanceof SpreadsheetMatrix) { - Object value2 = ((SpreadsheetMatrix) res).sumWithFormulaError(); - if(value2 instanceof String) return value2; - - sum += ((Number)value2).doubleValue(); - count += ((SpreadsheetMatrix) res).countOfActualDoubleValues(); - } else { - FormulaError2 err = FormulaError2.forObject(res); - if(err!=null) return err.getString(); - - if(res instanceof Variant){ - Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res); - if(dVal==null) res = ((Variant)res).toString(); - else res = dVal; - } - - Double v = null; - if(res instanceof String && !res.equals("")){ - v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res); - } - else if(res instanceof Number) - v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res); - - if(v!=null){ - sum += v; - count++; - } - } - } - if(count==0.0) return FormulaError2.DIV0.getString(); - return sum/count; - } -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java deleted file mode 100644 index f34b89f5a..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstRange; - -public class CountifFormulaFunction implements CellFormulaFunction { - - @Override - public Integer evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() != 2) throw new IllegalStateException(); - - AstRange range = (AstRange) args.values.get(0); - SpreadsheetMatrix matrix = (SpreadsheetMatrix) range.accept(visitor); - Object crit = null; - try { - crit = args.values.get(1).accept(visitor); - } catch (IllegalStateException e){ - return 0; - } - - String criteria = SpreadsheetGraphUtils.asString(crit); - int result = 0; - for (Object value : matrix.values) { - if (SpreadsheetGraphUtils.matchCriteria(value, criteria)) - result++; - } - return Integer.valueOf(result); - } -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java deleted file mode 100644 index e47cbe839..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import java.util.HashMap; -import java.util.Map; -import org.apache.poi.util.Internal; -import org.simantics.databoard.binding.mutable.Variant; - -public enum FormulaError2{ - @Internal - _NO_ERROR(-1, "(no error)"),NULL(0x00, "#NULL"),DIV0(0x07,"#DIV/0!"),VALUE(0x0F, - "#VALUE!"),REF(0x17,"#REF!"),NAME(0x1D,"#NAME?"),NUM(0x24,"#NUM!"),NA(0x2A, "#N/A"), - CIRCULAR_REF(0xFFFFFFC4, "~CIRCULAR~REF~"),FUNCTION_NOT_IMPLEMENTED(0xFFFFFFE2,"~FUNCTION~NOT~IMPLEMENTED~"); - - private final String text; - //private final Integer longType; - //private final byte shortType; - - private static Map smap = new HashMap(); - - private FormulaError2(int type, String text){ - //this.longType = type; - //this.shortType = (byte)type; - this.text = text; - } - - static { - for(FormulaError2 error : values()) { - smap.put(error.getString(), error); - } - } - - public String getString(){ - return this.text; - } - - public static FormulaError2 forString(String errorName){ - FormulaError2 err = smap.get(errorName); - return err; - } - - public static FormulaError2 forObject(Object errorObj){ - if(errorObj instanceof Variant) - return forString(((Variant)errorObj).getValue().toString()); - else - return forString(errorObj.toString()); - } - - public static String handleErrorCall(Object value){ - if(value==null) return VALUE.getString(); - FormulaError2 error = FormulaError2.forObject(value); - if(error!=null) return error.getString(); - return VALUE.getString(); - } -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java deleted file mode 100644 index 886898501..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; - -public class GeomeanFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() == 0) - throw new IllegalStateException(); - double result = 1.0; - double count = 0.0; - for (AstValue value : args.values){ - Object r = value.accept(visitor); - if (r instanceof SpreadsheetMatrix) { - Object v = ((SpreadsheetMatrix) r).productWithFormulaError(); - if(v instanceof String) return v; - double dval = ((Number)v).doubleValue(); - if(dval!=0.0){ - result = result*dval; - count += ((SpreadsheetMatrix) r).countOfActualDoubleValues(); - } - } else { - FormulaError2 error = FormulaError2.forObject(r); - if(error!=null) return error.getString(); - - Number vNum = SpreadsheetGraphUtils.asValidNumber(r); - Double v = null; - if(vNum!=null) v = vNum.doubleValue(); - - if(v!=null){ - if(v<=0) return FormulaError2.NUM.getString(); - result = result*v; - count++; - } - } - } - if(result==0.0 || count==0.0) return FormulaError2.NUM.getString(); - return Double.valueOf(Math.pow(result, (1.0/count))); - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java deleted file mode 100644 index 409ae8bd2..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public class HlookupFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException(); - - Object lookupValue = args.values.get(0).accept(visitor); - boolean lookupIsString = lookupValue instanceof String; - - FormulaError2 error = FormulaError2.forObject(lookupValue); - if(error!=null) return error.getString(); - - if(lookupValue instanceof Variant){ - Object varVal = ((Variant)lookupValue).getValue(); - Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(varVal); - if(dVal==null) { - lookupValue = varVal.toString(); - lookupIsString = true; - } - else lookupValue = dVal; - } - - SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); - - boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true; - - if(array.values.length != 0){ - if(lookupIsString){ - Object obj = array.values[0]; - if(obj instanceof Variant) - obj = ((Variant)obj).getValue(); - if(SpreadsheetGraphUtils.asValidNumber(obj)!=null) - return FormulaError2.NA.getString(); - obj = obj.toString(); - String valStr = ((String)obj).toLowerCase(); - if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 ) - return FormulaError2.NA.getString(); - } - else if(lookupValue instanceof Number){ - Double d = ((Number)lookupValue).doubleValue(); - Number d2 = SpreadsheetGraphUtils.asValidNumber(array.values[0]); - if(d2==null || d<(d2.doubleValue())) - return FormulaError2.NA.getString(); - } - } - - Number rowIndexN = (Number) SpreadsheetGraphUtils.asValidNumber(args.values.get(2).accept(visitor)); - if(rowIndexN==null) return FormulaError2.REF.getString(); - int rowIndexNum = rowIndexN.intValue(); - if(rowIndexNum>array.getHeight()) return FormulaError2.REF.getString(); - - if (approximateMatch) { - Integer colPosOfLargestValSmallerThanLookUp = null; - if(lookupIsString){ - String largestValSmallerThanLookUp = null; - String ref = lookupValue.toString(); - String previousValue = null; - for(int i = 0; i < array.getWidth(); i++){ - Object val = array.get(0, i); - if(val instanceof Variant) - val = ((Variant)val).getValue(); - String currValue = val.toString(); - int currCompedToRef = currValue.compareTo(ref); - if(currCompedToRef>=0){ - if(i==0) - return array.get(rowIndexNum-1, i); - else if(previousValue.compareTo(ref) > currCompedToRef ) - return array.get(rowIndexNum-1, i); - else - return array.get(rowIndexNum - 1, i - 1); - } - if(colPosOfLargestValSmallerThanLookUp==null){ - colPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = currValue; - } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){ - colPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = currValue; - } - previousValue = currValue; - } - - } else { - double ref = SpreadsheetGraphUtils.asNumber(lookupValue); - double lastDiff = Double.MIN_VALUE; - Double largestValSmallerThanLookUp = null; - for (int i = 0; i < array.getWidth(); i++) { - Object value = array.get(0, i); - double n = SpreadsheetGraphUtils.asNumber(value); - double diff = n - ref; - if (diff >= 0) { - if (i == 0) - return array.get(rowIndexNum - 1, i); - else if (diff < -lastDiff) - return array.get(rowIndexNum - 1, i); - else - return array.get(rowIndexNum - 1, i - 1); - } - if(colPosOfLargestValSmallerThanLookUp==null){ - colPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = n; - } else if(largestValSmallerThanLookUp < n){ - colPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = n; - } - lastDiff = diff; - } - } - if(colPosOfLargestValSmallerThanLookUp!=null) return array.get(rowIndexNum - 1, colPosOfLargestValSmallerThanLookUp); - - } else { - - for (int i = 0; i < array.getWidth(); i++) { - Object value = array.get(0, i); - if(value instanceof Variant){ - if(lookupIsString) - value = ((Variant)value).getValue().toString(); - else - value = SpreadsheetGraphUtils.asNumber(value); - } - if (SpreadsheetGraphUtils.excelEquals(lookupValue, value)) { - return array.get(rowIndexNum - 1, i); - } - } - - } - - return FormulaError2.NA.getString(); - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java deleted file mode 100644 index e9b7c7bc8..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public class MatchFormulaFunction implements CellFormulaFunction{ - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() < 2 || args.values.size() > 3) throw new IllegalStateException(); - - SpreadsheetMatrix lookup_array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); - if(lookup_array.getWidth()!=1 && lookup_array.getHeight()!=1) return FormulaError2.NA.getString(); - - Object lookup_value = args.values.get(0).accept(visitor); - - int match_type = 1; - try{ - if(args.values.size()==3){ - int matchArg = ((Number)args.values.get(2).accept(visitor)).intValue(); - if(matchArg<0) - match_type = -1; - else if(matchArg>0) - match_type = 1; - else - match_type = 0; - } - } catch(Exception e) { - return FormulaError2.NA.getString(); - } - - boolean useHeight = false; - if(lookup_array.getWidth()==1) useHeight = true; - - int max = 0; - if(useHeight) max = lookup_array.getHeight(); - else max = lookup_array.getWidth(); - - Integer pos = null; - if(lookup_value instanceof Variant){ - Object obj = ((Variant)lookup_value).getValue(); - Number nVal = SpreadsheetGraphUtils.asValidNumber(obj); - if(nVal!=null) obj = nVal; - else obj = obj.toString(); - } - - if(lookup_value instanceof Number){ - Double previousValue = null; - Double closestMatch = null; - Double lookup = ((Number)lookup_value).doubleValue(); - int indexWhereCorrectOrderStartsAt = 0; - - if(match_type!=0) { - for(int i = 0; i < max;i++){ - Double currValue = null; - Number currNum; - if(useHeight){ - currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(i,0)); - } else { - currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(0,i)); - } - if(currNum!=null){ - currValue = currNum.doubleValue(); - if(currValue != null){ - if(previousValue!=null){ - if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValuepreviousValue) || (match_type==1 && currValue 0 && match_type==1) || (comp<0 && match_type==-1)){ - if(closestMatch==null && pos==null){ - closestMatch = currValue; - pos = i; - } - else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){ - closestMatch = currValue; - pos = i; - } - } - previousValue = currValue; - } - } - } - } - - else if(lookup_value instanceof String){ - String previousValue = null; - String closestMatch = null; - String lookup = (String)lookup_value; - int indexWhereCorrectOrderStartsAt = 0; - - if(match_type!=0) { - for(int i = 0; i < max;i++){ - String currValue = null; - Object obj; - if(useHeight){ - obj = lookup_array.get(i,0); - } else { - obj = lookup_array.get(0,i); - } - if(obj instanceof Variant){ - obj = ((Variant)obj).getValue(); - } - if(obj!=null && !(obj instanceof Number)){ - currValue = obj.toString(); - currValue = currValue.toLowerCase(); - } - if(currValue != null && !currValue.equals("")){ - if(previousValue!=null){ - if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)) - indexWhereCorrectOrderStartsAt = i; - else - break; - } - previousValue = currValue; - } - } - } - - int begin = indexWhereCorrectOrderStartsAt; - - for(int i = begin; i < max;i++){ - String currValue = null; - Object obj; - if(useHeight){ - obj = lookup_array.get(i,0); - } else { - obj = lookup_array.get(0,i); - } - if(obj instanceof Variant){ - obj = ((Variant)obj).getValue(); - } - if(obj!=null && !(obj instanceof Number)){ - currValue = obj.toString(); - currValue = currValue.toLowerCase(); - } - - if(currValue != null && !currValue.equals("")){ - if(previousValue==null) previousValue = currValue; - if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)){ - if(pos!=null) - return pos+1; - previousValue = currValue; - } - int comp = lookup.compareTo(currValue); - if(comp == 0){ - closestMatch = currValue; - pos = i; - } - else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){ - if(closestMatch==null && pos==null){ - closestMatch = currValue; - pos = i; - } - else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){ - closestMatch = currValue; - pos = i; - } - } - previousValue = currValue; - } - } - } - - if(pos==null)return FormulaError2.NA.getString(); - return pos+1; - } -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java deleted file mode 100644 index 94222117e..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public class OrFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() == 0) throw new IllegalStateException(); - - for (int i = 0; i < args.values.size(); i++) { - Object obj = null; - try { - obj = args.values.get(i).accept(visitor); - } catch (IllegalStateException e){ - return FormulaError2.NAME.getString(); - } - FormulaError2 error = FormulaError2.forObject(obj); - if(error!=null) return error.getString(); - - if (SpreadsheetGraphUtils.asBoolean(obj)) - return Boolean.TRUE; - } - return Boolean.FALSE; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java deleted file mode 100644 index 5f99cfc35..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.simantics.spreadsheet.graph.formula; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; - -public class VlookupFormulaFunction implements CellFormulaFunction { - - @Override - public Object evaluate(CellValueVisitor visitor, AstArgList args) { - if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException(); - - Object lookupValue = args.values.get(0).accept(visitor); - boolean lookupIsString = lookupValue instanceof String; - - FormulaError2 error = FormulaError2.forObject(lookupValue); - if(error!=null) return error.getString(); - - if(lookupValue instanceof Variant){ - Object varVal = ((Variant)lookupValue).getValue(); - Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(varVal); - if(dVal==null) { - lookupValue = varVal.toString(); - lookupIsString = true; - } - else lookupValue = dVal; - } - - - SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); - - boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true; - - boolean valueExists = false; - if(array.values.length != 0){ - for(int i = 0; i < array.getHeight(); i++){ - if(lookupIsString){ - Object obj = array.get(i,0); - if(obj instanceof Variant) - obj = ((Variant)obj).getValue(); - if(obj!=null && SpreadsheetGraphUtils.asValidNumber(obj)==null){ - obj = obj.toString(); - String valStr = ((String)obj).toLowerCase(); - if((lookupValue.toString().toLowerCase()).compareTo(valStr)>=0 ){ - valueExists = true; - break; - } - } - } - else if(lookupValue instanceof Number){ - Double d = ((Number)lookupValue).doubleValue(); - Number d2 = SpreadsheetGraphUtils.asValidNumber(array.get(i,0)); - if(d2!=null && d>=(d2.doubleValue())){ - valueExists = true; - break; - } - } - } -// if(lookupIsString){ -// Object obj = array.values[0]; -// if(obj instanceof Variant) -// obj = ((Variant)obj).getValue(); -// if(SpreadsheetGraphUtils.asValidNumber(obj)!=null) -// return FormulaError2.NA.getString(); -// obj = obj.toString(); -// String valStr = ((String)obj).toLowerCase(); -// if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 ) -// return FormulaError2.NA.getString(); -// } -// else if(lookupValue instanceof Number){ -// Double d = ((Number)lookupValue).doubleValue(); -// Number d2 = SpreadsheetGraphUtils.asValidNumber(array.values[0]); -// if(d2==null || d<(d2.doubleValue())) -// return FormulaError2.NA.getString(); -// } - } - if(!valueExists) return FormulaError2.NA.getString(); - - Number colIndexN = SpreadsheetGraphUtils.asValidNumber(args.values.get(2).accept(visitor)); - if(colIndexN==null) return FormulaError2.REF.getString(); - int colIndexNum = colIndexN.intValue(); - if(colIndexNum>array.getWidth()) return FormulaError2.REF.getString(); - - if (approximateMatch) { - Integer rowPosOfLargestValSmallerThanLookUp = null; - if(lookupIsString){ - String ref = lookupValue.toString().toLowerCase(); - String previousValue = null; - String largestValSmallerThanLookUp = null; - for(int i = 0; i < array.getHeight(); i++){ - Object val = array.get(i, 0); - if(val instanceof Variant) - val = ((Variant)val).getValue(); - String currValue = val.toString().toLowerCase(); - if(currValue.compareTo(ref)>0){ - if(i==0) - return array.get(i, colIndexNum-1); - else if(previousValue.compareTo(ref) > currValue.compareTo(ref)) - return array.get(i, colIndexNum-1); - else - return array.get(i - 1, colIndexNum - 1); - } - if(rowPosOfLargestValSmallerThanLookUp==null){ - rowPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = currValue; - } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){ - rowPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = currValue; - } - previousValue = currValue; - } - - } else { - double ref = SpreadsheetGraphUtils.asNumber(lookupValue); - double lastDiff = Double.MIN_VALUE; - Double largestValSmallerThanLookUp = null; - for (int i = 0; i < array.getHeight(); i++) { - Object value = array.get(i, 0); - double n = SpreadsheetGraphUtils.asNumber(value); - double diff = n - ref; - if (diff > 0) { - if (i == 0) - return array.get(i, colIndexNum - 1); - else if (diff < -lastDiff) - return array.get(i, colIndexNum - 1); - else - return array.get(i - 1, colIndexNum - 1); - } - if(rowPosOfLargestValSmallerThanLookUp==null){ - rowPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = n; - } else if(largestValSmallerThanLookUp < n){ - rowPosOfLargestValSmallerThanLookUp = i; - largestValSmallerThanLookUp = n; - } - lastDiff = diff; - } - } - - if(rowPosOfLargestValSmallerThanLookUp!=null) return array.get(rowPosOfLargestValSmallerThanLookUp, colIndexNum - 1); - - } else { - for (int i = 0; i < array.getHeight(); i++) { - Object value = array.get(i, 0); - if(value instanceof Variant){ - if(lookupIsString) - value = ((Variant)value).getValue().toString(); - else - value = SpreadsheetGraphUtils.asNumber(value); - } - if (SpreadsheetGraphUtils.excelEquals(lookupValue, value)) { - return array.get(i, colIndexNum - 1); - } - } - } - - return FormulaError2.NA.getString(); - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java index 98ef90231..490993441 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java @@ -54,22 +54,25 @@ import org.simantics.simulator.variable.exceptions.NodeManagerException; import org.simantics.spreadsheet.CellEditor; import org.simantics.spreadsheet.ClientModel; import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.graph.ExcelFormula; -import org.simantics.spreadsheet.graph.SheetNode; -import org.simantics.spreadsheet.graph.SpreadsheetBook; -import org.simantics.spreadsheet.graph.SpreadsheetCell; -import org.simantics.spreadsheet.graph.SpreadsheetCellContent; -import org.simantics.spreadsheet.graph.SpreadsheetFormula; +import org.simantics.spreadsheet.Transaction; import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant; import org.simantics.spreadsheet.graph.SpreadsheetSessionManager; -import org.simantics.spreadsheet.graph.SpreadsheetStyle; -import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder; import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter; -import org.simantics.spreadsheet.graph.parser.ParseException; -import org.simantics.spreadsheet.graph.parser.SheetFormulaParser; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; import org.simantics.spreadsheet.resource.SpreadsheetResource; +import org.simantics.spreadsheet.solver.SheetNode; +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetCell; +import org.simantics.spreadsheet.solver.SpreadsheetCellContent; +import org.simantics.spreadsheet.solver.SpreadsheetFormula; +import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant; +import org.simantics.spreadsheet.solver.SpreadsheetStyle; +import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder; +import org.simantics.spreadsheet.solver.formula.parser.ParseException; +import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; +import org.simantics.spreadsheet.synchronization.ExcelFormula; +import org.simantics.spreadsheet.synchronization.LineContentBean; +import org.simantics.spreadsheet.synchronization.LineContentBeanCell; import org.simantics.spreadsheet.util.SpreadsheetUtils; import gnu.trove.map.TMap; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/SpreadsheetRootVariable.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/SpreadsheetRootVariable.java index 5327d9b7c..aad988fb9 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/SpreadsheetRootVariable.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/SpreadsheetRootVariable.java @@ -20,6 +20,7 @@ import org.simantics.db.layer0.variable.VariableNode; import org.simantics.db.layer0.variable.Variables; import org.simantics.spreadsheet.Range; import org.simantics.spreadsheet.SheetVariables; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.common.matrix.VariantMatrix; import org.simantics.spreadsheet.graph.Ranges; import org.simantics.spreadsheet.resource.SpreadsheetResource; @@ -77,7 +78,7 @@ public class SpreadsheetRootVariable extends StandardGraphChildVariable { if(name.contains(":")) { - Range range = SpreadsheetUtils.decodeRange(name, 0, 0); + Range range = Spreadsheets.decodeRange(name, 0, 0); VariantMatrix matrix = new VariantMatrix(range.height(),range.width()); String rangeNames[][] = new String[range.height()][range.width()]; @@ -85,7 +86,7 @@ public class SpreadsheetRootVariable extends StandardGraphChildVariable { for(int x=range.startColumn;x<=range.endColumn;x++) { for(int y=range.startRow;y<=range.endRow;y++) { - String location = SpreadsheetUtils.cellName(y,x); + String location = Spreadsheets.cellName(y,x); Variable child = context.getPossibleChild(graph, location); Variant value = null; if(child != null) diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java index be73a741c..71466070e 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java @@ -29,7 +29,7 @@ import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.layer0.Layer0; import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.util.SpreadsheetUtils; +import org.simantics.spreadsheet.Spreadsheets; public class SpreadsheetExpressionVisitor extends DepthFirstAdapter { @@ -220,13 +220,13 @@ public class SpreadsheetExpressionVisitor extends DepthFirstAdapter { String identifier = node.toString().trim(); - Range range = SpreadsheetUtils.decodeRange(identifier, row, column); + Range range = Spreadsheets.decodeRange(identifier, row, column); if (range.size() != 1) { ArrayList value = new ArrayList(); for (int c = range.startColumn; c <= range.endColumn; c++) { for (int r = range.startRow; r <= range.endRow; r++) { try { - String location = SpreadsheetUtils.cellName(r, c); + String location = Spreadsheets.cellName(r, c); Variable cell = cellVariable.getChild(graph, location); System.out.println("cell=" + cell.getURI(graph)); String label = cell.getPossiblePropertyValue(graph, "Label"); diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java deleted file mode 100644 index 90c96cc2d..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import java.io.StringReader; - -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.ExcelArrayFormula; -import org.simantics.spreadsheet.graph.ExcelFormula; -import org.simantics.spreadsheet.graph.SpreadsheetBook; -import org.simantics.spreadsheet.graph.SpreadsheetCell; -import org.simantics.spreadsheet.graph.SpreadsheetFormula; -import org.simantics.spreadsheet.graph.SpreadsheetLine; -import org.simantics.spreadsheet.graph.SpreadsheetLines; -import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant; -import org.simantics.spreadsheet.graph.function.LineContentBean; -import org.simantics.spreadsheet.graph.function.LineContentBeanCell; -import org.simantics.spreadsheet.graph.parser.SheetFormulaParser; -import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.utils.Solver; - -public class LineCommandBuilder implements CommandBuilder { - - private String name; -// private boolean update; - LineContentBean bean; - - public LineCommandBuilder(String name, boolean update) { - this.name = name; -// this.update = update; - } - - @Override - public void apply(Solver solver) { - - SpreadsheetBook book = solver.getConcreteSolver(); - - String path = name.substring(0, name.lastIndexOf("/")); - String lineName = name.substring(name.lastIndexOf("/")+1); - int row = Integer.parseInt(lineName.substring(3)); - - SpreadsheetLines node = book.ensureSubprocess(path); - SpreadsheetLine line = node.lines.get(-row); - if(line == null) { - line = new SpreadsheetLine(node, row); - node.lines.put(-row, line); - } - -// line.cells.clear(); - for(int i=0;i i) { - currentCell = line.cells.get(i); - } else { - currentCell = new SpreadsheetCell(line, i); - line.cells.add(currentCell); - } - - LineContentBeanCell cell = bean.cells[i]; - - try { - Object content = cell.getContent(); - if (content instanceof Variant) { - Variant cellVariant = (Variant) content; - if (cellVariant == LineContentBeanCell.EMPTY) { - currentCell.setStyle(cell.getStyleId()); - // Empty content - currentCell.setContent(""); -// if (currentCell != SpreadsheetCell.EMPTY) { -// line.cells.remove(i); -// line.cells.add(i, SpreadsheetCell.EMPTY); -// } - } else if(ExcelFormula.BINDING.type().equals(cellVariant.getBinding().type())) { - ExcelFormula formula = (ExcelFormula)cellVariant.getValue(ExcelFormula.BINDING); - SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression)); - AstValue v = p.relation(); - currentCell.setStyle(cell.getStyleId()); - SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression); - currentCell.setContent(sformula); - } else if (ExcelArrayFormula.BINDING.type().equals(cellVariant.getBinding().type())) { - ExcelArrayFormula formula = (ExcelArrayFormula)cellVariant.getValue(ExcelArrayFormula.BINDING); - SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression)); - AstArrayFormulaReference v = new AstArrayFormulaReference(formula.range, p.relation()); - currentCell.setStyle(cell.getStyleId()); - SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression); - currentCell.setContent(sformula); - } else { - currentCell.setStyle(cell.getStyleId()); - // DO not update constant values during update - currentCell.setContent(cellVariant.getValue()); - } - } else if (content instanceof SpreadsheetSCLConstant){ - currentCell.setStyle(cell.getStyleId()); - currentCell.setContent(content); - } - } catch (Throwable e) { - Object content = cell.getContent(); - if (content instanceof Variant) { - Variant cellVariant = (Variant) content; - currentCell.setStyle(cell.getStyleId()); - currentCell.setContent(content); - try { - new Exception("failed: " + ((ExcelFormula)(cellVariant.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace(); - } catch (AdaptException e1) { - e1.printStackTrace(); - } - } else { - currentCell.setStyle(cell.getStyleId()); - currentCell.setContent("LCB error happened"); - } - } - } - } - - @SuppressWarnings("unchecked") - @Override - public T getConcrete() { - return (T)this; - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java deleted file mode 100644 index 811a35c23..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import java.util.Collection; -import java.util.Map; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.base.ModuleUpdateContext; -import org.simantics.structural.synchronization.base.ModuleUpdaterBase; -import org.simantics.structural.synchronization.base.PropertyUpdateRule; - -public class LineNodeUpdater extends ModuleUpdaterBase { - - public LineNodeUpdater(String id) { - - super(id); - - isComposite = true; - - addPropertyUpdateRule(new PropertyUpdateRule() { - - @Override - public String getPropertyName() { - return "keys"; - } - - @Override - public void apply(ModuleUpdateContext context, boolean isCreating, - Map propertyMap, Map> connectionMap, Variant value) { - - LinesCommandBuilder builder = context.getConcreteCommand(); - Variant v = propertyMap.get("keys"); - if (v != null & v.getValue() != null) - builder.keys = (int[])v.getValue(); - - } - - }); - - } - - @Override - public CommandBuilder createAddCommandBuilder(String name) { - return new LinesCommandBuilder(name, false); - } - - @Override - public CommandBuilder createUpdateCommandBuilder(String name) { - return new LinesCommandBuilder(name, true); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java deleted file mode 100644 index 18f0bfbc5..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import java.util.Collection; -import java.util.Map; - -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.function.LineContentBean; -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.base.ModuleUpdateContext; -import org.simantics.structural.synchronization.base.ModuleUpdaterBase; -import org.simantics.structural.synchronization.base.PropertyUpdateRule; - -public class LineUpdater extends ModuleUpdaterBase { - - public LineUpdater(String id) { - super(id); - addPropertyUpdateRule(new PropertyUpdateRule() { - - @Override - public String getPropertyName() { - return "content"; - } - - @Override - public void apply(ModuleUpdateContext context, boolean isCreating, - Map propertyMap, Map> connectionMap, Variant value) { - - LineCommandBuilder builder = context.getConcreteCommand(); - try { - LineContentBean valuee = (LineContentBean) value.getValue(LineContentBean.BINDING); - builder.bean = valuee; - } catch (AdaptException e) { - e.printStackTrace(); - } catch (ClassCastException e) { - e.printStackTrace(); - } -// if (valuee instanceof LineContentBean) -// -// else -// System.err.println("valuee is instanceof " + valuee.getClass().getSimpleName() + " " + valuee); - - } - - }); - } - - @Override - public CommandBuilder createAddCommandBuilder(String name) { - return new LineCommandBuilder(name, false); - } - - @Override - public CommandBuilder createUpdateCommandBuilder(String name) { - return new LineCommandBuilder(name, true); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java deleted file mode 100644 index 4cf804c2d..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import org.simantics.spreadsheet.graph.SpreadsheetBook; -import org.simantics.spreadsheet.graph.SpreadsheetLines; -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.utils.Solver; - -public class LinesCommandBuilder implements CommandBuilder { - - private final boolean update; - private String name; - int[] keys; - - public LinesCommandBuilder(String name, boolean update) { - this.name = name; - this.update = update; - } - - @Override - public void apply(Solver solver) { -// if (update) -// return; - - SpreadsheetBook book = solver.getConcreteSolver(); - SpreadsheetLines node = book.ensureSubprocess(name); - node.setKeys(keys); - -// String path = name.substring(0, name.lastIndexOf("/")); -// String lineName = name.substring(name.lastIndexOf("/")+1); -// int row = Integer.parseInt(lineName.substring(3)); -// - -// SpreadsheetLine line = node.lines.get(-row); -// if(line == null) { -// line = new SpreadsheetLine(node, row); -// node.lines.put(-row, line); -// } -// -// for(int i=0;i T getConcrete() { - return (T)this; - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java deleted file mode 100644 index 80ed1ca13..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.utils.Solver; - -public class NullCommandBuilder implements CommandBuilder { - - @Override - public void apply(Solver solver) { - } - - @SuppressWarnings("unchecked") - @Override - public T getConcrete() { - return (T)this; - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java deleted file mode 100644 index e03169fd4..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import org.simantics.structural.synchronization.base.CommandBuilder; -import org.simantics.structural.synchronization.base.ModuleUpdaterBase; - -public class NullUpdater extends ModuleUpdaterBase { - - public NullUpdater(String typeId) { - super(typeId); - isComposite = true; - } - - @Override - public CommandBuilder createAddCommandBuilder(String name) { - return new NullCommandBuilder(); - } - - @Override - public CommandBuilder createUpdateCommandBuilder(String name) { - return new NullCommandBuilder(); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java deleted file mode 100644 index 5edea565f..000000000 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.simantics.spreadsheet.graph.synchronization; - -import java.io.Serializable; - -import org.simantics.structural.synchronization.utils.ComponentBase; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.procedure.TObjectProcedure; - -public class SheetLineComponent extends ComponentBase implements Serializable { - - private static final long serialVersionUID = 1777515716175831266L; - - private THashMap childMap = new THashMap<>(); - - public SheetLineComponent(String uid) { - super(uid, 0); - } - -// public SheetLineComponent(String uid, String solverComponentName, int componentId) { -// this.uid = uid; -// this.solverComponentName = solverComponentName; -// this.componentId = componentId; -// } - - @Override - public THashMap getChildMap() { - return childMap; - } - - @Override - public void setChildMap(THashMap newChildMap) { - childMap = newChildMap; - if(childMap != null) { - childMap.forEachValue(new TObjectProcedure() { - @Override - public boolean execute(SheetLineComponent component) { - component.parent = SheetLineComponent.this; - return true; - } - }); - } - } - - @Override - public String toString() { - return solverComponentName + " (" + super.toString() + ")"; - } - -} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SpreadsheetSynchronizationEventHandler.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SpreadsheetSynchronizationEventHandler.java index 716086b63..1d6d19de8 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SpreadsheetSynchronizationEventHandler.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SpreadsheetSynchronizationEventHandler.java @@ -1,8 +1,9 @@ package org.simantics.spreadsheet.graph.synchronization; import org.simantics.db.ReadGraph; -import org.simantics.spreadsheet.graph.SpreadsheetBook; import org.simantics.spreadsheet.graph.SpreadsheetReferenceResolver; +import org.simantics.spreadsheet.solver.SheetLineComponent; +import org.simantics.spreadsheet.solver.SpreadsheetBook; import org.simantics.structural.synchronization.base.SynchronizationEventHandlerBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java index 86fda3d5a..98335a529 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java @@ -10,8 +10,6 @@ *******************************************************************************/ package org.simantics.spreadsheet.ui; -import gnu.trove.map.hash.THashMap; - import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collection; @@ -23,10 +21,12 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.simantics.spreadsheet.ClientModel; -import org.simantics.spreadsheet.util.SpreadsheetUtils; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.collections.CollectionUtils; +import gnu.trove.map.hash.THashMap; + public class ClientModelImpl implements ClientModel { final private Map> properties = new THashMap>(); @@ -226,7 +226,7 @@ public class ClientModelImpl implements ClientModel { Map cls = cells.remove(location); if(cls == null) return; - long l = SpreadsheetUtils.decodeCellCoded(location); + long l = Spreadsheets.decodeCellCoded(location); int row = (int)(l & 0xffffffff) - 1; int column = (int)((l>>32) & 0xffffffff); @@ -280,7 +280,7 @@ public class ClientModelImpl implements ClientModel { cls.put(property, value); - long l = SpreadsheetUtils.decodeCellCoded(location); + long l = Spreadsheets.decodeCellCoded(location); int row = (int)(l & 0xffffffff) - 1; int column = (int)((l>>32) & 0xffffffff); diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientTableModel.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientTableModel.java index 395fcbdd7..b77350a0c 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientTableModel.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientTableModel.java @@ -18,8 +18,9 @@ import javax.swing.table.DefaultTableModel; import org.simantics.spreadsheet.ClientModel; import org.simantics.spreadsheet.ClientModel.ClientModelListener; -import org.simantics.spreadsheet.ClientModel.OperationMode; -import org.simantics.spreadsheet.graph.SpreadsheetStyle; +import org.simantics.spreadsheet.OperationMode; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.SpreadsheetStyle; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.ui.colors.Colors; import org.simantics.ui.fonts.Fonts; @@ -142,7 +143,7 @@ final public class ClientTableModel extends DefaultTableModel { @Override public Object getValueAt(int row, int column) { - String location = SpreadsheetUtils.cellName(row, column); + String location = Spreadsheets.cellName(row, column); // System.out.println("CellValue for location " + location); diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/DeleteHandler.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/DeleteHandler.java index 44c2b219a..6ac032259 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/DeleteHandler.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/DeleteHandler.java @@ -16,8 +16,8 @@ import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.ui.handlers.HandlerUtil; import org.simantics.spreadsheet.CellEditor; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.graph.GraphUI; -import org.simantics.spreadsheet.util.SpreadsheetUtils; public class DeleteHandler extends AbstractHandler { @@ -39,7 +39,7 @@ public class DeleteHandler extends AbstractHandler { for(int row : rows) { for(int col : cols) { - ce.edit(null, SpreadsheetUtils.cellName(row, col), null, null); + ce.edit(null, Spreadsheets.cellName(row, col), null, null); } } diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java index b21a22500..f39e92c7a 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java @@ -24,10 +24,11 @@ import org.simantics.databoard.binding.mutable.MutableVariant; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.spreadsheet.Adaptable; import org.simantics.spreadsheet.CellEditor; -import org.simantics.spreadsheet.CellEditor.Transaction; -import org.simantics.spreadsheet.ClientModel.OperationMode; import org.simantics.spreadsheet.ClientModel; +import org.simantics.spreadsheet.OperationMode; import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.Transaction; import org.simantics.spreadsheet.common.cell.StringCellParser; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.utils.threads.logger.ITask; @@ -196,7 +197,7 @@ public class ExcelAdapter implements ActionListener { CellValue cell = (CellValue)table.getValueAt(startRow+i, startCol+j); if(cell.label != null) { - String location = SpreadsheetUtils.cellName(startRow+i, startCol+j); + String location = Spreadsheets.cellName(startRow+i, startCol+j); Boolean computed = model.getPropertyAt(location, ClientModel.COMPUTED); if(computed != null && computed) return; removals.add(location); @@ -221,9 +222,9 @@ public class ExcelAdapter implements ActionListener { startCol+j< table.getColumnCount()) { if (value.startsWith("=")) { - editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null); + editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null); } else { - editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null); + editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null); } } @@ -243,8 +244,8 @@ public class ExcelAdapter implements ActionListener { for(int i=0;i 0) { - String left = SpreadsheetUtils.cellName(row, col-1); + String left = Spreadsheets.cellName(row, col-1); setCurrent(left, getCurrent(left, row, col-1) & 2); } if(row > 0) { - String up = SpreadsheetUtils.cellName(row-1, col); + String up = Spreadsheets.cellName(row-1, col); setCurrent(up, getCurrent(up, row-1, col) & 1); } setCurrent(location, 0); @@ -430,14 +430,14 @@ public class SpreadsheetModel { // Top else if(index == 2) { if(row > 0) { - String up = SpreadsheetUtils.cellName(row-1, col); + String up = Spreadsheets.cellName(row-1, col); setCurrent(up, getCurrent(up, row-1, col) | 2); } } // Left else if(index == 3) { if(col > 0) { - String left = SpreadsheetUtils.cellName(row, col-1); + String left = Spreadsheets.cellName(row, col-1); setCurrent(left, getCurrent(left, row, col-1) | 1); } } @@ -530,7 +530,7 @@ public class SpreadsheetModel { if (selection.intersects(span)) { selection = selection.union(span); found = true; - String location = SpreadsheetUtils.cellName(span.y, span.x); + String location = Spreadsheets.cellName(span.y, span.x); editor.edit(transaction, location, ClientModel.ROW_SPAN, 1, Bindings.INTEGER, null); editor.edit(transaction, location, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER, null); iter.remove(); @@ -538,7 +538,7 @@ public class SpreadsheetModel { } } - String location = SpreadsheetUtils.cellName(selection.y, selection.x); + String location = Spreadsheets.cellName(selection.y, selection.x); if (selection.height > 1) { editor.edit(transaction, location, ClientModel.ROW_SPAN, selection.height, Bindings.INTEGER, null); } @@ -1042,7 +1042,7 @@ public class SpreadsheetModel { private void editSelection(CellEditor editor, Transaction transaction, String property, Object value, Binding binding) { for(int col : table.getSelectedColumns()) { for(int row : table.getSelectedRows()) { - String location = SpreadsheetUtils.cellName(row, col); + String location = Spreadsheets.cellName(row, col); editor.edit(transaction, location, property, value, binding, null); } } @@ -1059,7 +1059,7 @@ public class SpreadsheetModel { // Transaction transaction = editor.startTransaction(); for(int col : selectedColumns) { for(int row : selectedRows) { - String location = SpreadsheetUtils.cellName(row, col); + String location = Spreadsheets.cellName(row, col); CellValue value = (CellValue)table.getValueAt(row, col); int align = value != null ? value.align : 0; diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetTable.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetTable.java index ee9a55b1d..96254ae63 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetTable.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetTable.java @@ -30,7 +30,7 @@ import org.simantics.scenegraph.INode; import org.simantics.scenegraph.swing.JTableSG; import org.simantics.spreadsheet.CellEditor; import org.simantics.spreadsheet.ClientModel; -import org.simantics.spreadsheet.ClientModel.OperationMode; +import org.simantics.spreadsheet.OperationMode; public class SpreadsheetTable extends JTableSG { diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TextTableCellEditor.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TextTableCellEditor.java index 24fade56a..f84e0ef84 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TextTableCellEditor.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TextTableCellEditor.java @@ -27,6 +27,7 @@ import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.spreadsheet.CellEditor; import org.simantics.spreadsheet.ClientModel; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.util.SpreadsheetUtils; class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEditor { @@ -135,7 +136,7 @@ class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEd String str = (String)getCellEditorValue(); - String cellName = SpreadsheetUtils.cellName(row, column); + String cellName = Spreadsheets.cellName(row, column); Object expressionO = clientModel.getPossiblePropertyAt(cellName, ClientModel.CONTENT_EXPRESSION); String expression = null; if(expressionO instanceof String) { @@ -158,11 +159,11 @@ class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEd return; if (str.startsWith("=")) { - editor.edit(null, SpreadsheetUtils.cellName(row, column), ClientModel.CONTENT_EXPRESSION, str, Bindings.STRING, null); + editor.edit(null, Spreadsheets.cellName(row, column), ClientModel.CONTENT_EXPRESSION, str, Bindings.STRING, null); //Update cell expression clientModel.setProperty(cellName, ClientModel.CONTENT_EXPRESSION, str); } else { - editor.edit(null, SpreadsheetUtils.cellName(row, column), Variant.ofInstance(str), null); + editor.edit(null, Spreadsheets.cellName(row, column), Variant.ofInstance(str), null); //Update cell expression clientModel.setProperty(cellName, ClientModel.CONTENT_EXPRESSION, null); //If not an expression, then the expression property is null } diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/CommandCellTab.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/CommandCellTab.java index 74a539c73..f0b9c8c0f 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/CommandCellTab.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/CommandCellTab.java @@ -24,8 +24,8 @@ import org.simantics.db.management.ISessionContext; import org.simantics.selectionview.PropertyTabContributorImpl; import org.simantics.spreadsheet.CommandCellExecutor; import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.graph.GraphUI; -import org.simantics.spreadsheet.util.SpreadsheetUtils; public class CommandCellTab extends PropertyTabContributorImpl { @@ -89,7 +89,7 @@ public class CommandCellTab extends PropertyTabContributorImpl { if(ui != null) { CommandCellExecutor executor = (CommandCellExecutor)ui.getAdapter(CommandCellExecutor.class); String location = variable.getPossiblePropertyValue(graph, "HasName"); - Range range = SpreadsheetUtils.decodeCellAbsolute(location); + Range range = Spreadsheets.decodeCellAbsolute(location); executor.execute(range.startRow, range.startColumn); System.out.println("uiui"); } diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/ExcelLink.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/ExcelLink.java index 03467d6f6..e68f115ad 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/ExcelLink.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/ExcelLink.java @@ -29,10 +29,11 @@ import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.excel.Excel; import org.simantics.excel.ExcelException; import org.simantics.layer0.Layer0; +import org.simantics.spreadsheet.CellParseException; import org.simantics.spreadsheet.ClientModel; import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.common.client.ClientModelListenerAdapter; -import org.simantics.spreadsheet.common.exception.CellParseException; import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.spreadsheet.util.SpreadsheetUtils; import org.simantics.utils.FileUtils; @@ -148,7 +149,7 @@ public class ExcelLink extends ClientModelListenerAdapter { if(ClientModel.CONTENT.equals(property) && value != null && value instanceof Variant) { if(handle == 0) return; - Range range = SpreadsheetUtils.decodeCellAbsolute(location); + Range range = Spreadsheets.decodeCellAbsolute(location); excel.setString_(handle, range.startRow, range.startColumn, ((Variant)value).getValue().toString()); final String modis = excel.getModifications_(handle); @@ -159,7 +160,7 @@ public class ExcelLink extends ClientModelListenerAdapter { String[] parts = (modis+"0").split("#"); - Range range = SpreadsheetUtils.decodeRange(parts[0]); + Range range = Spreadsheets.decodeRange(parts[0]); Layer0 L0 = Layer0.getInstance(graph); SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph); @@ -168,7 +169,7 @@ public class ExcelLink extends ClientModelListenerAdapter { for(int i=0;i label : model.listAll(ClientModel.LABEL)) { try { - Range range = SpreadsheetUtils.decodeCellAbsolute(label.first); + Range range = Spreadsheets.decodeCellAbsolute(label.first); excel.setString_(handle, range.startRow, range.startColumn, (String)label.second); // System.err.println("excel.setString " + label.second); } catch (CellParseException e) { @@ -255,7 +256,7 @@ public class ExcelLink extends ClientModelListenerAdapter { } for(Pair label : model.listAll(ClientModel.CONTENT)) { try { - Range range = SpreadsheetUtils.decodeCellAbsolute(label.first); + Range range = Spreadsheets.decodeCellAbsolute(label.first); //excel.setString_(handle, range.startRow, range.startColumn, (String)label.second); String uri = (String)label.second; diff --git a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/SpreadsheetSelectionProcessor.java b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/SpreadsheetSelectionProcessor.java index 11da9ac7b..ea54d6319 100644 --- a/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/SpreadsheetSelectionProcessor.java +++ b/bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/SpreadsheetSelectionProcessor.java @@ -11,10 +11,10 @@ import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.selectionview.ComparableTabContributor; import org.simantics.selectionview.SelectionProcessor; +import org.simantics.spreadsheet.Spreadsheets; import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.spreadsheet.ui.TableSelection; import org.simantics.spreadsheet.ui.editor.NoCellTab.NoCellInput; -import org.simantics.spreadsheet.util.SpreadsheetUtils; /** * @author Tuukka Lehtonen @@ -32,7 +32,7 @@ public class SpreadsheetSelectionProcessor implements SelectionProcessor result = new ArrayList(); final Variable cell = variable.getPossibleChild(graph, location); if(cell != null) { diff --git a/bundles/org.simantics.spreadsheet/.classpath b/bundles/org.simantics.spreadsheet/.classpath index eca7bdba8..b862a296d 100644 --- a/bundles/org.simantics.spreadsheet/.classpath +++ b/bundles/org.simantics.spreadsheet/.classpath @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/bundles/org.simantics.spreadsheet/META-INF/MANIFEST.MF b/bundles/org.simantics.spreadsheet/META-INF/MANIFEST.MF index ce6f47de2..2bbd595f7 100644 --- a/bundles/org.simantics.spreadsheet/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.spreadsheet/META-INF/MANIFEST.MF @@ -6,8 +6,23 @@ Bundle-Version: 1.1.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: org.simantics.spreadsheet, org.simantics.spreadsheet.cell.handler, - org.simantics.spreadsheet.event.model + org.simantics.spreadsheet.event.model, + org.simantics.spreadsheet.solver, + org.simantics.spreadsheet.solver.formula, + org.simantics.spreadsheet.solver.formula.parser, + org.simantics.spreadsheet.solver.formula.parser.ast, + org.simantics.spreadsheet.synchronization Require-Bundle: org.simantics.utils.datastructures;bundle-version="1.0.0", - org.simantics.databoard;bundle-version="0.6.1" + org.simantics.databoard;bundle-version="0.6.1", + it.unimi.dsi.fastutil;bundle-version="7.2.1", + org.apache.commons.math3, + gnu.trove3, + org.simantics.scl.runtime, + org.simantics.datatypes;bundle-version="1.0.0", + org.simantics.common;bundle-version="1.0.0", + org.simantics.simulator.toolkit;bundle-version="1.0.0", + org.simantics.structural.synchronization;bundle-version="1.0.0", + org.apache.poi, + org.slf4j.api;bundle-version="1.7.25" Bundle-Vendor: VTT Technical Research Centre of Finland Automatic-Module-Name: org.simantics.spreadsheet diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Adaptable.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Adaptable.java index a1c38ee47..7865ed84e 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Adaptable.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Adaptable.java @@ -14,7 +14,7 @@ package org.simantics.spreadsheet; public interface Adaptable { - - T getAdapter(Class clazz); - + + T getAdapter(Class clazz); + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellEditor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellEditor.java index b322335a1..4448a8798 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellEditor.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellEditor.java @@ -11,62 +11,39 @@ *******************************************************************************/ package org.simantics.spreadsheet; -import java.util.List; import java.util.function.Consumer; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.mutable.MutableVariant; import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.ClientModel.OperationMode; public interface CellEditor { - - public interface Transaction { - - void setContext(Object context); - - Object getContext(); - - void add(O operation); - - /* - * Applies the operations collected with this transaction - * - */ - void commit(); - - boolean isOperationMode(); - - List needSynchronization(); - void needSynchronization(Object synchronizable); - } - - /* - * Sets the given property of the given cell - * - * @param transaction a combined transaction, null for immediate change - * @param location a cell location e.g. 'A1' - * @param property the name of the property - * @param value the property value - * @param binding used for serializing the value - */ - void edit(Transaction transaction, String location, String property, T value, Binding binding, Consumer callback); - /* - * Edits the given cell using the given textual input - * - * @param transaction a combined transaction, null for immediate change - * @param location a cell location e.g. 'A1' - * @param value a text describing the change - */ + /* + * Sets the given property of the given cell + * + * @param transaction a combined transaction, null for immediate change + * @param location a cell location e.g. 'A1' + * @param property the name of the property + * @param value the property value + * @param binding used for serializing the value + */ + void edit(Transaction transaction, String location, String property, T value, Binding binding, Consumer callback); + /* + * Edits the given cell using the given textual input + * + * @param transaction a combined transaction, null for immediate change + * @param location a cell location e.g. 'A1' + * @param value a text describing the change + */ void edit(Transaction transaction, String location, Variant variant, Consumer callback); void copy(Transaction transaction, String location, MutableVariant variant, Consumer callback); - - /* - * Creates a new transaction object - * - */ + + /* + * Creates a new transaction object + * + */ Transaction startTransaction(OperationMode mode); - + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellModifier.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellModifier.java index ca15766c5..45c1fdf1a 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellModifier.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellModifier.java @@ -15,8 +15,8 @@ package org.simantics.spreadsheet; * An interface for updating a client spreadsheet model */ public interface CellModifier { - void setProperty(String location, String property, Object value); - void clear(String location); - void clearAll(); - void flush(); + void setProperty(String location, String property, Object value); + void clear(String location); + void clearAll(); + void flush(); } diff --git a/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/exception/CellParseException.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellParseException.java similarity index 93% rename from bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/exception/CellParseException.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellParseException.java index 055c002ac..d5025bed5 100644 --- a/bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/exception/CellParseException.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellParseException.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.common.exception; +package org.simantics.spreadsheet; public class CellParseException extends RuntimeException { @@ -18,5 +18,5 @@ public class CellParseException extends RuntimeException { public CellParseException(String message) { super(message); } - + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ClientModel.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ClientModel.java index 55cfa1f5e..bd9b5d1a1 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ClientModel.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ClientModel.java @@ -18,112 +18,107 @@ import org.simantics.utils.datastructures.Pair; public interface ClientModel extends CellModifier { - - public enum OperationMode { - OPERATION, - EDIT_MODE + + public interface ClientModelListener { + + public void rows(int amount); + public void columns(int amount); + + public void columnLabels(String[] labels); + public void rowLabels(String[] labels); + public void columnWidths(int[] widths); + + public void sources(String[] available, String current); + + public void propertyChange(String location, String property, Object value); + public void cleared(String location); + public void flush(); + } - public interface ClientModelListener { - - public void rows(int amount); - public void columns(int amount); - - public void columnLabels(String[] labels); - public void rowLabels(String[] labels); - public void columnWidths(int[] widths); - - public void sources(String[] available, String current); - - public void propertyChange(String location, String property, Object value); - public void cleared(String location); - public void flush(); - - } - - public static final String EXCEL = "Excel"; - public static final String EXCEL_VISIBLE = "Visible"; - - /** - * The location argument to use for setting header properties. - * @see #HEADERS_COL_LABELS - * @see #HEADERS_COL_WIDTHS - * @see #HEADERS_ROW_HEIGHTS - * @see #HEADERS_ROW_LABELS - */ - public static final String HEADERS = "Headers"; - public static final String HEADERS_COL_WIDTHS = "columnWidths"; - public static final String HEADERS_ROW_HEIGHTS = "rowHeights"; - public static final String HEADERS_COL_LABELS = "columnLabels"; - public static final String HEADERS_ROW_LABELS = "rowLabels"; - - /** - * The location argument to use for setting dimension properties. - * @see #DIMENSIONS_COL_COUNT - * @see #DIMENSIONS_FIT_COLS - * @see #DIMENSIONS_FIT_ROWS - * @see #DIMENSIONS_ROW_COUNT - */ - public static final String DIMENSIONS = "Dimensions"; - public static final String DIMENSIONS_FIT_ROWS = "fitRows"; - public static final String DIMENSIONS_FIT_COLS = "fitColumns"; - public static final String DIMENSIONS_COL_COUNT = "columnCount"; - public static final String DIMENSIONS_ROW_COUNT = "rowCount"; - - public static final String SOURCES = "Sources"; - public static final String SOURCES_AVAILABLE = "available"; - public static final String SOURCES_CURRENT = "current"; - - public static final String SHEETS = "Sheets"; - public static final String SHEETS_AVAILABLE = "available"; - public static final String SHEETS_CURRENT = "current"; - - public static final String CONTEXT = "Context"; - public static final String CONTEXT_CURRENT = "current"; - - public static final String MODE = "Mode"; - public static final String MODE_CURRENT = "current"; - - public static final String STATES = "States"; - public static final String STATES_AVAILABLE = "available"; - public static final String STATES_CURRENT = "current"; - - public static final String FONT = "font"; - public static final String FOREGROUND = "foreground"; - public static final String BACKGROUND = "background"; - public static final String BORDER = "border"; - public static final String ALIGN = "align"; - public static final String LABEL = "label"; - public static final String CONTENT = "content"; - public static final String CONTENT_EXPRESSION = "content#expression"; - public static final String COMPUTED = "Computed"; - public static final String LOCKED = "locked"; - public static final String ROW_SPAN = "rowSpan"; - public static final String COLUMN_SPAN = "columnSpan"; - + public static final String EXCEL = "Excel"; + public static final String EXCEL_VISIBLE = "Visible"; + + /** + * The location argument to use for setting header properties. + * @see #HEADERS_COL_LABELS + * @see #HEADERS_COL_WIDTHS + * @see #HEADERS_ROW_HEIGHTS + * @see #HEADERS_ROW_LABELS + */ + public static final String HEADERS = "Headers"; + public static final String HEADERS_COL_WIDTHS = "columnWidths"; + public static final String HEADERS_ROW_HEIGHTS = "rowHeights"; + public static final String HEADERS_COL_LABELS = "columnLabels"; + public static final String HEADERS_ROW_LABELS = "rowLabels"; + + /** + * The location argument to use for setting dimension properties. + * @see #DIMENSIONS_COL_COUNT + * @see #DIMENSIONS_FIT_COLS + * @see #DIMENSIONS_FIT_ROWS + * @see #DIMENSIONS_ROW_COUNT + */ + public static final String DIMENSIONS = "Dimensions"; + public static final String DIMENSIONS_FIT_ROWS = "fitRows"; + public static final String DIMENSIONS_FIT_COLS = "fitColumns"; + public static final String DIMENSIONS_COL_COUNT = "columnCount"; + public static final String DIMENSIONS_ROW_COUNT = "rowCount"; + + public static final String SOURCES = "Sources"; + public static final String SOURCES_AVAILABLE = "available"; + public static final String SOURCES_CURRENT = "current"; + + public static final String SHEETS = "Sheets"; + public static final String SHEETS_AVAILABLE = "available"; + public static final String SHEETS_CURRENT = "current"; + + public static final String CONTEXT = "Context"; + public static final String CONTEXT_CURRENT = "current"; + + public static final String MODE = "Mode"; + public static final String MODE_CURRENT = "current"; + + public static final String STATES = "States"; + public static final String STATES_AVAILABLE = "available"; + public static final String STATES_CURRENT = "current"; + + public static final String FONT = "font"; + public static final String FOREGROUND = "foreground"; + public static final String BACKGROUND = "background"; + public static final String BORDER = "border"; + public static final String ALIGN = "align"; + public static final String LABEL = "label"; + public static final String CONTENT = "content"; + public static final String CONTENT_EXPRESSION = "content#expression"; + public static final String COMPUTED = "Computed"; + public static final String LOCKED = "locked"; + public static final String ROW_SPAN = "rowSpan"; + public static final String COLUMN_SPAN = "columnSpan"; + public static final String ITERATION_ENABLED = "iterationEnabled"; - + void addListener(ClientModelListener listener); void removeListener(ClientModelListener listener); T getPropertyAt(String location, String property); T getPossiblePropertyAt(String location, String property); - + int[] getColumnWidths(); int[] getRowHeights(); - + int getRows(); int getColumns(); - public Collection> listAll(String property); - - /* - * Returns a copy of the span. Null if not found. - */ - public Rectangle getSpan(int row, int column); - - /* - * Returns a copy of the span list. - */ - public List getSpans(); - + public Collection> listAll(String property); + + /* + * Returns a copy of the span. Null if not found. + */ + public Rectangle getSpan(int row, int column); + + /* + * Returns a copy of the span list. + */ + public List getSpans(); + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CommandCellExecutor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CommandCellExecutor.java index 2287c1f61..84eaa00b5 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CommandCellExecutor.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CommandCellExecutor.java @@ -14,7 +14,7 @@ package org.simantics.spreadsheet; public interface CommandCellExecutor { - + void execute(int row, int column); - + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Disposable.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Disposable.java index e49ce181f..bd055461b 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Disposable.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Disposable.java @@ -14,6 +14,6 @@ package org.simantics.spreadsheet; public interface Disposable { - void dispose(); - + void dispose(); + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java new file mode 100644 index 000000000..327e5aeb6 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java @@ -0,0 +1,17 @@ +package org.simantics.spreadsheet; + +import org.simantics.databoard.binding.mutable.Variant; + +public interface ExternalRef { + + public interface ExternalRefListener { + + public void newValue(Variant value); + public boolean isDisposed(); + + } + + public void listen(Object context, ExternalRefListener listener); + public void modify(Object context, Variant newValue); + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Matrix.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Matrix.java index 9dfe56e95..8288cb6f3 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Matrix.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Matrix.java @@ -15,11 +15,11 @@ import java.util.Collection; public interface Matrix { - - int getColumnCount(); - int getRowCount(); - Object get(int row, int column); - Collection getColumn(int column); - Collection getRow(int column); - + + int getColumnCount(); + int getRowCount(); + Object get(int row, int column); + Collection getColumn(int column); + Collection getRow(int column); + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/OperationMode.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/OperationMode.java new file mode 100644 index 000000000..f894cc545 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/OperationMode.java @@ -0,0 +1,6 @@ +package org.simantics.spreadsheet; + +public enum OperationMode { + OPERATION, + EDIT_MODE +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Range.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Range.java index 3c9d4b87e..b4a31c316 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Range.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Range.java @@ -13,26 +13,26 @@ package org.simantics.spreadsheet; public class Range { - public static final int MAXROWSPEC = Integer.MAX_VALUE;//1048576;// - public static final int MAXCOLUMNSPEC = Integer.MAX_VALUE;//16384;// - + public static final int MAXROWSPEC = Integer.MAX_VALUE;//1048576;// + public static final int MAXCOLUMNSPEC = Integer.MAX_VALUE;//16384;// + public int startRow; public int endRow; public int startColumn; public int endColumn; - + public Range(int startRow, int endRow, int startColumn, int endColumn) { this.startRow = startRow; this.endRow = endRow; this.startColumn = startColumn; this.endColumn = endColumn; - + if(startRow == -1) this.startRow = MAXROWSPEC; - if(endRow == -1) this.endRow = MAXROWSPEC; - if(startColumn == -1) this.startColumn = MAXCOLUMNSPEC; - if(endColumn == -1) this.endColumn = MAXCOLUMNSPEC; + if(endRow == -1) this.endRow = MAXROWSPEC; + if(startColumn == -1) this.startColumn = MAXCOLUMNSPEC; + if(endColumn == -1) this.endColumn = MAXCOLUMNSPEC; } - + public Range(Range copy) { this.startRow = copy.startRow; this.endRow = copy.endRow; @@ -43,46 +43,46 @@ public class Range { public static Range combine(Range from, Range to) { return new Range(from.startRow, to.endRow, from.startColumn, to.endColumn); } - + public boolean isFull() { - return endRow == MAXROWSPEC && endColumn == MAXCOLUMNSPEC; + return endRow == MAXROWSPEC && endColumn == MAXCOLUMNSPEC; } public boolean isFullRows() { - return endRow == MAXROWSPEC; + return endRow == MAXROWSPEC; } public boolean isFullColumns() { - return endColumn == MAXCOLUMNSPEC; + return endColumn == MAXCOLUMNSPEC; } public int size() { return (endRow-startRow + 1) * (endColumn - startColumn + 1); } - + public int width() { - return (endColumn - startColumn + 1); + return (endColumn - startColumn + 1); } - + public int height() { - return (endRow-startRow + 1); + return (endRow-startRow + 1); } - + public boolean contains(Range r) { - if(endRow >= 0) { - if(r.endRow > endRow) return false; - if(r.startRow < startRow) return false; - } - if(endColumn >= 0) { - if(r.startColumn < startColumn) return false; - if(r.endColumn > endColumn) return false; - } - return true; + if(endRow >= 0) { + if(r.endRow > endRow) return false; + if(r.startRow < startRow) return false; + } + if(endColumn >= 0) { + if(r.startColumn < startColumn) return false; + if(r.endColumn > endColumn) return false; + } + return true; } - + @Override public String toString() { return "Range[(" + startRow + "," + startColumn + ")-(" + endRow + "," + endColumn + ")]"; } - + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SheetVariables.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SheetVariables.java index 6877ba80e..b79910fac 100644 --- a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SheetVariables.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SheetVariables.java @@ -2,9 +2,9 @@ package org.simantics.spreadsheet; public class SheetVariables { - public static final String CONTENT = "content"; - public static final String FOREGROUND = "foreground"; - public static final String BACKGROUND = "background"; - public static final String RANGE_CELL_NAMES = "rangeCellNames"; + public static final String CONTENT = "content"; + public static final String FOREGROUND = "foreground"; + public static final String BACKGROUND = "background"; + public static final String RANGE_CELL_NAMES = "rangeCellNames"; } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellStyle.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetCellStyle.java similarity index 83% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellStyle.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetCellStyle.java index a8dd3732d..3056e8cfc 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellStyle.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetCellStyle.java @@ -1,12 +1,18 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet; import java.util.Collections; import java.util.Map; +import org.simantics.spreadsheet.solver.SheetNode; +import org.simantics.spreadsheet.solver.SpreadsheetCell; + +@SuppressWarnings("rawtypes") public class SpreadsheetCellStyle implements SheetNode { - public final SpreadsheetCell cell; + private static final long serialVersionUID = -219628109106298874L; + public final SpreadsheetCell cell; + public SpreadsheetCellStyle(SpreadsheetCell spreadsheetCell) { this.cell = spreadsheetCell; } @@ -25,7 +31,7 @@ public class SpreadsheetCellStyle implements SheetNode { public Map getProperties() { return Collections.emptyMap(); } - + @Override public int hashCode() { final int prime = 31; diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java new file mode 100644 index 000000000..b6896d5ec --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java @@ -0,0 +1,128 @@ +package org.simantics.spreadsheet; + +import java.io.Serializable; + +import org.simantics.spreadsheet.solver.formula.FormulaError2; + +public class SpreadsheetMatrix implements Serializable { + + private static final long serialVersionUID = 5729700370527844640L; + + private int w; + private int h; + public Object[] values; + + public SpreadsheetMatrix(int w, int h) { + this.w = w; + this.h = h; + this.values = new Object[w*h]; + } + + public Object get(int row, int column) { + return values[w*row+column]; + } + + public void set(int row, int column, Object value) { + values[w*row+column] = value; + } + + public int getWidth() { + return w; + } + + public int getHeight() { + return h; + } + + public double sum() { + double result = 0; + for(int i=0;i= 3){ + String oper = sc.substring(0, 2); + String criteriaStr = sc.substring(2); + Double criteriaNum = null; + try { + criteriaNum = Double.parseDouble(criteriaStr); + if(oper.equals("<>")){ + if(!nums) return true; + } + else if(!nums) return false; + nums = true; + } catch (NumberFormatException e){ + if(oper.equals("<>")){ + if(nums) return true; + } + else if(nums) return false; + nums = false; + } + + if(oper.equals(">=")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) >= 0 ; + else return ((Number)valueObj).doubleValue() >= criteriaNum; + } else if(oper.equals("<=")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) <= 0 ; + else return ((Number)valueObj).doubleValue() <= criteriaNum; + } else if(oper.equals("<>")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) != 0 ; + else return ((Number)valueObj).doubleValue() != criteriaNum; + } + } + if(sc.length() >= 2){ + String oper = sc.substring(0, 1); + String criteriaStr = sc.substring(1); + Double criteriaNum = null; + + try { + criteriaNum = Double.parseDouble(criteriaStr); + if(!nums) return false; + nums = true; + } catch (NumberFormatException e){ + if(nums) return false; + nums = false; + } + if(oper.equals("<")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) < 0; + else return ((Number)valueObj).doubleValue() < criteriaNum; + } else if(oper.equals(">")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) > 0; + else return ((Number)valueObj).doubleValue() > criteriaNum; + } else if(oper.equals("=")){ + if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) == 0; + else return ((Number)valueObj).doubleValue() == criteriaNum; + } + } + return sc.equals(valueObj); + } + else if (criteria instanceof Number){ + return false; + } + throw new IllegalStateException(); + } + + public static boolean excelEquals(Object left, Object right) { + if(left instanceof String) { + if(right instanceof String) { + return ((String) left).toLowerCase().equals(((String) right).toLowerCase()); + } + } + return left.equals(right); + } + + + // 1 kirjain, 'A' + column + // 2 kirjainta, 'A' + column % 26 , 'A' + int((column-26)/26) + // 3 kirjainta 'A' + column % 26 , 'A' + int(column-(26*(26+1)) / 26) % 26 + + // 0 26 + // 26 26 + 26*26 + // 26 + 26*26 26 + 26*26 + 26*26*26 + + public static String columnName(int column, int current, int limit, int chars) { + + if(column < limit) { + + char[] buf = new char[chars]; + column -= current; + for(int i=chars-1;i>=0;i--) { + char rem = (char)(column % 26); + column = (column / 26); + buf[i] = (char)('A' + rem); + } + return new String(buf); + + } else return columnName(column, limit, 26*(limit+1), chars+1); + + } + + public static String columnName(int column) { + return columnName(column, 0, 26, 1); + } + + public static String cellName(int row, int column) { + + String result = columnName(column); + result += (row+1); + return result; + + } + + public static String offset(String location, int rowOffset, int columnOffset) { + + Range range = decodeCellAbsolute(location); + String result = cellName(range.startRow + rowOffset, range.startColumn + columnOffset); + // System.err.println("offset " + location + "(" + rowOffset + " " + columnOffset + ") = >" + result); + return result; + + } + + public static Range decodeCellAbsolute(String identifier) { + long l = decodeCellCoded(identifier); + int row = (int)(l & 0xffffffff) - 1; + int column = (int)((l>>32) & 0xffffffff); + return new Range(row, row, column, column); + } + + public static Range decodePossibleCellAbsolute(String identifier) { + try { + return decodeCellAbsolute(identifier); + } catch (CellParseException e) { + return null; + } + } + + public static long decodeCellCoded(String identifier) { + + // System.out.println("decodecellabsolute " + identifier); + + int row = 0; + int column = 0; + +// identifier. + + int position = 0; + + // We skip $ here + if(identifier.charAt(position) == '$') position++; + + int length = identifier.length(); + + while(position < length) { + char b = identifier.charAt(position); + if(b >= 'A' && b <= 'Z') column = column * 26 + (b-'A' + 1); + else break; + position++; + } + + // We skip $ here + if(position < length) + if(identifier.charAt(position) == '$') + position++; + + while(position < length) { + char b = identifier.charAt(position); + if(b >= '0' && b <= '9'){ + row = row * 10 + b-'0'; + } + else if(b=='-' && position < (length-1)){//identify use of full row range here. + position++; + char b2 = identifier.charAt(position); + if(b2=='1'){ + row = 0; + position++; + break; + } + } + else { + break; + } + position++; + } + + if(position == length) { + + // We need to be able to express -1 in row => report row + 1 here + column--; + // System.err.println("ra " + identifier + " => " + row + " " + column); + return row + (((long)column)<<32); + + } else { + + throw new CellParseException("Cell identifier '" + identifier + "' is not a valid cell reference."); + + } + + } + + public static Range decodeCellRelative(String identifier, int row, int column) { + + int offset = Integer.valueOf(identifier.substring(1).trim()); + // System.out.println("offset=" + offset); + + if(identifier.startsWith("L") || identifier.startsWith("l")) { + return new Range(row, row, column-offset, column-offset); + } else if(identifier.startsWith("R") || identifier.startsWith("r")) { + return new Range(row, row, column+offset, column+offset); + } else if(identifier.startsWith("U") || identifier.startsWith("u")) { + return new Range(row-offset, row-offset, column, column); + } else if(identifier.startsWith("D") || identifier.startsWith("d")) { + return new Range(row+offset, row+offset, column, column); + } else { + throw new CellParseException("Relative cell syntax must begin with L|R|U|D."); + } + + } + + public static Range decodeCell(String identifier, int row, int column) { + + if(identifier.startsWith("_")) { + return decodeCellRelative(identifier.substring(1), row, column); + } else { + return decodeCellAbsolute(identifier); + } + + } + + public static Range decodeReference(String identifier, int row, int column) { + if(!identifier.startsWith("&")) throw new CellParseException("A reference cell was expected."); + return decodeRange(identifier.substring(1), row, column); + } + + public static List decodeRanges(String ranges){ + String[] splitted = ranges.split(","); + List result = new ArrayList<>(); + for(String split : splitted){ + result.add(decodeRange(split)); + } + return result; + } + + public static Object extract(Object object, int row, int column) { + if(object instanceof List) { + @SuppressWarnings("rawtypes") + List list = (List)object; + if(list.size() <= row) return null; + Object item = list.get(row); + if(item instanceof Tuple) { + Tuple tuple = (Tuple)item; + if(tuple.length() <= column) return null; + return tuple.get(column); + } + } + return null; + } + + + + public static int startRow(List ranges){ + int s = -1; + for(Range r : ranges){ + if(r.startRow ranges){ + int s = -1; + for(Range r : ranges){ + if(r.startColumnendRow){ + endRow = r.endRow; + } + return endRow - startRow +1; + } + + public static int amountOfColumns(Range r){ + int endColumn = -2; + int startColumn = -2; + if(r.isFullColumns()){ + return Range.MAXCOLUMNSPEC; + } + if(endColumn == -2 && startColumn == -2){ + endColumn = r.endColumn; + startColumn = r.startColumn; + } + if(r.startColumnendColumn){ + endColumn = r.endColumn; + } + return endColumn - startColumn +1; + } + + public static Range decodeRange(String rangeOrCell) { + if(rangeOrCell.isEmpty()) return fullRange(); + return decodeRange(rangeOrCell, 0, 0); + } + + public static Range fullRange() { + return new Range(0, -1, 0, -1); + } + + public static Range decodeRange(String rangeOrCell, int row, int column) { + + String[] parts = rangeOrCell.split(":"); + if(parts.length == 1) { + + return decodeCell(rangeOrCell, row, column); + + } else if (parts.length == 2) { + + Range from = decodeCell(parts[0].trim(), row, column); + // System.out.println("decodefrom=" + from); + Range to = decodeCell(parts[1].trim(), row, column); + // System.out.println("decodeto=" + to); + return Range.combine(from, to); + + } else { + + throw new CellParseException("The reference cell syntax was invalid. At most 1 occurrence of ':' is expected."); + + } + + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Transaction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Transaction.java new file mode 100644 index 000000000..3702a22da --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Transaction.java @@ -0,0 +1,24 @@ +package org.simantics.spreadsheet; + +import java.util.List; + +public interface Transaction { + + void setContext(Object context); + + Object getContext(); + + void add(O operation); + + /* + * Applies the operations collected with this transaction + * + */ + void commit(); + + boolean isOperationMode(); + + List needSynchronization(); + + void needSynchronization(Object synchronizable); +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefConstant.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefConstant.java new file mode 100644 index 000000000..279326953 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefConstant.java @@ -0,0 +1,24 @@ +package org.simantics.spreadsheet.solver; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.ExternalRef; + +public class ExternalRefConstant implements ExternalRef { + + final private Variant constant; + + public ExternalRefConstant(Variant constant) { + this.constant = constant; + } + + @Override + public void listen(Object context, ExternalRefListener listener) { + listener.newValue(constant); + } + + @Override + public void modify(Object context, Variant newValue) { + } + +} + diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefData.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefData.java new file mode 100644 index 000000000..f561f4b1b --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/ExternalRefData.java @@ -0,0 +1,52 @@ +package org.simantics.spreadsheet.solver; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.ExternalRef; +import org.simantics.spreadsheet.ExternalRef.ExternalRefListener; + +class ExternalRefData implements ExternalRefListener { + + final private SpreadsheetBook book; + final private long referenceKey; + final private ExternalRef ref; + private boolean isDisposed = false; + private Variant value = SpreadsheetBook.DEFAULT_VALUE; + + public ExternalRefData(SpreadsheetBook book, long referenceKey, ExternalRef ref) { + this.book = book; + this.referenceKey = referenceKey; + this.ref = ref; + ref.listen(book.context, this); + } + + public Variant getContent() { + return value; + } + + public ExternalRef getRef() { + return ref; + } + + @Override + public void newValue(Variant newVariant) { + SpreadsheetCell cell = book.cellByReferenceKey(referenceKey); + if(cell.getContent() instanceof SpreadsheetSCLConstant) { + SpreadsheetSCLConstant ssc = (SpreadsheetSCLConstant)cell.getContent(); + Object content = ssc.getContent(); + if(content.equals(ref)) { + value = newVariant; + book.fireChanges(book.invalidate(cell)); + return; + } + } + isDisposed = true; + } + + @Override + public boolean isDisposed() { + if(isDisposed) + return true; + return book.isDisposed(); + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java new file mode 100644 index 000000000..1173a48f5 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java @@ -0,0 +1,44 @@ +package org.simantics.spreadsheet.solver; + +import java.io.Serializable; + +import org.simantics.structural.synchronization.utils.ComponentBase; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.procedure.TObjectProcedure; + +public class SheetLineComponent extends ComponentBase implements Serializable { + + private static final long serialVersionUID = 1777515716175831266L; + + private THashMap childMap = new THashMap<>(); + + public SheetLineComponent(String uid) { + super(uid, 0); + } + + @Override + public THashMap getChildMap() { + return childMap; + } + + @Override + public void setChildMap(THashMap newChildMap) { + childMap = newChildMap; + if(childMap != null) { + childMap.forEachValue(new TObjectProcedure() { + @Override + public boolean execute(SheetLineComponent component) { + component.parent = SheetLineComponent.this; + return true; + } + }); + } + } + + @Override + public String toString() { + return solverComponentName + " (" + super.toString() + ")"; + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SheetNode.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetNode.java similarity index 53% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SheetNode.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetNode.java index d2ec679b7..13b198f94 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SheetNode.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetNode.java @@ -1,12 +1,12 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.io.Serializable; import java.util.Map; public interface SheetNode, Property extends SheetNode> extends Serializable { - String getName(); - Map getChildren(); - Map getProperties(); - + String getName(); + Map getChildren(); + Map getProperties(); + } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java new file mode 100644 index 000000000..a5cbfea78 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java @@ -0,0 +1,519 @@ +package org.simantics.spreadsheet.solver; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.simulator.toolkit.StandardNodeManagerSupport; +import org.simantics.simulator.variable.exceptions.NodeManagerException; +import org.simantics.spreadsheet.ExternalRef; +import org.simantics.spreadsheet.SpreadsheetCellStyle; +import org.simantics.spreadsheet.SpreadsheetVisitor; +import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment; +import org.simantics.spreadsheet.synchronization.LineNodeUpdater; +import org.simantics.spreadsheet.synchronization.LineUpdater; +import org.simantics.spreadsheet.synchronization.NullUpdater; +import org.simantics.spreadsheet.synchronization.StyleUpdater; +import org.simantics.structural.synchronization.base.ModuleUpdaterBase; +import org.simantics.structural.synchronization.base.ModuleUpdaterFactoryBase; +import org.simantics.structural.synchronization.base.SolverNameUtil; +import org.simantics.structural.synchronization.utils.ComponentFactory; +import org.simantics.structural.synchronization.utils.MappingBase; +import org.simantics.structural.synchronization.utils.Solver; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.longs.AbstractLongList; +import it.unimi.dsi.fastutil.longs.AbstractLongSet; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongArraySet; +import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet; + +@SuppressWarnings("rawtypes") +public class SpreadsheetBook implements StandardNodeManagerSupport, SpreadsheetElement, Serializable, SheetNode, Solver, SolverNameUtil, ComponentFactory, ModuleUpdaterFactoryBase { + + private static final long serialVersionUID = 7417208688311691396L; + + public Serializable NotAvailableError = new Serializable() { + private static final long serialVersionUID = 2535371785498129460L; + }; + + public Long2ObjectOpenHashMap referenceMap = new Long2ObjectOpenHashMap<>(); + + private Int2ObjectArrayMap styles = new Int2ObjectArrayMap<>(); + public ArrayList sheets = new ArrayList(); + + private SpreadsheetMapping mapping; + + String context; + + private int idCounter = 1; + + private transient boolean disposed = false; + + public SpreadsheetBook(String context) { + getNewId(this); + mapping = new SpreadsheetMapping(new SheetLineComponent("")); + this.context = context; + } + + public Map children = new HashMap<>(); + + private boolean iterationEnabled; + + public int getNewId(SpreadsheetElement element) { + int result = idCounter++; + children.put(result, element); + return result; + } + + public long getEngineIndex(SpreadsheetEngine engine) { + for(int i=0;i getChildren(SheetNode node) { + return node.getChildren(); + } + + @SuppressWarnings("unchecked") + @Override + public Map getProperties(SheetNode node) { + return node.getProperties(); + } + + @Override + public String getName() { + return ""; + } + + @Override + public Map getChildren() { + Map result = new HashMap(); + for(SpreadsheetEngine engine : sheets) + result.put(engine.getName(), engine); + return result; + } + + @Override + public Map getProperties() { + return Collections.emptyMap(); + } + + public SpreadsheetCell get(String sheet, int row, int column) { + SpreadsheetEngine engine = getEngine(sheet); + if(engine == null) return null; + SpreadsheetLine line = engine.getLine(row); + if(line == null) return null; + if(line.cells.size() <= column) return null; + return line.cells.get(column); + } + + public SpreadsheetCell get(SpreadsheetEngine engine, int row, int column) { + SpreadsheetLine line = engine.getLine(row); + if(line == null) return null; + if(line.cells.size() <= column) return null; + return line.cells.get(column); + } + + public SpreadsheetEngine getEngine(String sheet) { + for(SpreadsheetEngine engine : sheets) + if(sheet.equals(engine.getName())) return engine; + return null; + } + + @Override + public ModuleUpdaterBase createUpdater(String id) throws Exception { + if("http://www.simantics.org/Spreadsheet-1.2/Line".equals(id)) + return new LineUpdater(id); + else if("http://www.simantics.org/Spreadsheet-1.2/LineNode".equals(id)) + return new LineNodeUpdater(id); + else if ("http://www.simantics.org/Spreadsheet-1.2/Style".equals(id)) + return new StyleUpdater(id); + else if("http://www.simantics.org/Spreadsheet-1.2/Lines".equals(id)) + return new NullUpdater(id); + else if("http://www.simantics.org/Spreadsheet-1.2/Spreadsheet".equals(id)) + return new NullUpdater(id); + else if("http://www.simantics.org/Spreadsheet-1.2/Book".equals(id)) + return new NullUpdater(id); + else + throw new IllegalStateException("createUpdater " + id); + } + + @Override + public SheetLineComponent create(String uid) { + return new SheetLineComponent(uid); + } + + @Override + public String getFreshName(String parentName, String name) { + return parentName + "/" + name; + } + + @Override + public String ensureNameIsVariationOf(String parentName, int id, String name) { + if (parentName.isEmpty()) + return name; + return parentName + "/" + name; + } + + final static int COMP_ROOT_POS = "COMP_ROOT/".length(); + + @Override + public int getId(String name) { + + if("COMP_ROOT".equals(name)) return 1; + + String path = name.substring(COMP_ROOT_POS); + String[] parts = path.split("/"); + Object o = resolve(parts, 0); + if(o instanceof SpreadsheetLines) { + return ((SpreadsheetLines)o).getId(); + } else if(o instanceof SpreadsheetLine) { + return ((SpreadsheetLine)o).getId(); + } else if(o instanceof SpreadsheetEngine) { + return ((SpreadsheetEngine)o).getId(); + } else if (o instanceof SpreadsheetStyle) { + return ((SpreadsheetStyle) o).getId(); + } + + throw new IllegalStateException("Resolved object for parts " + Arrays.toString(parts) + " is not the right type! It is " + o); + + } + + Object resolve(String[] parts, int index) { + String part = parts[index]; + if (part.startsWith("Style")) { + for (SpreadsheetStyle style : styles.values()) { + if (style.name.equals(part)) { + return style; + } + } + } + SpreadsheetEngine engine = getEngine(part); + if(engine == null) return 0; + if(index == parts.length-1) return engine; + else return engine.resolve(parts, index+1); + } + + @Override + public String getName(int id) { + if(id == -2) return "http://www.simantics.org/Spreadsheet-1.2/Book"; + else if(id == -3) return "http://www.simantics.org/Spreadsheet-1.2/Spreadsheet"; + else if(id == -4) return "http://www.simantics.org/Spreadsheet-1.2/Lines"; + else if(id == -5) + return "http://www.simantics.org/Spreadsheet-1.2/LineNode"; + else if (id == -6) + return "http://www.simantics.org/Spreadsheet-1.2/Line"; + else if(id == -7) + return "http://www.simantics.org/Spreadsheet-1.2/Style"; + else return "" + id; + } + + @Override + public int getModuleType(int id) { + Serializable s = children.get(id); + if(s instanceof SpreadsheetBook) return -2; + else if(s instanceof SpreadsheetEngine) return -3; + else if(s instanceof SpreadsheetLines) { + if("Lines".equals(((SpreadsheetLines) s).getName())) + return -4; + else + return -5; + } + else if(s instanceof SpreadsheetLine) + return -6; + else if (s instanceof SpreadsheetStyle) + return -7; + else throw new IllegalStateException(); + } + + @SuppressWarnings("unchecked") + @Override + public void remove(int id) { + + SpreadsheetElement child = children.get(id); + Optional parent = child.getParent(); + + if (parent.isPresent()) { + parent.get().remove(child); + children.remove(id); + } + } + + @Override + public void addSubprocess(String name, String subprocessType) { + ensureSubprocess(name); + } + + @SuppressWarnings("unchecked") + public T ensureSubprocess(String name) { + String[] parts = name.split("/"); + if(parts.length == 2) { + SpreadsheetEngine engine = getEngine(parts[1]); + if(engine == null) { + engine = new SpreadsheetEngine(this, parts[1]); + sheets.add(engine); + } + return (T)engine; + } else if (parts.length > 2) { + SpreadsheetEngine engine = getEngine(parts[1]); + return (T)engine.ensureSubprocess(parts, 2); + } + throw new IllegalStateException(); + } + + + @Override + public void includeSubprocess(String parentName, String subprocessName) { + // Nop + } + + @SuppressWarnings("unchecked") + @Override + public T getConcreteSolver() { + return (T)this; + } + + @Override + public void accept(SpreadsheetVisitor v) { + v.visit(this); + } + + SpreadsheetCell cellByReferenceKey(long ref) { + long sheet = ref >> 40; + long row = (ref >> 20) & 0xFFFFF; + long col = (ref) & 0xFFFFF; + return get(sheets.get((int)sheet), (int)row, (int)col); + } + + //Recursively find all SpreadsheetCells, invalidate them and return them all as a set + public Set invalidate(SpreadsheetCell cell) { + Set result = new HashSet<>(); + result.add(cell); + cell.invalidate(); + long refKey = cell.makeReferenceKey(); + AbstractLongSet refs = referenceMap.remove(refKey); + if(refs == null) return result; + for(long ref : refs) { + SpreadsheetCell referer = cellByReferenceKey(ref); + result.addAll(invalidate(referer)); + } + return result; + } + + @Deprecated + public List invalidateShallow(SpreadsheetCell cell) { + ArrayList result = new ArrayList<>(); + result.add(cell); + cell.invalidate(); + long refKey = cell.makeReferenceKey(); + AbstractLongSet refs = referenceMap.remove(refKey); + if(refs == null) return result; + for(long ref : refs) { + SpreadsheetCell referer = cellByReferenceKey(ref); + invalidate(referer); + result.add(referer); + } + return result; + } + + public void addStyle(SpreadsheetStyle style) { + if (style.name == null) { + new Exception("Trying to add style to book without name!!").printStackTrace(); + return; + } + style.setSynchronizationId(getNewId(style)); + styles.put(style.getStyleId(), style); + } + + public SpreadsheetStyle getStyle(int styleId) { + return styles.get(styleId); + } + + public MappingBase getMapping() { + return mapping; + } + + @Override + public Optional getParent() { + return Optional.empty(); + } + + @Override + public Collection getSpreadsheetChildren() { + return children.values(); + } + + @Override + public void remove(SpreadsheetElement child) { + // TODO Auto-generated method stub + + } + + public void setIterationEnabled(boolean value) { + this.iterationEnabled = value; + } + + public boolean isIterationEnabled() { + return iterationEnabled; + } + + static Variant DEFAULT_VALUE = Variant.ofInstance("Pending external reference"); + + private Map externalRefMap = new HashMap<>(); + + void registerListening(long referenceKey, ExternalRef ref) { + ExternalRefData data = externalRefMap.get(ref); + if(data == null) { + data = new ExternalRefData(this, referenceKey, ref); + externalRefMap.put(ref, data); + } else { + // Already registered + } + } + + ExternalRefData getExternalRefValue(long referenceKey, ExternalRef ref) { + ExternalRefData data = externalRefMap.get(ref); + if(data == null) { + registerListening(referenceKey, ref); + return new ExternalRefData(this, referenceKey, new ExternalRefConstant(DEFAULT_VALUE)); + } + return data; + } + + public boolean isDisposed() { + return disposed; + } + + public static interface SpreadsheetBookListener { + void cellsChanged(Collection cells); + } + + public void registerListener(SpreadsheetBookListener listener) { + if(listeners == null) + listeners = new ArrayList<>(); + listeners.add(listener); + } + + private transient ArrayList listeners = new ArrayList<>(); + + public void fireChanges(Collection cells) { + for(SpreadsheetBookListener listener : listeners) + listener.cellsChanged(cells); + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java new file mode 100644 index 000000000..5b732cf86 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java @@ -0,0 +1,230 @@ +package org.simantics.spreadsheet.solver; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.ExternalRef; +import org.simantics.spreadsheet.SpreadsheetCellStyle; +import org.simantics.spreadsheet.SpreadsheetVisitor; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.CellValueVisitor; +import org.simantics.spreadsheet.solver.formula.FormulaError2; +import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; + +@SuppressWarnings("rawtypes") +public class SpreadsheetCell implements SpreadsheetElement, SheetNode { + + private static final long serialVersionUID = 6616793596542239339L; + + public static SpreadsheetCell EMPTY; + + static { + EMPTY = new SpreadsheetCell(null, -1); + EMPTY.setContent(""); + EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId()); + } + + private boolean inProgress = false; + private int iterations = 0; + + final private SpreadsheetLine line; + final private int column; + int style; + private Object content; + final private Map properties; + + public SpreadsheetCell(SpreadsheetLine line, int column) { + this.properties = createProperties(); + this.line = line; + this.column = column; + } + + //All SpreadsheetCells have these properties - create them when object is created + private Map createProperties() { + Map p = new HashMap<>(); + p.put("typeURI", new SpreadsheetTypeNode(Spreadsheets.CELL_TYPE_URI)); + p.put("content", new SpreadsheetCellContent(this)); + p.put("style", new SpreadsheetCellStyle(this)); + p.put("editable", new SpreadsheetCellEditable(this)); + return p; + } + + public boolean hasExpression() { + return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; + } + + public void setContent(Object newContent) { + this.content = newContent; + } + + public int getColumn() { + return column; + } + + @Override + public String getName() { + return Spreadsheets.cellName(line.row, column); + } + + @Override + public Map getChildren() { + return Collections.emptyMap(); + } + + @Override + public Map getProperties() { + return properties; + } + + public SpreadsheetBook getBook() { + return line.getEngine().getBook(); + } + + public SpreadsheetEngine getEngine() { + return line.getEngine(); + } + + public T evaluate(SpreadsheetEvaluationEnvironment env) { + return evaluate(env, null); + } + + @SuppressWarnings("unchecked") + public T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) { + if(caller != null) + caller.addReference(makeReferenceKey()); + if(content instanceof SpreadsheetFormula) { + SpreadsheetFormula f = (SpreadsheetFormula)content; + if(f.result == null) { + CellValueVisitor visitor = new CellValueVisitor(env, this); + AstValue value = ((SpreadsheetFormula)content).value; + if(this.inProgress == true) this.iterations++; + + if(!env.getBook().isIterationEnabled()){ + if(this.inProgress == false){ + this.inProgress = true; + f.result = value.accept(visitor); + } + else f.result = FormulaError2.CIRCULAR_REF.getString(); + } + else if(this.iterations getParent() { + return Optional.of(line); + } + + @Override + public List getSpreadsheetChildren() { + return Collections.emptyList(); + } + + @Override + public void remove(SpreadsheetElement child) { + // TODO Auto-generated method stub + + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + column; + result = prime * result + ((line == null) ? 0 : line.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SpreadsheetCell other = (SpreadsheetCell) obj; + if (column != other.column) + return false; + if (line == null) { + if (other.line != null) + return false; + } else if (!line.equals(other.line)) + return false; + return true; + } + + public void setStyle(int styleId) { + this.style = styleId; + } + + public int getStyle() { + return style; + } + + public Object getContent() { + return content; + } + + public static SpreadsheetCell empty(SpreadsheetLine line, int column) { + SpreadsheetCell cell = new SpreadsheetCell(line, column); + cell.setContent(""); + cell.setStyle(SpreadsheetStyle.empty().getStyleId()); + return cell; + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContent.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContent.java similarity index 53% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContent.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContent.java index 3c1a4ff25..5358d2673 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContent.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContent.java @@ -1,34 +1,37 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.util.Collections; import java.util.Map; +@SuppressWarnings("rawtypes") public class SpreadsheetCellContent implements SheetNode { - public final SpreadsheetCell cell; - - public SpreadsheetCellContent(SpreadsheetCell cell) { - this.cell = cell; - } - - @Override - public String getName() { - return "content"; - } - - @Override - public Map getChildren() { - return Collections.emptyMap(); - } - - @Override - public Map getProperties() { - if(cell.hasExpression()) { - return Collections.singletonMap("expression", new SpreadsheetCellContentExpression(cell)); - } else { - return Collections.emptyMap(); - } - } + private static final long serialVersionUID = 6463195673537211769L; + + public final SpreadsheetCell cell; + + public SpreadsheetCellContent(SpreadsheetCell cell) { + this.cell = cell; + } + + @Override + public String getName() { + return "content"; + } + + @Override + public Map getChildren() { + return Collections.emptyMap(); + } + + @Override + public Map getProperties() { + if(cell.hasExpression()) { + return Collections.singletonMap("expression", new SpreadsheetCellContentExpression(cell)); + } else { + return Collections.emptyMap(); + } + } @Override public int hashCode() { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContentExpression.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContentExpression.java similarity index 61% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContentExpression.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContentExpression.java index 7c0b0263c..b90136793 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContentExpression.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContentExpression.java @@ -1,29 +1,32 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.util.Collections; import java.util.Map; +@SuppressWarnings("rawtypes") public class SpreadsheetCellContentExpression implements SheetNode { - public final SpreadsheetCell cell; - - public SpreadsheetCellContentExpression(SpreadsheetCell cell) { - this.cell = cell; - } - + private static final long serialVersionUID = 917517945851971254L; + + public final SpreadsheetCell cell; + + public SpreadsheetCellContentExpression(SpreadsheetCell cell) { + this.cell = cell; + } + + @Override + public String getName() { + return "expression"; + } + + @Override + public Map getChildren() { + return Collections.emptyMap(); + } + @Override - public String getName() { - return "expression"; - } - - @Override - public Map getChildren() { - return Collections.emptyMap(); - } - - @Override - public Map getProperties() { - return Collections.emptyMap(); + public Map getProperties() { + return Collections.emptyMap(); } @Override diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellEditable.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellEditable.java similarity index 62% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellEditable.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellEditable.java index 81033f44c..246bd705b 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellEditable.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellEditable.java @@ -1,14 +1,17 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.util.Collections; import java.util.Map; import org.simantics.databoard.binding.mutable.Variant; +@SuppressWarnings("rawtypes") public class SpreadsheetCellEditable implements SheetNode { - public final SpreadsheetCell cell; + private static final long serialVersionUID = -5078387091775971986L; + public final SpreadsheetCell cell; + public SpreadsheetCellEditable(SpreadsheetCell spreadsheetCell) { this.cell = spreadsheetCell; } @@ -27,7 +30,7 @@ public class SpreadsheetCellEditable implements SheetNode { public Map getProperties() { return Collections.emptyMap(); } - + @Override public int hashCode() { final int prime = 31; @@ -54,22 +57,22 @@ public class SpreadsheetCellEditable implements SheetNode { } public boolean editable() { - if (cell.content == null || cell.content instanceof SpreadsheetFormula || cell.content instanceof SpreadsheetSCLConstant) + if (cell.getContent() == null || cell.getContent() instanceof SpreadsheetFormula || cell.getContent() instanceof SpreadsheetSCLConstant) return false; - if (cell.content instanceof String) { - String content = (String) cell.content; - if (content.isEmpty()) - return false; + if (cell.getContent() instanceof String) { + String content = (String) cell.getContent(); + if (content.isEmpty()) + return false; } - if (cell.content instanceof Variant) { - Variant content = (Variant) cell.content; - if (content.getValue() == null) - return false; - if (content.getValue() instanceof String) { - String actualContent = (String) content.getValue(); - if (actualContent.isEmpty()) - return false; - } + if (cell.getContent() instanceof Variant) { + Variant content = (Variant) cell.getContent(); + if (content.getValue() == null) + return false; + if (content.getValue() instanceof String) { + String actualContent = (String) content.getValue(); + if (actualContent.isEmpty()) + return false; + } } // System.out.println("content is " + cell.content); return true; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetElement.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetElement.java similarity index 78% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetElement.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetElement.java index 71bbd8f97..05c4f1da3 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetElement.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetElement.java @@ -1,9 +1,11 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.io.Serializable; import java.util.Collection; import java.util.Optional; +import org.simantics.spreadsheet.SpreadsheetVisitable; + public interface SpreadsheetElement, Parent extends SpreadsheetElement> extends SpreadsheetVisitable, Serializable { Optional getParent(); diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java new file mode 100644 index 000000000..9ccbc6d1e --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java @@ -0,0 +1,163 @@ +package org.simantics.spreadsheet.solver; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.SpreadsheetVisitor; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange; + +@SuppressWarnings("rawtypes") +public class SpreadsheetEngine implements SpreadsheetElement, SheetNode { + + private static final long serialVersionUID = -5246063647558595642L; + + private static final String LINES = "Lines"; + + private final SpreadsheetBook book; + private final String name; + private final int id; + + public SpreadsheetLines lines; + + transient public Map rangeCache; + + public Map getRangeCache() { + if(rangeCache == null) rangeCache = new HashMap(); + return rangeCache; + } + + public Object getCachedRange(AstRange range) { + if(range.sheetName != null) return null; + return getRangeCache().get(range.first + ":" + range.second); + } + + public void cacheRange(AstRange range, Object value) { + if(range.sheetName != null) return; + getRangeCache().put(range.first + ":" + range.second, value); + } + + public SpreadsheetEngine(SpreadsheetBook book, String name) { + this.book = book; + this.name = name; + this.id = book.getNewId(this); + this.lines = new SpreadsheetLines(this, LINES); + } + + public SpreadsheetBook getBook() { + return book; + } + + public int getId() { + return id; + } + + Object resolve(String[] parts, int index) { + + String part = parts[index]; + if(!part.equals(LINES)) return null; + + if(index == parts.length-1) return lines; + + return lines.resolve(parts, index+1); + + } + + @Override + public String getName() { + return name; + } + + @Override + public Map getChildren() { + return Collections.singletonMap(LINES, lines); + } + + @Override + public Map getProperties() { + return Collections.emptyMap(); + } + + public Object ensureSubprocess(String[] path, int index) { + + String name = path[index]; + if(!LINES.equals(name)) throw new IllegalStateException(); + if(index == path.length - 1) return lines; + return lines.ensureSubprocess(path, index+1); + + } + + public SpreadsheetLine getLine(int row) { + assert(lines.nodes.size() == 1); + SpreadsheetLines root = lines.nodes.values().iterator().next(); + return root.getLine(row); + } + + @Override + public void accept(SpreadsheetVisitor v) { + v.visit(this); + } + + public Range actualRange(Range r) { + if(r.isFullRows()) { + SpreadsheetLines root = lines.nodes.values().iterator().next(); + Range result = new Range(r); + result.startRow = 0; + result.endRow = root.getMaxRow(); + return result; + } else { + return r; + } + } + + @Override + public Optional getParent() { + return Optional.of(book); + } + + @Override + public List getSpreadsheetChildren() { + return Collections.singletonList(lines); + } + + @Override + public void remove(SpreadsheetElement child) { + + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((book == null) ? 0 : book.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SpreadsheetEngine other = (SpreadsheetEngine) obj; + if (book == null) { + if (other.book != null) + return false; + } else if (!book.equals(other.book)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetFormula.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetFormula.java similarity index 62% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetFormula.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetFormula.java index d171fd87e..693335669 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetFormula.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetFormula.java @@ -1,21 +1,25 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.io.Serializable; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; public class SpreadsheetFormula implements Serializable { - - private static final long serialVersionUID = -3369406031425959191L; - - public AstValue value; - public String expression; - public Object result; - - public SpreadsheetFormula(AstValue value, String expression) { - this.value = value; - this.expression = expression; - } + + public static Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetFormula.class); + + private static final long serialVersionUID = -3369406031425959191L; + + public AstValue value; + public String expression; + public Object result; + + public SpreadsheetFormula(AstValue value, String expression) { + this.value = value; + this.expression = expression; + } @Override public int hashCode() { @@ -41,7 +45,7 @@ public class SpreadsheetFormula implements Serializable { return false; return true; } - + @Override public String toString() { return getClass().getSimpleName() + " [" + expression +" => " + result != null ? result.toString() : "" + "]"; diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java new file mode 100644 index 000000000..d11fdc6d2 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java @@ -0,0 +1,123 @@ +package org.simantics.spreadsheet.solver; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.SpreadsheetVisitor; +import org.simantics.spreadsheet.Spreadsheets; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +@SuppressWarnings("rawtypes") +public class SpreadsheetLine implements SpreadsheetElement, SheetNode { + + private static final long serialVersionUID = -304574098117404663L; + + final private SpreadsheetLines parent; + final public int row; + int id; + + public ObjectArrayList cells = new ObjectArrayList<>(); + + public SpreadsheetLine(SpreadsheetLines parent, int row) { + this.parent = parent; + this.row = row; + this.id = getEngine().getBook().getNewId(this); + } + + public int getId() { + return id; + } + + public SpreadsheetEngine getEngine() { + return ((SpreadsheetLines)parent).getEngine(); + } + + @Override + public String getName() { + return "Row"+row; + } + + @Override + public Map getChildren() { + String rowName = ""+row; + Map result = new HashMap<>(); + for(int i=0;i getParent() { + return Optional.of(parent); + } + + @Override + public List getSpreadsheetChildren() { + return cells; + } + + @Override + public void remove(SpreadsheetCell child) { + + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((parent == null) ? 0 : parent.hashCode()); + result = prime * result + row; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SpreadsheetLine other = (SpreadsheetLine) obj; + if (parent == null) { + if (other.parent != null) + return false; + } else if (!parent.equals(other.parent)) + return false; + if (row != other.row) + return false; + return true; + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java new file mode 100644 index 000000000..e53d7cb61 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java @@ -0,0 +1,209 @@ +package org.simantics.spreadsheet.solver; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +import org.simantics.spreadsheet.SpreadsheetVisitor; +import org.simantics.spreadsheet.Spreadsheets; + +import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap; + +@SuppressWarnings("rawtypes") +public class SpreadsheetLines implements SpreadsheetElement, SheetNode { + + private static final long serialVersionUID = -3615335969248723486L; + + private final int id; + private SpreadsheetEngine parent; + private String name; + public Int2ObjectAVLTreeMap nodes = new Int2ObjectAVLTreeMap(); + public Int2ObjectAVLTreeMap lines = new Int2ObjectAVLTreeMap(); + public int[] keys; + + public SpreadsheetLines(SpreadsheetEngine parent, String name) { + this.parent = parent; + this.name = name; + id = getEngine().getBook().getNewId(this); + } + + public SpreadsheetEngine getEngine() { + return parent; + } + + public int getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @SuppressWarnings({ "unchecked" }) + @Override + public Map getChildren() { + Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap(); + result.putAll(nodes); + result.putAll(lines); + return result; + } + + @Override + public Map getProperties() { + return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINES_TYPE_URI)); + } + + Object resolve(String[] parts, int index) { + + String part = parts[index]; + if(part.charAt(0) == 'R') { + int indx = Integer.parseInt(part.substring(3)); + SpreadsheetLine line = lines.get(-indx); + if(line != null) { + if(index == parts.length-1) return line; + else return line.resolve(parts, index+1); + } + } else { + int indx = Integer.parseInt(part); + SpreadsheetLines node = nodes.get(indx); + if(node != null) { + if(index == parts.length-1) return node; + else return node.resolve(parts, index+1); + } + } + + return null; + + } + + public Object ensureSubprocess(String[] path, int index) { + + String name = path[index]; + + int i = Integer.parseInt(name); + SpreadsheetLines line = nodes.get(i); + if(line == null) { + line = new SpreadsheetLines(parent, "" + i); + nodes.put(i, line); + } + + if(index == path.length - 1) { + return line; + } else { + return line.ensureSubprocess(path, index+1); + } + + } + + public void setKeys(int[] keys) { + this.keys = keys; + } + + @Override + public void accept(SpreadsheetVisitor v) { + v.visit(this); + } + + public String getPath() { + return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName(); + } + + private int getKey(int index) { + return keys[2*index+1]; + } + + private int getChild(int index) { + return keys[2*index]; + } + + /* + * [(child,key),...,key) + * + */ + public SpreadsheetLine getLine(int k) { + + int i=1; + int n = (keys.length - 1) / 2; + + while(i <= n && k > getKey(i-1)) i++; + + if(i <= n && k == getKey(i-1)) { + return lines.get(-k); + } + + int nodeName = getChild(i-1); + SpreadsheetLines node = nodes.get(nodeName); + if(node == null) return null; + return node.getLine(k); + + } + + public int getMaxRow() { + // if keys == null then this is the root of BTree which has only one child + if (keys == null) { + int maxRow = 0; + for (SpreadsheetLines node : nodes.values()) { + int row = node.getMaxRow(); + if (row > maxRow) + maxRow = row; + } + return maxRow; + } + int largestChild = keys[keys.length-1]; + if(largestChild > 0) { + SpreadsheetLines child = nodes.get(largestChild); + return child.getMaxRow(); + } else { + return keys[keys.length-2]; + } + } + + @Override + public Optional getParent() { + return Optional.of(parent); + } + + @Override + public Collection getSpreadsheetChildren() { + return lines.values(); + } + + @Override + public void remove(SpreadsheetLine child) { + lines.remove(-child.row); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((parent == null) ? 0 : parent.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SpreadsheetLines other = (SpreadsheetLines) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (parent == null) { + if (other.parent != null) + return false; + } else if (!parent.equals(other.parent)) + return false; + return true; + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java new file mode 100644 index 000000000..e08c6c080 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java @@ -0,0 +1,53 @@ +package org.simantics.spreadsheet.solver; + +import java.io.Serializable; + +import org.simantics.structural.synchronization.utils.ComponentFactory; +import org.simantics.structural.synchronization.utils.MappingBase; +import org.simantics.structural.synchronization.utils.Solver; +import org.simantics.structural.synchronization.utils.StateUndoContextBase; + +public class SpreadsheetMapping extends MappingBase implements Serializable { + + private static final long serialVersionUID = -7556699663877911393L; + + final SheetLineComponent configuration; + + public SpreadsheetMapping(SheetLineComponent configuration) { + super(configuration, true); + this.configuration = configuration; + } + + @Override + public SheetLineComponent getConfiguration() { + return configuration; + } + + @Override + public StateUndoContextBase createUndoContext() { + return new StateUndoContextBase() { + + @Override + public void saveState(Solver solver, int componentId, String uid) { + } + + @Override + public boolean loadState(Solver solver, int componentId, String uid) { + return false; + } + }; + } + + @Override + public ComponentFactory createComponentFactory() { + return new ComponentFactory() { + + @Override + public SheetLineComponent create(String uid) { + return new SheetLineComponent(uid); + } + + }; + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSCLConstant.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetSCLConstant.java similarity index 84% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSCLConstant.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetSCLConstant.java index e8d38b2c5..cc0148edb 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSCLConstant.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetSCLConstant.java @@ -1,4 +1,4 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.io.Serializable; @@ -9,15 +9,23 @@ public class SpreadsheetSCLConstant implements Serializable { private static final long serialVersionUID = 428064772427245449L; - public String expression; - public Object content; - + private String expression; + private Object content; + public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetSCLConstant.class); public SpreadsheetSCLConstant(String expression, Object object) { this.content = object; this.expression = expression; } + + public Object getContent() { + return content; + } + + public String getExpression() { + return expression; + } @Override public String toString() { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetStyle.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetStyle.java similarity index 81% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetStyle.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetStyle.java index ecd22175e..33dd5347b 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetStyle.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetStyle.java @@ -1,66 +1,70 @@ -package org.simantics.spreadsheet.graph; +package org.simantics.spreadsheet.solver; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Optional; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; import org.simantics.datatypes.literal.Font; import org.simantics.datatypes.literal.RGB; +import org.simantics.spreadsheet.SpreadsheetVisitor; +@SuppressWarnings("rawtypes") public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement { -// public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetStyle.class); - + public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetStyle.class); + private static final SpreadsheetStyle EMPTY = SpreadsheetStyle.newInstace().name("Style_E").build(); - + private static final long serialVersionUID = -4969920277489585741L; - + public final String name; - public final int border; - public final int align; - public final Font font; - public final RGB.Integer foreground; - public final RGB.Integer background; - public final boolean locked; - public final int rowSpan; - public final int columnSpan; - - private transient int synchronizationId; + public final int border; + public final int align; + public final Font font; + public final RGB.Integer foreground; + public final RGB.Integer background; + public final boolean locked; + public final int rowSpan; + public final int columnSpan; + + private transient int synchronizationId; private transient final int hashCode; public final String formatString; public final int formatIndex; - - public SpreadsheetStyle(String name, int border, int align2, Font font2, RGB.Integer foreground2, RGB.Integer background2, boolean locked2, int rowSpan2, int columnSpan2, String formatString, short formatIndex) { - this.name = name; - this.border = border; - this.align = align2; - this.font = font2; - this.foreground = foreground2; - this.background = background2; - this.locked = locked2; - this.rowSpan = rowSpan2; - this.columnSpan = columnSpan2; - - this.formatString = formatString; - this.formatIndex = formatIndex; - - - this.hashCode = hashCode(); + + public SpreadsheetStyle(String name, int border, int align2, Font font2, RGB.Integer foreground2, RGB.Integer background2, boolean locked2, int rowSpan2, int columnSpan2, String formatString, short formatIndex) { + this.name = name; + this.border = border; + this.align = align2; + this.font = font2; + this.foreground = foreground2; + this.background = background2; + this.locked = locked2; + this.rowSpan = rowSpan2; + this.columnSpan = columnSpan2; + + this.formatString = formatString; + this.formatIndex = formatIndex; + + + this.hashCode = hashCode(); + } + + public int getId() { + return synchronizationId; + } + + public int getStyleId() { + return hashCode(); } - - public int getId() { - return synchronizationId; - } - - public int getStyleId() { - return hashCode(); - } @Override public void accept(SpreadsheetVisitor v) { - + } @Override @@ -75,7 +79,7 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() == 0) + throw new IllegalStateException(); + Boolean finalResult = Boolean.TRUE; + for (int i = 0; i < args.values.size(); i++) { + Object res = (args.values.get(i).accept(visitor)); + FormulaError2 err = FormulaError2.forObject(res); + if(err!=null) return err.getString(); + + if ((res instanceof Boolean && !((Boolean)res)) || !Spreadsheets.asBoolean(res)) + finalResult = Boolean.FALSE; + } + return finalResult; + } +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java new file mode 100644 index 000000000..05528e27c --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java @@ -0,0 +1,51 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; + +public class AverageFormulaFunction implements CellFormulaFunction { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() == 0) + throw new IllegalStateException(); + Double sum = 0.0; + double count = 0.0; + for(AstValue value : args.values){ + Object res = value.accept(visitor); + if (res instanceof SpreadsheetMatrix) { + Object value2 = ((SpreadsheetMatrix) res).sumWithFormulaError(); + if(value2 instanceof String) return value2; + + sum += ((Number)value2).doubleValue(); + count += ((SpreadsheetMatrix) res).countOfActualDoubleValues(); + } else { + FormulaError2 err = FormulaError2.forObject(res); + if(err!=null) return err.getString(); + + if(res instanceof Variant){ + Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(res); + if(dVal==null) res = ((Variant)res).toString(); + else res = dVal; + } + + Double v = null; + if(res instanceof String && !res.equals("")){ + v = Spreadsheets.asDoubleWhereEmptyStringIsZero(res); + } + else if(res instanceof Number) + v = Spreadsheets.asDoubleWhereEmptyStringIsZero(res); + + if(v!=null){ + sum += v; + count++; + } + } + } + if(count==0.0) return FormulaError2.DIV0.getString(); + return sum/count; + } +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java new file mode 100644 index 000000000..d04bea1cf --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java @@ -0,0 +1,9 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; + +public interface CellFormulaFunction { + + T evaluate(CellValueVisitor visitor, AstArgList args); + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java new file mode 100644 index 000000000..fd5ecd167 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java @@ -0,0 +1,481 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.Range; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetCell; +import org.simantics.spreadsheet.solver.SpreadsheetEngine; +import org.simantics.spreadsheet.solver.SpreadsheetLine; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstApply; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArithmeticExpression; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArray; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstBoolean; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstDouble; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstFactor; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstIdentifier; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstInteger; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstNull; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstRelation; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstString; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstTerm; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValueVisitor; + +import it.unimi.dsi.fastutil.longs.AbstractLongList; +import it.unimi.dsi.fastutil.longs.LongArrayList; + +public class CellValueVisitor implements AstValueVisitor { + + final public SpreadsheetBook book; + final private SpreadsheetEvaluationEnvironment env; + final private SpreadsheetCell thisCell; + final private LongArrayList references = new LongArrayList(); + + public CellValueVisitor(SpreadsheetEvaluationEnvironment env, SpreadsheetCell thisCell) { + this.book = env.getBook(); + this.env = env; + this.thisCell = thisCell; + } + + public void addReference(long ref) { + references.add(ref); + } + + public AbstractLongList getReferences() { + return references; + } + + @Override + public Object visit(AstBoolean astBoolean) { + return astBoolean.value; + } + + @Override + public Object visit(AstDouble astFloat) { + return astFloat.value; + } + + @Override + public Object visit(AstInteger astInteger) { + return astInteger.value; + } + + @Override + public Object visit(AstNull astNull) { + throw new IllegalStateException(); + } + + @Override + public Object visit(AstString astString) { + return astString.value; + } + + @Override + public Object visit(AstRange astRange) { + + if(astRange.isRef()){ + return FormulaError2.REF.getString(); + } + + if(astRange.isCell()) { + String ref = astRange.first; + Range r = Spreadsheets.decodeCell(ref, 0, 0); + String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); + SpreadsheetCell cell = thisCell.getBook().get(sheetName, r.startRow, r.startColumn); + if(cell == null) { + SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); + SpreadsheetLine line = eng.getLine(r.startRow); + + if (line == null) { + line = new SpreadsheetLine(eng.lines, r.startRow); + eng.lines.lines.put(-r.startRow, line); + } + cell = SpreadsheetCell.empty(line, r.startColumn); + } + return cell.evaluate(env, this); + + } else { + + Object cached = thisCell.getEngine().getCachedRange(astRange); + if(cached != null) { + + Range r_ = Spreadsheets.decodeRange(astRange.first + ":" + astRange.second); + String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); + SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); + Range r = eng.actualRange(r_); + for(int row=0; row < r.height();row++) { + SpreadsheetLine line = eng.getLine(r.startRow + row); + if(line != null) { + for(int column=0; column < r.width();column++) { + int col = r.startColumn + column; + if(line.cells.size() > col) { + SpreadsheetCell cell = line.cells.get(r.startColumn + column); + //Add references, but do not evaluate if there exists a cached range. + addReference(cell.makeReferenceKey()); + } + } + } + } + return cached; + } + + Range r_ = Spreadsheets.decodeRange(astRange.first + ":" + astRange.second); + String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); + SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); + // Full ranges are resolved here + Range r = eng.actualRange(r_); + SpreadsheetMatrix result = new SpreadsheetMatrix(r.width(), r.height()); + for(int row=0; row < r.height();row++) { + SpreadsheetLine line = eng.getLine(r.startRow + row); + if(line != null) { + for(int column=0; column < r.width();column++) { + int col = r.startColumn + column; + if(line.cells.size() > col) { + SpreadsheetCell cell = line.cells.get(r.startColumn + column); + result.values[r.width()*row + column] = cell.evaluate(env, this); + } + } + } + } + thisCell.getEngine().cacheRange(astRange, result); + return result; + } + } + + @Override + public Object visit(AstArgList astArgList) { + throw new IllegalStateException(); + } + + @Override + public Object visit(AstApply astApply) { + CellFormulaFunction fn = env.getFunction(astApply.value); + if(fn != null) { + return fn.evaluate(this, astApply.args); + } else { + return FormulaError2.NAME.getString(); + } + } + + @Override + public Object visit(AstRelation astRelation) { + + Object leftResult = astRelation.left.accept(this); + Object rightResult = astRelation.right.accept(this); + + FormulaError2 err = FormulaError2.forObject(leftResult); + if(err!=null) return err.getString(); + FormulaError2 err2 = FormulaError2.forObject(rightResult); + if(err2!=null) return err2.getString(); + + if(leftResult instanceof Variant){ + Object leftTemp = ((Variant)leftResult).getValue(); + Double leftVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftTemp); + if(leftVal==null) leftResult = leftTemp.toString(); + else leftResult = leftVal; + } + if(rightResult instanceof Variant){ + Object rightTemp = ((Variant)rightResult).getValue(); + Double rightVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightTemp); + if(rightVal==null) rightResult = rightTemp.toString(); + else rightResult = rightVal; + } + if ((leftResult instanceof String) && (rightResult instanceof String)) { + String leftString = (leftResult.toString()).toLowerCase(); + String rightString = (rightResult.toString()).toLowerCase(); + if("<".equals(astRelation.op.trim())) return leftString.compareTo(rightString) < 0; + else if(">".equals(astRelation.op.trim())) return leftString.compareTo(rightString) > 0; + else if("=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) == 0; + else if("<>".equals(astRelation.op.trim())) return leftString.compareTo(rightString) != 0 ; + else if("<=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) <= 0 ; + else if(">=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) >= 0 ; + else throw new IllegalStateException(); + } else { + Number leftNumber = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftResult); + Number rightNumber = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightResult); + if(leftNumber==null || rightNumber==null) return false; + if("<".equals(astRelation.op.trim())) return leftNumber.doubleValue() < rightNumber.doubleValue(); + else if(">".equals(astRelation.op.trim())) return leftNumber.doubleValue() > rightNumber.doubleValue(); + else if("=".equals(astRelation.op.trim())) return leftNumber.doubleValue() == rightNumber.doubleValue(); + else if("<>".equals(astRelation.op.trim())) return leftNumber.doubleValue() != rightNumber.doubleValue(); + else if("<=".equals(astRelation.op.trim())) return leftNumber.doubleValue() <= rightNumber.doubleValue(); + else if(">=".equals(astRelation.op.trim())) return leftNumber.doubleValue() >= rightNumber.doubleValue(); + else throw new IllegalStateException(); + } + } + + Object leftValueWithPrefix(Object result, AstValue value, String prefix, boolean forceNumber) { + if(result == null) { + Object obj = value.accept(this); + FormulaError2 err = FormulaError2.forObject(obj); + if(err!=null) return err.getString(); + + if("-".equals(prefix)) { + result = Spreadsheets.asNumber(obj); + return -((Number)result).doubleValue(); + } else { + if(forceNumber) return Spreadsheets.asNumber(obj); + else return obj; + } + } + try{ + return (Number)Double.parseDouble(result.toString()); + } catch (NumberFormatException e){ + return result; + } + } + + @Override + public Object visit(AstArithmeticExpression exp) { + Object result = null; + Object other = null; + AstValue value = null; + Object acceptedValue = null; + + for(int i=0;i { + + @Override + public Integer evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() != 2) throw new IllegalStateException(); + + AstRange range = (AstRange) args.values.get(0); + SpreadsheetMatrix matrix = (SpreadsheetMatrix) range.accept(visitor); + Object crit = null; + try { + crit = args.values.get(1).accept(visitor); + } catch (IllegalStateException e){ + return 0; + } + + String criteria = Spreadsheets.asString(crit); + int result = 0; + for (Object value : matrix.values) { + if (Spreadsheets.matchCriteria(value, criteria)) + result++; + } + return Integer.valueOf(result); + } +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java new file mode 100644 index 000000000..d0f2b92ab --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java @@ -0,0 +1,55 @@ +package org.simantics.spreadsheet.solver.formula; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.util.Internal; +import org.simantics.databoard.binding.mutable.Variant; + +public enum FormulaError2{ + @Internal + _NO_ERROR(-1, "(no error)"),NULL(0x00, "#NULL"),DIV0(0x07,"#DIV/0!"),VALUE(0x0F, + "#VALUE!"),REF(0x17,"#REF!"),NAME(0x1D,"#NAME?"),NUM(0x24,"#NUM!"),NA(0x2A, "#N/A"), + CIRCULAR_REF(0xFFFFFFC4, "~CIRCULAR~REF~"),FUNCTION_NOT_IMPLEMENTED(0xFFFFFFE2,"~FUNCTION~NOT~IMPLEMENTED~"); + + private final String text; + //private final Integer longType; + //private final byte shortType; + + private static Map smap = new HashMap(); + + private FormulaError2(int type, String text){ + //this.longType = type; + //this.shortType = (byte)type; + this.text = text; + } + + static { + for(FormulaError2 error : values()) { + smap.put(error.getString(), error); + } + } + + public String getString(){ + return this.text; + } + + public static FormulaError2 forString(String errorName){ + FormulaError2 err = smap.get(errorName); + return err; + } + + public static FormulaError2 forObject(Object errorObj){ + if(errorObj instanceof Variant) + return forString(((Variant)errorObj).getValue().toString()); + else + return forString(errorObj.toString()); + } + + public static String handleErrorCall(Object value){ + if(value==null) return VALUE.getString(); + FormulaError2 error = FormulaError2.forObject(value); + if(error!=null) return error.getString(); + return VALUE.getString(); + } +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java new file mode 100644 index 000000000..25f3f5814 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java @@ -0,0 +1,45 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; + +public class GeomeanFormulaFunction implements CellFormulaFunction { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() == 0) + throw new IllegalStateException(); + double result = 1.0; + double count = 0.0; + for (AstValue value : args.values){ + Object r = value.accept(visitor); + if (r instanceof SpreadsheetMatrix) { + Object v = ((SpreadsheetMatrix) r).productWithFormulaError(); + if(v instanceof String) return v; + double dval = ((Number)v).doubleValue(); + if(dval!=0.0){ + result = result*dval; + count += ((SpreadsheetMatrix) r).countOfActualDoubleValues(); + } + } else { + FormulaError2 error = FormulaError2.forObject(r); + if(error!=null) return error.getString(); + + Number vNum = Spreadsheets.asValidNumber(r); + Double v = null; + if(vNum!=null) v = vNum.doubleValue(); + + if(v!=null){ + if(v<=0) return FormulaError2.NUM.getString(); + result = result*v; + count++; + } + } + } + if(result==0.0 || count==0.0) return FormulaError2.NUM.getString(); + return Double.valueOf(Math.pow(result, (1.0/count))); + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java new file mode 100644 index 000000000..c5e4a3ec3 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java @@ -0,0 +1,137 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; + +public class HlookupFormulaFunction implements CellFormulaFunction { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException(); + + Object lookupValue = args.values.get(0).accept(visitor); + boolean lookupIsString = lookupValue instanceof String; + + FormulaError2 error = FormulaError2.forObject(lookupValue); + if(error!=null) return error.getString(); + + if(lookupValue instanceof Variant){ + Object varVal = ((Variant)lookupValue).getValue(); + Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(varVal); + if(dVal==null) { + lookupValue = varVal.toString(); + lookupIsString = true; + } + else lookupValue = dVal; + } + + SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); + + boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true; + + if(array.values.length != 0){ + if(lookupIsString){ + Object obj = array.values[0]; + if(obj instanceof Variant) + obj = ((Variant)obj).getValue(); + if(Spreadsheets.asValidNumber(obj)!=null) + return FormulaError2.NA.getString(); + obj = obj.toString(); + String valStr = ((String)obj).toLowerCase(); + if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 ) + return FormulaError2.NA.getString(); + } + else if(lookupValue instanceof Number){ + Double d = ((Number)lookupValue).doubleValue(); + Number d2 = Spreadsheets.asValidNumber(array.values[0]); + if(d2==null || d<(d2.doubleValue())) + return FormulaError2.NA.getString(); + } + } + + Number rowIndexN = (Number) Spreadsheets.asValidNumber(args.values.get(2).accept(visitor)); + if(rowIndexN==null) return FormulaError2.REF.getString(); + int rowIndexNum = rowIndexN.intValue(); + if(rowIndexNum>array.getHeight()) return FormulaError2.REF.getString(); + + if (approximateMatch) { + Integer colPosOfLargestValSmallerThanLookUp = null; + if(lookupIsString){ + String largestValSmallerThanLookUp = null; + String ref = lookupValue.toString(); + String previousValue = null; + for(int i = 0; i < array.getWidth(); i++){ + Object val = array.get(0, i); + if(val instanceof Variant) + val = ((Variant)val).getValue(); + String currValue = val.toString(); + int currCompedToRef = currValue.compareTo(ref); + if(currCompedToRef>=0){ + if(i==0) + return array.get(rowIndexNum-1, i); + else if(previousValue.compareTo(ref) > currCompedToRef ) + return array.get(rowIndexNum-1, i); + else + return array.get(rowIndexNum - 1, i - 1); + } + if(colPosOfLargestValSmallerThanLookUp==null){ + colPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = currValue; + } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){ + colPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = currValue; + } + previousValue = currValue; + } + + } else { + double ref = Spreadsheets.asNumber(lookupValue); + double lastDiff = Double.MIN_VALUE; + Double largestValSmallerThanLookUp = null; + for (int i = 0; i < array.getWidth(); i++) { + Object value = array.get(0, i); + double n = Spreadsheets.asNumber(value); + double diff = n - ref; + if (diff >= 0) { + if (i == 0) + return array.get(rowIndexNum - 1, i); + else if (diff < -lastDiff) + return array.get(rowIndexNum - 1, i); + else + return array.get(rowIndexNum - 1, i - 1); + } + if(colPosOfLargestValSmallerThanLookUp==null){ + colPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = n; + } else if(largestValSmallerThanLookUp < n){ + colPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = n; + } + lastDiff = diff; + } + } + if(colPosOfLargestValSmallerThanLookUp!=null) return array.get(rowIndexNum - 1, colPosOfLargestValSmallerThanLookUp); + + } else { + + for (int i = 0; i < array.getWidth(); i++) { + Object value = array.get(0, i); + if(value instanceof Variant){ + if(lookupIsString) + value = ((Variant)value).getValue().toString(); + else + value = Spreadsheets.asNumber(value); + } + if (Spreadsheets.excelEquals(lookupValue, value)) { + return array.get(rowIndexNum - 1, i); + } + } + + } + + return FormulaError2.NA.getString(); + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfErrorFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfErrorFormulaFunction.java similarity index 63% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfErrorFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfErrorFormulaFunction.java index 891992c7d..9c7923482 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfErrorFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfErrorFormulaFunction.java @@ -1,16 +1,14 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class IfErrorFormulaFunction implements CellFormulaFunction { - - @Override + + @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { - + if (args.values.size() != 2) throw new IllegalStateException(); - + Object condition = args.values.get(0).accept(visitor); FormulaError2 error = FormulaError2.forObject(condition); if(error!=null) return error.getString(); diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfFormulaFunction.java similarity index 51% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfFormulaFunction.java index 2d2ef8c5b..351d6258f 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfFormulaFunction.java @@ -1,41 +1,39 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstNothing; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; public class IfFormulaFunction implements CellFormulaFunction { @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { if (args.values.size() != 3) throw new IllegalStateException(); - + Object condition = args.values.get(0).accept(visitor); AstValue ifTrueResult = args.values.get(1); AstValue ifFalseResult = args.values.get(2); - + FormulaError2 error = FormulaError2.forObject(condition); - if(error!=null) return error.getString(); + if(error!=null) return error.getString(); - if (SpreadsheetGraphUtils.asBoolean(condition)) { + if (Spreadsheets.asBoolean(condition)) { if(ifTrueResult==null || ifTrueResult instanceof AstNothing) - return 0; + return 0; try { - return ifTrueResult.accept(visitor); + return ifTrueResult.accept(visitor); } catch (IllegalStateException e){ - return FormulaError2.NAME.getString(); + return FormulaError2.NAME.getString(); } } else { if(ifFalseResult==null || ifFalseResult instanceof AstNothing) - return 0; + return 0; try { - return ifFalseResult.accept(visitor); + return ifFalseResult.accept(visitor); } catch (IllegalStateException e){ - return FormulaError2.NAME.getString(); + return FormulaError2.NAME.getString(); } } } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IsErrorFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IsErrorFormulaFunction.java similarity index 50% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IsErrorFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IsErrorFormulaFunction.java index 922b8af13..c2680cbf4 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IsErrorFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IsErrorFormulaFunction.java @@ -1,20 +1,18 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class IsErrorFormulaFunction implements CellFormulaFunction{ - @Override + @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { - + if (args.values.size() != 1) throw new IllegalStateException(); - + Object condition = args.values.get(0).accept(visitor); if(condition instanceof String){ - FormulaError2 error = FormulaError2.forString((String)condition); - return (error!=null); + FormulaError2 error = FormulaError2.forString((String)condition); + return (error!=null); } return false; } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/LinestFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/LinestFormulaFunction.java similarity index 82% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/LinestFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/LinestFormulaFunction.java index dd037e9ea..8d952c1ac 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/LinestFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/LinestFormulaFunction.java @@ -1,11 +1,9 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class LinestFormulaFunction implements CellFormulaFunction { @@ -30,9 +28,9 @@ public class LinestFormulaFunction implements CellFormulaFunction{ + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() < 2 || args.values.size() > 3) throw new IllegalStateException(); + + SpreadsheetMatrix lookup_array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); + if(lookup_array.getWidth()!=1 && lookup_array.getHeight()!=1) return FormulaError2.NA.getString(); + + Object lookup_value = args.values.get(0).accept(visitor); + + int match_type = 1; + try{ + if(args.values.size()==3){ + int matchArg = ((Number)args.values.get(2).accept(visitor)).intValue(); + if(matchArg<0) + match_type = -1; + else if(matchArg>0) + match_type = 1; + else + match_type = 0; + } + } catch(Exception e) { + return FormulaError2.NA.getString(); + } + + boolean useHeight = false; + if(lookup_array.getWidth()==1) useHeight = true; + + int max = 0; + if(useHeight) max = lookup_array.getHeight(); + else max = lookup_array.getWidth(); + + Integer pos = null; + if(lookup_value instanceof Variant){ + Object obj = ((Variant)lookup_value).getValue(); + Number nVal = Spreadsheets.asValidNumber(obj); + if(nVal!=null) obj = nVal; + else obj = obj.toString(); + } + + if(lookup_value instanceof Number){ + Double previousValue = null; + Double closestMatch = null; + Double lookup = ((Number)lookup_value).doubleValue(); + int indexWhereCorrectOrderStartsAt = 0; + + if(match_type!=0) { + for(int i = 0; i < max;i++){ + Double currValue = null; + Number currNum; + if(useHeight){ + currNum = Spreadsheets.asValidNumber(lookup_array.get(i,0)); + } else { + currNum = Spreadsheets.asValidNumber(lookup_array.get(0,i)); + } + if(currNum!=null){ + currValue = currNum.doubleValue(); + if(currValue != null){ + if(previousValue!=null){ + if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValuepreviousValue) || (match_type==1 && currValue 0 && match_type==1) || (comp<0 && match_type==-1)){ + if(closestMatch==null && pos==null){ + closestMatch = currValue; + pos = i; + } + else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){ + closestMatch = currValue; + pos = i; + } + } + previousValue = currValue; + } + } + } + } + + else if(lookup_value instanceof String){ + String previousValue = null; + String closestMatch = null; + String lookup = (String)lookup_value; + int indexWhereCorrectOrderStartsAt = 0; + + if(match_type!=0) { + for(int i = 0; i < max;i++){ + String currValue = null; + Object obj; + if(useHeight){ + obj = lookup_array.get(i,0); + } else { + obj = lookup_array.get(0,i); + } + if(obj instanceof Variant){ + obj = ((Variant)obj).getValue(); + } + if(obj!=null && !(obj instanceof Number)){ + currValue = obj.toString(); + currValue = currValue.toLowerCase(); + } + if(currValue != null && !currValue.equals("")){ + if(previousValue!=null){ + if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)) + indexWhereCorrectOrderStartsAt = i; + else + break; + } + previousValue = currValue; + } + } + } + + int begin = indexWhereCorrectOrderStartsAt; + + for(int i = begin; i < max;i++){ + String currValue = null; + Object obj; + if(useHeight){ + obj = lookup_array.get(i,0); + } else { + obj = lookup_array.get(0,i); + } + if(obj instanceof Variant){ + obj = ((Variant)obj).getValue(); + } + if(obj!=null && !(obj instanceof Number)){ + currValue = obj.toString(); + currValue = currValue.toLowerCase(); + } + + if(currValue != null && !currValue.equals("")){ + if(previousValue==null) previousValue = currValue; + if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)){ + if(pos!=null) + return pos+1; + previousValue = currValue; + } + int comp = lookup.compareTo(currValue); + if(comp == 0){ + closestMatch = currValue; + pos = i; + } + else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){ + if(closestMatch==null && pos==null){ + closestMatch = currValue; + pos = i; + } + else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){ + closestMatch = currValue; + pos = i; + } + } + previousValue = currValue; + } + } + } + + if(pos==null)return FormulaError2.NA.getString(); + return pos+1; + } +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java new file mode 100644 index 000000000..a852ecc41 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java @@ -0,0 +1,28 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; + +public class OrFormulaFunction implements CellFormulaFunction { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() == 0) throw new IllegalStateException(); + + for (int i = 0; i < args.values.size(); i++) { + Object obj = null; + try { + obj = args.values.get(i).accept(visitor); + } catch (IllegalStateException e){ + return FormulaError2.NAME.getString(); + } + FormulaError2 error = FormulaError2.forObject(obj); + if(error!=null) return error.getString(); + + if (Spreadsheets.asBoolean(obj)) + return Boolean.TRUE; + } + return Boolean.FALSE; + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/PiFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PiFormulaFunction.java similarity index 53% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/PiFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PiFormulaFunction.java index 8f62ac4cc..a6f285981 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/PiFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PiFormulaFunction.java @@ -1,8 +1,6 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class PiFormulaFunction implements CellFormulaFunction { diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java new file mode 100644 index 000000000..1738feb77 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java @@ -0,0 +1,168 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.spreadsheet.solver.formula.parser.ast.AstApply; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArithmeticExpression; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArray; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstBoolean; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstDouble; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstFactor; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstIdentifier; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstInteger; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstNull; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstRelation; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstString; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstTerm; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValueVisitor; + +public class PrintVisitor implements AstValueVisitor { + + @Override + public String visit(AstBoolean astBoolean) { + return "" + astBoolean.value; + } + + @Override + public String visit(AstDouble astFloat) { + return "" + astFloat.value; + } + + @Override + public String visit(AstInteger astInteger) { + return "" + astInteger.value; + } + + @Override + public String visit(AstNull astNull) { + return "AstNull"; + } + + @Override + public String visit(AstString astString) { + return "\"" + astString.value + "\""; + } + + @Override + public String visit(AstRange astRange) { + if(astRange.isCell()) { + return astRange.first; + } else { + return astRange.first + ":" + astRange.second; + } + } + + @Override + public String visit(AstArgList astArgList) { + StringBuilder b = new StringBuilder(); + for(int i=0;i 0) b.append(";"); + b.append(astArgList.values.get(i).accept(this)); + } + return b.toString(); + } + + @Override + public String visit(AstApply astApply) { + if(astApply.args == null) { + return astApply.value + "()"; + } else { + return astApply.value + "(" + astApply.args.accept(this) + ")"; + } + } + + @Override + public String visit(AstRelation astRelation) { + + StringBuilder b = new StringBuilder(); + b.append(astRelation.left.accept(this)); + b.append(astRelation.op.trim()); + b.append(astRelation.right.accept(this)); + return b.toString(); + + } + + @Override + public String visit(AstArithmeticExpression exp) { + + StringBuilder b = new StringBuilder(); + if(exp.prefix != null) b.append(exp.prefix); + + b.append(exp.left.accept(this)); + + for(int i=0;i 0) b.append(";"); + b.append(array.values.get(i).accept(this)); + } + return b.toString(); + } + + @Override + public String visit(AstNothing array) { + return "AstNothing"; + } + + @Override + public String visit(AstArrayFormulaReference ref) { + return "{" + ref.value.accept(this) + "}"; + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundFormulaFunction.java similarity index 62% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundFormulaFunction.java index b350bbc03..0a87291f4 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundFormulaFunction.java @@ -1,26 +1,24 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class RoundFormulaFunction implements CellFormulaFunction { @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { if (args.values.size() != 2) throw new IllegalStateException(); - + Object number = args.values.get(0).accept(visitor); Object digits = args.values.get(1).accept(visitor); - + FormulaError2 err1 = FormulaError2.forObject(number); if(err1!=null) return err1.getString(); FormulaError2 err2 = FormulaError2.forObject(digits); if(err2!=null) return err2.getString(); - - double n = SpreadsheetGraphUtils.asNumber(number); - double n2 = SpreadsheetGraphUtils.asNumber(digits); + + double n = Spreadsheets.asNumber(number); + double n2 = Spreadsheets.asNumber(digits); Double scale = Math.pow(10, n2); long l = Math.round(scale * n); diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundupFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundupFormulaFunction.java similarity index 62% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundupFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundupFormulaFunction.java index 20c057a89..7ba59d7e4 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundupFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundupFormulaFunction.java @@ -1,27 +1,25 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class RoundupFormulaFunction implements CellFormulaFunction { @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { if (args.values.size() != 2) throw new IllegalStateException(); - + Object number = args.values.get(0).accept(visitor); Object digits = args.values.get(1).accept(visitor); - + FormulaError2 err1 = FormulaError2.forObject(number); if(err1!=null) return err1.getString(); FormulaError2 err2 = FormulaError2.forObject(digits); if(err2!=null) return err2.getString(); - - double n = SpreadsheetGraphUtils.asNumber(number); - double n2 = SpreadsheetGraphUtils.asNumber(digits); - + + double n = Spreadsheets.asNumber(number); + double n2 = Spreadsheets.asNumber(digits); + Double scale = Math.pow(10, n2); double l = Math.ceil(scale * n); diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SpreadsheetEvaluationEnvironment.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SpreadsheetEvaluationEnvironment.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SpreadsheetEvaluationEnvironment.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SpreadsheetEvaluationEnvironment.java index 08483bccb..e3d3f18f7 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SpreadsheetEvaluationEnvironment.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SpreadsheetEvaluationEnvironment.java @@ -1,10 +1,9 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; import java.util.HashMap; import java.util.Map; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetBook; public class SpreadsheetEvaluationEnvironment { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SqrtFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SqrtFormulaFunction.java similarity index 54% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SqrtFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SqrtFormulaFunction.java index ae841568f..a5bccaa43 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SqrtFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SqrtFormulaFunction.java @@ -1,18 +1,16 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class SqrtFormulaFunction implements CellFormulaFunction { @Override public Object evaluate(CellValueVisitor visitor, AstArgList args) { if (args.values.size() != 1) throw new IllegalStateException(); - + Object number = args.values.get(0).accept(visitor); - Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(number); + Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(number); if(dVal==null) return FormulaError2.handleErrorCall(number); if(dVal<0) return FormulaError2.NUM.getString(); diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumFormulaFunction.java similarity index 52% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumFormulaFunction.java index 299973db5..97f864709 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumFormulaFunction.java @@ -1,11 +1,9 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; class SumFormulaFunction implements CellFormulaFunction { @@ -14,21 +12,21 @@ class SumFormulaFunction implements CellFormulaFunction { Double sum = 0.0; for (AstValue value : args.values) { Object result = value.accept(visitor); - + if (result instanceof SpreadsheetMatrix) { Object value2 = ((SpreadsheetMatrix) result).sumWithFormulaError(); if(value2 instanceof String) return value2; //means sumWithFormulaError returned an Error message. sum += ((Number)value2).doubleValue(); } else if(result instanceof String && !result.equals("")){ - FormulaError2 error = FormulaError2.forString(result.toString()); - if(error!=null) return error.getString(); - Double v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(result); - if(v!=null) - sum += v; + FormulaError2 error = FormulaError2.forString(result.toString()); + if(error!=null) return error.getString(); + Double v = Spreadsheets.asDoubleWhereEmptyStringIsZero(result); + if(v!=null) + sum += v; } else if(result instanceof Number){ sum += ((Number)result).doubleValue(); } else { - sum += SpreadsheetGraphUtils.asNumber(result); + sum += Spreadsheets.asNumber(result); } } return sum; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumifFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumifFormulaFunction.java similarity index 65% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumifFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumifFormulaFunction.java index 8826a3842..6ed9f00ac 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumifFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumifFormulaFunction.java @@ -1,10 +1,8 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils; -import org.simantics.spreadsheet.graph.SpreadsheetMatrix; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; class SumifFormulaFunction implements CellFormulaFunction { @@ -14,26 +12,26 @@ class SumifFormulaFunction implements CellFormulaFunction { Object test = args.values.get(0).accept(visitor); Object criteria = null; try { - criteria = args.values.get(1).accept(visitor); + criteria = args.values.get(1).accept(visitor); } catch (IllegalStateException e){ - return 0; + return 0; } FormulaError2 error = FormulaError2.forObject(criteria); if(error!=null) return error.getString(); - + if (test instanceof SpreadsheetMatrix) { double sum = 0.0; SpreadsheetMatrix tm = (SpreadsheetMatrix) test; for (int i = 0; i < tm.values.length; i++) { - if (SpreadsheetGraphUtils.matchCriteria(tm.values[i], criteria)) { - double d = SpreadsheetGraphUtils.asNumber(tm.values[i]); + if (Spreadsheets.matchCriteria(tm.values[i], criteria)) { + double d = Spreadsheets.asNumber(tm.values[i]); if (Double.isFinite(d)) sum += d; } } return sum; } else { - Double d = SpreadsheetGraphUtils.asNumber(test); + Double d = Spreadsheets.asNumber(test); return d; } } @@ -42,13 +40,13 @@ class SumifFormulaFunction implements CellFormulaFunction { Object test = args.values.get(0).accept(visitor); Object criteria = null; try { - criteria = args.values.get(1).accept(visitor); + criteria = args.values.get(1).accept(visitor); } catch (IllegalStateException e){ - return 0; + return 0; } FormulaError2 error = FormulaError2.forObject(criteria); if(error!=null) return error.getString(); - + Object range = args.values.get(2).accept(visitor); if (test instanceof SpreadsheetMatrix) { @@ -56,15 +54,15 @@ class SumifFormulaFunction implements CellFormulaFunction { SpreadsheetMatrix tm = (SpreadsheetMatrix) test; SpreadsheetMatrix rm = (SpreadsheetMatrix) range; for (int i = 0; i < tm.values.length; i++) { - if (SpreadsheetGraphUtils.matchCriteria(tm.values[i], criteria)) { - double d = SpreadsheetGraphUtils.asNumber(rm.values[i]); + if (Spreadsheets.matchCriteria(tm.values[i], criteria)) { + double d = Spreadsheets.asNumber(rm.values[i]); if (Double.isFinite(d)) sum += d; } } return sum; } else { - Double d = SpreadsheetGraphUtils.asNumber(test); + Double d = Spreadsheets.asNumber(test); return d; } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/TodayFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/TodayFormulaFunction.java similarity index 66% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/TodayFormulaFunction.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/TodayFormulaFunction.java index c4488f349..61d4da375 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/TodayFormulaFunction.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/TodayFormulaFunction.java @@ -1,13 +1,11 @@ -package org.simantics.spreadsheet.graph.formula; +package org.simantics.spreadsheet.solver.formula; import java.time.LocalDate; import java.time.Month; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; -import org.simantics.spreadsheet.graph.CellFormulaFunction; -import org.simantics.spreadsheet.graph.CellValueVisitor; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; public class TodayFormulaFunction implements CellFormulaFunction { diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java new file mode 100644 index 000000000..0c8bc8f4f --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java @@ -0,0 +1,161 @@ +package org.simantics.spreadsheet.solver.formula; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.SpreadsheetMatrix; +import org.simantics.spreadsheet.Spreadsheets; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList; + +public class VlookupFormulaFunction implements CellFormulaFunction { + + @Override + public Object evaluate(CellValueVisitor visitor, AstArgList args) { + if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException(); + + Object lookupValue = args.values.get(0).accept(visitor); + boolean lookupIsString = lookupValue instanceof String; + + FormulaError2 error = FormulaError2.forObject(lookupValue); + if(error!=null) return error.getString(); + + if(lookupValue instanceof Variant){ + Object varVal = ((Variant)lookupValue).getValue(); + Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(varVal); + if(dVal==null) { + lookupValue = varVal.toString(); + lookupIsString = true; + } + else lookupValue = dVal; + } + + + SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor); + + boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true; + + boolean valueExists = false; + if(array.values.length != 0){ + for(int i = 0; i < array.getHeight(); i++){ + if(lookupIsString){ + Object obj = array.get(i,0); + if(obj instanceof Variant) + obj = ((Variant)obj).getValue(); + if(obj!=null && Spreadsheets.asValidNumber(obj)==null){ + obj = obj.toString(); + String valStr = ((String)obj).toLowerCase(); + if((lookupValue.toString().toLowerCase()).compareTo(valStr)>=0 ){ + valueExists = true; + break; + } + } + } + else if(lookupValue instanceof Number){ + Double d = ((Number)lookupValue).doubleValue(); + Number d2 = Spreadsheets.asValidNumber(array.get(i,0)); + if(d2!=null && d>=(d2.doubleValue())){ + valueExists = true; + break; + } + } + } +// if(lookupIsString){ +// Object obj = array.values[0]; +// if(obj instanceof Variant) +// obj = ((Variant)obj).getValue(); +// if(Spreadsheets.asValidNumber(obj)!=null) +// return FormulaError2.NA.getString(); +// obj = obj.toString(); +// String valStr = ((String)obj).toLowerCase(); +// if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 ) +// return FormulaError2.NA.getString(); +// } +// else if(lookupValue instanceof Number){ +// Double d = ((Number)lookupValue).doubleValue(); +// Number d2 = Spreadsheets.asValidNumber(array.values[0]); +// if(d2==null || d<(d2.doubleValue())) +// return FormulaError2.NA.getString(); +// } + } + if(!valueExists) return FormulaError2.NA.getString(); + + Number colIndexN = Spreadsheets.asValidNumber(args.values.get(2).accept(visitor)); + if(colIndexN==null) return FormulaError2.REF.getString(); + int colIndexNum = colIndexN.intValue(); + if(colIndexNum>array.getWidth()) return FormulaError2.REF.getString(); + + if (approximateMatch) { + Integer rowPosOfLargestValSmallerThanLookUp = null; + if(lookupIsString){ + String ref = lookupValue.toString().toLowerCase(); + String previousValue = null; + String largestValSmallerThanLookUp = null; + for(int i = 0; i < array.getHeight(); i++){ + Object val = array.get(i, 0); + if(val instanceof Variant) + val = ((Variant)val).getValue(); + String currValue = val.toString().toLowerCase(); + if(currValue.compareTo(ref)>0){ + if(i==0) + return array.get(i, colIndexNum-1); + else if(previousValue.compareTo(ref) > currValue.compareTo(ref)) + return array.get(i, colIndexNum-1); + else + return array.get(i - 1, colIndexNum - 1); + } + if(rowPosOfLargestValSmallerThanLookUp==null){ + rowPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = currValue; + } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){ + rowPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = currValue; + } + previousValue = currValue; + } + + } else { + double ref = Spreadsheets.asNumber(lookupValue); + double lastDiff = Double.MIN_VALUE; + Double largestValSmallerThanLookUp = null; + for (int i = 0; i < array.getHeight(); i++) { + Object value = array.get(i, 0); + double n = Spreadsheets.asNumber(value); + double diff = n - ref; + if (diff > 0) { + if (i == 0) + return array.get(i, colIndexNum - 1); + else if (diff < -lastDiff) + return array.get(i, colIndexNum - 1); + else + return array.get(i - 1, colIndexNum - 1); + } + if(rowPosOfLargestValSmallerThanLookUp==null){ + rowPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = n; + } else if(largestValSmallerThanLookUp < n){ + rowPosOfLargestValSmallerThanLookUp = i; + largestValSmallerThanLookUp = n; + } + lastDiff = diff; + } + } + + if(rowPosOfLargestValSmallerThanLookUp!=null) return array.get(rowPosOfLargestValSmallerThanLookUp, colIndexNum - 1); + + } else { + for (int i = 0; i < array.getHeight(); i++) { + Object value = array.get(i, 0); + if(value instanceof Variant){ + if(lookupIsString) + value = ((Variant)value).getValue().toString(); + else + value = Spreadsheets.asNumber(value); + } + if (Spreadsheets.excelEquals(lookupValue, value)) { + return array.get(i, colIndexNum - 1); + } + } + } + + return FormulaError2.NA.getString(); + } + +} diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ParseException.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ParseException.java similarity index 99% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ParseException.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ParseException.java index 6bb308ab4..76b38cdba 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ParseException.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ParseException.java @@ -1,6 +1,6 @@ /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */ /* JavaCCOptions:KEEP_LINE_COL=null */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; /** * This exception is thrown when parse errors are encountered. diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.java similarity index 99% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.java index 4913c99d3..79326f034 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.java @@ -1,7 +1,7 @@ /* Generated By:JavaCC: Do not edit this line. SheetFormulaParser.java */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; -import org.simantics.spreadsheet.graph.parser.ast.*; +import org.simantics.spreadsheet.solver.formula.parser.ast.*; import java.util.ArrayList; import java.util.List; import java.util.Collections; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.jj b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.jj similarity index 100% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.jj rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.jj diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserConstants.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserConstants.java similarity index 97% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserConstants.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserConstants.java index be43ae5d9..3da3602d4 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserConstants.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserConstants.java @@ -1,5 +1,5 @@ /* Generated By:JavaCC: Do not edit this line. SheetFormulaParserConstants.java */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; /** diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserTokenManager.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserTokenManager.java similarity index 99% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserTokenManager.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserTokenManager.java index 92a00f19c..30a2d83ef 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserTokenManager.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserTokenManager.java @@ -1,6 +1,6 @@ /* Generated By:JavaCC: Do not edit this line. SheetFormulaParserTokenManager.java */ -package org.simantics.spreadsheet.graph.parser; -import org.simantics.spreadsheet.graph.parser.ast.*; +package org.simantics.spreadsheet.solver.formula.parser; +import org.simantics.spreadsheet.solver.formula.parser.ast.*; import java.util.ArrayList; import java.util.List; import java.util.Collections; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetParserUtils.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetParserUtils.java similarity index 96% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetParserUtils.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetParserUtils.java index 034682803..970fb1d86 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetParserUtils.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetParserUtils.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; public class SheetParserUtils { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SimpleCharStream.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SimpleCharStream.java similarity index 99% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SimpleCharStream.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SimpleCharStream.java index d504d68eb..534aa209e 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SimpleCharStream.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SimpleCharStream.java @@ -1,6 +1,6 @@ /* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */ /* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; /** * An implementation of interface CharStream, where the stream is assumed to diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/Token.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/Token.java similarity index 98% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/Token.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/Token.java index 0fe4b1b21..ede6504bc 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/Token.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/Token.java @@ -1,6 +1,6 @@ /* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ /* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; /** * Describes the input token stream. diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/TokenMgrError.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/TokenMgrError.java similarity index 98% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/TokenMgrError.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/TokenMgrError.java index e333f22e7..7ef95c896 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/TokenMgrError.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/TokenMgrError.java @@ -1,6 +1,6 @@ /* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ /* JavaCCOptions: */ -package org.simantics.spreadsheet.graph.parser; +package org.simantics.spreadsheet.solver.formula.parser; /** Token Manager Error. */ public class TokenMgrError extends Error diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstApply.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstApply.java similarity index 89% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstApply.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstApply.java index fec2ffc36..eb1791cff 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstApply.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstApply.java @@ -9,9 +9,9 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; -import org.simantics.spreadsheet.graph.PrintVisitor; +import org.simantics.spreadsheet.solver.formula.PrintVisitor; public class AstApply implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArgList.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArgList.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArgList.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArgList.java index 075ef48fd..ab415f75b 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArgList.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArgList.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; import java.util.ArrayList; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArithmeticExpression.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArithmeticExpression.java similarity index 90% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArithmeticExpression.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArithmeticExpression.java index 342fe58b2..26c77920d 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArithmeticExpression.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArithmeticExpression.java @@ -9,9 +9,9 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; -import org.simantics.spreadsheet.graph.PrintVisitor; +import org.simantics.spreadsheet.solver.formula.PrintVisitor; public class AstArithmeticExpression extends AstList { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArray.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArray.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArray.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArray.java index d492c206c..917936aa2 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArray.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArray.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; import java.util.ArrayList; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArrayFormulaReference.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArrayFormulaReference.java similarity index 94% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArrayFormulaReference.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArrayFormulaReference.java index cd6ae189a..aeda240ed 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArrayFormulaReference.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArrayFormulaReference.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstArrayFormulaReference implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstBoolean.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstBoolean.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstBoolean.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstBoolean.java index aa8caa9a4..d9fc5f3c5 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstBoolean.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstBoolean.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public enum AstBoolean implements AstValue { FALSE(false), diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstDouble.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstDouble.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstDouble.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstDouble.java index da8859d97..11364b069 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstDouble.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstDouble.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstDouble implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstFactor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstFactor.java similarity index 88% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstFactor.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstFactor.java index 03f4d2abc..6f1add8be 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstFactor.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstFactor.java @@ -9,9 +9,9 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; -import org.simantics.spreadsheet.graph.PrintVisitor; +import org.simantics.spreadsheet.solver.formula.PrintVisitor; public class AstFactor extends AstList { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstIdentifier.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstIdentifier.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstIdentifier.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstIdentifier.java index 92b4fea29..dffc58ba6 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstIdentifier.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstIdentifier.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstIdentifier implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstInteger.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstInteger.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstInteger.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstInteger.java index 9e498bd2b..4a493783c 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstInteger.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstInteger.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstInteger implements AstValue { public final Integer value; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstList.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstList.java similarity index 92% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstList.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstList.java index c889483f4..43ef6d3b1 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstList.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstList.java @@ -1,4 +1,4 @@ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; import java.util.ArrayList; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNothing.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNothing.java similarity index 94% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNothing.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNothing.java index 74d2f4ec8..4101c31f9 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNothing.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNothing.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; import java.io.Serializable; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNull.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNull.java similarity index 92% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNull.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNull.java index 852e4bb02..a7fddfb50 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNull.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNull.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public enum AstNull implements AstValue { NULL; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRange.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRange.java similarity index 92% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRange.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRange.java index 471c47dd3..7b9c0c038 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRange.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRange.java @@ -9,9 +9,9 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; -import org.simantics.spreadsheet.graph.PrintVisitor; +import org.simantics.spreadsheet.solver.formula.PrintVisitor; public class AstRange implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRelation.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRelation.java similarity index 94% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRelation.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRelation.java index a86ea7f7b..2c525fb43 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRelation.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRelation.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstRelation implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstString.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstString.java similarity index 93% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstString.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstString.java index d8e39e07a..b7a933adf 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstString.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstString.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public class AstString implements AstValue { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstTerm.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstTerm.java similarity index 88% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstTerm.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstTerm.java index 7d8b5b3a0..5efa32bd3 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstTerm.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstTerm.java @@ -9,9 +9,9 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; -import org.simantics.spreadsheet.graph.PrintVisitor; +import org.simantics.spreadsheet.solver.formula.PrintVisitor; public class AstTerm extends AstList { diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValue.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValue.java similarity index 92% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValue.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValue.java index 3cdeaa0ee..c2815cb34 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValue.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValue.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; import java.io.Serializable; diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValueVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValueVisitor.java similarity index 94% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValueVisitor.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValueVisitor.java index 14ae6f76a..79ddb1aea 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValueVisitor.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValueVisitor.java @@ -9,7 +9,7 @@ * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ -package org.simantics.spreadsheet.graph.parser.ast; +package org.simantics.spreadsheet.solver.formula.parser.ast; public interface AstValueVisitor { diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java new file mode 100644 index 000000000..87279633e --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java @@ -0,0 +1,18 @@ +package org.simantics.spreadsheet.synchronization; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; + +public class ExcelArrayFormula { + + public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelArrayFormula.class); + + public String range; + public String expression; + + public ExcelArrayFormula(String range, String expression) { + this.range = range; + this.expression = expression; + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java new file mode 100644 index 000000000..10d9e0311 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java @@ -0,0 +1,16 @@ +package org.simantics.spreadsheet.synchronization; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; + +public class ExcelFormula { + + public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelFormula.class); + + public String expression; + + public ExcelFormula(String expression) { + this.expression = expression; + } + +} diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java new file mode 100644 index 000000000..a40cf4950 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java @@ -0,0 +1,126 @@ +package org.simantics.spreadsheet.synchronization; + +import java.io.StringReader; +import java.util.ArrayList; + +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.ExternalRef; +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetCell; +import org.simantics.spreadsheet.solver.SpreadsheetFormula; +import org.simantics.spreadsheet.solver.SpreadsheetLine; +import org.simantics.spreadsheet.solver.SpreadsheetLines; +import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant; +import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference; +import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue; +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.utils.Solver; + +public class LineCommandBuilder implements CommandBuilder { + + private String name; + LineContentBean bean; + + public LineCommandBuilder(String name, boolean update) { + this.name = name; + } + + @Override + public void apply(Solver solver) { + + SpreadsheetBook book = solver.getConcreteSolver(); + + String path = name.substring(0, name.lastIndexOf("/")); + String lineName = name.substring(name.lastIndexOf("/")+1); + int row = Integer.parseInt(lineName.substring(3)); + + SpreadsheetLines node = book.ensureSubprocess(path); + SpreadsheetLine line = node.lines.get(-row); + if(line == null) { + line = new SpreadsheetLine(node, row); + node.lines.put(-row, line); + } + + ArrayList changes = new ArrayList<>(); + + for(int i=0;i i) { + currentCell = line.cells.get(i); + } else { + currentCell = new SpreadsheetCell(line, i); + line.cells.add(currentCell); + } + + LineContentBeanCell cell = bean.cells[i]; + + try { + Object content = cell.getContent(); + if (content instanceof Variant) { + Variant cellVariant = (Variant) content; + if (cellVariant == LineContentBeanCell.EMPTY) { + currentCell.setStyle(cell.getStyleId()); + // Empty content + currentCell.setContent(""); + } else if(ExcelFormula.BINDING.type().equals(cellVariant.getBinding().type())) { + ExcelFormula formula = (ExcelFormula)cellVariant.getValue(ExcelFormula.BINDING); + SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression)); + AstValue v = p.relation(); + currentCell.setStyle(cell.getStyleId()); + SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression); + currentCell.setContent(sformula); + } else if (ExcelArrayFormula.BINDING.type().equals(cellVariant.getBinding().type())) { + ExcelArrayFormula formula = (ExcelArrayFormula)cellVariant.getValue(ExcelArrayFormula.BINDING); + SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression)); + AstArrayFormulaReference v = new AstArrayFormulaReference(formula.range, p.relation()); + currentCell.setStyle(cell.getStyleId()); + SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression); + currentCell.setContent(sformula); + } else if (cellVariant.getValue() instanceof ExternalRef){ + throw new IllegalStateException(); + } else { + currentCell.setStyle(cell.getStyleId()); + // DO not update constant values during update + currentCell.setContent(cellVariant.getValue()); + } + } else if (content instanceof ExternalRef){ + throw new IllegalStateException(); + } else if (content instanceof SpreadsheetSCLConstant){ + currentCell.setStyle(cell.getStyleId()); + currentCell.setContent(content); + } + } catch (Throwable e) { + Object content = cell.getContent(); + if (content instanceof Variant) { + Variant cellVariant = (Variant) content; + currentCell.setStyle(cell.getStyleId()); + currentCell.setContent(content); + try { + new Exception("failed: " + ((ExcelFormula)(cellVariant.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace(); + } catch (AdaptException e1) { + e1.printStackTrace(); + } + } else { + currentCell.setStyle(cell.getStyleId()); + currentCell.setContent("LCB error happened"); + } + } + + changes.add(currentCell); + + } + + book.fireChanges(changes); + + } + + @SuppressWarnings("unchecked") + @Override + public T getConcrete() { + return (T)this; + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBean.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBean.java similarity index 66% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBean.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBean.java index 90a4f3dd5..54d93d946 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBean.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBean.java @@ -1,16 +1,20 @@ -package org.simantics.spreadsheet.graph.function; +package org.simantics.spreadsheet.synchronization; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; public class LineContentBean { - + public static final Binding BINDING = Bindings.getBindingUnchecked(LineContentBean.class); - + static { + register(); + } + + public static void register() { Bindings.defaultBindingRepository.put(BINDING.type(), BINDING); } - public LineContentBeanCell cells[]; - + public LineContentBeanCell cells[]; + } diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBeanCell.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBeanCell.java similarity index 78% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBeanCell.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBeanCell.java index 7c060da31..3f0d0c922 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBeanCell.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBeanCell.java @@ -1,12 +1,12 @@ -package org.simantics.spreadsheet.graph.function; +package org.simantics.spreadsheet.synchronization; import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.graph.SpreadsheetStyle; +import org.simantics.spreadsheet.solver.SpreadsheetStyle; public class LineContentBeanCell { public static final Variant EMPTY = new Variant(); - + public Variant content; public final int styleID; @@ -19,7 +19,6 @@ public class LineContentBeanCell { } public LineContentBeanCell(Variant content, int styleId) { -// System.err.println("LineContentBeanCell.construct: " + content + " " + styleId); this.content = content; this.styleID = styleId; } diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java new file mode 100644 index 000000000..7354b27e9 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java @@ -0,0 +1,53 @@ +package org.simantics.spreadsheet.synchronization; + +import java.util.Collection; +import java.util.Map; + +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.solver.SheetLineComponent; +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.base.ModuleUpdateContext; +import org.simantics.structural.synchronization.base.ModuleUpdaterBase; +import org.simantics.structural.synchronization.base.PropertyUpdateRule; + +public class LineNodeUpdater extends ModuleUpdaterBase { + + public LineNodeUpdater(String id) { + + super(id); + + isComposite = true; + + addPropertyUpdateRule(new PropertyUpdateRule() { + + @Override + public String getPropertyName() { + return "keys"; + } + + @Override + public void apply(ModuleUpdateContext context, boolean isCreating, + Map propertyMap, Map> connectionMap, Variant value) { + + LinesCommandBuilder builder = context.getConcreteCommand(); + Variant v = propertyMap.get("keys"); + if (v != null & v.getValue() != null) + builder.keys = (int[])v.getValue(); + + } + + }); + + } + + @Override + public CommandBuilder createAddCommandBuilder(String name) { + return new LinesCommandBuilder(name, false); + } + + @Override + public CommandBuilder createUpdateCommandBuilder(String name) { + return new LinesCommandBuilder(name, true); + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java new file mode 100644 index 000000000..95c601b50 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java @@ -0,0 +1,50 @@ +package org.simantics.spreadsheet.synchronization; + +import java.util.Collection; +import java.util.Map; + +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.spreadsheet.solver.SheetLineComponent; +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.base.ModuleUpdateContext; +import org.simantics.structural.synchronization.base.ModuleUpdaterBase; +import org.simantics.structural.synchronization.base.PropertyUpdateRule; + +public class LineUpdater extends ModuleUpdaterBase { + + public LineUpdater(String id) { + super(id); + addPropertyUpdateRule(new PropertyUpdateRule() { + @Override + public String getPropertyName() { + return "content"; + } + @Override + public void apply(ModuleUpdateContext context, boolean isCreating, + Map propertyMap, Map> connectionMap, Variant value) { +// System.err.println("LineUpdater.apply " + value); + LineCommandBuilder builder = context.getConcreteCommand(); + try { + LineContentBean valuee = (LineContentBean) value.getValue(LineContentBean.BINDING); + builder.bean = valuee; + } catch (AdaptException e) { + e.printStackTrace(); + } catch (ClassCastException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public CommandBuilder createAddCommandBuilder(String name) { + return new LineCommandBuilder(name, false); + } + + @Override + public CommandBuilder createUpdateCommandBuilder(String name) { + return new LineCommandBuilder(name, true); + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java new file mode 100644 index 000000000..c5c5ae554 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java @@ -0,0 +1,32 @@ +package org.simantics.spreadsheet.synchronization; + +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetLines; +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.utils.Solver; + +public class LinesCommandBuilder implements CommandBuilder { + + private String name; + int[] keys; + + public LinesCommandBuilder(String name, boolean update) { + this.name = name; + } + + @Override + public void apply(Solver solver) { + + SpreadsheetBook book = solver.getConcreteSolver(); + SpreadsheetLines node = book.ensureSubprocess(name); + node.setKeys(keys); + + } + + @SuppressWarnings("unchecked") + @Override + public T getConcrete() { + return (T)this; + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java new file mode 100644 index 000000000..73aaad55a --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java @@ -0,0 +1,18 @@ +package org.simantics.spreadsheet.synchronization; + +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.utils.Solver; + +public class NullCommandBuilder implements CommandBuilder { + + @Override + public void apply(Solver solver) { + } + + @SuppressWarnings("unchecked") + @Override + public T getConcrete() { + return (T)this; + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java new file mode 100644 index 000000000..f4e1cac54 --- /dev/null +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java @@ -0,0 +1,24 @@ +package org.simantics.spreadsheet.synchronization; + +import org.simantics.spreadsheet.solver.SheetLineComponent; +import org.simantics.structural.synchronization.base.CommandBuilder; +import org.simantics.structural.synchronization.base.ModuleUpdaterBase; + +public class NullUpdater extends ModuleUpdaterBase { + + public NullUpdater(String typeId) { + super(typeId); + isComposite = true; + } + + @Override + public CommandBuilder createAddCommandBuilder(String name) { + return new NullCommandBuilder(); + } + + @Override + public CommandBuilder createUpdateCommandBuilder(String name) { + return new NullCommandBuilder(); + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/StyleUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/StyleUpdater.java similarity index 96% rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/StyleUpdater.java rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/StyleUpdater.java index 4451d1314..e3555fc31 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/StyleUpdater.java +++ b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/StyleUpdater.java @@ -1,4 +1,4 @@ -package org.simantics.spreadsheet.graph.synchronization; +package org.simantics.spreadsheet.synchronization; import java.util.Collection; import java.util.Map; @@ -6,8 +6,9 @@ import java.util.Map; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.datatypes.literal.Font; import org.simantics.datatypes.literal.RGB; -import org.simantics.spreadsheet.graph.SpreadsheetBook; -import org.simantics.spreadsheet.graph.SpreadsheetStyle; +import org.simantics.spreadsheet.solver.SheetLineComponent; +import org.simantics.spreadsheet.solver.SpreadsheetBook; +import org.simantics.spreadsheet.solver.SpreadsheetStyle; import org.simantics.structural.synchronization.base.CommandBuilder; import org.simantics.structural.synchronization.base.ModuleUpdateContext; import org.simantics.structural.synchronization.base.ModuleUpdaterBase; @@ -21,7 +22,7 @@ public class StyleUpdater extends ModuleUpdaterBase { public String getPropertyName() { return "foreground"; } - + @Override public void apply(ModuleUpdateContext context, boolean isCreating, Map propertyMap, Map> connectionMap, Variant value) { StyleCommandBuilder builder = context.getConcreteCommand(); @@ -29,7 +30,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.foreground = color; } } - + private static class BackgroundUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -43,7 +44,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.background = color; } } - + private static class FontUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -71,7 +72,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.align = align; } } - + private static class FormatStringUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -113,7 +114,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.border = border; } } - + private static class LockedUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -127,7 +128,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.locked = locked; } } - + private static class ColumnSpanUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -141,7 +142,7 @@ public class StyleUpdater extends ModuleUpdaterBase { builder.columnSpan = columnSpan; } } - + private static class RowSpanUpdateRule implements PropertyUpdateRule { @Override public String getPropertyName() { @@ -156,10 +157,10 @@ public class StyleUpdater extends ModuleUpdaterBase { } } - + public StyleUpdater(String moduleType) { super(moduleType); - + addPropertyUpdateRule(new ForegroundUpdateRule()); addPropertyUpdateRule(new BackgroundUpdateRule()); addPropertyUpdateRule(new FontUpdateRule()); @@ -181,7 +182,7 @@ public class StyleUpdater extends ModuleUpdaterBase { public CommandBuilder createUpdateCommandBuilder(String name) { return new StyleCommandBuilder(name, true); } - + private static class StyleCommandBuilder implements CommandBuilder { protected int rowSpan; @@ -194,15 +195,13 @@ public class StyleUpdater extends ModuleUpdaterBase { protected org.simantics.datatypes.literal.RGB.Integer foreground; protected Font font; protected int align; - - private boolean update; + private String name; - + public StyleCommandBuilder(String name, boolean update) { this.name = name.split("/")[1]; - this.update = update; } - + @Override public void apply(Solver solver) { SpreadsheetBook book = solver.getConcreteSolver(); @@ -211,7 +210,7 @@ public class StyleUpdater extends ModuleUpdaterBase { .columnSpan(columnSpan).formatIndex((short) formatIndex).formatString(formatString).build(); if (book.getStyle(style.getStyleId()) == null) book.addStyle(style); - + } @SuppressWarnings("unchecked") @@ -219,14 +218,14 @@ public class StyleUpdater extends ModuleUpdaterBase { public T getConcrete() { return (T) this; } - + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("StyleCommandBuilder for ").append(name).append(" [background=").append(background).append(", foregroung=").append(foreground).append(", font=").append(font).append(", align=").append(align).append("]"); return sb.toString(); } - + } - + }