From 6a5eab54cb494b82854c266fbaa0013b41ea8b85 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 12 Dec 2023 00:52:38 +0300 Subject: [PATCH] Fix merging arrays --- build.gradle | 5 +++-- .../chronosxyz/JGUN/examples/chat/Main.java | 20 +++++++++++++++---- .../JGUN/api/NodeChangeListener.java | 3 ++- .../chronosx88/JGUN/api/PathReference.java | 5 +++++ .../chronosx88/JGUN/models/graph/Node.java | 10 ++++++++++ .../JGUN/models/graph/values/ArrayValue.java | 5 ++++- .../github/chronosx88/JGUN/storage/HAM.java | 6 +----- .../JGUN/storage/MemoryStorage.java | 9 +++++++++ .../chronosx88/JGUN/storage/Storage.java | 13 ++++-------- 9 files changed, 54 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index a730ba4..f826fd1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'java' + id 'java-library' } group 'io.github.chronosx88' @@ -15,7 +15,8 @@ repositories { } dependencies { - implementation 'org.java-websocket:Java-WebSocket:1.5.4' + api 'org.java-websocket:Java-WebSocket:1.5.4' + compileOnly 'org.java-websocket:Java-WebSocket:1.5.4' implementation 'net.sourceforge.streamsupport:android-retrofuture:1.7.0' implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3' diff --git a/examples/chat/src/main/java/io/github/chronosxyz/JGUN/examples/chat/Main.java b/examples/chat/src/main/java/io/github/chronosxyz/JGUN/examples/chat/Main.java index 5cd8aa6..5f311d8 100644 --- a/examples/chat/src/main/java/io/github/chronosxyz/JGUN/examples/chat/Main.java +++ b/examples/chat/src/main/java/io/github/chronosxyz/JGUN/examples/chat/Main.java @@ -1,22 +1,30 @@ package io.github.chronosxyz.JGUN.examples.chat; +import io.github.chronosx88.JGUN.api.Gun; +import io.github.chronosx88.JGUN.network.NetworkNode; +import io.github.chronosx88.JGUN.storage.MemoryStorage; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; +import java.net.InetAddress; +import java.net.URISyntaxException; +import java.net.UnknownHostException; + public class Main extends Application { @Override public void start(Stage stage) throws Exception { - Parent root = FXMLLoader.load(getClass().getResource("scene.fxml")); + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("scene.fxml")); + Parent root = fxmlLoader.load(); + FXMLController controller = fxmlLoader.getController(); + controller.setGunInstance(getGun()); Scene scene = new Scene(root); -// scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm()); - - stage.setTitle("JavaFX and Gradle"); + stage.setTitle("Gun Chat"); stage.setScene(scene); stage.show(); } @@ -25,4 +33,8 @@ public class Main extends Application { launch(args); } + private static Gun getGun() throws UnknownHostException, URISyntaxException, InterruptedException { + var storage = new MemoryStorage(); + return new Gun(storage, new NetworkNode(InetAddress.getLocalHost(), 5054, storage)); + } } \ No newline at end of file diff --git a/src/main/java/io/github/chronosx88/JGUN/api/NodeChangeListener.java b/src/main/java/io/github/chronosx88/JGUN/api/NodeChangeListener.java index 92ba625..6c4df9d 100644 --- a/src/main/java/io/github/chronosx88/JGUN/api/NodeChangeListener.java +++ b/src/main/java/io/github/chronosx88/JGUN/api/NodeChangeListener.java @@ -1,12 +1,13 @@ package io.github.chronosx88.JGUN.api; import io.github.chronosx88.JGUN.models.graph.Node; +import io.github.chronosx88.JGUN.models.graph.NodeValue; @FunctionalInterface public interface NodeChangeListener { void onChange(Node node); interface Map { - void onChange(String key, Object value); + void onChange(String key, NodeValue value); } } diff --git a/src/main/java/io/github/chronosx88/JGUN/api/PathReference.java b/src/main/java/io/github/chronosx88/JGUN/api/PathReference.java index 8c66c7b..fc1e809 100644 --- a/src/main/java/io/github/chronosx88/JGUN/api/PathReference.java +++ b/src/main/java/io/github/chronosx88/JGUN/api/PathReference.java @@ -109,6 +109,7 @@ public class PathReference { throw new RuntimeException(e); } storageManager.addChangeListener(pathData.get(pathData.size()-1), changeListener); + this.once().thenAccept(res -> changeListener.onChange(res.getData())); }); } @@ -121,6 +122,10 @@ public class PathReference { throw new RuntimeException(e); } storageManager.addMapChangeListener(pathData.get(pathData.size()-1), mapListener); + this.once().thenAccept(res -> { + var node = res.getData(); + node.getValues().forEach(mapListener::onChange); + }); }); } diff --git a/src/main/java/io/github/chronosx88/JGUN/models/graph/Node.java b/src/main/java/io/github/chronosx88/JGUN/models/graph/Node.java index 90511a2..c761bdc 100644 --- a/src/main/java/io/github/chronosx88/JGUN/models/graph/Node.java +++ b/src/main/java/io/github/chronosx88/JGUN/models/graph/Node.java @@ -35,4 +35,14 @@ public class Node { public void allSetter(String key, NodeValue value) { values.put(key, value); } + + @Override + public Node clone() { + return Node.builder() + .metadata(NodeMetadata.builder() + .nodeID(new String(this.getMetadata().getNodeID())) + .states(new LinkedHashMap<>(this.getMetadata().getStates())).build()) + .values(new LinkedHashMap<>(this.getValues())) + .build(); + } } \ No newline at end of file diff --git a/src/main/java/io/github/chronosx88/JGUN/models/graph/values/ArrayValue.java b/src/main/java/io/github/chronosx88/JGUN/models/graph/values/ArrayValue.java index 3ba2f9e..6fc8a85 100644 --- a/src/main/java/io/github/chronosx88/JGUN/models/graph/values/ArrayValue.java +++ b/src/main/java/io/github/chronosx88/JGUN/models/graph/values/ArrayValue.java @@ -10,7 +10,6 @@ import java.util.ArrayList; import java.util.List; @Getter -@NoArgsConstructor public class ArrayValue implements NodeValue { @JsonValue private List value = new ArrayList<>(); @@ -24,6 +23,10 @@ public class ArrayValue implements NodeValue { this.value = value; } + public ArrayValue() { + this.value = new ArrayList<>(); + } + @Override public ValueType getValueType() { return ValueType.ARRAY; diff --git a/src/main/java/io/github/chronosx88/JGUN/storage/HAM.java b/src/main/java/io/github/chronosx88/JGUN/storage/HAM.java index e615f27..424ed59 100644 --- a/src/main/java/io/github/chronosx88/JGUN/storage/HAM.java +++ b/src/main/java/io/github/chronosx88/JGUN/storage/HAM.java @@ -31,11 +31,7 @@ public class HAM { result.incoming = true; return result; } else { // if incoming state and current state is the same - if (incomingValue.equals(currentValue)) { - result.current = true; - return result; - } - result.incoming = true; // always update local value with incoming value if state is the same + result.incoming = false; // don't update local value with incoming value if state is the same return result; } } diff --git a/src/main/java/io/github/chronosx88/JGUN/storage/MemoryStorage.java b/src/main/java/io/github/chronosx88/JGUN/storage/MemoryStorage.java index 7b14c0c..2b8b957 100644 --- a/src/main/java/io/github/chronosx88/JGUN/storage/MemoryStorage.java +++ b/src/main/java/io/github/chronosx88/JGUN/storage/MemoryStorage.java @@ -7,6 +7,7 @@ import io.github.chronosx88.JGUN.models.graph.DeferredNode; import io.github.chronosx88.JGUN.models.graph.Node; import io.github.chronosx88.JGUN.models.graph.NodeMetadata; import io.github.chronosx88.JGUN.models.graph.NodeValue; +import io.github.chronosx88.JGUN.models.graph.values.ArrayValue; import org.checkerframework.checker.index.qual.NonNegative; import java.util.Collection; @@ -62,6 +63,14 @@ public class MemoryStorage extends Storage { @Override protected void updateNode(Node newNode) { Node currentNode = nodes.get(newNode.getMetadata().getNodeID()); + newNode.values.forEach((k, v) -> { + if (v.getValueType() != NodeValue.ValueType.ARRAY) return; + var currentValue = currentNode.getValues().get(k); + if (currentValue.getValueType() != NodeValue.ValueType.ARRAY) return; + ArrayValue currentArrayValue = (ArrayValue) currentValue; + currentArrayValue.getValue().addAll(((ArrayValue) v).getValue()); + newNode.getValues().put(k, currentArrayValue); + }); currentNode.values.putAll(newNode.values); currentNode.getMetadata().getStates().putAll(newNode.getMetadata().getStates()); } diff --git a/src/main/java/io/github/chronosx88/JGUN/storage/Storage.java b/src/main/java/io/github/chronosx88/JGUN/storage/Storage.java index c9c6a37..27f7b91 100644 --- a/src/main/java/io/github/chronosx88/JGUN/storage/Storage.java +++ b/src/main/java/io/github/chronosx88/JGUN/storage/Storage.java @@ -45,10 +45,11 @@ public abstract class Storage { if (!diff.nodes.isEmpty()) { for (Map.Entry diffEntry : diff.getNodes().entrySet()) { Node changedNode = diffEntry.getValue(); + var changedNodeClone = changedNode.clone(); if (!this.hasNode(changedNode.getMetadata().getNodeID())) { - this.addNode(changedNode.getMetadata().getNodeID(), changedNode); + this.addNode(changedNodeClone.getMetadata().getNodeID(), changedNodeClone); } else { - this.updateNode(changedNode); + this.updateNode(changedNodeClone); } if (changeListeners.containsKey(diffEntry.getKey())) { @@ -56,7 +57,7 @@ public abstract class Storage { } if (mapChangeListeners.containsKey(diffEntry.getKey())) { for (Map.Entry nodeEntry : changedNode.getValues().entrySet()) { - mapChangeListeners.get(nodeEntry.getKey()).forEach((e) -> e.onChange(nodeEntry.getKey(), nodeEntry.getValue())); + mapChangeListeners.get(diffEntry.getKey()).forEach((e) -> e.onChange(nodeEntry.getKey(), nodeEntry.getValue())); } } } @@ -104,12 +105,6 @@ public abstract class Storage { .build(); } - if (value.getValueType() == NodeValue.ValueType.ARRAY) { - // handle appending element to array instead of rewriting - ArrayValue array = (ArrayValue) changedNode.getValues().getOrDefault(key, new ArrayValue(List.of())); - array.getValue().addAll(((ArrayValue) value).getValue()); - value = array; - } changedNode.getValues().put(key, value); changedNode.getMetadata().getStates().put(key, state); }