From 139e098e8519805b57f9bec00e80f8a6b0fd2af1 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 1 Feb 2018 14:59:33 +0100 Subject: [PATCH] DATACMNS-1251 - Added methods returning Instant to Revision. Revision and RevisionMetadata now have methods returning Instant instead of LocalDateTime. The existing methods returning LocalDateTime are now deprecated. Original pull request: #270. --- .../history/AnnotationRevisionMetadata.java | 47 ++++++++++++++- .../data/history/Revision.java | 26 ++++++++- .../data/history/RevisionMetadata.java | 27 ++++++++- .../AnnotationRevisionMetadataUnitTests.java | 58 ++++++++++++++++--- .../data/history/RevisionUnitTests.java | 11 ++++ 5 files changed, 156 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java b/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java index 2f1dca7b3..48c8ab659 100755 --- a/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java +++ b/src/main/java/org/springframework/data/history/AnnotationRevisionMetadata.java @@ -16,7 +16,10 @@ package org.springframework.data.history; import java.lang.annotation.Annotation; +import java.time.Instant; import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.temporal.TemporalAccessor; import java.util.Optional; import org.springframework.data.util.AnnotationDetectionFieldCallback; @@ -26,15 +29,17 @@ import org.springframework.util.ReflectionUtils; /** * A {@link RevisionMetadata} implementation that inspects the given object for fields with the configured annotations - * and returns the field's values on calls to {@link #getRevisionDate()} and {@link #getRevisionNumber()}. + * and returns the field's values on calls to {@link #getRevisionDate()}, {@link #getRevisionInstant()} and + * {@link #getRevisionNumber()}. * * @author Oliver Gierke + * @author Jens Schauder */ public class AnnotationRevisionMetadata> implements RevisionMetadata { private final Object entity; private final Lazy> revisionNumber; - private final Lazy> revisionDate; + private final Lazy> revisionDate; /** * Creates a new {@link AnnotationRevisionMetadata} inspecting the given entity for the given annotations. If no @@ -68,8 +73,44 @@ public class AnnotationRevisionMetadata> implem * (non-Javadoc) * @see org.springframework.data.history.RevisionMetadata#getRevisionDate() */ + @Deprecated public Optional getRevisionDate() { - return revisionDate.get(); + + return revisionDate.get().map(this::convertToLocalDateTime); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.history.RevisionMetadata#getRevisionDate() + */ + public Optional getRevisionInstant() { + return revisionDate.get().map(this::convertToInstant); + } + + private LocalDateTime convertToLocalDateTime(TemporalAccessor temporalAccessor) { + + if (temporalAccessor instanceof LocalDateTime) { + return (LocalDateTime) temporalAccessor; + } + + if (temporalAccessor instanceof Instant) { + return LocalDateTime.ofInstant((Instant) temporalAccessor, ZoneOffset.systemDefault()); + } + + throw new IllegalArgumentException(String.format("Can't convert %s to LocalDateTime", temporalAccessor)); + } + + private Instant convertToInstant(TemporalAccessor temporalAccessor) { + + if (temporalAccessor instanceof Instant) { + return (Instant) temporalAccessor; + } + + if (temporalAccessor instanceof LocalDateTime) { + return ((LocalDateTime) temporalAccessor).atZone(ZoneOffset.systemDefault()).toInstant(); + } + + throw new IllegalArgumentException(String.format("Can't convert %s to LocalDateTime", temporalAccessor)); } /* diff --git a/src/main/java/org/springframework/data/history/Revision.java b/src/main/java/org/springframework/data/history/Revision.java index f466b3d48..ad8981f03 100755 --- a/src/main/java/org/springframework/data/history/Revision.java +++ b/src/main/java/org/springframework/data/history/Revision.java @@ -22,6 +22,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Value; +import java.time.Instant; import java.time.LocalDateTime; import java.util.Optional; @@ -33,6 +34,7 @@ import org.springframework.lang.Nullable; * @author Oliver Gierke * @author Philipp Huegelmeyer * @author Christoph Strobl + * @author Jens Schauder */ @Value @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @@ -80,21 +82,43 @@ public final class Revision, T> implements Comp /** * Returns the revision date of the revision. * - * @return + * @return Guaranteed to be not {@literal null}. + * @deprecated Use {@link #getRevisionInstant()} instead. */ + @Deprecated public Optional getRevisionDate() { return metadata.getRevisionDate(); } + /** + * Returns the timestamp of the revision. + * + * @return Guaranteed to be not {@literal null}. + */ + public Optional getRevisionInstant() { + return metadata.getRevisionInstant(); + } + /** * Returns the revision date of the revision, immediately failing on absence. * * @return the revision date. + * @deprecated Use {@link #getRequiredRevisionInstant()} instead. */ + @Deprecated public LocalDateTime getRequiredRevisionDate() { return metadata.getRequiredRevisionDate(); } + /** + * Returns the timestamp of the revision, immediately failing on absence. + * + * @return the revision {@link Instant}. May be {@literal null}. + */ + public Instant getRequiredRevisionInstant() { + return metadata.getRequiredRevisionInstant(); + } + /* * (non-Javadoc) * @see java.lang.Comparable#compareTo(java.lang.Object) diff --git a/src/main/java/org/springframework/data/history/RevisionMetadata.java b/src/main/java/org/springframework/data/history/RevisionMetadata.java index 06b7e907b..b42107f1e 100755 --- a/src/main/java/org/springframework/data/history/RevisionMetadata.java +++ b/src/main/java/org/springframework/data/history/RevisionMetadata.java @@ -15,6 +15,7 @@ */ package org.springframework.data.history; +import java.time.Instant; import java.time.LocalDateTime; import java.util.Optional; @@ -23,6 +24,7 @@ import java.util.Optional; * * @author Philipp Huegelmeyer * @author Oliver Gierke + * @author Jens Schauder */ public interface RevisionMetadata> { @@ -48,20 +50,43 @@ public interface RevisionMetadata> { * Returns the date of the revision. * * @return will never be {@literal null}. + * @deprecated use {@link #getRevisionInstant()} instead. */ + @Deprecated Optional getRevisionDate(); + /** + * Returns the timestamp of the revision. + * + * @return will never be {@literal null}. + */ + Optional getRevisionInstant(); + /** * Returns the revision date of the revision, immediately failing on absence. * * @return will never be {@literal null}. - * @throw IllegalStateException if no revision date is available. + * @throws IllegalStateException if no revision date is available. + * @deprecated Use {@link #getRevisionInstant()} instead. */ + @Deprecated default LocalDateTime getRequiredRevisionDate() { return getRevisionDate().orElseThrow( () -> new IllegalStateException(String.format("No revision date found on %s!", (Object) getDelegate()))); } + + /** + * Returns the timestamp of the revision, immediately failing on absence. + * + * @return will never be {@literal null}. + * @throws IllegalStateException if no revision date is available. + */ + default Instant getRequiredRevisionInstant() { + return getRevisionInstant().orElseThrow( + () -> new IllegalStateException(String.format("No revision date found on %s!", (Object) getDelegate()))); + } + /** * Returns the underlying revision metadata which might provider more detailed implementation specific information. * diff --git a/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java b/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java index 115224040..7d247237e 100644 --- a/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java +++ b/src/test/java/org/springframework/data/history/AnnotationRevisionMetadataUnitTests.java @@ -17,8 +17,11 @@ package org.springframework.data.history; import static org.assertj.core.api.Assertions.*; +import java.time.Instant; import java.time.LocalDateTime; +import java.time.ZoneOffset; +import org.assertj.core.api.SoftAssertions; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Reference; @@ -27,9 +30,12 @@ import org.springframework.data.annotation.Reference; * Unit tests for {@link AnnotationRevisionMetadata}. * * @author Oliver Gierke + * @author Jens Schauder */ public class AnnotationRevisionMetadataUnitTests { + SoftAssertions softly = new SoftAssertions(); + @Test // DATACMNS-1173 public void exposesNoInformationOnEmptyProbe() { @@ -40,10 +46,14 @@ public class AnnotationRevisionMetadataUnitTests { assertThat(metadata.getRevisionDate()).isEmpty(); assertThatExceptionOfType(IllegalStateException.class) // - .isThrownBy(() -> metadata.getRequiredRevisionNumber()); + .isThrownBy(metadata::getRequiredRevisionNumber); assertThatExceptionOfType(IllegalStateException.class) // - .isThrownBy(() -> metadata.getRequiredRevisionDate()); + .isThrownBy(metadata::getRequiredRevisionDate); + + assertThatExceptionOfType(IllegalStateException.class) // + .isThrownBy(metadata::getRequiredRevisionInstant); + } @Test // DATACMNS-1173 @@ -54,23 +64,49 @@ public class AnnotationRevisionMetadataUnitTests { RevisionMetadata metadata = getMetadata(sample); - assertThat(metadata.getRevisionNumber()).hasValue(1L); - assertThat(metadata.getRequiredRevisionNumber()).isEqualTo(1L); + softly.assertThat(metadata.getRevisionNumber()).hasValue(1L); + softly.assertThat(metadata.getRequiredRevisionNumber()).isEqualTo(1L); + + softly.assertAll(); } @Test // DATACMNS-1173 - public void exposesRevisionDate() { + public void exposesRevisionDateAndInstantForLocalDateTime() { Sample sample = new Sample(); sample.revisionDate = LocalDateTime.now(); + Instant expectedInstant = sample.revisionDate.atZone(ZoneOffset.systemDefault()).toInstant(); RevisionMetadata metadata = getMetadata(sample); - assertThat(metadata.getRevisionDate()).hasValue(sample.revisionDate); - assertThat(metadata.getRequiredRevisionDate()).isEqualTo(sample.revisionDate); + softly.assertThat(metadata.getRevisionDate()).hasValue(sample.revisionDate); + softly.assertThat(metadata.getRequiredRevisionDate()).isEqualTo(sample.revisionDate); + + softly.assertThat(metadata.getRevisionInstant()).hasValue(expectedInstant); + softly.assertThat(metadata.getRequiredRevisionInstant()).isEqualTo(expectedInstant); + + softly.assertAll(); } - private static RevisionMetadata getMetadata(Sample sample) { + @Test // DATACMNS-1251 + public void exposesRevisionDateAndInstantForInstant() { + + SampleWithInstant sample = new SampleWithInstant(); + sample.revisionInstant = Instant.now(); + LocalDateTime expectedLocalDateTime = LocalDateTime.ofInstant(sample.revisionInstant, ZoneOffset.systemDefault()); + + RevisionMetadata metadata = getMetadata(sample); + + softly.assertThat(metadata.getRevisionDate()).hasValue(expectedLocalDateTime); + softly.assertThat(metadata.getRequiredRevisionDate()).isEqualTo(expectedLocalDateTime); + + softly.assertThat(metadata.getRevisionInstant()).hasValue(sample.revisionInstant); + softly.assertThat(metadata.getRequiredRevisionInstant()).isEqualTo(sample.revisionInstant); + + softly.assertAll(); + } + + private static RevisionMetadata getMetadata(Object sample) { return new AnnotationRevisionMetadata<>(sample, Autowired.class, Reference.class); } @@ -79,4 +115,10 @@ public class AnnotationRevisionMetadataUnitTests { @Autowired Long revisionNumber; @Reference LocalDateTime revisionDate; } + + static class SampleWithInstant { + + @Autowired Long revisionNumber; + @Reference Instant revisionInstant; + } } diff --git a/src/test/java/org/springframework/data/history/RevisionUnitTests.java b/src/test/java/org/springframework/data/history/RevisionUnitTests.java index 24a57d73d..c14d0f3d6 100755 --- a/src/test/java/org/springframework/data/history/RevisionUnitTests.java +++ b/src/test/java/org/springframework/data/history/RevisionUnitTests.java @@ -18,6 +18,7 @@ package org.springframework.data.history; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.time.Instant; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -33,6 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner; * Unit tests for {@link RevisionMetadata}. * * @author Oliver Gierke + * @author Jens Schauder */ @RunWith(MockitoJUnitRunner.class) public class RevisionUnitTests { @@ -72,6 +74,15 @@ public class RevisionUnitTests { assertThat(Revision.of(firstMetadata, new Object()).getRevisionDate()).isEqualTo(reference); } + @Test // DATACMNS-1251 + public void returnsRevisionInstant() { + + Optional reference = Optional.of(Instant.now()); + when(firstMetadata.getRevisionInstant()).thenReturn(reference); + + assertThat(Revision.of(firstMetadata, new Object()).getRevisionInstant()).isEqualTo(reference); + } + @Test // DATACMNS-218 public void returnsRevisionMetadata() { assertThat(Revision.of(firstMetadata, new Object()).getMetadata()).isEqualTo(firstMetadata);