Skip to content

Commit

Permalink
implement config nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Schuh committed Jan 2, 2023
1 parent d50639d commit 5f14ba4
Show file tree
Hide file tree
Showing 12 changed files with 235 additions and 78 deletions.
56 changes: 43 additions & 13 deletions src/main/java/io/github/robbilie/nodegreen/Flow.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,62 @@
import java.util.*;

public class Flow {
public static Flow create(FlowConfig global, ObjectNode config) {
return new Flow(global, config);
public static Flow create(Flow parent, ObjectNode global, ObjectNode config) {
return new Flow(parent, global, config);
}
public static Flow create(ObjectNode global) {
return new Flow(global);
}

Flow parent;

FlowConfig global;
ObjectNode global;
ObjectNode flow;
Map<String, INode> activeNodes = new HashMap<>();
public Flow(FlowConfig global, ObjectNode flow) {

Boolean isGlobalFlow;
public Flow(ObjectNode global) {
this.isGlobalFlow = true;
this.global = global;
this.flow = global;
}
public Flow(Flow parent, ObjectNode global, ObjectNode flow) {
this.isGlobalFlow = false;
this.global = global;
this.flow = flow;
this.parent = parent;
}

public void start() {
for (Iterator<String> it = this.flow.get("nodes").fieldNames(); it.hasNext(); ) {
String id = it.next();
if (this.flow.get("nodes").has(id)) {
JsonNode node = this.flow.get("nodes").get(id);
if (!node.has("d")) {
if (!node.has("subflow")) {
if (this.flow.has("configs")) {
for (Iterator<String> it = this.flow.get("configs").fieldNames(); it.hasNext(); ) {
String id = it.next();
if (this.flow.get("configs").has(id)) {
JsonNode node = this.flow.get("configs").get(id);
if (!node.has("d")) {
if (!this.activeNodes.containsKey(id)) {
INode newNode = FlowUtil.createNode(this, node);
this.activeNodes.put(id, newNode);
}
}
}
}

}
if (this.flow.has("nodes")) {
for (Iterator<String> it = this.flow.get("nodes").fieldNames(); it.hasNext(); ) {
String id = it.next();
if (this.flow.get("nodes").has(id)) {
JsonNode node = this.flow.get("nodes").get(id);
if (!node.has("d")) {
if (!node.has("subflow")) {
if (!this.activeNodes.containsKey(id)) {
INode newNode = FlowUtil.createNode(this, node);
this.activeNodes.put(id, newNode);
}
}
}
}
}
}
}

Expand Down Expand Up @@ -62,7 +91,7 @@ public static void handlePreDeliver(Flow flow, SendEvent sendEvent) {
}
}

INode getNode(String id) {
public INode getNode(String id) {
if (id == null) {
return null;
}
Expand All @@ -75,8 +104,9 @@ INode getNode(String id) {
return this.activeNodes.get(id);
} else if (this.activeNodes.containsKey(id)) {
return this.activeNodes.get(id);
} else {
return this.parent.getNode(id);
}
return null;
}

public void stop() {
Expand Down
17 changes: 0 additions & 17 deletions src/main/java/io/github/robbilie/nodegreen/FlowConfig.java

This file was deleted.

70 changes: 36 additions & 34 deletions src/main/java/io/github/robbilie/nodegreen/FlowUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,39 @@
public class FlowUtil {
private static final Pattern subflowInstanceRE = Pattern.compile("^subflow:(.+)$");

public static FlowConfig parseConfig(List<JsonNode> input) throws JsonProcessingException {
FlowConfig flow = new FlowConfig();
flow.allNodes = new HashMap<>();
flow.subflows = new HashMap<>();
flow.configs = new HashMap<>();
flow.flows = new HashMap<>();
flow.groups = new HashMap<>();
flow.missingTypes = new ArrayList<>();
public static ObjectNode parseConfig(List<JsonNode> input) throws JsonProcessingException {
ObjectNode flow = new ObjectMapper().createObjectNode();
flow.putObject("allNodes");
flow.putObject("subflows");
flow.putObject("configs");
flow.putObject("flows");
flow.putObject("groups");
//flow.putArray("missingTypes");

List<ObjectNode> config = new ArrayList<>();
for (JsonNode n : input) {
config.add(n.deepCopy());
}

for (ObjectNode n : config) {
flow.allNodes.put(n.get("id").asText(), n.deepCopy());
((ObjectNode)flow.get("allNodes")).put(n.get("id").asText(), n.deepCopy());
if (n.get("type").asText().equals("tab")) {
flow.flows.put(n.get("id").asText(), n);
flow.flows.get(n.get("id").asText()).putObject("subflows");
flow.flows.get(n.get("id").asText()).putObject("configs");
flow.flows.get(n.get("id").asText()).putObject("nodes");
((ObjectNode)flow.get("flows")).put(n.get("id").asText(), n);
((ObjectNode)flow.get("flows").get(n.get("id").asText())).putObject("subflows");
((ObjectNode)flow.get("flows").get(n.get("id").asText())).putObject("configs");
((ObjectNode)flow.get("flows").get(n.get("id").asText())).putObject("nodes");
}
if (n.get("type").asText().equals("group")) {
flow.groups.put(n.get("id").asText(), n);
((ObjectNode)flow.get("groups")).put(n.get("id").asText(), n);
}
}

for (ObjectNode n : config) {
if (n.get("type").asText().equals("subflow")) {
flow.subflows.put(n.get("id").asText(), n);
flow.subflows.get(n.get("id").asText()).putObject("configs");
flow.subflows.get(n.get("id").asText()).putObject("nodes");
flow.subflows.get(n.get("id").asText()).putArray("instances");
((ObjectNode)flow.get("subflows")).put(n.get("id").asText(), n);
((ObjectNode)flow.get("subflows").get(n.get("id").asText())).putObject("configs");
((ObjectNode)flow.get("subflows").get(n.get("id").asText())).putObject("nodes");
((ObjectNode)flow.get("subflows").get(n.get("id").asText())).putArray("instances");
}
}

Expand All @@ -58,23 +58,25 @@ public static FlowConfig parseConfig(List<JsonNode> input) throws JsonProcessing
if (!n.get("type").asText().equals("subflow") && !n.get("type").asText().equals("tab") && !n.get("type").asText().equals("group")) {
Matcher subflowDetails = subflowInstanceRE.matcher(n.get("type").asText());

if ((subflowDetails.matches() && !flow.subflows.containsKey(subflowDetails.group(1))) ||
if ((subflowDetails.matches() && !flow.get("subflows").has(subflowDetails.group(1))) ||
(!subflowDetails.matches() && !RED.nodes.containsKey(n.get("type").asText()))) {
if (!flow.missingTypes.contains(n.get("type").asText())) {
flow.missingTypes.add(n.get("type").asText());
}
//if (!((ArrayNode)flow.get("missingTypes")).to.contains(n.get("type").asText())) {
// flow.missingTypes.add(n.get("type").asText());
//}
}
ObjectNode container = null;
if (flow.flows.containsKey(n.get("z").asText())) {
container= flow.flows.get(n.get("z").asText());
} else if (flow.subflows.containsKey(n.get("z").asText())) {
container = flow.subflows.get(n.get("z").asText());
if (n.has("z")) {
if (flow.get("flows").has(n.get("z").asText())) {
container = (ObjectNode)flow.get("flows").get(n.get("z").asText());
} else if (flow.get("subflows").has(n.get("z").asText())) {
container = (ObjectNode)flow.get("subflows").get(n.get("z").asText());
}
}
if (n.has("x") && n.has("y")) {
if (subflowDetails.matches()) {
String subflowType = subflowDetails.group(1);
n.put("subflow", subflowType);
((ArrayNode) flow.subflows.get(subflowType).get("instances")).add(n);
((ArrayNode) flow.get("subflows").get(subflowType).get("instances")).add(n);
}
if (container != null) {
((ObjectNode) container.get("nodes")).set(n.get("id").asText(), n);
Expand All @@ -83,8 +85,8 @@ public static FlowConfig parseConfig(List<JsonNode> input) throws JsonProcessing
if (container != null) {
((ObjectNode) container.get("configs")).set(n.get("id").asText(), n);
} else {
flow.configs.put(n.get("id").asText(), n);
flow.configs.get(n.get("id").asText()).putArray("_users");
((ObjectNode)flow.get("configs")).put(n.get("id").asText(), n);
((ObjectNode)(flow.get("configs")).get(n.get("id").asText())).putArray("_users");
}
}
if (n.get("type").asText().equals("link in") && n.has("links")) {
Expand Down Expand Up @@ -112,21 +114,21 @@ public static FlowConfig parseConfig(List<JsonNode> input) throws JsonProcessing
for (ObjectNode n : config) {
if (!n.get("type").asText().equals("subflow") && !n.get("type").asText().equals("tab") && !n.get("type").asText().equals("group")) {
/*for (JsonNode prop : n) {
if (n.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== 'type' && prop !== '_users' && flow.configs.hasOwnProperty(n[prop])) {
if (n.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== 'type' && prop !== '_users' && ((ObjectNode)flow.get("configs")).hasOwnProperty(n[prop])) {
// This property references a global config node
flow.configs[n[prop]]._users.push(n.id)
((ObjectNode)flow.get("configs"))[n[prop]]._users.push(n.id)
}
}*/
if (n.has("z") && !flow.subflows.containsKey(n.get("z").asText())) {
if (n.has("z") && !((ObjectNode)flow.get("subflows")).has(n.get("z").asText())) {

if (!flow.flows.containsKey(n.get("z").asText())) {
if (!((ObjectNode)flow.get("flows")).has(n.get("z").asText())) {
ObjectNode tab = new ObjectMapper().createObjectNode();
tab.put("type", "tab");
tab.put("id", n.get("z").asText());
tab.putObject("subflows");
tab.putObject("configs");
tab.putObject("nodes");
flow.flows.put(n.get("z").asText(), tab);
((ObjectNode)flow.get("flows")).put(n.get("z").asText(), tab);
addedTabs.put(n.get("z").asText(), tab);
}
if (addedTabs.containsKey(n.get("z").asText())) {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/io/github/robbilie/nodegreen/FlowsJson.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.robbilie.nodegreen;

import com.fasterxml.jackson.databind.JsonNode;

import java.util.List;

public class FlowsJson {
public String rev;
public List<JsonNode> flows;
}
4 changes: 3 additions & 1 deletion src/main/java/io/github/robbilie/nodegreen/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public Node(Flow flow, JsonNode config) {
this.name = config.get("name").asText();
}
this.flow = flow;
this.updateWires(config.get("wires"));
if (config.has("wires")) {
this.updateWires(config.get("wires"));
}
}

void updateWires(JsonNode wires) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import java.util.Map;
import java.util.function.BiFunction;

public class TypeRegistry {
public class Nodes {
public void registerType(String name, BiFunction<Flow, JsonNode, INode> fn) {
this.registry.put(name, fn);
}
Expand Down
35 changes: 34 additions & 1 deletion src/main/java/io/github/robbilie/nodegreen/RED.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,39 @@
package io.github.robbilie.nodegreen;

import com.fasterxml.jackson.databind.node.ObjectNode;

import java.util.*;
import java.util.stream.Collectors;

public class RED {

public static TypeRegistry nodes = new TypeRegistry();
public static Nodes nodes = new Nodes();
public static Map<String,Flow> activeFlows = new HashMap<>();
public static void start(ObjectNode activeFlowConfig) {
RED.stop();
RED.activeFlows = new HashMap<>();
RED.activeFlows.put("global", Flow.create(activeFlowConfig));
for (Iterator<String> it = activeFlowConfig.get("flows").fieldNames(); it.hasNext(); ) {
String id = it.next();
if (!RED.activeFlows.containsKey(id)) {
RED.activeFlows.put(id, Flow.create(RED.activeFlows.get("global"), activeFlowConfig, (ObjectNode) activeFlowConfig.get("flows").get(id)));
}
}
for (Iterator<String> it = RED.activeFlows.keySet().iterator(); it.hasNext(); ) {
String id = it.next();
RED.activeFlows.get(id).start();
}
}

public static void stop() {
List<String> activeFlowIds = RED.activeFlows.keySet().stream().filter(id -> !id.equals("global")).collect(Collectors.toList());
if (RED.activeFlows.containsKey("global")) {
activeFlowIds.add("global");
}
for (Iterator<String> it = activeFlowIds.iterator(); it.hasNext(); ) {
String id = it.next();
RED.activeFlows.get(id).stop();
}
RED.activeFlows = new HashMap<>();
}
}
32 changes: 21 additions & 11 deletions src/test/java/io/github/robbilie/nodegreen/MainTest.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
package io.github.robbilie.nodegreen;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.github.robbilie.nodegreen.nodes.AssetsNode;
import io.github.robbilie.nodegreen.nodes.CompositionNode;
import io.github.robbilie.nodegreen.nodes.CompositionsNode;
import io.github.robbilie.nodegreen.nodes.SelectThemeNode;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class MainTest {

@Test
void mainTest() {
String json = "[{\"id\":\"global\",\"type\":\"tab\",\"label\":\"Global\",\"disabled\":false,\"info\":\"\",\"env\":[]},{\"x\":0,\"y\":0,\"z\":\"global\",\"id\":\"1234\",\"type\":\"select_theme\",\"wires\":[[\"5678\"]]},{\"x\":0,\"y\":0,\"z\":\"global\",\"id\":\"5678\",\"type\":\"composition\",\"composition\":\"007\",\"wires\":[]}]";
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("flows.json").getFile());
String json = null;
try {
json = new String(Files.readAllBytes(file.toPath()));
} catch (IOException e) {
throw new RuntimeException(e);
}

try {
List<JsonNode> config = new ObjectMapper().readValue(json, new TypeReference<List<JsonNode>>() {});
FlowsJson flowsJson = new ObjectMapper().readValue(json, FlowsJson.class);

RED.nodes.registerType("select_theme", SelectThemeNode::new);
RED.nodes.registerType("assets", AssetsNode::new);
RED.nodes.registerType("compositions", CompositionsNode::new);
RED.nodes.registerType("composition", CompositionNode::new);
RED.nodes.registerType("select_theme", SelectThemeNode::new);

FlowConfig fc = FlowUtil.parseConfig(config);
ObjectNode config = FlowUtil.parseConfig(flowsJson.flows);

System.out.println(fc);
System.out.println(config);

Flow flow = Flow.create(fc, fc.flows.get("global"));
flow.start();
RED.start(config);

assertEquals(1, SelectThemeNode.nodes.size());

Expand All @@ -39,7 +49,7 @@ void mainTest() {
SelectThemeNode.nodes.get(id).receive(msg);
}

flow.stop();
RED.stop();

for (String id : SelectThemeNode.nodes.keySet()) {
ObjectNode msg = new ObjectMapper().createObjectNode();
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/io/github/robbilie/nodegreen/nodes/AssetsNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.github.robbilie.nodegreen.nodes;

import com.fasterxml.jackson.databind.JsonNode;
import io.github.robbilie.nodegreen.Flow;
import io.github.robbilie.nodegreen.Node;

import java.util.List;

public class AssetsNode extends Node {
public List<JsonNode> assets;
public AssetsNode(Flow flow, JsonNode config) {
super(flow, config);
this.assets = config.findValues("assets");
}
}
Loading

0 comments on commit 5f14ba4

Please sign in to comment.