mirror of
https://github.com/ChronosX88/JGUN.git
synced 2024-11-09 16:51:02 +00:00
Reimplement .put() API
This commit is contained in:
parent
87da965616
commit
b83e3ee14e
@ -20,6 +20,11 @@ dependencies {
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3'
|
||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3'
|
||||
implementation 'com.github.ben-manes.caffeine:jcache:3.1.5'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
|
||||
compileOnly 'org.projectlombok:lombok:1.18.30'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.30'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
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.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GraphNodeBuilder {
|
||||
private final MemoryGraph graph;
|
||||
private final Node rootNode;
|
||||
protected static final String ROOT_NODE = "__ROOT__";
|
||||
|
||||
public GraphNodeBuilder() {
|
||||
this.graph = MemoryGraph.builder().build();
|
||||
this.rootNode = Node.builder()
|
||||
.metadata(NodeMetadata.builder()
|
||||
.nodeID(null)
|
||||
.build())
|
||||
.build();
|
||||
graph.nodes.put(ROOT_NODE, this.rootNode);
|
||||
}
|
||||
|
||||
private GraphNodeBuilder addScalar(String name, Object 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 GraphNodeBuilder add(String name, BigInteger value) {
|
||||
return addScalar(name, value);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, BigDecimal value) {
|
||||
return addScalar(name, value);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, int value) {
|
||||
return addScalar(name, value);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, long value) {
|
||||
return addScalar(name, value);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, double value) {
|
||||
return addScalar(name, value);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, boolean value) {
|
||||
return addScalar(name, value);
|
||||
|
||||
}
|
||||
|
||||
public GraphNodeBuilder addNull(String name) {
|
||||
return addScalar(name, null);
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, GraphNodeBuilder builder) {
|
||||
String newNodeID = UUID.randomUUID().toString();
|
||||
rootNode.values.put(name, NodeLink.builder()
|
||||
.link(newNodeID)
|
||||
.build());
|
||||
MemoryGraph innerGraph = builder.build();
|
||||
innerGraph.nodes.get(ROOT_NODE).getMetadata().setNodeID(newNodeID);
|
||||
innerGraph.nodes.put(newNodeID, innerGraph.nodes.get(ROOT_NODE));
|
||||
innerGraph.nodes.remove(ROOT_NODE);
|
||||
graph.nodes.putAll(innerGraph.nodes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GraphNodeBuilder add(String name, NodeArrayBuilder builder) {
|
||||
MemoryGraph innerGraph = builder.build();
|
||||
//noinspection unchecked
|
||||
var innerArray = (List<Object>) innerGraph.nodes.get(ROOT_NODE).values.get(NodeArrayBuilder.ARRAY_FIELD);
|
||||
rootNode.values.put(name, innerArray);
|
||||
rootNode.getMetadata().getStates().put(name, innerGraph
|
||||
.nodes
|
||||
.get(ROOT_NODE)
|
||||
.getMetadata()
|
||||
.getStates()
|
||||
.get(NodeArrayBuilder.ARRAY_FIELD));
|
||||
innerGraph.nodes.remove(ROOT_NODE);
|
||||
graph.nodes.putAll(innerGraph.nodes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MemoryGraph build() {
|
||||
return this.graph;
|
||||
}
|
||||
}
|
@ -1,25 +1,34 @@
|
||||
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.futures.FuturePut;
|
||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
||||
import io.github.chronosx88.JGUN.models.requests.PutRequest;
|
||||
import io.github.chronosx88.JGUN.nodes.GunClient;
|
||||
import io.github.chronosx88.JGUN.storage.Storage;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Gun {
|
||||
private GunClient gunClient;
|
||||
private GunClient peer;
|
||||
private final Storage storage;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final Executor executorService = Executors.newCachedThreadPool();
|
||||
|
||||
public Gun(InetAddress address, int port, Storage storage) {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new Jdk8Module());
|
||||
this.storage = storage;
|
||||
try {
|
||||
this.gunClient = new GunClient(address, port, storage);
|
||||
this.gunClient.connectBlocking();
|
||||
this.peer = new GunClient(address, port, storage);
|
||||
this.peer.connectBlocking();
|
||||
} catch (URISyntaxException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,11 +46,27 @@ public class Gun {
|
||||
storage.addMapChangeListener(nodeID, listener);
|
||||
}
|
||||
|
||||
protected void sendPutRequest(MemoryGraph data) {
|
||||
// TODO
|
||||
protected FuturePut sendPutRequest(MemoryGraph data) {
|
||||
String reqID = Dup.random();
|
||||
executorService.execute(() -> {
|
||||
storage.mergeUpdate(data);
|
||||
var request = PutRequest.builder()
|
||||
.id(reqID)
|
||||
.graph(data)
|
||||
.build();
|
||||
String encodedRequest;
|
||||
try {
|
||||
encodedRequest = this.objectMapper.writeValueAsString(request);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
peer.emit(encodedRequest);
|
||||
});
|
||||
return new FuturePut(reqID);
|
||||
}
|
||||
|
||||
protected void sendGetRequest(String key, String field) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ 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.futures.FutureGet;
|
||||
import io.github.chronosx88.JGUN.futures.FuturePut;
|
||||
import io.github.chronosx88.JGUN.futures.GetResult;
|
||||
@ -31,12 +32,15 @@ public class NetworkHandler {
|
||||
private final Storage storage;
|
||||
private final Dup dup;
|
||||
private final Executor executorService = Executors.newCachedThreadPool();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public NetworkHandler(Storage storage, Peer peer, Dup dup) {
|
||||
this.storage = storage;
|
||||
this.peer = peer;
|
||||
this.dup = dup;
|
||||
|
||||
this.objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new Jdk8Module());
|
||||
}
|
||||
|
||||
public void addPendingGetRequest(FutureGet future) {
|
||||
|
@ -0,0 +1,88 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -2,15 +2,15 @@ package io.github.chronosx88.JGUN;
|
||||
|
||||
import io.github.chronosx88.JGUN.futures.FutureGet;
|
||||
import io.github.chronosx88.JGUN.futures.FuturePut;
|
||||
import io.github.chronosx88.JGUN.nodes.GunClient;
|
||||
import io.github.chronosx88.JGUN.models.MemoryGraph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class PathReference {
|
||||
private final ArrayList<String> path = new ArrayList<>();
|
||||
private final List<String> path = new ArrayList<>();
|
||||
|
||||
private Gun gun;
|
||||
private final Gun gun;
|
||||
|
||||
public PathReference(Gun gun) {
|
||||
this.gun = gun;
|
||||
@ -21,14 +21,13 @@ public class PathReference {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FutureGet getData() {
|
||||
public FutureGet once() {
|
||||
// TODO
|
||||
return null;
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
public FuturePut put(HashMap<String, Object> data) {
|
||||
// TODO
|
||||
return null;
|
||||
public FuturePut put(MemoryGraph graph) {
|
||||
return gun.sendPutRequest(graph);
|
||||
}
|
||||
|
||||
public void on(NodeChangeListener changeListener) {
|
||||
|
@ -1,10 +1,8 @@
|
||||
package io.github.chronosx88.JGUN.futures;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Getter
|
||||
public class BaseCompletableFuture<T> extends CompletableFuture<T> {
|
||||
@ -14,24 +12,4 @@ public class BaseCompletableFuture<T> extends CompletableFuture<T> {
|
||||
super();
|
||||
futureID = id;
|
||||
}
|
||||
|
||||
public void addListener(final BaseFutureListener<T> listener) {
|
||||
this.whenCompleteAsync((t, throwable) -> {
|
||||
if(throwable == null) {
|
||||
listener.onComplete(t);
|
||||
} else {
|
||||
listener.onError(t, throwable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T await() {
|
||||
T t = null;
|
||||
try {
|
||||
t = super.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
package io.github.chronosx88.JGUN.futures;
|
||||
|
||||
public interface BaseFutureListener<T> {
|
||||
void onComplete(T result);
|
||||
void onError(T result, Throwable exception);
|
||||
}
|
14
src/main/java/io/github/chronosx88/JGUN/models/NodeLink.java
Normal file
14
src/main/java/io/github/chronosx88/JGUN/models/NodeLink.java
Normal file
@ -0,0 +1,14 @@
|
||||
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;
|
||||
}
|
@ -6,6 +6,7 @@ import lombok.Data;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@ -14,7 +15,7 @@ import java.util.Map;
|
||||
public class NodeMetadata {
|
||||
@JsonProperty(">")
|
||||
@Builder.Default
|
||||
private Map<String, Long> states = new HashMap<>(); // field -> state
|
||||
private Map<String, Long> states = new LinkedHashMap<>(); // field -> state
|
||||
|
||||
@JsonProperty("#")
|
||||
private String nodeID;
|
||||
|
@ -5,10 +5,11 @@ import io.github.chronosx88.JGUN.models.BaseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@SuperBuilder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Jacksonized
|
||||
public class GetRequest extends BaseMessage {
|
||||
|
@ -7,11 +7,12 @@ import io.github.chronosx88.JGUN.models.Node;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
@Data
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@SuperBuilder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PutRequest extends BaseMessage {
|
||||
@JsonProperty("put")
|
||||
|
@ -2,6 +2,8 @@ package io.github.chronosx88.JGUN.nodes;
|
||||
|
||||
import io.github.chronosx88.JGUN.Dup;
|
||||
import io.github.chronosx88.JGUN.NetworkHandler;
|
||||
import io.github.chronosx88.JGUN.futures.FutureGet;
|
||||
import io.github.chronosx88.JGUN.futures.FuturePut;
|
||||
import io.github.chronosx88.JGUN.storage.Storage;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
@ -44,4 +46,19 @@ public class GunClient extends WebSocketClient implements Peer {
|
||||
public void emit(String data) {
|
||||
this.send(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPendingPutRequest(FuturePut futurePut) {
|
||||
this.handler.addPendingPutRequest(futurePut);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPendingGetRequest(FutureGet futureGet) {
|
||||
this.handler.addPendingGetRequest(futureGet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.connect();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
package io.github.chronosx88.JGUN.nodes;
|
||||
|
||||
public class GunNodeBuilder {
|
||||
}
|
@ -1,5 +1,12 @@
|
||||
package io.github.chronosx88.JGUN.nodes;
|
||||
|
||||
import io.github.chronosx88.JGUN.futures.BaseCompletableFuture;
|
||||
import io.github.chronosx88.JGUN.futures.FutureGet;
|
||||
import io.github.chronosx88.JGUN.futures.FuturePut;
|
||||
|
||||
public interface Peer {
|
||||
void emit(String data);
|
||||
void addPendingPutRequest(FuturePut futurePut);
|
||||
void addPendingGetRequest(FutureGet futureGet);
|
||||
void start();
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public abstract class Storage {
|
||||
*/
|
||||
public void mergeUpdate(MemoryGraph update) {
|
||||
long machine = System.currentTimeMillis();
|
||||
MemoryGraph diff = new MemoryGraph();
|
||||
MemoryGraph diff = MemoryGraph.builder().build();
|
||||
for (Map.Entry<String, Node> entry : update.getNodes().entrySet()) {
|
||||
Node node = entry.getValue();
|
||||
Node diffNode = this.mergeNode(node, machine);
|
||||
|
@ -0,0 +1,63 @@
|
||||
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 org.junit.jupiter.api.Test;
|
||||
|
||||
class GraphNodeBuilderTest {
|
||||
|
||||
@Test
|
||||
void Test_sampleGraph1() {
|
||||
var objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new Jdk8Module());
|
||||
|
||||
var graph = new GraphNodeBuilder()
|
||||
.add("firstName", "John")
|
||||
.add("lastName", "Smith")
|
||||
.add("age", 25)
|
||||
.add("address", new GraphNodeBuilder()
|
||||
.add("streetAddress", "21 2nd Street")
|
||||
.add("city", "New York")
|
||||
.add("state", "NY")
|
||||
.add("postalCode", "10021"))
|
||||
.add("phoneNumber", new NodeArrayBuilder()
|
||||
.add(new GraphNodeBuilder()
|
||||
.add("type", "home")
|
||||
.add("number", "212 555-1234"))
|
||||
.add(new GraphNodeBuilder()
|
||||
.add("type", "fax")
|
||||
.add("number", "646 555-4567")))
|
||||
.build();
|
||||
|
||||
String graphJSON = null;
|
||||
try {
|
||||
graphJSON = objectMapper.writeValueAsString(graph);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println(graphJSON);
|
||||
}
|
||||
|
||||
@Test
|
||||
void Test_sampleGraph2() {
|
||||
var objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new Jdk8Module());
|
||||
|
||||
var graph = new GraphNodeBuilder()
|
||||
.add("a", new NodeArrayBuilder()
|
||||
.add(new GraphNodeBuilder()
|
||||
.add("b", new GraphNodeBuilder()
|
||||
.add("c", true)))
|
||||
.add(0))
|
||||
.build();
|
||||
|
||||
String graphJSON = null;
|
||||
try {
|
||||
graphJSON = objectMapper.writeValueAsString(graph);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println(graphJSON);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user