mklemm / jaxb-rich-contract-plugin

Implements some JAXB plugins to generate advanced contract scenarios from XSD
MIT License
67 stars 33 forks source link

Chained Builders + copyOf feature request #33

Closed pmihnea closed 6 years ago

pmihnea commented 7 years ago

Hi, While replacing a hand-made set of builders with the generated ones based on fluent-builder plugin I encountered a need for a new feature. Currently I use some builders that have the nested chained builders feature, but also the possibility to add nested builder based on a prototype builder and then fluently change certain properties. Here is an example of two classes:

class A {
 String name;
 String id;
 }
class B {
 String color;
 String id;
 }
class C {
 A a;
List<B> items;
}

Currently I can write a construct similar with this:

C.builder()
 .withA(A-builder-prototype).withId("123").end()  
 .addItem(B-builder-prototype1).withId("456").end()
 .addItem(B-builder-prototype2).withId("789").end()
.build()

But the fluent-builder plugin currently doesn't generate methods on the builder class like withA(A.Builder) but only withA() or withA(A). Also there is no method in the builder class like copyOf(A) or copyOf(A.Builder) so I could write something like C.builder().withA().copyOf(A-builder-prototype).withId("123").end() .... The first approach would be more convenient but would multiply the generated methods. The second one would only require two more methods in the builder class. I've seen that other builder generators have implemented the same feature. See FreeBuilder with mergeFrom kind of methods in the builder class. For me the chained builders feature is very important and I could not find it in other builder generators but I use also prototypes in many cases and currently I could not see how I can chain fluently the nested builders and use the prototypes. Looking at the existing API I think an easy way to extend the A.Builder would be to add such methods:

public A.Builder<_B> copyOf(final A.Builder<_B> _other ){
    return copyOf(_other.build());
}
public A.Builder<_B> copyOf(final A _other ){
    _other.copyTo(this);
    return this;
}