package javaflow.network.impl;
import javaflow.network.api.PacketListener;
import javaflow.network.api.PortReference;
import javaflow.network.api.SubnetDefinition;
import java.util.*;
final class SubnetComponent extends AbstractRunnableComponent {
private final SubnetDefinition subnetDefinition;
private final NetworkImpl subnetwork;
private final SimpleNetworkBuilder builder;
public SubnetComponent(
String name, final SubnetDefinition subnet,
Collection<InputPortImpl> inputs,
Collection<OutputPortImpl> outputs) {
super(name,inputs,outputs);
this.subnetDefinition = subnet;
subnetwork = new NetworkImpl();
for(InputPortImpl in : inputs) {
final InputPortImpl inputPort = in;
String portName = in.port().portName();
final OutputPortImpl outputPort = new OutputPortImpl(new PortReference(null, portName));
subnetwork.addOutputPort(outputPort.portReference().toString(), outputPort);
final boolean isSubstreamSensitive = subnet.isSubstreamSensitivePort(portName);
final AbstractRunnableComponent runnableComponent = createInputComponent(portName, inputPort, outputPort, isSubstreamSensitive);
subnetwork.addComponent(runnableComponent);
}
for(OutputPortImpl out : outputs) {
final OutputPortImpl outputPort = out;
String portName = out.portReference().portName();
final InputPortImpl inputPort = new InputPortImpl(new PortReference(null, portName));
subnetwork.addInputPort(inputPort.port().toString(), inputPort);
final boolean isSubnetSensitive = subnet.isSubstreamSensitivePort(portName);
final AbstractRunnableComponent runnableComponent = createOutputComponent(portName, inputPort, outputPort, isSubnetSensitive);
subnetwork.addComponent(runnableComponent);
}
subnetwork.addPacketListener(new PacketListener() {
@Override
public void packetCreatedByComponent(long packetId, int componentId) {
packetListener().packetCreatedByComponent(packetId, componentId());
}
@Override
public void packetArrivedAtComponent(long packetId, int componentId) {
}
@Override
public void packetDroppedByComponent(long packetId, int componentId) {
packetListener().packetDroppedByComponent(packetId, componentId());
}
@Override
public void packetLeftComponent(long packetId, int fromComponentId, int towardsComponentId) {
}
});
builder = new SimpleNetworkBuilder();
try {
builder.buildNetwork(subnetDefinition, subnetwork);
} catch (Exception e) {
throw new Error(e);
}
}
private AbstractRunnableComponent createOutputComponent(String portName, InputPortImpl inputPort, OutputPortImpl outputPort, boolean isSubnetSensitive) {
final AbstractRunnableComponent runnableComponent;
if (isSubnetSensitive) {
runnableComponent = new RunnableSubstreamSensitiveSubnetOutput(portName, inputPort, outputPort,this);
} else {
runnableComponent = new RunnableSubnetOutput(portName, inputPort, outputPort, this);
}
return runnableComponent;
}
private AbstractRunnableComponent createInputComponent(String portName, InputPortImpl inputPort, OutputPortImpl outputPort, boolean isSubstreamSensitive) {
final AbstractRunnableComponent runnableComponent;
if (isSubstreamSensitive) {
runnableComponent = new RunnableSubstreamSensitiveSubnetInput(portName,
inputPort,
outputPort,this);
} else {
runnableComponent = new RunnableSubnetInput(portName,
inputPort,
outputPort, this);
}
return runnableComponent;
}
@Override
public void onNetworkShutdown() {
}
@Override
public boolean mustRun() {
return false;
}
@Override
protected void execute() throws Exception{
subnetwork.runInCurrentThread();
if (shouldContinueRunning()){
reinitializeSubnetwork();
}
}
private void reinitializeSubnetwork() {
builder.initializeIntialPackets(subnetDefinition,subnetwork);
subnetwork.reopenAllPorts();
}
}