--- /dev/null
+package org.simantics.spreadsheet.graph;\r
+\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Map;\r
+import java.util.Optional;\r
+\r
+import org.simantics.spreadsheet.resource.SpreadsheetResource;\r
+\r
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;\r
+\r
+public class SpreadsheetLines implements SpreadsheetElement<SpreadsheetLine, SpreadsheetEngine>, SheetNode {\r
+\r
+ private static final long serialVersionUID = -3615335969248723486L;\r
+ \r
+ private final int id;\r
+ private SpreadsheetEngine parent;\r
+ private String name;\r
+ public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();\r
+ public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();\r
+ public int[] keys;\r
+\r
+ public SpreadsheetLines(SpreadsheetEngine parent, String name) {\r
+ this.parent = parent;\r
+ this.name = name;\r
+ id = getEngine().getBook().getNewId(this);\r
+ }\r
+\r
+ public SpreadsheetEngine getEngine() {\r
+ return parent;\r
+ }\r
+\r
+ public int getId() {\r
+ return id;\r
+ }\r
+ \r
+ @Override\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ @Override\r
+ public Map getChildren() {\r
+ Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap();\r
+ result.putAll(nodes);\r
+ result.putAll(lines);\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public Map getProperties() {\r
+ return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Lines));\r
+ } \r
+ \r
+ Object resolve(String[] parts, int index) {\r
+ \r
+ String part = parts[index];\r
+ if(part.charAt(0) == 'R') {\r
+ int indx = Integer.parseInt(part.substring(3));\r
+ SpreadsheetLine line = lines.get(-indx);\r
+ if(line != null) {\r
+ if(index == parts.length-1) return line;\r
+ else return line.resolve(parts, index+1);\r
+ }\r
+ } else {\r
+ int indx = Integer.parseInt(part);\r
+ SpreadsheetLines node = nodes.get(indx);\r
+ if(node != null) {\r
+ if(index == parts.length-1) return node;\r
+ else return node.resolve(parts, index+1);\r
+ }\r
+ }\r
+ \r
+ return null;\r
+\r
+ }\r
+\r
+ public Object ensureSubprocess(String[] path, int index) {\r
+ \r
+ String name = path[index];\r
+\r
+ int i = Integer.parseInt(name);\r
+ SpreadsheetLines line = nodes.get(i);\r
+ if(line == null) {\r
+ line = new SpreadsheetLines(parent, "" + i);\r
+ nodes.put(i, line);\r
+ }\r
+\r
+ if(index == path.length - 1) {\r
+ return line;\r
+ } else {\r
+ return line.ensureSubprocess(path, index+1);\r
+ }\r
+ \r
+ }\r
+ \r
+ public void setKeys(int[] keys) {\r
+ this.keys = keys;\r
+ }\r
+ \r
+ @Override\r
+ public void accept(SpreadsheetVisitor v) {\r
+ v.visit(this);\r
+ }\r
+\r
+ public String getPath() {\r
+ return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName();\r
+ }\r
+\r
+ private int getKey(int index) {\r
+ return keys[2*index+1];\r
+ }\r
+\r
+ private int getChild(int index) {\r
+ return keys[2*index];\r
+ }\r
+\r
+ /*\r
+ * [(child,key),...,key)\r
+ * \r
+ */\r
+ public SpreadsheetLine getLine(int k) {\r
+ \r
+ int i=1;\r
+ int n = (keys.length - 1) / 2;\r
+ \r
+ while(i <= n && k > getKey(i-1)) i++;\r
+ \r
+ if(i <= n && k == getKey(i-1)) {\r
+ return lines.get(-k);\r
+ }\r
+\r
+ int nodeName = getChild(i-1);\r
+ SpreadsheetLines node = nodes.get(nodeName);\r
+ if(node == null) return null;\r
+ return node.getLine(k);\r
+ \r
+ }\r
+ \r
+ public int getMaxRow() {\r
+ // if keys == null then this is the root of BTree which has only one child \r
+ if (keys == null) {\r
+ int maxRow = 0;\r
+ for (SpreadsheetLines node : nodes.values()) {\r
+ int row = node.getMaxRow();\r
+ if (row > maxRow)\r
+ maxRow = row;\r
+ }\r
+ return maxRow;\r
+ }\r
+ int largestChild = keys[keys.length-1]; \r
+ if(largestChild > 0) {\r
+ SpreadsheetLines child = nodes.get(largestChild);\r
+ return child.getMaxRow();\r
+ } else {\r
+ return keys[keys.length-2];\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Optional<SpreadsheetEngine> getParent() {\r
+ return Optional.of(parent);\r
+ }\r
+\r
+ @Override\r
+ public Collection<SpreadsheetLine> getSpreadsheetChildren() {\r
+ return lines.values();\r
+ }\r
+\r
+ @Override\r
+ public void remove(SpreadsheetLine child) {\r
+ lines.remove(-child.row);\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((name == null) ? 0 : name.hashCode());\r
+ result = prime * result + ((parent == null) ? 0 : parent.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
+ SpreadsheetLines other = (SpreadsheetLines) obj;\r
+ if (name == null) {\r
+ if (other.name != null)\r
+ return false;\r
+ } else if (!name.equals(other.name))\r
+ return false;\r
+ if (parent == null) {\r
+ if (other.parent != null)\r
+ return false;\r
+ } else if (!parent.equals(other.parent))\r
+ return false;\r
+ return true;\r
+ }\r
+ \r
+}\r