generated from Nekojimi/JavaMavenTemplate
Initial version of a lot of behaviour.
This commit is contained in:
parent
b35bd6c2d5
commit
f4e9c3e823
|
@ -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;
|
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
|
* @author Nekojimi
|
||||||
*/
|
*/
|
||||||
public class Main
|
public class Main
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static final Class[] testClasses =
|
||||||
|
{
|
||||||
|
String.class,
|
||||||
|
Integer.class,
|
||||||
|
Math.class,
|
||||||
|
HashMap.class,
|
||||||
|
OffsetDateTime.class,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param args the command line arguments
|
* @param args the command line arguments
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, IOException
|
||||||
{
|
{
|
||||||
System.out.println("Hello world!");
|
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()
|
||||||
|
{
|
||||||
|
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…
Reference in New Issue