diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java index 2cd3497d1b..010b8eec8b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,7 +52,6 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConvertingComparator; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; -import org.springframework.util.comparator.CompoundComparator; import org.springframework.util.comparator.InstanceComparator; /** @@ -73,8 +72,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto private static final Comparator METHOD_COMPARATOR; static { - CompoundComparator comparator = new CompoundComparator<>(); - comparator.addComparator(new ConvertingComparator<>( + Comparator adviceKindComparator = new ConvertingComparator<>( new InstanceComparator<>( Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class), new Converter() { @@ -84,15 +82,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method); return (annotation != null ? annotation.getAnnotation() : null); } - })); - comparator.addComparator(new ConvertingComparator<>( + }); + Comparator methodNameComparator = new ConvertingComparator<>( new Converter() { @Override public String convert(Method method) { return method.getName(); } - })); - METHOD_COMPARATOR = comparator; + }); + METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator); } diff --git a/spring-core/src/main/java/org/springframework/core/convert/converter/ConvertingComparator.java b/spring-core/src/main/java/org/springframework/core/convert/converter/ConvertingComparator.java index 716f834603..d941f7a7b1 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/converter/ConvertingComparator.java +++ b/spring-core/src/main/java/org/springframework/core/convert/converter/ConvertingComparator.java @@ -21,12 +21,12 @@ import java.util.Map; import org.springframework.core.convert.ConversionService; import org.springframework.util.Assert; -import org.springframework.util.comparator.ComparableComparator; +import org.springframework.util.comparator.Comparators; /** - * A {@link Comparator} that converts values before they are compared. The specified - * {@link Converter} will be used to convert each value before it passed to the underlying - * {@code Comparator}. + * A {@link Comparator} that converts values before they are compared. + * The specified {@link Converter} will be used to convert each value + * before it passed to the underlying {@code Comparator}. * * @author Phillip Webb * @since 3.2 @@ -44,9 +44,8 @@ public class ConvertingComparator implements Comparator { * Create a new {@link ConvertingComparator} instance. * @param converter the converter */ - @SuppressWarnings("unchecked") public ConvertingComparator(Converter converter) { - this(ComparableComparator.INSTANCE, converter); + this(Comparators.comparable(), converter); } /** @@ -62,7 +61,7 @@ public class ConvertingComparator implements Comparator { } /** - * Create a new {@link ComparableComparator} instance. + * Create a new {@code ConvertingComparator} instance. * @param comparator the underlying comparator * @param conversionService the conversion service * @param targetType the target type diff --git a/spring-core/src/main/java/org/springframework/util/comparator/BooleanComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/BooleanComparator.java index ec68351e79..b54297b4bd 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/BooleanComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/BooleanComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,23 +20,24 @@ import java.io.Serializable; import java.util.Comparator; /** - * A Comparator for Boolean objects that can sort either true or false first. + * A {@link Comparator} for {@link Boolean} objects that can sort either + * {@code true} or {@code false} first. * * @author Keith Donald * @since 1.2.2 */ @SuppressWarnings("serial") -public final class BooleanComparator implements Comparator, Serializable { +public class BooleanComparator implements Comparator, Serializable { /** - * A shared default instance of this comparator, treating true lower - * than false. + * A shared default instance of this comparator, + * treating {@code true} lower than {@code false}. */ public static final BooleanComparator TRUE_LOW = new BooleanComparator(true); /** - * A shared default instance of this comparator, treating true higher - * than false. + * A shared default instance of this comparator, + * treating {@code true} higher than {@code false}. */ public static final BooleanComparator TRUE_HIGH = new BooleanComparator(false); @@ -64,20 +65,16 @@ public final class BooleanComparator implements Comparator, Serializabl return (v1 ^ v2) ? ((v1 ^ this.trueLow) ? 1 : -1) : 0; } + @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof BooleanComparator)) { - return false; - } - return (this.trueLow == ((BooleanComparator) obj).trueLow); + return (this == obj || + (obj instanceof BooleanComparator && (this.trueLow == ((BooleanComparator) obj).trueLow))); } @Override public int hashCode() { - return (this.trueLow ? -1 : 1) * getClass().hashCode(); + return getClass().hashCode() * (this.trueLow ? -1 : 1); } @Override diff --git a/spring-core/src/main/java/org/springframework/util/comparator/ComparableComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/ComparableComparator.java index b8b27418cb..1fc4683250 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/ComparableComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/ComparableComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,9 +29,14 @@ import java.util.Comparator; */ public class ComparableComparator> implements Comparator { + /** + * A shared instance of this default comparator + * @see Comparators#comparable() + */ @SuppressWarnings("rawtypes") public static final ComparableComparator INSTANCE = new ComparableComparator(); + @Override public int compare(T o1, T o2) { return o1.compareTo(o2); diff --git a/spring-core/src/main/java/org/springframework/util/comparator/Comparators.java b/spring-core/src/main/java/org/springframework/util/comparator/Comparators.java new file mode 100644 index 0000000000..82a46c6686 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/util/comparator/Comparators.java @@ -0,0 +1,77 @@ +/* + * Copyright 2002-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.util.comparator; + +import java.util.Comparator; + +/** + * Convenient entry point with generically typed factory methods + * for common Spring {@link Comparator} variants. + * + * @author Juergen Hoeller + * @since 5.0 + */ +public abstract class Comparators { + + /** + * Return a {@link Comparable} adapter. + * @see ComparableComparator#INSTANCE + */ + @SuppressWarnings("unchecked") + public static Comparator comparable() { + return ComparableComparator.INSTANCE; + } + + /** + * Return a {@link Comparable} adapter which accepts + * null values and sorts them lower than non-null values. + * @see NullSafeComparator#NULLS_LOW + */ + @SuppressWarnings("unchecked") + public static Comparator nullsLow() { + return NullSafeComparator.NULLS_LOW; + } + + /** + * Return a decorator for the given comparator which accepts + * null values and sorts them lower than non-null values. + * @see NullSafeComparator#NullSafeComparator(boolean) + */ + public static Comparator nullsLow(Comparator comparator) { + return new NullSafeComparator(comparator, false); + } + + /** + * Return a {@link Comparable} adapter which accepts + * null values and sorts them higher than non-null values. + * @see NullSafeComparator#NULLS_HIGH + */ + @SuppressWarnings("unchecked") + public static Comparator nullsHigh() { + return NullSafeComparator.NULLS_HIGH; + } + + /** + * Return a decorator for the given comparator which accepts + * null values and sorts them higher than non-null values. + * @see NullSafeComparator#NullSafeComparator(boolean) + */ + public static Comparator nullsHigh(Comparator comparator) { + return new NullSafeComparator(comparator, false); + } + +} diff --git a/spring-core/src/main/java/org/springframework/util/comparator/CompoundComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/CompoundComparator.java index b027fb287c..d0282c41eb 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/CompoundComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/CompoundComparator.java @@ -36,7 +36,10 @@ import org.springframework.util.Assert; * @author Keith Donald * @author Juergen Hoeller * @since 1.2.2 + * @deprecated as of Spring Framework 5.0, in favor of the standard JDK 8 + * {@link Comparator#thenComparing(Comparator)} */ +@Deprecated @SuppressWarnings({"serial", "rawtypes"}) public class CompoundComparator implements Comparator, Serializable { @@ -165,10 +168,11 @@ public class CompoundComparator implements Comparator, Serializable { return this.comparators.size(); } + @Override @SuppressWarnings("unchecked") public int compare(T o1, T o2) { - Assert.state(this.comparators.size() > 0, + Assert.state(!this.comparators.isEmpty(), "No sort definitions have been added to this CompoundComparator to compare"); for (InvertibleComparator comparator : this.comparators) { int result = comparator.compare(o1, o2); @@ -179,6 +183,7 @@ public class CompoundComparator implements Comparator, Serializable { return 0; } + @Override @SuppressWarnings("unchecked") public boolean equals(Object obj) { diff --git a/spring-core/src/main/java/org/springframework/util/comparator/InstanceComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/InstanceComparator.java index 8f033bad27..44118b74e7 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/InstanceComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/InstanceComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,12 +27,12 @@ import org.springframework.util.Assert; * *

Only the specified {@code instanceOrder} classes are considered during comparison. * If two objects are both instances of the ordered type this comparator will return a - * {@code 0}. Consider combining with a {@link CompoundComparator} if additional sorting - * is required. + * {@code 0}. Consider combining with {@link Comparator#thenComparing(Comparator)} + * if additional sorting is required. * * @author Phillip Webb * @since 3.2 - * @see CompoundComparator + * @see Comparator#thenComparing(Comparator) * @param the type of objects being compared */ public class InstanceComparator implements Comparator { @@ -46,7 +46,7 @@ public class InstanceComparator implements Comparator { * objects. Classes earlier in the list will be given a higher priority. */ public InstanceComparator(Class... instanceOrder) { - Assert.notNull(instanceOrder, "'instanceOrder' must not be null"); + Assert.notNull(instanceOrder, "'instanceOrder' array must not be null"); this.instanceOrder = instanceOrder; } diff --git a/spring-core/src/main/java/org/springframework/util/comparator/InvertibleComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/InvertibleComparator.java index 9a9f5f9c19..adb15d3d18 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/InvertibleComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/InvertibleComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,10 @@ import org.springframework.util.Assert; * @author Keith Donald * @author Juergen Hoeller * @since 1.2.2 + * @deprecated as of Spring Framework 5.0, in favor of the standard JDK 8 + * {@link Comparator#reversed()} */ +@Deprecated @SuppressWarnings("serial") public class InvertibleComparator implements Comparator, Serializable { diff --git a/spring-core/src/main/java/org/springframework/util/comparator/NullSafeComparator.java b/spring-core/src/main/java/org/springframework/util/comparator/NullSafeComparator.java index 3732a28f04..aa23fa4478 100644 --- a/spring-core/src/main/java/org/springframework/util/comparator/NullSafeComparator.java +++ b/spring-core/src/main/java/org/springframework/util/comparator/NullSafeComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ public class NullSafeComparator implements Comparator { /** * A shared default instance of this comparator, treating nulls lower * than non-null objects. + * @see Comparators#nullsLow() */ @SuppressWarnings("rawtypes") public static final NullSafeComparator NULLS_LOW = new NullSafeComparator<>(true); @@ -41,10 +42,12 @@ public class NullSafeComparator implements Comparator { /** * A shared default instance of this comparator, treating nulls higher * than non-null objects. + * @see Comparators#nullsHigh() */ @SuppressWarnings("rawtypes") public static final NullSafeComparator NULLS_HIGH = new NullSafeComparator<>(false); + private final Comparator nonNullComparator; private final boolean nullsLow; @@ -64,9 +67,9 @@ public class NullSafeComparator implements Comparator { * @see #NULLS_LOW * @see #NULLS_HIGH */ - @SuppressWarnings({ "unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") private NullSafeComparator(boolean nullsLow) { - this.nonNullComparator = new ComparableComparator(); + this.nonNullComparator = ComparableComparator.INSTANCE; this.nullsLow = nullsLow; } @@ -80,7 +83,7 @@ public class NullSafeComparator implements Comparator { * @param nullsLow whether to treat nulls lower or higher than non-null objects */ public NullSafeComparator(Comparator comparator, boolean nullsLow) { - Assert.notNull(comparator, "The non-null comparator is required"); + Assert.notNull(comparator, "Non-null Comparator is required"); this.nonNullComparator = comparator; this.nullsLow = nullsLow; } @@ -100,6 +103,7 @@ public class NullSafeComparator implements Comparator { return this.nonNullComparator.compare(o1, o2); } + @Override @SuppressWarnings("unchecked") public boolean equals(Object obj) { @@ -115,7 +119,7 @@ public class NullSafeComparator implements Comparator { @Override public int hashCode() { - return (this.nullsLow ? -1 : 1) * this.nonNullComparator.hashCode(); + return this.nonNullComparator.hashCode() * (this.nullsLow ? -1 : 1); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/MediaType.java b/spring-web/src/main/java/org/springframework/http/MediaType.java index 528e3990be..821e84bb22 100644 --- a/spring-web/src/main/java/org/springframework/http/MediaType.java +++ b/spring-web/src/main/java/org/springframework/http/MediaType.java @@ -33,7 +33,6 @@ import org.springframework.util.InvalidMimeTypeException; import org.springframework.util.MimeType; import org.springframework.util.MimeTypeUtils; import org.springframework.util.StringUtils; -import org.springframework.util.comparator.CompoundComparator; /** * A sub-class of {@link MimeType} that adds support for quality parameters as defined @@ -644,8 +643,8 @@ public class MediaType extends MimeType implements Serializable { public static void sortBySpecificityAndQuality(List mediaTypes) { Assert.notNull(mediaTypes, "'mediaTypes' must not be null"); if (mediaTypes.size() > 1) { - Collections.sort(mediaTypes, new CompoundComparator<>( - MediaType.SPECIFICITY_COMPARATOR, MediaType.QUALITY_VALUE_COMPARATOR)); + Collections.sort(mediaTypes, + MediaType.SPECIFICITY_COMPARATOR.thenComparing(MediaType.QUALITY_VALUE_COMPARATOR)); } }