--- /dev/null
+package org.simantics.spreadsheet.graph;\r
+\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Optional;\r
+\r
+import org.simantics.spreadsheet.graph.formula.FormulaError2;\r
+import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;\r
+import org.simantics.spreadsheet.graph.parser.ast.AstValue;\r
+import org.simantics.spreadsheet.resource.SpreadsheetResource;\r
+import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
+\r
+public class SpreadsheetCell implements SpreadsheetElement, SheetNode {\r
+\r
+ private static final long serialVersionUID = 6616793596542239339L;\r
+\r
+ public static SpreadsheetCell EMPTY;\r
+ \r
+ static {\r
+ EMPTY = new SpreadsheetCell(null, -1);\r
+ EMPTY.setContent("");\r
+ EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId());\r
+ }\r
+ \r
+ private boolean inProgress = false;\r
+ private int iterations = 0;\r
+ \r
+ final private SpreadsheetLine line;\r
+ final private int column;\r
+ int style;\r
+ Object content;\r
+ \r
+ public SpreadsheetCell(SpreadsheetLine line, int column) {\r
+ this.line = line;\r
+ this.column = column;\r
+ }\r
+\r
+ public boolean hasExpression() {\r
+ return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; \r
+ }\r
+ \r
+ public void setContent(Object newContent) {\r
+// if(newContent != null) {\r
+// if (!(newContent instanceof Serializable)) {\r
+// throw new AssertionError("content not instanceof Serializable but it is " + newContent.getClass().getSimpleName());\r
+// }\r
+// }\r
+ if (GraphUI.DEBUG)\r
+ System.out.println("SpreadsheetCell.setContent "+ this + " " + newContent);\r
+ this.content = newContent;\r
+ }\r
+\r
+ @Override\r
+ public String getName() {\r
+ return SpreadsheetUtils.cellName(line.row, column);\r
+ }\r
+\r
+ @Override\r
+ public Map<?, ?> getChildren() {\r
+ return Collections.emptyMap();\r
+ }\r
+ \r
+ private static String[] keys = { "typeURI", "content" };\r
+ \r
+ @Override\r
+ public Map<String, SheetNode> getProperties() {\r
+ Map<String, SheetNode> properties = new HashMap<>();\r
+ \r
+ if (GraphUI.DEBUG)\r
+ System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style);\r
+ \r
+ properties.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell));\r
+ properties.put("content", new SpreadsheetCellContent(this));\r
+ properties.put("style", new SpreadsheetCellStyle(this));\r
+ properties.put("editable", new SpreadsheetCellEditable(this));\r
+ return properties;\r
+ }\r
+ \r
+ public SpreadsheetBook getBook() {\r
+ return line.getEngine().getBook();\r
+ }\r
+\r
+ public SpreadsheetEngine getEngine() {\r
+ return line.getEngine();\r
+ }\r
+\r
+ public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {\r
+ return evaluate(env, null);\r
+ }\r
+\r
+ public <T> T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) {\r
+// System.err.println(getEngine().getName() + ":" + getName() + ": evaluate");\r
+ if(caller != null)\r
+ caller.addReference(makeReferenceKey());\r
+ if(content instanceof SpreadsheetFormula) {\r
+ SpreadsheetFormula f = (SpreadsheetFormula)content;\r
+ if(f.result == null) {\r
+ CellValueVisitor visitor = new CellValueVisitor(env, this);\r
+ AstValue value = ((SpreadsheetFormula)content).value;\r
+ if(this.inProgress == true) this.iterations++;\r
+ \r
+ if(env.iterationEnabled == false){\r
+ if(this.inProgress == false){\r
+ this.inProgress = true;\r
+ f.result = value.accept(visitor);\r
+ }\r
+ else f.result = FormulaError2.CIRCULAR_REF.getString();\r
+ }\r
+ else if(iterations<env.iterationLimit){\r
+ this.inProgress = true;\r
+ f.result = value.accept(visitor);\r
+ }\r
+ else f.result = 0.0;\r
+ \r
+ env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());\r
+ }\r
+ this.inProgress = false;\r
+ return (T)f.result;\r
+ } else if (content instanceof SpreadsheetSCLConstant) {\r
+ SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;\r
+ return (T) sclConstant.content;\r
+ } else {\r
+ this.inProgress = false;\r
+ return (T)content;\r
+ }\r
+ }\r
+ \r
+ public long makeReferenceKey() {\r
+ SpreadsheetBook book = getBook();\r
+ SpreadsheetEngine engine = getEngine();\r
+ long engineIndex = book.getEngineIndex(engine);\r
+ long row = line.row;\r
+ long col = column;\r
+ return (engineIndex << 40) + (row << 20) + col; \r
+ }\r
+ \r
+ public void invalidate() {\r
+ getEngine().rangeCache = null;\r
+ if(content instanceof SpreadsheetFormula) {\r
+ SpreadsheetFormula f = (SpreadsheetFormula)content;\r
+ f.result = null;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void accept(SpreadsheetVisitor v) {\r
+ v.visit(this);\r
+ }\r
+\r
+ @Override\r
+ public Optional<SpreadsheetElement> getParent() {\r
+ return Optional.of(line);\r
+ }\r
+\r
+ @Override\r
+ public List<SpreadsheetElement> getSpreadsheetChildren() {\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ @Override\r
+ public void remove(SpreadsheetElement child) {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + column;\r
+ result = prime * result + ((line == null) ? 0 : line.hashCode());\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ SpreadsheetCell other = (SpreadsheetCell) obj;\r
+ if (column != other.column)\r
+ return false;\r
+ if (line == null) {\r
+ if (other.line != null)\r
+ return false;\r
+ } else if (!line.equals(other.line))\r
+ return false;\r
+ return true;\r
+ }\r
+\r
+ public void setStyle(int styleId) {\r
+ this.style = styleId;\r
+ }\r
+\r
+ public int getStyle() {\r
+ return style;\r
+ }\r
+\r
+ public Object getContent() {\r
+ return content;\r
+ }\r
+ \r
+ public static SpreadsheetCell empty(SpreadsheetLine line, int column) {\r
+ SpreadsheetCell cell = new SpreadsheetCell(line, column);\r
+ cell.setContent("");\r
+ cell.setStyle(SpreadsheetStyle.empty().getStyleId());\r
+ return cell;\r
+ }\r
+\r
+}\r