CollectionUtils.lastElement for common Set/List extraction
Issue: SPR-16374
This commit is contained in:
parent
13a8f90e08
commit
06e6386dc9
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -712,8 +712,7 @@ class ConfigurationClassParser {
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public AnnotationMetadata getImportingClassFor(String importedClass) {
|
public AnnotationMetadata getImportingClassFor(String importedClass) {
|
||||||
List<AnnotationMetadata> list = this.imports.get(importedClass);
|
return CollectionUtils.lastElement(this.imports.get(importedClass));
|
||||||
return (!CollectionUtils.isEmpty(list) ? list.get(list.size() - 1) : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,6 +24,8 @@ import joptsimple.OptionSet;
|
||||||
import joptsimple.OptionSpec;
|
import joptsimple.OptionSpec;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CommandLinePropertySource} implementation backed by a JOpt {@link OptionSet}.
|
* {@link CommandLinePropertySource} implementation backed by a JOpt {@link OptionSet}.
|
||||||
|
@ -86,13 +88,13 @@ public class JOptCommandLinePropertySource extends CommandLinePropertySource<Opt
|
||||||
public String[] getPropertyNames() {
|
public String[] getPropertyNames() {
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
for (OptionSpec<?> spec : this.source.specs()) {
|
for (OptionSpec<?> spec : this.source.specs()) {
|
||||||
List<String> aliases = new ArrayList<>(spec.options());
|
String lastOption = CollectionUtils.lastElement(spec.options());
|
||||||
if (!aliases.isEmpty()) {
|
if (lastOption != null) {
|
||||||
// Only the longest name is used for enumerating
|
// Only the longest name is used for enumerating
|
||||||
names.add(aliases.get(aliases.size() - 1));
|
names.add(lastOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names.toArray(new String[names.size()]);
|
return StringUtils.toStringArray(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -29,6 +29,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
@ -312,6 +313,48 @@ public abstract class CollectionUtils {
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the last element of the given Set, using {@link SortedSet#last()}
|
||||||
|
* or otherwise iterating over all elements (assuming a linked set).
|
||||||
|
* @param set the Set to check (may be {@code null} or empty)
|
||||||
|
* @return the last element, or {@code null} if none
|
||||||
|
* @since 5.0.3
|
||||||
|
* @see SortedSet
|
||||||
|
* @see LinkedHashMap#keySet()
|
||||||
|
* @see java.util.LinkedHashSet
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static <T> T lastElement(@Nullable Set<T> set) {
|
||||||
|
if (isEmpty(set)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (set instanceof SortedSet) {
|
||||||
|
return ((SortedSet<T>) set).last();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full iteration necessary...
|
||||||
|
Iterator<T> it = set.iterator();
|
||||||
|
T last = null;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
last = it.next();
|
||||||
|
}
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the last element of the given List, accessing the highest index.
|
||||||
|
* @param list the List to check (may be {@code null} or empty)
|
||||||
|
* @return the last element, or {@code null} if none
|
||||||
|
* @since 5.0.3
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static <T> T lastElement(@Nullable List<T> list) {
|
||||||
|
if (isEmpty(list)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.get(list.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marshal the elements from the given enumeration into an array of the given type.
|
* Marshal the elements from the given enumeration into an array of the given type.
|
||||||
* Enumeration elements must be assignable to the type of the given array. The array
|
* Enumeration elements must be assignable to the type of the given array. The array
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -26,6 +26,7 @@ import org.springframework.asm.ClassWriter;
|
||||||
import org.springframework.asm.MethodVisitor;
|
import org.springframework.asm.MethodVisitor;
|
||||||
import org.springframework.asm.Opcodes;
|
import org.springframework.asm.Opcodes;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the class being generated by the compilation process.
|
* Manages the class being generated by the compilation process.
|
||||||
|
@ -153,10 +154,7 @@ public class CodeFlow implements Opcodes {
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String lastDescriptor() {
|
public String lastDescriptor() {
|
||||||
if (this.compilationScopes.peek().isEmpty()) {
|
return CollectionUtils.lastElement(this.compilationScopes.peek());
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return this.compilationScopes.peek().get(this.compilationScopes.peek().size() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -31,6 +31,7 @@ import org.springframework.expression.spel.SpelEvaluationException;
|
||||||
import org.springframework.expression.spel.SpelMessage;
|
import org.springframework.expression.spel.SpelMessage;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +161,7 @@ public class Selection extends SpelNodeImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.variant == LAST) {
|
if (this.variant == LAST) {
|
||||||
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result.get(result.size() - 1)), this);
|
return new ValueRef.TypedValueHolderValueRef(new TypedValue(CollectionUtils.lastElement(result)), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operand instanceof Iterable) {
|
if (operand instanceof Iterable) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,12 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.web.method.annotation;
|
package org.springframework.web.method.annotation;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||||
|
@ -38,6 +37,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
* {@link BindingResult}.
|
* {@link BindingResult}.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||||
|
@ -58,18 +58,15 @@ public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolv
|
||||||
"Errors/BindingResult argument only supported on regular handler methods");
|
"Errors/BindingResult argument only supported on regular handler methods");
|
||||||
|
|
||||||
ModelMap model = mavContainer.getModel();
|
ModelMap model = mavContainer.getModel();
|
||||||
if (model.size() > 0) {
|
String lastKey = CollectionUtils.lastElement(model.keySet());
|
||||||
int lastIndex = model.size()-1;
|
if (lastKey != null && lastKey.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
|
||||||
String lastKey = new ArrayList<>(model.keySet()).get(lastIndex);
|
return model.get(lastKey);
|
||||||
if (lastKey.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
|
|
||||||
return model.get(lastKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"An Errors/BindingResult argument is expected to be declared immediately after " +
|
"An Errors/BindingResult argument is expected to be declared immediately after " +
|
||||||
"the model attribute, the @RequestBody or the @RequestPart arguments " +
|
"the model attribute, the @RequestBody or the @RequestPart arguments " +
|
||||||
"to which they apply: " + parameter.getMethod());
|
"to which they apply: " + parameter.getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -35,7 +35,7 @@ import static org.junit.Assert.*;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class ErrorsMethodHandlerArgumentResolverTests {
|
public class ErrorsMethodArgumentResolverTests {
|
||||||
|
|
||||||
private final ErrorsMethodArgumentResolver resolver = new ErrorsMethodArgumentResolver();
|
private final ErrorsMethodArgumentResolver resolver = new ErrorsMethodArgumentResolver();
|
||||||
|
|
||||||
|
@ -45,15 +45,17 @@ public class ErrorsMethodHandlerArgumentResolverTests {
|
||||||
|
|
||||||
private NativeWebRequest webRequest;
|
private NativeWebRequest webRequest;
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setup() throws Exception {
|
||||||
paramErrors = new MethodParameter(getClass().getDeclaredMethod("handle", Errors.class), 0);
|
paramErrors = new MethodParameter(getClass().getDeclaredMethod("handle", Errors.class), 0);
|
||||||
bindingResult = new WebDataBinder(new Object(), "attr").getBindingResult();
|
bindingResult = new WebDataBinder(new Object(), "attr").getBindingResult();
|
||||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void supports() throws Exception {
|
public void supports() {
|
||||||
resolver.supportsParameter(paramErrors);
|
resolver.supportsParameter(paramErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +70,6 @@ public class ErrorsMethodHandlerArgumentResolverTests {
|
||||||
mavContainer.addAllAttributes(bindingResult.getModel());
|
mavContainer.addAllAttributes(bindingResult.getModel());
|
||||||
|
|
||||||
Object actual = resolver.resolveArgument(paramErrors, mavContainer, webRequest, null);
|
Object actual = resolver.resolveArgument(paramErrors, mavContainer, webRequest, null);
|
||||||
|
|
||||||
assertSame(actual, bindingResult);
|
assertSame(actual, bindingResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +87,9 @@ public class ErrorsMethodHandlerArgumentResolverTests {
|
||||||
resolver.resolveArgument(paramErrors, new ModelAndViewContainer(), webRequest, null);
|
resolver.resolveArgument(paramErrors, new ModelAndViewContainer(), webRequest, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private void handle(Errors errors) {
|
private void handle(Errors errors) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue