PersonLombokSecure.java
package fr.univtln.bruno.samples.java101.tp1.lombok;
import lombok.*;
import java.util.Objects;
/**
* Secure Lombok-backed Person: validation is performed at the factory/builder boundary.
*
* <p>This class demonstrates a recommended pattern when using Lombok:
* the public, validated static factory method {@link #of(String, String, int)} is
* annotated with {@code @Builder}. Lombok generates a builder whose {@code build()}
* method delegates to this factory method; therefore both calls to
* {@code PersonLombokSecure.of(...)} and to the generated builder
* {@code PersonLombokSecure.builder()...build()} use the same validation
* and normalization logic implemented in {@code of(...)}.</p>
*
* <p>Implementation notes:
* <ul>
* <li>The all-args constructor is private (generated by Lombok with
* {@code @AllArgsConstructor(access = AccessLevel.PRIVATE)}), ensuring
* instances can only be created through the validated factory or the
* generated builder.</li>
* <li>The factory performs lightweight validation (null checks, range checks)
* and normalization (e.g. {@code String.strip()}) before creating the
* instance. Validation uses {@link Objects#requireNonNull} and throws
* {@link IllegalArgumentException} for invalid numeric values.</li>
* <li>We intentionally avoid using {@code @Data} here to keep the example
* explicit; use {@code @Data} only when you want the convenience of
* generating getters/setters and other boilerplate in one go.</li>
* </ul>
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public class PersonLombokSecure {
private final String firstName;
private final String lastName;
@Setter
private int age;
/**
* Private no-arg constructor kept for tools and to avoid a missing Javadoc
* warning for the implicit default constructor. Instances should be created
* through the validating factory {@link #of(String,String,int)} or the
* Lombok-generated builder.
*/
@SuppressWarnings("unused")
private PersonLombokSecure() {
this.firstName = "";
this.lastName = "";
this.age = 0;
}
@Builder
public static PersonLombokSecure of(String firstName, String lastName, int age) {
Objects.requireNonNull(firstName, "firstName must not be null");
Objects.requireNonNull(lastName, "lastName must not be null");
if (age < 0) throw new IllegalArgumentException("age must be >= 0");
return new PersonLombokSecure(firstName.strip(), lastName.strip(), age);
}
}