org.jactr.core.utils.ChainedComparator.java Source code

Java tutorial

Introduction

Here is the source code for org.jactr.core.utils.ChainedComparator.java

Source

/**
 * Copyright (C) 2001-3, Anthony Harrison anh23@pitt.edu This library is free
 * software; you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details. You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package org.jactr.core.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Description of the Class
 * 
 * @author harrison
 */
public class ChainedComparator<T> implements Comparator<T> {
    static private final transient Log LOGGER = LogFactory.getLog(ChainedComparator.class);

    List<Comparator<T>> _comparators;

    boolean _permitEqualities = true;

    int _comparatorSeed = (int) ((Math.random() + 1) * System.currentTimeMillis());

    /**
     * Constructor for the ChainedComparator object
     * 
     * @param permitEqualities TODO
     */
    public ChainedComparator(boolean permitEqualities) {
        _comparators = new ArrayList<Comparator<T>>(3);
        _permitEqualities = permitEqualities;
    }

    /**
     * @param comp TODO
     * @param permitEqualities TODO
     */
    public ChainedComparator(Comparator<T> comp, boolean permitEqualities) {
        this(permitEqualities);
        add(comp);
    }

    public ChainedComparator(Collection<Comparator<T>> comps, boolean permitEqualities) {
        this(permitEqualities);
        _comparators.addAll(comps);
    }

    /**
     * Adds a feature to the Comparator attribute of the ChainedComparator object
     * 
     * @param comp
     *          The feature to be added to the Comparator attribute
     */
    public void add(Comparator<T> comp) {
        _comparators.add(comp);
    }

    /**
     * Description of the Method
     * 
     * @param comp
     *          Description of the Parameter
     */
    public void remove(Comparator<T> comp) {
        _comparators.remove(comp);
    }

    @Deprecated
    public int getNumberOfComparators() {
        return _comparators.size();
    }

    public int size() {
        return _comparators.size();
    }

    /**
     * Gets the comparators attribute of the ChainedComparator object
     * 
     * @return The comparators value
     */
    public List<Comparator<T>> getComparators() {
        return new ArrayList<Comparator<T>>(_comparators);
    }

    /**
     * Description of the Method
     * 
     * @param one
     *          Description of the Parameter
     * @param two
     *          Description of the Parameter
     * @return Description of the Return Value
     */
    public int compare(T one, T two) {
        if (one == two)
            return 0;

        for (Comparator<T> comparator : _comparators) {
            int rtnValue = comparator.compare(one, two);
            if (rtnValue != 0)
                return rtnValue;
        }

        if (_permitEqualities)
            return 0;

        /*
         * this is strange. If we're in the situation where all the comparators say
         * the two are equal, it is likely that their hashCodes are consistent such
         * that some relationship between the two hashcodes will be constant. So, we
         * change it up with an instance specific mask
         */
        int h1 = one.hashCode() & _comparatorSeed;
        int h2 = two.hashCode() & _comparatorSeed;

        int rtn = Integer.compare(h1, h2);

        if (rtn == 0) {
            // one last attempt
            h1 *= hashCode();
            h2 *= hashCode();
            rtn = Integer.compare(h1, h2);

            if (rtn == 0)
                LOGGER.error(String.format("functional equality %s.%d = %s.%d ", one, one.hashCode(), two,
                        two.hashCode()));
        }

        return rtn;
    }

}