Initial version of a lot of behaviour.

master
Nekojimi 3 years ago
parent b35bd6c2d5
commit f4e9c3e823
  1. 30
      src/main/java/moe/nekojimi/nodeprocessor/ClassMethodType.java
  2. 178
      src/main/java/moe/nekojimi/nodeprocessor/Main.java
  3. 36
      src/main/java/moe/nekojimi/nodeprocessor/NodeSpec.java
  4. 108
      src/main/java/moe/nekojimi/nodeprocessor/Program.java
  5. 42
      src/main/java/moe/nekojimi/nodeprocessor/links/ConstantLink.java
  6. 83
      src/main/java/moe/nekojimi/nodeprocessor/links/Link.java
  7. 38
      src/main/java/moe/nekojimi/nodeprocessor/links/PullLink.java
  8. 42
      src/main/java/moe/nekojimi/nodeprocessor/links/QueueLink.java
  9. 35
      src/main/java/moe/nekojimi/nodeprocessor/nodes/DebugOutNode.java
  10. 76
      src/main/java/moe/nekojimi/nodeprocessor/nodes/MethodNode.java
  11. 158
      src/main/java/moe/nekojimi/nodeprocessor/nodes/Node.java
  12. 160
      src/main/java/moe/nekojimi/nodeprocessor/nodes/ObjectNode.java
  13. 57
      src/main/java/moe/nekojimi/nodeprocessor/nodes/SerialiserNode.java
  14. 55
      src/main/java/moe/nekojimi/nodeprocessor/nodes/ValueNode.java
  15. 18
      src/main/java/moe/nekojimi/nodeprocessor/ports/ConstantOutPort.java
  16. 46
      src/main/java/moe/nekojimi/nodeprocessor/ports/InPort.java
  17. 45
      src/main/java/moe/nekojimi/nodeprocessor/ports/OutPort.java
  18. 83
      src/main/java/moe/nekojimi/nodeprocessor/ports/Port.java
  19. 37
      src/main/java/moe/nekojimi/nodeprocessor/ports/PullOutPort.java
  20. 18
      src/main/java/moe/nekojimi/nodeprocessor/ports/QueueOutPort.java

@ -0,0 +1,30 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor;
/**
*
* @author jimj316
*/
public enum ClassMethodType
{
/**
* takes no input, makes no changes, returns a value
* Should be added to an object node, given a constant port
*/
GETTER,
SETTER, // takes one input, changes one field, returns nothing
ADDER, // takes one input, makes other state changes, returns nothing
TAKER, // takes no input, makes other state changes, returns a value
CALLBACK, // takes a single argument of an abstract class
ACTION, // takes no input or output
TRANSFORMER, // takes input, changes the object, then returns the object (eg. builder methods)
FUNCTION, // takes one or more unrelated types, and returns a result
CONSTANT, // static; no input, returns a value
FACTORY,
OTHER,
}

