generated from Nekojimi/JavaMavenTemplate
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 |
||||||
|
{ |
||||||
|
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 |
||||||
{ |
{ |
||||||
System.out.println("Hello world!"); |
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