We have a method which receives an object of the class on the top of the class hierarchy. It uses a condition based on a field somewhere deeper in the hierarchy, and if that is fulfilled then it uses for a builder another field also somewhere deeper in the hierarchy but on a different route starting from the top class.
public Optional<SomeType> create(final TopClassInHierarchy topClass) {
Optional<SomeType> someObject = Optional.empty();
if (someCondition.evaluate(getFieldOne(topClass))) {
someObject = Optional.of(new SomeType.Builder()
.withFieldTwo(getFieldTwo(topClass))
.build());
}
return someObject;
private FieldOne getFieldOne(TopClassInHierarchy topClass) { return topClass.getSomething()...getFieldOne();
private FieldTwo getFieldTwo(TopClassInHierarchy topClass) { return topClass.getSomethingElse()...getFieldTwo();
We would like to preferably condense this into one statement, something like this
SomeType.Builder builder = new SomeType.Builder();
Optional.of(topClass)
.map(this::getFieldOne)
.filter(someCondition::evaluate)
.map(this::getFieldTwo) //???
.ifPresent(builder::withFieldTwo);
However, once we map topClass down to fieldOne for the condition evaluation, afterwards we don't seem to be able to "step back" to topClass to map it down to fieldTwo for the builder. Is this feasible with one statement?
If think this should work:
public Optional<SomeType> create(final TopClassInHierarchy topClass) {
Builder builder = new Builder();
return Optional.of(topClass)
.filter(tc -> someCondition.evaluate(getFieldOne(tc)))
.map(tc -> builder.withFieldTwo(getFieldTwo(tc)).build());
}
someCondition.evaluate
in filter
needs fieldOne
as input, but to keep topClass
as the current state of the Optional
we do not map
to fieldOne
. Instead the method getFieldOne
is used. If the filter is passed we can map topClass
to the result of the builder
applied on fieldTwo
retrieved by the method getFieldTwo
.
Or with more intermediate mappings:
public Optional<SomeType> create(final TopClassInHierarchy topClass) {
Builder builder = new Builder();
return Optional.of(topClass)
.filter(tc -> someCondition.evaluate(getFieldOne(tc)))
.map(this::getFieldTwo)
.map(builder::withFieldTwo)
.map(Builder::build);
}