Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,56 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>it.aboutbits</groupId>
<artifactId>spring-boot-toolbox</artifactId>
<version>BUILD-SNAPSHOT</version>
<description>Utility library for Spring Boot projects.</description>
<packaging>jar</packaging>

<properties>
<java.version>21</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- Utilities -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Validation -->
<!-- https://mvnrepository.com/artifact/commons-validator/commons-validator -->
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.9.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.jetbrains/annotations -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
</dependency>

<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package it.aboutbits.springboot.toolbox.type;

import it.aboutbits.springboot.toolbox.validation.util.EmailAddressValidator;
import org.jetbrains.annotations.NotNull;

/**
* A record representing an email address, validated and stored in lowercase.
* <p>
* The EmailAddress record ensures that the provided email address string
* is in a valid format and automatically converts it to lowercase for
* consistent internal representation. It implements the Comparable
* interface to allow comparison between different email addresses.
* </p>
*
* @param value the email address string
* @throws IllegalArgumentException if the provided email address is not in a valid format
*/
public record EmailAddress(String value) implements Comparable<EmailAddress> {
public EmailAddress(String value) {
if (value == null || EmailAddressValidator.isNotValid(value)) {
throw new IllegalArgumentException("Value is not a valid email address: " + value);
}

this.value = value.toLowerCase();
}

@Override
public String toString() {
return value;
}

@Override
public int compareTo(@NotNull EmailAddress o) {
Comment thread
SirCotare marked this conversation as resolved.
Outdated
return value().compareTo(o.value());
}
}
46 changes: 46 additions & 0 deletions src/main/java/it/aboutbits/springboot/toolbox/type/Iban.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package it.aboutbits.springboot.toolbox.type;

import it.aboutbits.springboot.toolbox.validation.util.IbanValidator;
import org.jetbrains.annotations.NotNull;

import java.util.Optional;

