-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow registration of a Supplier of Randomizers #28 #96
Allow registration of a Supplier of Randomizers #28 #96
Conversation
8efd2ed
to
e952c53
Compare
updated |
e952c53
to
32dda3d
Compare
Hello Pascal, Thanks for implementing this feature. I think the idea of #28 is to use Suppliers as Randomizers, ie, Suppliers will supply random values directly and not supply randomizers. Looking at this change:
Instead, I guess this would be
This is quite similar to the API suggested in #28. Do you see the difference?
I saw you changes and I believe this is good enough. But I've got another idea on how to implement this and I would like to know what do you think about it. Instead of having two mappings (one for randomizers and one for suppliers):
and the corresponding logic to both of them, my idea is to dynamically create a proxy randomizer for the supplier provided by the user. This way, everything remains intact, we only need to adapt the Supplier into a Randomizer. Here is a quick prototype: import io.github.benas.randombeans.api.Randomizer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.function.Supplier;
class RandomizerProxy implements InvocationHandler {
private Object target;
public RandomizerProxy(final Object target) {
this.target = target;
}
public static Randomizer asRandomizer(final Supplier supplier) {
return (Randomizer) Proxy.newProxyInstance(
Randomizer.class.getClassLoader(),
new Class[]{Randomizer.class},
new RandomizerProxy(supplier));
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if ("getRandomValue".equals(method.getName())) {
return target.getClass().getMethod("get").invoke(target, args);
}
return null;
}
} and a test: import io.github.benas.randombeans.api.Randomizer;
import org.junit.Test;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
public class RandomizerProxyTest {
@Test
public void testAsRandomizer() throws Exception {
MySupplier supplier = new MySupplier();
Randomizer randomizer = RandomizerProxy.asRandomizer(supplier);
Object randomValue = randomizer.getRandomValue();
assertThat(randomValue).isInstanceOf(String.class).isEqualTo("foo");
}
class MySupplier implements Supplier<String> {
@Override
public String get() {
return "foo";
}
}
} At registration time, we need to call the This way, we can register Suppliers and Randomizers in a consistent way. Random Beans will create a dynamic proxy for the Supplier at runtime. This technique will allow us to add support for guava supplier or any other type easily without impacting the internal logic. I would love to hear your thoughts. |
Hi Mahmoud, like your idea a lot. 😄 It's exactly what was requested in the issue and simple to use. I was struggling to come up with a way to use a supplier as a randomizer, but you solved it elegantly. 😄 Kind regards, |
Just a quick prototype and not exactly what was requested in #28, but maybe good enough?