Skip to content

Instantly share code, notes, and snippets.

@mikaelhg
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikaelhg/1c167d36bd97cdedf83e to your computer and use it in GitHub Desktop.
Save mikaelhg/1c167d36bd97cdedf83e to your computer and use it in GitHub Desktop.
Playing around with ideas for easily readable bean or even JSON converters using Java 8 lambdas
package io.mikael.convert;
import java.util.ArrayList;
import java.util.List;
import java.util.function.*;
public class LambdaConverter {
public static class Foo {
public String getA() { return "A"; }
public void invalid(final String in) { System.err.println("INVALID"); }
}
public static class Bar {
public void setB(final String b) { System.out.println("b: " + b); }
public String invalid() { System.err.println("INVALID"); return "INVALID"; }
}
public static abstract class AbstractFieldTransfer<SOURCE, TARGET> {
protected final Converter<SOURCE, TARGET> converter;
public AbstractFieldTransfer(final Converter<SOURCE, TARGET> converter) {
this.converter = converter;
}
public boolean isActive(final SOURCE source) {
return true;
}
public abstract void convert(final SOURCE source, final TARGET target);
}
public static class FieldGroup<SOURCE, TARGET> extends AbstractFieldTransfer<SOURCE, TARGET> {
private final List<AbstractFieldTransfer<SOURCE, TARGET>> transfers = new ArrayList<>();
private final Predicate<SOURCE> predicate;
private FieldGroup() {
this(null);
}
public FieldGroup(final Converter<SOURCE, TARGET> converter) {
this(converter, null);
}
public FieldGroup(final Converter<SOURCE, TARGET> converter, final Predicate<SOURCE> predicate) {
super(converter);
this.predicate = predicate;
}
public Converter<SOURCE, TARGET> end() {
return converter;
}
public <D> FieldGroup<SOURCE, TARGET> field(
final Function<SOURCE, D> in, final BiConsumer<TARGET, D> out)
{
transfers.add(new Field<>(converter, in, out));
return this;
}
public void convert(final SOURCE source, final TARGET target) {
transfers.stream()
.filter(t -> t.isActive(source))
.forEach(t -> t.convert(source, target));
}
@Override
public boolean isActive(final SOURCE source) {
return predicate == null || predicate.test(source);
}
}
public static class Field<SOURCE, TARGET, D> extends AbstractFieldTransfer<SOURCE, TARGET> {
private final Function<SOURCE, D> in;
private final BiConsumer<TARGET, D> out;
private Field() {
this(null, null, null);
}
public Field(final Converter<SOURCE, TARGET> converter,
final Function<SOURCE, D> in, final BiConsumer<TARGET, D> out)
{
super(converter);
this.in = in;
this.out = out;
}
public void convert(final SOURCE source, final TARGET target) {
out.accept(target, in.apply(source));
}
}
public static class Converter<SOURCE, TARGET> {
private final List<AbstractFieldTransfer<SOURCE, TARGET>> transfers = new ArrayList<>();
public static <S, T> Converter<S, T> fromTo(final Class<S> cs, final Class<T> ct) {
return new Converter<>();
}
public static <S, T> Converter<S, T> fromTo() {
return new Converter<>();
}
public <D> Converter<SOURCE, TARGET> field(
final Function<SOURCE, D> in, final BiConsumer<TARGET, D> out)
{
transfers.add(new Field<>(this, in, out));
return this;
}
public FieldGroup<SOURCE, TARGET> fieldGroup() {
final FieldGroup<SOURCE, TARGET> ret = new FieldGroup<>(this);
transfers.add(ret);
return ret;
}
public FieldGroup<SOURCE, TARGET> fieldGroup(final Predicate<SOURCE> isGroupActive) {
final FieldGroup<SOURCE, TARGET> ret = new FieldGroup<>(this, isGroupActive);
transfers.add(ret);
return ret;
}
public TARGET convert(final SOURCE source, final TARGET target) {
transfers.stream()
.filter(t -> t.isActive(source))
.forEach(t -> t.convert(source, target));
return target;
}
}
public static void main(String[] args) {
final Converter<Foo, Bar> c1 = Converter.<Foo, Bar>fromTo()
.field(Foo::getA, Bar::setB);
final Converter<Foo, Bar> c2 = Converter.fromTo(Foo.class, Bar.class)
.field(Foo::getA, Bar::setB);
final Converter<Foo, Bar> c3 = Converter.fromTo(Foo.class, Bar.class)
.fieldGroup()
.field(Foo::getA, Bar::setB)
.end();
final Converter<Foo, Bar> c4 = Converter.fromTo(Foo.class, Bar.class)
.fieldGroup(f -> f.getA().equals("I AM A TEAPOT"))
.field(Foo::getA, Bar::setB)
.end();
final Bar bar = Converter.fromTo(Foo.class, Bar.class)
.fieldGroup(f -> f.getA().equals("I AM A TEAPOT"))
.field(Foo::getA, Bar::setB)
.end()
.convert(new Foo(), new Bar());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment