Fix merging arrays

This commit is contained in:
ChronosX88 2023-12-12 00:52:38 +03:00
parent 096f3c4387
commit 6a5eab54cb
9 changed files with 54 additions and 22 deletions

View File

@ -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'

View File

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

View File

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

View File

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

View File

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

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.List;
@Getter
@NoArgsConstructor
public class ArrayValue implements NodeValue {
@JsonValue
private List<NodeValue> 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;

View File

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

View File

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

View File

@ -45,10 +45,11 @@ public abstract class Storage {
if (!diff.nodes.isEmpty()) {
for (Map.Entry<String, Node> 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<String, NodeValue> 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);
}