diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index e04cc6d..06229da 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -18,16 +18,16 @@ jobs:
build:
strategy:
matrix:
- java: [ '17', '21' ]
+ java: [ '11', '16', '17', '21', '22' ]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - name: Set up JDK
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.java }}
- distribution: 'temurin'
- cache: maven
- - name: Build with Maven
- run: mvn -B -ntp verify --file pom.xml
+ - uses: actions/checkout@v4
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.java }}
+ distribution: 'temurin'
+ cache: maven
+ - name: Build with Maven
+ run: mvn -B -ntp verify --file pom.xml
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 66a9ada..44c6667 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,8 +44,8 @@
1.5.0
3.1.2
- 17
- 17
+ 11
+ 11
1.9.0
1.13.0
diff --git a/processor/src/main/java/io/jonasg/bob/BuildableField.java b/processor/src/main/java/io/jonasg/bob/BuildableField.java
index 84edfd3..41e2b6b 100644
--- a/processor/src/main/java/io/jonasg/bob/BuildableField.java
+++ b/processor/src/main/java/io/jonasg/bob/BuildableField.java
@@ -1,5 +1,6 @@
package io.jonasg.bob;
+import java.util.Objects;
import java.util.Optional;
import javax.lang.model.type.TypeMirror;
@@ -7,23 +8,84 @@
/**
* Represents a field that is buildable
*
- * @param name the name of the field as declared in the type that will be built
- * @param isConstructorArgument indicates if the field can be set through the constructor
- * @param setterMethodName the name of the setter method to access the field.
- * @param type the type of the field
+ * {@link BuildableField#name} the name of the field as declared in the type that will be built
+ * {@link BuildableField#isConstructorArgument} indicates if the field can be set through the constructor
+ * {@link BuildableField#setterMethodName} the name of the setter method to access the field.
+ * {@link BuildableField#type} the type of the field
*/
-public record BuildableField(
- String name,
- boolean isConstructorArgument,
- boolean isMandatory,
- Optional setterMethodName,
- TypeMirror type) {
-
- public static BuildableField fromConstructor(String fieldName, TypeMirror type) {
- return new BuildableField(fieldName, true, false, Optional.empty(), type);
- }
-
- public static BuildableField fromSetter(String fieldName, boolean fieldIsMandatory, String setterMethodName, TypeMirror type) {
- return new BuildableField(fieldName, false, fieldIsMandatory, Optional.of(setterMethodName), type);
- }
+public final class BuildableField {
+ private final String name;
+ private final boolean isConstructorArgument;
+ private final boolean isMandatory;
+ private final Optional setterMethodName;
+ private final TypeMirror type;
+
+ public BuildableField(
+ String name,
+ boolean isConstructorArgument,
+ boolean isMandatory,
+ Optional setterMethodName,
+ TypeMirror type) {
+ this.name = name;
+ this.isConstructorArgument = isConstructorArgument;
+ this.isMandatory = isMandatory;
+ this.setterMethodName = setterMethodName;
+ this.type = type;
+ }
+
+ public static BuildableField fromConstructor(String fieldName, TypeMirror type) {
+ return new BuildableField(fieldName, true, false, Optional.empty(), type);
+ }
+
+ public static BuildableField fromSetter(String fieldName, boolean fieldIsMandatory, String setterMethodName, TypeMirror type) {
+ return new BuildableField(fieldName, false, fieldIsMandatory, Optional.of(setterMethodName), type);
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public boolean isConstructorArgument() {
+ return isConstructorArgument;
+ }
+
+ public boolean isMandatory() {
+ return isMandatory;
+ }
+
+ public Optional setterMethodName() {
+ return setterMethodName;
+ }
+
+ public TypeMirror type() {
+ return type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (BuildableField) obj;
+ return Objects.equals(this.name, that.name) &&
+ this.isConstructorArgument == that.isConstructorArgument &&
+ this.isMandatory == that.isMandatory &&
+ Objects.equals(this.setterMethodName, that.setterMethodName) &&
+ Objects.equals(this.type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, isConstructorArgument, isMandatory, setterMethodName, type);
+ }
+
+ @Override
+ public String toString() {
+ return "BuildableField[" +
+ "name=" + name + ", " +
+ "isConstructorArgument=" + isConstructorArgument + ", " +
+ "isMandatory=" + isMandatory + ", " +
+ "setterMethodName=" + setterMethodName + ", " +
+ "type=" + type + ']';
+ }
+
}
diff --git a/processor/src/main/java/io/jonasg/bob/BuilderTypeSpecFactory.java b/processor/src/main/java/io/jonasg/bob/BuilderTypeSpecFactory.java
index 804d4e0..a876d27 100644
--- a/processor/src/main/java/io/jonasg/bob/BuilderTypeSpecFactory.java
+++ b/processor/src/main/java/io/jonasg/bob/BuilderTypeSpecFactory.java
@@ -65,11 +65,11 @@ protected BuilderTypeSpecFactory(TypeDefinition typeDefinition, Buildable builda
private List extractBuildableFieldsFrom(TypeDefinition typeDefinition) {
var fieldNames = typeDefinition.fields().stream()
.map(FieldDefinition::name)
- .toList();
+ .collect(Collectors.toList());
List eligibleConstructorParams = this.constructorDefinition.parameters()
.stream()
.filter(p -> fieldNames.contains(p.name()))
- .toList();
+ .collect(Collectors.toList());
Stream constructorBuildableFields = this.constructorDefinition.parameters()
.stream()
.filter(p -> fieldNames.contains(p.name()))
@@ -84,13 +84,13 @@ private List extractBuildableFieldsFrom(TypeDefinition typeDefin
|| p.field().isAnnotatedWith(Buildable.Mandatory.class);
return BuildableField.fromSetter(p.field().name(), fieldIsMandatory, p.methodName(), p.type());
});
- return Stream.concat(constructorBuildableFields, setterBuildableFields).toList();
+ return Stream.concat(constructorBuildableFields, setterBuildableFields).collect(Collectors.toList());
}
private ConstructorDefinition extractConstructorDefinitionFrom(TypeDefinition typeDefinition) {
var buildableConstructors = typeDefinition.constructors().stream()
.filter(c -> c.isAnnotatedWith(Buildable.Constructor.class))
- .toList();
+ .collect(Collectors.toList());
if (buildableConstructors.size() > 1) {
throw new IllegalArgumentException("Only one constructor can be annotated with @Buildable.Constructor");
}
@@ -132,7 +132,7 @@ private List generateSetters() {
return this.buildableFields.stream()
.filter(this::notExcluded)
.map(this::generateSetterForField)
- .toList();
+ .collect(Collectors.toList());
}
protected MethodSpec generateSetterForField(BuildableField field) {
@@ -166,7 +166,7 @@ private boolean isEnforcedAllowNullsConstructorPolicy() {
private List generateFields() {
return buildableFields.stream()
.map(this::generateField)
- .toList();
+ .collect(Collectors.toList());
}
protected FieldSpec generateField(BuildableField field) {
@@ -249,21 +249,27 @@ protected CodeBlock generateFieldAssignment(BuildableField field) {
.build();
} else {
return CodeBlock.builder()
- .addStatement("instance.%s(this.%s)".formatted(setterName(field.setterMethodName().orElseThrow()),
+ .addStatement(String.format("instance.%s(this.%s)", setterName(field.setterMethodName().orElseThrow()),
field.name()))
.build();
}
}
protected String defaultForType(TypeMirror type) {
- return switch (type.toString()) {
- case "int" -> "0";
- case "long" -> "0L";
- case "float" -> "0.0f";
- case "double" -> "0.0d";
- case "boolean" -> "false";
- default -> "null";
- };
+ switch (type.toString()) {
+ case "int":
+ return "0";
+ case "long":
+ return "0L";
+ case "float":
+ return "0.0f";
+ case "double":
+ return "0.0d";
+ case "boolean":
+ return "false";
+ default:
+ return "null";
+ }
}
private MethodSpec of() {
diff --git a/processor/src/main/java/io/jonasg/bob/StepBuilderInterfaceTypeSpecFactory.java b/processor/src/main/java/io/jonasg/bob/StepBuilderInterfaceTypeSpecFactory.java
index 07316f9..21cb155 100644
--- a/processor/src/main/java/io/jonasg/bob/StepBuilderInterfaceTypeSpecFactory.java
+++ b/processor/src/main/java/io/jonasg/bob/StepBuilderInterfaceTypeSpecFactory.java
@@ -7,8 +7,10 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
import javax.lang.model.element.Modifier;
@@ -40,9 +42,46 @@ public StepBuilderInterfaceTypeSpecFactory(TypeDefinition typeDefinition,
this.packageName = packageName;
}
- record BuilderDetails(TypeSpec typeSpec, Set interfaces) {
+ final class BuilderDetails {
+ private final TypeSpec typeSpec;
+ private final Set interfaces;
- }
+ BuilderDetails(TypeSpec typeSpec, Set interfaces) {
+ this.typeSpec = typeSpec;
+ this.interfaces = interfaces;
+ }
+
+ public TypeSpec typeSpec() {
+ return typeSpec;
+ }
+
+ public Set interfaces() {
+ return interfaces;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (BuilderDetails) obj;
+ return Objects.equals(this.typeSpec, that.typeSpec) &&
+ Objects.equals(this.interfaces, that.interfaces);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(typeSpec, interfaces);
+ }
+
+ @Override
+ public String toString() {
+ return "BuilderDetails[" +
+ "typeSpec=" + typeSpec + ", " +
+ "interfaces=" + interfaces + ']';
+ }
+
+
+ }
BuilderDetails typeSpec(String builderImplName) {
Set interfaces = new HashSet<>();
@@ -88,7 +127,7 @@ BuilderDetails typeSpec(String builderImplName) {
.stream()
.filter(field -> (field.isConstructorArgument() && isEnforcedConstructorPolicy())
|| field.isMandatory())
- .toList();
+ .collect(Collectors.toList());
mandatoryFields
.subList(0, mandatoryFields.size() - 1)
.stream()
diff --git a/processor/src/main/java/io/jonasg/bob/TypeSpecInterfaceBuilder.java b/processor/src/main/java/io/jonasg/bob/TypeSpecInterfaceBuilder.java
index dd7fe37..6fc8920 100644
--- a/processor/src/main/java/io/jonasg/bob/TypeSpecInterfaceBuilder.java
+++ b/processor/src/main/java/io/jonasg/bob/TypeSpecInterfaceBuilder.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import javax.lang.model.element.Modifier;
@@ -84,7 +85,44 @@ public TypeSpec build() {
}
- record Argument(TypeName typeName, String name) {
- }
+ final class Argument {
+ private final TypeName typeName;
+ private final String name;
+
+ Argument(TypeName typeName, String name) {
+ this.typeName = typeName;
+ this.name = name;
+ }
+
+ public TypeName typeName() {
+ return typeName;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (Argument) obj;
+ return Objects.equals(this.typeName, that.typeName) &&
+ Objects.equals(this.name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(typeName, name);
+ }
+
+ @Override
+ public String toString() {
+ return "Argument[" +
+ "typeName=" + typeName + ", " +
+ "name=" + name + ']';
+ }
+
+ }
}
}
diff --git a/processor/src/main/java/io/jonasg/bob/definitions/FieldDefinition.java b/processor/src/main/java/io/jonasg/bob/definitions/FieldDefinition.java
index f220093..7f83a26 100644
--- a/processor/src/main/java/io/jonasg/bob/definitions/FieldDefinition.java
+++ b/processor/src/main/java/io/jonasg/bob/definitions/FieldDefinition.java
@@ -6,12 +6,58 @@
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeMirror;
-public record FieldDefinition(String name,
- List extends AnnotationMirror> annotations,
- TypeMirror type) {
- public boolean isAnnotatedWith(Class type) {
- return annotations.stream()
- .anyMatch(a -> Objects.equals(type.getName().replaceAll("\\$", "."),
- a.getAnnotationType().asElement().asType().toString()));
- }
+public final class FieldDefinition {
+ private final String name;
+ private final List extends AnnotationMirror> annotations;
+ private final TypeMirror type;
+
+ public FieldDefinition(String name,
+ List extends AnnotationMirror> annotations,
+ TypeMirror type) {
+ this.name = name;
+ this.annotations = annotations;
+ this.type = type;
+ }
+
+ public boolean isAnnotatedWith(Class type) {
+ return annotations.stream()
+ .anyMatch(a -> Objects.equals(type.getName().replaceAll("\\$", "."),
+ a.getAnnotationType().asElement().asType().toString()));
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public List extends AnnotationMirror> annotations() {
+ return annotations;
+ }
+
+ public TypeMirror type() {
+ return type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (FieldDefinition) obj;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.annotations, that.annotations) &&
+ Objects.equals(this.type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, annotations, type);
+ }
+
+ @Override
+ public String toString() {
+ return "FieldDefinition[" +
+ "name=" + name + ", " +
+ "annotations=" + annotations + ", " +
+ "type=" + type + ']';
+ }
+
}
diff --git a/processor/src/main/java/io/jonasg/bob/definitions/MethodDefinition.java b/processor/src/main/java/io/jonasg/bob/definitions/MethodDefinition.java
index 2350531..26193ae 100644
--- a/processor/src/main/java/io/jonasg/bob/definitions/MethodDefinition.java
+++ b/processor/src/main/java/io/jonasg/bob/definitions/MethodDefinition.java
@@ -1,9 +1,47 @@
package io.jonasg.bob.definitions;
import java.util.List;
+import java.util.Objects;
import javax.lang.model.type.TypeMirror;
-public record MethodDefinition(String name,
- List parameters) {
+public final class MethodDefinition {
+ private final String name;
+ private final List parameters;
+
+ public MethodDefinition(String name,
+ List parameters) {
+ this.name = name;
+ this.parameters = parameters;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public List parameters() {
+ return parameters;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (MethodDefinition) obj;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.parameters, that.parameters);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, parameters);
+ }
+
+ @Override
+ public String toString() {
+ return "MethodDefinition[" +
+ "name=" + name + ", " +
+ "parameters=" + parameters + ']';
+ }
+
}
diff --git a/processor/src/main/java/io/jonasg/bob/definitions/SetterMethodDefinition.java b/processor/src/main/java/io/jonasg/bob/definitions/SetterMethodDefinition.java
index 8165a86..ab65ea9 100644
--- a/processor/src/main/java/io/jonasg/bob/definitions/SetterMethodDefinition.java
+++ b/processor/src/main/java/io/jonasg/bob/definitions/SetterMethodDefinition.java
@@ -1,8 +1,54 @@
package io.jonasg.bob.definitions;
import javax.lang.model.type.TypeMirror;
+import java.util.Objects;
+
+public final class SetterMethodDefinition {
+ private final String methodName;
+ private final FieldDefinition field;
+ private final TypeMirror type;
+
+ public SetterMethodDefinition(String methodName,
+ FieldDefinition field,
+ TypeMirror type) {
+ this.methodName = methodName;
+ this.field = field;
+ this.type = type;
+ }
+
+ public String methodName() {
+ return methodName;
+ }
+
+ public FieldDefinition field() {
+ return field;
+ }
+
+ public TypeMirror type() {
+ return type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (SetterMethodDefinition) obj;
+ return Objects.equals(this.methodName, that.methodName) &&
+ Objects.equals(this.field, that.field) &&
+ Objects.equals(this.type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(methodName, field, type);
+ }
+
+ @Override
+ public String toString() {
+ return "SetterMethodDefinition[" +
+ "methodName=" + methodName + ", " +
+ "field=" + field + ", " +
+ "type=" + type + ']';
+ }
-public record SetterMethodDefinition(String methodName,
- FieldDefinition field,
- TypeMirror type) {
}
diff --git a/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinition.java b/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinition.java
index b9dea65..d688589 100644
--- a/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinition.java
+++ b/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinition.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Defines a specific Java Type.
@@ -53,7 +54,7 @@ public List getSetterMethods() {
List setters = new ArrayList<>();
List methodsWithOneParam = this.methods.stream()
.filter(m -> m.parameters().size() == 1)
- .toList();
+ .collect(Collectors.toList());
for (FieldDefinition field : fields) {
String name = field.name().substring(0, 1).toUpperCase() + field.name().substring(1);
methodsWithOneParam.stream()
@@ -62,7 +63,7 @@ public List getSetterMethods() {
.map(m -> new SetterMethodDefinition(m.name(), field, m.parameters().get(0)))
.ifPresent(setters::add);
methodsWithOneParam.stream()
- .filter(m -> m.name().equals("set%s".formatted(name)))
+ .filter(m -> m.name().equals(String.format("set%s", name)))
.findFirst()
.map(m -> new SetterMethodDefinition(m.name(), field, m.parameters().get(0)))
.ifPresent(setters::add);
diff --git a/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinitionFactory.java b/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinitionFactory.java
index bcbdca2..4115eef 100644
--- a/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinitionFactory.java
+++ b/processor/src/main/java/io/jonasg/bob/definitions/TypeDefinitionFactory.java
@@ -5,6 +5,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
@@ -141,12 +142,12 @@ private List fields() {
private List methods() {
return ElementFilter.methodsIn(element.getEnclosedElements()).stream()
.map(e -> new MethodDefinition(e.getSimpleName().toString(), parameterTypes(e)))
- .toList();
+ .collect(Collectors.toList());
}
private List parameterTypes(ExecutableElement element) {
return element.getParameters().stream()
.map(VariableElement::asType)
- .toList();
+ .collect(Collectors.toList());
}
}