package org.succlz123.utils;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
/**
* <p>Operations on {@code Object}.</p>
*
* <p>This class tries to handle {@code null} input gracefully.
* An exception will generally not be thrown for a {@code null} input.
* Each method documents its behaviour in more detail.</p>
*
* <p>#ThreadSafe#</p>
* @since 1.0
* @version $Id: ObjectUtils.java 1199894 2011-11-09 17:53:59Z ggregory $
*/
public class ObjectUtils {
/**
* <p>Singleton used as a {@code null} placeholder where
* {@code null} has another meaning.</p>
*
* <p>For example, in a {@code HashMap} the
* {@link HashMap#get(Object)} method returns
* {@code null} if the {@code Map} contains {@code null} or if there
* is no matching key. The {@code Null} placeholder can be used to
* distinguish between these two cases.</p>
*
* <p>Another example is {@code Hashtable}, where {@code null}
* cannot be stored.</p>
*
* <p>This instance is Serializable.</p>
*/
public static final Null NULL = new Null();
/**
* <p>{@code ObjectUtils} instances should NOT be constructed in
* standard programming. Instead, the static methods on the class should
* be used, such as {@code ObjectUtils.defaultIfNull("a","b");}.</p>
*
* <p>This constructor is public to permit tools that require a JavaBean
* instance to operate.</p>
*/
public ObjectUtils() {
super();
}
// Defaulting
//-----------------------------------------------------------------------
/**
* <p>Returns a default value if the object passed is {@code null}.</p>
*
* <pre>
* ObjectUtils.defaultIfNull(null, null) = null
* ObjectUtils.defaultIfNull(null, "") = ""
* ObjectUtils.defaultIfNull(null, "zz") = "zz"
* ObjectUtils.defaultIfNull("abc", *) = "abc"
* ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
* </pre>
*
* @param <T> the type of the object
* @param object the {@code Object} to test, may be {@code null}
* @param defaultValue the default value to return, may be {@code null}
* @return {@code object} if it is not {@code null}, defaultValue otherwise
*/
public static <T> T defaultIfNull(T object, T defaultValue) {
return object != null ? object : defaultValue;
}
/**
* <p>Returns the first value in the array which is not {@code null}.
* If all the values are {@code null} or the array is {@code null}
* or empty then {@code null} is returned.</p>
*
* <pre>
* ObjectUtils.firstNonNull(null, null) = null
* ObjectUtils.firstNonNull(null, "") = ""
* ObjectUtils.firstNonNull(null, null, "") = ""
* ObjectUtils.firstNonNull(null, "zz") = "zz"
* ObjectUtils.firstNonNull("abc", *) = "abc"
* ObjectUtils.firstNonNull(null, "xyz", *) = "xyz"
* ObjectUtils.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE
* ObjectUtils.firstNonNull() = null
* </pre>
*
* @param <T> the component type of the array
* @param values the values to test, may be {@code null} or empty
* @return the first value from {@code values} which is not {@code null},
* or {@code null} if there are no non-null values
*/
public static <T> T firstNonNull(T... values) {
if (values != null) {
for (T val : values) {
if (val != null) {
return val;
}
}
}
return null;
}
/**
* <p>Returns the first value in the Collection which is not {@code null}.
* If all the values are {@code null} or the array is {@code null}
* or empty then {@code null} is returned.</p>
*
* <pre>
* ObjectUtils.firstNonNull([null, null]) = null
* ObjectUtils.firstNonNull([null, ""]) = ""
* ObjectUtils.firstNonNull([null, null, ""]) = ""
* ObjectUtils.firstNonNull([null, "zz"]) = "zz"
* ObjectUtils.firstNonNull(["abc", *]) = "abc"
* ObjectUtils.firstNonNull([null, "xyz", *]) = "xyz"
* ObjectUtils.firstNonNull([Boolean.TRUE, *]) = Boolean.TRUE
* </pre>
*
* @param <T> the component type of the array
* @param values the values to test, may be {@code null} or empty
* @return the first value from {@code values} which is not {@code null},
* or {@code null} if there are no non-null values
*/
public static <T> T firstNonNull(Collection<T> values) {
if (values != null) {
for (T val : values) {
if (val != null) {
return val;
}
}
}
return null;
}
// Null-safe equals/hashCode
//-----------------------------------------------------------------------
/**
* <p>Compares two objects for equality, where either one or both
* objects may be {@code null}.</p>
*
* <pre>
* ObjectUtils.equals(null, null) = true
* ObjectUtils.equals(null, "") = false
* ObjectUtils.equals("", null) = false
* ObjectUtils.equals("", "") = true
* ObjectUtils.equals(Boolean.TRUE, null) = false
* ObjectUtils.equals(Boolean.TRUE, "true") = false
* ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE) = true
* ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
* </pre>
*
* @param object1 the first object, may be {@code null}
* @param object2 the second object, may be {@code null}
* @return {@code true} if the values of both objects are the same
*/
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if (object1 == null || object2 == null) {
return false;
}
return object1.equals(object2);
}
/**
* <p>Gets the hash code of an object returning zero when the
* object is {@code null}.</p>
*
* <pre>
* ObjectUtils.hashCode(null) = 0
* ObjectUtils.hashCode(obj) = obj.hashCode()
* </pre>
*
* @param obj the object to obtain the hash code of, may be {@code null}
* @return the hash code of the object, or zero if null
*/
public static int hashCode(Object obj) {
// hashCode(Object) retained for performance, as hash code is often critical
return obj == null ? 0 : obj.hashCode();
}
// Identity ToString
//-----------------------------------------------------------------------
/**
* <p>Gets the toString that would be produced by {@code Object}
* if a class did not override toString itself. {@code null}
* will return {@code null}.</p>
*
* <pre>
* ObjectUtils.identityToString(null) = null
* ObjectUtils.identityToString("") = "java.lang.String@1e23"
* ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
* </pre>
*
* @param object the object to create a toString for, may be
* {@code null}
* @return the default toString text, or {@code null} if
* {@code null} passed in
*/
public static String identityToString(Object object) {
if (object == null) {
return null;
}
StringBuffer buffer = new StringBuffer();
identityToString(buffer, object);
return buffer.toString();
}
/**
* <p>Appends the toString that would be produced by {@code Object}
* if a class did not override toString itself. {@code null}
* will throw a NullPointerException for either of the two parameters. </p>
* <p/>
* <pre>
* ObjectUtils.identityToString(appendable, "") = appendable.append("java.lang.String@1e23"
* ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa"
* ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa")
* </pre>
*
* @param appendable the appendable to append to
* @param object the object to create a toString for
* @throws IOException if an I/O error occurs
*/
public static void identityToString(final Appendable appendable, final Object object) throws IOException {
if (object == null) {
throw new NullPointerException("Cannot get the toString of a null identity");
}
appendable.append(object.getClass().getName())
.append('@')
.append(Integer.toHexString(System.identityHashCode(object)));
}
/**
* <p>Appends the toString that would be produced by {@code Object}
* if a class did not override toString itself. {@code null}
* will throw a NullPointerException for either of the two parameters. </p>
*
* <pre>
* ObjectUtils.identityToString(buf, "") = buf.append("java.lang.String@1e23"
* ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa"
* ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
* </pre>
*
* @param buffer the buffer to append to
* @param object the object to create a toString for
*/
public static void identityToString(StringBuffer buffer, Object object) {
if (object == null) {
throw new NullPointerException("Cannot get the toString of a null identity");
}
buffer.append(object.getClass().getName())
.append('@')
.append(Integer.toHexString(System.identityHashCode(object)));
}
// ToString
//-----------------------------------------------------------------------
/**
* <p>Gets the {@code toString} of an {@code Object} returning
* an empty string ("") if {@code null} input.</p>
*
* <pre>
* ObjectUtils.toString(null) = ""
* ObjectUtils.toString("") = ""
* ObjectUtils.toString("bat") = "bat"
* ObjectUtils.toString(Boolean.TRUE) = "true"
* </pre>
*
* @see String#valueOf(Object)
* @param obj the Object to {@code toString}, may be null
* @return the passed in Object's toString, or nullStr if {@code null} input
*/
public static String toString(Object obj) {
return obj == null ? "" : obj.toString();
}
/**
* <p>Gets the {@code toString} of an {@code Object} returning
* a specified text if {@code null} input.</p>
*
* <pre>
* ObjectUtils.toString(null, null) = null
* ObjectUtils.toString(null, "null") = "null"
* ObjectUtils.toString("", "null") = ""
* ObjectUtils.toString("bat", "null") = "bat"
* ObjectUtils.toString(Boolean.TRUE, "null") = "true"
* </pre>
*
* @see String#valueOf(Object)
* @param obj the Object to {@code toString}, may be null
* @param nullStr the String to return if {@code null} input, may be null
* @return the passed in Object's toString, or nullStr if {@code null} input
* @since 1.0
*/
public static String toString(Object obj, String nullStr) {
return obj == null ? nullStr : obj.toString();
}
// Comparable
//-----------------------------------------------------------------------
/**
* <p>Null safe comparison of Comparables.</p>
*
* @param <T> type of the values processed by this method
* @param values the set of comparable values, may be null
* @return
* <ul>
* <li>If any objects are non-null and unequal, the lesser object.
* <li>If all objects are non-null and equal, the first.
* <li>If any of the comparables are null, the lesser of the non-null objects.
* <li>If all the comparables are null, null is returned.
* </ul>
*/
public static <T extends Comparable<? super T>> T min(T... values) {
T result = null;
if (values != null) {
for (T value : values) {
if (compare(value, result, true) < 0) {
result = value;
}
}
}
return result;
}
/**
* <p>Null safe comparison of Comparables.</p>
*
* @param <T> type of the values processed by this method
* @param values the set of comparable values, may be null
* @return
* <ul>
* <li>If any objects are non-null and unequal, the greater object.
* <li>If all objects are non-null and equal, the first.
* <li>If any of the comparables are null, the greater of the non-null objects.
* <li>If all the comparables are null, null is returned.
* </ul>
*/
public static <T extends Comparable<? super T>> T max(T... values) {
T result = null;
if (values != null) {
for (T value : values) {
if (compare(value, result, false) > 0) {
result = value;
}
}
}
return result;
}
/**
* <p>Null safe comparison of Comparables.
* {@code null} is assumed to be less than a non-{@code null} value.</p>
*
* @param <T> type of the values processed by this method
* @param c1 the first comparable, may be null
* @param c2 the second comparable, may be null
* @return a negative value if c1 < c2, zero if c1 = c2
* and a positive value if c1 > c2
*/
public static <T extends Comparable<? super T>> int compare(T c1, T c2) {
return compare(c1, c2, false);
}
/**
* <p>Null safe comparison of Comparables.</p>
*
* @param <T> type of the values processed by this method
* @param c1 the first comparable, may be null
* @param c2 the second comparable, may be null
* @param nullGreater if true {@code null} is considered greater
* than a non-{@code null} value or if false {@code null} is
* considered less than a Non-{@code null} value
* @return a negative value if c1 < c2, zero if c1 = c2
* and a positive value if c1 > c2
* @see Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> int compare(T c1, T c2, boolean nullGreater) {
if (c1 == c2) {
return 0;
} else if (c1 == null) {
return nullGreater ? 1 : -1;
} else if (c2 == null) {
return nullGreater ? -1 : 1;
}
return c1.compareTo(c2);
}
// cloning
//-----------------------------------------------------------------------
/**
* <p>Clone an object.</p>
*
* @param <T> the type of the object
* @param obj the object to clone, null returns null
* @return the clone if the object implements {@link Cloneable} otherwise {@code null}
* @throws CloneFailedException if the object is cloneable and the clone operation fails
*/
public static <T> T clone(final T obj) {
if (obj instanceof Cloneable) {
final Object result;
if (obj.getClass().isArray()) {
final Class<?> componentType = obj.getClass().getComponentType();
if (!componentType.isPrimitive()) {
result = ((Object[]) obj).clone();
} else {
int length = Array.getLength(obj);
result = Array.newInstance(componentType, length);
System.arraycopy(obj, 0, result, 0, length);
}
} else {
try {
final Method clone = obj.getClass().getMethod("clone");
result = clone.invoke(obj);
} catch (final NoSuchMethodException e) {
throw new CloneFailedException("Cloneable type "
+ obj.getClass().getName()
+ " has no clone method", e);
} catch (final IllegalAccessException e) {
throw new CloneFailedException("Cannot clone Cloneable type "
+ obj.getClass().getName(), e);
} catch (final InvocationTargetException e) {
throw new CloneFailedException("Exception cloning Cloneable type "
+ obj.getClass().getName(), e.getCause());
}
}
@SuppressWarnings("unchecked")
final T checked = (T) result;
return checked;
}
return null;
}
/**
* <p>Clone an object if possible.</p>
*
* <p>This method is similar to {@link #clone(Object)}, but will return the provided
* instance as the return value instead of {@code null} if the instance
* is not cloneable. This is more convenient if the caller uses different
* implementations (e.g. of a service) and some of the implementations do not allow concurrent
* processing or have state. In such cases the implementation can simply provide a proper
* clone implementation and the caller's code does not have to change.</p>
*
* @param <T> the type of the object
* @param obj the object to clone, null returns null
* @return the clone if the object implements {@link Cloneable} otherwise the object itself
* @throws CloneFailedException if the object is cloneable and the clone operation fails
*/
public static <T> T cloneIfPossible(final T obj) {
final T clone = clone(obj);
return clone == null ? obj : clone;
}
// Null
//-----------------------------------------------------------------------
/**
* <p>Class used as a null placeholder where {@code null}
* has another meaning.</p>
*
* <p>For example, in a {@code HashMap} the
* {@link HashMap#get(Object)} method returns
* {@code null} if the {@code Map} contains {@code null} or if there is
* no matching key. The {@code Null} placeholder can be used to distinguish
* between these two cases.</p>
*
* <p>Another example is {@code Hashtable}, where {@code null}
* cannot be stored.</p>
*/
public static class Null implements Serializable {
/**
* Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
*
* @see Serializable
*/
private static final long serialVersionUID = 7092611880189329093L;
/**
* Restricted constructor - singleton.
*/
Null() {
super();
}
/**
* <p>Ensure singleton.</p>
*
* @return the singleton value
*/
private Object readResolve() {
return ObjectUtils.NULL;
}
}
}