DATAREST-93 - Fixed formatting in Spring Data REST.
Added formatter to be used within Eclipse going forward.
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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.data.rest.convert;
|
||||
|
||||
import java.util.Stack;
|
||||
@@ -5,89 +20,91 @@ import java.util.Stack;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* This {@link ConversionService} implementation delegates the actual conversion to the {@literal ConversionService} it
|
||||
* finds in its internal {@link Stack} that claims to be able to convert a given class. It will roll through the
|
||||
* {@literal ConversionService}s until it finds one that can convert the given type.
|
||||
*
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @authot Oliver Gierke
|
||||
*/
|
||||
public class DelegatingConversionService implements ConversionService {
|
||||
|
||||
private Stack<ConversionService> conversionServices = new Stack<ConversionService>();
|
||||
private final Stack<ConversionService> conversionServices;
|
||||
|
||||
public DelegatingConversionService() {
|
||||
}
|
||||
public DelegatingConversionService(ConversionService... svcs) {
|
||||
|
||||
public DelegatingConversionService(ConversionService... svcs) {
|
||||
addConversionServices(svcs);
|
||||
}
|
||||
this.conversionServices = new Stack<ConversionService>();
|
||||
|
||||
/**
|
||||
* Add {@link ConversionService}s to the internal list of those to delegate to.
|
||||
*
|
||||
* @param svcs
|
||||
* The ConversionServices to delegate to (in order).
|
||||
*
|
||||
* @return @this
|
||||
*/
|
||||
public DelegatingConversionService addConversionServices(ConversionService... svcs) {
|
||||
for(ConversionService svc : svcs) {
|
||||
conversionServices.add(svc);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
for (ConversionService svc : svcs) {
|
||||
Assert.notNull(svc);
|
||||
conversionServices.add(svc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ConversionService} to the internal list at a specific index for controlling the priority.
|
||||
*
|
||||
* @param atIndex
|
||||
* Where in the stack to add this ConversionService.
|
||||
* @param svc
|
||||
* The ConversionService to add.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DelegatingConversionService addConversionService(int atIndex, ConversionService svc) {
|
||||
conversionServices.add(atIndex, svc);
|
||||
return this;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.ConversionService#canConvert(java.lang.Class, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public boolean canConvert(Class<?> from, Class<?> to) {
|
||||
|
||||
@Override public boolean canConvert(Class<?> from, Class<?> to) {
|
||||
for(ConversionService svc : conversionServices) {
|
||||
if(svc.canConvert(from, to)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (ConversionService svc : conversionServices) {
|
||||
if (svc.canConvert(from, to)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean canConvert(TypeDescriptor from, TypeDescriptor to) {
|
||||
for(ConversionService svc : conversionServices) {
|
||||
if(svc.canConvert(from, to)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public <T> T convert(Object o, Class<T> type) {
|
||||
for(ConversionService svc : conversionServices) {
|
||||
if(svc.canConvert(o.getClass(), type)) {
|
||||
return svc.convert(o, type);
|
||||
}
|
||||
}
|
||||
throw new ConverterNotFoundException(TypeDescriptor.forObject(o), TypeDescriptor.valueOf(type));
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.ConversionService#canConvert(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public boolean canConvert(TypeDescriptor from, TypeDescriptor to) {
|
||||
|
||||
@Override public Object convert(Object o, TypeDescriptor from, TypeDescriptor to) {
|
||||
for(ConversionService svc : conversionServices) {
|
||||
if(svc.canConvert(from, to)) {
|
||||
return svc.convert(o, from, to);
|
||||
}
|
||||
}
|
||||
throw new ConverterNotFoundException(from, to);
|
||||
}
|
||||
for (ConversionService svc : conversionServices) {
|
||||
if (svc.canConvert(from, to)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.ConversionService#convert(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> T convert(Object o, Class<T> type) {
|
||||
|
||||
for (ConversionService svc : conversionServices) {
|
||||
if (svc.canConvert(o.getClass(), type)) {
|
||||
return svc.convert(o, type);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ConverterNotFoundException(TypeDescriptor.forObject(o), TypeDescriptor.valueOf(type));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.ConversionService#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object o, TypeDescriptor from, TypeDescriptor to) {
|
||||
|
||||
for (ConversionService svc : conversionServices) {
|
||||
if (svc.canConvert(from, to)) {
|
||||
return svc.convert(o, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ConverterNotFoundException(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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.data.rest.convert;
|
||||
|
||||
import java.text.DateFormat;
|
||||
@@ -15,62 +30,81 @@ import org.springframework.core.convert.converter.Converter;
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class ISO8601DateConverter implements ConditionalGenericConverter,
|
||||
Converter<String[], Date> {
|
||||
public class ISO8601DateConverter implements ConditionalGenericConverter, Converter<String[], Date> {
|
||||
|
||||
public static final ConditionalGenericConverter INSTANCE = new ISO8601DateConverter();
|
||||
public static final ConditionalGenericConverter INSTANCE = new ISO8601DateConverter();
|
||||
|
||||
private static final Set<ConvertiblePair> CONVERTIBLE_PAIRS = new HashSet<ConvertiblePair>();
|
||||
private static final Set<ConvertiblePair> CONVERTIBLE_PAIRS = new HashSet<ConvertiblePair>();
|
||||
|
||||
static {
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(String.class, Date.class));
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(Date.class, String.class));
|
||||
}
|
||||
static {
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(String.class, Date.class));
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(Date.class, String.class));
|
||||
}
|
||||
|
||||
@Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if(String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return Date.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
return Date.class.isAssignableFrom(sourceType.getType())
|
||||
&& String.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
if (String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return Date.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
|
||||
@Override public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return CONVERTIBLE_PAIRS;
|
||||
}
|
||||
return Date.class.isAssignableFrom(sourceType.getType()) && String.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
|
||||
@Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
DateFormat dateFmt = iso8601DateFormat();
|
||||
if(String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return dateFmt.format(source);
|
||||
} else {
|
||||
try {
|
||||
return dateFmt.parse(source.toString());
|
||||
} catch(ParseException e) {
|
||||
throw new ConversionFailedException(sourceType, targetType, source, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes()
|
||||
*/
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return CONVERTIBLE_PAIRS;
|
||||
}
|
||||
|
||||
@Override public Date convert(String[] source) {
|
||||
if(source.length > 0) {
|
||||
try {
|
||||
return iso8601DateFormat().parse(source[0]);
|
||||
} catch(ParseException e) {
|
||||
throw new ConversionFailedException(
|
||||
TypeDescriptor.valueOf(String[].class),
|
||||
TypeDescriptor.valueOf(Date.class),
|
||||
source[0],
|
||||
new IllegalArgumentException("Source does not conform to ISO8601 date format (YYYY-MM-DDTHH:MM:SS-0000")
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
private DateFormat iso8601DateFormat() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
}
|
||||
DateFormat dateFmt = iso8601DateFormat();
|
||||
|
||||
if (String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return dateFmt.format(source);
|
||||
}
|
||||
|
||||
try {
|
||||
return dateFmt.parse(source.toString());
|
||||
} catch (ParseException e) {
|
||||
throw new ConversionFailedException(sourceType, targetType, source, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Date convert(String[] source) {
|
||||
|
||||
if (source.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return iso8601DateFormat().parse(source[0]);
|
||||
} catch (ParseException e) {
|
||||
throw new ConversionFailedException(TypeDescriptor.valueOf(String[].class), TypeDescriptor.valueOf(Date.class),
|
||||
source[0], new IllegalArgumentException(
|
||||
"Source does not conform to ISO8601 date format (YYYY-MM-DDTHH:MM:SS-0000"));
|
||||
}
|
||||
}
|
||||
|
||||
private DateFormat iso8601DateFormat() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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.data.rest.convert;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -9,38 +24,51 @@ import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
||||
/**
|
||||
* For converting a {@link UUID} into a {@link String}.
|
||||
*
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class UUIDConverter implements ConditionalGenericConverter {
|
||||
|
||||
public static final UUIDConverter INSTANCE = new UUIDConverter();
|
||||
private static final Set<ConvertiblePair> CONVERTIBLE_PAIRS = new HashSet<ConvertiblePair>();
|
||||
public static final UUIDConverter INSTANCE = new UUIDConverter();
|
||||
private static final Set<ConvertiblePair> CONVERTIBLE_PAIRS = new HashSet<ConvertiblePair>();
|
||||
|
||||
static {
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(String.class, UUID.class));
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(UUID.class, String.class));
|
||||
}
|
||||
static {
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(String.class, UUID.class));
|
||||
CONVERTIBLE_PAIRS.add(new ConvertiblePair(UUID.class, String.class));
|
||||
}
|
||||
|
||||
@Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if(String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return UUID.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return UUID.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
|
||||
return UUID.class.isAssignableFrom(sourceType.getType())
|
||||
&& String.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
return UUID.class.isAssignableFrom(sourceType.getType()) && String.class.isAssignableFrom(targetType.getType());
|
||||
}
|
||||
|
||||
@Override public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return CONVERTIBLE_PAIRS;
|
||||
}
|
||||
|
||||
@Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if(String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return UUID.fromString(source.toString());
|
||||
} else {
|
||||
return source.toString();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes()
|
||||
*/
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return CONVERTIBLE_PAIRS;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (String.class.isAssignableFrom(sourceType.getType())) {
|
||||
return UUID.fromString(source.toString());
|
||||
} else {
|
||||
return source.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* {@link org.springframework.core.convert.ConversionService} and {@link org.springframework.core.convert.converter.Converter} integration for Spring Data REST.
|
||||
*/
|
||||
package org.springframework.data.rest.convert;
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Core components used across Spring Data REST.
|
||||
*/
|
||||
package org.springframework.data.rest.core;
|
||||
|
||||
|
||||
@@ -38,14 +38,14 @@ public abstract class MapUtils {
|
||||
* @return
|
||||
*/
|
||||
public static <K, V> Map<K, Collection<V>> toMap(MultiValueMap<K, V> map) {
|
||||
|
||||
|
||||
Assert.notNull(map, "Given map must not be null!");
|
||||
Map<K, Collection<V>> result = new LinkedHashMap<K, Collection<V>>(map.size());
|
||||
|
||||
for (Entry<K, List<V>> entry : map.entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,210 +1,25 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Helper methods for dealing with URIs.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public abstract class UriUtils {
|
||||
|
||||
private UriUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given {@link URI} based on the "base" {@link URI}?
|
||||
* <p>e.g. given a base URI of {@literal http://localhost:8080/data} and a URI of {@code
|
||||
* http://localhost:8080/data/person}, this method would report the baseUri being a valid base of the given URI.
|
||||
* </p>
|
||||
*
|
||||
* @param baseUri
|
||||
* {@link URI} to check.
|
||||
* @param uri
|
||||
* {@link URI} against which to compare the base.
|
||||
*
|
||||
* @return {@literal true} if the baseUri is valid against the given {@link URI}, {@literal false} otherwise.
|
||||
*/
|
||||
public static boolean validBaseUri(URI baseUri, URI uri) {
|
||||
String path = UriUtils.path(baseUri.relativize(uri));
|
||||
return !StringUtils.hasText(path) || path.charAt(0) != '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given {@link Function} for each segment in the {@link URI}.
|
||||
* <p>e.g. given a URI of {@literal http://localhost:8080/data/person/1} and a base URI of {@code
|
||||
* http://localhost:8080/data}, this method will explode the URI into it's components, as compared to the base URI.
|
||||
* The result would be: the given handler gets called twice, once passing a relative {@link URI} of "person" and a
|
||||
* second time passing a relative {@link URI} of "1".
|
||||
* </p>
|
||||
*
|
||||
* @param baseUri
|
||||
* base {@link URI}
|
||||
* @param uri
|
||||
* {@link URI} to explode and iterate over.
|
||||
* @param handler
|
||||
* {@link Function} to call for each segment of the URI's path.
|
||||
* @param <V>
|
||||
* Return type of the handler.
|
||||
*
|
||||
* @return Handler return value, or possibly {@literal null}.
|
||||
*/
|
||||
public static <V> V foreach(URI baseUri, URI uri, Function<URI, V> handler) {
|
||||
List<URI> uris = explode(baseUri, uri);
|
||||
V v = null;
|
||||
for(URI u : uris) {
|
||||
v = handler.apply(u);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the given {@link URI} into its component parts, as compared to the base {@link URI}.
|
||||
* <p>Given a base URI of {@literal http://localhost:8080/data}, exploding the URI {@code
|
||||
* http://localhost:8080/data/person/1} strips the first part of the URI, leaving {@literal person/1}. This results
|
||||
* in
|
||||
* a {@link Stack} of relative {@link URI}s of size 2--one for "person" and one for "1".</p>
|
||||
*
|
||||
* @param baseUri
|
||||
* base {@link URI}
|
||||
* @param uri
|
||||
* {@link URI} to explode
|
||||
*
|
||||
* @return {@link Stack} of relative {@link URI}s.
|
||||
*/
|
||||
public static Stack<URI> explode(URI baseUri, URI uri) {
|
||||
Stack<URI> uris = new Stack<URI>();
|
||||
if(StringUtils.hasText(uri.getPath())) {
|
||||
URI relativeUri = baseUri.relativize(uri);
|
||||
if(StringUtils.hasText(relativeUri.getPath())) {
|
||||
for(String part : relativeUri.getPath().split("/")) {
|
||||
uris.add(URI.create(part + (StringUtils.hasText(uri.getQuery()) ? "?" + uri.getQuery() : "")));
|
||||
}
|
||||
}
|
||||
}
|
||||
return uris;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the components of these {@link URI}s into a single URI. Useful for combining a relative URI with a base URI
|
||||
* and coming up with a full absolute URI.
|
||||
* <p>e.g. merging base URI {@literal http://localhost:8080/data} and relative uri {@literal person/1?name=John+Doe}
|
||||
* would result in an absolute URI of {@literal http://localhost:8080/data/person/1?name=John+Doe}</p>
|
||||
*
|
||||
* @param baseUri
|
||||
* base {@link URI}
|
||||
* @param uris
|
||||
* {@link URI}s to merge
|
||||
*
|
||||
* @return {@link URI} that is the combination of all the given (possibly relative, possibly absolute) URIs.
|
||||
*/
|
||||
public static URI merge(URI baseUri, URI... uris) {
|
||||
StringBuilder query = new StringBuilder();
|
||||
|
||||
UriComponentsBuilder ub = UriComponentsBuilder.fromUri(baseUri);
|
||||
for(URI uri : uris) {
|
||||
String s = uri.getScheme();
|
||||
if(null != s) {
|
||||
ub.scheme(s);
|
||||
}
|
||||
|
||||
s = uri.getUserInfo();
|
||||
if(null != s) {
|
||||
ub.userInfo(s);
|
||||
}
|
||||
|
||||
s = uri.getHost();
|
||||
if(null != s) {
|
||||
ub.host(s);
|
||||
}
|
||||
|
||||
int i = uri.getPort();
|
||||
if(i > 0) {
|
||||
ub.port(i);
|
||||
}
|
||||
|
||||
s = uri.getPath();
|
||||
if(null != s) {
|
||||
if(!uri.isAbsolute() && StringUtils.hasText(s)) {
|
||||
ub.pathSegment(s);
|
||||
} else {
|
||||
ub.path(s);
|
||||
}
|
||||
}
|
||||
|
||||
s = uri.getQuery();
|
||||
if(null != s) {
|
||||
if(query.length() > 0) {
|
||||
query.append("&");
|
||||
}
|
||||
query.append(s);
|
||||
}
|
||||
|
||||
s = uri.getFragment();
|
||||
if(null != s) {
|
||||
ub.fragment(s);
|
||||
}
|
||||
}
|
||||
|
||||
if(query.length() > 0) {
|
||||
ub.query(query.toString());
|
||||
}
|
||||
|
||||
return ub.build().toUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Just the path portion of the {@link URI}, but with any trailing slash "/" removed.
|
||||
*
|
||||
* @param uri
|
||||
* path URI
|
||||
*
|
||||
* @return the path portion of the URI, but with any trailing slash removed
|
||||
*/
|
||||
public static String path(URI uri) {
|
||||
if(null == uri) {
|
||||
return null;
|
||||
}
|
||||
String s = uri.getPath();
|
||||
if(s.endsWith("/")) {
|
||||
return s.substring(0, s.length() - 1);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The very last segment of the {@link URI}.
|
||||
*
|
||||
* @param baseUri
|
||||
* base {@link URI}
|
||||
* @param uri
|
||||
* {@link URI} to explode
|
||||
*
|
||||
* @return Relative {@link URI} that is the last segment of the path for the given URI.
|
||||
*/
|
||||
public static URI tail(URI baseUri, URI uri) {
|
||||
Stack<URI> uris = explode(baseUri, uri);
|
||||
return uris.size() > 0 ? uris.get(Math.max(uris.size() - 1, 0)) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link URI} out of the components.
|
||||
*
|
||||
* @param baseUri
|
||||
* The base URI these path segments are relative to.
|
||||
* @param pathSegments
|
||||
* The path segments to add to the given base URI.
|
||||
*
|
||||
* @return A new URI built from the given base URI and additional path segments.
|
||||
*/
|
||||
public static URI buildUri(URI baseUri, String... pathSegments) {
|
||||
return UriComponentsBuilder.fromUri(baseUri).pathSegment(pathSegments).build().toUri();
|
||||
}
|
||||
/**
|
||||
* Create a new {@link URI} out of the components.
|
||||
*
|
||||
* @param baseUri The base URI these path segments are relative to.
|
||||
* @param pathSegments The path segments to add to the given base URI.
|
||||
* @return A new URI built from the given base URI and additional path segments.
|
||||
*/
|
||||
public static URI buildUri(URI baseUri, String... pathSegments) {
|
||||
return UriComponentsBuilder.fromUri(baseUri).pathSegment(pathSegments).build().toUri();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Spring Data REST
|
||||
*/
|
||||
package org.springframework.data.rest;
|
||||
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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.data.rest.convert;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -16,48 +32,53 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
|
||||
/**
|
||||
* Tests to ensure the {@link DelegatingConversionService} properly delegates conversions to the {@link
|
||||
* org.springframework.core.convert.ConversionService} that is appropriate for the given source and return types.
|
||||
*
|
||||
* Tests to ensure the {@link DelegatingConversionService} properly delegates conversions to the
|
||||
* {@link org.springframework.core.convert.ConversionService} that is appropriate for the given source and return types.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DelegatingConversionServiceUnitTests {
|
||||
|
||||
private static final UUID RANDOM_UUID = UUID.fromString("9deccfd7-f892-4e26-a4d5-c92893392e78");
|
||||
private static final UUID RANDOM_UUID = UUID.fromString("9deccfd7-f892-4e26-a4d5-c92893392e78");
|
||||
|
||||
@Mock ConversionService conversionService;
|
||||
DelegatingConversionService delegatingConversionService;
|
||||
@Mock ConversionService conversionService;
|
||||
DelegatingConversionService delegatingConversionService;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
DefaultFormattingConversionService cs = new DefaultFormattingConversionService(false);
|
||||
cs.addConverter(UUIDConverter.INSTANCE);
|
||||
DefaultFormattingConversionService cs = new DefaultFormattingConversionService(false);
|
||||
cs.addConverter(UUIDConverter.INSTANCE);
|
||||
|
||||
delegatingConversionService = new DelegatingConversionService(conversionService, cs);
|
||||
|
||||
when(conversionService.canConvert(String.class, UUID.class)).thenReturn(false);
|
||||
when(conversionService.canConvert(UUID.class, String.class)).thenReturn(false);
|
||||
}
|
||||
delegatingConversionService = new DelegatingConversionService(conversionService, cs);
|
||||
|
||||
@Test
|
||||
public void shouldDelegateToProperConversionService() throws Exception {
|
||||
assertThat(delegatingConversionService.canConvert(String.class, UUID.class), is(true));
|
||||
assertThat(delegatingConversionService.convert(RANDOM_UUID.toString(), UUID.class), is(RANDOM_UUID));
|
||||
verifyConversionService();
|
||||
}
|
||||
when(conversionService.canConvert(String.class, UUID.class)).thenReturn(false);
|
||||
when(conversionService.canConvert(UUID.class, String.class)).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldConvertUUIDToString() throws Exception {
|
||||
assertThat(delegatingConversionService.canConvert(UUID.class, String.class), is(true));
|
||||
assertThat(delegatingConversionService.convert(RANDOM_UUID, String.class), is(RANDOM_UUID.toString()));
|
||||
verifyConversionService();
|
||||
}
|
||||
@Test
|
||||
public void shouldDelegateToProperConversionService() {
|
||||
|
||||
private void verifyConversionService() {
|
||||
verify(conversionService, times(0)).convert(Matchers.any(String.class), eq(UUID.class));
|
||||
verify(conversionService, times(0)).convert(Matchers.any(UUID.class), eq(String.class));
|
||||
}
|
||||
assertThat(delegatingConversionService.canConvert(String.class, UUID.class), is(true));
|
||||
assertThat(delegatingConversionService.convert(RANDOM_UUID.toString(), UUID.class), is(RANDOM_UUID));
|
||||
|
||||
verifyConversionService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldConvertUUIDToString() {
|
||||
|
||||
assertThat(delegatingConversionService.canConvert(UUID.class, String.class), is(true));
|
||||
assertThat(delegatingConversionService.convert(RANDOM_UUID, String.class), is(RANDOM_UUID.toString()));
|
||||
|
||||
verifyConversionService();
|
||||
}
|
||||
|
||||
private void verifyConversionService() {
|
||||
|
||||
verify(conversionService, times(0)).convert(Matchers.any(String.class), eq(UUID.class));
|
||||
verify(conversionService, times(0)).convert(Matchers.any(UUID.class), eq(String.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,92 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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.data.rest.core.util;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests to verify that {@link UriUtils} can manipulate {@link URI}s.
|
||||
*
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class UriUtilsUnitTests {
|
||||
|
||||
private static final String BASE_URI_STR = "http://localhost:8080/data";
|
||||
private static final URI BASE_URI = URI.create(BASE_URI_STR);
|
||||
private static final String BASE_URI_STR = "http://localhost:8080/data";
|
||||
private static final URI BASE_URI = URI.create(BASE_URI_STR);
|
||||
|
||||
private static final String PERSON_2LVL_STR = BASE_URI_STR + "/person/1";
|
||||
private static final URI PERSON_2LVL_URI = URI.create(PERSON_2LVL_STR);
|
||||
private static final String PERSON_2LVL_STR = BASE_URI_STR + "/person/1";
|
||||
private static final URI PERSON_2LVL_URI = URI.create(PERSON_2LVL_STR);
|
||||
|
||||
@Test
|
||||
public void shouldValidateBaseURI() throws Exception {
|
||||
URI uri = new URI(BASE_URI + "/person/1");
|
||||
|
||||
assertThat(UriUtils.validBaseUri(BASE_URI, uri), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIterateOverPathElements() throws Exception {
|
||||
final List<String> paths = new ArrayList<String>();
|
||||
Function<URI, Void> fn = new Function<URI, Void>() {
|
||||
@Override public Void apply(URI uri) {
|
||||
paths.add(uri.getPath());
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
UriUtils.foreach(BASE_URI, PERSON_2LVL_URI, fn);
|
||||
|
||||
assertThat(paths, hasSize(2));
|
||||
assertThat(paths, contains("person", "1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExplodeRelativeURI() throws Exception {
|
||||
Stack<URI> uris = UriUtils.explode(BASE_URI, PERSON_2LVL_URI);
|
||||
|
||||
assertThat(uris, hasSize(2));
|
||||
assertThat(uris, contains(URI.create("person"), URI.create("1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMergeDifferentURIsIntoOne() throws Exception {
|
||||
String qrystr = "?queryParam=testValue";
|
||||
|
||||
URI uriWithQuery = URI.create(qrystr);
|
||||
URI uriWithPath = URI.create("person/1");
|
||||
|
||||
URI uri = UriUtils.merge(BASE_URI, uriWithPath, uriWithQuery);
|
||||
|
||||
assertThat(uri.toString(), is(PERSON_2LVL_STR + qrystr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStripTrailingSlashFromPath() throws Exception {
|
||||
URI uri = URI.create("person/");
|
||||
|
||||
String path = UriUtils.path(uri);
|
||||
|
||||
assertThat(path, is("person"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStripTheLastPathSegmentFromAURI() throws Exception {
|
||||
URI uri = UriUtils.tail(BASE_URI, PERSON_2LVL_URI);
|
||||
|
||||
assertThat(uri, is(URI.create("1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBuildURIFromPathSegments() throws Exception {
|
||||
URI uri = UriUtils.buildUri(BASE_URI, "person", "1");
|
||||
|
||||
assertThat(uri, is(PERSON_2LVL_URI));
|
||||
}
|
||||
@Test
|
||||
public void shouldBuildURIFromPathSegments() throws Exception {
|
||||
|
||||
URI uri = UriUtils.buildUri(BASE_URI, "person", "1");
|
||||
assertThat(uri, is(PERSON_2LVL_URI));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user