diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java index e34270572..f4eb5158e 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java @@ -22,6 +22,8 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.rest.core.Path; import org.springframework.data.rest.core.annotation.Description; import org.springframework.data.rest.core.annotation.RestResource; +import org.springframework.data.util.Lazy; +import org.springframework.data.util.Optionals; import org.springframework.hateoas.LinkRelation; import org.springframework.hateoas.server.LinkRelationProvider; import org.springframework.hateoas.server.core.EvoInflectorLinkRelationProvider; @@ -38,8 +40,11 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { private final Class type; private final LinkRelationProvider relProvider; - private final RestResource annotation; - private final Description description; + private final Optional annotation; + + private final Lazy path; + private final Lazy rel; + private final Lazy description, itemResourceDescription; /** * Creates a new {@link TypeBasedCollectionResourceMapping} using the given type. @@ -63,8 +68,45 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { this.type = type; this.relProvider = relProvider; - this.annotation = AnnotationUtils.findAnnotation(type, RestResource.class); - this.description = AnnotationUtils.findAnnotation(type, Description.class); + this.annotation = Optional.ofNullable(AnnotationUtils.findAnnotation(type, RestResource.class)); + + this.path = Lazy.of(() -> annotation.map(RestResource::path) // + .map(String::trim) // + .filter(StringUtils::hasText) // + .orElseGet(() -> getDefaultPathFor(type)))// + .map(Path::new); + + this.rel = Lazy.of(() -> annotation // + .map(RestResource::rel) // + .filter(StringUtils::hasText) // + .map(LinkRelation::of) // + .orElseGet(() -> relProvider.getCollectionResourceRelFor(type))); + + Optional descriptionAnnotation = Optional + .ofNullable(AnnotationUtils.findAnnotation(type, Description.class)); + + this.description = Lazy.of(() -> { + + ResourceDescription fallback = SimpleResourceDescription.defaultFor(getRel()); + + return Optionals. firstNonEmpty(// + () -> descriptionAnnotation.map(it -> new AnnotationBasedResourceDescription(it, fallback)), // + () -> annotation.map(RestResource::description) + .map(it -> new AnnotationBasedResourceDescription(it, fallback))) // + .orElse(fallback); + }); + + this.itemResourceDescription = Lazy.of(() -> { + + ResourceDescription fallback = SimpleResourceDescription.defaultFor(getItemResourceRel()); + + return Optionals. firstNonEmpty(// + () -> annotation.map(RestResource::description) // + .filter(it -> StringUtils.hasText(it.value())) // + .map(it -> new AnnotationBasedResourceDescription(it, fallback)), // + () -> descriptionAnnotation.map(it -> new AnnotationBasedResourceDescription(it, fallback))) // + .orElse(fallback); + }); } /* @@ -73,10 +115,7 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public Path getPath() { - - String path = annotation == null ? null : annotation.path().trim(); - path = StringUtils.hasText(path) ? path : getDefaultPathFor(type); - return new Path(path); + return path.get(); } /* @@ -85,7 +124,10 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public boolean isExported() { - return annotation != null ? annotation.exported() : Modifier.isPublic(type.getModifiers()); + + return annotation // + .map(RestResource::exported) // + .orElseGet(() -> Modifier.isPublic(type.getModifiers())); } /* @@ -94,12 +136,7 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public LinkRelation getRel() { - - if (annotation == null || !StringUtils.hasText(annotation.rel())) { - return relProvider.getCollectionResourceRelFor(type); - } - - return LinkRelation.of(annotation.rel()); + return rel.get(); } /* @@ -126,18 +163,7 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public ResourceDescription getDescription() { - - ResourceDescription fallback = SimpleResourceDescription.defaultFor(getRel()); - - if (description != null) { - return new AnnotationBasedResourceDescription(description, fallback); - } - - if (annotation != null) { - return new AnnotationBasedResourceDescription(annotation.description(), fallback); - } - - return fallback; + return description.get(); } /* @@ -146,18 +172,7 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public ResourceDescription getItemResourceDescription() { - - ResourceDescription fallback = SimpleResourceDescription.defaultFor(getItemResourceRel()); - - if (annotation != null && StringUtils.hasText(annotation.description().value())) { - return new AnnotationBasedResourceDescription(annotation.description(), fallback); - } - - if (description != null) { - return new AnnotationBasedResourceDescription(description, fallback); - } - - return fallback; + return itemResourceDescription.get(); } /*