    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
    018package org.apache.commons.codec;
    019
    020import 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$
    030 */
    031@SuppressWarnings("rawtypes")
    032// TODO ought to implement Comparator<String> but that's not possible whilst maintaining binary compatibility.
    033public 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}