/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.utils;
import java.lang.reflect.Method;
import java.util.Comparator;
/**
* INTERNAL: Class that contains useful methods.
*/
public class ObjectUtils {
private ObjectUtils() {
}
/**
* INTERNAL: Returns true if the two objects are different. The
* method handle null values without throwing a
* NullPointerException. Null equals null.
*/
public static boolean different(Object o1, Object o2) {
return !(o1 == null ? o2 == null : o1.equals(o2));
}
/**
* INTERNAL: Returns true if the two objects are equals. The method
* handle null values without throwing a NullPointerException. Null
* equals null.
*/
public static boolean equals(Object o1, Object o2) {
return (o1 == null ? o2 == null : o1.equals(o2));
}
/**
* INTERNAL: Compares two int values.
*/
public static int compare(int i1, int i2) {
return (i1 > i2 ? 1 : (i2 > i1 ? -1 : 0));
}
/**
* INTERNAL: Compares two double values. Note that this method is
* included in Java 1.4, but we've included it here because we have
* to support Java 1.3.
*/
public static int compare(double d1, double d2) {
if (d1 < d2) return -1;
if (d1 > d2) return 1;
long d1Bits = Double.doubleToLongBits(d1);
long d2Bits = Double.doubleToLongBits(d2);
return (d1Bits == d2Bits ? 0 : (d1Bits < d2Bits ? -1 : 1));
}
/**
* INTERNAL: Compares two string or null values in a consistent way
* ignoring the case. Will not throw a NullPointerException if any
* of the arguments are null.
*
* @since 3.4
*/
public static int compareIgnoreCase(String s1, String s2) {
if (s1 == null)
return (s2 == null ? 0 : -1);
else if (s2 == null)
return 1;
else
return s1.compareToIgnoreCase(s2);
}
/**
* INTERNAL: Compares two objects or null values in a consistent
* way. Will not throw a NullPointerException if any of the
* arguments are null.
*
* @since 3.4
*/
public static int compare(Comparable o1, Comparable o2) {
if (o1 == null)
return (o2 == null ? 0 : -1);
else if (o2 == null)
return 1;
else
return o1.compareTo(o2);
}
/**
* INTERNAL: Compares two objects or null values in a consistent way
* using the given comparator. Will not throw a NullPointerException
* if any of the arguments are null.
*
* @since 3.4
*/
public static int compare(Object o1, Object o2, Comparator c) {
if (o1 == null)
return (o2 == null ? 0 : -1);
else if (o2 == null)
return 1;
else
return c.compare(o1, o2);
}
/**
* INTERNAL: Get bean property value from object.
*/
public static Object getProperty(Object bean, String propertyName) {
try {
// Lookup getter method
String methodName = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Method method = bean.getClass().getMethod(methodName, new Class[] {});
// Invoke getter method
return method.invoke(bean, new Object[] {});
}
catch (Exception e) {
throw new OntopiaRuntimeException(e);
}
}
/**
* INTERNAL: Get bean property value from object. Returns null if property does not exist or fails.
*/
public static Object getProperty(Object bean, String propertyName, Object _default) {
try {
// Lookup getter method
String methodName = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Method method = bean.getClass().getMethod(methodName, new Class[] {});
// Invoke getter method
return method.invoke(bean, new Object[] {});
} catch (Exception e) {
return _default;
}
}
/**
* INTERNAL: Returns boolean value if Boolean object. If not returns false.
*/
public static boolean isTrue(Object value) {
if (value instanceof Boolean)
return ((Boolean)value).booleanValue();
else
return false;
}
/**
* INTERNAL: Casts string to int value, returns default if it fails.
*/
public static int toInteger(String value, int _default) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return _default;
}
}
/**
* INTERNAL: Create new instance of given class. Class must have a
* default constructor.
*/
public static Object newInstance(String className) {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class klass = Class.forName(className, true, classLoader);
return klass.newInstance();
}
catch (Exception e) {
throw new OntopiaRuntimeException(e);
}
}
/**
* INTERNAL: Extract real exception from wrapper exception.
*/
public static Throwable getRealCause(Throwable t) {
Throwable cause;
if (t instanceof OntopiaRuntimeException)
cause = ((OntopiaRuntimeException)t).getCause();
else if (t instanceof org.xml.sax.SAXException)
cause = ((org.xml.sax.SAXException)t).getException();
else
cause = null; // may want to support 1.4 getCause method
if (cause != null)
return getRealCause(cause);
else
return t;
}
/**
* INTERNAL: Extract real exception from wrapper exception and
* rethrow as a RuntimeException.
*/
public static void throwRuntimeException(Throwable t) {
Throwable x = getRealCause(t);
if (x instanceof RuntimeException)
throw ((RuntimeException)x);
else
throw new OntopiaRuntimeException(x);
}
/* --- Dual arrays: insertion sort */
public static void sortParallel(Object[] x, Object[] y, Comparator c) {
// Sorts x and shifts the items in y accordingly
sortParallel(x, 0, x.length, y, 0, c);
}
private static void sortParallel(Object[] x, int xoff, int xlen, Object[] y, int yoff, Comparator c) {
// Insertion sort; fast when arrays are small.
int yrel = xoff-yoff;
for (int i=xoff; i < xlen+xoff; i++) {
for (int j=i; j > xoff && c.compare(x[j-1], x[j]) > 0; j--) {
swapParallel(x, y, j, j-1, yrel);
}
}
}
private static void swapParallel(Object[] x, Object[] y, int a, int b, int yrel) {
// Swaps x[a] with x[b] and y[a] with y[b].
Object tx = x[a], ty = y[a+yrel];
x[a] = x[b]; y[a+yrel] = y[b+yrel];
x[b] = tx; y[b+yrel] = ty;
}
/**
* INTERNAL: Compare array size, then each element in sequence using
* a comparator.
*/
public static int compareArrays(Object[] a1, Object[] a2, Comparator c) {
int r = compare(a1.length, a2.length);
if (r != 0) return r;
for (int i=0; i < a1.length; i++) {
r = c.compare(a1[i], a2[i]);
if (r != 0) return r;
}
return 0;
}
public static String toString(Object o) {
return (o == null ? "null" : o.toString());
}
}