@ -1,16 +1,190 @@
package moe.nekojimi.nodeprocessor;
import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.stream.Collectors;
import moe.nekojimi.nodeprocessor.links.Link;
import moe.nekojimi.nodeprocessor.nodes.MethodNode;
import moe.nekojimi.nodeprocessor.nodes.DebugOutNode;
import moe.nekojimi.nodeprocessor.nodes.ValueNode;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
/**
*
* @author Nekojimi
*/
public class Main
{
private static final Class[] testClasses =
{
String.class,
Integer.class,
Math.class,
HashMap.class,
OffsetDateTime.class,
};
/**
* @param args the command line arguments
*/
public static void main(String[] args)
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, IOException
{
for (Class testClass : testClasses)
{
System.out.println(testClass.getName() + ":");
Method[] methods = testClass.getMethods();
for (Method method : methods)
{
if (method.getDeclaringClass() == testClass)
{
ClassMethodType type = guessMethodType(method);
System.out.println("\t" + method.toString());
System.out.println("\t\t" + type.name());
}
}
}
// helloWorldProgram();
}
private static void fibonnaciProgram()
{
System.out.println("Hello world!");
Program program = new Program();
}
private static void addNumbersProgram() throws NoSuchMethodException
{
Program program = new Program();
ValueNode<Integer> twoNode = new ValueNode<>(program, Integer.class);
twoNode.setValue(2);
ValueNode<Integer> threeNode = new ValueNode<>(program, Integer.class);
threeNode.setValue(3);
MethodNode<Integer> methodNode = new MethodNode<>(program, Integer.class, Integer.class.getMethod("sum", Integer.class, Integer.class));
DebugOutNode debugOutNode = new DebugOutNode(program);
// Link.makeLink(Integer.class, twoNode, fromPort, twoNode, toPort);
program.start();
}
private static void helloWorldProgram() throws SecurityException, NoSuchMethodException
{
Program program = new Program();
ValueNode<String> valueNode = new ValueNode<>(program, String.class);
valueNode.setValue("Hello world!");
final Method method = String.class.getMethod("toUpperCase");
MethodNode<String> methodNode = new MethodNode<>(program, String.class, method);
DebugOutNode debugOutNode = new DebugOutNode(program);
Link.makeLink(String.class, valueNode, "out", methodNode, "object");
Link.makeLink(String.class, methodNode, "out", debugOutNode, "in");
program.start();
}
public static Set<Class> findAllClassesUsingClassLoader(String packageName)
{
InputStream stream = ClassLoader.getSystemClassLoader()
.getResourceAsStream(packageName.replaceAll("[.]", "/"));
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
return reader.lines()
.filter(line -> line.endsWith(".class"))
.map(line -> getClass(line, packageName))
.collect(Collectors.toSet());
}
public static Set<Class> findAllClassesUsingReflectionsLibrary(String packageName)
{
Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
return reflections.getSubTypesOf(Object.class)
.stream()
.collect(Collectors.toSet());
}
private static Class getClass(String className, String packageName)
{
try
{
return Class.forName(packageName + "."
+ className.substring(0, className.lastIndexOf('.')));
} catch (ClassNotFoundException e)
{
// handle the exception
}
return null;
}
private static ClassMethodType guessMethodType(Method method)
{
String name = method.getName();
Class<?> clazz = method.getDeclaringClass();
Class<?> returnType = method.getReturnType();
boolean hasReturn = (returnType != Void.TYPE);
int paramCount = method.getParameterCount();
Class<?> firstParamType = null;
Parameter[] parameters = method.getParameters();
if (paramCount > 0)
firstParamType = parameters[0].getType();
boolean isStatic = Modifier.isStatic(method.getModifiers());
if (!isStatic)
{
if (hasReturn)
{
if (paramCount == 0) // methods that only return
{
if (name.startsWith("take") || name.startsWith("poll") || name.startsWith("remove") || name.startsWith("pop") || name.startsWith("read"))
return ClassMethodType.TAKER;
else
return ClassMethodType.GETTER;
} else if (clazz.isAssignableFrom(returnType))
return ClassMethodType.TRANSFORMER;
else if (paramCount == 1
&& Modifier.isAbstract(parameters[0].getType().getModifiers())
&& !parameters[0].getType().isPrimitive()
&& name.toLowerCase().matches("(on.+|.*listener.*|.*observer.*)"))
{
int abstractMethods = 0;
Method[] paramTypeMethods = parameters[0].getType().getMethods();
for (Method paramTypeMethod : paramTypeMethods)
{
if (Modifier.isAbstract(paramTypeMethod.getModifiers()))
abstractMethods++;
}
if (abstractMethods >= 1)
return ClassMethodType.CALLBACK;
} else
return ClassMethodType.FUNCTION;
} else // returns nothing
{
if (paramCount == 1)
{
if (name.startsWith("give") || name.startsWith("add") || name.startsWith("push") || name.startsWith("write"))
return ClassMethodType.ADDER;
else
return ClassMethodType.SETTER;
} else if (paramCount == 0) // no input, return nothing
return ClassMethodType.ACTION;
}
} else // static method
{
if (clazz.isAssignableFrom(returnType))
return ClassMethodType.FACTORY;
else if (hasReturn && paramCount > 0)
return ClassMethodType.FUNCTION;
else if (hasReturn && paramCount == 0)
return ClassMethodType.CONSTANT;
}
return ClassMethodType.OTHER;
}
}

