How do I safely call setter after getter chain eg foo.getX().getY().setZ(...);
? For example, suppose I have a nested POJO, and I want to be able to set a field of a nested object.
Foo foo = ...
foo.getX().getY().setZ(...);
I want the behavior to be such that if X and Y do not exist then they are created automatically; otherwise it reuses the existing object.
In other words, I want it to be behave equivalent to
Foo foo = ...
X x = foo.getX();
if (x == null) {
x = new X();
foo.setX(x);
}
Y y = x.getY();
if (y == null) {
y = newY();
x.setY(y);
}
y.setZ(...);
I'm wondering if there is a trick out there using reflection/functional that comes close to this.
I also have the following constraints:
x = foo.getX()
to modify foo. Use functional programming. Create a method that accepts a getter, a setter and a supplier for the default value, that returns a getter encapsulating the logic you need:
public static <T, U> Function<T, U> getOrSetDefault(
Function<T, U> getter,
BiConsumer<T, U> setter,
Supplier<U> defaultValue) {
return t -> {
U u = getter.apply(t);
if (u == null) {
u = defaultValue.get();
setter.accept(t, u);
}
return u;
};
}
Then create these decorated getters:
Function<Foo, X> getX = getOrSetDefault(Foo::getX, Foo::setX, X::new);
Function<X, Y> getY = getOrSetDefault(X::getY, X::setY, Y::new);
Finally, chain them and apply the resulting function passing in your foo
instance as an argument:
Foo foo = ...
getX.andThen(getY).apply(foo).setZ(...);
EDIT: This assumes that both X
and Y
have a no-args constructor that is referenced by X::new
and Y::new
, respectively. But you could use anything as the Supplier
, i.e. an already created instance, or the return value of a method, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With