Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify support for java.time.* and annotation @Future, @FutureOrPresent, @PastOrPresent and @Past classes for Issue #323 #324

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
15 changes: 11 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
<version>9</version>
</parent>

<groupId>uk.co.jemos.podam</groupId>
Expand Down Expand Up @@ -185,6 +185,13 @@
<role>Developer</role>
</roles>
</contributor>
<contributor>
<name>Liam KINCAID</name>
<email>[email protected]</email>
<roles>
<role>Developer</role>
</roles>
</contributor>
</contributors>


Expand Down Expand Up @@ -226,10 +233,10 @@
<version>3.10.1</version>
<configuration>
<jdkToolchain>
<version>7</version>
<version>8</version>
</jdkToolchain>
<target>7</target>s
<source>7</source>
<target>8</target>
<source>8</source>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,17 @@

import uk.co.jemos.podam.common.*;
import uk.co.jemos.podam.exceptions.PodamMockeryException;
import uk.co.jemos.podam.typeManufacturers.ArrayTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.BooleanTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.ByteTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.CharTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.CollectionTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.DoubleTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.EnumTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.FloatTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.IntTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.LongTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.MapTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.ShortTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.StringTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.TypeTypeManufacturerImpl;
import uk.co.jemos.podam.typeManufacturers.TypeManufacturer;

import jakarta.validation.constraints.Email;
import uk.co.jemos.podam.typeManufacturers.*;

import jakarta.validation.constraints.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.time.*;
import java.time.temporal.Temporal;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -196,8 +184,40 @@ public AbstractRandomDataProviderStrategy(int nbrOfCollectionElements) {

TypeManufacturer<?> arrayManufacturer = new ArrayTypeManufacturerImpl();
typeManufacturers.put(Cloneable.class, arrayManufacturer);


/**
* Support of classes with annotation strategy:
* - {@link java.time.Duration}
* - {@link java.time.ZoneId}
* - {@link java.time.ZoneOffset}
*/
addOrReplaceTypeManufacturer(Duration.class, new DurationTypeManufacturerImpl());
addOrReplaceTypeManufacturer(MonthDay.class, new MonthDayTypeManufacturerImpl());
addOrReplaceTypeManufacturer(Period.class, new PeriodTypeManufacturerImpl());
addOrReplaceTypeManufacturer(ZoneId.class, new ZoneIdTypeManufacturerImpl());
addOrReplaceTypeManufacturer(ZoneOffset.class, new ZoneOffsetTypeManufacturerImpl());

/**
* Support of {@link java.time.Temporal} classes with annotation strategy:
* - {@link jakarta.validation.constraint.Future}
* - {@link jakarta.validation.constraint.FutureOfPresent}
* - {@link jakarta.validation.constraint.PastOfPresent}
* - {@link jakarta.validation.constraint.Past}
*/
addOrReplaceTypeManufacturer(Clock.class, new ClockTypeManufacturerImpl());
addOrReplaceTypeManufacturer(Instant.class, new InstantTypeManufacturerImpl());
addOrReplaceTypeManufacturer(LocalDate.class, new LocalDateTypeManufacturerImpl());
addOrReplaceTypeManufacturer(LocalDateTime.class, new LocalDateTimeTypeManufacturerImpl());
addOrReplaceTypeManufacturer(LocalTime.class, new LocalTimeTypeManufacturerImpl());
addOrReplaceTypeManufacturer(OffsetDateTime.class, new OffsetDateTimeTypeManufacturerImpl());
addOrReplaceTypeManufacturer(OffsetTime.class, new OffsetTimeTypeManufacturerImpl());
addOrReplaceTypeManufacturer(Year.class, new YearTypeManufacturerImpl());
addOrReplaceTypeManufacturer(ZonedDateTime.class, new ZonedDateTimeTypeManufacturerImpl());
addOrReplaceAttributeStrategy(Email.class, new EmailStrategy());
addOrReplaceAttributeStrategy(Future.class, new FutureStrategy());
addOrReplaceAttributeStrategy(FutureOrPresent.class, new FutureOrPresentStrategy());
addOrReplaceAttributeStrategy(PastOrPresent.class, new PastOrPresentStrategy());
addOrReplaceAttributeStrategy(Past.class, new PastStrategy());
}

// ------------------->> Public methods
Expand Down
99 changes: 69 additions & 30 deletions src/main/java/uk/co/jemos/podam/common/BeanValidationStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.co.jemos.podam.api.AttributeMetadata;
import uk.co.jemos.podam.api.PodamUtils;
import uk.co.jemos.podam.exceptions.PodamMockeryException;

Expand All @@ -13,12 +15,20 @@
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalUnit;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
Expand All @@ -31,6 +41,26 @@ public class BeanValidationStrategy implements AttributeStrategy<Object> {

// ------------------->> Constants

/**
* The minimum second supported, '-253402300800'.
*/
long MIN_SECOND = -253_402_300_800L;

/**
* The maximum second supported, '253402300799'.
*/
long MAX_SECOND = 253_402_300_799L;

/**
* The minimum nanosecond supported, '.'.
*/
long MIN_NANOSECOND = 0L;

/**
* The maximum nanosecond supported, '999999999'.
*/
long MAX_NANOSECOND = 999_999_999L;

// ------------------->> Instance / Static variables

private static final Logger LOG = LoggerFactory.getLogger(BeanValidationStrategy.class);
Expand Down Expand Up @@ -74,34 +104,6 @@ public Object getValue(Class<?> attrType, List<Annotation> annotations) throws P
return Boolean.FALSE;
}

if (null != findTypeFromList(annotations, Past.class)) {

long days = PodamUtils.getIntegerInRange(1, 365);
long offset = -TimeUnit.DAYS.toSeconds(days);
return timestampToReturnType(offset);
}

if (null != findTypeFromList(annotations, PastOrPresent.class)) {

long days = PodamUtils.getIntegerInRange(0, 365);
long offset = -TimeUnit.DAYS.toSeconds(days);
return timestampToReturnType(-days);
}

if (null != findTypeFromList(annotations, Future.class)) {

long days = PodamUtils.getIntegerInRange(1, 365);
long offset = TimeUnit.DAYS.toSeconds(days);
return timestampToReturnType(days);
}

if (null != findTypeFromList(annotations, FutureOrPresent.class)) {

long days = PodamUtils.getIntegerInRange(0, 365);
long offset = TimeUnit.DAYS.toSeconds(days);
return timestampToReturnType(days);
}