@ -0,0 +1,36 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor;
import com.amihaiemil.eoyaml.YamlMapping;
import moe.nekojimi.nodeprocessor.nodes.Node;
/**
* Specifies a type of node that can exist.
* Holds a list of one or more methods and their archetypes to be added to the
* new node???
*
* @author jimj316
*/
public class NodeSpec<T extends Node>
{
public static NodeSpec fromYAML(YamlMapping yaml) throws ClassNotFoundException
{
Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass(yaml.string("class"));
final NodeSpec nodeSpec = new NodeSpec(clazz);
return nodeSpec;
}
public NodeSpec(Class<T> clazz)
{
}
public T construct()
{
return null;
}
}

@ -0,0 +1,108 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor;
import java.util.*;
import moe.nekojimi.nodeprocessor.links.Link;
import moe.nekojimi.nodeprocessor.nodes.Node;
/**
*
* @author jimj316
*/
public class Program
{
private final List<Node> nodes = new ArrayList<>();
private final Set<Link> links = new HashSet<>();
private final Queue<Node> executionQueue = new LinkedList<>();
private final Set<Node> idleNodes = new HashSet<>();
private Thread thread;
private State state = State.STOPPED;
public void addNode(Node node)
{
if (!nodes.contains(node))
nodes.add(node);
nodes.sort(Node.DEPENDENCY_ORDER);
}
public void addLink(Link link)
{
links.add(link);
}
public void queueNodeProcess(Node node)
{
executionQueue.add(node);
}
public void setIdleNode(Node node, boolean idle)
{
if (idle)
idleNodes.add(node);
else
idleNodes.remove(node);
}
public State getState()
{
return state;
}
public void start()
{
if (state != State.STOPPED)
throw new IllegalStateException("Thread isn't stopped!");
if (thread == null)
thread = new Thread(runnable);
thread.start();
}
private final Runnable runnable = () ->
{
state = State.RUNNING;
for (Node node : nodes)
{
node.reset();
if (node.getNumberOfInputs() == 0)
node.signal();
}
while (!executionQueue.isEmpty())
{
Node node = executionQueue.poll();
boolean done = node.process();
if (!done)
queueNodeProcess(node);
}
state = State.STOPPED;
};
public List<Node> getNodes()
{
return nodes;
}
public Set<Link> getLinks()
{
return links;
}
public Set<Node> getIdleNodes()
{
return idleNodes;
}
public enum State
{
STOPPED,
PAUSED,
RUNNING,
IDLE
}
}

@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.links;
import moe.nekojimi.nodeprocessor.ports.ConstantOutPort;
import moe.nekojimi.nodeprocessor.ports.InPort;
public class ConstantLink<T> extends Link<T, InPort<T>, ConstantOutPort<T>>
{
T value = null;
public ConstantLink(ConstantOutPort<T> from, InPort<T> to)
{
super(from, to);
}
@Override
public T read()
{
return value;
}
@Override
public void write(T val)
{
if (val != value)
signal();
value = val;
}
@Override
public boolean has()
{
return value != null;
}
}

