]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java
SCL API for direct access to SpreadsheetBooks
[simantics/platform.git] / bundles / org.simantics.spreadsheet / src / org / simantics / spreadsheet / solver / SpreadsheetLines.java
1 package org.simantics.spreadsheet.solver;
2
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.Map;
6 import java.util.Optional;
7 import java.util.function.Consumer;
8
9 import org.simantics.spreadsheet.SpreadsheetVisitor;
10 import org.simantics.spreadsheet.Spreadsheets;
11
12 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
13
14 @SuppressWarnings("rawtypes")
15 public class SpreadsheetLines implements SpreadsheetElement<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
16
17     private static final long serialVersionUID = -3615335969248723486L;
18
19     private final int id;
20     private SpreadsheetEngine parent;
21     private String name;
22     public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
23     public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
24     public int[] keys;
25
26     public SpreadsheetLines(SpreadsheetEngine parent, String name) {
27         this.parent = parent;
28         this.name = name;
29         id = getEngine().getBook().getNewId(this);
30     }
31
32     public SpreadsheetEngine getEngine() {
33         return parent;
34     }
35
36     public int getId() {
37         return id;
38     }
39
40     @Override
41     public String getName() {
42         return name;
43     }
44
45     @SuppressWarnings({ "unchecked" })
46     @Override
47     public Map getChildren() {
48         Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap();
49         result.putAll(nodes);
50         result.putAll(lines);
51         return result;
52     }
53
54     @Override
55     public Map getProperties() {
56         return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINES_TYPE_URI));
57     } 
58
59     Object resolve(String[] parts, int index) {
60
61         String part = parts[index];
62         if(part.charAt(0) == 'R') {
63             int indx = Integer.parseInt(part.substring(3));
64             SpreadsheetLine line = lines.get(-indx);
65             if(line != null) {
66                 if(index == parts.length-1) return line;
67                 else return line.resolve(parts, index+1);
68             }
69         } else {
70             int indx = Integer.parseInt(part);
71             SpreadsheetLines node = nodes.get(indx);
72             if(node != null) {
73                 if(index == parts.length-1) return node;
74                 else return node.resolve(parts, index+1);
75             }
76         }
77
78         return null;
79
80     }
81
82     public Object ensureSubprocess(String[] path, int index) {
83
84         String name = path[index];
85
86         int i = Integer.parseInt(name);
87         SpreadsheetLines line = nodes.get(i);
88         if(line == null) {
89             line = new SpreadsheetLines(parent, "" + i);
90             nodes.put(i, line);
91         }
92
93         if(index == path.length - 1) {
94             return line;
95         } else {
96             return line.ensureSubprocess(path, index+1);
97         }
98
99     }
100
101     public void setKeys(int[] keys) {
102         this.keys = keys;
103     }
104
105     @Override
106     public void accept(SpreadsheetVisitor v) {
107         v.visit(this);
108     }
109
110     public String getPath() {
111         return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName();
112     }
113
114     private int getKey(int index) {
115         return keys[2*index+1];
116     }
117
118     private int getChild(int index) {
119         return keys[2*index];
120     }
121
122     /*
123      *  [(child,key),...,key)
124      * 
125      */
126     public SpreadsheetLine getLine(int k) {
127
128         int i=1;
129         int n = (keys.length - 1) / 2;
130
131         while(i <= n && k > getKey(i-1)) i++;
132
133         if(i <= n && k == getKey(i-1)) {
134             return lines.get(-k);
135         }
136
137         int nodeName = getChild(i-1);
138         SpreadsheetLines node = nodes.get(nodeName);
139         if(node == null) return null;
140         return node.getLine(k);
141
142     }
143
144     public String getLinesPath() {
145         return getName();
146     }
147     
148     public void forLines(Consumer<SpreadsheetLine> consumer, int min, int max) {
149
150         int i=1;
151         int n = (keys.length - 1) / 2;
152
153         // Smaller keys
154         while(i <= n && min > getKey(i-1)) i++;
155         
156         while(i <= n && max > getKey(i-1)) {
157
158             int nodeName = getChild(i-1);
159             
160             SpreadsheetLines node = nodes.get(nodeName);
161             if(node == null) {
162                 consumer.accept(lines.get(-getKey(i-1)));
163             } else {
164                 node.forLines(consumer, min, max);
165             }
166             
167             i++;
168             
169         }
170         
171     }
172
173     public int getMaxRow() {
174         // if keys == null then this is the root of BTree which has only one child 
175         if (keys == null) {
176             int maxRow = 0;
177             for (SpreadsheetLines node : nodes.values()) {
178                 int row = node.getMaxRow();
179                 if (row > maxRow)
180                     maxRow = row;
181             }
182             return maxRow;
183         }
184         int largestChild = keys[keys.length-1]; 
185         if(largestChild > 0) {
186             SpreadsheetLines child = nodes.get(largestChild);
187             return child.getMaxRow();
188         } else {
189             return keys[keys.length-2];
190         }
191     }
192
193     @Override
194     public Optional<SpreadsheetEngine> getParent() {
195         return Optional.of(parent);
196     }
197
198     @Override
199     public Collection<SpreadsheetLine> getSpreadsheetChildren() {
200         return lines.values();
201     }
202
203     @Override
204     public void remove(SpreadsheetLine child) {
205         lines.remove(-child.row);
206     }
207
208     @Override
209     public int hashCode() {
210         final int prime = 31;
211         int result = 1;
212         result = prime * result + ((name == null) ? 0 : name.hashCode());
213         result = prime * result + ((parent == null) ? 0 : parent.hashCode());
214         return result;
215     }
216
217     @Override
218     public boolean equals(Object obj) {
219         if (this == obj)
220             return true;
221         if (obj == null)
222             return false;
223         if (getClass() != obj.getClass())
224             return false;
225         SpreadsheetLines other = (SpreadsheetLines) obj;
226         if (name == null) {
227             if (other.name != null)
228                 return false;
229         } else if (!name.equals(other.name))
230             return false;
231         if (parent == null) {
232             if (other.parent != null)
233                 return false;
234         } else if (!parent.equals(other.parent))
235             return false;
236         return true;
237     }
238
239 }