160 lines
3.7 KiB
Java
160 lines
3.7 KiB
Java
package it.cavallium.strangedb.server;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Arrays;
|
|
|
|
public class TreePath {
|
|
public final TreePath parent;
|
|
private final byte[] node;
|
|
private final int offset;
|
|
|
|
private TreePath() {
|
|
parent = null;
|
|
node = null;
|
|
offset = 0;
|
|
}
|
|
|
|
private TreePath(TreePath parent, byte[] node) {
|
|
this.parent = parent;
|
|
this.node = node;
|
|
this.offset = 0;
|
|
}
|
|
|
|
private TreePath(TreePath parent, int offset) {
|
|
this.parent = parent;
|
|
this.node = null;
|
|
this.offset = offset;
|
|
}
|
|
|
|
public TreePath resolveArrayElement(int offset) {
|
|
return new TreePath(this, offset);
|
|
}
|
|
|
|
public TreePath resolveNode(byte[] child) {
|
|
return new TreePath(this, child);
|
|
}
|
|
|
|
public boolean isNodeProperty() {
|
|
return (isRoot() || node != null);
|
|
}
|
|
|
|
public boolean isArrayOffset() {
|
|
return !isNodeProperty();
|
|
}
|
|
|
|
public byte[] getNodeValue() {
|
|
if(node == null || isRoot())
|
|
throw new NullPointerException();
|
|
return node;
|
|
}
|
|
|
|
public int getArrayOffset() {
|
|
if(node != null || isRoot())
|
|
throw new NullPointerException();
|
|
return offset;
|
|
}
|
|
|
|
public boolean hasParent() {
|
|
return parent != null;
|
|
}
|
|
|
|
public TreePath getParent() {
|
|
if (parent == null)
|
|
throw new NullPointerException();
|
|
return parent;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return toStringBuilder().toString();
|
|
}
|
|
|
|
/**
|
|
* Convert to string the actual TreePath
|
|
* @return The TreePath as a string
|
|
*/
|
|
private StringBuilder toStringBuilder() {
|
|
StringBuilder builder;
|
|
if (parent == null) {
|
|
builder = new StringBuilder();
|
|
} else {
|
|
builder = parent.toStringBuilder();
|
|
}
|
|
if (isRoot()) {
|
|
return builder;
|
|
}
|
|
if (node != null) {
|
|
if (parent != null && !parent.isRoot())
|
|
builder.append('.');
|
|
builder.append(nodeToString(node));
|
|
} else {
|
|
builder.append('[').append(offset).append(']');
|
|
}
|
|
return builder;
|
|
}
|
|
|
|
/**
|
|
* Convert node bytes to a StringBuilder
|
|
* @param node node letters
|
|
* @return node letters joined together
|
|
*/
|
|
public static StringBuilder nodeToString(byte[] node) {
|
|
StringBuilder string = new StringBuilder();
|
|
for (byte letter : node) {
|
|
string.append((char) letter);
|
|
}
|
|
return string;
|
|
}
|
|
|
|
public static byte[] stringToNode(String text) {
|
|
return text.getBytes(StandardCharsets.US_ASCII);
|
|
}
|
|
|
|
/**
|
|
* Convert a char sequence to a TreePath
|
|
* @param str char sequence
|
|
* @return The tree path
|
|
*/
|
|
public static TreePath get(CharSequence str) {
|
|
byte[] currentName = new byte[32];
|
|
byte currentNamePosition = 0;
|
|
TreePath currentTreePath = new TreePath();
|
|
for (int i = 0; i < str.length(); i++) {
|
|
byte character = (byte) str.charAt(i);
|
|
if (character >= '0' && character <= '9'
|
|
|| character >= 'A' && character <= 'Z'
|
|
|| character >= 'a' && character <= 'z'
|
|
|| character == '_') {
|
|
currentName[currentNamePosition] = character;
|
|
currentNamePosition++;
|
|
} else if((character == '.' || character == '[') && currentNamePosition > 0) {
|
|
currentTreePath = currentTreePath.resolveNode(Arrays.copyOf(currentName, currentNamePosition));
|
|
currentNamePosition = 0;
|
|
} else if (character == ']') {
|
|
if (currentNamePosition == 0) throw new NullPointerException();
|
|
int arrayOffset = toInt(Arrays.copyOf(currentName, currentNamePosition));
|
|
currentTreePath = currentTreePath.resolveArrayElement(arrayOffset);
|
|
currentNamePosition = 0;
|
|
}
|
|
}
|
|
if (currentNamePosition != 0) {
|
|
currentTreePath = currentTreePath.resolveNode(Arrays.copyOf(currentName, currentNamePosition));
|
|
}
|
|
return currentTreePath;
|
|
}
|
|
|
|
private static int toInt(byte[] number) {
|
|
int result = 0;
|
|
int tenpower = 1;
|
|
for (int i = number.length - 1; i >= 0; i--) {
|
|
result += (number[i] - '0') * tenpower;
|
|
tenpower *= 10;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public boolean isRoot() {
|
|
return parent == null;
|
|
}
|
|
}
|