package com.revolsys.parallel.process; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import com.revolsys.parallel.channel.Channel; import com.revolsys.parallel.channel.ChannelOutput; public final class Delta<T> extends AbstractInProcess<T> { private boolean clone = true; private List<ChannelOutput<T>> out = new ArrayList<>(); private boolean running; public Delta() { } public Delta(final InProcess<T>... processes) { if (processes != null) { for (final InProcess<T> process : processes) { final Channel<T> channel = process.getIn(); addOut(channel); } } } private void addOut(final ChannelOutput<T> channel) { if (channel != null) { channel.writeConnect(); this.out.add(channel); } } @SuppressWarnings("unchecked") private T clone(final T value) { if (this.clone && value instanceof Cloneable) { try { final Class<? extends Object> valueClass = value.getClass(); final Method method = valueClass.getMethod("clone", new Class[0]); if (method != null) { return (T)method.invoke(value, new Object[0]); } } catch (final IllegalArgumentException e) { throw e; } catch (final InvocationTargetException e) { final Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { final RuntimeException re = (RuntimeException)cause; throw re; } else if (cause instanceof Error) { final Error ee = (Error)cause; throw ee; } else { throw new RuntimeException(cause.getMessage(), cause); } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new RuntimeException(e.getMessage(), e); } } return value; } @Override protected void destroy() { super.destroy(); disconnectOut(); } private void disconnectOut() { for (final ChannelOutput<T> channel : this.out) { if (channel != null) { channel.writeDisconnect(); } } } public List<ChannelOutput<T>> getOut() { return this.out; } public boolean isClone() { return this.clone; } @Override protected void run(final Channel<T> in) { this.running = true; try { while (this.running) { final T record = in.read(); if (record != null) { for (final ChannelOutput<T> out : this.out) { final T clonedObject = clone(record); out.write(clonedObject); } } } } finally { try { } finally { this.running = false; } } } public void setClone(final boolean clone) { this.clone = clone; } public void setOut(final List<ChannelOutput<T>> out) { disconnectOut(); this.out = new ArrayList<>(); for (final ChannelOutput<T> channel : out) { addOut(channel); } } }