@ -0,0 +1,83 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.links;
import moe.nekojimi.nodeprocessor.nodes.Node;
import moe.nekojimi.nodeprocessor.ports.ConstantOutPort;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.OutPort;
import moe.nekojimi.nodeprocessor.ports.QueueOutPort;
/**
*
* @author jimj316
*/
public abstract class Link<T, I extends InPort<T>, O extends OutPort<T>>
{
final O from;
private final I to;
public Link(O from, I to)
{
this.from = from;
this.to = to;
connect();
}
public final void connect()
{
from.connect(this);
to.connect(this);
from.getNode().getProgram().addLink(this);
to.getNode().getProgram().addLink(this);
}
public final void disconnect()
{
from.disconnect(this);
to.disconnect(this);
}
public abstract T read();
public abstract void write(T val);
public abstract boolean has();
public static <T> Link<T, ?, ?> makeLink(Class<T> clazz, Node from, String fromPort, Node to, String toPort)
{
OutPort<T> outPort = from.getOutPort(fromPort, clazz);
InPort<T> inPort = to.getInPort(toPort, clazz);
if (outPort instanceof QueueOutPort)
{
QueueOutPort<T> q = (QueueOutPort<T>) outPort;
return new QueueLink<>(q, inPort);
} else if (outPort instanceof ConstantOutPort)
{
ConstantOutPort<T> c = (ConstantOutPort<T>) outPort;
return new ConstantLink<>(c, inPort);
} else
{
return null;
}
}
protected void signal()
{
to.signal();
}
public O getFrom()
{
return from;
}
public I getTo()
{
return to;
}
}

@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.links;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.PullOutPort;
public class PullLink<T> extends Link<T, InPort<T>, PullOutPort<T>>
{
public PullLink(PullOutPort<T> from, InPort<T> to)
{
super(from, to);
}
@Override
public T read()
{
return from.pull();
}
@Override
public void write(T val)
{
// not used
}
@Override
public boolean has()
{
return true;
}
}

@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.links;
import java.util.LinkedList;
import java.util.Queue;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.QueueOutPort;
public class QueueLink<T> extends Link<T, InPort<T>, QueueOutPort<T>>
{
private final Queue<T> queue = new LinkedList<>();
public QueueLink(QueueOutPort<T> from, InPort<T> to)
{
super(from, to);
}
@Override
public T read()
{
return queue.poll();
}
@Override
public void write(T val)
{
queue.add(val);
signal();
}
@Override
public boolean has()
{
return !queue.isEmpty();
}
}

@ -0,0 +1,35 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import moe.nekojimi.nodeprocessor.Program;
import moe.nekojimi.nodeprocessor.ports.InPort;
public class DebugOutNode extends Node
{
public DebugOutNode(Program scene)
{
super(scene);
addInPort(new InPort("in", Object.class, this));
}
@Override
public boolean process()
{
InPort<Object> inPort = getInPort("in", Object.class);
System.out.println(inPort.get());
return true;
}
@Override
public boolean check()
{
InPort<Object> inPort = getInPort("in", Object.class);
return inPort.has();
}
}

