}
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;
} else {
Variable parent = variable.getParent(graph);
if(parent == null) return null;
- else return proxyVariableBase(graph, parent);
+ else return proxyVariableInput(graph, parent);
}
}
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
VP.BrowseContext.SupportsRenamingOf MBC.Symbol
VP.BrowseContext.HasActionContribution
MOD.Contributions.NewSheetBook
+ MOD.Contributions.ImportSheetBook
@VP.renamingTestContribution
L0.SharedOntology
@MOD.sclAction "createSCLQueryTypeAction"
ACTIONS.NewSheetBook
@MOD.sclAction "createSpreadsheetBookAction"
+ACTIONS.ImportSheetBook
+ @MOD.sclAction "importSpreadsheetBookAction"
ACTIONS.ActivateModel
@MOD.sclAction "activateModelAction"
ACTIONS.ActivateExperiment
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,
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<Range> decodeRanges(String ranges){
- String[] splitted = ranges.split(",");
- List<Range> result = new ArrayList<>();
- for(String split : splitted){
- result.add(decodeRange(split));
- }
- return result;
- }
-
- public static int startRow(List<Range> ranges){
- int s = -1;
- for(Range r : ranges){
- if(r.startRow<s || s==-1){
- s = r.startRow;
- }
- }
- return s;
- }
-
- public static int startColumn(List<Range> ranges){
- int s = -1;
- for(Range r : ranges){
- if(r.startColumn<s || s==-1){
- s = r.startColumn;
- }
- }
- return s;
- }
-
- public static int amountOfRows(Range r){
- int endRow = -2;
- int startRow = -2;
- if(r.isFullRows()){
- return Range.MAXROWSPEC;
- }
- if(endRow == -2 && startRow == -2){
- endRow = r.endRow;
- startRow = r.startRow;
- }
- if(r.startRow<startRow){
- startRow = r.startRow;
- }
- if(r.endRow>endRow){
- 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.startColumn<startColumn){
- startColumn = r.startColumn;
- }
- if(r.endColumn>endColumn){
- 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<String, Collection<PropertyCreationData>> parse(String text, StringCellParser[] parsers) {
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);
}
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;
return true;
}
- public static void schedule(CellEditor.Transaction<?> transaction, Write write) {
+ public static void schedule(Transaction<?> transaction, Write write) {
if(transaction == null) {
return new TransactionImpl(mode);
}
- static class TransactionImpl implements CellEditor.Transaction<Write> {
+ static class TransactionImpl implements Transaction<Write> {
private ArrayList<Write> writes = new ArrayList<>();
private final OperationMode mode;
// 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();
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) {
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<Range> decodeRanges(String ranges) {
+ return Spreadsheets.decodeRanges(ranges);
+ }
+
+ /*
+ * Please use Spreadsheets.startColumn instead
+ */
+ @Deprecated
+ public static int startColumn(List<Range> ranges) {
+ return Spreadsheets.startColumn(ranges);
+ }
+
+ /*
+ * Please use Spreadsheets.startRow instead
+ */
+ @Deprecated
+ public static int startRow(List<Range> 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);
+ }
+
}
<externalClass className="org.simantics.db.layer0.variable.ValueAccessor"/>
<externalClass className="org.simantics.db.layer0.variable.VariableMap"/>
<externalClass className="org.simantics.spreadsheet.CellEditor"/>
- <externalClass className="org.simantics.spreadsheet.graph.function.LineContentBean"/>
+ <externalClass className="org.simantics.spreadsheet.synchronization.LineContentBean"/>
<class className="org.simantics.spreadsheet.graph.function.All"/>
</namespace>
</extension>
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 -> <Proc> Transaction
+ @JavaName "edit"
+ editProperty_ :: CellEditor -> String -> String -> a -> Binding a -> Maybe Consumer -> <SpreadsheetTransaction> ()
+ @JavaName "edit"
+ editContent :: CellEditor -> String -> Variant -> Maybe Consumer -> <SpreadsheetTransaction> ()
+
+@inline
+editProperty :: Serializable a => CellEditor -> String -> String -> a -> Maybe Consumer -> <SpreadsheetTransaction> ()
+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 -> <Proc> ()
+
importJava "org.simantics.spreadsheet.common.TreeTableCell" where
data TreeTableCell
saveInitialCondition :: Variable -> Resource -> String -> <WriteGraph> Resource
findCell :: Variable -> String -> <ReadGraph> Maybe Variable
invalidateAll :: Variable -> <ReadGraph> ()
+ extRefVariable :: Variable -> <ReadGraph> Variant
+ extRefActiveVariable :: Variable -> <ReadGraph> Variant
+ cellEditor :: Resource -> <ReadGraph> CellEditor
+ syncExec :: CellEditor -> OperationMode -> (<SpreadsheetTransaction, Proc> a) -> <Proc> a
+ cellColumn :: Variable -> <ReadGraph> Integer
+
+importJava "org.simantics.spreadsheet.Spreadsheets" where
+ cellName :: Integer -> Integer -> String
importJava "org.simantics.spreadsheet.util.SpreadsheetUtils" where
createSheet :: Resource -> String -> <WriteGraph> Resource
selectColumn :: Integer -> TableCell -> Boolean
setSCLLine :: Resource -> Integer -> String -> <WriteGraph> ()
sheetRun :: Resource -> Variable -> <ReadGraph> Variable
+ @JavaName "sheetRun"
+ bookRun :: Resource -> Variable -> <ReadGraph> Variable
+
+sheetRunDefault :: Resource -> <ReadGraph> Variable
+sheetRunDefault sheet = sheetRun sheet (resourceVariable sheet)
importJava "org.simantics.spreadsheet.graph.SpreadsheetSessionManager" where
removeSpreadsheetSession :: Variable -> <Proc, WriteGraph> ()
importJava "org.simantics.spreadsheet.graph.ExcelImport" where
importBook :: Resource -> File -> <Proc> ()
+importSpreadsheetBookAction :: Resource -> <Proc> ()
+importSpreadsheetBookAction res = match fileDialog "foo" [("Excel file", "*.xls"), ("Excel File", "*.xlsx")] with
+ Nothing -> ()
+ Just file -> importBook res file
+
createSpreadsheetBookAction :: Resource -> <Proc> ()
createSpreadsheetBookAction res = do
syncWrite (\() -> createSpreadsheetBookDefault res)
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public interface CellFormulaFunction<T> {
-
- T evaluate(CellValueVisitor visitor, AstArgList args);
-
-}
+++ /dev/null
-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<Object> {
-
- 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<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- value = exp.rightValue(i);
- acceptedValue = value.accept(this);
- if("+".equals(op)) {
- result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
-
- if(!(result instanceof Number)) {
- FormulaError2 err = FormulaError2.forObject(result);
- if(err!=null) return err.getString();
-
- if(result instanceof String && !((String) result).isEmpty()){
- Number num = SpreadsheetGraphUtils.asValidNumber(result);
- if(num == null) {
- return FormulaError2.VALUE.getString();
- } else {
- result = num;
- }
- }
- else if(result instanceof Variant){
- Object val = ((Variant)result).getValue();
- if(val instanceof String && (val.toString().isEmpty())){
- result = 0.0;
- } else {
- Number resNum = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(val);
- if(resNum==null) return FormulaError2.VALUE.getString();
- else result = resNum;
- }
- } else {
- result = 0.0;
- }
- }
-
- FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
- if(err2!=null) return err2.getString();
-
- other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(acceptedValue);
- if(other==null)
- return FormulaError2.handleErrorCall(acceptedValue);
-
- result = ((Number)result).doubleValue() + ((Number)other).doubleValue();
-
- } else if("-".equals(op)) {
- result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
-
- if(!(result instanceof Number)) {
- FormulaError2 err = FormulaError2.forObject(result);
- if(err!=null) return err.getString();
-
- if(result instanceof String && !((String) result).isEmpty()){
- Number num = SpreadsheetGraphUtils.asValidNumber(result);
- if(num == null) {
- return FormulaError2.VALUE.getString();
- } else {
- result = num;
- }
- }
- else if(result instanceof Variant){
- Object val = ((Variant)result).getValue();
- if(val instanceof String && (val.toString().isEmpty())){
- result = 0.0;
- } else {
- Number resNum = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(val);
- if(resNum==null)
- return FormulaError2.VALUE.getString();
- else result = resNum;
- }
- } else {
- result = 0.0;
- }
- }
- FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
- if(err2!=null) return err2.getString();
-
- other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(acceptedValue);
- if(other==null)
- return FormulaError2.handleErrorCall(acceptedValue);
-
- result = ((Number)result).doubleValue() - ((Number)other).doubleValue();
-
- } else if("&".equals(op)) {
- result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
- FormulaError2 err = FormulaError2.forObject(result);
- if(err!=null) return err.getString();
- FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
- if(err2!=null) return err2.getString();
-
- result = SpreadsheetGraphUtils.asString(result);
- other = SpreadsheetGraphUtils.asString(acceptedValue);
-
- result += (String)other;
- }
- }
- return leftValueWithPrefix(result, exp.left, exp.prefix, false);
-
- }
-
- @Override
- public Object visit(AstTerm exp) {
- Number result = null;
- for(int i=0;i<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- AstValue value = exp.rightValue(i);
- Object leftValue = exp.left.accept(this);
- Object rightValue = value.accept(this);
- if("*".equals(op)) {
- if(result == null) {
- result = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftValue);
- if(result == null)
- return FormulaError2.handleErrorCall(leftValue);
- }
- Number other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightValue);
- if(other==null) return FormulaError2.handleErrorCall(rightValue);
-
- result = new Double(result.doubleValue() * other.doubleValue());
-
- } else if("/".equals(op)) {
- if(result == null) {
- result = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftValue);
- if(result == null)
- return FormulaError2.handleErrorCall(leftValue);
- }
- Number other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightValue);
- if(other==null) return FormulaError2.handleErrorCall(rightValue);
- if(other.doubleValue()==0.0) return FormulaError2.DIV0.getString();
-
- result = new Double(result.doubleValue() / other.doubleValue());
- }
- }
- if(result == null) result = SpreadsheetGraphUtils.asNumber(exp.left.accept(this));
- return result;
- }
-
- @Override
- public Object visit(AstFactor exp) {
- Object result = null;
- for(int i=0;i<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- AstValue value = exp.rightValue(i);
- if("^".equals(op)) {
- if(result == null) {
- Object leftValue = exp.left.accept(this);
-
- FormulaError2 err = FormulaError2.forObject(leftValue);
- if(err!=null) return err.getString();
-
- if(leftValue instanceof Variant){
- Object leftTemp = ((Variant)leftValue).getValue();
- Double leftV = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftTemp);
- if(leftV==null) leftValue = leftTemp.toString();
- else leftValue = leftV;
- }
-
- if(leftValue instanceof String){
- if((leftValue.toString()).isEmpty())
- result = 0;
- else
- return FormulaError2.VALUE.getString();
- }
- else if(leftValue instanceof SpreadsheetMatrix)
- result = leftValue;
- else
- result = SpreadsheetGraphUtils.asNumber(leftValue);
- }
- Object otherValue = value.accept(this);
-
- FormulaError2 err2 = FormulaError2.forObject(otherValue);
- if(err2!=null) return err2.getString();
-
- if(otherValue instanceof Variant){
- Object otherTemp = ((Variant)otherValue).getValue();
- Double otherV = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(otherTemp);
- if(otherV==null) otherValue = otherTemp.toString();
- else otherValue = otherV;
- }
-
- if(otherValue instanceof String){
- if((otherValue.toString()).isEmpty())
- otherValue = 0;
- else
- return FormulaError2.VALUE.getString();
- }
-
- if(result instanceof SpreadsheetMatrix) {
- result = ((SpreadsheetMatrix)result).pow(otherValue);
- } else {
- if(otherValue instanceof SpreadsheetMatrix) {
- throw new IllegalStateException();
- } else {
- Double base = ((Number)result).doubleValue();
- Double exponent = SpreadsheetGraphUtils.asNumber(otherValue);
- if(exponent==0 && base==0)
- return FormulaError2.NUM.getString();
- if(exponent<0 && base==0)
- return FormulaError2.DIV0.getString();
- result = Math.pow(base, exponent);
- if(result instanceof Double && Double.isInfinite((Double)result)){
- return FormulaError2.NUM.getString();
- }
- }
- }
- }
- }
- if(result == null) result = SpreadsheetGraphUtils.asNumber(exp.left.accept(this));
- return result;
- }
-
- @Override
- public Object visit(AstIdentifier id) {
- return FormulaError2.NAME.getString();
- //throw new IllegalStateException();
- }
-
- @Override
- public Object visit(AstArray array) {
- SpreadsheetMatrix m = new SpreadsheetMatrix(array.values.size(), 1);
- for(int i=0;i<array.values.size();i++) {
- m.values[i] = array.values.get(i).accept(this);
- }
- return m;
- }
-
- @Override
- public Object visit(AstNothing array) {
- return AstNothing.NOTHING;
- }
-
- @Override
- public Object visit(AstArrayFormulaReference ref) {
-
- Range thisRange = SpreadsheetUtils.decodeRange(thisCell.getName());
- Range arrayRange = SpreadsheetUtils.decodeRange(ref.range);
- int x = thisRange.startColumn - arrayRange.startColumn;
- int y = thisRange.startRow - arrayRange.startRow;
-
- SpreadsheetMatrix m = (SpreadsheetMatrix)ref.value.accept(this);
- return m.get(y, x);
-
- }
-
-}
package org.simantics.spreadsheet.graph;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+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.SpreadsheetLines;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
public class EvaluateAll implements SpreadsheetVisitor {
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-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;
- }
-
-}
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-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;
- }
-
-}
import org.simantics.db.service.XSupport;
import org.simantics.layer0.Layer0;
import org.simantics.operation.Layer0X;
-import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.spreadsheet.Spreadsheets;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
+import org.simantics.spreadsheet.solver.formula.CellValueVisitor;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.spreadsheet.synchronization.ExcelArrayFormula;
+import org.simantics.spreadsheet.synchronization.ExcelFormula;
import org.simantics.utils.DataContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
graph.claim(sheet, 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, Spreadsheets.SPREADSHEET_BTREE_SIZE, SR.Lines, SR.LineNode, L0.PartOf, true);
result.add(bt);
Resource lines = bt.rootOfBTree();
Cell val = row.getCell(i, Row.RETURN_BLANK_AS_NULL);
if(val != null) {
- String cellName = SpreadsheetUtils.cellName(rowN, i);
+ String cellName = Spreadsheets.cellName(rowN, i);
int ccIndx = val.getColumnIndex();
if(columnWidths.size()<=ccIndx){
SheetFormulaParser p = new SheetFormulaParser(new StringReader("(-(0.2/2)+SQRT((0.2/2)^2-4*((0.2/2)^2-(3*0.17625)/(PI()*4.7))))"));
AstValue v = p.relation();
System.err.println("v="+v);
- SpreadsheetBook book = new SpreadsheetBook();
+ SpreadsheetBook book = new SpreadsheetBook("http:/");
Object o = v.accept(new CellValueVisitor(SpreadsheetEvaluationEnvironment.getInstance(book), null));
System.err.println("o="+o);
}
import org.simantics.spreadsheet.Adaptable;
import org.simantics.spreadsheet.CellEditor;
import org.simantics.spreadsheet.ClientModel;
-import org.simantics.spreadsheet.ClientModel.OperationMode;
+import org.simantics.spreadsheet.OperationMode;
import org.simantics.spreadsheet.SheetCommands;
+import org.simantics.spreadsheet.Transaction;
import org.simantics.spreadsheet.event.model.RemoveCellHandler;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
import org.simantics.ui.selection.WorkbenchSelectionUtils;
import org.simantics.utils.datastructures.Pair;
import org.simantics.utils.strings.AlphanumComparator;
package org.simantics.spreadsheet.graph;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+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.SpreadsheetLines;
+
public class InvalidateAll implements SpreadsheetVisitor {
public InvalidateAll() {
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.simantics.spreadsheet.Range;
-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;
-
-public class PrintVisitor implements AstValueVisitor<String> {
-
- @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<astArgList.values.size();i++) {
- if(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<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- b.append(op);
- AstValue value = exp.rightValue(i);
- b.append(value.accept(this));
- }
-
- return b.toString();
-
- }
-
- @Override
- public String visit(AstTerm exp) {
-
- StringBuilder b = new StringBuilder();
-
- b.append(exp.left.accept(this));
-
- for(int i=0;i<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- b.append(op);
- AstValue value = exp.rightValue(i);
- b.append(value.accept(this));
- }
-
- return b.toString();
-
- }
-
- @Override
- public String visit(AstFactor exp) {
-
- StringBuilder b = new StringBuilder();
-
- b.append(exp.left.accept(this));
-
- for(int i=0;i<exp.rightCount();i++) {
- String op = exp.rightOp(i);
- b.append(op);
- AstValue value = exp.rightValue(i);
- b.append(value.accept(this));
- }
-
- return b.toString();
-
- }
-
- @Override
- public String visit(AstIdentifier id) {
- return "AstIdentifier";
- }
-
- @Override
- public String visit(AstArray array) {
- StringBuilder b = new StringBuilder();
- for(int i=0;i<array.values.size();i++) {
- if(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) + "}";
- }
-
-}
+++ /dev/null
-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<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
-
- private static final long serialVersionUID = 7417208688311691396L;
-
- public Serializable NotAvailableError = new Serializable() {
- private static final long serialVersionUID = 2535371785498129460L;
- };
-
- public Long2ObjectOpenHashMap<AbstractLongSet> referenceMap = new Long2ObjectOpenHashMap<>();
-
- private Int2ObjectArrayMap<SpreadsheetStyle> styles = new Int2ObjectArrayMap<>();
-// public ObjectArrayList<SpreadsheetStyle> styles = new ObjectArrayList<SpreadsheetStyle>();
- public ArrayList<SpreadsheetEngine> sheets = new ArrayList<SpreadsheetEngine>();
-
- private SpreadsheetMapping mapping;
-
-
- private int idCounter = 1;
-
- public SpreadsheetBook() {
- getNewId(this);
- mapping = new SpreadsheetMapping(new SheetLineComponent(""));
- }
-
- public Map<Integer, SpreadsheetElement> 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<sheets.size();i++)
- if(sheets.get(i) == engine) return i;
- throw new IllegalStateException("Did not find sheet " + engine.getName());
- }
-
- public void registerReferences(long cell, AbstractLongList refs) {
- for(int i=0;i<refs.size();i++) {
- long key = refs.getLong(i);
- AbstractLongSet set = referenceMap.get(key);
- if(set == null) {
- set = new LongArraySet();
- referenceMap.put(key, set);
- }
- if(set.size() == 5) {
- AbstractLongSet newSet = new LongLinkedOpenHashSet();
- newSet.addAll(set);
- set = newSet;
- referenceMap.put(key, set);
- }
- set.add(cell);
- }
- }
-
- @Override
- public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
- Object value = getEngineValue(node);
- if(value instanceof Variant) return Bindings.VARIANT;
- if(value instanceof String) return Bindings.STRING;
- if(value instanceof Boolean) return Bindings.BOOLEAN;
- else return Bindings.VOID;
-
- }
-
- @Override
- public Object getEngineValue(SheetNode node) {
- if(node instanceof SpreadsheetCellContent) {
- try {
- SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
- Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
- if(content == null) return Variant.ofInstance("");
- if(content instanceof Variant) return content;
- else return Variant.ofInstance(content);
- } catch (Throwable t) {
- t.printStackTrace();
- return Variant.ofInstance(t.toString());
- }
- } else if (node instanceof SpreadsheetCellContentExpression) {
- SpreadsheetCellContentExpression scce = (SpreadsheetCellContentExpression)node;
- if (scce.cell.content instanceof SpreadsheetFormula) {
- SpreadsheetFormula formula = (SpreadsheetFormula)scce.cell.content;
- return formula.expression;
- } else if (scce.cell.content instanceof SpreadsheetSCLConstant) {
- SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) scce.cell.content;
- return "=" + sclConstant.expression;
- } else {
- System.out.println("Broken SpreadsheetCellContentExpression possibly due to overwriting an existing expression with a constant or something else (current content is " + scce.cell.content + ")");
- if (scce.cell.content instanceof Variant) {
- return scce.cell.content;
- } else {
- return Variant.ofInstance(scce.cell.content);
- }
- }
- } else if (node instanceof SpreadsheetTypeNode) {
- SpreadsheetTypeNode stn = (SpreadsheetTypeNode)node;
- return stn.uri;
- } else if (node instanceof SpreadsheetCellStyle) {
- int styleId = ((SpreadsheetCellStyle) node).cell.style;
- SpreadsheetStyle style = getStyle(styleId);
- if (style == null) {
- style = SpreadsheetStyle.empty();
- if (styleId != style.getStyleId())
- new Exception("different style ids!" + styleId + " " + style.getStyleId()).printStackTrace();
- addStyle(style);
- }
- return style;
- } else if (node instanceof SpreadsheetCellEditable) {
- boolean editable = ((SpreadsheetCellEditable) node).editable();
- return editable;
- }
- return null;
- }
-
- @Override
- public void setEngineValue(SheetNode node, Object value) {
- }
-
- @Override
- public String getName(SheetNode node) {
- return node.getName();
- }
-
- @Override
- public Map<String, SheetNode> getChildren(SheetNode node) {
- return node.getChildren();
- }
-
- @Override
- public Map<String, SheetNode> getProperties(SheetNode node) {
- return node.getProperties();
- }
-
- @Override
- public String getName() {
- return "";
- }
-
- @Override
- public Map<String, SpreadsheetEngine> getChildren() {
- Map<String,SpreadsheetEngine> result = new HashMap<String,SpreadsheetEngine>();
- for(SpreadsheetEngine engine : sheets)
- result.put(engine.getName(), engine);
- return result;
- }
-
- @Override
- public Map<String, SheetNode> 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<SheetLineComponent> 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<SpreadsheetElement> 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> 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> 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<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
- Set<SpreadsheetCell> 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<SpreadsheetCell> invalidateShallow(SpreadsheetCell cell) {
- ArrayList<SpreadsheetCell> 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<SheetLineComponent> getMapping() {
- return mapping;
- }
-
- @Override
- public Optional<SpreadsheetElement> getParent() {
- return Optional.empty();
- }
-
- @Override
- public Collection<SpreadsheetElement> 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;
- }
-
-}
+++ /dev/null
-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<String, SheetNode> 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<String, SheetNode> createProperties() {
- Map<String, SheetNode> 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<String, SheetNode> 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> T evaluate(SpreadsheetEvaluationEnvironment env) {
- return evaluate(env, null);
- }
-
- public <T> 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<env.iterationLimit){
- this.inProgress = true;
- f.result = value.accept(visitor);
- }
- else {
- if(f.result==null)
- f.result = 0.0;
- }
-
- env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
- }
- this.inProgress = false;
- this.iterations = 0;
- return (T)f.result;
- } else if (content instanceof SpreadsheetSCLConstant) {
- SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
- return (T) sclConstant.content;
- } else {
- this.inProgress = false;
- return (T)content;
- }
- }
-
- public long makeReferenceKey() {
- SpreadsheetBook book = getBook();
- SpreadsheetEngine engine = getEngine();
- long engineIndex = book.getEngineIndex(engine);
- long row = line.row;
- long col = column;
- return (engineIndex << 40) + (row << 20) + col;
- }
-
- public void invalidate() {
- getEngine().rangeCache = null;
- if(content instanceof SpreadsheetFormula) {
- SpreadsheetFormula f = (SpreadsheetFormula)content;
- f.result = null;
- }
- }
-
- @Override
- public void accept(SpreadsheetVisitor v) {
- v.visit(this);
- }
-
- @Override
- public Optional<SpreadsheetElement> getParent() {
- return Optional.of(line);
- }
-
- @Override
- public List<SpreadsheetElement> 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;
- }
-
-}
+++ /dev/null
-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<String,Object> rangeCache;
-
- public Map<String,Object> getRangeCache() {
- if(rangeCache == null) rangeCache = new HashMap<String,Object>();
- 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<String, SheetNode> getChildren() {
- return Collections.singletonMap(LINES, lines);
- }
-
- @Override
- public Map<String, SheetNode> 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<SpreadsheetElement> getParent() {
- return Optional.of(book);
- }
-
- @Override
- public List<SpreadsheetElement> 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
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);
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 {
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();
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;
}
- 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<Variable> possibleConfigurationCellVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
List<Variable> rowVariables = possibleConfigurationLineVariables(graph, sheet, range);
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");
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, ""));
}
}
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<String, Variant>(uri) {
+
+ @Override
+ public Variant perform(ReadGraph graph) throws DatabaseException {
+ Variable variable = Variables.getVariable(graph, parameter);
+ return variable.getVariantValue(graph);
+ }
+
+ }, new Listener<Variant>() {
+
+ @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, String, Variant>((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<Variant>() {
+
+ @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());
+ }
+
}
+++ /dev/null
-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<SpreadsheetCell, SpreadsheetLines>, SheetNode {
-
- private static final long serialVersionUID = -304574098117404663L;
-
- final private SpreadsheetLines parent;
- final public int row;
- int id;
-
- public ObjectArrayList<SpreadsheetCell> 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<String,SpreadsheetCell> result = new HashMap<>();
- for(int i=0;i<cells.size();i++) {
- SpreadsheetCell cell = cells.get(i);
- if(SpreadsheetCell.EMPTY == cell) continue;
- String name = "Row"+SpreadsheetUtils.columnName(i) + rowName;
- result.put(name, cell);
- }
- return result;
- }
-
- @Override
- public Map getProperties() {
- return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Line));
- }
-
- Object resolve(String[] parts, int index) {
-
- if(index == parts.length) return this;
-
- Range r = SpreadsheetUtils.decodeCellAbsolute(parts[index]);
- return cells.get(r.startColumn);
-
- }
-
- public void accept(SpreadsheetVisitor v) {
- v.visit(this);
- }
-
- public String getPath() {
- return ((SpreadsheetLines)parent).getPath() + "/" + getName();
- }
-
- @Override
- public Optional<SpreadsheetLines> getParent() {
- return Optional.of(parent);
- }
-
- @Override
- public List<SpreadsheetCell> 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;
- }
-
-}
+++ /dev/null
-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<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
-
- private static final long serialVersionUID = -3615335969248723486L;
-
- private final int id;
- private SpreadsheetEngine parent;
- private String name;
- public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
- public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
- 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<SpreadsheetEngine> getParent() {
- return Optional.of(parent);
- }
-
- @Override
- public Collection<SpreadsheetLine> 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;
- }
-
-}
+++ /dev/null
-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<SheetLineComponent> 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<SheetLineComponent> createComponentFactory() {
- return new ComponentFactory<SheetLineComponent>() {
-
- @Override
- public SheetLineComponent create(String uid) {
- return new SheetLineComponent(uid);
- }
-
- };
- }
-
-}
+++ /dev/null
-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<values.length;i++) {
- Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
- if(n != null) result += n.doubleValue();
- }
- return result;
- }
-
- public Object sumWithFormulaError(){
- Double result = 0.0;
- for(int i = 0; i < values.length; i++){
- Object obj = values[i];
- if(obj != null){
- FormulaError2 error = FormulaError2.forObject(obj);
- if(error!=null) return error.getString();
-
- Number n = SpreadsheetGraphUtils.asValidNumber(obj);
- if(n != null) result += n.doubleValue();
- }
- }
- return result;
- }
-
- public double average() {
- double result = 0;
- double count = 0;
- for(int i=0;i<values.length;i++) {
- Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
- if(n != null) {
- result += n.doubleValue();
- count++;
- }
- }
- if(count == 0) return result;
- return result / count;
- }
-
- public double countOfActualDoubleValues(){
- double count = 0.0;
- for(int i = 0; i < values.length; i++){
- Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
- if(n!=null) count++;
- }
- return count;
- }
-
- public Object productWithFormulaError(){
- Double result = 1.0;
- boolean atLeastOne = false;
- for(int i = 0; i < values.length; i++){
- Object obj = values[i];
- if(obj != null){
- FormulaError2 error = FormulaError2.forObject(obj);
- if(error!=null) return error.getString();
-
- Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
- if(n != null) {
- double dval = n.doubleValue();
- if(dval<=0) return FormulaError2.NUM.getString();
- result = result*dval;
- atLeastOne = true;
- }
- }
- }
- if(atLeastOne) return result;
- else return 0.0;
- }
-
- public SpreadsheetMatrix pow(Object exponent_) {
- if(exponent_ instanceof SpreadsheetMatrix) {
- SpreadsheetMatrix exponent = (SpreadsheetMatrix)exponent_;
- SpreadsheetMatrix result = new SpreadsheetMatrix(exponent.w, h);
- for(int i=0;i<h;i++) {
- for(int j=0;j<exponent.w;j++) {
- result.set(i,j, Math.pow(SpreadsheetGraphUtils.asNumber(get(i, 0)),
- SpreadsheetGraphUtils.asNumber(exponent.get(0, j))));
- }
- }
- return result;
- } else {
- double n = SpreadsheetGraphUtils.asNumber(exponent_);
- SpreadsheetMatrix result = new SpreadsheetMatrix(w, h);
- for(int i=0;i<result.values.length;i++) {
- result.values[i] = Math.pow(SpreadsheetGraphUtils.asNumber(values[i]), n);
- }
- return result;
- }
- }
-
-
-}
\ No newline at end of file
package org.simantics.spreadsheet.graph;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.layer0.Layer0;
-import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.db.StandardVariableNodeManager;
import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.spreadsheet.SpreadsheetCellStyle;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetBook.SpreadsheetBookListener;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
+import org.simantics.spreadsheet.solver.SpreadsheetCellContentExpression;
+import org.simantics.spreadsheet.solver.SpreadsheetCellEditable;
+import org.simantics.spreadsheet.solver.SpreadsheetFormula;
+import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
+import org.simantics.spreadsheet.solver.SpreadsheetTypeNode;
import org.simantics.structural.stubs.StructuralResource2;
@SuppressWarnings("rawtypes")
-public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, SpreadsheetBook> {
+public class SpreadsheetNodeManager extends StandardVariableNodeManager<SheetNode, SpreadsheetBook> {
public SpreadsheetNodeManager(SpreadsheetRealm realm) {
super(realm, realm.getEngine());
+ realm.getEngine().registerListener(new SpreadsheetBookListener() {
+
+ @Override
+ public void cellsChanged(Collection<SpreadsheetCell> 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<String> COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component);
public void setValue(SheetNode node, Object value, Binding binding) throws NodeManagerException {
Set<SheetNode> 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
return dirtyNodeContents;
}
+
+
+ @Override
+ protected Variant getEngineVariantOrCached(SheetNode node) throws NodeManagerException {
+ Variant variant = valueCache.get(node);
+ if(variant == null) {
+ Object value = realm.getEngine().getEngineValue(node);
+ Binding binding = realm.getEngine().getEngineBinding(node);
+ variant = new Variant(binding, value);
+ valueCache.put(node, variant);
+ }
+ return variant;
+ }
+
}
import org.simantics.simulator.toolkit.StandardNodeManager;
import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
package org.simantics.spreadsheet.graph;
-import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
import org.simantics.structural.synchronization.base.ReferenceResolverBase;
import org.simantics.structural.synchronization.utils.Solver;
import org.slf4j.Logger;
import org.simantics.db.layer0.variable.Variables;
import org.simantics.simulator.toolkit.StandardRealm;
import org.simantics.simulator.toolkit.db.StandardVariableSessionManager;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
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.formula.SpreadsheetEvaluationEnvironment;
import org.simantics.structural.synchronization.client.Synchronizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return ic;
}
- SpreadsheetBook book = new SpreadsheetBook();
+ SpreadsheetBook book = new SpreadsheetBook(context.getURI(graph));
Variable base = ProxyVariables.proxyVariableBase(graph, run);
Resource bookResource = base.getRepresents(graph);
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collections;
-import java.util.Map;
-
-public class SpreadsheetTypeNode implements SheetNode {
-
- public final String uri;
-
- public SpreadsheetTypeNode(String uri) {
- this.uri = uri;
- }
-
- @Override
- public String getName() {
- return "typeURI";
- }
-
- @Override
- public Map getChildren() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map getProperties() {
- return Collections.emptyMap();
- }
-
-}
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-public interface SpreadsheetVisitable {
- void accept(SpreadsheetVisitor v);
-}
+++ /dev/null
-package org.simantics.spreadsheet.graph;
-
-public interface SpreadsheetVisitor {
-
- void visit(SpreadsheetBook book);
- void visit(SpreadsheetEngine engine);
- void visit(SpreadsheetLines node);
- void visit(SpreadsheetLine line);
- void visit(SpreadsheetCell cell);
-
-}
import org.simantics.db.layer0.variable.Variable;
import org.simantics.db.layer0.variable.Variables;
import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
import org.simantics.spreadsheet.common.cell.VariableCellEditor;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
public class DoubleArrayCellVariable extends ConstantChildVariable {
if(baseLocation == null) return;
String editLocation = cell.getPossiblePropertyValue(graph, Variables.NAME);
- Range baseRange = SpreadsheetUtils.decodeCellAbsolute(baseLocation);
- Range editRange = SpreadsheetUtils.decodeCellAbsolute(editLocation);
+ Range baseRange = Spreadsheets.decodeCellAbsolute(baseLocation);
+ Range editRange = Spreadsheets.decodeCellAbsolute(editLocation);
int x = editRange.startColumn - baseRange.startColumn;
int y = editRange.startRow - baseRange.startRow;
import java.util.Collections;
import org.simantics.databoard.Bindings;
-import org.simantics.databoard.Datatypes;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.db.ReadGraph;
import org.simantics.db.layer0.variable.VariableFactory;
import org.simantics.db.layer0.variable.Variables;
import org.simantics.spreadsheet.SheetVariables;
+import org.simantics.spreadsheet.Spreadsheets;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
import org.simantics.utils.datastructures.datatype.RGBInt8;
public class DoubleArrayCells implements VariableFactory {
for(int offset=0,i=0;i<rows;i++) {
for(int j=0;j<width;j++) {
double value = data[offset++];
- String valueLocation = SpreadsheetUtils.offset(location, i, j);
+ String valueLocation = Spreadsheets.offset(location, i, j);
result.add(new DoubleArrayCellVariable(variable, valueLocation, propertyNames, bindings, new Object[] { Variant.ofInstance(value), fore, back, configuration, String.valueOf(value), false }));
}
}
import org.simantics.layer0.Layer0;
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.util.SpreadsheetUtils;
public class SpreadsheetVariable extends ExtendedGraphChildVariable {
@Override
public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
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());
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 = getPossibleChild(graph, location);
Variant value = null;
if(child != null)
import org.simantics.db.layer0.variable.Variable;
import org.simantics.db.layer0.variable.VariableFactory;
import org.simantics.db.layer0.variable.Variables;
+import org.simantics.spreadsheet.Spreadsheets;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
public class StringArrayCells implements VariableFactory {
for(int offset=0,i=0;i<rows;i++) {
for(int j=0;j<width;j++) {
String value = data[offset++];
- String valueLocation = SpreadsheetUtils.offset(location, i, j);
+ String valueLocation = Spreadsheets.offset(location, i, j);
result.add(new ConstantChildVariable(variable, valueLocation, propertyNames, bindings, new Object[] { value, true }));
}
}
import org.simantics.db.layer0.variable.Variable;
import org.simantics.db.request.Write;
import org.simantics.spreadsheet.CellEditor;
-import org.simantics.spreadsheet.ClientModel.OperationMode;
+import org.simantics.spreadsheet.OperationMode;
+import org.simantics.spreadsheet.Transaction;
import org.simantics.spreadsheet.util.SpreadsheetUtils;
public class GraphCellEditorAdapter implements CellEditor<Write> {
+++ /dev/null
-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<Object> {
-
- @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
+++ /dev/null
-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<Object> {
-
- @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
+++ /dev/null
-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<Integer> {
-
- @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);
- }
-}
+++ /dev/null
-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<String, FormulaError2> smap = new HashMap<String, FormulaError2>();
-
- 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
+++ /dev/null
-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<Object> {
-
- @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)));
- }
-
-}
+++ /dev/null
-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<Object> {
-
- @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();
- }
-
-}
+++ /dev/null
-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<Object>{
-
- @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 && currValue<previousValue))
- indexWhereCorrectOrderStartsAt = i;
- else
- break;
- }
- previousValue = currValue;
- }
- }
- }
- }
- int begin = indexWhereCorrectOrderStartsAt;
-
- for(int i = begin; 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) previousValue = currValue;
- if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue)){
- 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;
- }
- }
- }
- }
-
- 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;
- }
-}
+++ /dev/null
-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<Object> {
-
- @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;
- }
-
-}
+++ /dev/null
-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<Object> {
-
- @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();
- }
-
-}
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;
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;
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()];
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)
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 {
String identifier = node.toString().trim();
- Range range = SpreadsheetUtils.decodeRange(identifier, row, column);
+ Range range = Spreadsheets.decodeRange(identifier, row, column);
if (range.size() != 1) {
ArrayList<Object> value = new ArrayList<Object>();
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");
+++ /dev/null
-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<bean.cells.length;i++) {
-
- SpreadsheetCell currentCell;
- if (line.cells.size() > 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> T getConcrete() {
- return (T)this;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<SheetLineComponent> {
-
- public LineNodeUpdater(String id) {
-
- super(id);
-
- isComposite = true;
-
- addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
-
- @Override
- public String getPropertyName() {
- return "keys";
- }
-
- @Override
- public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
- Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
-
- LinesCommandBuilder builder = context.<LinesCommandBuilder>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
+++ /dev/null
-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<SheetLineComponent> {
-
- public LineUpdater(String id) {
- super(id);
- addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
-
- @Override
- public String getPropertyName() {
- return "content";
- }
-
- @Override
- public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
- Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
-
- LineCommandBuilder builder = context.<LineCommandBuilder>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
+++ /dev/null
-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<bean.cells.length;i++) {
-//
-// LineContentBeanCell cell = bean.cells[i];
-//
-// try {
-//
-// if(ExcelFormula.BINDING.type().equals(cell.content.getBinding().type())) {
-// ExcelFormula formula = (ExcelFormula)cell.content.getValue(ExcelFormula.BINDING);
-// SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
-// AstValue v = p.relation();
-// line.cells.add(new SpreadsheetCell(line, i, new SpreadsheetFormula(v, formula.expression), 0));
-// } else {
-// line.cells.add(new SpreadsheetCell(line, i, cell.content.getValue(), 0));
-// }
-// } catch (Throwable e) {
-// line.cells.add(new SpreadsheetCell(line, i, cell.content.getValue(), 0));
-// try {
-// new Exception("failed: " + ((ExcelFormula)(cell.content.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace();
-// } catch (AdaptException e1) {
-// e1.printStackTrace();
-// }
-// }
-//
-// }
-
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T getConcrete() {
- return (T)this;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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> T getConcrete() {
- return (T)this;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<SheetLineComponent> {
-
- 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
+++ /dev/null
-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<SheetLineComponent> implements Serializable {
-
- private static final long serialVersionUID = 1777515716175831266L;
-
- private THashMap<String, SheetLineComponent> 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<String, SheetLineComponent> getChildMap() {
- return childMap;
- }
-
- @Override
- public void setChildMap(THashMap<String, SheetLineComponent> newChildMap) {
- childMap = newChildMap;
- if(childMap != null) {
- childMap.forEachValue(new TObjectProcedure<SheetLineComponent>() {
- @Override
- public boolean execute(SheetLineComponent component) {
- component.parent = SheetLineComponent.this;
- return true;
- }
- });
- }
- }
-
- @Override
- public String toString() {
- return solverComponentName + " (" + super.toString() + ")";
- }
-
-}
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;
*******************************************************************************/
package org.simantics.spreadsheet.ui;
-import gnu.trove.map.hash.THashMap;
-
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
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<String, Map<String, Object>> properties = new THashMap<String, Map<String, Object>>();
Map<String, Object> 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);
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);
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;
@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);
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 {
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);
}
}
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;
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);
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);
}
}
for(int i=0;i<from.height();i++) {
for(int j=0;j<from.width();j++) {
- String fromCell = SpreadsheetUtils.cellName(from.startRow+i, from.startColumn+j);
- String toCell = SpreadsheetUtils.cellName(to.startRow+i, to.startColumn+j);
+ String fromCell = Spreadsheets.cellName(from.startRow+i, from.startColumn+j);
+ String toCell = Spreadsheets.cellName(to.startRow+i, to.startColumn+j);
Object obj = model.getPropertyAt(fromCell, "content");
if (obj == null)
continue;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.spreadsheet.CellEditor;
import org.simantics.spreadsheet.ClientModel;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.Spreadsheets;
public class ExpressionTextListener implements FocusListener, KeyListener {
if(currentRow == -1 || currentColumn == -1) return;
if (current.startsWith("=")) {
- editor.edit(null, SpreadsheetUtils.cellName(currentRow, currentColumn), ClientModel.CONTENT_EXPRESSION, current, Bindings.STRING, null);
+ editor.edit(null, Spreadsheets.cellName(currentRow, currentColumn), ClientModel.CONTENT_EXPRESSION, current, Bindings.STRING, null);
} else {
- editor.edit(null, SpreadsheetUtils.cellName(currentRow, currentColumn), Variant.ofInstance(current), null);
+ editor.edit(null, Spreadsheets.cellName(currentRow, currentColumn), Variant.ofInstance(current), null);
}
undoPoint = current;
import org.simantics.db.layer0.variable.Variable;
import org.simantics.spreadsheet.Adaptable;
import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.Spreadsheets;
import org.simantics.spreadsheet.util.SpreadsheetUtils;
-import org.simantics.utils.ui.jface.ActiveSelectionProvider;
import org.simantics.ui.selection.VariableWorkbenchSelectionElement;
+import org.simantics.utils.ui.jface.ActiveSelectionProvider;
public class SelectionListener implements ListSelectionListener {
String expression = "";
- Object expressionO = clientModel.getPossiblePropertyAt(SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
+ Object expressionO = clientModel.getPossiblePropertyAt(Spreadsheets.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
if(expressionO instanceof String) {
expression = (String)expressionO;
} else if(expressionO instanceof Variant) {
}
if(expression == null) {
- Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT);
+ Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, Spreadsheets.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT);
if(content != null)
expression = content.getValue().toString();
else
import org.simantics.scenegraph.swing.JScrollPaneSG;
import org.simantics.spreadsheet.Adaptable;
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.SheetCommands;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.Transaction;
import org.simantics.spreadsheet.common.cell.Parsers;
import org.simantics.spreadsheet.common.cell.StringCellParser;
import org.simantics.spreadsheet.event.model.RemoveCellHandler;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
import org.simantics.ui.colors.Colors;
import org.simantics.ui.dnd.LocalObjectTransfer;
import org.simantics.ui.dnd.LocalObjectTransferable;
import org.simantics.ui.fonts.Fonts;
-import org.simantics.utils.ui.dialogs.ShowMessage;
import org.simantics.utils.ui.awt.WrapLayout;
+import org.simantics.utils.ui.dialogs.ShowMessage;
import org.simantics.utils.ui.jface.ActiveSelectionProvider;
@SuppressWarnings({ "rawtypes", "unchecked" })
for(int col : selectedColumns) {
for(int row : selectedRows) {
- String location = SpreadsheetUtils.cellName(row, col);
+ String location = Spreadsheets.cellName(row, col);
// No
if(index == 0) {
if(col > 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);
// 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);
}
}
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();
}
}
- 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);
}
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);
}
}
// 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;
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 {
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 {
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) {
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
}
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 {
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");
}
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;
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);
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);
for(int i=0;i<range.height();i++) {
for(int j=0;j<range.width();j++) {
- String addr = SpreadsheetUtils.cellName(range.startRow + i, range.startColumn + j);
+ String addr = Spreadsheets.cellName(range.startRow + i, range.startColumn + j);
String content = parts[index++];
Resource cell = Layer0Utils.getPossibleChild(graph, container, addr);
for(Pair<String, Object> 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) {
}
for(Pair<String, Object> 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;
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
final TableSelection sel = (TableSelection)it.next();
int row = sel.getRows()[0];
int column = sel.getColumns()[0];
- String location = SpreadsheetUtils.cellName(row, column);
+ String location = Spreadsheets.cellName(row, column);
ArrayList<ComparableTabContributor> result = new ArrayList<ComparableTabContributor>();
final Variable cell = variable.getPossibleChild(graph, location);
if(cell != null) {
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
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
public interface Adaptable {
-
- <T> T getAdapter(Class<T> clazz);
-
+
+ <T> T getAdapter(Class<T> clazz);
+
}
*******************************************************************************/
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<O> {
-
- public interface Transaction<O> {
-
- void setContext(Object context);
-
- Object getContext();
-
- void add(O operation);
-
- /*
- * Applies the operations collected with this transaction
- *
- */
- void commit();
-
- boolean isOperationMode();
-
- List<Object> 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
- */
- <T> void edit(Transaction<O> 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
+ */
+ <T> void edit(Transaction<O> 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<O> transaction, String location, Variant variant, Consumer<?> callback);
void copy(Transaction<O> transaction, String location, MutableVariant variant, Consumer<?> callback);
-
- /*
- * Creates a new transaction object
- *
- */
+
+ /*
+ * Creates a new transaction object
+ *
+ */
Transaction<O> startTransaction(OperationMode mode);
-
+
}
* 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();
}
* 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 {
public CellParseException(String message) {
super(message);
}
-
+
}
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> T getPropertyAt(String location, String property);
<T> T getPossiblePropertyAt(String location, String property);
-
+
int[] getColumnWidths();
int[] getRowHeights();
-
+
int getRows();
int getColumns();
- public Collection<Pair<String, Object>> 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<Rectangle> getSpans();
-
+ public Collection<Pair<String, Object>> 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<Rectangle> getSpans();
+
}
public interface CommandCellExecutor {
-
+
void execute(int row, int column);
-
+
}
public interface Disposable {
- void dispose();
-
+ void dispose();
+
}
--- /dev/null
+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);
+
+}
public interface Matrix {
-
- int getColumnCount();
- int getRowCount();
- Object get(int row, int column);
- Collection<Object> getColumn(int column);
- Collection<Object> getRow(int column);
-
+
+ int getColumnCount();
+ int getRowCount();
+ Object get(int row, int column);
+ Collection<Object> getColumn(int column);
+ Collection<Object> getRow(int column);
+
}
--- /dev/null
+package org.simantics.spreadsheet;
+
+public enum OperationMode {
+ OPERATION,
+ EDIT_MODE
+}
\ No newline at end of file
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;
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 + ")]";
}
-
+
}
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";
}
-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;
}
public Map getProperties() {
return Collections.emptyMap();
}
-
+
@Override
public int hashCode() {
final int prime = 31;
--- /dev/null
+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<values.length;i++) {
+ Number n = Spreadsheets.asValidNumber(values[i]);
+ if(n != null) result += n.doubleValue();
+ }
+ return result;
+ }
+
+ public Object sumWithFormulaError(){
+ Double result = 0.0;
+ for(int i = 0; i < values.length; i++){
+ Object obj = values[i];
+ if(obj != null){
+ FormulaError2 error = FormulaError2.forObject(obj);
+ if(error!=null) return error.getString();
+
+ Number n = Spreadsheets.asValidNumber(obj);
+ if(n != null) result += n.doubleValue();
+ }
+ }
+ return result;
+ }
+
+ public double average() {
+ double result = 0;
+ double count = 0;
+ for(int i=0;i<values.length;i++) {
+ Number n = Spreadsheets.asValidNumber(values[i]);
+ if(n != null) {
+ result += n.doubleValue();
+ count++;
+ }
+ }
+ if(count == 0) return result;
+ return result / count;
+ }
+
+ public double countOfActualDoubleValues(){
+ double count = 0.0;
+ for(int i = 0; i < values.length; i++){
+ Number n = Spreadsheets.asValidNumber(values[i]);
+ if(n!=null) count++;
+ }
+ return count;
+ }
+
+ public Object productWithFormulaError(){
+ Double result = 1.0;
+ boolean atLeastOne = false;
+ for(int i = 0; i < values.length; i++){
+ Object obj = values[i];
+ if(obj != null){
+ FormulaError2 error = FormulaError2.forObject(obj);
+ if(error!=null) return error.getString();
+
+ Number n = Spreadsheets.asValidNumber(values[i]);
+ if(n != null) {
+ double dval = n.doubleValue();
+ if(dval<=0) return FormulaError2.NUM.getString();
+ result = result*dval;
+ atLeastOne = true;
+ }
+ }
+ }
+ if(atLeastOne) return result;
+ else return 0.0;
+ }
+
+ public SpreadsheetMatrix pow(Object exponent_) {
+ if(exponent_ instanceof SpreadsheetMatrix) {
+ SpreadsheetMatrix exponent = (SpreadsheetMatrix)exponent_;
+ SpreadsheetMatrix result = new SpreadsheetMatrix(exponent.w, h);
+ for(int i=0;i<h;i++) {
+ for(int j=0;j<exponent.w;j++) {
+ result.set(i,j, Math.pow(Spreadsheets.asNumber(get(i, 0)),
+ Spreadsheets.asNumber(exponent.get(0, j))));
+ }
+ }
+ return result;
+ } else {
+ double n = Spreadsheets.asNumber(exponent_);
+ SpreadsheetMatrix result = new SpreadsheetMatrix(w, h);
+ for(int i=0;i<result.values.length;i++) {
+ result.values[i] = Math.pow(Spreadsheets.asNumber(values[i]), n);
+ }
+ return result;
+ }
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.spreadsheet;
+
+public interface SpreadsheetVisitable {
+ void accept(SpreadsheetVisitor v);
+}
--- /dev/null
+package org.simantics.spreadsheet;
+
+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.SpreadsheetLines;
+
+public interface SpreadsheetVisitor {
+
+ void visit(SpreadsheetBook book);
+ void visit(SpreadsheetEngine engine);
+ void visit(SpreadsheetLines node);
+ void visit(SpreadsheetLine line);
+ void visit(SpreadsheetCell cell);
+
+}
--- /dev/null
+package org.simantics.spreadsheet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.scl.runtime.tuple.Tuple;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+
+public class Spreadsheets {
+
+ public static final int SPREADSHEET_BTREE_SIZE = 100;
+ public static final String CELL_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Cell";
+ public static final String LINE_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Line";
+ public static final String LINES_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Lines";
+
+ 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);
+ }
+
+
+ // 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<Range> decodeRanges(String ranges){
+ String[] splitted = ranges.split(",");
+ List<Range> 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<Range> ranges){
+ int s = -1;
+ for(Range r : ranges){
+ if(r.startRow<s || s==-1){
+ s = r.startRow;
+ }
+ }
+ return s;
+ }
+
+ public static int startColumn(List<Range> ranges){
+ int s = -1;
+ for(Range r : ranges){
+ if(r.startColumn<s || s==-1){
+ s = r.startColumn;
+ }
+ }
+ return s;
+ }
+
+ public static int amountOfRows(Range r){
+ int endRow = -2;
+ int startRow = -2;
+ if(r.isFullRows()){
+ return Range.MAXROWSPEC;
+ }
+ if(endRow == -2 && startRow == -2){
+ endRow = r.endRow;
+ startRow = r.startRow;
+ }
+ if(r.startRow<startRow){
+ startRow = r.startRow;
+ }
+ if(r.endRow>endRow){
+ 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.startColumn<startColumn){
+ startColumn = r.startColumn;
+ }
+ if(r.endColumn>endColumn){
+ 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.");
+
+ }
+
+ }
+
+}
--- /dev/null
+package org.simantics.spreadsheet;
+
+import java.util.List;
+
+public interface Transaction<O> {
+
+ void setContext(Object context);
+
+ Object getContext();
+
+ void add(O operation);
+
+ /*
+ * Applies the operations collected with this transaction
+ *
+ */
+ void commit();
+
+ boolean isOperationMode();
+
+ List<Object> needSynchronization();
+
+ void needSynchronization(Object synchronizable);
+}
\ No newline at end of file
--- /dev/null
+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) {
+ }
+
+}
+
--- /dev/null
+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
--- /dev/null
+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<SheetLineComponent> implements Serializable {
+
+ private static final long serialVersionUID = 1777515716175831266L;
+
+ private THashMap<String, SheetLineComponent> childMap = new THashMap<>();
+
+ public SheetLineComponent(String uid) {
+ super(uid, 0);
+ }
+
+ @Override
+ public THashMap<String, SheetLineComponent> getChildMap() {
+ return childMap;
+ }
+
+ @Override
+ public void setChildMap(THashMap<String, SheetLineComponent> newChildMap) {
+ childMap = newChildMap;
+ if(childMap != null) {
+ childMap.forEachValue(new TObjectProcedure<SheetLineComponent>() {
+ @Override
+ public boolean execute(SheetLineComponent component) {
+ component.parent = SheetLineComponent.this;
+ return true;
+ }
+ });
+ }
+ }
+
+ @Override
+ public String toString() {
+ return solverComponentName + " (" + super.toString() + ")";
+ }
+
+}
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
import java.io.Serializable;
import java.util.Map;
public interface SheetNode<Child extends SheetNode<?, ?>, Property extends SheetNode<?, ?>> extends Serializable {
- String getName();
- Map<String, Child> getChildren();
- Map<String, Property> getProperties();
-
+ String getName();
+ Map<String, Child> getChildren();
+ Map<String, Property> getProperties();
+
}
--- /dev/null
+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<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
+
+ private static final long serialVersionUID = 7417208688311691396L;
+
+ public Serializable NotAvailableError = new Serializable() {
+ private static final long serialVersionUID = 2535371785498129460L;
+ };
+
+ public Long2ObjectOpenHashMap<AbstractLongSet> referenceMap = new Long2ObjectOpenHashMap<>();
+
+ private Int2ObjectArrayMap<SpreadsheetStyle> styles = new Int2ObjectArrayMap<>();
+ public ArrayList<SpreadsheetEngine> sheets = new ArrayList<SpreadsheetEngine>();
+
+ 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<Integer, SpreadsheetElement> 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<sheets.size();i++)
+ if(sheets.get(i) == engine) return i;
+ throw new IllegalStateException("Did not find sheet " + engine.getName());
+ }
+
+ public void registerReferences(long cell, AbstractLongList refs) {
+ for(int i=0;i<refs.size();i++) {
+ long key = refs.getLong(i);
+ AbstractLongSet set = referenceMap.get(key);
+ if(set == null) {
+ set = new LongArraySet();
+ referenceMap.put(key, set);
+ }
+ if(set.size() == 5) {
+ AbstractLongSet newSet = new LongLinkedOpenHashSet();
+ newSet.addAll(set);
+ set = newSet;
+ referenceMap.put(key, set);
+ }
+ set.add(cell);
+ }
+ }
+
+ @Override
+ public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
+ Object value = getEngineValue(node);
+ if(value instanceof Variant) return Bindings.VARIANT;
+ if(value instanceof String) return Bindings.STRING;
+ if(value instanceof Boolean) return Bindings.BOOLEAN;
+ else return Bindings.getBindingUnchecked(value.getClass());
+ }
+
+ @Override
+ public Object getEngineValue(SheetNode node) {
+ if(node instanceof SpreadsheetCellContent) {
+ try {
+ SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
+ Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
+ if(content == null) return Variant.ofInstance("");
+ if(content instanceof Variant) return content;
+ if(content instanceof ExternalRefData) return ((ExternalRefData)content).getContent();
+ else return Variant.ofInstance(content);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return Variant.ofInstance(t.toString());
+ }
+ } else if (node instanceof SpreadsheetCellContentExpression) {
+ SpreadsheetCellContentExpression scce = (SpreadsheetCellContentExpression)node;
+ if (scce.cell.getContent() instanceof SpreadsheetFormula) {
+ SpreadsheetFormula formula = (SpreadsheetFormula)scce.cell.getContent();
+ return formula.expression;
+ } else if (scce.cell.getContent() instanceof SpreadsheetSCLConstant) {
+ SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) scce.cell.getContent();
+ return "=" + sclConstant.getExpression();
+ } else {
+ System.out.println("Broken SpreadsheetCellContentExpression possibly due to overwriting an existing expression with a constant or something else (current content is " + scce.cell.getContent() + ")");
+ if (scce.cell.getContent() instanceof Variant) {
+ return scce.cell.getContent();
+ } else {
+ return Variant.ofInstance(scce.cell.getContent());
+ }
+ }
+ } else if (node instanceof SpreadsheetTypeNode) {
+ SpreadsheetTypeNode stn = (SpreadsheetTypeNode)node;
+ return stn.uri;
+ } else if (node instanceof SpreadsheetCellStyle) {
+ int styleId = ((SpreadsheetCellStyle) node).cell.style;
+ SpreadsheetStyle style = getStyle(styleId);
+ if (style == null) {
+ style = SpreadsheetStyle.empty();
+ if (styleId != style.getStyleId())
+ new Exception("different style ids!" + styleId + " " + style.getStyleId()).printStackTrace();
+ addStyle(style);
+ }
+ return style;
+ } else if (node instanceof SpreadsheetCellEditable) {
+ boolean editable = ((SpreadsheetCellEditable) node).editable();
+ return editable;
+ }
+ return null;
+ }
+
+ @Override
+ public void setEngineValue(SheetNode node, Object value) {
+
+ SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
+
+ Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
+ System.err.println("content2: " + content);
+ if (content instanceof Variant) {
+ scc.cell.setContent(value);
+ } else if (content instanceof ExternalRefData) {
+ ExternalRefData erd = (ExternalRefData)content;
+ erd.getRef().modify(context, (Variant)value);
+ } else {
+ throw new IllegalStateException("Unable to set cell value");
+ }
+
+ }
+
+ @Override
+ public String getName(SheetNode node) {
+ return node.getName();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Map<String, SheetNode> getChildren(SheetNode node) {
+ return node.getChildren();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Map<String, SheetNode> getProperties(SheetNode node) {
+ return node.getProperties();
+ }
+
+ @Override
+ public String getName() {
+ return "";
+ }
+
+ @Override
+ public Map<String, SpreadsheetEngine> getChildren() {
+ Map<String,SpreadsheetEngine> result = new HashMap<String,SpreadsheetEngine>();
+ for(SpreadsheetEngine engine : sheets)
+ result.put(engine.getName(), engine);
+ return result;
+ }
+
+ @Override
+ public Map<String, SheetNode> 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<SheetLineComponent> 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<SpreadsheetElement> 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> 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> 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<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
+ Set<SpreadsheetCell> 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<SpreadsheetCell> invalidateShallow(SpreadsheetCell cell) {
+ ArrayList<SpreadsheetCell> 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<SheetLineComponent> getMapping() {
+ return mapping;
+ }
+
+ @Override
+ public Optional<SpreadsheetElement> getParent() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Collection<SpreadsheetElement> 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<ExternalRef,ExternalRefData> 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<SpreadsheetCell> cells);
+ }
+
+ public void registerListener(SpreadsheetBookListener listener) {
+ if(listeners == null)
+ listeners = new ArrayList<>();
+ listeners.add(listener);
+ }
+
+ private transient ArrayList<SpreadsheetBookListener> listeners = new ArrayList<>();
+
+ public void fireChanges(Collection<SpreadsheetCell> cells) {
+ for(SpreadsheetBookListener listener : listeners)
+ listener.cellsChanged(cells);
+ }
+
+}
--- /dev/null
+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<String, SheetNode> 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<String, SheetNode> createProperties() {
+ Map<String, SheetNode> 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<String, SheetNode> getProperties() {
+ return properties;
+ }
+
+ public SpreadsheetBook getBook() {
+ return line.getEngine().getBook();
+ }
+
+ public SpreadsheetEngine getEngine() {
+ return line.getEngine();
+ }
+
+ public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {
+ return evaluate(env, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> 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<env.iterationLimit){
+ this.inProgress = true;
+ f.result = value.accept(visitor);
+ }
+ else {
+ if(f.result==null)
+ f.result = 0.0;
+ }
+ env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
+ }
+ this.inProgress = false;
+ this.iterations = 0;
+ return (T)f.result;
+ } else if (content instanceof SpreadsheetSCLConstant) {
+ SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
+ Object c = sclConstant.getContent();
+ if(c instanceof Variant) {
+ Variant v = (Variant)c;
+ return (T) c;
+ } else if (c instanceof ExternalRef) {
+ ExternalRefData erd = env.getBook().getExternalRefValue(makeReferenceKey(), (ExternalRef)c);
+ return (T)erd;
+ } else {
+ throw new IllegalStateException("Unsupported content " + c);
+ }
+ } else {
+ this.inProgress = false;
+ return (T)content;
+ }
+ }
+
+ public long makeReferenceKey() {
+ SpreadsheetBook book = getBook();
+ SpreadsheetEngine engine = getEngine();
+ long engineIndex = book.getEngineIndex(engine);
+ long row = line.row;
+ long col = column;
+ return (engineIndex << 40) + (row << 20) + col;
+ }
+
+ public void invalidate() {
+ getEngine().rangeCache = null;
+ if(content instanceof SpreadsheetFormula) {
+ SpreadsheetFormula f = (SpreadsheetFormula)content;
+ f.result = null;
+ }
+ }
+
+ @Override
+ public void accept(SpreadsheetVisitor v) {
+ v.visit(this);
+ }
+
+ @Override
+ public Optional<SpreadsheetElement> getParent() {
+ return Optional.of(line);
+ }
+
+ @Override
+ public List<SpreadsheetElement> 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;
+ }
+
+}
-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() {
-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
-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;
}
public Map getProperties() {
return Collections.emptyMap();
}
-
+
@Override
public int hashCode() {
final int prime = 31;
}
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;
-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<Child extends SpreadsheetElement<?, ?>, Parent extends SpreadsheetElement<?, ?>> extends SpreadsheetVisitable, Serializable {
Optional<Parent> getParent();
--- /dev/null
+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<String,Object> rangeCache;
+
+ public Map<String,Object> getRangeCache() {
+ if(rangeCache == null) rangeCache = new HashMap<String,Object>();
+ 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<String, SheetNode> getChildren() {
+ return Collections.singletonMap(LINES, lines);
+ }
+
+ @Override
+ public Map<String, SheetNode> 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<SpreadsheetElement> getParent() {
+ return Optional.of(book);
+ }
+
+ @Override
+ public List<SpreadsheetElement> 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
-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() {
return false;
return true;
}
-
+
@Override
public String toString() {
return getClass().getSimpleName() + " [" + expression +" => " + result != null ? result.toString() : "" + "]";
--- /dev/null
+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<SpreadsheetCell, SpreadsheetLines>, SheetNode {
+
+ private static final long serialVersionUID = -304574098117404663L;
+
+ final private SpreadsheetLines parent;
+ final public int row;
+ int id;
+
+ public ObjectArrayList<SpreadsheetCell> 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<String,SpreadsheetCell> result = new HashMap<>();
+ for(int i=0;i<cells.size();i++) {
+ SpreadsheetCell cell = cells.get(i);
+ if(SpreadsheetCell.EMPTY == cell) continue;
+ String name = "Row"+Spreadsheets.columnName(i) + rowName;
+ result.put(name, cell);
+ }
+ return result;
+ }
+
+ @Override
+ public Map getProperties() {
+ return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINE_TYPE_URI));
+ }
+
+ Object resolve(String[] parts, int index) {
+
+ if(index == parts.length) return this;
+
+ Range r = Spreadsheets.decodeCellAbsolute(parts[index]);
+ return cells.get(r.startColumn);
+
+ }
+
+ public void accept(SpreadsheetVisitor v) {
+ v.visit(this);
+ }
+
+ public String getPath() {
+ return ((SpreadsheetLines)parent).getPath() + "/" + getName();
+ }
+
+ @Override
+ public Optional<SpreadsheetLines> getParent() {
+ return Optional.of(parent);
+ }
+
+ @Override
+ public List<SpreadsheetCell> 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;
+ }
+
+}
--- /dev/null
+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<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
+
+ private static final long serialVersionUID = -3615335969248723486L;
+
+ private final int id;
+ private SpreadsheetEngine parent;
+ private String name;
+ public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
+ public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
+ 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<SpreadsheetEngine> getParent() {
+ return Optional.of(parent);
+ }
+
+ @Override
+ public Collection<SpreadsheetLine> 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;
+ }
+
+}
--- /dev/null
+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<SheetLineComponent> 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<SheetLineComponent> createComponentFactory() {
+ return new ComponentFactory<SheetLineComponent>() {
+
+ @Override
+ public SheetLineComponent create(String uid) {
+ return new SheetLineComponent(uid);
+ }
+
+ };
+ }
+
+}
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
import java.io.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() {
-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<SpreadsheetStyle, SpreadsheetStyle> {
-// 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
@Override
public void remove(SpreadsheetStyle child) {
-
+
}
@Override
public int hashCode() {
if (hashCode != 0)
return hashCode;
-
+
final int prime = 31;
int result = 1;
result = prime * result + align;
result = prime * result + ((foreground == null) ? 0 : foreground.hashCode());
result = prime * result + (locked ? 1231 : 1237);
result = prime * result + rowSpan;
-
+
return result;
}
return false;
return true;
}
-
+
public static SpreadsheetStyleBuilder newInstace() {
return new SpreadsheetStyleBuilder();
}
-
+
public static SpreadsheetStyle empty() {
return EMPTY;
}
-
+
public static class SpreadsheetStyleBuilder {
-
+
private String name;
private RGB.Integer foreground;
private RGB.Integer background;
private short formatIndex;
private SpreadsheetStyleBuilder() {}
-
+
public SpreadsheetStyleBuilder name(String name) {
this.name = name;
return this;
}
-
+
public SpreadsheetStyleBuilder foreground(RGB.Integer foreground) {
this.foreground = foreground;
return this;
}
-
+
public SpreadsheetStyleBuilder background(RGB.Integer background) {
this.background = background;
return this;
}
-
+
public SpreadsheetStyleBuilder border(Integer border) {
this.border = border == null ? 0 : border;
return this;
}
-
+
public SpreadsheetStyleBuilder align(Integer align) {
this.align = align == null ? 0 : align;
return this;
}
-
+
public SpreadsheetStyleBuilder font(Font font) {
this.font = font;
return this;
}
-
+
public SpreadsheetStyleBuilder locked(boolean locked) {
this.locked = locked;
return this;
}
-
+
public SpreadsheetStyleBuilder rowSpan(int rowSpan) {
this.rowSpan = rowSpan;
return this;
}
-
+
public SpreadsheetStyleBuilder font(int columnSpan) {
this.columnSpan = columnSpan;
return this;
}
-
+
public SpreadsheetStyle build() {
SpreadsheetStyle style = new SpreadsheetStyle(name, border, align, font, foreground, background, locked, rowSpan, columnSpan, formatString, formatIndex);
return style;
public void setSynchronizationId(int newId) {
this.synchronizationId = newId;
}
-
+
}
--- /dev/null
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collections;
+import java.util.Map;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetTypeNode implements SheetNode {
+
+ private static final long serialVersionUID = 8008959901150210428L;
+
+ public final String uri;
+
+ public SpreadsheetTypeNode(String uri) {
+ this.uri = uri;
+ }
+
+ @Override
+ public String getName() {
+ return "typeURI";
+ }
+
+ @Override
+ public Map getChildren() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map getProperties() {
+ return Collections.emptyMap();
+ }
+
+}
--- /dev/null
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class AndFormulaFunction implements CellFormulaFunction<Object> {
+
+ @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
--- /dev/null
+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<Object> {
+
+ @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
--- /dev/null
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public interface CellFormulaFunction<T> {
+
+ T evaluate(CellValueVisitor visitor, AstArgList args);
+
+}
--- /dev/null
+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<Object> {
+
+ 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<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ value = exp.rightValue(i);
+ acceptedValue = value.accept(this);
+ if("+".equals(op)) {
+ result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+ if(!(result instanceof Number)) {
+ FormulaError2 err = FormulaError2.forObject(result);
+ if(err!=null) return err.getString();
+
+ if(result instanceof String && !((String) result).isEmpty()){
+ Number num = Spreadsheets.asValidNumber(result);
+ if(num == null) {
+ return FormulaError2.VALUE.getString();
+ } else {
+ result = num;
+ }
+ }
+ else if(result instanceof Variant){
+ Object val = ((Variant)result).getValue();
+ if(val instanceof String && (val.toString().isEmpty())){
+ result = 0.0;
+ } else {
+ Number resNum = Spreadsheets.asDoubleWhereEmptyStringIsZero(val);
+ if(resNum==null) return FormulaError2.VALUE.getString();
+ else result = resNum;
+ }
+ } else {
+ result = 0.0;
+ }
+ }
+
+ FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+ if(err2!=null) return err2.getString();
+
+ other = Spreadsheets.asDoubleWhereEmptyStringIsZero(acceptedValue);
+ if(other==null)
+ return FormulaError2.handleErrorCall(acceptedValue);
+
+ result = ((Number)result).doubleValue() + ((Number)other).doubleValue();
+
+ } else if("-".equals(op)) {
+ result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+ if(!(result instanceof Number)) {
+ FormulaError2 err = FormulaError2.forObject(result);
+ if(err!=null) return err.getString();
+
+ if(result instanceof String && !((String) result).isEmpty()){
+ Number num = Spreadsheets.asValidNumber(result);
+ if(num == null) {
+ return FormulaError2.VALUE.getString();
+ } else {
+ result = num;
+ }
+ }
+ else if(result instanceof Variant){
+ Object val = ((Variant)result).getValue();
+ if(val instanceof String && (val.toString().isEmpty())){
+ result = 0.0;
+ } else {
+ Number resNum = Spreadsheets.asDoubleWhereEmptyStringIsZero(val);
+ if(resNum==null)
+ return FormulaError2.VALUE.getString();
+ else result = resNum;
+ }
+ } else {
+ result = 0.0;
+ }
+ }
+ FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+ if(err2!=null) return err2.getString();
+
+ other = Spreadsheets.asDoubleWhereEmptyStringIsZero(acceptedValue);
+ if(other==null)
+ return FormulaError2.handleErrorCall(acceptedValue);
+
+ result = ((Number)result).doubleValue() - ((Number)other).doubleValue();
+
+ } else if("&".equals(op)) {
+ result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+ FormulaError2 err = FormulaError2.forObject(result);
+ if(err!=null) return err.getString();
+ FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+ if(err2!=null) return err2.getString();
+
+ result = Spreadsheets.asString(result);
+ other = Spreadsheets.asString(acceptedValue);
+
+ result += (String)other;
+ }
+ }
+ return leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+ }
+
+ @Override
+ public Object visit(AstTerm exp) {
+ Number result = null;
+ for(int i=0;i<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ AstValue value = exp.rightValue(i);
+ Object leftValue = exp.left.accept(this);
+ Object rightValue = value.accept(this);
+ if("*".equals(op)) {
+ if(result == null) {
+ result = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftValue);
+ if(result == null)
+ return FormulaError2.handleErrorCall(leftValue);
+ }
+ Number other = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightValue);
+ if(other==null) return FormulaError2.handleErrorCall(rightValue);
+
+ result = new Double(result.doubleValue() * other.doubleValue());
+
+ } else if("/".equals(op)) {
+ if(result == null) {
+ result = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftValue);
+ if(result == null)
+ return FormulaError2.handleErrorCall(leftValue);
+ }
+ Number other = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightValue);
+ if(other==null) return FormulaError2.handleErrorCall(rightValue);
+ if(other.doubleValue()==0.0) return FormulaError2.DIV0.getString();
+
+ result = new Double(result.doubleValue() / other.doubleValue());
+ }
+ }
+ if(result == null) result = Spreadsheets.asNumber(exp.left.accept(this));
+ return result;
+ }
+
+ @Override
+ public Object visit(AstFactor exp) {
+ Object result = null;
+ for(int i=0;i<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ AstValue value = exp.rightValue(i);
+ if("^".equals(op)) {
+ if(result == null) {
+ Object leftValue = exp.left.accept(this);
+
+ FormulaError2 err = FormulaError2.forObject(leftValue);
+ if(err!=null) return err.getString();
+
+ if(leftValue instanceof Variant){
+ Object leftTemp = ((Variant)leftValue).getValue();
+ Double leftV = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftTemp);
+ if(leftV==null) leftValue = leftTemp.toString();
+ else leftValue = leftV;
+ }
+
+ if(leftValue instanceof String){
+ if((leftValue.toString()).isEmpty())
+ result = 0;
+ else
+ return FormulaError2.VALUE.getString();
+ }
+ else if(leftValue instanceof SpreadsheetMatrix)
+ result = leftValue;
+ else
+ result = Spreadsheets.asNumber(leftValue);
+ }
+ Object otherValue = value.accept(this);
+
+ FormulaError2 err2 = FormulaError2.forObject(otherValue);
+ if(err2!=null) return err2.getString();
+
+ if(otherValue instanceof Variant){
+ Object otherTemp = ((Variant)otherValue).getValue();
+ Double otherV = Spreadsheets.asDoubleWhereEmptyStringIsZero(otherTemp);
+ if(otherV==null) otherValue = otherTemp.toString();
+ else otherValue = otherV;
+ }
+
+ if(otherValue instanceof String){
+ if((otherValue.toString()).isEmpty())
+ otherValue = 0;
+ else
+ return FormulaError2.VALUE.getString();
+ }
+
+ if(result instanceof SpreadsheetMatrix) {
+ result = ((SpreadsheetMatrix)result).pow(otherValue);
+ } else {
+ if(otherValue instanceof SpreadsheetMatrix) {
+ throw new IllegalStateException();
+ } else {
+ Double base = ((Number)result).doubleValue();
+ Double exponent = Spreadsheets.asNumber(otherValue);
+ if(exponent==0 && base==0)
+ return FormulaError2.NUM.getString();
+ if(exponent<0 && base==0)
+ return FormulaError2.DIV0.getString();
+ result = Math.pow(base, exponent);
+ if(result instanceof Double && Double.isInfinite((Double)result)){
+ return FormulaError2.NUM.getString();
+ }
+ }
+ }
+ }
+ }
+ if(result == null) result = Spreadsheets.asNumber(exp.left.accept(this));
+ return result;
+ }
+
+ @Override
+ public Object visit(AstIdentifier id) {
+ return FormulaError2.NAME.getString();
+ //throw new IllegalStateException();
+ }
+
+ @Override
+ public Object visit(AstArray array) {
+ SpreadsheetMatrix m = new SpreadsheetMatrix(array.values.size(), 1);
+ for(int i=0;i<array.values.size();i++) {
+ m.values[i] = array.values.get(i).accept(this);
+ }
+ return m;
+ }
+
+ @Override
+ public Object visit(AstNothing array) {
+ return AstNothing.NOTHING;
+ }
+
+ @Override
+ public Object visit(AstArrayFormulaReference ref) {
+
+ Range thisRange = Spreadsheets.decodeRange(thisCell.getName());
+ Range arrayRange = Spreadsheets.decodeRange(ref.range);
+ int x = thisRange.startColumn - arrayRange.startColumn;
+ int y = thisRange.startRow - arrayRange.startRow;
+
+ SpreadsheetMatrix m = (SpreadsheetMatrix)ref.value.accept(this);
+ return m.get(y, x);
+
+ }
+
+}
--- /dev/null
+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.AstRange;
+
+public class CountifFormulaFunction implements CellFormulaFunction<Integer> {
+
+ @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);
+ }
+}
--- /dev/null
+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<String, FormulaError2> smap = new HashMap<String, FormulaError2>();
+
+ 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
--- /dev/null
+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<Object> {
+
+ @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)));
+ }
+
+}
--- /dev/null
+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<Object> {
+
+ @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();
+ }
+
+}
-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<Object> {
-
- @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();
-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<Object> {
@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();
}
}
}
-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<Object>{
- @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;
}
-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<SpreadsheetMatrix> {
double x[][] = new double[ysm.values.length][xsm.getWidth()];
for (int i = 0; i < ysm.values.length; i++) {
- y[i] = SpreadsheetGraphUtils.asNumber(ysm.values[i]);
+ y[i] = Spreadsheets.asNumber(ysm.values[i]);
for (int j = 0; j < xsm.getWidth(); j++) {
- x[i][j] = SpreadsheetGraphUtils.asNumber(xsm.get(i, j));
+ x[i][j] = Spreadsheets.asNumber(xsm.get(i, j));
}
}
result.set(2,2, FormulaError2.NA.getString());
result.set(3,2, FormulaError2.NA.getString());
result.set(4,2, FormulaError2.NA.getString());
-
+
return result;
}
--- /dev/null
+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 MatchFormulaFunction implements CellFormulaFunction<Object>{
+
+ @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 && currValue<previousValue))
+ indexWhereCorrectOrderStartsAt = i;
+ else
+ break;
+ }
+ previousValue = currValue;
+ }
+ }
+ }
+ }
+ int begin = indexWhereCorrectOrderStartsAt;
+
+ for(int i = begin; 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) previousValue = currValue;
+ if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue)){
+ 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;
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+}
--- /dev/null
+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<Object> {
+
+ @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;
+ }
+
+}
-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<Double> {
--- /dev/null
+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<String> {
+
+ @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<astArgList.values.size();i++) {
+ if(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<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ b.append(op);
+ AstValue value = exp.rightValue(i);
+ b.append(value.accept(this));
+ }
+
+ return b.toString();
+
+ }
+
+ @Override
+ public String visit(AstTerm exp) {
+
+ StringBuilder b = new StringBuilder();
+
+ b.append(exp.left.accept(this));
+
+ for(int i=0;i<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ b.append(op);
+ AstValue value = exp.rightValue(i);
+ b.append(value.accept(this));
+ }
+
+ return b.toString();
+
+ }
+
+ @Override
+ public String visit(AstFactor exp) {
+
+ StringBuilder b = new StringBuilder();
+
+ b.append(exp.left.accept(this));
+
+ for(int i=0;i<exp.rightCount();i++) {
+ String op = exp.rightOp(i);
+ b.append(op);
+ AstValue value = exp.rightValue(i);
+ b.append(value.accept(this));
+ }
+
+ return b.toString();
+
+ }
+
+ @Override
+ public String visit(AstIdentifier id) {
+ return "AstIdentifier";
+ }
+
+ @Override
+ public String visit(AstArray array) {
+ StringBuilder b = new StringBuilder();
+ for(int i=0;i<array.values.size();i++) {
+ if(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) + "}";
+ }
+
+}
-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<Object> {
@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);
-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<Object> {
@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);
-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 {
-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<Object> {
@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();
-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<Object> {
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;
-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<Object> {
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;
}
}
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) {
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;
}
-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<Long> {
--- /dev/null
+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<Object> {
+
+ @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();
+ }
+
+}
/* 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.
/* 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;
/* Generated By:JavaCC: Do not edit this line. SheetFormulaParserConstants.java */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
/**
/* 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;
* 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 {
/* 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
/* 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.
/* 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
* 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 {
* 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;
* 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 {
* 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;
* 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 {
* 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),
* 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 {
* 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 {
* 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 {
* 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;
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
import java.util.ArrayList;
* 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;
* 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;
* 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 {
* 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 {
* 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 {
* 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 {
* 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;
* 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<T> {
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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<SpreadsheetCell> changes = new ArrayList<>();
+
+ for(int i=0;i<bean.cells.length;i++) {
+
+ SpreadsheetCell currentCell;
+ if (line.cells.size() > 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> T getConcrete() {
+ return (T)this;
+ }
+
+}
\ No newline at end of file
-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[];
+
}
-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;
}
public LineContentBeanCell(Variant content, int styleId) {
-// System.err.println("LineContentBeanCell.construct: " + content + " " + styleId);
this.content = content;
this.styleID = styleId;
}
--- /dev/null
+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<SheetLineComponent> {
+
+ public LineNodeUpdater(String id) {
+
+ super(id);
+
+ isComposite = true;
+
+ addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
+
+ @Override
+ public String getPropertyName() {
+ return "keys";
+ }
+
+ @Override
+ public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
+ Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
+
+ LinesCommandBuilder builder = context.<LinesCommandBuilder>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
--- /dev/null
+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<SheetLineComponent> {
+
+ public LineUpdater(String id) {
+ super(id);
+ addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
+ @Override
+ public String getPropertyName() {
+ return "content";
+ }
+ @Override
+ public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
+ Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
+// System.err.println("LineUpdater.apply " + value);
+ LineCommandBuilder builder = context.<LineCommandBuilder>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
--- /dev/null
+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> T getConcrete() {
+ return (T)this;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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> T getConcrete() {
+ return (T)this;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<SheetLineComponent> {
+
+ 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
-package org.simantics.spreadsheet.graph.synchronization;
+package org.simantics.spreadsheet.synchronization;
import java.util.Collection;
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;
public String getPropertyName() {
return "foreground";
}
-
+
@Override
public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating, Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
StyleCommandBuilder builder = context.getConcreteCommand();
builder.foreground = color;
}
}
-
+
private static class BackgroundUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
builder.background = color;
}
}
-
+
private static class FontUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
builder.align = align;
}
}
-
+
private static class FormatStringUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
builder.border = border;
}
}
-
+
private static class LockedUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
builder.locked = locked;
}
}
-
+
private static class ColumnSpanUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
builder.columnSpan = columnSpan;
}
}
-
+
private static class RowSpanUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
@Override
public String getPropertyName() {
}
}
-
+
public StyleUpdater(String moduleType) {
super(moduleType);
-
+
addPropertyUpdateRule(new ForegroundUpdateRule());
addPropertyUpdateRule(new BackgroundUpdateRule());
addPropertyUpdateRule(new FontUpdateRule());
public CommandBuilder createUpdateCommandBuilder(String name) {
return new StyleCommandBuilder(name, true);
}
-
+
private static class StyleCommandBuilder implements CommandBuilder {
protected int rowSpan;
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();
.columnSpan(columnSpan).formatIndex((short) formatIndex).formatString(formatString).build();
if (book.getStyle(style.getStyleId()) == null)
book.addStyle(style);
-
+
}
@SuppressWarnings("unchecked")
public <T> 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();
}
-
+
}
-
+
}