From 3a2b6b601bba4f95291cc1e254d665cbb85df4d8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Aug 2017 10:24:23 +0200 Subject: [PATCH] DATACMNS-1141 - Add missing NonNullApi and Nullable annotations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Nullable annotation to ParsingUtils, Sort.Order and PropertyValueProvider. Add getRequiredAnnotation(…) to PersistentEntity and PersistentProperty to provide methods returning required, non-null annotations. --- .../data/config/ParsingUtils.java | 5 ++-- .../org/springframework/data/domain/Sort.java | 6 ++--- .../data/mapping/PersistentEntity.java | 20 ++++++++++++++ .../data/mapping/PersistentProperty.java | 21 +++++++++++++++ .../mapping/model/PropertyValueProvider.java | 3 +++ ...ationBasedPersistentPropertyUnitTests.java | 27 +++++++++++++++---- .../model/BasicPersistentEntityUnitTests.java | 18 +++++++++++++ 7 files changed, 90 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/springframework/data/config/ParsingUtils.java b/src/main/java/org/springframework/data/config/ParsingUtils.java index 66cd6a99b..37c81ddb7 100644 --- a/src/main/java/org/springframework/data/config/ParsingUtils.java +++ b/src/main/java/org/springframework/data/config/ParsingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.w3c.dom.Element; * Utility methods for {@link BeanDefinitionParser} implementations. * * @author Oliver Gierke + * @author Mark Paluch */ public abstract class ParsingUtils { @@ -138,7 +139,7 @@ public abstract class ParsingUtils { * @param source * @return */ - public static AbstractBeanDefinition getObjectFactoryBeanDefinition(String targetBeanName, Object source) { + public static AbstractBeanDefinition getObjectFactoryBeanDefinition(String targetBeanName, @Nullable Object source) { Assert.hasText(targetBeanName, "Target bean name must not be null or empty!"); diff --git a/src/main/java/org/springframework/data/domain/Sort.java b/src/main/java/org/springframework/data/domain/Sort.java index 28d8eda6f..2daa6a699 100644 --- a/src/main/java/org/springframework/data/domain/Sort.java +++ b/src/main/java/org/springframework/data/domain/Sort.java @@ -414,7 +414,7 @@ public class Sort implements Streamable> extends It @Nullable A findAnnotation(Class annotationType); + /** + * Returns the required annotation of the given type on the {@link PersistentEntity}. + * + * @param annotationType must not be {@literal null}. + * @return the annotation. + * @throws IllegalStateException if the required {@code annotationType} is not found. + * @since 2.0 + */ + default A getRequiredAnnotation(Class annotationType) throws IllegalStateException { + + A annotation = findAnnotation(annotationType); + + if (annotation != null) { + return annotation; + } + + throw new IllegalStateException( + String.format("Required annotation %s not found for %s!", annotationType, getType())); + } + /** * Checks whether the annotation of the given type is present on the {@link PersistentEntity}. * diff --git a/src/main/java/org/springframework/data/mapping/PersistentProperty.java b/src/main/java/org/springframework/data/mapping/PersistentProperty.java index f71af1542..3d911a0fc 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/PersistentProperty.java @@ -269,6 +269,27 @@ public interface PersistentProperty

> { @Nullable A findAnnotation(Class annotationType); + /** + * Looks up the annotation of the given type on the {@link PersistentProperty}. Will inspect accessors and the + * potentially backing field and traverse accessor methods to potentially available super types. + * + * @param annotationType the annotation to look up, must not be {@literal null}. + * @return the annotation of the given type. + * @throws IllegalStateException if the required {@code annotationType} is not found. + * @since 2.0 + */ + default A getRequiredAnnotation(Class annotationType) throws IllegalStateException { + + A annotation = findAnnotation(annotationType); + + if (annotation != null) { + return annotation; + } + + throw new IllegalStateException( + String.format("Required annotation %s not found for %s!", annotationType, getName())); + } + /** * Looks up the annotation of the given type on the property and the owning type if no annotation can be found on it. * Useful to lookup annotations that can be configured on the type but overridden on an individual property. diff --git a/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java b/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java index 3b5d9ddef..c4d4473ce 100644 --- a/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java @@ -16,11 +16,13 @@ package org.springframework.data.mapping.model; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.lang.Nullable; /** * SPI for components to provide values for as {@link PersistentProperty}. * * @author Oliver Gierke + * @author Mark Paluch */ public interface PropertyValueProvider

> { @@ -30,5 +32,6 @@ public interface PropertyValueProvider

> { * @param property will never be {@literal null}. * @return */ + @Nullable T getPropertyValue(P property); } diff --git a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java index 5f45251ec..ae3100f4e 100755 --- a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java @@ -25,8 +25,6 @@ import java.lang.annotation.Target; import java.util.Map; import java.util.Optional; -import org.springframework.lang.Nullable; - import org.junit.Before; import org.junit.Test; import org.springframework.core.annotation.AliasFor; @@ -37,8 +35,10 @@ import org.springframework.data.annotation.Id; import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.annotation.Transient; import org.springframework.data.mapping.MappingException; +import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.context.SampleMappingContext; import org.springframework.data.mapping.context.SamplePersistentProperty; +import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; /** @@ -46,6 +46,7 @@ import org.springframework.test.util.ReflectionTestUtils; * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ public class AnnotationBasedPersistentPropertyUnitTests

> { @@ -217,9 +218,25 @@ public class AnnotationBasedPersistentPropertyUnitTests

assertThat(property.findAnnotation(RevisedAnnnotationWithAliasFor.class)).satisfies(annotation -> { - assertThat(annotation.name()).isEqualTo("my-value"); - assertThat(annotation.value()).isEqualTo("my-value"); - })); + assertThat(annotation.name()).isEqualTo("my-value"); + assertThat(annotation.value()).isEqualTo("my-value"); + })); + } + + @Test // DATACMNS-1141 + public void getRequiredAnnotationReturnsAnnotation() { + + PersistentProperty property = getProperty(Sample.class, "id"); + + assertThat(property.getRequiredAnnotation(Id.class)).isNotNull(); + } + + @Test // DATACMNS-1141 + public void getRequiredAnnotationThrowsException() { + + PersistentProperty property = getProperty(Sample.class, "id"); + + assertThatThrownBy(() -> property.getRequiredAnnotation(Transient.class)).isInstanceOf(IllegalStateException.class); } @SuppressWarnings("unchecked") diff --git a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java index 69ffd9176..cd858cb55 100755 --- a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java @@ -39,6 +39,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.TypeAlias; import org.springframework.data.mapping.Alias; +import org.springframework.data.mapping.Document; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntitySpec; @@ -258,6 +259,23 @@ public class BasicPersistentEntityUnitTests> { assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> entity.addAssociation(null)); } + @Test // DATACMNS-1141 + public void getRequiredAnnotationReturnsAnnotation() { + + PersistentEntity entity = createEntity( + AliasEntityUsingComposedAnnotation.class); + assertThat(entity.getRequiredAnnotation(TypeAlias.class).value()).isEqualTo("bar"); + } + + @Test // DATACMNS-1141 + public void getRequiredAnnotationThrowsException() { + + PersistentEntity entity = createEntity( + AliasEntityUsingComposedAnnotation.class); + + assertThatThrownBy(() -> entity.getRequiredAnnotation(Document.class)).isInstanceOf(IllegalStateException.class); + } + private BasicPersistentEntity createEntity(Class type) { return createEntity(type, null); }