Skip to content
Snippets Groups Projects
Commit b3905713 authored by Christian Wulf's avatar Christian Wulf
Browse files

Merge branch 'distributor-clone-strategy' into 'master'

Distributor clone strategy

This merge would add an experimental implementation for the clone strategy of the distributor. It tries to create a new instance of incoming elements and uses available getters/setters to copy the values. Technically it is not a deep copy and I doubt it to be very fast. The additional JUnit test documents the functionality.

See merge request !30
parents d6e6f1f5 02f7e195
No related branches found
No related tags found
No related merge requests found
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
*/ */
package teetime.stage.basic.distributor; package teetime.stage.basic.distributor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import teetime.framework.OutputPort; import teetime.framework.OutputPort;
/** /**
...@@ -26,7 +32,83 @@ public final class CloneStrategy implements IDistributorStrategy { ...@@ -26,7 +32,83 @@ public final class CloneStrategy implements IDistributorStrategy {
@Override @Override
public <T> boolean distribute(final OutputPort<T>[] outputPorts, final T element) { public <T> boolean distribute(final OutputPort<T>[] outputPorts, final T element) {
throw new UnsupportedOperationException(); for (final OutputPort<T> outputPort : outputPorts) {
outputPort.send(clone(element));
}
return true;
}
@SuppressWarnings("unchecked")
private static <T> T clone(final T element) {
try {
final T newInstance = (T) element.getClass().newInstance();
final Collection<Method> setters = findSetters(element.getClass());
final Collection<Method> getters = findGetters(element.getClass());
for (Method setter : setters) {
final Method getter = findCorrespondingGetter(setter, getters);
if (getter != null) {
setter.invoke(newInstance, getter.invoke(element, new Object[0]));
}
}
return newInstance;
} catch (InstantiationException e) {
throw new UnsupportedOperationException();
} catch (IllegalAccessException e) {
throw new UnsupportedOperationException();
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException();
} catch (InvocationTargetException e) {
throw new UnsupportedOperationException();
}
}
private static Collection<Method> findSetters(final Class<?> clazz) {
final List<Method> methods = new ArrayList<Method>();
for (Method method : clazz.getMethods()) {
if (method.getReturnType() == Void.TYPE) {
if (method.getParameterCount() == 1) {
if (method.getName().matches("set[A-Z].*")) {
methods.add(method);
}
}
}
}
return methods;
}
private static Collection<Method> findGetters(final Class<?> clazz) {
final List<Method> methods = new ArrayList<Method>();
for (Method method : clazz.getMethods()) {
if (method.getReturnType() != Void.TYPE) {
if (method.getParameterCount() == 0) {
if (method.getName().matches("get[A-Z].*") || method.getName().matches("is[A-Z].*")) {
methods.add(method);
}
}
}
}
return methods;
}
private static Method findCorrespondingGetter(final Method setter, final Collection<Method> getters) {
final String attributeName = setter.getName().substring(3);
for (Method getter : getters) {
if (getter.getReturnType() == setter.getParameterTypes()[0]) {
if (getter.getName().matches("get" + attributeName) || getter.getName().matches("is" + attributeName)) {
return getter;
}
}
}
return null;
} }
} }
...@@ -17,6 +17,7 @@ package teetime.stage.basic.distributor; ...@@ -17,6 +17,7 @@ package teetime.stage.basic.distributor;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
...@@ -105,11 +106,50 @@ public class DistributorTest { ...@@ -105,11 +106,50 @@ public class DistributorTest {
} }
@Test @Test
public void cloneShouldNotWork() { public void cloneForIntegerShouldNotWork() {
distributorUnderTest.setStrategy(new CloneStrategy()); distributorUnderTest.setStrategy(new CloneStrategy());
expectedException.expect(UnsupportedOperationException.class); expectedException.expect(UnsupportedOperationException.class);
this.distributorUnderTest.execute(1); this.distributorUnderTest.execute(1);
} }
@Test
public void cloneForSimpleBeanShoulWork() throws Exception {
final Distributor<SimpleBean> distributorUnderTest = new Distributor<SimpleBean>(new CloneStrategy());
final CollectorSink<SimpleBean> collector = new CollectorSink<SimpleBean>();
final IPipeFactory pipeFactory = new SingleElementPipeFactory();
pipeFactory.create(distributorUnderTest.getNewOutputPort(), collector.getInputPort());
distributorUnderTest.onStarting();
final SimpleBean originalBean = new SimpleBean(42);
distributorUnderTest.execute(originalBean);
final SimpleBean clonedBean = collector.getElements().get(0);
assertThat(originalBean, is(not(clonedBean)));
assertThat(originalBean.getValue(), is(clonedBean.getValue()));
}
private static class SimpleBean {
private int value;
@SuppressWarnings("unused")
public SimpleBean() {}
public SimpleBean(final int value) {
this.setValue(value);
}
public int getValue() {
return value;
}
public void setValue(final int value) {
this.value = value;
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment