Make node values type-safe

This commit is contained in:
ChronosX88 2023-11-16 23:17:38 +03:00
parent b83e3ee14e
commit 45e013098f
Signed by: ChronosXYZ
GPG Key ID: 52A90DE5862D8321
21 changed files with 433 additions and 189 deletions

View File

@ -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;
}
}

View File

@ -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
public interface NodeChangeListener {

View File

@ -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;
}
}

View File

@ -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.Node;
import io.github.chronosx88.JGUN.models.NodeLink;
import io.github.chronosx88.JGUN.models.NodeMetadata;
import io.github.chronosx88.JGUN.models.graph.*;
import io.github.chronosx88.JGUN.models.graph.values.*;
import io.github.chronosx88.JGUN.models.graph.NodeValue;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.UUID;
public class GraphNodeBuilder {
public class NodeBuilder {
private final MemoryGraph graph;
private final Node rootNode;
protected static final String ROOT_NODE = "__ROOT__";
public GraphNodeBuilder() {
this.graph = MemoryGraph.builder().build();
public NodeBuilder() {
this.graph = new MemoryGraph();
this.rootNode = Node.builder()
.metadata(NodeMetadata.builder()
.nodeID(null)
@ -25,48 +24,47 @@ public class GraphNodeBuilder {
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.getMetadata().getStates().put(name, System.currentTimeMillis());
return this;
}
public GraphNodeBuilder add(String name, String value) {
return addScalar(name, value);
public NodeBuilder add(String name, String value) {
return addScalar(name, new StringValue(value));
}
public GraphNodeBuilder add(String name, BigInteger value) {
return addScalar(name, value);
public NodeBuilder add(String name, BigInteger value) {
return addScalar(name, new IntValue(value));
}
public GraphNodeBuilder add(String name, BigDecimal value) {
return addScalar(name, value);
public NodeBuilder add(String name, BigDecimal value) {
return addScalar(name, new DecimalValue(value));
}
public GraphNodeBuilder add(String name, int value) {
return addScalar(name, value);
public NodeBuilder add(String name, int value) {
return addScalar(name, new IntValue(value));
}
public GraphNodeBuilder add(String name, long value) {
return addScalar(name, value);
public NodeBuilder add(String name, long value) {
return addScalar(name, new IntValue(value));
}
public GraphNodeBuilder add(String name, double value) {
return addScalar(name, value);
public NodeBuilder add(String name, double value) {
return addScalar(name, new DecimalValue(value));
}
public GraphNodeBuilder add(String name, boolean value) {
return addScalar(name, value);
public NodeBuilder add(String name, boolean value) {
return addScalar(name, new BooleanValue(value));
}
public GraphNodeBuilder addNull(String name) {
public NodeBuilder addNull(String name) {
return addScalar(name, null);
}
public GraphNodeBuilder add(String name, GraphNodeBuilder builder) {
public NodeBuilder add(String name, NodeBuilder builder) {
String newNodeID = UUID.randomUUID().toString();
rootNode.values.put(name, NodeLink.builder()
rootNode.values.put(name, NodeLinkValue.builder()
.link(newNodeID)
.build());
MemoryGraph innerGraph = builder.build();
@ -77,17 +75,16 @@ public class GraphNodeBuilder {
return this;
}
public GraphNodeBuilder add(String name, NodeArrayBuilder builder) {
public NodeBuilder add(String name, ArrayBuilder builder) {
MemoryGraph innerGraph = builder.build();
//noinspection unchecked
var innerArray = (List<Object>) innerGraph.nodes.get(ROOT_NODE).values.get(NodeArrayBuilder.ARRAY_FIELD);
var innerArray = (NodeValue) innerGraph.nodes.get(ROOT_NODE).values.get(ArrayBuilder.ARRAY_FIELD);
rootNode.values.put(name, innerArray);
rootNode.getMetadata().getStates().put(name, innerGraph
.nodes
.get(ROOT_NODE)
.getMetadata()
.getStates()
.get(NodeArrayBuilder.ARRAY_FIELD));
.get(ArrayBuilder.ARRAY_FIELD));
innerGraph.nodes.remove(ROOT_NODE);
graph.nodes.putAll(innerGraph.nodes);
return this;

View File

@ -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;
}

View File

@ -1,8 +1,7 @@
package io.github.chronosx88.JGUN.models.acks;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.chronosx88.JGUN.models.MemoryGraph;
import lombok.Builder;
import io.github.chronosx88.JGUN.models.graph.MemoryGraph;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.SuperBuilder;

View File

@ -1,6 +1,4 @@
package io.github.chronosx88.JGUN.models;
import lombok.Getter;
package io.github.chronosx88.JGUN.models.graph;
import java.util.Map;
import java.util.concurrent.Delayed;
@ -9,7 +7,7 @@ import java.util.concurrent.TimeUnit;
public class DeferredNode extends Node implements Delayed {
private long deferredUntil = 0;
DeferredNode(NodeMetadata metadata, Map<String, Object> values) {
DeferredNode(NodeMetadata metadata, Map<String, NodeValue> values) {
super(metadata, values);
}

View File

@ -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.JsonAnySetter;
@ -11,12 +11,9 @@ import java.util.LinkedHashMap;
import java.util.Map;
@Data
@Builder
@Jacksonized
public class MemoryGraph {
@JsonIgnore
@Builder.Default
public final Map<String, Node> nodes = new LinkedHashMap<>();
public Map<String, Node> nodes = new LinkedHashMap<>();
@JsonAnyGetter
public Map<String, Node> nodes() {

View File

@ -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.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.jackson.Jacksonized;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Data
@Jacksonized
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Node {
@JsonProperty("_")
private NodeMetadata metadata;
@Builder.Default
private final NodeMetadata metadata = new NodeMetadata(new HashMap<>(), null);
@JsonIgnore
@Builder.Default
public Map<String, Object> values = new LinkedHashMap<>(); // Data
public final Map<String, NodeValue> values = new LinkedHashMap<>(); // Data
@JsonAnyGetter
public Map<String, Object> getValues() {
public Map<String, NodeValue> getValues() {
return values;
}
@JsonAnySetter
public void allSetter(String key, String value) {
public void allSetter(String key, NodeValue value) {
values.put(key, value);
}
}

View File

@ -1,4 +1,4 @@
package io.github.chronosx88.JGUN.models;
package io.github.chronosx88.JGUN.models.graph;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;

View File

@ -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();
}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -3,8 +3,8 @@ package io.github.chronosx88.JGUN.storage;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Expiry;
import io.github.chronosx88.JGUN.models.DeferredNode;
import io.github.chronosx88.JGUN.models.Node;
import io.github.chronosx88.JGUN.models.graph.DeferredNode;
import io.github.chronosx88.JGUN.models.graph.Node;
import org.checkerframework.checker.index.qual.NonNegative;
import java.util.Collection;

View File

@ -1,11 +1,8 @@
package io.github.chronosx88.JGUN.storage;
import io.github.chronosx88.JGUN.HAM;
import io.github.chronosx88.JGUN.NodeChangeListener;
import io.github.chronosx88.JGUN.models.DeferredNode;
import io.github.chronosx88.JGUN.models.MemoryGraph;
import io.github.chronosx88.JGUN.models.Node;
import io.github.chronosx88.JGUN.models.NodeMetadata;
import io.github.chronosx88.JGUN.api.NodeChangeListener;
import io.github.chronosx88.JGUN.models.graph.*;
import io.github.chronosx88.JGUN.models.graph.NodeValue;
import java.util.*;
@ -36,7 +33,7 @@ public abstract class Storage {
*/
public void mergeUpdate(MemoryGraph update) {
long machine = System.currentTimeMillis();
MemoryGraph diff = MemoryGraph.builder().build();
MemoryGraph diff = new MemoryGraph();
for (Map.Entry<String, Node> entry : update.getNodes().entrySet()) {
Node node = entry.getValue();
Node diffNode = this.mergeNode(node, machine);
@ -57,7 +54,7 @@ public abstract class Storage {
changeListeners.get(diffEntry.getKey()).forEach((e) -> e.onChange(diffEntry.getValue()));
}
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()));
}
}
@ -75,7 +72,7 @@ public abstract class Storage {
public Node mergeNode(Node incomingNode, long machineState) {
Node changedNode = null;
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 previousState = -1;
Object currentValue = null;

View File

@ -3,61 +3,72 @@ package io.github.chronosx88.JGUN;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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 static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class GraphNodeBuilderTest {
@Test
void Test_sampleGraph1() {
void Test_sampleGraph1() throws JsonProcessingException {
var objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
var graph = new GraphNodeBuilder()
var graph = new NodeBuilder()
.add("firstName", "John")
.add("lastName", "Smith")
.add("age", 25)
.add("address", new GraphNodeBuilder()
.add("address", new NodeBuilder()
.add("streetAddress", "21 2nd Street")
.add("city", "New York")
.add("state", "NY")
.add("postalCode", "10021"))
.add("phoneNumber", new NodeArrayBuilder()
.add(new GraphNodeBuilder()
.add("phoneNumber", new ArrayBuilder()
.add(new NodeBuilder()
.add("type", "home")
.add("number", "212 555-1234"))
.add(new GraphNodeBuilder()
.add(new NodeBuilder()
.add("type", "fax")
.add("number", "646 555-4567")))
.addNull("heh")
.build();
String graphJSON = null;
try {
graphJSON = objectMapper.writeValueAsString(graph);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
System.out.println(graphJSON);
String graphJSON1 = objectMapper.writeValueAsString(graph);
System.out.println(graphJSON1);
graph = objectMapper.readValue(graphJSON1, MemoryGraph.class);
String graphJSON2 = objectMapper.writeValueAsString(graph);
System.out.println(graphJSON2);
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
void Test_sampleGraph2() {
void Test_sampleGraph2() throws JsonProcessingException {
var objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
var graph = new GraphNodeBuilder()
.add("a", new NodeArrayBuilder()
.add(new GraphNodeBuilder()
.add("b", new GraphNodeBuilder()
var graph = new NodeBuilder()
.add("a", new ArrayBuilder()
.add(new NodeBuilder()
.add("b", new NodeBuilder()
.add("c", true)))
.add(0))
.build();
String graphJSON = null;
try {
String graphJSON = objectMapper.writeValueAsString(graph);
System.out.println(graphJSON);
graph = objectMapper.readValue(graphJSON, MemoryGraph.class);
graphJSON = objectMapper.writeValueAsString(graph);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
System.out.println(graphJSON);
}
}