Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
37e85df
adding explicit setter property in builder definition
AndreasIgel May 9, 2025
209e76f
Improving Javadoc
AndreasIgel May 9, 2025
6f4cccc
Renaming fields in BuilderDefinition for better understanding
AndreasIgel May 9, 2025
65a90d8
Adding fields of constructor to BuilderDefintion too
AndreasIgel May 9, 2025
0a00c54
Merge branch origin/main into feature/supporting-final-fields
AndreasIgel Aug 28, 2025
a8bdfa3
Updating tests according to desired functionality
AndreasIgel Aug 28, 2025
d9f69a8
adding test for exact usage examples in Readme.MD
AndreasIgel Aug 28, 2025
779be11
changing example in Readme to use HashMapBuilder instead of Map.of
AndreasIgel Aug 28, 2025
9c75892
Merge main into feature/mapbuilder-in-readme - resolved conflicts
AndreasIgel Sep 7, 2025
15f4e5d
Fixing failure in merging main
AndreasIgel Sep 7, 2025
1a4c16b
Fixing tests (double compilation in one test)
AndreasIgel Sep 7, 2025
bad2005
Codeformat
AndreasIgel Sep 7, 2025
7a0fe9a
Implementation of helper-functions and HashMapBuilder supplier
AndreasIgel Sep 7, 2025
c6ee710
Adepting tests to final implementation of functionality
AndreasIgel Sep 7, 2025
4dcae4b
Fixing codestyle
AndreasIgel Sep 7, 2025
6439fb1
Removed unused functionality
AndreasIgel Sep 7, 2025
4c0c1d6
Extending coverage by adding test for raw type
AndreasIgel Sep 7, 2025
b68a11d
Adding a test for generic properties without being lists,sets,maps
AndreasIgel Sep 7, 2025
8603f41
Fixing codeformat
AndreasIgel Sep 7, 2025
92d275b
Updating coverage calculation. according to common sense 80% should b…
AndreasIgel Sep 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,9 @@ Project project = ProjectBuilder.create()
.description("Update README and add Javadocs")
.build())
)
.metadata(Map.of("version", "1.0.0", "owner", "dev-team"))
.metadata(metadata -> metadata
.put("version", "1.0.0")
.put("owner", "dev-team"))
.build();
```

Expand Down
5 changes: 3 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ coverage:
status:
project:
default:
target: auto
target: 80%
patch:
default:
target: auto
target: 90%
threshold: 5%

comment:
layout: "condensed_header, condensed_files, condensed_footer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class BuilderDefinitionDto {

/**
* List of all fields of target DTO which are supported by builder. A field could be supported by
* several functions in builder.
* multiple functions in builder.
*/
private final List<FieldDto> setterFieldsForBuilder = new LinkedList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.apache.commons.lang3.StringUtils;
import org.javahelpers.simple.builders.core.annotations.SimpleBuilder;
import org.javahelpers.simple.builders.core.builders.ArrayListBuilder;
import org.javahelpers.simple.builders.core.builders.HashMapBuilder;
import org.javahelpers.simple.builders.core.builders.HashSetBuilder;
import org.javahelpers.simple.builders.processor.dtos.*;
import org.javahelpers.simple.builders.processor.exceptions.BuilderException;
Expand Down Expand Up @@ -134,26 +135,38 @@ private static Optional<MethodDto> createMethodDto(

private static void addAdditionalHelperMethodsForField(
FieldDto result, String fieldName, TypeName fieldType) {
if (isList(fieldType)) {
List<TypeName> innerTypes;
int innerTypesCnt;
if (fieldType instanceof TypeNameGeneric fieldTypeGeneric) {
innerTypes = fieldTypeGeneric.getInnerTypeArguments();
innerTypesCnt = innerTypes.size();
} else {
innerTypes = null;
innerTypesCnt = 0;
}

if (isList(fieldType) && innerTypesCnt == 1) {
result.addMethod(
createFieldSetterWithTransform(
fieldName,
"List.of(%s)",
new TypeNameArray(fieldType.getInnerType().get(), false),
new TypeNameArray(innerTypes.get(0), false),
result.getFieldGenerics()));
return;
}
if (isSet(fieldType)) {
} else if (isSet(fieldType) && innerTypesCnt == 1) {
result.addMethod(
createFieldSetterWithTransform(
fieldName,
"Set.of(%s)",
new TypeNameArray(fieldType.getInnerType().get(), true),
new TypeNameArray(innerTypes.get(0), true),
result.getFieldGenerics()));
return;
}
if (isMap(fieldType)) {
// TODO MAP (having 2 inner classes, TypeNameGeneric is not able to address that yet)
} else if (isMap(fieldType) && innerTypesCnt == 2) {
TypeName mapEntryType =
new TypeNameArray(
new TypeNameGeneric("java.util", "Map.Entry", innerTypes.get(0), innerTypes.get(1)),
false);
result.addMethod(
createFieldSetterWithTransform(
fieldName, "Map.ofEntries(%s)", mapEntryType, result.getFieldGenerics()));
}
}

Expand Down Expand Up @@ -185,16 +198,33 @@ private static void addConsumerMethodsForField(
&& hasEmptyConstructor(fieldTypeElement, elementUtils)) {
// Only generate a Consumer for concrete classes with an accessible empty constructor
result.addMethod(createFieldConsumer(fieldName, fieldType));
} else if (isList(fieldType)) {
} else if (isList(fieldType)
&& fieldType instanceof TypeNameGeneric fieldTypeGeneric
&& fieldTypeGeneric.getInnerTypeArguments().size() == 1) {
result.addMethod(
createFieldConsumerWithBuilder(
fieldName, map2TypeName(ArrayListBuilder.class), fieldType.getInnerType().get()));
} else if (isMap(fieldType)) {
// TODO MAP (having 2 inner classes, TypeNameGeneric is not able to adress that yet)
} else if (isSet(fieldType)) {
fieldName,
map2TypeName(ArrayListBuilder.class),
fieldTypeGeneric.getInnerTypeArguments().get(0)));
} else if (isMap(fieldType)
&& fieldType instanceof TypeNameGeneric fieldTypeGeneric
&& fieldTypeGeneric.getInnerTypeArguments().size() == 2) {
TypeName builderTargetTypeName =
new TypeNameGeneric(
map2TypeName(HashMapBuilder.class),
fieldTypeGeneric.getInnerTypeArguments().get(0),
fieldTypeGeneric.getInnerTypeArguments().get(1));
MethodDto mapConsumerWithBuilder =
BuilderDefinitionCreator.createFieldConsumerWithBuilder(fieldName, builderTargetTypeName);
result.addMethod(mapConsumerWithBuilder);
} else if (isSet(fieldType)
&& fieldType instanceof TypeNameGeneric fieldTypeGeneric
&& fieldTypeGeneric.getInnerTypeArguments().size() == 1) {
result.addMethod(
createFieldConsumerWithBuilder(
fieldName, map2TypeName(HashSetBuilder.class), fieldType.getInnerType().get()));
fieldName,
map2TypeName(HashSetBuilder.class),
fieldTypeGeneric.getInnerTypeArguments().get(0)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,60 @@ public void setAge(int age) {
"public PersonBuilder age(int age)");
}

@Test
void shouldHandleGenericWrapperTypes() {

JavaFileObject optionalWrapperClass =
ProcessorTestUtils.forSource(
"""
package test;
import java.util.Optional;
import java.time.LocalDate;
import org.javahelpers.simple.builders.core.annotations.SimpleBuilder;

@SimpleBuilder
public class OptionalWrapper {
private Optional<String> name;
private Optional<Integer> count;
private Optional<LocalDate> date;

public Optional<String> getName() { return name; }
public void setName(Optional<String> name) { this.name = name; }

public Optional<Integer> getCount() { return count; }
public void setCount(Optional<Integer> count) { this.count = count; }

public Optional<LocalDate> getDate() { return date; }
public void setDate(Optional<LocalDate> date) { this.date = date; }
}
""");

// Test builder generation (without usage)
Compilation compilation = compile(optionalWrapperClass);
String optionalBuilder = loadGeneratedSource(compilation, "OptionalWrapperBuilder");

// Verify Optional wrapper generates basic methods
assertGenerationSucceeded(compilation, "OptionalWrapperBuilder", optionalBuilder);
ProcessorAsserts.assertContaining(
optionalBuilder,
"public static OptionalWrapperBuilder create()",
"public OptionalWrapperBuilder name(Optional<String> name)",
"public OptionalWrapperBuilder count(Optional<Integer> count)",
"public OptionalWrapperBuilder date(Optional<LocalDate> date)",
"public OptionalWrapper build()");

// Verify no additional helper methods are generated for these generic types
// (since they don't match List/Set/Map patterns)
ProcessorAsserts.assertNotContaining(
optionalBuilder,
"nameBuilderConsumer",
"countBuilderConsumer",
"dateBuilderConsumer",
"name(String...)",
"count(Integer...)",
"date(LocalDate...)");
}

@Test
void shouldGenerateSetterForClassInDifferentPackage() {
// Given
Expand Down Expand Up @@ -1004,42 +1058,6 @@ void shouldNotGenerateConsumersForPrimitiveAndArrayFields() {
notContains("public PrimAndArrayBuilder names(Consumer"));
}

@Test
void shouldNotGenerateSpecialMethodsForMapBeyondSetterAndSupplier() {
// Given
String packageName = "test";
String className = "HasMap";
String builderClassName = className + "Builder";

JavaFileObject sourceFile =
ProcessorTestUtils.simpleBuilderClass(
packageName,
className,
"""
private java.util.Map<String, Integer> map;

public java.util.Map<String, Integer> getMap() { return map; }
public void setMap(java.util.Map<String, Integer> map) { this.map = map; }
""");

// When
Compilation compilation = compile(sourceFile);

// Then
String generatedCode = loadGeneratedSource(compilation, builderClassName);
assertGenerationSucceeded(compilation, builderClassName, generatedCode);

// Expect only direct setter and supplier; no varargs/consumer for Map
ProcessorAsserts.assertingResult(
generatedCode,
contains("public HasMapBuilder map("),
contains("mapSupplier)"),
notContains("map(String..."),
notContains("map(java.lang.String..."),
notContains("mapBuilderConsumer"),
notContains("mapConsumer"));
}

@Test
void shouldNotGenerateConsumerForAbstractHelper() {
// Given
Expand Down Expand Up @@ -1959,4 +1977,57 @@ void shouldHandleOverloadedSettersForSameFieldWithoutConflicts() {
"public OverloadedNamesBuilder names(Supplier<List<String>> namesSupplier)",
"public OverloadedNamesBuilder names(String... names)");
}

@Test
void collectionsWithRawTypes_shouldGenerateBuilders() {

JavaFileObject rawCollectionsClass =
ProcessorTestUtils.forSource(
"""
package test;
import org.javahelpers.simple.builders.core.annotations.SimpleBuilder;
import java.util.List;
import java.util.Set;
import java.util.Map;
@SimpleBuilder
public class RawCollections {
private List rawList;
private Set rawSet;
private Map rawMap;

public List getRawList() { return rawList; }
public void setRawList(List rawList) { this.rawList = rawList; }

public Set getRawSet() { return rawSet; }
public void setRawSet(Set rawSet) { this.rawSet = rawSet; }

public Map getRawMap() { return rawMap; }
public void setRawMap(Map rawMap) { this.rawMap = rawMap; }
}
""");

// Test builder generation (without usage)
Compilation compilation = compile(rawCollectionsClass);
String generatedCode = loadGeneratedSource(compilation, "RawCollectionsBuilder");
assertGenerationSucceeded(compilation, "RawCollectionsBuilder", generatedCode);

// Verify basic builder methods are generated
ProcessorAsserts.assertContaining(
generatedCode,
"public static RawCollectionsBuilder create()",
"public RawCollectionsBuilder rawList(List rawList)",
"public RawCollectionsBuilder rawSet(Set rawSet)",
"public RawCollectionsBuilder rawMap(Map rawMap)",
"public RawCollections build()");

// Verify no additional helper methods are generated for raw types
ProcessorAsserts.assertNotContaining(
generatedCode,
"rawListBuilderConsumer",
"rawSetBuilderConsumer",
"rawMapBuilderConsumer",
"rawList(String...)",
"rawSet(String...)",
"rawMap(Map.Entry)");
}
}
Loading
Loading