Implemented exists()
This commit is contained in:
parent
1def19d219
commit
2e9d989a6c
34
pom.xml
34
pom.xml
|
@ -27,9 +27,15 @@
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>4.11</version>
|
<version>5.4.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>5.4.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -110,6 +116,28 @@
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
<version>2.8.2</version>
|
<version>2.8.2</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>it.cavallium.strangedb.server.Server</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
|
|
|
@ -4,12 +4,14 @@ import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import it.cavallium.strangedb.database.IReferencesIO;
|
import it.cavallium.strangedb.database.IReferencesIO;
|
||||||
import it.cavallium.strangedb.database.references.DatabaseReferencesMetadata;
|
import it.cavallium.strangedb.database.references.DatabaseReferencesMetadata;
|
||||||
import org.json.*;
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static it.cavallium.strangedb.server.TreePath.stringToNode;
|
import static it.cavallium.strangedb.server.TreePath.stringToNode;
|
||||||
|
@ -18,8 +20,10 @@ public class DatabaseNodesIO {
|
||||||
private final IReferencesIO referencesIO;
|
private final IReferencesIO referencesIO;
|
||||||
private static final int isArrayMask = 0b10000000000000000000000000000000;
|
private static final int isArrayMask = 0b10000000000000000000000000000000;
|
||||||
private static final int isValueMask = 0b01000000000000000000000000000000;
|
private static final int isValueMask = 0b01000000000000000000000000000000;
|
||||||
private static final int isNumberMask = 0b11000000000000000000000000000000;
|
private static final int isValueNumberMask = 0b00000000000000000000000000000001;
|
||||||
private static final int nodeCountMask = 0b01111111111111111111111111111111;
|
private static final int isValueStringMask = 0b00000000000000000000000000000010;
|
||||||
|
private static final int isValueBooleanMask = 0b00000000000000000000000000000100;
|
||||||
|
private static final int nodeCountMask = 0b01111111111111111111111111111111;
|
||||||
private static final int arrayCountMask = 0b01111111111111111111111111111111;
|
private static final int arrayCountMask = 0b01111111111111111111111111111111;
|
||||||
|
|
||||||
public DatabaseNodesIO(IReferencesIO referencesIO, DatabaseReferencesMetadata referencesMetadata) throws IOException {
|
public DatabaseNodesIO(IReferencesIO referencesIO, DatabaseReferencesMetadata referencesMetadata) throws IOException {
|
||||||
|
@ -37,8 +41,12 @@ public class DatabaseNodesIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String get(TreePath path) throws IOException {
|
public String get(TreePath path) throws IOException {
|
||||||
Node foundNode = getNode(path);
|
try {
|
||||||
return toJson(foundNode);
|
Node foundNode = getNode(path);
|
||||||
|
return toJson(foundNode);
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toJson(Node foundNode) throws IOException {
|
private String toJson(Node foundNode) throws IOException {
|
||||||
|
@ -82,12 +90,7 @@ public class DatabaseNodesIO {
|
||||||
}
|
}
|
||||||
case VALUE: {
|
case VALUE: {
|
||||||
ValueNode valueNode = (ValueNode) foundNode;
|
ValueNode valueNode = (ValueNode) foundNode;
|
||||||
sb.append(org.json.JSONObject.quote(loadValue(valueNode.getValueReference())));
|
sb.append(loadValue(valueNode));
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NUMBER: {
|
|
||||||
NumberNode valueNode = (NumberNode) foundNode;
|
|
||||||
sb.append(loadNumber(valueNode.getNumberReference()));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,16 +101,19 @@ public class DatabaseNodesIO {
|
||||||
referencesIO.writeToReference(reference, valueBytes.limit(), valueBytes);
|
referencesIO.writeToReference(reference, valueBytes.limit(), valueBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String loadValue(long reference) throws IOException {
|
private String loadValue(ValueNode valueNode) throws IOException {
|
||||||
ByteBuffer buffer = referencesIO.readFromReference(reference);
|
ByteBuffer buffer = referencesIO.readFromReference(valueNode.getReference());
|
||||||
return StandardCharsets.UTF_8.decode(buffer).toString();
|
ByteBuffer valueBuffer = referencesIO.readFromReference(valueNode.getValueReference());
|
||||||
}
|
switch (valueNode.getValueType()) {
|
||||||
|
case STRING:
|
||||||
private void setNumber(long reference, double value) throws IOException {
|
return JSONObject.quote(StandardCharsets.UTF_8.decode(valueBuffer).toString());
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES);
|
case NUMBER:
|
||||||
buffer.putDouble(value);
|
return JSONObject.doubleToString(valueBuffer.getDouble());
|
||||||
buffer.flip();
|
case BOOLEAN:
|
||||||
referencesIO.writeToReference(reference, buffer.limit(), buffer);
|
return valueBuffer.get() == 1 ? "true" : "false";
|
||||||
|
default:
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double loadNumber(long reference) throws IOException {
|
private double loadNumber(long reference) throws IOException {
|
||||||
|
@ -149,7 +155,6 @@ public class DatabaseNodesIO {
|
||||||
classNode.setProperty(propertyName, valueReference);
|
classNode.setProperty(propertyName, valueReference);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NUMBER:
|
|
||||||
case VALUE: {
|
case VALUE: {
|
||||||
throw new IOException("WTF you shouldn't be here!");
|
throw new IOException("WTF you shouldn't be here!");
|
||||||
}
|
}
|
||||||
|
@ -171,6 +176,15 @@ public class DatabaseNodesIO {
|
||||||
case '{':
|
case '{':
|
||||||
JSONObject obj = new JSONObject(value);
|
JSONObject obj = new JSONObject(value);
|
||||||
return importJsonNode(obj, reference);
|
return importJsonNode(obj, reference);
|
||||||
|
case 'u':
|
||||||
|
if (value.equals("undefined"))
|
||||||
|
return importJsonNode(value, reference);
|
||||||
|
case 'N':
|
||||||
|
if (value.equals("NaN"))
|
||||||
|
return importJsonNode(value, reference);
|
||||||
|
case 'n':
|
||||||
|
if (value.equals("null"))
|
||||||
|
return importJsonNode(value, reference);
|
||||||
case '"':
|
case '"':
|
||||||
return importJsonNode(value.substring(1, value.length() - 1), reference);
|
return importJsonNode(value.substring(1, value.length() - 1), reference);
|
||||||
case '0':
|
case '0':
|
||||||
|
@ -185,6 +199,12 @@ public class DatabaseNodesIO {
|
||||||
case '9':
|
case '9':
|
||||||
case '.':
|
case '.':
|
||||||
return importJsonNode(Double.parseDouble(value), reference);
|
return importJsonNode(Double.parseDouble(value), reference);
|
||||||
|
case 't':
|
||||||
|
if (value.equals("true"))
|
||||||
|
return importJsonNode(true, reference);
|
||||||
|
case 'f':
|
||||||
|
if (value.equals("false"))
|
||||||
|
return importJsonNode(false, reference);
|
||||||
default:
|
default:
|
||||||
throw new IOException("Unrecognized input");
|
throw new IOException("Unrecognized input");
|
||||||
}
|
}
|
||||||
|
@ -199,6 +219,9 @@ public class DatabaseNodesIO {
|
||||||
if (o instanceof ArrayList<?>) {
|
if (o instanceof ArrayList<?>) {
|
||||||
o = new JSONArray((ArrayList<?>) o);
|
o = new JSONArray((ArrayList<?>) o);
|
||||||
}
|
}
|
||||||
|
if (o instanceof HashMap<?, ?>) {
|
||||||
|
o = new JSONObject((HashMap<?, ?>) o);
|
||||||
|
}
|
||||||
if (o instanceof JSONArray) {
|
if (o instanceof JSONArray) {
|
||||||
JSONArray array = (JSONArray) o;
|
JSONArray array = (JSONArray) o;
|
||||||
int length = array.length();
|
int length = array.length();
|
||||||
|
@ -217,12 +240,13 @@ public class DatabaseNodesIO {
|
||||||
for (Map.Entry<String, Object> entry : jsonProperties.entrySet()) {
|
for (Map.Entry<String, Object> entry : jsonProperties.entrySet()) {
|
||||||
NodeProperty nodeProperty = new NodeProperty(stringToNode(entry.getKey()), importJsonNode(entry.getValue()));
|
NodeProperty nodeProperty = new NodeProperty(stringToNode(entry.getKey()), importJsonNode(entry.getValue()));
|
||||||
properties[i] = nodeProperty;
|
properties[i] = nodeProperty;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
Node node = createNewNodeNode(properties, reference);
|
Node node = createNewNodeNode(properties, reference);
|
||||||
setNode(node);
|
setNode(node);
|
||||||
return node.getReference();
|
return node.getReference();
|
||||||
} else if (o instanceof String) {
|
} else if (o instanceof String) {
|
||||||
Node node = createNewValueNode((String) o, reference);
|
Node node = createNewValueNode(o, ValueType.STRING, reference);
|
||||||
setNode(node);
|
setNode(node);
|
||||||
return node.getReference();
|
return node.getReference();
|
||||||
} else if (o instanceof Double || o instanceof Float || o instanceof Integer || o instanceof Long) {
|
} else if (o instanceof Double || o instanceof Float || o instanceof Integer || o instanceof Long) {
|
||||||
|
@ -233,12 +257,14 @@ public class DatabaseNodesIO {
|
||||||
number = (Long) o;
|
number = (Long) o;
|
||||||
} else if (o instanceof Float) {
|
} else if (o instanceof Float) {
|
||||||
number = (Float) o;
|
number = (Float) o;
|
||||||
} else if (o instanceof Double) {
|
|
||||||
number = (Double) o;
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException();
|
number = (Double) o;
|
||||||
}
|
}
|
||||||
Node node = createNewNumberNode(number+0, reference);
|
Node node = createNewValueNode(number, ValueType.NUMBER, reference);
|
||||||
|
setNode(node);
|
||||||
|
return node.getReference();
|
||||||
|
} else if (o instanceof Boolean) {
|
||||||
|
Node node = createNewValueNode(o, ValueType.BOOLEAN, reference);
|
||||||
setNode(node);
|
setNode(node);
|
||||||
return node.getReference();
|
return node.getReference();
|
||||||
} else {
|
} else {
|
||||||
|
@ -252,6 +278,7 @@ public class DatabaseNodesIO {
|
||||||
|
|
||||||
public boolean exists(TreePath path) throws IOException {
|
public boolean exists(TreePath path) throws IOException {
|
||||||
TreePathWalker pathWalker = new TreePathWalker(path);
|
TreePathWalker pathWalker = new TreePathWalker(path);
|
||||||
|
pathWalker.walkToRoot();
|
||||||
Node node = loadNode(0);
|
Node node = loadNode(0);
|
||||||
while (pathWalker.hasNext()) {
|
while (pathWalker.hasNext()) {
|
||||||
TreePath nodePath = pathWalker.next();
|
TreePath nodePath = pathWalker.next();
|
||||||
|
@ -260,7 +287,7 @@ public class DatabaseNodesIO {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int offset = nodePath.getArrayOffset();
|
int offset = nodePath.getArrayOffset();
|
||||||
if (!((ArrayNode)node).hasItem(offset)) {
|
if (!((ArrayNode) node).hasItem(offset)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
long nodeReference = ((ArrayNode) node).getItem(offset);
|
long nodeReference = ((ArrayNode) node).getItem(offset);
|
||||||
|
@ -280,6 +307,52 @@ public class DatabaseNodesIO {
|
||||||
return node != null;
|
return node != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size(CharSequence path) throws IOException {
|
||||||
|
return size(TreePath.get(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size(TreePath path) throws IOException {
|
||||||
|
TreePathWalker pathWalker = new TreePathWalker(path);
|
||||||
|
pathWalker.walkToRoot();
|
||||||
|
Node node = loadNode(0);
|
||||||
|
while (pathWalker.hasNext()) {
|
||||||
|
TreePath nodePath = pathWalker.next();
|
||||||
|
if (nodePath.isArrayOffset()) {
|
||||||
|
if (node.getType() != NodeType.ARRAY) {
|
||||||
|
throw new NullPointerException("Node not found");
|
||||||
|
}
|
||||||
|
int offset = nodePath.getArrayOffset();
|
||||||
|
if (!((ArrayNode) node).hasItem(offset)) {
|
||||||
|
throw new NullPointerException("Node not found");
|
||||||
|
}
|
||||||
|
long nodeReference = ((ArrayNode) node).getItem(offset);
|
||||||
|
node = loadNode(nodeReference);
|
||||||
|
} else if (nodePath.isNodeProperty()) {
|
||||||
|
if (node.getType() == NodeType.ARRAY) {
|
||||||
|
throw new NullPointerException("Node not found");
|
||||||
|
}
|
||||||
|
byte[] propertyName = nodePath.getNodeValue();
|
||||||
|
if (!((ClassNode) node).hasProperty(propertyName)) {
|
||||||
|
throw new NullPointerException("Node not found");
|
||||||
|
}
|
||||||
|
long nodeReference = ((ClassNode) node).getProperty(propertyName);
|
||||||
|
node = loadNode(nodeReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node != null) {
|
||||||
|
switch (node.getType()) {
|
||||||
|
case ARRAY:
|
||||||
|
return ((ArrayNode) node).countItems();
|
||||||
|
case CLASS:
|
||||||
|
return ((ClassNode) node).countProperties();
|
||||||
|
default:
|
||||||
|
throw new NullPointerException("You can't get the size of this node!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new NullPointerException("Node not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Node getNode(TreePath path) throws IOException {
|
private Node getNode(TreePath path) throws IOException {
|
||||||
TreePathWalker pathWalker = new TreePathWalker(path);
|
TreePathWalker pathWalker = new TreePathWalker(path);
|
||||||
pathWalker.walkToRoot();
|
pathWalker.walkToRoot();
|
||||||
|
@ -320,27 +393,43 @@ public class DatabaseNodesIO {
|
||||||
return new ArrayNode(reference, items);
|
return new ArrayNode(reference, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewValueNode() throws IOException {
|
private Node createNewValueNode(ValueType type) throws IOException {
|
||||||
long reference = referencesIO.allocateReference();
|
long reference = referencesIO.allocateReference();
|
||||||
return new ValueNode(reference, referencesIO.allocateReference());
|
return new ValueNode(reference, referencesIO.allocateReference(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewValueNode(String value) throws IOException {
|
private Node createNewValueNode(String value) throws IOException {
|
||||||
return createNewValueNode(value, referencesIO.allocateReference());
|
return createNewValueNode(value, ValueType.STRING, referencesIO.allocateReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewValueNode(String value, long reference) throws IOException {
|
private Node createNewValueNode(double value) throws IOException {
|
||||||
byte[] string = value.getBytes(StandardCharsets.UTF_8);
|
return createNewValueNode(value, ValueType.NUMBER, referencesIO.allocateReference());
|
||||||
long dataReference = referencesIO.allocateReference(string.length, ByteBuffer.wrap(string));
|
|
||||||
return new ValueNode(reference, dataReference);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewNumberNode(double value, long reference) throws IOException {
|
private Node createNewValueNode(Object value, ValueType valueType, long reference) throws IOException {
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES);
|
ByteBuffer buffer = null;
|
||||||
buffer.putDouble(value);
|
switch (valueType) {
|
||||||
buffer.flip();
|
case STRING:
|
||||||
long dataReference = referencesIO.allocateReference(buffer.limit(), buffer);
|
buffer = StandardCharsets.UTF_8.encode((String) value);
|
||||||
return new NumberNode(reference, dataReference);
|
break;
|
||||||
|
case NUMBER:
|
||||||
|
buffer = ByteBuffer.allocate(Double.BYTES);
|
||||||
|
buffer.putDouble((Double) value);
|
||||||
|
buffer.flip();
|
||||||
|
break;
|
||||||
|
case BOOLEAN:
|
||||||
|
buffer = ByteBuffer.allocate(Byte.BYTES);
|
||||||
|
buffer.put(((boolean) value) ? (byte) 1 : 0);
|
||||||
|
buffer.flip();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
long dataReference = -1;
|
||||||
|
if (buffer != null) {
|
||||||
|
dataReference = referencesIO.allocateReference(buffer.limit(), buffer);
|
||||||
|
}
|
||||||
|
return new ValueNode(reference, dataReference, valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node createNewNodeNode() throws IOException {
|
private Node createNewNodeNode() throws IOException {
|
||||||
|
@ -383,15 +472,22 @@ public class DatabaseNodesIO {
|
||||||
buffer = ByteBuffer.wrap(dataOutput.toByteArray());
|
buffer = ByteBuffer.wrap(dataOutput.toByteArray());
|
||||||
break;
|
break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
|
ValueNode valueNode = (ValueNode) node;
|
||||||
buffer = ByteBuffer.allocate(Integer.BYTES + Long.BYTES);
|
buffer = ByteBuffer.allocate(Integer.BYTES + Long.BYTES);
|
||||||
buffer.putInt(isValueMask);
|
switch (valueNode.getValueType()) {
|
||||||
buffer.putLong(((ValueNode) node).getValueReference());
|
case STRING:
|
||||||
buffer.flip();
|
buffer.putInt(isValueMask | isValueStringMask);
|
||||||
break;
|
break;
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
buffer = ByteBuffer.allocate(Integer.BYTES + Long.BYTES);
|
buffer.putInt(isValueMask | isValueNumberMask);
|
||||||
buffer.putInt(isNumberMask);
|
break;
|
||||||
buffer.putLong(((NumberNode) node).getNumberReference());
|
case BOOLEAN:
|
||||||
|
buffer.putInt(isValueMask | isValueBooleanMask);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
buffer.putLong(valueNode.getValueReference());
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -404,8 +500,7 @@ public class DatabaseNodesIO {
|
||||||
Node node;
|
Node node;
|
||||||
ByteBuffer nodeData = referencesIO.readFromReference(reference);
|
ByteBuffer nodeData = referencesIO.readFromReference(reference);
|
||||||
int propertiesCount = nodeData.getInt();
|
int propertiesCount = nodeData.getInt();
|
||||||
boolean isNumber = (propertiesCount & isNumberMask) == isNumberMask;
|
boolean isArray = (propertiesCount & isArrayMask) != 0;
|
||||||
boolean isArray = !isNumber && (propertiesCount & isArrayMask) != 0;
|
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
int arrayElementsCount = propertiesCount & arrayCountMask;
|
int arrayElementsCount = propertiesCount & arrayCountMask;
|
||||||
long[] arrayElementsReferences = new long[arrayElementsCount];
|
long[] arrayElementsReferences = new long[arrayElementsCount];
|
||||||
|
@ -414,13 +509,18 @@ public class DatabaseNodesIO {
|
||||||
}
|
}
|
||||||
node = new ArrayNode(reference, arrayElementsReferences);
|
node = new ArrayNode(reference, arrayElementsReferences);
|
||||||
} else {
|
} else {
|
||||||
boolean isValue = !isNumber && (propertiesCount & isValueMask) != 0;
|
boolean isValue = (propertiesCount & isValueMask) != 0;
|
||||||
if (isValue) {
|
if (isValue) {
|
||||||
long valueReference = nodeData.getLong();
|
long dataReference = nodeData.getLong();
|
||||||
node = new ValueNode(reference, valueReference);
|
if ((propertiesCount & isValueStringMask) != 0) {
|
||||||
} else if (isNumber) {
|
node = new ValueNode(reference, dataReference, ValueType.STRING);
|
||||||
long numberReference = nodeData.getLong();
|
} else if ((propertiesCount & isValueNumberMask) != 0) {
|
||||||
node = new NumberNode(reference, numberReference);
|
node = new ValueNode(reference, dataReference, ValueType.NUMBER);
|
||||||
|
} else if ((propertiesCount & isValueBooleanMask) != 0) {
|
||||||
|
node = new ValueNode(reference, dataReference, ValueType.BOOLEAN);
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NodeProperty[] nodeProperties = new NodeProperty[propertiesCount & nodeCountMask];
|
NodeProperty[] nodeProperties = new NodeProperty[propertiesCount & nodeCountMask];
|
||||||
for (int i = 0; i < propertiesCount; i++) {
|
for (int i = 0; i < propertiesCount; i++) {
|
||||||
|
|
|
@ -24,4 +24,8 @@ public class DatabaseSimple extends DatabaseCore {
|
||||||
public boolean exists(CharSequence path) throws IOException {
|
public boolean exists(CharSequence path) throws IOException {
|
||||||
return databaseNodesIO.exists(path);
|
return databaseNodesIO.exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size(CharSequence path) throws IOException {
|
||||||
|
return databaseNodesIO.size(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,5 @@ package it.cavallium.strangedb.server;
|
||||||
public enum NodeType {
|
public enum NodeType {
|
||||||
VALUE,
|
VALUE,
|
||||||
CLASS,
|
CLASS,
|
||||||
ARRAY,
|
ARRAY
|
||||||
NUMBER;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package it.cavallium.strangedb.server;
|
|
||||||
|
|
||||||
public class NumberNode implements Node {
|
|
||||||
|
|
||||||
private final long reference;
|
|
||||||
private long value;
|
|
||||||
|
|
||||||
public NumberNode(long reference, long value) {
|
|
||||||
this.reference = reference;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getNumberReference() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(long value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getReference() {
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Node copy() {
|
|
||||||
return new NumberNode(reference, value);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ import com.sun.net.httpserver.HttpServer;
|
||||||
import it.cavallium.strangedb.server.http.ExistsHandler;
|
import it.cavallium.strangedb.server.http.ExistsHandler;
|
||||||
import it.cavallium.strangedb.server.http.GetHandler;
|
import it.cavallium.strangedb.server.http.GetHandler;
|
||||||
import it.cavallium.strangedb.server.http.SetHandler;
|
import it.cavallium.strangedb.server.http.SetHandler;
|
||||||
|
import it.cavallium.strangedb.server.http.SizeHandler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -19,6 +20,7 @@ public class Server {
|
||||||
server.createContext("/get", new GetHandler(this));
|
server.createContext("/get", new GetHandler(this));
|
||||||
server.createContext("/set", new SetHandler(this));
|
server.createContext("/set", new SetHandler(this));
|
||||||
server.createContext("/exists", new ExistsHandler(this));
|
server.createContext("/exists", new ExistsHandler(this));
|
||||||
|
server.createContext("/size", new SizeHandler(this));
|
||||||
server.setExecutor(null);
|
server.setExecutor(null);
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +43,10 @@ public class Server {
|
||||||
return database.exists(path);
|
return database.exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size(CharSequence path) throws IOException {
|
||||||
|
return database.size(path);
|
||||||
|
}
|
||||||
|
|
||||||
public String get(CharSequence path) throws IOException {
|
public String get(CharSequence path) throws IOException {
|
||||||
return database.get(path);
|
return database.get(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,13 @@ import java.util.Arrays;
|
||||||
public class ValueNode implements Node {
|
public class ValueNode implements Node {
|
||||||
|
|
||||||
private final long reference;
|
private final long reference;
|
||||||
|
private final ValueType valueType;
|
||||||
private long value;
|
private long value;
|
||||||
|
|
||||||
public ValueNode(long reference, long value) {
|
public ValueNode(long reference, long value, ValueType valueType) {
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.valueType = valueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getValueReference() {
|
public long getValueReference() {
|
||||||
|
@ -25,6 +27,10 @@ public class ValueNode implements Node {
|
||||||
return NodeType.VALUE;
|
return NodeType.VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return valueType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getReference() {
|
public long getReference() {
|
||||||
return reference;
|
return reference;
|
||||||
|
@ -32,6 +38,6 @@ public class ValueNode implements Node {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node copy() {
|
public Node copy() {
|
||||||
return new ValueNode(reference, value);
|
return new ValueNode(reference, value, valueType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package it.cavallium.strangedb.server;
|
||||||
|
|
||||||
|
public enum ValueType {
|
||||||
|
STRING,
|
||||||
|
NUMBER,
|
||||||
|
BOOLEAN
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package it.cavallium.strangedb.server.http;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
|
import it.cavallium.strangedb.server.Server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class SizeHandler implements HttpHandler {
|
||||||
|
|
||||||
|
private final Server server;
|
||||||
|
|
||||||
|
public SizeHandler(Server server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpExchange exchange) throws IOException {
|
||||||
|
String requestPath = exchange.getRequestURI().toString().split("/size/", 2)[1].replace('(', '[').replace(')', ']');
|
||||||
|
int responseCode = 500;
|
||||||
|
String response;
|
||||||
|
try {
|
||||||
|
response = "" + server.size(requestPath);
|
||||||
|
responseCode = 200;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
response = "Error";
|
||||||
|
}
|
||||||
|
byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);
|
||||||
|
exchange.sendResponseHeaders(responseCode, responseBytes.length);
|
||||||
|
OutputStream os = exchange.getResponseBody();
|
||||||
|
os.write(responseBytes);
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,15 @@
|
||||||
package it.cavallium.strangedb.server;
|
package it.cavallium.strangedb.server;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import static junit.framework.Assert.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
public class GetSetExistsTest {
|
public class GetSetExistsTest {
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ public class GetSetExistsTest {
|
||||||
private Path path3;
|
private Path path3;
|
||||||
private DatabaseSimple db;
|
private DatabaseSimple db;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
path1 = Files.createTempFile("db-tests-", ".db");
|
path1 = Files.createTempFile("db-tests-", ".db");
|
||||||
path2 = Files.createTempFile("db-tests-", ".db");
|
path2 = Files.createTempFile("db-tests-", ".db");
|
||||||
|
@ -32,22 +33,58 @@ public class GetSetExistsTest {
|
||||||
db.set("", "{}");
|
db.set("", "{}");
|
||||||
assertTrue(db.exists(""));
|
assertTrue(db.exists(""));
|
||||||
assertEquals(db.get(""), "{}");
|
assertEquals(db.get(""), "{}");
|
||||||
db.set("brightness", "\"15\"");
|
db.set("value", "{}");
|
||||||
|
db.set("value.int", "12");
|
||||||
|
db.set("value.number", "12.13");
|
||||||
|
db.set("value.null", "null");
|
||||||
|
db.set("value.boolean", "true");
|
||||||
|
db.set("value.undefined", "undefined");
|
||||||
|
db.set("value.string", "\"test\"");
|
||||||
|
db.set("value.array", "[1,2,3,4,5]");
|
||||||
|
db.set("value.object", "{a: 1, b: \"2\", c: [3], d: {}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldGetObject() throws IOException {
|
public void shouldGetObject() throws IOException {
|
||||||
assertFalse(db.exists("brightness"));
|
db.set("", "{\n" +
|
||||||
db.set("brightness", "\"15\"");
|
"\t\"value\": {\n" +
|
||||||
assertTrue(db.exists("brightness"));
|
"\t\t\"int\": 12,\n" +
|
||||||
assertEquals(db.get("brightness"), "\"15\"");
|
"\t\t\"number\": 12.13," +
|
||||||
assertEquals(db.get(""), "{brightness:\"15\"}");
|
"nil: null,\n" +
|
||||||
db.set("brightness", "\"16\"");
|
"\t\t\"boolean\": true,\n" +
|
||||||
assertEquals(db.get("brightness"), "\"16\"");
|
"\t\t\"string\": \"test\",\n" +
|
||||||
assertEquals(db.get(""), "{brightness:\"16\"}");
|
"\t\t\"array\": [1,2,3,4],\n" +
|
||||||
|
"\t\t\"object\": {\n" +
|
||||||
|
"\t\t\t\"a\": 1,\n" +
|
||||||
|
"\t\t\t\"b\": \"2\",\n" +
|
||||||
|
"\t\t\t\"c\": [3],\n" +
|
||||||
|
"\t\t\t\"d\": {}\n" +
|
||||||
|
"\t\t}\n" +
|
||||||
|
"\t}\n" +
|
||||||
|
"}");
|
||||||
|
assertFalse(db.exists("random"));
|
||||||
|
assertTrue(db.exists("value"));
|
||||||
|
assertEquals("12", db.get("value.int"));
|
||||||
|
assertEquals("12.13", db.get("value.number"));
|
||||||
|
assertEquals("null", db.get("value.nil"));
|
||||||
|
assertEquals("true", db.get("value.boolean"));
|
||||||
|
assertEquals("\"test\"", db.get("value.string"));
|
||||||
|
assertEquals("[1,2,3,4]", db.get("value.array"));
|
||||||
|
assertEquals("1", db.get("value.object.a"));
|
||||||
|
assertEquals("\"2\"", db.get("value.object.b"));
|
||||||
|
assertEquals("[3]", db.get("value.object.c"));
|
||||||
|
assertEquals("{}", db.get("value.object.d"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@Test
|
||||||
|
public void shouldGetSize() throws IOException {
|
||||||
|
db.set("", "{array:[1,2,3,4,5], object: {a: 1, b: 2, c: 3}, string: \"test\"}");
|
||||||
|
assertEquals(5, db.size("array"));
|
||||||
|
assertEquals(3, db.size("object"));
|
||||||
|
assertThrows(NullPointerException.class, () -> db.size("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
db.close();
|
db.close();
|
||||||
Files.deleteIfExists(path1);
|
Files.deleteIfExists(path1);
|
||||||
|
|
Loading…
Reference in New Issue