mirror of
https://github.com/ChronosX88/JGUN.git
synced 2024-11-23 23:12:18 +00:00
Make node values type-safe
This commit is contained in:
parent
b83e3ee14e
commit
45e013098f
@ -1,88 +0,0 @@
|
|||||||
package io.github.chronosx88.JGUN;
|
|
||||||
|
|
||||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
|
||||||
import io.github.chronosx88.JGUN.models.Node;
|
|
||||||
import io.github.chronosx88.JGUN.models.NodeLink;
|
|
||||||
import io.github.chronosx88.JGUN.models.NodeMetadata;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class NodeArrayBuilder {
|
|
||||||
private final MemoryGraph graph;
|
|
||||||
private final Node rootNode;
|
|
||||||
private final List<Object> innerArray;
|
|
||||||
protected static final String ARRAY_FIELD = "__ARRAY__";
|
|
||||||
|
|
||||||
public NodeArrayBuilder() {
|
|
||||||
this.graph = MemoryGraph.builder().build();
|
|
||||||
this.innerArray = new ArrayList<>();
|
|
||||||
this.rootNode = Node.builder()
|
|
||||||
.metadata(NodeMetadata.builder()
|
|
||||||
.nodeID(null)
|
|
||||||
.states(new HashMap<>(Map.of(ARRAY_FIELD, System.currentTimeMillis())))
|
|
||||||
.build())
|
|
||||||
.values(Map.of(ARRAY_FIELD, innerArray))
|
|
||||||
.build();
|
|
||||||
graph.nodes.put(GraphNodeBuilder.ROOT_NODE, this.rootNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private NodeArrayBuilder addScalar(Object value) {
|
|
||||||
this.innerArray.add(value);
|
|
||||||
this.rootNode.getMetadata().getStates().put(ARRAY_FIELD, System.currentTimeMillis());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(String value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(BigInteger value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(BigDecimal value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(int value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(long value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(double value) {
|
|
||||||
return addScalar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(boolean value) {
|
|
||||||
return addScalar(value);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder addNull(String name) {
|
|
||||||
return addScalar(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeArrayBuilder add(GraphNodeBuilder builder) {
|
|
||||||
String newNodeID = UUID.randomUUID().toString();
|
|
||||||
//noinspection unchecked
|
|
||||||
List<Object> innerArray = (List<Object>) rootNode.values.get(ARRAY_FIELD);
|
|
||||||
innerArray.add(NodeLink.builder()
|
|
||||||
.link(newNodeID)
|
|
||||||
.build());
|
|
||||||
MemoryGraph innerGraph = builder.build();
|
|
||||||
innerGraph.nodes.get(GraphNodeBuilder.ROOT_NODE).getMetadata().setNodeID(newNodeID);
|
|
||||||
innerGraph.nodes.put(newNodeID, innerGraph.nodes.get(GraphNodeBuilder.ROOT_NODE));
|
|
||||||
innerGraph.nodes.remove(GraphNodeBuilder.ROOT_NODE);
|
|
||||||
this.graph.nodes.putAll(innerGraph.nodes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemoryGraph build() {
|
|
||||||
return this.graph;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package io.github.chronosx88.JGUN;
|
package io.github.chronosx88.JGUN.api;
|
||||||
|
|
||||||
import io.github.chronosx88.JGUN.models.Node;
|
import io.github.chronosx88.JGUN.models.graph.Node;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface NodeChangeListener {
|
public interface NodeChangeListener {
|
@ -0,0 +1,87 @@
|
|||||||
|
package io.github.chronosx88.JGUN.api.graph;
|
||||||
|
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.MemoryGraph;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.Node;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.values.*;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeMetadata;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ArrayBuilder {
|
||||||
|
private final MemoryGraph graph;
|
||||||
|
private final Node rootNode;
|
||||||
|
private final List<NodeValue> innerArray;
|
||||||
|
protected static final String ARRAY_FIELD = "__ARRAY__";
|
||||||
|
|
||||||
|
public ArrayBuilder() {
|
||||||
|
this.graph = new MemoryGraph();
|
||||||
|
this.innerArray = new ArrayList<>();
|
||||||
|
this.rootNode = Node.builder()
|
||||||
|
.metadata(NodeMetadata.builder()
|
||||||
|
.nodeID(null)
|
||||||
|
.states(new HashMap<>(Map.of(ARRAY_FIELD, System.currentTimeMillis())))
|
||||||
|
.build())
|
||||||
|
.values(Map.of(ARRAY_FIELD, new ArrayValue(this.innerArray)))
|
||||||
|
.build();
|
||||||
|
graph.nodes.put(NodeBuilder.ROOT_NODE, this.rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayBuilder addScalar(NodeValue value) {
|
||||||
|
this.innerArray.add(value);
|
||||||
|
this.rootNode.getMetadata().getStates().put(ARRAY_FIELD, System.currentTimeMillis());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(String value) {
|
||||||
|
return addScalar(new StringValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(BigInteger value) {
|
||||||
|
return addScalar(new IntValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(BigDecimal value) {
|
||||||
|
return addScalar(new DecimalValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(int value) {
|
||||||
|
return addScalar(new IntValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(long value) {
|
||||||
|
return addScalar(new IntValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(double value) {
|
||||||
|
return addScalar(new DecimalValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(boolean value) {
|
||||||
|
return addScalar(new BooleanValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder addNull(String name) {
|
||||||
|
return addScalar(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayBuilder add(NodeBuilder builder) {
|
||||||
|
String newNodeID = UUID.randomUUID().toString();
|
||||||
|
List<NodeValue> innerArray = ((ArrayValue) rootNode.values.get(ARRAY_FIELD)).getValue();
|
||||||
|
innerArray.add(NodeLinkValue.builder()
|
||||||
|
.link(newNodeID)
|
||||||
|
.build());
|
||||||
|
MemoryGraph innerGraph = builder.build();
|
||||||
|
innerGraph.nodes.get(NodeBuilder.ROOT_NODE).getMetadata().setNodeID(newNodeID);
|
||||||
|
innerGraph.nodes.put(newNodeID, innerGraph.nodes.get(NodeBuilder.ROOT_NODE));
|
||||||
|
innerGraph.nodes.remove(NodeBuilder.ROOT_NODE);
|
||||||
|
this.graph.nodes.putAll(innerGraph.nodes);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryGraph build() {
|
||||||
|
return this.graph;
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,21 @@
|
|||||||
package io.github.chronosx88.JGUN;
|
package io.github.chronosx88.JGUN.api.graph;
|
||||||
|
|
||||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
import io.github.chronosx88.JGUN.models.graph.*;
|
||||||
import io.github.chronosx88.JGUN.models.Node;
|
import io.github.chronosx88.JGUN.models.graph.values.*;
|
||||||
import io.github.chronosx88.JGUN.models.NodeLink;
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
import io.github.chronosx88.JGUN.models.NodeMetadata;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class GraphNodeBuilder {
|
public class NodeBuilder {
|
||||||
private final MemoryGraph graph;
|
private final MemoryGraph graph;
|
||||||
private final Node rootNode;
|
private final Node rootNode;
|
||||||
protected static final String ROOT_NODE = "__ROOT__";
|
protected static final String ROOT_NODE = "__ROOT__";
|
||||||
|
|
||||||
public GraphNodeBuilder() {
|
public NodeBuilder() {
|
||||||
this.graph = MemoryGraph.builder().build();
|
this.graph = new MemoryGraph();
|
||||||
this.rootNode = Node.builder()
|
this.rootNode = Node.builder()
|
||||||
.metadata(NodeMetadata.builder()
|
.metadata(NodeMetadata.builder()
|
||||||
.nodeID(null)
|
.nodeID(null)
|
||||||
@ -25,48 +24,47 @@ public class GraphNodeBuilder {
|
|||||||
graph.nodes.put(ROOT_NODE, this.rootNode);
|
graph.nodes.put(ROOT_NODE, this.rootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GraphNodeBuilder addScalar(String name, Object value) {
|
private NodeBuilder addScalar(String name, NodeValue value) {
|
||||||
rootNode.values.put(name, value);
|
rootNode.values.put(name, value);
|
||||||
rootNode.getMetadata().getStates().put(name, System.currentTimeMillis());
|
rootNode.getMetadata().getStates().put(name, System.currentTimeMillis());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, String value) {
|
public NodeBuilder add(String name, String value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new StringValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, BigInteger value) {
|
public NodeBuilder add(String name, BigInteger value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new IntValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, BigDecimal value) {
|
public NodeBuilder add(String name, BigDecimal value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new DecimalValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, int value) {
|
public NodeBuilder add(String name, int value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new IntValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, long value) {
|
public NodeBuilder add(String name, long value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new IntValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, double value) {
|
public NodeBuilder add(String name, double value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new DecimalValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, boolean value) {
|
public NodeBuilder add(String name, boolean value) {
|
||||||
return addScalar(name, value);
|
return addScalar(name, new BooleanValue(value));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder addNull(String name) {
|
public NodeBuilder addNull(String name) {
|
||||||
return addScalar(name, null);
|
return addScalar(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, GraphNodeBuilder builder) {
|
public NodeBuilder add(String name, NodeBuilder builder) {
|
||||||
String newNodeID = UUID.randomUUID().toString();
|
String newNodeID = UUID.randomUUID().toString();
|
||||||
rootNode.values.put(name, NodeLink.builder()
|
rootNode.values.put(name, NodeLinkValue.builder()
|
||||||
.link(newNodeID)
|
.link(newNodeID)
|
||||||
.build());
|
.build());
|
||||||
MemoryGraph innerGraph = builder.build();
|
MemoryGraph innerGraph = builder.build();
|
||||||
@ -77,17 +75,16 @@ public class GraphNodeBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphNodeBuilder add(String name, NodeArrayBuilder builder) {
|
public NodeBuilder add(String name, ArrayBuilder builder) {
|
||||||
MemoryGraph innerGraph = builder.build();
|
MemoryGraph innerGraph = builder.build();
|
||||||
//noinspection unchecked
|
var innerArray = (NodeValue) innerGraph.nodes.get(ROOT_NODE).values.get(ArrayBuilder.ARRAY_FIELD);
|
||||||
var innerArray = (List<Object>) innerGraph.nodes.get(ROOT_NODE).values.get(NodeArrayBuilder.ARRAY_FIELD);
|
|
||||||
rootNode.values.put(name, innerArray);
|
rootNode.values.put(name, innerArray);
|
||||||
rootNode.getMetadata().getStates().put(name, innerGraph
|
rootNode.getMetadata().getStates().put(name, innerGraph
|
||||||
.nodes
|
.nodes
|
||||||
.get(ROOT_NODE)
|
.get(ROOT_NODE)
|
||||||
.getMetadata()
|
.getMetadata()
|
||||||
.getStates()
|
.getStates()
|
||||||
.get(NodeArrayBuilder.ARRAY_FIELD));
|
.get(ArrayBuilder.ARRAY_FIELD));
|
||||||
innerGraph.nodes.remove(ROOT_NODE);
|
innerGraph.nodes.remove(ROOT_NODE);
|
||||||
graph.nodes.putAll(innerGraph.nodes);
|
graph.nodes.putAll(innerGraph.nodes);
|
||||||
return this;
|
return this;
|
@ -1,14 +0,0 @@
|
|||||||
package io.github.chronosx88.JGUN.models;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.extern.jackson.Jacksonized;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@Jacksonized
|
|
||||||
public class NodeLink {
|
|
||||||
@JsonProperty("#")
|
|
||||||
String link;
|
|
||||||
}
|
|
@ -1,8 +1,7 @@
|
|||||||
package io.github.chronosx88.JGUN.models.acks;
|
package io.github.chronosx88.JGUN.models.acks;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
import io.github.chronosx88.JGUN.models.graph.MemoryGraph;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package io.github.chronosx88.JGUN.models;
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Delayed;
|
import java.util.concurrent.Delayed;
|
||||||
@ -9,7 +7,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class DeferredNode extends Node implements Delayed {
|
public class DeferredNode extends Node implements Delayed {
|
||||||
private long deferredUntil = 0;
|
private long deferredUntil = 0;
|
||||||
|
|
||||||
DeferredNode(NodeMetadata metadata, Map<String, Object> values) {
|
DeferredNode(NodeMetadata metadata, Map<String, NodeValue> values) {
|
||||||
super(metadata, values);
|
super(metadata, values);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package io.github.chronosx88.JGUN.models;
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
@ -11,12 +11,9 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
|
||||||
@Jacksonized
|
|
||||||
public class MemoryGraph {
|
public class MemoryGraph {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@Builder.Default
|
public Map<String, Node> nodes = new LinkedHashMap<>();
|
||||||
public final Map<String, Node> nodes = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
@JsonAnyGetter
|
@JsonAnyGetter
|
||||||
public Map<String, Node> nodes() {
|
public Map<String, Node> nodes() {
|
@ -1,34 +1,38 @@
|
|||||||
package io.github.chronosx88.JGUN.models;
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Jacksonized
|
|
||||||
@Builder
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class Node {
|
public class Node {
|
||||||
@JsonProperty("_")
|
@JsonProperty("_")
|
||||||
private NodeMetadata metadata;
|
@Builder.Default
|
||||||
|
private final NodeMetadata metadata = new NodeMetadata(new HashMap<>(), null);
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
public Map<String, Object> values = new LinkedHashMap<>(); // Data
|
public final Map<String, NodeValue> values = new LinkedHashMap<>(); // Data
|
||||||
|
|
||||||
@JsonAnyGetter
|
@JsonAnyGetter
|
||||||
public Map<String, Object> getValues() {
|
public Map<String, NodeValue> getValues() {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonAnySetter
|
@JsonAnySetter
|
||||||
public void allSetter(String key, String value) {
|
public void allSetter(String key, NodeValue value) {
|
||||||
values.put(key, value);
|
values.put(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.github.chronosx88.JGUN.models;
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
@ -0,0 +1,19 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
|
||||||
|
//@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
|
||||||
|
@JsonDeserialize(using = NodeValueDeserializer.class)
|
||||||
|
public interface NodeValue {
|
||||||
|
enum ValueType {
|
||||||
|
ARRAY,
|
||||||
|
STRING,
|
||||||
|
INTEGER,
|
||||||
|
DECIMAL,
|
||||||
|
BOOLEAN,
|
||||||
|
NULL,
|
||||||
|
LINK
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType getValueType();
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JacksonException;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.values.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class NodeValueDeserializer extends JsonDeserializer<NodeValue> {
|
||||||
|
@Override
|
||||||
|
public NodeValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
|
||||||
|
JsonNode node = p.readValueAsTree();
|
||||||
|
return parseValue(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeValue parseValue(JsonNode node) throws JsonProcessingException {
|
||||||
|
if (node.isBoolean()) {
|
||||||
|
return new BooleanValue(node.booleanValue());
|
||||||
|
} else if (node.isBigDecimal()) {
|
||||||
|
return new DecimalValue(node.decimalValue());
|
||||||
|
} else if (node.isFloat()) {
|
||||||
|
return new DecimalValue(node.floatValue());
|
||||||
|
} else if (node.isDouble()) {
|
||||||
|
return new DecimalValue(node.doubleValue());
|
||||||
|
} else if (node.isTextual()) {
|
||||||
|
return new StringValue(node.textValue());
|
||||||
|
} else if (node.isInt()) {
|
||||||
|
return new IntValue(node.intValue());
|
||||||
|
} else if (node.isBigInteger()) {
|
||||||
|
return new IntValue(node.bigIntegerValue());
|
||||||
|
} else if (node.isLong()) {
|
||||||
|
return new IntValue(node.longValue());
|
||||||
|
} else if (node.isObject()) {
|
||||||
|
if (node.has("#")) {
|
||||||
|
return NodeLinkValue.builder()
|
||||||
|
.link(node.get("#").textValue())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("node can have only links, not actual objects");
|
||||||
|
}
|
||||||
|
} else if (node.isArray()) {
|
||||||
|
ArrayValue value = new ArrayValue();
|
||||||
|
for (JsonNode arrayItem : node) {
|
||||||
|
value.getValue().add(parseValue(arrayItem));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("unsupported node value");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ArrayValue implements NodeValue {
|
||||||
|
@JsonValue
|
||||||
|
private List<NodeValue> value = new ArrayList<>();
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public ArrayValue(NodeValue[] value) {
|
||||||
|
this.value = new ArrayList<>(List.of(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayValue(List<NodeValue> value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return ValueType.ARRAY;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class BooleanValue implements NodeValue {
|
||||||
|
@JsonValue
|
||||||
|
private boolean value;
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public BooleanValue(boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeValue.ValueType getValueType() {
|
||||||
|
return NodeValue.ValueType.BOOLEAN;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public class DecimalValue implements NodeValue {
|
||||||
|
@JsonValue
|
||||||
|
private BigDecimal value;
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public DecimalValue(double num) {
|
||||||
|
this.value = BigDecimal.valueOf(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public DecimalValue(float num) {
|
||||||
|
this.value = BigDecimal.valueOf(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public DecimalValue(BigDecimal value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return ValueType.DECIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDouble() {
|
||||||
|
return value.floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloat() {
|
||||||
|
return value.floatValue();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class IntValue implements NodeValue {
|
||||||
|
@JsonValue
|
||||||
|
public BigInteger value;
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public IntValue(int value) {
|
||||||
|
this.value = BigInteger.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public IntValue(long value) {
|
||||||
|
this.value = BigInteger.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||||
|
public IntValue(BigInteger value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt() {
|
||||||
|
return value.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getBig() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong() {
|
||||||
|
return value.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return ValueType.INTEGER;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@Jacksonized
|
||||||
|
public class NodeLinkValue implements NodeValue {
|
||||||
|
@JsonProperty("#")
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return ValueType.LINK;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package io.github.chronosx88.JGUN.models.graph.values;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class StringValue implements NodeValue {
|
||||||
|
@JsonValue
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public StringValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getValueType() {
|
||||||
|
return ValueType.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,8 +3,8 @@ package io.github.chronosx88.JGUN.storage;
|
|||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.github.benmanes.caffeine.cache.Expiry;
|
import com.github.benmanes.caffeine.cache.Expiry;
|
||||||
import io.github.chronosx88.JGUN.models.DeferredNode;
|
import io.github.chronosx88.JGUN.models.graph.DeferredNode;
|
||||||
import io.github.chronosx88.JGUN.models.Node;
|
import io.github.chronosx88.JGUN.models.graph.Node;
|
||||||
import org.checkerframework.checker.index.qual.NonNegative;
|
import org.checkerframework.checker.index.qual.NonNegative;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package io.github.chronosx88.JGUN.storage;
|
package io.github.chronosx88.JGUN.storage;
|
||||||
|
|
||||||
import io.github.chronosx88.JGUN.HAM;
|
import io.github.chronosx88.JGUN.api.NodeChangeListener;
|
||||||
import io.github.chronosx88.JGUN.NodeChangeListener;
|
import io.github.chronosx88.JGUN.models.graph.*;
|
||||||
import io.github.chronosx88.JGUN.models.DeferredNode;
|
import io.github.chronosx88.JGUN.models.graph.NodeValue;
|
||||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
|
||||||
import io.github.chronosx88.JGUN.models.Node;
|
|
||||||
import io.github.chronosx88.JGUN.models.NodeMetadata;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -36,7 +33,7 @@ public abstract class Storage {
|
|||||||
*/
|
*/
|
||||||
public void mergeUpdate(MemoryGraph update) {
|
public void mergeUpdate(MemoryGraph update) {
|
||||||
long machine = System.currentTimeMillis();
|
long machine = System.currentTimeMillis();
|
||||||
MemoryGraph diff = MemoryGraph.builder().build();
|
MemoryGraph diff = new MemoryGraph();
|
||||||
for (Map.Entry<String, Node> entry : update.getNodes().entrySet()) {
|
for (Map.Entry<String, Node> entry : update.getNodes().entrySet()) {
|
||||||
Node node = entry.getValue();
|
Node node = entry.getValue();
|
||||||
Node diffNode = this.mergeNode(node, machine);
|
Node diffNode = this.mergeNode(node, machine);
|
||||||
@ -57,7 +54,7 @@ public abstract class Storage {
|
|||||||
changeListeners.get(diffEntry.getKey()).forEach((e) -> e.onChange(diffEntry.getValue()));
|
changeListeners.get(diffEntry.getKey()).forEach((e) -> e.onChange(diffEntry.getValue()));
|
||||||
}
|
}
|
||||||
if (mapChangeListeners.containsKey(diffEntry.getKey())) {
|
if (mapChangeListeners.containsKey(diffEntry.getKey())) {
|
||||||
for (Map.Entry<String, Object> nodeEntry : changedNode.getValues().entrySet()) {
|
for (Map.Entry<String, NodeValue> nodeEntry : changedNode.getValues().entrySet()) {
|
||||||
mapChangeListeners.get(nodeEntry.getKey()).forEach((e) -> e.onChange(nodeEntry.getKey(), nodeEntry.getValue()));
|
mapChangeListeners.get(nodeEntry.getKey()).forEach((e) -> e.onChange(nodeEntry.getKey(), nodeEntry.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +72,7 @@ public abstract class Storage {
|
|||||||
public Node mergeNode(Node incomingNode, long machineState) {
|
public Node mergeNode(Node incomingNode, long machineState) {
|
||||||
Node changedNode = null;
|
Node changedNode = null;
|
||||||
for (String key : incomingNode.getValues().keySet()) {
|
for (String key : incomingNode.getValues().keySet()) {
|
||||||
Object value = incomingNode.getValues().get(key);
|
NodeValue value = incomingNode.getValues().get(key);
|
||||||
long state = incomingNode.getMetadata().getStates().get(key);
|
long state = incomingNode.getMetadata().getStates().get(key);
|
||||||
long previousState = -1;
|
long previousState = -1;
|
||||||
Object currentValue = null;
|
Object currentValue = null;
|
||||||
|
@ -3,61 +3,72 @@ package io.github.chronosx88.JGUN;
|
|||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
||||||
|
import io.github.chronosx88.JGUN.api.graph.NodeBuilder;
|
||||||
|
import io.github.chronosx88.JGUN.api.graph.ArrayBuilder;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.MemoryGraph;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.values.IntValue;
|
||||||
|
import io.github.chronosx88.JGUN.models.graph.values.NodeLinkValue;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
class GraphNodeBuilderTest {
|
class GraphNodeBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void Test_sampleGraph1() {
|
void Test_sampleGraph1() throws JsonProcessingException {
|
||||||
var objectMapper = new ObjectMapper();
|
var objectMapper = new ObjectMapper();
|
||||||
objectMapper.registerModule(new Jdk8Module());
|
objectMapper.registerModule(new Jdk8Module());
|
||||||
|
|
||||||
var graph = new GraphNodeBuilder()
|
var graph = new NodeBuilder()
|
||||||
.add("firstName", "John")
|
.add("firstName", "John")
|
||||||
.add("lastName", "Smith")
|
.add("lastName", "Smith")
|
||||||
.add("age", 25)
|
.add("age", 25)
|
||||||
.add("address", new GraphNodeBuilder()
|
.add("address", new NodeBuilder()
|
||||||
.add("streetAddress", "21 2nd Street")
|
.add("streetAddress", "21 2nd Street")
|
||||||
.add("city", "New York")
|
.add("city", "New York")
|
||||||
.add("state", "NY")
|
.add("state", "NY")
|
||||||
.add("postalCode", "10021"))
|
.add("postalCode", "10021"))
|
||||||
.add("phoneNumber", new NodeArrayBuilder()
|
.add("phoneNumber", new ArrayBuilder()
|
||||||
.add(new GraphNodeBuilder()
|
.add(new NodeBuilder()
|
||||||
.add("type", "home")
|
.add("type", "home")
|
||||||
.add("number", "212 555-1234"))
|
.add("number", "212 555-1234"))
|
||||||
.add(new GraphNodeBuilder()
|
.add(new NodeBuilder()
|
||||||
.add("type", "fax")
|
.add("type", "fax")
|
||||||
.add("number", "646 555-4567")))
|
.add("number", "646 555-4567")))
|
||||||
|
.addNull("heh")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
String graphJSON = null;
|
String graphJSON1 = objectMapper.writeValueAsString(graph);
|
||||||
try {
|
System.out.println(graphJSON1);
|
||||||
graphJSON = objectMapper.writeValueAsString(graph);
|
|
||||||
} catch (JsonProcessingException e) {
|
graph = objectMapper.readValue(graphJSON1, MemoryGraph.class);
|
||||||
throw new RuntimeException(e);
|
String graphJSON2 = objectMapper.writeValueAsString(graph);
|
||||||
}
|
System.out.println(graphJSON2);
|
||||||
System.out.println(graphJSON);
|
|
||||||
|
assertEquals(graphJSON1, graphJSON2);
|
||||||
|
assertEquals(((IntValue) graph.nodes.get("__ROOT__").getValues().get("age")).getInt(), 25);
|
||||||
|
assertTrue(graph.nodes.get("__ROOT__").getValues().get("address") instanceof NodeLinkValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void Test_sampleGraph2() {
|
void Test_sampleGraph2() throws JsonProcessingException {
|
||||||
var objectMapper = new ObjectMapper();
|
var objectMapper = new ObjectMapper();
|
||||||
objectMapper.registerModule(new Jdk8Module());
|
objectMapper.registerModule(new Jdk8Module());
|
||||||
|
|
||||||
var graph = new GraphNodeBuilder()
|
var graph = new NodeBuilder()
|
||||||
.add("a", new NodeArrayBuilder()
|
.add("a", new ArrayBuilder()
|
||||||
.add(new GraphNodeBuilder()
|
.add(new NodeBuilder()
|
||||||
.add("b", new GraphNodeBuilder()
|
.add("b", new NodeBuilder()
|
||||||
.add("c", true)))
|
.add("c", true)))
|
||||||
.add(0))
|
.add(0))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
String graphJSON = null;
|
String graphJSON = objectMapper.writeValueAsString(graph);
|
||||||
try {
|
System.out.println(graphJSON);
|
||||||
|
|
||||||
|
graph = objectMapper.readValue(graphJSON, MemoryGraph.class);
|
||||||
graphJSON = objectMapper.writeValueAsString(graph);
|
graphJSON = objectMapper.writeValueAsString(graph);
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
System.out.println(graphJSON);
|
System.out.println(graphJSON);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user