001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.util.comparator;
018:
019: import java.util.Comparator;
020:
021: import org.springframework.util.Assert;
022:
023: /**
024: * A Comparator that will safely compare nulls to be lower or higher than
025: * other objects. Can decorate a given Comparator or work on Comparables.
026: *
027: * @author Keith Donald
028: * @author Juergen Hoeller
029: * @since 1.2.2
030: * @see Comparable
031: */
032: public class NullSafeComparator implements Comparator {
033:
034: /**
035: * A shared default instance of this comparator, treating nulls lower
036: * than non-null objects.
037: */
038: public static final NullSafeComparator NULLS_LOW = new NullSafeComparator(
039: true);
040:
041: /**
042: * A shared default instance of this comparator, treating nulls higher
043: * than non-null objects.
044: */
045: public static final NullSafeComparator NULLS_HIGH = new NullSafeComparator(
046: false);
047:
048: private final Comparator nonNullComparator;
049:
050: private final boolean nullsLow;
051:
052: /**
053: * Create a NullSafeComparator that sorts <code>null</code> based on
054: * the provided flag, working on Comparables.
055: * <p>When comparing two non-null objects, their Comparable implementation
056: * will be used: this means that non-null elements (that this Comparator
057: * will be applied to) need to implement Comparable.
058: * <p>As a convenience, you can use the default shared instances:
059: * <code>NullSafeComparator.NULLS_LOW</code> and
060: * <code>NullSafeComparator.NULLS_HIGH</code>.
061: * @param nullsLow whether to treat nulls lower or higher than non-null objects
062: * @see java.lang.Comparable
063: * @see #NULLS_LOW
064: * @see #NULLS_HIGH
065: */
066: private NullSafeComparator(boolean nullsLow) {
067: this (new ComparableComparator(), nullsLow);
068: }
069:
070: /**
071: * Create a NullSafeComparator that sorts <code>null</code> based on the
072: * provided flag, decorating the given Comparator.
073: * <p>When comparing two non-null objects, the specified Comparator will be used.
074: * The given underlying Comparator must be able to handle the elements that this
075: * Comparator will be applied to.
076: * @param comparator the comparator to use when comparing two non-null objects
077: * @param nullsLow whether to treat nulls lower or higher than non-null objects
078: */
079: public NullSafeComparator(Comparator comparator, boolean nullsLow) {
080: Assert.notNull(comparator,
081: "The non-null comparator is required");
082: this .nonNullComparator = comparator;
083: this .nullsLow = nullsLow;
084: }
085:
086: public int compare(Object o1, Object o2) {
087: if (o1 == o2) {
088: return 0;
089: }
090: if (o1 == null) {
091: return (this .nullsLow ? -1 : 1);
092: }
093: if (o2 == null) {
094: return (this .nullsLow ? 1 : -1);
095: }
096: return this .nonNullComparator.compare(o1, o2);
097: }
098:
099: public boolean equals(Object obj) {
100: if (this == obj) {
101: return true;
102: }
103: if (!(obj instanceof NullSafeComparator)) {
104: return false;
105: }
106: NullSafeComparator other = (NullSafeComparator) obj;
107: return (this .nonNullComparator.equals(other.nonNullComparator) && this .nullsLow == other.nullsLow);
108: }
109:
110: public int hashCode() {
111: return (this .nullsLow ? -1 : 1)
112: * this .nonNullComparator.hashCode();
113: }
114:
115: public String toString() {
116: return "NullSafeComparator: non-null comparator ["
117: + this .nonNullComparator + "]; "
118: + (this .nullsLow ? "nulls low" : "nulls high");
119: }
120:
121: }
|