Size size = findTypeFromList(annotations, Size.class);
if (null != size) {

Expand Down Expand Up @@ -358,7 +360,7 @@ private Object decimalToReturnType(BigDecimal result) {
*/
private Object timestampToReturnType(Long offsetSecs) {

long timestamp;
long timestamp;
if (Temporal.class.isAssignableFrom(attributeType)) {

try {
Expand All @@ -376,7 +378,7 @@ private Object timestampToReturnType(Long offsetSecs) {

timestamp = System.currentTimeMillis() + offsetSecs * 1000;
}

if (attributeType.isAssignableFrom(Date.class)) {

return new Date(timestamp);
Expand All @@ -387,6 +389,43 @@ private Object timestampToReturnType(Long offsetSecs) {
calendar.setTimeInMillis(timestamp);
return calendar;

} else if (attributeType.isAssignableFrom(Clock.class)) {

Set<String> zoneIds = ZoneId.getAvailableZoneIds();
Integer index = PodamUtils.getIntegerInRange(0, zoneIds.size());

int i = 0;
ZoneId result = null;
for (String zoneId : zoneIds) {
if (index.equals(i++)) {
return Clock.system(ZoneId.of(zoneId));
}
}

return Clock.system(ZoneId.systemDefault());

} else if (attributeType.isAssignableFrom(ZoneId.class)) {

Set<String> zoneIds = ZoneId.getAvailableZoneIds();
Integer index = PodamUtils.getIntegerInRange(0, zoneIds.size());

int i = 0;
ZoneId result = null;
for (String zoneId : zoneIds) {
if (index.equals(i++)) {
return ZoneId.of(zoneId);
}
}

return ZoneId.systemDefault();

} else if (attributeType.isAssignableFrom(ZoneOffset.class)) {

int hours = PodamUtils.getIntegerInRange(-18, 18);
int minutes = PodamUtils.getIntegerInRange(-59, 59);
int seconds = PodamUtils.getIntegerInRange(-59, 59);
return ZoneOffset.ofHoursMinutesSeconds(hours, minutes, seconds);

} else {

LOG.warn("Unsupported attribute type {}", attributeType);
Expand Down
115 changes: 115 additions & 0 deletions src/main/java/uk/co/jemos/podam/common/CommonTypeOrStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package uk.co.jemos.podam.common;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.FutureOrPresent;
import jakarta.validation.constraints.Past;
import jakarta.validation.constraints.PastOrPresent;
import java.lang.annotation.Annotation;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import uk.co.jemos.podam.api.PodamUtils;

/**
* Base {@link java.time.temporal.Temporal} type strategy.
*
* @author liam on 03/01/2024.
* @since 8.0.1.RELEASE
*/
public interface CommonTypeOrStrategy {

/**
* It returns an {@link java.time.ZoneId} value.
*
* @return A {@link java.time.ZoneId} value
*/
default ZoneId getZoneId() {
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
Integer index = PodamUtils.getIntegerInRange(0, zoneIds.size());

int i = 0;
for (String zoneId : zoneIds) {
if (index.equals(i++)) {
return ZoneId.of(zoneId);
}
}

return ZoneId.systemDefault();
}

/**
* Calculate a couple of seconds and nanoseconds
*
* @param annotations list of annotations attached to an attribute
* @param seconds A amount a seconds
* @param nanos A amoutn of nanoseconds
*/
default void getSecondsNanos(List<Annotation> annotations, AtomicReference<Long> seconds, AtomicReference<Long> nanos) {

Instant now = Instant.now();

if (annotations.stream().anyMatch(Future.class::isInstance)) {

Instant futur = now.plus(1L, ChronoUnit.DAYS);
seconds.set(PodamUtils.getLongInRange(futur.getEpochSecond(), Instant.MAX.getEpochSecond()));

} else if (annotations.stream().anyMatch(FutureOrPresent.class::isInstance)) {

seconds.set(PodamUtils.getLongInRange(now.getEpochSecond(), Instant.MAX.getEpochSecond()));

} else if (annotations.stream().anyMatch(PastOrPresent.class::isInstance)) {

seconds.set(PodamUtils.getLongInRange(Instant.MIN.getEpochSecond(), now.getEpochSecond()));

} else if (annotations.stream().anyMatch(Past.class::isInstance)) {

Instant past = now.minus(1L, ChronoUnit.DAYS);
seconds.set(PodamUtils.getLongInRange(Instant.MIN.getEpochSecond(), past.getEpochSecond()));

} else {

seconds.set(PodamUtils.getLongInRange(Instant.MIN.getEpochSecond(), Instant.MAX.getEpochSecond()));
}

nanos.set(PodamUtils.getLongInRange(Instant.MIN.getNano(), Instant.MAX.getNano()));
}

/**
* Calculate a couple of years
*
* @param annotations list of annotations attached to an attribute
* @param years A amount a year
*/
default void getYearsMonthsDays(List<Annotation> annotations, AtomicReference<Integer> years, AtomicReference<Integer> months, AtomicReference<Integer> days) {

YearMonth now = YearMonth.now();

if (annotations.stream().anyMatch(Future.class::isInstance)) {

YearMonth futur = now.plusMonths(6L);
years.set(PodamUtils.getIntegerInRange(futur.getYear(), Year.MAX_VALUE));

} else if (annotations.stream().anyMatch(FutureOrPresent.class::isInstance)) {

years.set(PodamUtils.getIntegerInRange(now.getYear(), Year.MAX_VALUE));

} else if (annotations.stream().anyMatch(PastOrPresent.class::isInstance)) {

years.set(PodamUtils.getIntegerInRange(Year.MIN_VALUE, now.getYear()));

} else if (annotations.stream().anyMatch(Past.class::isInstance)) {

YearMonth past = now.minusMonths(6L);
years.set(PodamUtils.getIntegerInRange(Year.MIN_VALUE, past.getYear()));

} else {

years.set(PodamUtils.getIntegerInRange(Year.MIN_VALUE, Year.MAX_VALUE));
}

months.set(PodamUtils.getIntegerInRange(1, 12));
days.set(PodamUtils.getIntegerInRange(1, YearMonth.of(years.get(), months.get()).atEndOfMonth().getDayOfMonth()));
}
}
Loading