/*
*
* YAQP - Yet Another QSAR Project:
* Machine Learning algorithms designed for the prediction of toxicological
* features of chemical compounds become available on the Web. Yaqp is developed
* under OpenTox (http://opentox.org) which is an FP7-funded EU research project.
* This project was developed at the Automatic Control Lab in the Chemical Engineering
* School of National Technical University of Athens. Please read README for more
* information.
*
* Copyright (C) 2009-2010 Pantelis Sopasakis & Charalampos Chomenides
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact:
* Pantelis Sopasakis
* chvng@mail.ntua.gr
* Address: Iroon Politechniou St. 9, Zografou, Athens Greece
* tel. +30 210 7723236
*/
package org.opentox.core.processors;
import org.opentox.core.exceptions.YaqpException;
import org.opentox.core.interfaces.JMultiProcessorStatus.STATUS;
import org.opentox.core.interfaces.JProcessor;
/**
* A set of jobs to be executed through a pipeline of processors
* is a sequential layout if some processor is enabled. Note that if P1, P2, ..., PN
* is a sequence of processors building a pipeline, then the output type from a processor
* P_k should be a valid input to P_k+1 otherwise the processor P_k+1 will throw an
* exception.
* @param <Input> Type for the input to the pipeline
* @param <Output> Type for the output of the pipeline
* @param <P> Type of processors contained in the pipeline
* @author Sopasakis Pantelis
* @author Charalampos Chomenides
*/
@SuppressWarnings({"unchecked"})
public class Pipeline<Input, Output, P extends JProcessor<Input, Output>>
extends AbstractMultiProcessor<Input, Output, P> {
private String PROPERTY_PIPELINE_STATUS = getStatus().getClass().getName();
/**
* Constructs a new Pipeline which is an ordered sequence of Processors
* that are used to process input data sequentially (if enabled)
*/
public Pipeline() {
super();
setfailSensitive(true);
}
/**
* Construct a new pipeline providing a sequence of processors.
* @param processors
* A sequence of processor nested in a pipeline.
*/
public Pipeline(P... processors){
this();
for (P p : processors){
this.add(p);
}
}
public void addProcessors(P... processors){
for (P p : processors){
add(p);
}
}
/**
*
*
* This method processes the input data to produce some output,
* using the sequence of processors. The result from the first processor,
* is input to the second and so on. Any non-enabled processors are overriden.
* @param data
* @return Pipeline Output
* @throws YaqpException
*/
public Output process(Input data) throws YaqpException {
long start_time = 0;
getStatus().setMessage("pipeline in process");
Object o = data;
// Process:
for (int i = 0; i < size(); i++) {
try {
if (get(i).isEnabled()) {
start_time = System.currentTimeMillis();
getStatus().increment(STATUS.INITIALIZED);
o = get(i).process((Input) o); // --> this might throw a YaqpException
Output o1 = (Output) o;
getStatus().increment(STATUS.PROCESSED);
getStatus().incrementElapsedTime(STATUS.PROCESSED, System.currentTimeMillis() - start_time);
firePropertyChange(PROPERTY_PIPELINE_STATUS, null, getStatus());
}
} catch (YaqpException ex) {
if (isfailSensitive()) {
throw ex;
}
getStatus().increment(STATUS.ERROR);
getStatus().incrementElapsedTime(STATUS.ERROR, System.currentTimeMillis() - start_time);
}catch (ClassCastException ex){
throw new ClassCastException("Typecasting error in the pipeline - be more careful");
}
}
getStatus().setMessage("Pipeline completed the job.");
getStatus().completed();
firePropertyChange(PROPERTY_PIPELINE_STATUS, null, getStatus());
// Try to cast the result as 'Output'
try {
return (Output) o;
} catch (ClassCastException ex) {
String message = "pipeline output typecasting error";
throw new ClassCastException(message);
}
}
}