diff --git a/src/main/java/org/springframework/data/envers/repository/support/DefaultRevisionMetadata.java b/src/main/java/org/springframework/data/envers/repository/support/DefaultRevisionMetadata.java index b309be2..7ef973d 100755 --- a/src/main/java/org/springframework/data/envers/repository/support/DefaultRevisionMetadata.java +++ b/src/main/java/org/springframework/data/envers/repository/support/DefaultRevisionMetadata.java @@ -15,10 +15,17 @@ */ package org.springframework.data.envers.repository.support; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.Value; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.Optional; + import org.hibernate.envers.DefaultRevisionEntity; -import org.joda.time.DateTime; import org.springframework.data.history.RevisionMetadata; -import org.springframework.util.Assert; /** * {@link RevisionMetadata} working with a {@link DefaultRevisionEntity}. @@ -26,35 +33,25 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Philip Huegelmeyer */ +@Value public class DefaultRevisionMetadata implements RevisionMetadata { - private final DefaultRevisionEntity entity; - - /** - * Creates a new {@link DefaultRevisionMetadata}. - * - * @param entity must not be {@literal null}. - */ - public DefaultRevisionMetadata(DefaultRevisionEntity entity) { - - Assert.notNull(entity); - this.entity = entity; - } + private final @NonNull @Getter(AccessLevel.NONE) DefaultRevisionEntity entity; /* * (non-Javadoc) * @see org.springframework.data.history.RevisionMetadata#getRevisionNumber() */ - public Integer getRevisionNumber() { - return entity.getId(); + public Optional getRevisionNumber() { + return Optional.ofNullable(entity.getId()); } /* * (non-Javadoc) * @see org.springframework.data.history.RevisionMetadata#getRevisionDate() */ - public DateTime getRevisionDate() { - return new DateTime(entity.getTimestamp()); + public Optional getRevisionDate() { + return Optional.of(LocalDateTime.from(Instant.ofEpochMilli(entity.getTimestamp()))); } /* diff --git a/src/main/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImpl.java b/src/main/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImpl.java index 2b35466..1fb3a9c 100755 --- a/src/main/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImpl.java +++ b/src/main/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImpl.java @@ -16,13 +16,12 @@ package org.springframework.data.envers.repository.support; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; +import java.util.Optional; import javax.persistence.EntityManager; @@ -42,7 +41,10 @@ import org.springframework.data.history.Revisions; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.history.RevisionRepository; import org.springframework.data.repository.history.support.RevisionEntityInformation; +import org.springframework.data.util.Pair; +import org.springframework.data.util.StreamUtils; import org.springframework.util.Assert; /** @@ -53,7 +55,7 @@ import org.springframework.util.Assert; * @author Michael Igler */ public class EnversRevisionRepositoryImpl> - extends SimpleJpaRepository implements EnversRevisionRepository { + extends SimpleJpaRepository implements RevisionRepository { private final EntityInformation entityInformation; private final RevisionEntityInformation revisionEntityInformation; @@ -72,7 +74,7 @@ public class EnversRevisionRepositoryImpl findLastChangeRevision(ID id) { + public Optional> findLastChangeRevision(ID id) { Class type = entityInformation.getJavaType(); AuditReader reader = AuditReaderFactory.get(entityManager); @@ -92,7 +94,7 @@ public class EnversRevisionRepositoryImpl revisions = reader.getRevisions(type, id); if (revisions.isEmpty()) { - return null; + return Optional.empty(); } N latestRevision = (N) revisions.get(revisions.size() - 1); @@ -101,7 +103,8 @@ public class EnversRevisionRepositoryImpl metadata = (RevisionMetadata) getRevisionMetadata(revisionEntity); - return new Revision(metadata, reader.find(type, id, latestRevision)); + + return Optional.of(Revision.of(metadata, reader.find(type, id, latestRevision))); } /* @@ -109,7 +112,7 @@ public class EnversRevisionRepositoryImpl findRevision(ID id, N revisionNumber) { + public Optional> findRevision(ID id, N revisionNumber) { Assert.notNull(id, "Identifier must not be null!"); Assert.notNull(revisionNumber, "Revision number must not be null!"); @@ -128,7 +131,7 @@ public class EnversRevisionRepositoryImpl revisionNumbers = reader.getRevisions(type, id); - return revisionNumbers.isEmpty() ? new Revisions(Collections.EMPTY_LIST) + return revisionNumbers.isEmpty() ? Revisions.none() : getEntitiesForRevisions((List) revisionNumbers, id, reader); } @@ -149,13 +152,13 @@ public class EnversRevisionRepositoryImpl revisionNumbers.size()) { - return new PageImpl>(Collections.>emptyList(), pageable, 0); + return new PageImpl>(Collections.> emptyList(), pageable, 0); } - int upperBound = pageable.getOffset() + pageable.getPageSize(); + long upperBound = pageable.getOffset() + pageable.getPageSize(); upperBound = upperBound > revisionNumbers.size() ? revisionNumbers.size() : upperBound; - List subList = revisionNumbers.subList(pageable.getOffset(), upperBound); + List subList = revisionNumbers.subList(toInt(pageable.getOffset()), toInt(upperBound)); Revisions revisions = getEntitiesForRevisions((List) subList, id, reader); revisions = isDescending ? revisions.reverse() : revisions; @@ -185,7 +188,7 @@ public class EnversRevisionRepositoryImpl(toRevisions(revisions, revisionEntities)); + return Revisions.of(toRevisions(revisions, revisionEntities)); } /** @@ -197,31 +200,24 @@ public class EnversRevisionRepositoryImpl getEntityForRevision(N revisionNumber, ID id, AuditReader reader) { + private Optional> getEntityForRevision(N revisionNumber, ID id, AuditReader reader) { Class type = revisionEntityInformation.getRevisionEntityClass(); T revision = (T) reader.findRevision(type, revisionNumber); - Object entity = reader.find(entityInformation.getJavaType(), id, revisionNumber); + Optional entity = Optional.ofNullable(reader.find(entityInformation.getJavaType(), id, revisionNumber)); - return new Revision((RevisionMetadata) getRevisionMetadata(revision), (T) entity); + return entity.map(it -> Revision.of((RevisionMetadata) getRevisionMetadata(revision), (T) it)); } @SuppressWarnings("unchecked") private List> toRevisions(Map source, Map revisionEntities) { - List> result = new ArrayList>(); - - for (Entry revision : source.entrySet()) { - - N revisionNumber = revision.getKey(); - T entity = revision.getValue(); - RevisionMetadata metadata = (RevisionMetadata) getRevisionMetadata(revisionEntities.get(revisionNumber)); - result.add(new Revision(metadata, entity)); - } - - Collections.sort(result); - return Collections.unmodifiableList(result); + return source.entrySet().stream()// + .map(entry -> Pair.of(revisionEntities.get(entry.getKey()), entry.getValue()))// + .map(pair -> Revision.of((RevisionMetadata) getRevisionMetadata(pair.getFirst()), pair.getSecond()))// + .sorted()// + .collect(StreamUtils.toUnmodifiableList()); } /** @@ -231,10 +227,18 @@ public class EnversRevisionRepositoryImpl getRevisionMetadata(Object object) { - if (object instanceof DefaultRevisionEntity) { - return new DefaultRevisionMetadata((DefaultRevisionEntity) object); - } else { - return new AnnotationRevisionMetadata(object, RevisionNumber.class, RevisionTimestamp.class); + + return object instanceof DefaultRevisionEntity // + ? new DefaultRevisionMetadata((DefaultRevisionEntity) object) // + : new AnnotationRevisionMetadata(object, RevisionNumber.class, RevisionTimestamp.class); + } + + private static int toInt(long value) { + + if (value > Integer.MAX_VALUE) { + throw new IllegalStateException(String.format("%s can't be mapped to an integer, too large!", value)); } + + return Long.valueOf(value).intValue(); } } diff --git a/src/main/java/org/springframework/data/envers/repository/support/ReflectionRevisionEntityInformation.java b/src/main/java/org/springframework/data/envers/repository/support/ReflectionRevisionEntityInformation.java index a36fc5f..f136ac2 100644 --- a/src/main/java/org/springframework/data/envers/repository/support/ReflectionRevisionEntityInformation.java +++ b/src/main/java/org/springframework/data/envers/repository/support/ReflectionRevisionEntityInformation.java @@ -15,6 +15,8 @@ */ package org.springframework.data.envers.repository.support; +import lombok.Getter; + import org.hibernate.envers.RevisionNumber; import org.springframework.data.repository.history.support.RevisionEntityInformation; import org.springframework.data.util.AnnotationDetectionFieldCallback; @@ -27,6 +29,7 @@ import org.springframework.util.ReflectionUtils; * * @author Oliver Gierke */ +@Getter public class ReflectionRevisionEntityInformation implements RevisionEntityInformation { private final Class revisionEntityClass; @@ -39,24 +42,16 @@ public class ReflectionRevisionEntityInformation implements RevisionEntityInform */ public ReflectionRevisionEntityInformation(Class revisionEntityClass) { - Assert.notNull(revisionEntityClass); + Assert.notNull(revisionEntityClass, "Revision entity type must not be null!"); AnnotationDetectionFieldCallback fieldCallback = new AnnotationDetectionFieldCallback(RevisionNumber.class); ReflectionUtils.doWithFields(revisionEntityClass, fieldCallback); - this.revisionNumberType = fieldCallback.getType(); + this.revisionNumberType = fieldCallback.getRequiredType(); this.revisionEntityClass = revisionEntityClass; } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionNumberType() - */ - public Class getRevisionNumberType() { - return revisionNumberType; - } - /* * (non-Javadoc) * @see org.springframework.data.repository.history.support.RevisionEntityInformation#isDefaultRevisionEntity() @@ -64,12 +59,4 @@ public class ReflectionRevisionEntityInformation implements RevisionEntityInform public boolean isDefaultRevisionEntity() { return false; } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionEntityClass() - */ - public Class getRevisionEntityClass() { - return revisionEntityClass; - } } diff --git a/src/test/java/org/springframework/data/envers/repository/support/RepositoryIntegrationTests.java b/src/test/java/org/springframework/data/envers/repository/support/RepositoryIntegrationTests.java index 76491be..42e06b5 100755 --- a/src/test/java/org/springframework/data/envers/repository/support/RepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/envers/repository/support/RepositoryIntegrationTests.java @@ -15,15 +15,13 @@ */ package org.springframework.data.envers.repository.support; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import static org.assertj.core.api.Assertions.*; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -import java.util.List; +import java.util.Optional; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -88,17 +86,19 @@ public class RepositoryIntegrationTests { countryRepository.save(de); - Revision revision = licenseRepository.findLastChangeRevision(license.id); - assertThat(revision, is(notNullValue())); + Optional> revision = licenseRepository.findLastChangeRevision(license.id); - Page> revisions = licenseRepository.findRevisions(license.id, new PageRequest(0, 10)); - Revisions wrapper = new Revisions(revisions.getContent()); - assertThat(wrapper.getLatestRevision(), is(revision)); + assertThat(revision).hasValueSatisfying(it -> { + + Page> page = licenseRepository.findRevisions(license.id, PageRequest.of(0, 10)); + Revisions revisions = Revisions.of(page.getContent()); + assertThat(revisions.getLatestRevision()).isEqualTo(it); + }); } @Test public void returnsEmptyRevisionsForUnrevisionedEntity() { - assertThat(countryRepository.findRevisions(100L).getContent(), is(hasSize(0))); + assertThat(countryRepository.findRevisions(100L)).isEmpty(); } /** @@ -119,14 +119,19 @@ public class RepositoryIntegrationTests { Revisions revisions = countryRepository.findRevisions(de.id); - assertThat(revisions, is(Matchers.>iterableWithSize(2))); + assertThat(revisions).hasSize(2); Iterator> iterator = revisions.iterator(); Revision first = iterator.next(); Revision second = iterator.next(); - assertThat(countryRepository.findRevision(de.id, first.getRevisionNumber()).getEntity().name, is("Deutschland")); - assertThat(countryRepository.findRevision(de.id, second.getRevisionNumber()).getEntity().name, is("Germany")); + assertThat(countryRepository.findRevision(de.id, first.getRequiredRevisionNumber())).hasValueSatisfying(it -> { + assertThat(it.getEntity().name).isEqualTo("Deutschland"); + }); + + assertThat(countryRepository.findRevision(de.id, second.getRequiredRevisionNumber())).hasValueSatisfying(it -> { + assertThat(it.getEntity().name).isEqualTo("Germany"); + }); } /** @@ -145,10 +150,11 @@ public class RepositoryIntegrationTests { countryRepository.save(de); - List> content = countryRepository - .findRevisions(de.id, new PageRequest(0, 10, RevisionSort.desc())).getContent(); + Page> page = countryRepository.findRevisions(de.id, + PageRequest.of(0, 10, RevisionSort.desc())); - assertThat(content, hasSize(2)); - assertThat(content.get(0).getRevisionNumber(), is(greaterThan(content.get(1).getRevisionNumber()))); + assertThat(page).hasSize(2); + assertThat(page.getContent().get(0).getRequiredRevisionNumber()) + .isGreaterThan(page.getContent().get(1).getRequiredRevisionNumber()); } } diff --git a/src/test/java/org/springframework/data/envers/sample/AbstractEntity.java b/src/test/java/org/springframework/data/envers/sample/AbstractEntity.java index 4ba3c0e..c4c2dbf 100644 --- a/src/test/java/org/springframework/data/envers/sample/AbstractEntity.java +++ b/src/test/java/org/springframework/data/envers/sample/AbstractEntity.java @@ -15,38 +15,15 @@ */ package org.springframework.data.envers.sample; +import lombok.EqualsAndHashCode; + import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; -import org.springframework.util.ObjectUtils; - @MappedSuperclass +@EqualsAndHashCode abstract class AbstractEntity { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long id; - - /* - * (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - - if (this == obj) { - return true; - } - - if (!(obj instanceof AbstractEntity)) { - return false; - } - - AbstractEntity that = (AbstractEntity) obj; - - return ObjectUtils.nullSafeEquals(this.id, that.id); - } - -} \ No newline at end of file + public @Id @GeneratedValue Long id; +}