package org.myrobotlab.document.workflow;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import org.myrobotlab.document.Document;
import org.myrobotlab.document.ProcessingStatus;
import org.myrobotlab.document.transformer.AbstractStage;
import org.myrobotlab.document.transformer.StageConfiguration;
import org.myrobotlab.document.transformer.WorkflowConfiguration;
import org.myrobotlab.logging.LoggerFactory;
import org.slf4j.Logger;
/**
*
* WorkflowWorker : this is a list of stages that will poll the workflow queue
* and process documents through that list of stages.
*/
public class WorkflowWorker extends Thread {
public final static Logger log = LoggerFactory.getLogger(WorkflowWorker.class);
boolean processing = false;
private ArrayList<AbstractStage> stages;
private final LinkedBlockingQueue<Document> queue;
WorkflowWorker(WorkflowConfiguration workflowConfig, LinkedBlockingQueue<Document> queue) throws ClassNotFoundException {
// set the thread name
this.setName("WorkflowWorker-" + workflowConfig.getName());
this.queue = queue;
stages = new ArrayList<AbstractStage>();
for (StageConfiguration stageConf : workflowConfig.getStages()) {
String stageClass = stageConf.getStageClass().trim();
String stageName = stageConf.getStageName();
log.info("Starting stage: {} class: {}", stageName, stageClass);
Class<?> sc = Workflow.class.getClassLoader().loadClass(stageClass);
try {
AbstractStage stageInst = (AbstractStage) sc.newInstance();
stageInst.startStage(stageConf);
addStage(stageInst);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void run() {
Document doc;
boolean running = true;
while (running) {
try {
doc = queue.take();
// when can this case happen
if (doc == null) {
log.info("Doc was null from workflow queue. setting running to false.");
running = false;
} else {
processing = true;
// process from the start of the workflow
processDocumentInternal(doc, 0);
processing = false;
}
} catch (InterruptedException e) {
// TODO: handle these properly
log.warn("Workflow Worker Died! {}", e.getMessage());
e.printStackTrace();
}
}
}
public boolean isProcessing() {
return processing;
}
public void processDocumentInternal(Document doc, int stageOffset) {
// TODO:
int i = 0;
for (AbstractStage s : stages.subList(i, stages.size())) {
// create a pool of stages, so that when you call processDocument
// or each thread should have it's own pool?
List<Document> childDocs = s.processDocument(doc);
i++;
if (childDocs != null) {
// process each of the children docs down the rest of the pipeline
for (Document childDoc : childDocs) {
processDocumentInternal(childDoc, i);
}
}
// TODO:should I create a completely new concept for
// callbacks?
if (doc.getStatus().equals(ProcessingStatus.DROP)) {
// if it's a drop, break here.
break;
}
}
}
public void addStage(AbstractStage stage) {
stages.add(stage);
}
public void flush() {
for (AbstractStage s : stages) {
s.flush();
}
}
}