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