1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections4.comparators;
18
19 import java.io.Serializable;
20 import java.util.Comparator;
21 import java.util.Objects;
22
23 import org.apache.commons.collections4.ComparatorUtils;
24 import org.apache.commons.collections4.Transformer;
25
26 /**
27 * Decorates another Comparator with transformation behavior. That is, the
28 * return value from the transform operation will be passed to the decorated
29 * {@link Comparator#compare(Object,Object) compare} method.
30 * <p>
31 * This class is Serializable from Commons Collections 4.0.
32 * </p>
33 *
34 * @param <I> the type of the input to the function
35 * @param <O> the type of the result of the function
36 * @since 2.1
37 * @see org.apache.commons.collections4.Transformer
38 * @see org.apache.commons.collections4.comparators.ComparableComparator
39 */
40 public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
41
42 /** Serialization version from Collections 4.0. */
43 private static final long serialVersionUID = 3456940356043606220L;
44
45 /** The decorated comparator. */
46 private final Comparator<O> decorated;
47
48 /** The transformer being used. */
49 private final Transformer<? super I, ? extends O> transformer;
50
51 /**
52 * Constructs an instance with the given Transformer and a
53 * {@link ComparableComparator ComparableComparator}.
54 *
55 * @param transformer what will transform the arguments to {@code compare}
56 */
57 public TransformingComparator(final Transformer<? super I, ? extends O> transformer) {
58 this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
59 }
60
61 /**
62 * Constructs an instance with the given Transformer and Comparator.
63 *
64 * @param transformer what will transform the arguments to {@code compare}
65 * @param decorated the decorated Comparator
66 */
67 public TransformingComparator(final Transformer<? super I, ? extends O> transformer,
68 final Comparator<O> decorated) {
69 this.decorated = decorated;
70 this.transformer = transformer;
71 }
72
73 /**
74 * Returns the result of comparing the values from the transform operation.
75 *
76 * @param obj1 the first object to transform then compare
77 * @param obj2 the second object to transform then compare
78 * @return negative if obj1 is less, positive if greater, zero if equal
79 */
80 @Override
81 public int compare(final I obj1, final I obj2) {
82 final O value1 = transformer.apply(obj1);
83 final O value2 = transformer.apply(obj2);
84 return decorated.compare(value1, value2);
85 }
86
87 /**
88 * Returns {@code true} iff <em>that</em> Object is
89 * a {@link Comparator} whose ordering is known to be
90 * equivalent to mine.
91 * <p>
92 * This implementation returns {@code true}
93 * iff {@code <em>that</em>} is a {@link TransformingComparator}
94 * whose attributes are equal to mine.
95 *
96 * @param object the object to compare to
97 * @return true if equal
98 */
99 @Override
100 public boolean equals(final Object object) {
101 if (this == object) {
102 return true;
103 }
104 if (null == object) {
105 return false;
106 }
107 if (object.getClass().equals(this.getClass())) {
108 final TransformingComparator<?, ?> comp = (TransformingComparator<?, ?>) object;
109 return Objects.equals(decorated, comp.decorated) &&
110 Objects.equals(transformer, comp.transformer);
111 }
112 return false;
113 }
114
115 /**
116 * Implement a hash code for this comparator that is consistent with
117 * {@link #equals(Object) equals}.
118 *
119 * @return a hash code for this comparator.
120 */
121 @Override
122 public int hashCode() {
123 int total = 17;
124 total = total * 37 + (decorated == null ? 0 : decorated.hashCode());
125 return total * 37 + (transformer == null ? 0 : transformer.hashCode());
126 }
127
128 }
129