1 package org.simantics.spreadsheet.solver;
3 import java.util.Collection;
4 import java.util.Collections;
6 import java.util.Optional;
7 import java.util.function.Consumer;
9 import org.simantics.spreadsheet.SpreadsheetVisitor;
10 import org.simantics.spreadsheet.Spreadsheets;
12 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
14 @SuppressWarnings("rawtypes")
15 public class SpreadsheetLines implements SpreadsheetElement<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
17 private static final long serialVersionUID = -3615335969248723486L;
20 private SpreadsheetEngine parent;
22 public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
23 public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
26 public SpreadsheetLines(SpreadsheetEngine parent, String name) {
29 id = getEngine().getBook().getNewId(this);
32 public SpreadsheetEngine getEngine() {
41 public String getName() {
45 @SuppressWarnings({ "unchecked" })
47 public Map getChildren() {
48 Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap();
55 public Map getProperties() {
56 return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINES_TYPE_URI));
59 Object resolve(String[] parts, int index) {
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);
66 if(index == parts.length-1) return line;
67 else return line.resolve(parts, index+1);
70 int indx = Integer.parseInt(part);
71 SpreadsheetLines node = nodes.get(indx);
73 if(index == parts.length-1) return node;
74 else return node.resolve(parts, index+1);
82 public Object ensureSubprocess(String[] path, int index) {
84 String name = path[index];
86 int i = Integer.parseInt(name);
87 SpreadsheetLines line = nodes.get(i);
89 line = new SpreadsheetLines(parent, "" + i);
93 if(index == path.length - 1) {
96 return line.ensureSubprocess(path, index+1);
101 public void setKeys(int[] keys) {
106 public void accept(SpreadsheetVisitor v) {
110 public String getPath() {
111 return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName();
114 private int getKey(int index) {
115 return keys[2*index+1];
118 private int getChild(int index) {
119 return keys[2*index];
123 * [(child,key),...,key)
126 public SpreadsheetLine getLine(int k) {
129 int n = (keys.length - 1) / 2;
131 while(i <= n && k > getKey(i-1)) i++;
133 if(i <= n && k == getKey(i-1)) {
134 return lines.get(-k);
137 int nodeName = getChild(i-1);
138 SpreadsheetLines node = nodes.get(nodeName);
139 if(node == null) return null;
140 return node.getLine(k);
144 public String getLinesPath() {
148 public void forLines(Consumer<SpreadsheetLine> consumer, int min, int max) {
151 int n = (keys.length - 1) / 2;
154 while(i <= n && min > getKey(i-1)) i++;
156 while(i <= n && max > getKey(i-1)) {
158 int nodeName = getChild(i-1);
160 SpreadsheetLines node = nodes.get(nodeName);
162 consumer.accept(lines.get(-getKey(i-1)));
164 node.forLines(consumer, min, max);
173 public int getMaxRow() {
174 // if keys == null then this is the root of BTree which has only one child
177 for (SpreadsheetLines node : nodes.values()) {
178 int row = node.getMaxRow();
184 int largestChild = keys[keys.length-1];
185 if(largestChild > 0) {
186 SpreadsheetLines child = nodes.get(largestChild);
187 return child.getMaxRow();
189 return keys[keys.length-2];
194 public Optional<SpreadsheetEngine> getParent() {
195 return Optional.of(parent);
199 public Collection<SpreadsheetLine> getSpreadsheetChildren() {
200 return lines.values();
204 public void remove(SpreadsheetLine child) {
205 lines.remove(-child.row);
209 public int hashCode() {
210 final int prime = 31;
212 result = prime * result + ((name == null) ? 0 : name.hashCode());
213 result = prime * result + ((parent == null) ? 0 : parent.hashCode());
218 public boolean equals(Object obj) {
223 if (getClass() != obj.getClass())
225 SpreadsheetLines other = (SpreadsheetLines) obj;
227 if (other.name != null)
229 } else if (!name.equals(other.name))
231 if (parent == null) {
232 if (other.parent != null)
234 } else if (!parent.equals(other.parent))