Closed matthiasmast closed 2 years ago
Hello @matthiasmast, Could you please share an example input class and expected generated code?
Hello @helospark
I think something like this should work
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
public class Example{
private int intData = 5;
private Collection<String> texts = List.of("default");
private String noData;
public int getIntData(){
return this.intData;
}
public Collection<String> getTexts(){
return this.texts;
}
public String getNoData(){
return this.noData;
}
@Generated("SparkTools")
private Example(Builder builder){
if(builder.isIntDataSet){
this.intData = builder.intData;
}
if(builder.isTextsSet){
this.texts = builder.texts;
}
if(builder.isNoDataSet){
this.noData = builder.noData;
}
}
@Generated("SparkTools")
public static Builder builder(){
return new Builder();
}
@Generated("SparkTools")
public static final class Builder{
private int intData;
private boolean isIntDataSet = false;
private Collection<String> texts = Collections.emptyList();
private boolean isTextsSet = false;
private String noData;
private boolean isNoDataSet = false;
private Builder(){
}
public Builder withIntData(int intData){
this.intData = intData;
this.isIntDataSet = true;
return this;
}
public Builder withTexts(Collection<String> texts){
this.texts = texts;
this.isTextsSet = true;
return this;
}
public Builder withNoData(String noData){
this.noData = noData;
this.isNoDataSet = true;
return this;
}
public Example build(){
return new Example(this);
}
}
}
Test
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.List;
import org.junit.Test;
public class ExampleTest{
@Test
public void testNoData(){
Example example = Example.builder()
.build();
assertEquals(5, example.getIntData());
assertEquals(1, example.getTexts().size());
assertNull(example.getNoData());
}
@Test
public void testWithData(){
Example example = Example.builder()
.withIntData(10)
.withTexts(List.of("1", "2"))
.withNoData(null)
.build();
assertEquals(10, example.getIntData());
assertEquals(2, example.getTexts().size());
assertNull(example.getNoData());
}
}
I think this would reflect very well the intention of the class creator if he initialised the fields with values
could even be improved like this for more complex default values
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
public class Example{
private int intData;
private Collection<String> texts;
private String noData;
private int defaultIntData(){
return 5;
}
private Collection<String> defaultTexts(){
return List.of("default");
}
private String defaultNoData(){
return null;
}
public int getIntData(){
return this.intData;
}
public Collection<String> getTexts(){
return this.texts;
}
public String getNoData(){
return this.noData;
}
@Generated("SparkTools")
private Example(Builder builder){
if(builder.isIntDataSet){
this.intData = builder.intData;
} else{
this.intData = this.defaultIntData();
}
if(builder.isTextsSet){
this.texts = builder.texts;
} else{
this.texts = this.defaultTexts();
}
if(builder.isNoDataSet){
this.noData = builder.noData;
} else{
this.noData = this.defaultNoData();
}
}
@Generated("SparkTools")
public static Builder builder(){
return new Builder();
}
@Generated("SparkTools")
public static final class Builder{
private int intData;
private boolean isIntDataSet = false;
private Collection<String> texts = Collections.emptyList();
private boolean isTextsSet = false;
private String noData;
private boolean isNoDataSet = false;
private Builder(){
}
public Builder withIntData(int intData){
this.intData = intData;
this.isIntDataSet = true;
return this;
}
public Builder withTexts(Collection<String> texts){
this.texts = texts;
this.isTextsSet = true;
return this;
}
public Builder withNoData(String noData){
this.noData = noData;
this.isNoDataSet = true;
return this;
}
public Example build(){
return new Example(this);
}
}
}
but then ordering is important
I wonder why not just copy the field assignments to the builder, like:
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
public class Example{
private int intData = 5;
private Collection<String> texts = List.of("default");
private String noData;
public int getIntData(){
return this.intData;
}
public Collection<String> getTexts(){
return this.texts;
}
public String getNoData(){
return this.noData;
}
@Generated("SparkTools")
private Example(Builder builder){
this.intData = builder.intData;
this.texts = builder.texts;
this.noData = builder.noData;
}
@Generated("SparkTools")
public static Builder builder(){
return new Builder();
}
@Generated("SparkTools")
public static final class Builder{
private int intData = 5;
private Collection<String> texts = List.of("default");
private String noData;
private Builder(){
}
public Builder withIntData(int intData){
this.intData = intData;
return this;
}
public Builder withTexts(Collection<String> texts){
this.texts = texts;
return this;
}
public Builder withNoData(String noData){
this.noData = noData;
return this;
}
public Example build(){
return new Example(this);
}
}
}
This seems cleaner, I guess the only thing not supported by this is the initialization of a field by private (non-static) method.
that would also work. A disadvantage here would be that if you change the default values you have to remember to change them in both places or to renew the builder.
Released change in 0.0.24, please check.
works fine. Thank you very much!
Hello,
thank you for this great tool.
I didn't find an option for default values. If a value was not set in the builder the field in the class will be null even if the field was initialised with a value.
I think this would be a really helpful feature.
Use cases: