package com.revolsys.parallel.process;
import org.apache.log4j.Logger;
import com.revolsys.parallel.channel.Channel;
import com.revolsys.parallel.channel.ChannelValueStore;
import com.revolsys.parallel.channel.ClosedException;
import com.revolsys.parallel.channel.store.Buffer;
import com.revolsys.parallel.channel.store.ZeroBuffer;
public abstract class AbstractInOutProcess<I, O> extends AbstractProcess
implements InOutProcess<I, O> {
private Channel<I> in;
private int inBufferSize = 0;
private Channel<O> out;
private int outBufferSize = 0;
public AbstractInOutProcess() {
}
public AbstractInOutProcess(final Channel<I> in, final Channel<O> out) {
this.in = in;
this.out = out;
}
protected void destroy() {
}
/**
* @return the in
*/
@Override
public Channel<I> getIn() {
if (this.in == null) {
final String channelName = getBeanName() + ".in";
final ChannelValueStore<I> buffer = newInValueStore();
final Channel<I> channel = new Channel<>(channelName, buffer);
setIn(channel);
}
return this.in;
}
public int getInBufferSize() {
return this.inBufferSize;
}
/**
* @return the out
*/
@Override
public Channel<O> getOut() {
if (this.out == null) {
final String channelName = getBeanName() + ".out";
final ChannelValueStore<O> buffer = newOutValueStore();
final Channel<O> channel = new Channel<>(channelName, buffer);
setOut(channel);
}
return this.out;
}
public int getOutBufferSize() {
return this.outBufferSize;
}
protected void init() {
}
protected ChannelValueStore<I> newInValueStore() {
if (this.inBufferSize == 0) {
return new ZeroBuffer<>();
} else if (this.inBufferSize < 0) {
return new Buffer<>();
} else {
return new Buffer<>(this.inBufferSize);
}
}
protected ChannelValueStore<O> newOutValueStore() {
if (this.outBufferSize == 0) {
return new ZeroBuffer<>();
} else if (this.outBufferSize < 0) {
return new Buffer<>();
} else {
return new Buffer<>(this.outBufferSize);
}
}
@Override
public final void run() {
boolean hasError = false;
final Logger log = Logger.getLogger(getClass());
try {
log.debug("Start");
init();
run(this.in, this.out);
} catch (final ClosedException e) {
log.debug("Shutdown");
} catch (final ThreadDeath e) {
log.debug("Shutdown");
} catch (final Throwable e) {
log.error(e.getMessage(), e);
hasError = true;
} finally {
if (this.in != null) {
this.in.readDisconnect();
}
if (this.out != null) {
this.out.writeDisconnect();
}
destroy();
}
if (hasError) {
getProcessNetwork().stop();
}
}
protected abstract void run(Channel<I> in, Channel<O> out);
/**
* @param in the in to set
*/
@Override
public void setIn(final Channel<I> in) {
this.in = in;
in.readConnect();
}
public void setInBufferSize(final int inBufferSize) {
this.inBufferSize = inBufferSize;
}
/**
* @param out the out to set
*/
@Override
public void setOut(final Channel<O> out) {
this.out = out;
out.writeConnect();
}
public void setOutBufferSize(final int outBufferSize) {
this.outBufferSize = outBufferSize;
}
}