1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.collections.comparators;
  17. import java.io.Serializable;
  18. import java.util.Comparator;
  19. /**
  20. * A Comparator that will compare nulls to be either lower or higher than
  21. * other objects.
  22. *
  23. * @since Commons Collections 2.0
  24. * @version $Revision: 1.13 $ $Date: 2004/05/15 13:24:11 $
  25. *
  26. * @author Michael A. Smith
  27. */
  28. public class NullComparator implements Comparator, Serializable {
  29. /** Serialization version. */
  30. private static final long serialVersionUID = -5820772575483504339L;
  31. /**
  32. * The comparator to use when comparing two non-<code>null</code> objects.
  33. **/
  34. private Comparator nonNullComparator;
  35. /**
  36. * Specifies whether a <code>null</code> are compared as higher than
  37. * non-<code>null</code> objects.
  38. **/
  39. private boolean nullsAreHigh;
  40. //-----------------------------------------------------------------------
  41. /**
  42. * Construct an instance that sorts <code>null</code> higher than any
  43. * non-<code>null</code> object it is compared with. When comparing two
  44. * non-<code>null</code> objects, the {@link ComparableComparator} is
  45. * used.
  46. **/
  47. public NullComparator() {
  48. this(ComparableComparator.getInstance(), true);
  49. }
  50. /**
  51. * Construct an instance that sorts <code>null</code> higher than any
  52. * non-<code>null</code> object it is compared with. When comparing two
  53. * non-<code>null</code> objects, the specified {@link Comparator} is
  54. * used.
  55. *
  56. * @param nonNullComparator the comparator to use when comparing two
  57. * non-<code>null</code> objects. This argument cannot be
  58. * <code>null</code>
  59. *
  60. * @exception NullPointerException if <code>nonNullComparator</code> is
  61. * <code>null</code>
  62. **/
  63. public NullComparator(Comparator nonNullComparator) {
  64. this(nonNullComparator, true);
  65. }
  66. /**
  67. * Construct an instance that sorts <code>null</code> higher or lower than
  68. * any non-<code>null</code> object it is compared with. When comparing
  69. * two non-<code>null</code> objects, the {@link ComparableComparator} is
  70. * used.
  71. *
  72. * @param nullsAreHigh a <code>true</code> value indicates that
  73. * <code>null</code> should be compared as higher than a
  74. * non-<code>null</code> object. A <code>false</code> value indicates
  75. * that <code>null</code> should be compared as lower than a
  76. * non-<code>null</code> object.
  77. **/
  78. public NullComparator(boolean nullsAreHigh) {
  79. this(ComparableComparator.getInstance(), nullsAreHigh);
  80. }
  81. /**
  82. * Construct an instance that sorts <code>null</code> higher or lower than
  83. * any non-<code>null</code> object it is compared with. When comparing
  84. * two non-<code>null</code> objects, the specified {@link Comparator} is
  85. * used.
  86. *
  87. * @param nonNullComparator the comparator to use when comparing two
  88. * non-<code>null</code> objects. This argument cannot be
  89. * <code>null</code>
  90. *
  91. * @param nullsAreHigh a <code>true</code> value indicates that
  92. * <code>null</code> should be compared as higher than a
  93. * non-<code>null</code> object. A <code>false</code> value indicates
  94. * that <code>null</code> should be compared as lower than a
  95. * non-<code>null</code> object.
  96. *
  97. * @exception NullPointerException if <code>nonNullComparator</code> is
  98. * <code>null</code>
  99. **/
  100. public NullComparator(Comparator nonNullComparator, boolean nullsAreHigh) {
  101. this.nonNullComparator = nonNullComparator;
  102. this.nullsAreHigh = nullsAreHigh;
  103. if(nonNullComparator == null) {
  104. throw new NullPointerException("null nonNullComparator");
  105. }
  106. }
  107. //-----------------------------------------------------------------------
  108. /**
  109. * Perform a comparison between two objects. If both objects are
  110. * <code>null</code>, a <code>0</code> value is returned. If one object
  111. * is <code>null</code> and the other is not, the result is determined on
  112. * whether the Comparator was constructed to have nulls as higher or lower
  113. * than other objects. If neither object is <code>null</code>, an
  114. * underlying comparator specified in the constructor (or the default) is
  115. * used to compare the non-<code>null</code> objects.
  116. *
  117. * @param o1 the first object to compare
  118. * @param o2 the object to compare it to.
  119. * @return <code>-1</code> if <code>o1</code> is "lower" than (less than,
  120. * before, etc.) <code>o2</code> <code>1</code> if <code>o1</code> is
  121. * "higher" than (greater than, after, etc.) <code>o2</code> or
  122. * <code>0</code> if <code>o1</code> and <code>o2</code> are equal.
  123. **/
  124. public int compare(Object o1, Object o2) {
  125. if(o1 == o2) { return 0; }
  126. if(o1 == null) { return (this.nullsAreHigh ? 1 : -1); }
  127. if(o2 == null) { return (this.nullsAreHigh ? -1 : 1); }
  128. return this.nonNullComparator.compare(o1, o2);
  129. }
  130. //-----------------------------------------------------------------------
  131. /**
  132. * Implement a hash code for this comparator that is consistent with
  133. * {@link #equals(Object)}.
  134. *
  135. * @return a hash code for this comparator.
  136. **/
  137. public int hashCode() {
  138. return (nullsAreHigh ? -1 : 1) * nonNullComparator.hashCode();
  139. }
  140. /**
  141. * Determines whether the specified object represents a comparator that is
  142. * equal to this comparator.
  143. *
  144. * @param obj the object to compare this comparator with.
  145. *
  146. * @return <code>true</code> if the specified object is a NullComparator
  147. * with equivalent <code>null</code> comparison behavior
  148. * (i.e. <code>null</code> high or low) and with equivalent underlying
  149. * non-<code>null</code> object comparators.
  150. **/
  151. public boolean equals(Object obj) {
  152. if(obj == null) { return false; }
  153. if(obj == this) { return true; }
  154. if(!obj.getClass().equals(this.getClass())) { return false; }
  155. NullComparator other = (NullComparator)obj;
  156. return ((this.nullsAreHigh == other.nullsAreHigh) &&
  157. (this.nonNullComparator.equals(other.nonNullComparator)));
  158. }
  159. }