package uk.ac.imperial.lsds.seep.api.operator; import java.util.ArrayList; import java.util.List; import uk.ac.imperial.lsds.seep.api.ConnectionType; import uk.ac.imperial.lsds.seep.api.DataStore; import uk.ac.imperial.lsds.seep.api.SeepTask; import uk.ac.imperial.lsds.seep.api.operator.sinks.TaggingSink; import uk.ac.imperial.lsds.seep.api.operator.sources.TaggingSource; import uk.ac.imperial.lsds.seep.api.state.SeepState; import uk.ac.imperial.lsds.seep.util.Utils; public class SeepLogicalOperator implements LogicalOperator { private int opId; private String name; private boolean stateful; private SeepTask task; private SeepState state; private List<DownstreamConnection> downstream = new ArrayList<DownstreamConnection>(); private List<UpstreamConnection> upstream = new ArrayList<UpstreamConnection>(); private SeepLogicalOperator(int opId, SeepTask task, String name){ this.opId = opId; this.task = task; this.name = name; this.stateful = false; } private SeepLogicalOperator(int opId, SeepTask task, SeepState state, String name){ this.opId = opId; this.task = task; this.name = name; this.state = state; this.stateful = true; } // Empty constructor for serialization public SeepLogicalOperator() { } public static LogicalOperator newStatelessOperator(int opId, SeepTask task){ String name = new Integer(opId).toString(); return SeepLogicalOperator.newStatelessOperator(opId, task, name); } public static LogicalOperator newStatelessOperator(int opId, SeepTask task, String name){ return new SeepLogicalOperator(opId, task, name); } public static LogicalOperator newStatefulOperator(int opId, SeepTask task, SeepState state){ String name = new Integer(opId).toString(); return SeepLogicalOperator.newStatefulOperator(opId, task, state, name); } public static LogicalOperator newStatefulOperator(int opId, SeepTask task, SeepState state, String name){ return new SeepLogicalOperator(opId, task, state, name); } @Override public int getOperatorId() { return opId; } @Override public String getOperatorName() { return name; } @Override public boolean isStateful() { return stateful; } @Override public SeepState getState() { return state; } @Override public SeepTask getSeepTask() { return task; } @Override public List<DownstreamConnection> downstreamConnections() { return downstream; } @Override public List<UpstreamConnection> upstreamConnections() { return upstream; } public void connectTo(Operator downstreamOperator, int streamId, DataStore dataStore) { this.connectTo(downstreamOperator, streamId, dataStore, ConnectionType.ONE_AT_A_TIME); } public void connectTo(Operator downstreamOperator, int streamId, DataStore dataStore, ConnectionType connectionType){ // Add downstream to this operator this.addDownstream(downstreamOperator, streamId, dataStore, connectionType); // Add this as a new upstream to the downstream operator. With the exception of downstream being a // TaggingSink in which case its existence is transient and its purpose of limited scope, // like that of all of us. At least until someone figures out how to cure aging, and people start // reading more philosophy and less shit, and working hard to figure out why they want to be alive, // instead of simply following their animal instincts of survival. Those lazy bastards. if(! (downstreamOperator instanceof TaggingSink)) { ((SeepLogicalOperator)downstreamOperator).addUpstream(this, streamId, dataStore, connectionType); } } public void reverseConnection(TaggingSource ss, int streamId, DataStore dataStore, ConnectionType connectionType) { this.addUpstream(null, streamId, dataStore, connectionType); } /* Methods to manage logicalOperator connections */ private void addDownstream(Operator lo, int streamId, DataStore dataStore, ConnectionType connectionType) { DownstreamConnection dc = new DownstreamConnection(lo, streamId, dataStore, connectionType); this.downstream.add(dc); } private void addUpstream(Operator lo, int streamId, DataStore dataStore, ConnectionType connectionType) { UpstreamConnection uc = new UpstreamConnection(lo, streamId, dataStore, connectionType); this.upstream.add(uc); } /* Methods to print info about the operator */ public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("LogicalOperator"); sb.append(Utils.NL); sb.append("###############"); sb.append(Utils.NL); sb.append("Name: "+this.name); sb.append(Utils.NL); sb.append("OpId: "+this.opId); sb.append(Utils.NL); sb.append("Stateful?: "+this.stateful); sb.append(Utils.NL); sb.append("#Downstream: "+this.downstream.size()); sb.append(Utils.NL); for(int i = 0; i<this.downstream.size(); i++){ DownstreamConnection down = downstream.get(i); sb.append(" Down-conn-"+i+"-> StreamId: "+down.getStreamId()+" to opId: " + ""+down.getDownstreamOperator().getOperatorId()); sb.append(Utils.NL); } sb.append("#Upstream: "+this.upstream.size()); sb.append(Utils.NL); for(int i = 0; i<this.upstream.size(); i++){ UpstreamConnection up = upstream.get(i); if(up.getUpstreamOperator() != null) { sb.append(" Up-conn-"+i+"-> StreamId: "+up.getStreamId()+" to opId: " + ""+up.getUpstreamOperator().getOperatorId()+"" + " with connType: "+up.getConnectionType()+" and dataOrigin: "+up.getDataStoreType()); } else { sb.append(" Up-conn-"+i+"-> StreamId: "+up.getStreamId()+" to opId: " + ""+up.getDataStoreType().toString()+"" + " with connType: "+up.getConnectionType()+" and dataOrigin: "+up.getDataStoreType()); } sb.append(Utils.NL); } return sb.toString(); } }