    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.codec;
    019
    020    import java.util.Comparator;
    021
    022    /**
    023     * Compares Strings using a {@link StringEncoder}. This comparator is used to sort Strings by an encoding scheme such as
    024     * Soundex, Metaphone, etc. This class can come in handy if one need to sort Strings by an encoded form of a name such
    025     * as Soundex.
    026     *
    027     * <p>This class is immutable and thread-safe.</p>
    028     *
    029     * @version $Id: StringEncoderComparator.java 1468177 2013-04-15 18:35:15Z ggregory $
    030     */
    031    @SuppressWarnings("rawtypes")
    032    // TODO ought to implement Comparator<String> but that's not possible whilst maintaining binary compatibility.
    033    public class StringEncoderComparator implements Comparator {
    034
    035        /**
    036         * Internal encoder instance.
    037         */
    038        private final StringEncoder stringEncoder;
    039
    040        /**
    041         * Constructs a new instance.
    042         *
    043         * @deprecated Creating an instance without a {@link StringEncoder} leads to a {@link NullPointerException}. Will be
    044         *             removed in 2.0.
    045         */
    046        @Deprecated
    047        public StringEncoderComparator() {
    048            this.stringEncoder = null; // Trying to use this will cause things to break
    049        }
    050
    051        /**
    052         * Constructs a new instance with the given algorithm.
    053         *
    054         * @param stringEncoder
    055         *            the StringEncoder used for comparisons.
    056         */
    057        public StringEncoderComparator(final StringEncoder stringEncoder) {
    058            this.stringEncoder = stringEncoder;
    059        }
    060
    061        /**
    062         * Compares two strings based not on the strings themselves, but on an encoding of the two strings using the
    063         * StringEncoder this Comparator was created with.
    064         *
    065         * If an {@link EncoderException} is encountered, return <code>0</code>.
    066         *
    067         * @param o1
    068         *            the object to compare
    069         * @param o2
    070         *            the object to compare to
    071         * @return the Comparable.compareTo() return code or 0 if an encoding error was caught.
    072         * @see Comparable
    073         */
    074        @Override
    075        public int compare(final Object o1, final Object o2) {
    076
    077            int compareCode = 0;
    078
    079            try {
    080                @SuppressWarnings("unchecked") // May fail with CCE if encode returns something that is not Comparable
    081                // However this was always the case.
    082                final Comparable<Comparable<?>> s1 = (Comparable<Comparable<?>>) this.stringEncoder.encode(o1);
    083                final Comparable<?> s2 = (Comparable<?>) this.stringEncoder.encode(o2);
    084                compareCode = s1.compareTo(s2);
    085            } catch (final EncoderException ee) {
    086                compareCode = 0;
    087            }
    088            return compareCode;
    089        }
    090
    091    }