TSK-1994: introduce new Generic Interval

Co-authored-by: Alex <arolfes@users.noreply.github.com>
This commit is contained in:
Mustapha Zorgati 2023-02-16 17:05:46 +01:00
parent f9e6b26817
commit ff643fdff6
6 changed files with 216 additions and 99 deletions

View File

@ -1,56 +1,14 @@
package pro.taskana.common.api;
import java.util.Objects;
import pro.taskana.common.internal.Interval;
/**
* IntInterval captures an Integer interval. A fixed interval has defined begin and end. An open
* ended interval has either begin == null or end ==null.
*/
public class IntInterval {
private final Integer begin;
private final Integer end;
public class IntInterval extends Interval<Integer> {
public IntInterval(Integer begin, Integer end) {
this.begin = begin;
this.end = end;
}
public boolean isValid() {
boolean isValid = begin != null || end != null;
if (begin != null && end != null && begin > end) {
isValid = false;
}
return isValid;
}
public Integer getBegin() {
return begin;
}
public Integer getEnd() {
return end;
}
@Override
public int hashCode() {
return Objects.hash(begin, end);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof IntInterval)) {
return false;
}
IntInterval other = (IntInterval) obj;
return Objects.equals(begin, other.begin) && Objects.equals(end, other.end);
}
@Override
public String toString() {
return "IntInterval [" + "begin=" + this.begin + ", end=" + this.end + "]";
super(begin, end);
}
}

View File

@ -1,66 +1,16 @@
package pro.taskana.common.api;
import java.time.Instant;
import java.util.Objects;
import pro.taskana.common.internal.Interval;
/**
* Capture a time interval. A fixed interval has defined begin and end Instant. An open ended
* interval has either begin == null or end ==null.
*/
public class TimeInterval {
private final Instant begin;
private final Instant end;
public class TimeInterval extends Interval<Instant> {
public TimeInterval(Instant begin, Instant end) {
this.begin = begin;
this.end = end;
}
public boolean contains(Instant i) {
if (i == null) {
return false;
}
boolean isAfterBegin = begin == null || !i.isBefore(begin);
boolean isBeforeEnd = end == null || !i.isAfter(end);
return (isAfterBegin && isBeforeEnd);
}
public boolean isValid() {
boolean isValid = begin != null || end != null;
if (begin != null && end != null && begin.isAfter(end)) {
isValid = false;
}
return isValid;
}
public Instant getBegin() {
return begin;
}
public Instant getEnd() {
return end;
}
@Override
public int hashCode() {
return Objects.hash(begin, end);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof TimeInterval)) {
return false;
}
TimeInterval other = (TimeInterval) obj;
return Objects.equals(begin, other.begin) && Objects.equals(end, other.end);
}
@Override
public String toString() {
return "TimeInterval [" + "begin=" + this.begin + ", end=" + this.end + "]";
super(begin, end);
}
}

View File

@ -0,0 +1,69 @@
package pro.taskana.common.internal;
import java.util.Objects;
/**
* An Interval captures an interval of Type <code>T extends Comparable</code>. A fixed interval has
* defined begin and end. An open ended interval has either begin == null or end ==null.
*
* <p>Example: <code>Interval&lt;Integer&gt; interval = new Interval&lt;&gt;(1, 2);</code> or <code>
* Interval&lt;Instant&gt; timeInterval = new Interval&lt;&gt;(instant_1, instant_2)</code>
*/
public class Interval<T extends Comparable<? super T>> {
private final T begin;
private final T end;
public Interval(T begin, T end) {
this.begin = begin;
this.end = end;
}
public T getBegin() {
return begin;
}
public T getEnd() {
return end;
}
public boolean contains(T i) {
if (i == null) {
return false;
}
boolean isAfterBegin = begin == null || i.compareTo(begin) >= 0;
boolean isBeforeEnd = end == null || i.compareTo(end) <= 0;
return (isAfterBegin && isBeforeEnd);
}
public boolean isValid() {
boolean isValid = begin != null || end != null;
if (begin != null && end != null && begin.compareTo(end) > 0) {
isValid = false;
}
return isValid;
}
@Override
public int hashCode() {
return Objects.hash(begin, end);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Interval)) {
return false;
}
Interval<?> other = (Interval<?>) obj;
return Objects.equals(begin, other.begin) && Objects.equals(end, other.end);
}
@Override
public String toString() {
return "Interval [" + "begin=" + this.begin + ", end=" + this.end + "]";
}
}

View File

