[FEAT] add ApiNotNull to overwrite all fields possibility

This commit is contained in:
Edouard DUPIN 2025-04-02 21:34:27 +02:00
parent b283f8545c
commit 44df939873
3 changed files with 70 additions and 6 deletions

View File

@ -0,0 +1,45 @@
package org.kar.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to explicitly define the nullability of a parameter in an API.
*
* This annotation allows marking a parameter as required (non-null) or optional (nullable),
* overriding any other nullability considerations. It is useful in API generation frameworks
* to ensure precise validation and documentation of method parameters.
*
* <p>Usage:
* - Target: This annotation can be applied to parameters.
* - Retention: The annotation is retained at runtime, allowing it to be
* processed by frameworks or libraries that handle code generation logic.
*
* <p>Behavior:
* - When applied to a parameter, it explicitly marks it as optional or required in the API.
* This annotation overrides all other considerations regarding nullability.
*
* <p>Example:
* <pre>{@code
* public class User {
* @ReadOnlyField
* @ApiNotNull
* public String username;
* public String email;
* }
* }</pre>
*
* In this example, the `username` field in the `User` class is explicitly marked as non-null in the generated API.
*/
@Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiNotNull {
/**
* (Optional) Specifies whether the API element can be null.
* If set to `true`, the element is required (non-null).
* If set to `false`, the element is optional (nullable).
*/
boolean value() default true;
}

View File

@ -13,6 +13,7 @@ import java.util.Set;
import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.apiGenerator.ApiAccessLimitation; import org.kar.archidata.annotation.apiGenerator.ApiAccessLimitation;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode; import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.annotation.apiGenerator.ApiNotNull;
import org.kar.archidata.exception.DataAccessException; import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.AnnotationCreator; import org.kar.archidata.tools.AnnotationCreator;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -83,13 +84,26 @@ public class ClassObjectModel extends ClassModel {
Email email, Email email,
ApiAccessLimitation accessLimitation, ApiAccessLimitation accessLimitation,
Boolean notNull, Boolean notNull,
ApiNotNull apiNotNull,
Boolean columnNotNull, Boolean columnNotNull,
Boolean nullable) { Boolean nullable) {
public FieldProperty(final String name, final ClassModel model, final ClassModel linkClass, public FieldProperty(//
final String comment, final Size stringSize, final Min min, final Max max, final DecimalMin decimalMin, final String name, //
final DecimalMax decimalMax, final Pattern pattern, final Email email, final ClassModel model, //
final ApiAccessLimitation accessLimitation, final Boolean notNull, final Boolean columnNotNull, final ClassModel linkClass, //
final String comment, //
final Size stringSize, //
final Min min, //
final Max max, //
final DecimalMin decimalMin, //
final DecimalMax decimalMax, //
final Pattern pattern, //
final Email email, //
final ApiAccessLimitation accessLimitation, //
final Boolean notNull, //
final ApiNotNull apiNotNull, //
final Boolean columnNotNull, //
final Boolean nullable) { final Boolean nullable) {
this.name = name; this.name = name;
this.model = model; this.model = model;
@ -108,6 +122,7 @@ public class ClassObjectModel extends ClassModel {
this.accessLimitation = accessLimitation; this.accessLimitation = accessLimitation;
} }
this.notNull = notNull; this.notNull = notNull;
this.apiNotNull = apiNotNull;
this.columnNotNull = columnNotNull; this.columnNotNull = columnNotNull;
this.nullable = nullable; this.nullable = nullable;
@ -160,6 +175,7 @@ public class ClassObjectModel extends ClassModel {
AnnotationTools.getConstraintsEmail(field), // AnnotationTools.getConstraintsEmail(field), //
AnnotationTools.get(field, ApiAccessLimitation.class), // AnnotationTools.get(field, ApiAccessLimitation.class), //
AnnotationTools.getConstraintsNotNull(field), // AnnotationTools.getConstraintsNotNull(field), //
AnnotationTools.get(field, ApiNotNull.class), //
AnnotationTools.getColumnNotNull(field), // AnnotationTools.getColumnNotNull(field), //
AnnotationTools.getNullable(field)); AnnotationTools.getNullable(field));
} }

View File

@ -237,6 +237,9 @@ public class TsClassElement {
} }
public boolean isOptionalTypeZod(final FieldProperty field) { public boolean isOptionalTypeZod(final FieldProperty field) {
if (field.apiNotNull() != null) {
return field.apiNotNull().value();
}
// Common checking element (apply to List, Map, ...) // Common checking element (apply to List, Map, ...)
if (field.nullable()) { if (field.nullable()) {
return true; return true;
@ -287,13 +290,13 @@ public class TsClassElement {
builder.append(")"); builder.append(")");
} }
} }
/*Must be tested before /* Must be tested before
if (field.pattern() != null) { if (field.pattern() != null) {
builder.append(".regex(("); builder.append(".regex((");
builder.append(field.pattern().regexp()); builder.append(field.pattern().regexp());
builder.append(")"); builder.append(")");
}*/ }*/
/*Must be tested before /* Must be tested before
if (field.email() != null) { if (field.email() != null) {
builder.append(".regex(("); builder.append(".regex((");
builder.append(field.email().regexp()); builder.append(field.email().regexp());