/* * @(#) src/net/sf/ivmaidns/util/GComparator.java -- * Class for 'greater-than' comparators. ** * Copyright (c) 2000 Ivan Maidanski <ivmai@mail.ru> * All rights reserved. */ /* * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. ** * This software 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 * General Public License (GPL) for more details. ** * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. ** * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package net.sf.ivmaidns.util; import java.io.Serializable; /** * Class for 'greater-than' comparators. ** * A binary predicate, which tests whether the first its argument is * greater than the second one, should extend this adapter class and * override <CODE>greater(Object, Object)</CODE>, implementing own * comparison rules. <CODE>Immutable</CODE> interface is implemented * to underline that such comparators must have constant internal * state. The comparators may be used in serializable data * structures since <CODE>Serializable</CODE> interface is * implemented. In addition, this class provides the default * comparator for objects of <CODE>Sortable</CODE> interface, and of * <CODE>String</CODE> class and of the standard wrappers for the * primitive types. ** * @see Sortable * @see StrComparator ** * @version 2.0 * @author Ivan Maidanski ** * @since 1.8 */ public class GComparator implements Immutable, Serializable { /** * The class version unique identifier for serialization * interoperability. ** * @since 1.8 */ private static final long serialVersionUID = 1310911848083016948L; /** * The standard comparator for objects. ** * This constant field is initialized with the instantiation of * exactly this comparator. The implemented standard comparator * correctly orders any two objects of the class which implements * <CODE>Sortable</CODE> interface, or both of <CODE>String</CODE> * class, or both of the same primary-type value wrapper. ** * @see #greater(java.lang.Object, java.lang.Object) */ public static final GComparator INSTANCE = new GComparator(); /** * Constructs a new comparator. ** * This constructor is made <CODE>public</CODE> to allow custom * dynamic instantiation of this class. ** * @see #INSTANCE */ public GComparator() {} /** * The body of 'Greater-Than' comparator. ** * Tests whether or not the first specified object is greater than * the second one (according to the semantics). This method should * be overridden in the adapter subclasses. If any argument is not * instance of the expected type then standard comparison should be * performed (which is implemented in this method of this class). * The standard comparison of two objects is as follows: if * <CODE>objA == objB</CODE> then <CODE>false</CODE> is returned * else if <VAR>objA</VAR> is instance of <CODE>Sortable</CODE> then * <CODE>greaterThan(objB)</CODE> for <VAR>objA</VAR> is returned * else if <VAR>objB</VAR> is instance of <CODE>Sortable</CODE> then * <CODE>!greaterThan(objA)</CODE> for <VAR>objB</VAR> is returned, * else if <VAR>objA</VAR> is <CODE>null</CODE> then * <CODE>true</CODE> is returned, else if <VAR>objA</VAR> and * <VAR>objB</VAR> are both of the same class (either * <CODE>Boolean</CODE>, <CODE>Byte</CODE>, <CODE>Short</CODE>, * <CODE>Integer</CODE>, <CODE>Long</CODE>, <CODE>Float</CODE>, * <CODE>Double</CODE>, <CODE>Character</CODE> or * <CODE>String</CODE>) and the first (primary) value is greater * than the second one then <CODE>true</CODE> else * <CODE>false</CODE> is returned. Important notes: * <CODE>String</CODE> objects are compared here in the * case-sensitive manner; <CODE>Float</CODE> and <CODE>Double</CODE> * objects are compared here handling their zero and * <CODE>NaN</CODE> values specially (<CODE>0</CODE> is greater than * <CODE>-0</CODE> and <CODE>NaN</CODE> is greater than * non-<CODE>NaN</CODE>). ** * @param objA * the first compared argument (may be <CODE>null</CODE>). * @param objB * the second compared argument (may be <CODE>null</CODE>). * @return * <CODE>true</CODE> if and only if <VAR>objA</VAR> is greater than * <VAR>objB</VAR>. ** * @see #INSTANCE */ public boolean greater(Object objA, Object objB) { if (objA != objB) { if (objA instanceof Sortable) return ((Sortable)objA).greaterThan(objB); if (objB instanceof Sortable) return !((Sortable)objB).greaterThan(objA); if (objA == null) return true; if (objB != null) { if (objA instanceof String) return objB instanceof String && ((String)objA).compareTo((String)objB) > 0; if (objA instanceof Integer) return objB instanceof Integer && ((Integer)objA).intValue() > ((Integer)objB).intValue(); if (objA instanceof Long) return objB instanceof Long && ((Long)objA).longValue() > ((Long)objB).longValue(); if (objA instanceof Character) return objB instanceof Character && ((Character)objA).charValue() > ((Character)objB).charValue(); if (objA instanceof Short) return objB instanceof Short && ((Short)objA).intValue() > ((Short)objB).intValue(); if (objA instanceof Byte) return objB instanceof Byte && ((Byte)objA).intValue() > ((Byte)objB).intValue(); if (objA instanceof Boolean) return objB instanceof Boolean && ((Boolean)objA).booleanValue() && !((Boolean)objB).booleanValue(); if (objA instanceof Float && objB instanceof Float) { float floatB = ((Float)objB).floatValue(), floatA; return (floatA = ((Float)objA).floatValue()) > floatB || !(floatA < floatB) && Float.floatToIntBits(floatA) > Float.floatToIntBits(floatB); } if (objA instanceof Double && objB instanceof Double) { double doubleB = ((Double)objB).doubleValue(), doubleA; return (doubleA = ((Double)objA).doubleValue()) > doubleB || !(doubleA < doubleB) && Double.doubleToLongBits(doubleA) > Double.doubleToLongBits(doubleB); } } } return false; } }