GH-2335 - Remove deprecations introduced until 2.0.
This commit is contained in:
@@ -204,15 +204,6 @@ public abstract class AffordanceModel {
|
||||
*/
|
||||
Stream<PropertyMetadata> stream();
|
||||
|
||||
/**
|
||||
* @deprecated since 1.4, for removal in 1.5. Prefer {@link #stream()} and selecting individual
|
||||
* {@code PropertyMetadata} instances yourself.
|
||||
*/
|
||||
@Deprecated
|
||||
default Optional<PropertyMetadata> getPropertyMetadata(String name) {
|
||||
return stream().filter(it -> it.hasName(name)).findFirst();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default Class<?> getType() {
|
||||
return null;
|
||||
@@ -235,23 +226,6 @@ public abstract class AffordanceModel {
|
||||
: DelegatingInputPayloadMetadata.of(metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@link InputPayloadMetadata} to the given target.
|
||||
*
|
||||
* @param <T>
|
||||
* @param target
|
||||
* @return
|
||||
* @deprecated since 1.3, prefer setting up the model types via
|
||||
* {@link AffordanceModel#createProperties(BiFunction)}.
|
||||
*/
|
||||
@Deprecated
|
||||
default <T extends PropertyMetadataConfigured<T> & Named> T applyTo(T target) {
|
||||
|
||||
return getPropertyMetadata(target.getName()) //
|
||||
.map(it -> target.apply(it)) //
|
||||
.orElse(target);
|
||||
}
|
||||
|
||||
<T extends Named> T customize(T target, Function<PropertyMetadata, T> customizer);
|
||||
|
||||
/**
|
||||
@@ -321,15 +295,6 @@ public abstract class AffordanceModel {
|
||||
return metadata.stream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.AffordanceModel.InputPayloadMetadata#customize(org.springframework.hateoas.AffordanceModel.PropertyMetadataConfigured)
|
||||
*/
|
||||
@Override
|
||||
public <T extends PropertyMetadataConfigured<T> & Named> T applyTo(T target) {
|
||||
return target;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.AffordanceModel.InputPayloadMetadata#customize(org.springframework.hateoas.AffordanceModel.Named, java.util.function.Function)
|
||||
|
||||
@@ -95,18 +95,29 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
* Static helper to fashion {@link VariableType#PATH_VARIABLE} variables.
|
||||
*
|
||||
* @param variable must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable pathVariable(String variable) {
|
||||
return new TemplateVariable(variable, VariableType.PATH_VARIABLE);
|
||||
return new TemplateVariable(variable, VariableType.SIMPLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of {@link #pathVariable(String)}.
|
||||
*
|
||||
* @param variable must not be {@literal null} or empty.
|
||||
* @return will never be {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static TemplateVariable simple(String variable) {
|
||||
return new TemplateVariable(variable, VariableType.SIMPLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper to fashion {@link VariableType#REQUEST_PARAM} variables.
|
||||
*
|
||||
* @param parameter must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable requestParameter(String parameter) {
|
||||
@@ -117,7 +128,7 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
* Static helper to fashion {@link VariableType#REQUEST_PARAM_CONTINUED} variables.
|
||||
*
|
||||
* @param parameter must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable requestParameterContinued(String parameter) {
|
||||
@@ -128,41 +139,35 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
* Static helper to fashion {@link VariableType#SEGMENT} variables.
|
||||
*
|
||||
* @param segment must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable segment(String segment) {
|
||||
return new TemplateVariable(segment, VariableType.SEGMENT);
|
||||
return new TemplateVariable(segment, VariableType.PATH_SEGMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper to fashion {@link VariableType#FRAGMENT} variables.
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable fragment(String name) {
|
||||
return new TemplateVariable(name, VariableType.FRAGMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper to fashion {@link VariableType#RESERVED_STRING} variables.
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @return will never be {@literal null}.
|
||||
* @since 1.1
|
||||
*/
|
||||
public static TemplateVariable reservedString(String name) {
|
||||
return new TemplateVariable(name, VariableType.RESERVED_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper to fashion {@link VariableType#COMPOSITE_PARAM} variables.
|
||||
*
|
||||
* @param parameter must not be {@literal null} or empty.
|
||||
* @return
|
||||
* @since 1.1
|
||||
* @deprecated since 1.4, use actual parameter type and call {@link #composite()} on the instance instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static TemplateVariable compositeParameter(String parameter) {
|
||||
return new TemplateVariable(parameter, VariableType.COMPOSITE_PARAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the current template variable as composite value.
|
||||
*
|
||||
@@ -220,18 +225,6 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
return StringUtils.hasText(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the template variable is optional, which means the template can be expanded to a URI without a
|
||||
* value given for that variable.
|
||||
*
|
||||
* @return
|
||||
* @deprecated since 1.4. No replacement as template variables are never required actually.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isRequired() {
|
||||
return !type.isOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link TemplateVariable} is of the same type as the current one.
|
||||
*
|
||||
@@ -285,7 +278,6 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
}
|
||||
|
||||
public String asString() {
|
||||
|
||||
return "{" + type.toString() + essence() + "}";
|
||||
}
|
||||
|
||||
@@ -474,32 +466,13 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
public enum VariableType {
|
||||
|
||||
SIMPLE("", ",", false), //
|
||||
|
||||
/**
|
||||
* @deprecated since 1.4, use {@link #SIMPLE} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
PATH_VARIABLE("", ",", true), //
|
||||
RESERVED_STRING("+", ",", true), //
|
||||
DOT(".", ".", true), //
|
||||
REQUEST_PARAM("?", "&", true), //
|
||||
REQUEST_PARAM_CONTINUED("&", "&", true), //
|
||||
|
||||
PATH_SEGMENT("/", "/", true), //
|
||||
|
||||
/**
|
||||
* @deprecated since 1.4, use {@link #PATH_SEGMENT} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
SEGMENT("/", "/", true), //
|
||||
PATH_STYLE_PARAMETER(";", ";", true), //
|
||||
FRAGMENT("#", ",", true), //
|
||||
|
||||
/**
|
||||
* @deprecated since 1.4. Use the actual type and call {@link TemplateVariable#composite()}.
|
||||
*/
|
||||
@Deprecated
|
||||
COMPOSITE_PARAM("*", "", true);
|
||||
FRAGMENT("#", ",", true);
|
||||
|
||||
private static final EnumSet<VariableType> COMBINABLE_TYPES = EnumSet.of(REQUEST_PARAM, REQUEST_PARAM_CONTINUED);
|
||||
static final String DEFAULT_SEPARATOR = ",";
|
||||
@@ -518,7 +491,6 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
|
||||
|
||||
switch (this) {
|
||||
case DOT:
|
||||
case SEGMENT:
|
||||
case PATH_SEGMENT:
|
||||
case PATH_STYLE_PARAMETER:
|
||||
case REQUEST_PARAM:
|
||||
|
||||
@@ -114,16 +114,6 @@ public @interface EnableHypermediaSupport {
|
||||
return this.mediaTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.5, in favor of {@link #getMediaTypes()} as a logical media type might have been associated
|
||||
* with multiple media type identifiers (see {@link #HAL}).
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
@Deprecated(since = "2.5", forRemoval = true)
|
||||
public MediaType getMediaType() {
|
||||
return this.mediaTypes.get(0);
|
||||
}
|
||||
|
||||
public String getLocalPackageName() {
|
||||
return localPackageName;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
* @author Greg Turnquist
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
public class AnnotationMappingDiscoverer implements MappingDiscoverer {
|
||||
public class AnnotationMappingDiscoverer implements MappingDiscoverer, RawMappingDiscoverer {
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
private final @Nullable String mappingAttributeName;
|
||||
@@ -73,50 +73,59 @@ public class AnnotationMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMapping(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
|
||||
String[] mapping = getMappingFrom(findMergedAnnotation(type, annotationType));
|
||||
|
||||
return mapping.length == 0 ? null : mapping[0];
|
||||
public UriMapping getUriMapping(Class<?> type) {
|
||||
return UriMapping.of(getMapping(type));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.reflect.Method)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMapping(Method method) {
|
||||
public UriMapping getUriMapping(Method method) {
|
||||
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
return getMapping(method.getDeclaringClass(), method);
|
||||
|
||||
return getUriMapping(method.getDeclaringClass(), method);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMapping(Class<?> type, Method method) {
|
||||
public UriMapping getUriMapping(Class<?> type, Method method) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
var mapping = getMapping(type, method);
|
||||
|
||||
String[] mapping = getMappingFrom(findMergedAnnotation(method, annotationType));
|
||||
return mapping == null ? null : UriMapping.of(cleanup(mapping));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.server.core.RawMappingDiscoverer#getMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
*/
|
||||
@Override
|
||||
public @Nullable String getMapping(@Nullable Class<?> type, @Nullable Method method) {
|
||||
|
||||
String[] mapping = method == null ? new String[0] : getMappingFrom(findMergedAnnotation(method, annotationType));
|
||||
String typeMapping = getMapping(type);
|
||||
|
||||
if (mapping.length == 0) {
|
||||
return typeMapping;
|
||||
}
|
||||
|
||||
return cleanup(typeMapping == null || "/".equals(typeMapping) ? mapping[0] : join(typeMapping, mapping[0]));
|
||||
var result = typeMapping == null || "/".equals(typeMapping)
|
||||
? mapping[0]
|
||||
: join(typeMapping, mapping[0]);
|
||||
|
||||
return cleanup(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,6 +188,17 @@ public class AnnotationMappingDiscoverer implements MappingDiscoverer {
|
||||
return params == null ? new String[0] : params;
|
||||
}
|
||||
|
||||
private @Nullable String getMapping(@Nullable Class<?> type) {
|
||||
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] mapping = getMappingFrom(findMergedAnnotation(type, annotationType));
|
||||
|
||||
return mapping.length == 0 ? null : mapping[0];
|
||||
}
|
||||
|
||||
private String[] getMappingFrom(@Nullable Annotation annotation) {
|
||||
|
||||
if (annotation == null) {
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class CachingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
private static final Map<String, String> MAPPINGS = new ConcurrentReferenceHashMap<>();
|
||||
private static final Map<String, UriMapping> MAPPINGS = new ConcurrentReferenceHashMap<>();
|
||||
private static final Map<String, Collection<HttpMethod>> METHODS = new ConcurrentReferenceHashMap<>();
|
||||
private static final Map<String, String[]> PARAMS = new ConcurrentReferenceHashMap<>();
|
||||
private static final Map<String, List<MediaType>> CONSUMES = new ConcurrentReferenceHashMap<>();
|
||||
@@ -52,38 +52,38 @@ public class CachingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Class<?> type) {
|
||||
public UriMapping getUriMapping(Class<?> type) {
|
||||
|
||||
String key = key(type, null);
|
||||
|
||||
return MAPPINGS.computeIfAbsent(key, __ -> delegate.getMapping(type));
|
||||
return MAPPINGS.computeIfAbsent(key, __ -> delegate.getUriMapping(type));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.reflect.Method)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Method method) {
|
||||
return MAPPINGS.computeIfAbsent(key(method), __ -> delegate.getMapping(method));
|
||||
public UriMapping getUriMapping(Method method) {
|
||||
return MAPPINGS.computeIfAbsent(key(method), __ -> delegate.getUriMapping(method));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Class<?> type, Method method) {
|
||||
public UriMapping getUriMapping(Class<?> type, Method method) {
|
||||
|
||||
String key = key(type, method);
|
||||
|
||||
return MAPPINGS.computeIfAbsent(key, __ -> delegate.getMapping(type, method));
|
||||
return MAPPINGS.computeIfAbsent(key, __ -> delegate.getUriMapping(type, method));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -33,17 +33,6 @@ import org.springframework.http.MediaType;
|
||||
*/
|
||||
public interface MappingDiscoverer {
|
||||
|
||||
/**
|
||||
* Returns the mapping associated with the given type.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the type-level mapping or {@literal null} in case none is present.
|
||||
* @deprecated since 2.0, prefer {@link #getUriMapping(Class)}
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
String getMapping(Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns the mapping associated with the given type.
|
||||
*
|
||||
@@ -52,20 +41,7 @@ public interface MappingDiscoverer {
|
||||
* @since 2.0
|
||||
*/
|
||||
@Nullable
|
||||
default UriMapping getUriMapping(Class<?> type) {
|
||||
return UriMapping.of(getMapping(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapping associated with the given {@link Method}. This will include the type-level mapping.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @return the method mapping including the type-level one or {@literal null} if neither of them present.
|
||||
* @deprecated since 2.0, use {@link #getUriMapping(Method)} instead
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
String getMapping(Method method);
|
||||
UriMapping getUriMapping(Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns the mapping associated with the given {@link Method}. This will include the type-level mapping.
|
||||
@@ -75,22 +51,7 @@ public interface MappingDiscoverer {
|
||||
* @since 2.0
|
||||
*/
|
||||
@Nullable
|
||||
default UriMapping getUriMapping(Method method) {
|
||||
return UriMapping.of(getMapping(method));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapping for the given {@link Method} invoked on the given type. This can be used to calculate the
|
||||
* mapping for a super type method being invoked on a sub-type with a type mapping.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param method must not be {@literal null}.
|
||||
* @return the method mapping including the type-level one or {@literal null} if neither of them present.
|
||||
* @deprecated since 2.0, use {@link #getUriMapping(Class, Method)} instead
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
String getMapping(Class<?> type, Method method);
|
||||
UriMapping getUriMapping(Method method);
|
||||
|
||||
/**
|
||||
* Returns the mapping for the given {@link Method} invoked on the given type. This can be used to calculate the
|
||||
@@ -102,9 +63,7 @@ public interface MappingDiscoverer {
|
||||
* @since 2.0
|
||||
*/
|
||||
@Nullable
|
||||
default UriMapping getUriMapping(Class<?> type, Method method) {
|
||||
return UriMapping.of(getMapping(type, method));
|
||||
}
|
||||
UriMapping getUriMapping(Class<?> type, Method method);
|
||||
|
||||
/**
|
||||
* Returns the HTTP verbs for the given {@link Method} invoked on the given type. This can be used to build hypermedia
|
||||
|
||||
@@ -35,9 +35,9 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
*/
|
||||
class PropertyResolvingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
private final MappingDiscoverer delegate;
|
||||
private final RawMappingDiscoverer delegate;
|
||||
|
||||
PropertyResolvingMappingDiscoverer(MappingDiscoverer delegate) {
|
||||
PropertyResolvingMappingDiscoverer(RawMappingDiscoverer delegate) {
|
||||
|
||||
Assert.notNull(delegate, "Delegate MappingDiscoverer must not be null!");
|
||||
|
||||
@@ -46,32 +46,41 @@ class PropertyResolvingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Class<?> type) {
|
||||
return resolveProperties(delegate.getMapping(type));
|
||||
public UriMapping getUriMapping(Class<?> type) {
|
||||
|
||||
var mapping = delegate.getMapping(type, null);
|
||||
|
||||
return mapping == null ? null : UriMapping.of(resolveProperties(mapping));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.reflect.Method)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Method method) {
|
||||
return resolveProperties(delegate.getMapping(method));
|
||||
public UriMapping getUriMapping(Method method) {
|
||||
|
||||
var mapping = delegate.getMapping(method.getDeclaringClass(), method);
|
||||
|
||||
return mapping == null ? null : UriMapping.of(resolveProperties(mapping));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.core.MappingDiscoverer#getMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
* @see org.springframework.hateoas.server.core.MappingDiscoverer#getUriMapping(java.lang.Class, java.lang.reflect.Method)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMapping(Class<?> type, Method method) {
|
||||
return resolveProperties(delegate.getMapping(type, method));
|
||||
public UriMapping getUriMapping(Class<?> type, Method method) {
|
||||
|
||||
var mapping = delegate.getMapping(type, method);
|
||||
|
||||
return mapping == null ? null : UriMapping.of(resolveProperties(mapping));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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 org.springframework.hateoas.server.core;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An extension of {@link MappingDiscoverer} that allows access to the raw {@link String}-based mapping before turning
|
||||
* it into a {@link UriMapping}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 3.0
|
||||
*/
|
||||
interface RawMappingDiscoverer extends MappingDiscoverer {
|
||||
|
||||
/**
|
||||
* Returns the raw URI mapping associated with the given method of the given class.
|
||||
*
|
||||
* @param type can be {@literal null}.
|
||||
* @param method can be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
String getMapping(@Nullable Class<?> type, @Nullable Method method);
|
||||
}
|
||||
@@ -70,20 +70,6 @@ public class SpringAffordanceBuilder {
|
||||
.apply(Affordances.of(affordanceLink));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapping for the given type's method.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param method must not be {@literal null}.
|
||||
* @return
|
||||
* @deprecated since 2.0, use {@link #getUriMapping(Class, Method)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static String getMapping(Class<?> type, Method method) {
|
||||
return DISCOVERER.getMapping(type, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapping for the given type's method.
|
||||
*
|
||||
|
||||
@@ -17,8 +17,10 @@ package org.springframework.hateoas.server.core;
|
||||
|
||||
import static org.springframework.web.util.UriComponents.UriTemplateVariables.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -95,6 +97,43 @@ public class UriMapping {
|
||||
return this.variables;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return mapping + " " + variables;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof UriMapping that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(this.mapping, that.mapping)
|
||||
&& Objects.equals(this.variables, that.variables);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.mapping, this.variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* All {@link MappingVariable}s contained in a {@link UriTemplate}.
|
||||
*
|
||||
@@ -105,7 +144,14 @@ public class UriMapping {
|
||||
private final List<MappingVariable> variables;
|
||||
|
||||
public MappingVariables(UriTemplate template) {
|
||||
this.variables = template.getVariableNames().stream().map(MappingVariable::of).collect(Collectors.toList());
|
||||
|
||||
this.variables = template.getVariableNames().stream()
|
||||
.map(MappingVariable::of)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private MappingVariables(List<MappingVariable> variables) {
|
||||
this.variables = variables;
|
||||
}
|
||||
|
||||
public boolean hasCapturingVariable() {
|
||||
@@ -129,6 +175,19 @@ public class UriMapping {
|
||||
.orElseThrow(() -> new IllegalArgumentException("No variable named " + name + " found!"));
|
||||
}
|
||||
|
||||
public MappingVariables and(MappingVariables other) {
|
||||
|
||||
List<MappingVariable> result = new ArrayList<>(variables);
|
||||
|
||||
for (MappingVariable variable : other) {
|
||||
if (!result.contains(variable)) {
|
||||
result.add(variable);
|
||||
}
|
||||
}
|
||||
|
||||
return new MappingVariables(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
@@ -137,6 +196,42 @@ public class UriMapping {
|
||||
public Iterator<MappingVariable> iterator() {
|
||||
return variables.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return variables.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof MappingVariables that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(this.variables, that.variables);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(variables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,6 +321,43 @@ public class UriMapping {
|
||||
public Object getAbsentValue() {
|
||||
return composite ? TemplateVariable.segment(name).composite().toString() : SKIP_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + (composite ? "*" : "");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof MappingVariable that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(this.name, that.name)
|
||||
&& this.composite == that.composite;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, composite);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,7 +390,6 @@ public class UriMapping {
|
||||
* @see java.util.function.Function#apply(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("null")
|
||||
public String apply(String source) {
|
||||
|
||||
Matcher matcher = PATH_CAPTURE.matcher(source);
|
||||
|
||||
@@ -84,8 +84,8 @@ public class WebMvcLinkBuilder extends TemplateVariableAwareLinkBuilderSupport<W
|
||||
Assert.notNull(controller, "Controller must not be null!");
|
||||
Assert.notNull(parameters, "Parameters must not be null!");
|
||||
|
||||
var mapping = SpringAffordanceBuilder.DISCOVERER.getMapping(controller);
|
||||
var defaulted = mapping == null ? "/" : mapping;
|
||||
var mapping = SpringAffordanceBuilder.DISCOVERER.getUriMapping(controller);
|
||||
var defaulted = mapping == null ? "/" : mapping.getMapping();
|
||||
|
||||
var uri = URI_FACTORY.expand(defaulted, parameters);
|
||||
var uriComponents = UriComponentsBuilder.fromUri(uri).build();
|
||||
@@ -107,8 +107,8 @@ public class WebMvcLinkBuilder extends TemplateVariableAwareLinkBuilderSupport<W
|
||||
Assert.notNull(controller, "Controller must not be null!");
|
||||
Assert.notNull(parameters, "Parameters must not be null!");
|
||||
|
||||
var mapping = SpringAffordanceBuilder.DISCOVERER.getMapping(controller);
|
||||
var defaulted = mapping == null ? "/" : mapping;
|
||||
var mapping = SpringAffordanceBuilder.DISCOVERER.getUriMapping(controller);
|
||||
var defaulted = mapping == null ? "/" : mapping.getMapping();
|
||||
|
||||
var uri = URI_FACTORY.expand(defaulted, parameters);
|
||||
var uriComponents = UriComponentsBuilder.fromUri(uri).build();
|
||||
|
||||
@@ -332,9 +332,9 @@ class UriTemplateUnitTest {
|
||||
.isEqualTo("/foo{#var}");
|
||||
|
||||
assertThat(UriTemplate.of("/foo") //
|
||||
.with(compositeParameter("var")) //
|
||||
.with(simple("var").composite()) //
|
||||
.toString()) //
|
||||
.isEqualTo("/foo{*var}");
|
||||
.isEqualTo("/foo{var*}");
|
||||
}
|
||||
|
||||
@Test // #227
|
||||
|
||||
@@ -45,32 +45,32 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
|
||||
@Test
|
||||
void discoversTypeLevelMapping() {
|
||||
assertThat(discoverer.getMapping(MyController.class)).isEqualTo("/type");
|
||||
assertThat(discoverer.getUriMapping(MyController.class)).isEqualTo(UriMapping.of("/type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void discoversMethodLevelMapping() throws Exception {
|
||||
Method method = MyController.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type/method");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/type/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsNullForNonExistentTypeLevelMapping() {
|
||||
assertThat(discoverer.getMapping(ControllerWithoutTypeLevelMapping.class)).isNull();
|
||||
assertThat(discoverer.getUriMapping(ControllerWithoutTypeLevelMapping.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesMethodLevelMappingWithoutTypeLevelMapping() throws Exception {
|
||||
|
||||
Method method = ControllerWithoutTypeLevelMapping.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/method");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesMethodLevelMappingWithSlashRootMapping() throws Exception {
|
||||
|
||||
Method method = SlashRootMapping.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/method");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/method"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +80,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
void treatsMissingMethodMappingAsEmptyMapping() throws Exception {
|
||||
|
||||
Method method = MyController.class.getMethod("noMethodMapping");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/type"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
void detectsClassMappingOnSuperType() throws Exception {
|
||||
|
||||
Method method = ChildController.class.getMethod("mapping");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/parent/child");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/parent/child"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
void includesTypeMappingFromChildClass() throws Exception {
|
||||
|
||||
Method method = ParentWithMethod.class.getMethod("mapping");
|
||||
assertThat(discoverer.getMapping(ChildWithTypeMapping.class, method)).isEqualTo("/child/parent");
|
||||
assertThat(discoverer.getUriMapping(ChildWithTypeMapping.class, method)).isEqualTo(UriMapping.of("/child/parent"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,16 +110,16 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
void handlesSlashes() throws Exception {
|
||||
|
||||
Method method = ControllerWithoutSlashes.class.getMethod("noslash");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("slashes/noslash");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("slashes/noslash"));
|
||||
|
||||
method = ControllerWithoutSlashes.class.getMethod("withslash");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("slashes/withslash");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("slashes/withslash"));
|
||||
|
||||
method = ControllerWithTrailingSlashes.class.getMethod("noslash");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("trailing/noslash");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("trailing/noslash"));
|
||||
|
||||
method = ControllerWithTrailingSlashes.class.getMethod("withslash");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("trailing/withslash");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("trailing/withslash"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +130,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
|
||||
Method method = ControllerWithMultipleSlashes.class.getMethod("withslash");
|
||||
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("trailing/withslash");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("trailing/withslash"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,7 +141,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
|
||||
Method method = MultipleMappingsController.class.getMethod("method");
|
||||
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type/method");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/type/method"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,14 +151,14 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
void discoversMethodLevelMappingUsingComposedAnnotation() throws Exception {
|
||||
|
||||
Method method = MyController.class.getMethod("methodWithComposedAnnotation");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type/otherMethod");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/type/otherMethod"));
|
||||
}
|
||||
|
||||
@Test // #1412
|
||||
void removesMatchingExpressionFromTemplateVariable() throws Exception {
|
||||
|
||||
Method method = MyController.class.getMethod("mappingWithMatchingExpression");
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type/foo/{bar}");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/type/foo/{bar}"));
|
||||
}
|
||||
|
||||
@Test // #1442
|
||||
@@ -176,7 +176,8 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
|
||||
Method method = MyController.class.getMethod("multipleRegularExpressions");
|
||||
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/type/spring-web/{symbolicName}-{version}{extension}");
|
||||
assertThat(discoverer.getUriMapping(method))
|
||||
.isEqualTo(UriMapping.of("/type/spring-web/{symbolicName}-{version}{extension}"));
|
||||
}
|
||||
|
||||
@Test // #1468
|
||||
@@ -184,7 +185,7 @@ class AnnotationMappingDiscovererUnitTest {
|
||||
|
||||
Method method = TrailingSlashes.class.getMethod("trailingSlash");
|
||||
|
||||
assertThat(discoverer.getMapping(method)).isEqualTo("/api/myentities/");
|
||||
assertThat(discoverer.getUriMapping(method)).isEqualTo(UriMapping.of("/api/myentities/"));
|
||||
}
|
||||
|
||||
@RequestMapping("/type")
|
||||
|
||||
@@ -58,18 +58,20 @@ class PropertyResolvingMappingDiscovererUnitTest extends TestUtils {
|
||||
AnnotationMappingDiscoverer annotationMappingDiscoverer = new AnnotationMappingDiscoverer(RequestMapping.class);
|
||||
|
||||
// Test plain AnnotationMappingDiscoverer first
|
||||
assertThat(annotationMappingDiscoverer.getMapping(ResolveEndpointController.class)).isEqualTo("/${test.parent}");
|
||||
assertThat(annotationMappingDiscoverer.getMapping(ResolveMethodEndpointController.class, method))
|
||||
.isEqualTo("/${test.parent}/${test.child}");
|
||||
assertThat(annotationMappingDiscoverer.getUriMapping(ResolveEndpointController.class))
|
||||
.isEqualTo(UriMapping.of("/${test.parent}"));
|
||||
assertThat(annotationMappingDiscoverer.getUriMapping(ResolveMethodEndpointController.class, method))
|
||||
.isEqualTo(UriMapping.of("/${test.parent}/${test.child}"));
|
||||
|
||||
PropertyResolvingMappingDiscoverer propertyResolvingMappingDiscoverer = new PropertyResolvingMappingDiscoverer(
|
||||
annotationMappingDiscoverer);
|
||||
|
||||
assertThat(propertyResolvingMappingDiscoverer.getMapping(ResolveEndpointController.class))
|
||||
.isEqualTo("/resolvedparent");
|
||||
assertThat(propertyResolvingMappingDiscoverer.getMapping(method)).isEqualTo("/resolvedparent/resolvedchild");
|
||||
assertThat(propertyResolvingMappingDiscoverer.getMapping(ResolveMethodEndpointController.class, method))
|
||||
.isEqualTo("/resolvedparent/resolvedchild");
|
||||
assertThat(propertyResolvingMappingDiscoverer.getUriMapping(ResolveEndpointController.class))
|
||||
.isEqualTo(UriMapping.of("/resolvedparent"));
|
||||
assertThat(propertyResolvingMappingDiscoverer.getUriMapping(method))
|
||||
.isEqualTo(UriMapping.of("/resolvedparent/resolvedchild"));
|
||||
assertThat(propertyResolvingMappingDiscoverer.getUriMapping(ResolveMethodEndpointController.class, method))
|
||||
.isEqualTo(UriMapping.of("/resolvedparent/resolvedchild"));
|
||||
}
|
||||
|
||||
@RequestMapping("/${test.parent}")
|
||||
|
||||
@@ -34,7 +34,6 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.Named;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
Reference in New Issue
Block a user