@ -0,0 +1,76 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import moe.nekojimi.nodeprocessor.ports.InPort;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.logging.Level;
import java.util.logging.Logger;
import moe.nekojimi.nodeprocessor.Program;
import moe.nekojimi.nodeprocessor.ports.QueueOutPort;
/**
*
* @author jimj316
* @param <C> the class that declares this method.
*/
public class MethodNode<C> extends Node
{
private final InPort<C> objectInPort;
private final QueueOutPort returnOutPort;
private final Method method;
public MethodNode(Program scene, Class<C> clazz, Method method)
{
super(scene);
assert (method.getDeclaringClass() == clazz);
if (Modifier.isStatic(method.getModifiers()))
objectInPort = null;
else
{
objectInPort = new InPort<>("object", clazz, this);
addInPort(objectInPort);
}
this.method = method;
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters)
addInPort(new InPort(parameter.getName(), parameter.getType(), this));
Class<?> returnType = method.getReturnType();
returnOutPort = new QueueOutPort("out", returnType, this);
addOutPort(returnOutPort);
setName(method.getDeclaringClass().getSimpleName() + " " + method.getName());
}
@Override
public boolean process()
{
try
{
C object = null;
if (objectInPort != null)
object = objectInPort.get();
Object ret = method.invoke(object);
returnOutPort.set(ret);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
{
Logger.getLogger(MethodNode.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
@Override
public boolean check()
{
return getInPorts().stream().allMatch(in -> (in.has()));
}
}

@ -0,0 +1,158 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import java.util.*;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.OutPort;
import moe.nekojimi.nodeprocessor.Program;
/**
*
* @author jimj316
*/
public abstract class Node
{
// protected Map<String, Link> inLinks = new HashMap<>();
// protected Map<String, Link> outLinks = new HashMap<>();
private final Program program;
private Map<String, InPort> inPorts = new HashMap<>();
private Map<String, OutPort> outPorts = new HashMap<>();
private String name;
public Node(Program program)
{
this.program = program;
program.addNode(this);
this.name = this.getClass().getSimpleName();
}
public String getName()
{
return name;
}
protected void setName(String name)
{
this.name = name;
}
protected final void addInPort(InPort port)
{
inPorts.putIfAbsent(getPortName(port.getClazz(), port.getName()), port);
}
protected final void addOutPort(OutPort port)
{
outPorts.putIfAbsent(getPortName(port.getClazz(), port.getName()), port);
}
public final <X> InPort<X> getInPort(String name, Class<X> clazz)
{
Class<? super X> c = clazz;
InPort ret;
do
{
ret = inPorts.get(getPortName(c, name));
c = c.getSuperclass();
} while (ret == null && c != null);
return ret;
}
public final <X> OutPort<X> getOutPort(String name, Class<X> clazz)
{
Class<? super X> c = clazz;
OutPort ret;
do
{
ret = outPorts.get(getPortName(clazz, name));
c = c.getSuperclass();
} while (ret == null && c != null);
return ret;
}
public final Collection<InPort> getInPorts()
{
return inPorts.values();
}
public final Collection<OutPort> getOutPorts()
{
return outPorts.values();
}
private static <X> String getPortName(Class<X> clazz, String name)
{
return clazz.getCanonicalName() + "-" + name;
}
public int getNumberOfInputs()
{
return inPorts.values().stream().mapToInt((t) -> t.getNumberOfConnections()).sum();
}
public int getNumberOfOutputs()
{
return outPorts.values().stream().mapToInt((t) -> t.getNumberOfConnections()).sum();
}
public Program getProgram()
{
return program;
}
public boolean dependsOn(Node other)
{
// TODO: this is a crude search that will enter an infinite loop if a node depends on itself
for (InPort port : inPorts.values())
{
Set<Node> linkedNodes = port.getLinkedNodes();
if (linkedNodes.contains(other))
return true;
else
for (Node dependent : linkedNodes)
{
if (dependent.dependsOn(other))
return true;
}
}
return false;
}
/**
* Processes this node's inputs, and generates output (or performs some
* other useful function).
*
* @return true if there will be no more output until an input is received;
* false if process() should be called again.
*/
public abstract boolean process();
public abstract boolean check();
public void signal()
{
if (check())
program.queueNodeProcess(this);
}
public void reset()
{
// assume most nodes are stateless
// default implementation does nothing
}
public static final Comparator<Node> DEPENDENCY_ORDER = (Node a, Node b) ->
{
int ret = 0;
if (a.dependsOn(b))
ret--;
if (b.dependsOn(a))
ret++;
return ret;
};
}

@ -0,0 +1,160 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import moe.nekojimi.nodeprocessor.Program;
import moe.nekojimi.nodeprocessor.ports.ConstantOutPort;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.OutPort;
/**
* Represents an object that performs some function.
* Has a set of inputs that will cause the object to be (re) created when
* changed.
*
* @author jimj316
* @param <T>
*/
public class ObjectNode<T> extends Node
{
protected T object;
private final Constructor<T> constructor;
private final Set<InPort> composingInPorts = new HashSet<>();
private final Set<InPort> setterInPorts = new HashSet<>();
private final Set<OutPort> getterOutPorts = new HashSet<>();
private final OutPort<T> objectOutPort;
private final Map<String, Object> composingValues = new HashMap<>();
private final Class<T> clazz;
public ObjectNode(Program scene, Class<T> clazz, Constructor<T> constructor)
{
super(scene);
this.clazz = clazz;
this.constructor = constructor;
objectOutPort = new ConstantOutPort<>("this", clazz, this);
addConstructor();
addAutoMethods();
}
public void addAutoMethods() throws SecurityException
{
for (Method method : clazz.getMethods())
{
String name = method.getName();
Class<?> returnType = method.getReturnType();
Parameter[] parameters = method.getParameters();
if (returnType == null && parameters.length == 1 && name.startsWith("set"))
{
// this is a setter method
InPort in = new InPort(name, parameters[0].getType(), this);
addInPort(in);
setterInPorts.add(in);
} else if (returnType != null && parameters.length == 0 && (name.startsWith("get") || name.startsWith("is")))
{
// this is a getter method
ConstantOutPort out = new ConstantOutPort(name, returnType, this);
addOutPort(out);
getterOutPorts.add(out);
}
}
}
public void addConstructor()
{
Parameter[] parameters = constructor.getParameters();
for (Parameter parameter : parameters)
{
InPort in = new InPort(parameter.getName(), parameter.getType(), this);
addInPort(in);
composingInPorts.add(in);
}
}
@Override
public void reset()
{
super.reset();
if (object instanceof Closeable)
{
try
{
((Closeable) object).close();
} catch (IOException ex)
{
Logger.getLogger(ObjectNode.class.getName()).log(Level.SEVERE, null, ex);
}
}
object = null;
}
@Override
public boolean process()
{
// check if the composing values have changed; if so delete the object
// if the object doesn't exist, create it
if (object == null)
{
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors)
{
Parameter[] parameters = constructor.getParameters();
List<Object> args = new ArrayList<>();
for (Parameter parameter : parameters)
{
InPort<?> inPort = getInPort(parameter.getName(), parameter.getType());
if (inPort.has())
args.add(inPort.get());
else
break;
}
if (args.size() == parameters.length)
{
try
{
object = (T) constructor.newInstance(args.toArray());
objectOutPort.set(object);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
{
Logger.getLogger(ObjectNode.class.getName()).log(Level.SEVERE, null, ex);
}
break;
}
}
}
// now the object exists, do something with it
if (object != null)
{
// take input from setters
// give output to getters
return doProcess();
}
return true;
}
protected boolean doProcess()
{
return true;
}
@Override
public boolean check()
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

@ -0,0 +1,57 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import java.util.Iterator;
import moe.nekojimi.nodeprocessor.Program;
import moe.nekojimi.nodeprocessor.ports.InPort;
import moe.nekojimi.nodeprocessor.ports.OutPort;
import moe.nekojimi.nodeprocessor.ports.QueueOutPort;
public class SerialiserNode<T> extends Node
{
private final Class<Iterable<T>> aClass;
private final Class<T> clazz;
public SerialiserNode(Program scene, Class<T> clazz)
{
super(scene);
Iterable<T> it = () ->
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
};
aClass = (Class<Iterable<T>>) it.getClass();
addInPort(new InPort("in", aClass, this));
this.clazz = clazz;
addOutPort(new QueueOutPort("out", clazz, this));
}
@Override
public boolean process()
{
InPort<Iterable<T>> inPort = getInPort("in", aClass);
OutPort<T> outPort = getOutPort("out", clazz);
if (inPort.has())
{
Iterable<T> iterable = inPort.get();
Iterator<T> iterator = iterable.iterator();
while (iterator.hasNext())
{
outPort.set(iterator.next());
}
}
return true;
}
@Override
public boolean check()
{
InPort<Iterable<T>> inPort = getInPort("in", aClass);
return inPort.has();
}
}

@ -0,0 +1,55 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.nodes;
import moe.nekojimi.nodeprocessor.Program;
import moe.nekojimi.nodeprocessor.ports.ConstantOutPort;
import moe.nekojimi.nodeprocessor.ports.InPort;
public class ValueNode<T> extends Node
{
private T value;
private final ConstantOutPort<T> outPort;
private final InPort<T> inPort;
public ValueNode(Program scene, Class<T> clazz)
{
super(scene);
inPort = new InPort("set", clazz, this);
addInPort(inPort);
outPort = new ConstantOutPort("out", clazz, this);
addOutPort(outPort);
}
public void setValue(T val)
{
value = val;
signal();
}
public T getValue()
{
return value;
}
@Override
public boolean process()
{
if (inPort.has())
value = inPort.get();
outPort.set(value);
return true;
}
@Override
public boolean check()
{
return inPort.has();
}
}

@ -0,0 +1,18 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import moe.nekojimi.nodeprocessor.nodes.Node;
public class ConstantOutPort<T> extends OutPort<T>
{
public ConstantOutPort(String name, Class<T> clazz, Node node)
{
super(name, clazz, node);
}
}

@ -0,0 +1,46 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import moe.nekojimi.nodeprocessor.links.Link;
import moe.nekojimi.nodeprocessor.nodes.Node;
/**
*
* @author jimj316
*/
public class InPort<T> extends Port<T>
{
public InPort(String name, Class<T> clazz, Node node)
{
super(name, clazz, node);
}
public boolean has()
{
if (links.isEmpty())
return false;
else
return links.stream().anyMatch((l) -> l.has());
}
public T get()
{
for (Link<T, ?, ?> link : links)
{
if (link.has())
return link.read();
}
return null;
}
public void signal()
{
node.signal();
}
}

@ -0,0 +1,45 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import moe.nekojimi.nodeprocessor.links.Link;
import moe.nekojimi.nodeprocessor.nodes.Node;
/**
*
* @author jimj316
*/
public abstract class OutPort<T> extends Port<T>
{
public OutPort(String name, Class<T> clazz, Node node)
{
super(name, clazz, node);
}
public void set(T value)
{
for (Link<T, ?, ?> link : links)
{
link.write(value);
}
}
@Override
public void connect(Link<T, ?, ?> link)
{
super.connect(link);
// also re-order the links into dependency order
links.sort((Link a, Link b) ->
{
Node aNode = a.getTo().getNode();
Node bNode = b.getTo().getNode();
return Node.DEPENDENCY_ORDER.compare(aNode, bNode);
});
}
}

@ -0,0 +1,83 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import moe.nekojimi.nodeprocessor.links.Link;
import moe.nekojimi.nodeprocessor.nodes.Node;
/**
*
* @author jimj316
*/
public abstract class Port<T>
{
protected final String name;
protected final Class<T> clazz;
protected final Node node;
protected final List<Link<T, ?, ?>> links = new ArrayList<>();
public String getName()
{
return name;
}
public Class<T> getClazz()
{
return clazz;
}
public void connect(Link<T, ?, ?> link)
{
links.add(link);
}
public void disconnect(Link<T, ?, ?> link)
{
links.remove(link);
}
public Port(String name, Class<T> clazz, Node node)
{
this.name = name;
this.clazz = clazz;
this.node = node;
}
public Set<Node> getLinkedNodes()
{
Set<Node> ret = new HashSet<>();
for (Link<T, ?, ?> link : links)
{
Port otherSide;
if (link.getFrom() == this)
otherSide = link.getTo();
else
otherSide = link.getFrom();
ret.add(otherSide.node);
}
return ret;
}
public int getNumberOfConnections()
{
return links.size();
}
public Node getNode()
{
return node;
}
public List<Link<T, ?, ?>> getLinks()
{
return links;
}
}

@ -0,0 +1,37 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import java.util.function.Supplier;
import moe.nekojimi.nodeprocessor.nodes.Node;
public class PullOutPort<T> extends OutPort<T>
{
private Supplier<T> supplier;
public PullOutPort(String name, Class<T> clazz, Node node)
{
super(name, clazz, node);
}
public void setSupplier(Supplier<T> supplier)
{
this.supplier = supplier;
}
@Override
public void set(T value)
{
// not used
}
public T pull()
{
return supplier.get();
}
}

@ -0,0 +1,18 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package moe.nekojimi.nodeprocessor.ports;
import moe.nekojimi.nodeprocessor.nodes.Node;
public class QueueOutPort<T> extends OutPort<T>
{
public QueueOutPort(String name, Class<T> clazz, Node node)
{
super(name, clazz, node);
}
}
Loading…
Cancel
Save