X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.spreadsheet.graph%2Fsrc%2Forg%2Fsimantics%2Fspreadsheet%2Fgraph%2FCellValueVisitor.java;h=8150b4dbadba87104e927a965c1e963970ea2fd0;hp=022326248c39bacdf395e484f06de8220410893a;hb=9a37dabc6c0212ed3e14499c88df3208cd06f9b0;hpb=861a3da972d67bf5f0d246129c63f611922e03f0 diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java index 022326248..8150b4dba 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java @@ -1,478 +1,478 @@ -package org.simantics.spreadsheet.graph; - -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.spreadsheet.Range; -import org.simantics.spreadsheet.graph.formula.FormulaError2; -import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment; -import org.simantics.spreadsheet.graph.parser.ast.AstApply; -import org.simantics.spreadsheet.graph.parser.ast.AstArgList; -import org.simantics.spreadsheet.graph.parser.ast.AstArithmeticExpression; -import org.simantics.spreadsheet.graph.parser.ast.AstArray; -import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference; -import org.simantics.spreadsheet.graph.parser.ast.AstBoolean; -import org.simantics.spreadsheet.graph.parser.ast.AstDouble; -import org.simantics.spreadsheet.graph.parser.ast.AstFactor; -import org.simantics.spreadsheet.graph.parser.ast.AstIdentifier; -import org.simantics.spreadsheet.graph.parser.ast.AstInteger; -import org.simantics.spreadsheet.graph.parser.ast.AstNothing; -import org.simantics.spreadsheet.graph.parser.ast.AstNull; -import org.simantics.spreadsheet.graph.parser.ast.AstRange; -import org.simantics.spreadsheet.graph.parser.ast.AstRelation; -import org.simantics.spreadsheet.graph.parser.ast.AstString; -import org.simantics.spreadsheet.graph.parser.ast.AstTerm; -import org.simantics.spreadsheet.graph.parser.ast.AstValue; -import org.simantics.spreadsheet.graph.parser.ast.AstValueVisitor; -import org.simantics.spreadsheet.util.SpreadsheetUtils; - -import it.unimi.dsi.fastutil.longs.AbstractLongList; -import it.unimi.dsi.fastutil.longs.LongArrayList; - -public class CellValueVisitor implements AstValueVisitor { - - final public SpreadsheetBook book; - final private SpreadsheetEvaluationEnvironment env; - final private SpreadsheetCell thisCell; - final private LongArrayList references = new LongArrayList(); - - public CellValueVisitor(SpreadsheetEvaluationEnvironment env, SpreadsheetCell thisCell) { - this.book = env.getBook(); - this.env = env; - this.thisCell = thisCell; - } - - public void addReference(long ref) { - references.add(ref); - } - - public AbstractLongList getReferences() { - return references; - } - - @Override - public Object visit(AstBoolean astBoolean) { - return astBoolean.value; - } - - @Override - public Object visit(AstDouble astFloat) { - return astFloat.value; - } - - @Override - public Object visit(AstInteger astInteger) { - return astInteger.value; - } - - @Override - public Object visit(AstNull astNull) { - throw new IllegalStateException(); - } - - @Override - public Object visit(AstString astString) { - return astString.value; - } - - @Override - public Object visit(AstRange astRange) { - - if(astRange.isRef()){ - return FormulaError2.REF.getString(); - } - - if(astRange.isCell()) { - String ref = astRange.first; - Range r = SpreadsheetUtils.decodeCell(ref, 0, 0); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetCell cell = thisCell.getBook().get(sheetName, r.startRow, r.startColumn); - if(cell == null) { - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - SpreadsheetLine line = eng.getLine(r.startRow); - - if (line == null) { - line = new SpreadsheetLine(eng.lines, r.startRow); - eng.lines.lines.put(-r.startRow, line); - } - cell = SpreadsheetCell.empty(line, r.startColumn); - } - return cell.evaluate(env, this); - - } else { - - Object cached = thisCell.getEngine().getCachedRange(astRange); - if(cached != null) { - - Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - Range r = eng.actualRange(r_); - for(int row=0; row < r.height();row++) { - SpreadsheetLine line = eng.getLine(r.startRow + row); - if(line != null) { - for(int column=0; column < r.width();column++) { - int col = r.startColumn + column; - if(line.cells.size() > col) { - SpreadsheetCell cell = line.cells.get(r.startColumn + column); - //Add references, but do not evaluate if there exists a cached range. - addReference(cell.makeReferenceKey()); - } - } - } - } - return cached; - } - - Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second); - String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName(); - SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName); - // Full ranges are resolved here - Range r = eng.actualRange(r_); - SpreadsheetMatrix result = new SpreadsheetMatrix(r.width(), r.height()); - for(int row=0; row < r.height();row++) { - SpreadsheetLine line = eng.getLine(r.startRow + row); - if(line != null) { - for(int column=0; column < r.width();column++) { - int col = r.startColumn + column; - if(line.cells.size() > col) { - SpreadsheetCell cell = line.cells.get(r.startColumn + column); - result.values[r.width()*row + column] = cell.evaluate(env, this); - } - } - } - } - thisCell.getEngine().cacheRange(astRange, result); - return result; - } - } - - @Override - public Object visit(AstArgList astArgList) { - throw new IllegalStateException(); - } - - @Override - public Object visit(AstApply astApply) { - CellFormulaFunction fn = env.getFunction(astApply.value); - if(fn != null) { - return fn.evaluate(this, astApply.args); - } else { - return FormulaError2.NAME.getString(); - } - } - - @Override - public Object visit(AstRelation astRelation) { - - Object leftResult = astRelation.left.accept(this); - Object rightResult = astRelation.right.accept(this); - - FormulaError2 err = FormulaError2.forObject(leftResult); - if(err!=null) return err.getString(); - FormulaError2 err2 = FormulaError2.forObject(rightResult); - if(err2!=null) return err2.getString(); - - if(leftResult instanceof Variant){ - Object leftTemp = ((Variant)leftResult).getValue(); - Double leftVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftTemp); - if(leftVal==null) leftResult = leftTemp.toString(); - else leftResult = leftVal; - } - if(rightResult instanceof Variant){ - Object rightTemp = ((Variant)rightResult).getValue(); - Double rightVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightTemp); - if(rightVal==null) rightResult = rightTemp.toString(); - else rightResult = rightVal; - } - - if ((leftResult instanceof String) || (rightResult instanceof String)) { - String leftString = (leftResult.toString()).toLowerCase(); - String rightString = (rightResult.toString()).toLowerCase(); - if("<".equals(astRelation.op.trim())) return leftString.compareTo(rightString) < 0; - else if(">".equals(astRelation.op.trim())) return leftString.compareTo(rightString) > 0; - // empty string should equal zero (TODO: this is a hack, the proper fix should be somewhere earlier so other cases would work as well) - else if("=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) == 0 || emptyAndZero(leftString, rightString) || emptyAndZero(rightString, leftString); - 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.asNumber(leftResult); - Number rightNumber = SpreadsheetGraphUtils.asNumber(rightResult); - 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(); - } - } - - private static boolean emptyAndZero(String a, String b) { - try { - return a.isEmpty() && (Double.parseDouble(b) == 0); - } - catch (NumberFormatException e) { - return false; - } - } - - 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 { + + 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