Modak is a library that helps you define data correction rules and provides APIs to correct data in your objects based on those rules. Main features:
- Lets you express data correction rules on object models via annotations
- Lets you write custom constraint in an extensible way
- Provides APIs to correct objects
- Works for Java & Kotlin projects
Modak is a traditional Indian sweet, typically a dumpling, made with rice or wheat flour and filled with a sweet mixture, often grated coconut and jaggery.
Available on Maven Central
dependencies {
implementation("io.github.akash-kansara:modak-core:$version")
}dependencies {
implementation 'io.github.akash-kansara:modak-core:$version'
}<dependency>
<groupId>io.github.akash-kansara</groupId>
<artifactId>modak-core</artifactId>
<version>VERSION</version>
</dependency>// Correction annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Correction(correctedBy = {UserCorrectionApplier.class})
public @interface UserCorrection {
String defaultRole() default "USER";
String adminRole() default "ADMIN";
}
// Correction applier:
public class UserCorrectionApplier implements CorrectionApplier<UserCorrection, User> {
private String defaultRole;
private String adminRole;
@Override
public void initialize(UserCorrection annotation) {
this.defaultRole = annotation.defaultRole();
this.adminRole = annotation.adminRole();
}
@Override
public CorrectionApplierResult<User> correct(User user, CorrectionApplierContext context) {
if (user.role == null) {
String newRole = this.defaultRole;
if (user.email != null && user.email.endsWith("@company.com")) {
newRole = this.adminRole;
}
user.role = newRole;
return new CorrectionApplierResult.Edited<>(user, user); // Left value is original, right is corrected. Here we're updating in-place but you can return a new instance as well
} else {
return new CorrectionApplierResult.NoChange<>();
}
}
}@UserCorrection( // Your custom correction rule
defaultRole = "DEFAULT",
adminRole = "ADMIN"
)
public class User {
@Trim // Provided by library
@DefaultValue(strValue = "Anonymous") // If you're using getter/setter, you can annotate the getter instead of fields
public String name; // public modifier is required
@DefaultValue(intValue = 18) // Provided by library
public Integer age;
public String role;
@RegexReplace( // Provided by library
regexPattern = "[^a-zA-Z0-9@._-]",
replaceStr = ""
)
public String email;
public User(String name, Integer age, String role, String email) {
this.name = name;
this.age = age;
this.role = role;
this.email = email;
}
}Corrector corrector = CorrectorFactory.buildCorrector();
User user = new User(null, null, null, "example@com!pany.com");
CorrectionResult<User, ErrorLike> result = corrector.correct(user);
System.out.println(result.isSuccess()); // true
CorrectionResult.Success<User> successResult = (CorrectionResult.Success<User>) result;
System.out.println( // 4
successResult.getAppliedCorrections().size()
);
System.out.println(user); // User{name='Anonymous', age=18, role='ADMIN', email='example@company.com'}Modak is a companion library to Jakarta Bean Validation. Its scope is limited to data correction and does not provide data validation features, but it seamlessly integrates with bean validation. You can use any bean validation such as Hibernate Validator, Apache BVal along with Modak.
public class User {
private String name;
public User(String name) {
this.name = name;
}
@NotNull // Jakarta Bean Validation constraint
@DefaultValue(
strValue = "Anonymous",
constraintFilter = {NotNull.class} // Only apply if NotNull constraint fails
)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User user = new User(null);
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<User>> violations = validator.validate(user);
Corrector corrector = CorrectorFactory.buildCorrector();
CorrectionResult<User, ErrorLike> result = corrector.correct( // Since violations are supplied, correction will be applied only if NotNull constraint has failed
user,
violations
);
System.out.println(user.getName()); // Anonymousπ Full Documentation
π§ Automatic Data Correction - Automatically fix inconsistent or invalid data
π Annotation-Based - Use simple, declarative annotations to define correction rules
π Jakarta Validation Integration - Works with existing validation constraints
π― Built-in Corrections - Common corrections ready to use
π οΈ Custom Corrections - Easy to extend with your own logic
π₯ Group Support - Sequence, filter corrections based on groups & group sequences
ποΈ Constraint Filtering - Target specific validation constraints
π³ Nested Objects - Automatically traverse and correct nested structures
π‘οΈ Type Safe - Full Kotlin type safety with generics
Contributions welcome! Please see our contributing guidelines and feel free to submit issues and pull requests.
Licensed under the terms in the LICENSE file.
Need help? Open an issue or check the full documentation.