/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2001-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotoolkit.util;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.geotoolkit.lang.Static;
import org.apache.sis.util.Version;
/**
* Miscellaneous methods.
* <p>
* This class also provides convenience methods for computing {@linkplain Object#hashCode hash code}
* values. All those methods expect a {@code seed} argument, which is the hash code value computed
* for previous fields in a class. For the initial seed (the one for the field for which to compute
* an hash code), an arbitrary value must be provided. We suggest a different number for different
* class in order to reduce the risk of collision between "empty" instances of different classes.
* {@linkplain java.io.Serializable} classes can use {@code (int) serialVersionUID} for example.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 4.00
*
* @since 1.2
* @module
*/
public final class Utilities extends Static {
/**
* A prime number used for hash code computation. Value 31 is often used because
* some modern compilers can optimize {@code x*31} as {@code (x << 5) - x}
* (Josh Bloch, <cite>Effective Java</cite>).
*/
private static final int PRIME_NUMBER = 31;
/**
* The version of this Geotoolkit.org distribution.
*/
public static final Version VERSION = new Version("4.00-SNAPSHOT");
/**
* Forbid object creation.
*/
private Utilities() {
}
/**
* Returns {@code true} if the given floats are equals. Positive and negative zero are
* considered different, while a NaN value is considered equal to all other NaN values.
*
* @param o1 The first value to compare.
* @param o2 The second value to compare.
* @return {@code true} if both values are equal.
*
* @see Float#equals(Object)
*/
public static boolean equals(final float o1, final float o2) {
return Float.floatToIntBits(o1) == Float.floatToIntBits(o2);
}
/**
* Returns {@code true} if the given doubles are equals. Positive and negative zero are
* considered different, while a NaN value is considered equal to all other NaN values.
*
* @param o1 The first value to compare.
* @param o2 The second value to compare.
* @return {@code true} if both values are equal.
*
* @see Double#equals(Object)
*/
public static boolean equals(final double o1, final double o2) {
return Double.doubleToLongBits(o1) == Double.doubleToLongBits(o2);
}
/**
* Alters the given seed with the hash code value computed from the given value.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final boolean value, final int seed) {
// Use the same values than Boolean.hashCode()
return seed * PRIME_NUMBER + (value ? 1231 : 1237);
}
/**
* Alters the given seed with the hash code value computed from the given value.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final char value, final int seed) {
return seed * PRIME_NUMBER + (int) value;
}
/**
* Alters the given seed with the hash code value computed from the given value.
* {@code byte} and {@code short} primitive types are handled by this method as
* well through implicit widening conversion.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final int value, final int seed) {
return seed * PRIME_NUMBER + value;
}
/**
* Alters the given seed with the hash code value computed from the given value.
* {@code byte} and {@code short} primitive types are handled by this method as
* well through implicit widening conversion.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final long value, final int seed) {
return seed * PRIME_NUMBER + (((int) value) ^ ((int) (value >>> 32)));
}
/**
* Alters the given seed with the hash code value computed from the given value.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final float value, final int seed) {
return seed * PRIME_NUMBER + Float.floatToIntBits(value);
}
/**
* Alters the given seed with the hash code value computed from the given value.
*
* @param value The value whose hash code to compute.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
*/
public static int hash(final double value, final int seed) {
return hash(Double.doubleToLongBits(value), seed);
}
/**
* Alters the given seed with the hash code value computed from the given value. The given
* object may be null. This method do <strong>not</strong> iterates recursively in array
* elements. If array needs to be hashed, use one of {@link Arrays} method or
* {@link #deepHashCode deepHashCode} instead.
* <p>
* <b>Note on assertions:</b> There is no way to ensure at compile time that this method
* is not invoked with an array argument, while doing so would usually be a program error.
* Performing a systematic argument check would impose a useless overhead for correctly
* implemented {@link Object#hashCode} methods. As a compromise we perform this check at
* runtime only if assertions are enabled. Using assertions for argument check in a public
* API is usually a deprecated practice, but we make an exception for this particular method.
*
* @param value The value whose hash code to compute, or {@code null}.
* @param seed The hash code value computed so far. If this method is invoked for the first
* field, then any arbitrary value (preferably different for each class) is okay.
* @return An updated hash code value.
* @throws AssertionError If assertions are enabled and the given value is an array.
*/
public static int hash(final Object value, int seed) throws AssertionError {
seed *= PRIME_NUMBER;
if (value != null) {
assert !value.getClass().isArray() : name(value);
seed += value.hashCode();
}
return seed;
}
/**
* Returns the class name of the given object.
* Used in assertions only.
*/
private static String name(final Object object) {
return object.getClass().getSimpleName();
}
/**
* Utility method to avoid to fill an empty list during equals.
* But we want to consider equals a null list and an empty one, for JAXB purpose
* @param l1 first list to compare
* @param l2 second list to compare
* @return True if the two list are equals, or if one is null and the other empty
*/
public static boolean listNullEquals(List l1, List l2) {
if (l1 == null && l2 != null && l2.isEmpty()) {
return true;
} else if (l2 == null && l1 != null && l1.isEmpty()) {
return true;
} else {
return Objects.equals(l1, l2);
}
}
}