diff --git a/README.md b/README.md
index dc18368..ed7e948 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ To install, you can simply include the dependency from Maven Central:
com.redfin
validity
- 2.1.0
+ 2.2.0
```
diff --git a/pom.xml b/pom.xml
index b3de72f..1c04130 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
com.redfin
validity
- 1.0-SNAPSHOT
+ 2.2.0
4.0.0
jar
diff --git a/src/main/java/com/redfin/validity/VerifiableFactory.java b/src/main/java/com/redfin/validity/VerifiableFactory.java
index 496ebb3..fa1dcbe 100644
--- a/src/main/java/com/redfin/validity/VerifiableFactory.java
+++ b/src/main/java/com/redfin/validity/VerifiableFactory.java
@@ -31,7 +31,9 @@
import com.redfin.validity.verifiers.objects.VerifiableClass;
import com.redfin.validity.verifiers.objects.VerifiableCollection;
import com.redfin.validity.verifiers.objects.VerifiableDouble;
+import com.redfin.validity.verifiers.objects.VerifiableDuration;
import com.redfin.validity.verifiers.objects.VerifiableFloat;
+import com.redfin.validity.verifiers.objects.VerifiableInstant;
import com.redfin.validity.verifiers.objects.VerifiableInteger;
import com.redfin.validity.verifiers.objects.VerifiableLong;
import com.redfin.validity.verifiers.objects.VerifiableObject;
@@ -45,6 +47,9 @@
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveInt;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveLong;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveShort;
+
+import java.time.Duration;
+import java.time.Instant;
import java.util.Collection;
/**
@@ -242,6 +247,10 @@ public VerifiablePrimitiveShort that(short subject) {
// Objects
// - - - - - - - - - - - - - - - - - - - - - -
+ // - - - - - - - - - - - - - - - - -
+ // Boxed Primitive Types
+ // - - - - - - - - - - - - - - - - -
+
/**
* @param subject the object to perform validation on.
* @return a {@link VerifiableBoolean} instance for the given subject.
@@ -266,25 +275,6 @@ public VerifiableCharacter that(Character subject) {
return new VerifiableCharacter<>(failedValidationExecutor, subject, message);
}
- /**
- * @param subject the object to perform validation on.
- * @param the class being validated.
- * @return a {@link VerifiableClass} instance for the given subject.
- */
- public VerifiableClass that(Class subject) {
- return new VerifiableClass<>(failedValidationExecutor, subject, message);
- }
-
- /**
- * @param subject the object to perform validation on.
- * @param the type of the objects in the collection.
- * @param the type of the Collection (e.g. list, map, etc).
- * @return a {@link VerifiableCollection} instance for the given subject.
- */
- public > VerifiableCollection that(T subject) {
- return new VerifiableCollection<>(failedValidationExecutor, subject, message);
- }
-
/**
* @param subject the object to perform validation on.
* @return a {@link VerifiableDouble} instance for the given subject.
@@ -318,23 +308,54 @@ public VerifiableLong that(Long subject) {
}
/**
- * This is the default object validation for subjects that
- * don't match any of the other pre-defined types.
- *
* @param subject the object to perform validation on.
- * @param the type of the subject.
- * @return a {@link VerifiableObject} instance for the given subject.
+ * @return a {@link VerifiableShort} instance for the given subject.
*/
- public VerifiableObject that(T subject) {
- return new VerifiableObject<>(failedValidationExecutor, subject, message);
+ public VerifiableShort that(Short subject) {
+ return new VerifiableShort<>(failedValidationExecutor, subject, message);
}
+ // - - - - - - - - - - - - - - - - -
+ // Time Object Types
+ // - - - - - - - - - - - - - - - - -
+
/**
* @param subject the object to perform validation on.
- * @return a {@link VerifiableShort} instance for the given subject.
+ * @return a {@link VerifiableDuration} instance for the given subject.
*/
- public VerifiableShort that(Short subject) {
- return new VerifiableShort<>(failedValidationExecutor, subject, message);
+ public VerifiableDuration that(Duration subject) {
+ return new VerifiableDuration<>(failedValidationExecutor, subject, message);
+ }
+
+ /**
+ * @param subject the object to perform validation on.
+ * @return a {@link VerifiableInstant} instance for the given subject.
+ */
+ public VerifiableInstant that(Instant subject) {
+ return new VerifiableInstant<>(failedValidationExecutor, subject, message);
+ }
+
+ // - - - - - - - - - - - - - - - - -
+ // Other Object Types
+ // - - - - - - - - - - - - - - - - -
+
+ /**
+ * @param subject the object to perform validation on.
+ * @param the class being validated.
+ * @return a {@link VerifiableClass} instance for the given subject.
+ */
+ public VerifiableClass that(Class subject) {
+ return new VerifiableClass<>(failedValidationExecutor, subject, message);
+ }
+
+ /**
+ * @param subject the object to perform validation on.
+ * @param the type of the objects in the collection.
+ * @param the type of the Collection (e.g. list, map, etc).
+ * @return a {@link VerifiableCollection} instance for the given subject.
+ */
+ public > VerifiableCollection that(T subject) {
+ return new VerifiableCollection<>(failedValidationExecutor, subject, message);
}
/**
@@ -345,6 +366,18 @@ public VerifiableString that(String subject) {
return new VerifiableString<>(failedValidationExecutor, subject, message);
}
+ /**
+ * This is the default object validation for subjects that
+ * don't match any of the other pre-defined types.
+ *
+ * @param subject the object to perform validation on.
+ * @param the type of the subject.
+ * @return a {@link VerifiableObject} instance for the given subject.
+ */
+ public VerifiableObject that(T subject) {
+ return new VerifiableObject<>(failedValidationExecutor, subject, message);
+ }
+
// --------------------------------------------------------------
// Not a value type enforcement
// --------------------------------------------------------------
diff --git a/src/main/java/com/redfin/validity/verifiers/objects/VerifiableDuration.java b/src/main/java/com/redfin/validity/verifiers/objects/VerifiableDuration.java
new file mode 100644
index 0000000..2bf8412
--- /dev/null
+++ b/src/main/java/com/redfin/validity/verifiers/objects/VerifiableDuration.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright: (c) 2016 Redfin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.redfin.validity.verifiers.objects;
+
+import com.redfin.validity.FailedValidationExecutor;
+import com.redfin.validity.verifiers.AbstractVerifiableComparable;
+import com.redfin.validity.verifiers.AbstractVerifiableObject;
+
+import java.time.Duration;
+
+/**
+ * Concrete class for verifying {@link Duration} subjects.
+ *
+ * @param the type of {@link Throwable} to be thrown on validation failure.
+ */
+public final class VerifiableDuration extends AbstractVerifiableComparable {
+
+ /**
+ * Create a new {@link AbstractVerifiableObject} instance with the given values.
+ *
+ * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
+ * on validation failure.
+ * May not be null.
+ * @param subject the subject to be validated.
+ * May be null.
+ * @param message the String custom message to pre-pend a failure with.
+ * May be null.
+ *
+ * @throws NullPointerException if failedValidationExecutor is null.
+ */
+ public VerifiableDuration(FailedValidationExecutor failedValidationExecutor, Duration subject, String message) {
+ super(failedValidationExecutor, subject, message);
+ }
+
+ /**
+ * @return the subject if it is zero.
+ * @throws X if the subject is null or is not zero.
+ */
+ public Duration isZero() throws X {
+ Duration subject = getSubject();
+ if (null == subject || !subject.isZero()) {
+ fail("t -> t.isZero()");
+ }
+ return subject;
+ }
+
+ /**
+ * @return the subject if it is not zero.
+ * @throws X if the subject is null or is zero.
+ */
+ public Duration isNotZero() throws X {
+ Duration subject = getSubject();
+ if (null == subject || subject.isZero()) {
+ fail("t -> !t.isZero()");
+ }
+ return subject;
+ }
+
+ /**
+ * @return the subject if it is not zero and negative.
+ * @throws X if the subject is null, is zero, or is positive.
+ */
+ public Duration isStrictlyNegative() throws X {
+ Duration subject = getSubject();
+ if (null == subject || !subject.isNegative()) {
+ fail("t -> t.isNegative()");
+ }
+ return subject;
+ }
+
+ /**
+ * @return the subject if it is not zero and positive.
+ * @throws X if the subject is null, is zero, or is negative.
+ */
+ public Duration isStrictlyPositive() throws X {
+ Duration subject = getSubject();
+ if (null == subject || subject.isZero() || subject.isNegative()) {
+ fail("t -> !t.isZero() && !t.isNegative()");
+ }
+ return subject;
+ }
+}
diff --git a/src/main/java/com/redfin/validity/verifiers/objects/VerifiableInstant.java b/src/main/java/com/redfin/validity/verifiers/objects/VerifiableInstant.java
new file mode 100644
index 0000000..a627277
--- /dev/null
+++ b/src/main/java/com/redfin/validity/verifiers/objects/VerifiableInstant.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright: (c) 2016 Redfin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.redfin.validity.verifiers.objects;
+
+import com.redfin.validity.FailedValidationExecutor;
+import com.redfin.validity.verifiers.AbstractVerifiableComparable;
+
+import java.time.Instant;
+
+/**
+ * Concrete class for verifying {@link Instant} subjects.
+ *
+ * @param the type of {@link Throwable} to be thrown on validation failure.
+ */
+public final class VerifiableInstant extends AbstractVerifiableComparable {
+
+ /**
+ * Create a new {@link AbstractVerifiableComparable} instance with the given values.
+ *
+ * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
+ * on validation failure.
+ * May not be null.
+ * @param subject the subject to be validated.
+ * May be null.
+ * @param message the String custom message to pre-pend a failure with.
+ * May be null.
+ *
+ * @throws NullPointerException if failedValidationExecutor is null.
+ */
+ public VerifiableInstant(FailedValidationExecutor failedValidationExecutor, Instant subject, String message) {
+ super(failedValidationExecutor, subject, message);
+ }
+}
diff --git a/src/test/java/com/redfin/validity/verifiers/objects/VerifiableDurationTest.java b/src/test/java/com/redfin/validity/verifiers/objects/VerifiableDurationTest.java
new file mode 100644
index 0000000..6a3418d
--- /dev/null
+++ b/src/test/java/com/redfin/validity/verifiers/objects/VerifiableDurationTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright: (c) 2016 Redfin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.redfin.validity.verifiers.objects;
+
+import com.redfin.validity.DefaultValidityFailedValidationExecutor;
+import com.redfin.validity.FailedValidationExecutor;
+import com.redfin.validity.verifiers.AbstractVerifiableComparableContract;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.time.Duration;
+
+final class VerifiableDurationTest implements AbstractVerifiableComparableContract> {
+
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Test values & contract implementations
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ private static final Duration SUBJECT = Duration.ofMinutes(1);
+ private static final Duration EQUAL = Duration.ofMinutes(1);
+ private static final Duration NON_EQUAL = Duration.ofMinutes(2);
+ private static final Duration LESS_THAN = Duration.ofMinutes(-1);
+ private static final Duration GREATER_THAN = Duration.ofMinutes(10);
+
+
+ @Override
+ public Duration getSubject() {
+ return SUBJECT;
+ }
+
+ @Override
+ public Duration getEqualSubject() {
+ return EQUAL;
+ }
+
+ @Override
+ public Duration getNonEqualSubject() {
+ return NON_EQUAL;
+ }
+
+ @Override
+ public VerifiableDuration getVerifiableInstance(FailedValidationExecutor failedValidationExecutor, Duration subject, String message) {
+ return new VerifiableDuration<>(failedValidationExecutor, subject, message);
+ }
+
+ @Override
+ public Class getThrowableClass() {
+ return IllegalArgumentException.class;
+ }
+
+ @Override
+ public FailedValidationExecutor getFailedValidationExecutor() {
+ return new DefaultValidityFailedValidationExecutor<>(IllegalArgumentException::new);
+ }
+
+ @Override
+ public Duration getComparableSubject() {
+ return EQUAL;
+ }
+
+ @Override
+ public Duration getNonComparableSubject() {
+ return NON_EQUAL;
+ }
+
+ @Override
+ public Duration getLessThanSubject() {
+ return LESS_THAN;
+ }
+
+ @Override
+ public Duration getGreaterThanSubject() {
+ return GREATER_THAN;
+ }
+
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Test cases
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ @Test
+ void testIsZeroReturnsSubjectForZeroSubject() {
+ Duration subject = Duration.ZERO;
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertTrue(subject == verifiable.isZero(),
+ "VerifiableDuration should return it's given subject for isZero when it's zero");
+ }
+
+ @Test
+ void testIsZeroThrowsForNonZeroSubject() {
+ Duration subject = Duration.ofMinutes(1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isZero);
+ }
+
+ @Test
+ void testIsZeroThrowsForNullSubject() {
+ VerifiableDuration verifiable = getVerifiableInstance(null);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isZero);
+ }
+
+ @Test
+ void testIsNotZeroReturnsSubjectForNonZeroSubject() {
+ Duration subject = Duration.ofMinutes(1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertTrue(subject == verifiable.isNotZero(),
+ "VerifiableDuration should return it's given subject for isNotZero when it's not zero");
+ }
+
+ @Test
+ void testIsNotZeroThrowsForZeroSubject() {
+ Duration subject = Duration.ZERO;
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isNotZero);
+ }
+
+ @Test
+ void testIsNotZeroThrowsForNullSubject() {
+ VerifiableDuration verifiable = getVerifiableInstance(null);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isNotZero);
+ }
+
+ @Test
+ void testIsStrictlyPositiveReturnsSubjectForPositiveSubject() {
+ Duration subject = Duration.ofMinutes(1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertTrue(subject == verifiable.isStrictlyPositive(),
+ "VerifiableDuration should return it's given subject for isStrictlyPositive when it's positive");
+ }
+
+ @Test
+ void testIsStrictlyPositiveThrowsForZeroSubject() {
+ Duration subject = Duration.ZERO;
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyPositive);
+ }
+
+ @Test
+ void testIsStrictlyPositiveThrowsForNegativeSubject() {
+ Duration subject = Duration.ofMinutes(-1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyPositive);
+ }
+
+ @Test
+ void testIsStrictlyPositiveThrowsForNullSubject() {
+ VerifiableDuration verifiable = getVerifiableInstance(null);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyPositive);
+ }
+
+ @Test
+ void testIsStrictlyNegativeReturnsSubjectForNegativeSubject() {
+ Duration subject = Duration.ofMinutes(-1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertTrue(subject == verifiable.isStrictlyNegative(),
+ "VerifiableDuration should return it's given subject for isStrictlyNegative when it's negative");
+ }
+
+ @Test
+ void testIsStrictlyNegativeThrowsForZeroSubject() {
+ Duration subject = Duration.ZERO;
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyNegative);
+ }
+
+ @Test
+ void testIsStrictlyNegativeThrowsForPositiveSubject() {
+ Duration subject = Duration.ofMinutes(1);
+ VerifiableDuration verifiable = getVerifiableInstance(subject);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyNegative);
+ }
+
+ @Test
+ void testIsStrictlyNegativeThrowsForNullSubject() {
+ VerifiableDuration verifiable = getVerifiableInstance(null);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ verifiable::isStrictlyNegative);
+ }
+}
diff --git a/src/test/java/com/redfin/validity/verifiers/objects/VerifiableInstantTest.java b/src/test/java/com/redfin/validity/verifiers/objects/VerifiableInstantTest.java
new file mode 100644
index 0000000..584f0a6
--- /dev/null
+++ b/src/test/java/com/redfin/validity/verifiers/objects/VerifiableInstantTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright: (c) 2016 Redfin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.redfin.validity.verifiers.objects;
+
+import com.redfin.validity.DefaultValidityFailedValidationExecutor;
+import com.redfin.validity.FailedValidationExecutor;
+import com.redfin.validity.verifiers.AbstractVerifiableComparableContract;
+
+import java.time.Duration;
+import java.time.Instant;
+
+final class VerifiableInstantTest implements AbstractVerifiableComparableContract> {
+
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Test values & contract implementations
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ private static final Instant SUBJECT = Instant.now();
+ private static final Instant EQUAL = Instant.ofEpochMilli(SUBJECT.toEpochMilli());
+ private static final Instant NON_EQUAL = SUBJECT.minus(Duration.ofSeconds(10));
+ private static final Instant LESS_THAN = SUBJECT.minus(Duration.ofMinutes(1));
+ private static final Instant GREATER_THAN = SUBJECT.plus(Duration.ofMinutes(1));
+
+ @Override
+ public Instant getSubject() {
+ return SUBJECT;
+ }
+
+ @Override
+ public Instant getEqualSubject() {
+ return EQUAL;
+ }
+
+ @Override
+ public Instant getNonEqualSubject() {
+ return NON_EQUAL;
+ }
+
+ @Override
+ public VerifiableInstant getVerifiableInstance(FailedValidationExecutor failedValidationExecutor, Instant subject, String message) {
+ return new VerifiableInstant<>(failedValidationExecutor, subject, message);
+ }
+
+ @Override
+ public Class getThrowableClass() {
+ return IllegalArgumentException.class;
+ }
+
+ @Override
+ public FailedValidationExecutor getFailedValidationExecutor() {
+ return new DefaultValidityFailedValidationExecutor<>(IllegalArgumentException::new);
+ }
+
+ @Override
+ public Instant getComparableSubject() {
+ return EQUAL;
+ }
+
+ @Override
+ public Instant getNonComparableSubject() {
+ return NON_EQUAL;
+ }
+
+ @Override
+ public Instant getLessThanSubject() {
+ return LESS_THAN;
+ }
+
+ @Override
+ public Instant getGreaterThanSubject() {
+ return GREATER_THAN;
+ }
+}