@ -0,0 +1,60 @@
package pro.taskana.common.api;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class IntIntervalTest {
@Test
void should_BeAValidIntervall_when_BeginIsBeforEnd() {
IntInterval interval = new IntInterval(1, 2);
assertThat(interval.isValid()).isTrue();
}
@Test
void should_BeAValidIntervall_when_BeginAndEndAreEqual() {
IntInterval interval = new IntInterval(1, 1);
assertThat(interval.isValid()).isTrue();
}
@Test
void should_NotBeAValidIntervall_when_BeginIsAfterEnd() {
IntInterval interval = new IntInterval(2, 1);
assertThat(interval.isValid()).isFalse();
}
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void should_ContainIntegerInIntervall_when_BeginIsOneAndEndIsThree(int number) {
IntInterval interval = new IntInterval(1, 3);
assertThat(interval.contains(number)).isTrue();
}
@ParameterizedTest
@ValueSource(ints = {0, 4})
void should_NotContainIntegerInIntervall_when_BeginIsOneAndEndIsThree(int number) {
IntInterval interval = new IntInterval(1, 3);
assertThat(interval.contains(number)).isFalse();
}
@Test
void should_TwoIntervallsAreEqual_when_BothHaveSameBeginAndEnd() {
IntInterval interval1 = new IntInterval(1, 2);
IntInterval interval2 = new IntInterval(1, 2);
assertThat(interval1).isEqualTo(interval2);
assertThat(interval2).isEqualTo(interval1);
}
@Test
void should_TwoIntervallsAreNotEqual_when_BeginAndEndAreDifferent() {
IntInterval interval1 = new IntInterval(1, 2);
IntInterval interval2 = new IntInterval(1, 3);
assertThat(interval1).isNotEqualTo(interval2);
assertThat(interval2).isNotEqualTo(interval1);
}
}

View File

@ -0,0 +1,77 @@
package pro.taskana.common.api;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class TimeIntervalTest {
private static final ZoneId UTC = ZoneId.of("UTC");
private final Instant date1 = LocalDate.of(2023, 2, 10).atStartOfDay(UTC).toInstant();
private final Instant date2 = LocalDate.of(2023, 2, 13).atStartOfDay(UTC).toInstant();
@Test
void should_BeAValidIntervall_when_BeginIsBeforEnd() {
TimeInterval timeInterval = new TimeInterval(date1, date2);
assertThat(timeInterval.isValid()).isTrue();
}
@Test
void should_BeAValidIntervall_when_BeginAndEndAreEqual() {
TimeInterval timeInterval = new TimeInterval(date1, date1);
assertThat(timeInterval.isValid()).isTrue();
}
@Test
void should_NotBeAValidIntervall_when_BeginIsAfterEnd() {
TimeInterval timeInterval = new TimeInterval(date2, date1);
assertThat(timeInterval.isValid()).isFalse();
}
@ParameterizedTest
@ValueSource(ints = {10, 11, 12, 13})
void should_ContainDateInIntervall(int day) {
TimeInterval timeInterval = new TimeInterval(date1, date2);
Instant actualInstant = LocalDate.of(2023, 2, day).atStartOfDay(UTC).toInstant();
assertThat(timeInterval.contains(actualInstant)).isTrue();
}
@ParameterizedTest
@ValueSource(ints = {8, 9, 14, 15})
void should_NotContainDateInIntervall_when_InstantIsBeforeOrAfter(int day) {
TimeInterval timeInterval = new TimeInterval(date1, date2);
Instant actualInstant = LocalDate.of(2023, 2, day).atStartOfDay(UTC).toInstant();
assertThat(timeInterval.contains(actualInstant)).isFalse();
}
@Test
void should_TwoIntervallsAreEqual_when_BothHaveSameBeginAndEnd() {
TimeInterval timeInterval1 = new TimeInterval(date1, date2);
TimeInterval timeInterval2 = new TimeInterval(date1, date2);
assertThat(timeInterval1).isEqualTo(timeInterval2);
assertThat(timeInterval2).isEqualTo(timeInterval1);
}
@Test
void should_TwoIntervallsAreNotEqual_when_BeginAndEndAreDifferent() {
TimeInterval timeInterval1 = new TimeInterval(date1, date2);
TimeInterval timeInterval2 =
new TimeInterval(date1, LocalDate.of(2023, 2, 14).atStartOfDay(UTC).toInstant());
assertThat(timeInterval1).isNotEqualTo(timeInterval2);
assertThat(timeInterval2).isNotEqualTo(timeInterval1);
}
}

View File

@ -66,6 +66,7 @@ import pro.taskana.common.api.exceptions.ErrorCode;
import pro.taskana.common.api.exceptions.TaskanaException;
import pro.taskana.common.api.exceptions.TaskanaRuntimeException;
import pro.taskana.common.internal.InternalTaskanaEngine;
import pro.taskana.common.internal.Interval;
import pro.taskana.common.internal.logging.LoggingAspect;
import pro.taskana.common.internal.util.MapCreator;
import pro.taskana.testapi.TaskanaIntegrationTest;
@ -214,6 +215,8 @@ class ArchitectureTest {
.resideInAPackage("..api..")
.and()
.areNotAssignableFrom(TaskanaEngine.class)
.and()
.areNotAssignableTo(Interval.class)
.should()
.onlyDependOnClassesThat(
resideOutsideOfPackage("..pro.taskana..internal..")