/**
* The {@code Iban} class represents an International Bank Account Number (IBAN) and provides functionality for validation
* and comparison of IBANs. It ensures the valid format of the IBAN according to predefined rules.
*
* @param value the IBAN value, which must be a valid and non-null string
*/
public record Iban(String value) implements Comparable<Iban> {
public Iban(String value) {
if (value == null || IbanValidator.isNotValid(value.toUpperCase())) {
throw new IllegalArgumentException("Value is not a valid IBAN: " + value);
}

this.value = value.toUpperCase();
}

@Override
public String toString() {
return value;
}

/**
* Retrieves the ABI (Bank Branch Code) if the IBAN belongs to an Italian bank.
*
* @return An {@code Optional} containing the ABI value if the IBAN is Italian, or an empty {@code Optional} otherwise.
*/
public Optional<String> getAbiIfItalian() {
var iban = value();

if (!iban.startsWith("IT")) {
return Optional.empty();
}
return Optional.of(iban.substring(5, 10));
}

@Override
public int compareTo(@NotNull Iban o) {
return value().compareTo(o.value());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package it.aboutbits.springboot.toolbox.type;

import lombok.NonNull;
import org.jetbrains.annotations.NotNull;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Objects;

/**
* A record that represents a scaled BigDecimal with a fixed MathContext.
* This class provides various constructors for creating instances with different numerical types.
* It also provides a set of arithmetic operations that return new instances with the appropriate scale and rounding.
*/
public record ScaledBigDecimal(
@NonNull BigDecimal value
) implements Comparable<ScaledBigDecimal> {
private static final MathContext MATH_CONTEXT = new MathContext(15, RoundingMode.HALF_UP);

public static final ScaledBigDecimal ZERO = new ScaledBigDecimal(0);
public static final ScaledBigDecimal ONE = new ScaledBigDecimal(1);
public static final ScaledBigDecimal TWO = new ScaledBigDecimal(2);
public static final ScaledBigDecimal TEN = new ScaledBigDecimal(10);

public ScaledBigDecimal(@NonNull BigDecimal value) {
this.value = value.setScale(MATH_CONTEXT.getPrecision(), MATH_CONTEXT.getRoundingMode());
}

public ScaledBigDecimal(int value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull Integer value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull BigInteger value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public ScaledBigDecimal(long value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull Long value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public ScaledBigDecimal(float value) {
this(new BigDecimal(String.valueOf(value), MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull Float value) {
this(new BigDecimal(String.valueOf(value), MATH_CONTEXT));
}

public ScaledBigDecimal(double value) {
this(new BigDecimal(String.valueOf(value), MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull Double value) {
this(new BigDecimal(String.valueOf(value), MATH_CONTEXT));
}

public ScaledBigDecimal(@NonNull String value) {
this(new BigDecimal(value, MATH_CONTEXT));
}

public static ScaledBigDecimal valueOf(int value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull Integer value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull BigInteger value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(long value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull Long value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(float value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull Float value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(double value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull Double value) {
return new ScaledBigDecimal(value);
}

public static ScaledBigDecimal valueOf(@NonNull String value) {
return new ScaledBigDecimal(value);
}

@NotNull
public ScaledBigDecimal add(@NonNull ScaledBigDecimal other) {
return new ScaledBigDecimal(this.value().add(other.value()));
}

@NotNull
public ScaledBigDecimal subtract(@NonNull ScaledBigDecimal other) {
return new ScaledBigDecimal(this.value().subtract(other.value()));
}

@NotNull
public ScaledBigDecimal multiply(@NonNull ScaledBigDecimal other) {
return new ScaledBigDecimal(this.value().multiply(other.value()));
}

@NotNull
public ScaledBigDecimal divide(@NonNull ScaledBigDecimal other) {
return new ScaledBigDecimal(this.value().divide(other.value(), MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal add(@NonNull BigDecimal other) {
return new ScaledBigDecimal(this.value().add(other));
}

@NotNull
public ScaledBigDecimal subtract(@NonNull BigDecimal other) {
return new ScaledBigDecimal(this.value().subtract(other));
}

@NotNull
public ScaledBigDecimal multiply(@NonNull BigDecimal other) {
return new ScaledBigDecimal(this.value().multiply(other));
}

@NotNull
public ScaledBigDecimal divide(@NonNull BigDecimal other) {
return new ScaledBigDecimal(this.value().divide(other, MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal remainder(@NonNull ScaledBigDecimal divisor) {
return new ScaledBigDecimal(this.value().remainder(divisor.value(), MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal remainder(@NonNull BigDecimal divisor) {
return new ScaledBigDecimal(this.value().remainder(divisor, MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal sqrt() {
return new ScaledBigDecimal(this.value().sqrt(MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal pow(int n) {
return new ScaledBigDecimal(this.value().pow(n, MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal abs() {
return new ScaledBigDecimal(this.value().abs(MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal negate() {
return new ScaledBigDecimal(this.value().negate(MATH_CONTEXT));
}

@NotNull
public ScaledBigDecimal min(@NonNull ScaledBigDecimal val) {
return new ScaledBigDecimal(this.value().min(val.value()));
}

@NotNull
public ScaledBigDecimal min(@NonNull BigDecimal val) {
return new ScaledBigDecimal(this.value().min(val));
}

@NotNull
public ScaledBigDecimal max(@NonNull ScaledBigDecimal val) {
return new ScaledBigDecimal(this.value().max(val.value()));
}

@NotNull
public ScaledBigDecimal max(@NonNull BigDecimal val) {
return new ScaledBigDecimal(this.value().max(val));
}

@NotNull
public BigDecimal toBigDecimal(int scale) {
return this.value().setScale(scale, RoundingMode.HALF_UP);
}

@NotNull
public ScaledBigDecimal roundToScale(int scale) {
return new ScaledBigDecimal(this.value().setScale(scale, RoundingMode.HALF_UP));
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}

if (o instanceof ScaledBigDecimal other) {
return this.value().compareTo(other.value()) == 0;
}

return false;
}

@Override
public int hashCode() {
return Objects.hash(MATH_CONTEXT, value());
}
Comment thread
SirCotare marked this conversation as resolved.

@Override
public int compareTo(@NotNull ScaledBigDecimal o) {
return this.value().compareTo(o.value());
}
}
Loading