1 package org.simantics.spreadsheet.graph;
\r
3 import java.util.Collections;
\r
4 import java.util.HashMap;
\r
5 import java.util.List;
\r
6 import java.util.Map;
\r
7 import java.util.Optional;
\r
9 import org.simantics.spreadsheet.graph.formula.FormulaError2;
\r
10 import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
\r
11 import org.simantics.spreadsheet.graph.parser.ast.AstValue;
\r
12 import org.simantics.spreadsheet.resource.SpreadsheetResource;
\r
13 import org.simantics.spreadsheet.util.SpreadsheetUtils;
\r
15 public class SpreadsheetCell implements SpreadsheetElement, SheetNode {
\r
17 private static final long serialVersionUID = 6616793596542239339L;
\r
19 public static SpreadsheetCell EMPTY;
\r
22 EMPTY = new SpreadsheetCell(null, -1);
\r
23 EMPTY.setContent("");
\r
24 EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId());
\r
27 private boolean inProgress = false;
\r
28 private int iterations = 0;
\r
30 final private SpreadsheetLine line;
\r
31 final private int column;
\r
35 public SpreadsheetCell(SpreadsheetLine line, int column) {
\r
37 this.column = column;
\r
40 public boolean hasExpression() {
\r
41 return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant;
\r
44 public void setContent(Object newContent) {
\r
45 // if(newContent != null) {
\r
46 // if (!(newContent instanceof Serializable)) {
\r
47 // throw new AssertionError("content not instanceof Serializable but it is " + newContent.getClass().getSimpleName());
\r
51 System.out.println("SpreadsheetCell.setContent "+ this + " " + newContent);
\r
52 this.content = newContent;
\r
56 public String getName() {
\r
57 return SpreadsheetUtils.cellName(line.row, column);
\r
61 public Map<?, ?> getChildren() {
\r
62 return Collections.emptyMap();
\r
65 private static String[] keys = { "typeURI", "content" };
\r
68 public Map<String, SheetNode> getProperties() {
\r
69 Map<String, SheetNode> properties = new HashMap<>();
\r
72 System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style);
\r
74 properties.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell));
\r
75 properties.put("content", new SpreadsheetCellContent(this));
\r
76 properties.put("style", new SpreadsheetCellStyle(this));
\r
77 properties.put("editable", new SpreadsheetCellEditable(this));
\r
81 public SpreadsheetBook getBook() {
\r
82 return line.getEngine().getBook();
\r
85 public SpreadsheetEngine getEngine() {
\r
86 return line.getEngine();
\r
89 public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {
\r
90 return evaluate(env, null);
\r
93 public <T> T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) {
\r
94 // System.err.println(getEngine().getName() + ":" + getName() + ": evaluate");
\r
96 caller.addReference(makeReferenceKey());
\r
97 if(content instanceof SpreadsheetFormula) {
\r
98 SpreadsheetFormula f = (SpreadsheetFormula)content;
\r
99 if(f.result == null) {
\r
100 CellValueVisitor visitor = new CellValueVisitor(env, this);
\r
101 AstValue value = ((SpreadsheetFormula)content).value;
\r
102 if(this.inProgress == true) this.iterations++;
\r
104 if(!env.getBook().isIterationEnabled()){
\r
105 if(this.inProgress == false){
\r
106 this.inProgress = true;
\r
107 f.result = value.accept(visitor);
\r
109 else f.result = FormulaError2.CIRCULAR_REF.getString();
\r
111 else if(this.iterations<env.iterationLimit){
\r
112 this.inProgress = true;
\r
113 f.result = value.accept(visitor);
\r
120 env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
\r
122 this.inProgress = false;
\r
123 this.iterations = 0;
\r
124 return (T)f.result;
\r
125 } else if (content instanceof SpreadsheetSCLConstant) {
\r
126 SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
\r
127 return (T) sclConstant.content;
\r
129 this.inProgress = false;
\r
134 public long makeReferenceKey() {
\r
135 SpreadsheetBook book = getBook();
\r
136 SpreadsheetEngine engine = getEngine();
\r
137 long engineIndex = book.getEngineIndex(engine);
\r
138 long row = line.row;
\r
140 return (engineIndex << 40) + (row << 20) + col;
\r
143 public void invalidate() {
\r
144 getEngine().rangeCache = null;
\r
145 if(content instanceof SpreadsheetFormula) {
\r
146 SpreadsheetFormula f = (SpreadsheetFormula)content;
\r
152 public void accept(SpreadsheetVisitor v) {
\r
157 public Optional<SpreadsheetElement> getParent() {
\r
158 return Optional.of(line);
\r
162 public List<SpreadsheetElement> getSpreadsheetChildren() {
\r
163 return Collections.emptyList();
\r
167 public void remove(SpreadsheetElement child) {
\r
168 // TODO Auto-generated method stub
\r
173 public int hashCode() {
\r
174 final int prime = 31;
\r
176 result = prime * result + column;
\r
177 result = prime * result + ((line == null) ? 0 : line.hashCode());
\r
182 public boolean equals(Object obj) {
\r
187 if (getClass() != obj.getClass())
\r
189 SpreadsheetCell other = (SpreadsheetCell) obj;
\r
190 if (column != other.column)
\r
192 if (line == null) {
\r
193 if (other.line != null)
\r
195 } else if (!line.equals(other.line))
\r
200 public void setStyle(int styleId) {
\r
201 this.style = styleId;
\r
204 public int getStyle() {
\r
208 public Object getContent() {
\r
212 public static SpreadsheetCell empty(SpreadsheetLine line, int column) {
\r
213 SpreadsheetCell cell = new SpreadsheetCell(line, column);
\r
214 cell.setContent("");
\r
215 cell.setStyle(SpreadsheetStyle.empty().getStyleId());
\r