All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.empire.commons.ObjectUtils Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.empire.commons;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.empire.data.ColumnExpr;
import org.apache.empire.db.expr.column.DBValueExpr;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.InvalidValueException;
import org.apache.empire.exceptions.ItemNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class contains common functions for comparing and converting values of type Object. 
 * 
 */
public final class ObjectUtils
{
    /**
     * This class explicitly defines that an Object has not been assigned a value.
* This may be used in cases where the value of null may be a valid value. */ private static final class NoValue // *Deprecated* implements Serializable { // *Deprecated* private static final long serialVersionUID = 1L; private NoValue() { /* dummy */ } @Override public String toString() { return "[NO-VALUE]"; } } /** * Constant that defines a object of type NoValue. * This may be used in cases where the value of null is a valid value. */ public static final NoValue NO_VALUE = new NoValue(); // Logger private static final Logger log = LoggerFactory.getLogger(ObjectUtils.class); private static final String DATE_FORMAT = "yyyy-MM-dd"; private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; // DateOnly Formatter private static final ThreadLocal dateOnlyFormatter = new ThreadLocal() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat(DATE_FORMAT); } }; // DateTime Formatter private static final ThreadLocal dateTimeFormatter = new ThreadLocal() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat(DATETIME_FORMAT); } }; // Interal literal for NULL private static final String NULL = "NULL"; private ObjectUtils() { // Static Function only // No instance may be created } /** * Checks whether an object has no value. * A Object is empty if and only if the Object is null or if its an empty string. * @param o the object to check * @return true if the Object is null or if its an empty string. */ public static boolean isEmpty(Object o) { if (o==null) return true; if (o==NO_VALUE) throw new InvalidValueException(o); if ((o instanceof String) && ((String)o).length()==0) return true; if ((o instanceof Object[]) && ((Object[])o).length==0) return true; if ((o instanceof Collection) && ((Collection)o).isEmpty()) return true; if (o instanceof DBValueExpr) return isEmpty(((DBValueExpr)o).getValue()); // not empty return false; } /** * Checks whether an object has a value. * A Object is considered to have a value if it is not null and not an empty string * @param o the object to check * @return true if the Object is neither null nor an empty string. */ public static boolean isNotEmpty(Object o) { return !isEmpty(o); } /** * Checks whether a number is null or zero * @param value the number to check * @return true if the value is null or zero */ public static boolean isZero(Number value) { if (value==null) return true; if (value instanceof BigDecimal) return (BigDecimal.ZERO.compareTo((BigDecimal)value) == 0); if (value instanceof Float) return (((Float) value).compareTo(0.0f)==0); if (value instanceof Double) return (((Double) value).compareTo(0.0d)==0); if (value instanceof Long) return (value.longValue()==0l); // default: check int value return (value.intValue()==0); } /** * Checks whether a number is NOT null or zero * @param value the number to check * @return true if the value is NOT null or zero */ public static boolean isNonZero(Number value) { return !isZero(value); } /** * returns the string length of an object * @param o the object to check * @return the string length of the object */ public static int lengthOf(Object o) { if (o==null || o==NO_VALUE) return 0; if ((o instanceof String)) return ((String)o).length(); // convert return o.toString().length(); } /** * Compares two objects for equality * * @param o1 the first object * @param o2 the second object * * @return true if both objects are equal or false otherwise */ @SuppressWarnings("unchecked") public static boolean compareEqual(Object o1, Object o2) { // simple case if (o1==o2) return true; // Check for Empty Values if (isEmpty(o1)) return isEmpty(o2); if (isEmpty(o2)) return isEmpty(o1); // Check classes if (o1.getClass().equals(o2.getClass())) { // Check simple array if ((o1 instanceof Object[]) && (o2 instanceof Object[])) return compareEqual((Object[])o1, (Object[])o2); // Check if object implements comparable if (o1 instanceof Comparable) return (((Comparable)o1).compareTo(o2)==0); else return o1.equals(o2); } // Classes don't match // Use equal check first if (o1.equals(o2) || o2.equals(o1)) return true; // Compare Numbers if (o1 instanceof Number && o2 instanceof Number) { // boolean test = obj1.equals(obj2); double d1 = ((Number)o1).doubleValue(); double d2 = ((Number)o2).doubleValue(); return (d1==d2); } // Compare Date with LocalDate / LocalDateTime if (o1 instanceof Temporal && o2 instanceof Date) { // swap Object tmp = o2; o2 = o1; o1 = tmp; } if (o1 instanceof Date && o2 instanceof LocalDate) return o1.equals(DateUtils.toDate((LocalDate)o2)); if (o1 instanceof Date && o2 instanceof LocalDateTime) return o1.equals(DateUtils.toDate((LocalDateTime)o2)); // Enum if (o1 instanceof Enum) { // Special enum handling if (o2 instanceof Number) return ((Enum)o1).ordinal()==((Number)o2).intValue(); // Compare Strings String strVal = StringUtils.coalesce(getString((Enum)o1), NULL); return strVal.equals(getString(o2)); } else if (o2 instanceof Enum) { // Special enum handling if (o1 instanceof Number) return ((Enum)o2).ordinal()==((Number)o1).intValue(); // Compare Strings String strVal = StringUtils.coalesce(getString((Enum)o2), NULL); return strVal.equals(getString(o1)); } // Compare Strings if (o1 instanceof String) return ((String)o1).equals(o2.toString()); if (o2 instanceof String) return ((String)o2).equals(o1.toString()); // Not equal return false; } /** * Compares two arrays for equality * * @param array1 the first array * @param array2 the second array * * @return true if both arrays are equal or false otherwise */ public static boolean compareEqual(Object[] array1, Object[] array2) { // Compare Length int len1 = (array1!=null ? array1.length : 0); int len2 = (array2!=null ? array2.length : 0); if (len1!= len2) return false; // Compare Key Values for (int i = 0; i < len1; i++) { // Check String Values if (!ObjectUtils.compareEqual(array1[i], array2[i])) return false; } return true; } /** * Compares two ColumnExpr for equality * * @param expr a column expression * @param other a column expression * * @return true if both expressions are equal or false otherwise */ public static boolean compareEqual(ColumnExpr expr, ColumnExpr other) { if (isWrapper(other) && !isWrapper(expr)) return expr.equals(unwrap(other)); else if (!isWrapper(other) && isWrapper(expr)) return unwrap(expr).equals(other); // both wrapped or both unwrapped return expr.equals(other); } /** * Compares two objects for equality * * @param o1 the first object * @param o2 the second object * * @return true if both objects are equal or false otherwise */ @SuppressWarnings("unchecked") public static int compare(Object o1, Object o2) { // simple case if (o1==o2) return 0; // Check for Empty Values if (isEmpty(o1)) return isEmpty(o2) ? 0 : -1; if (isEmpty(o2)) return isEmpty(o1) ? 0 : 1; // Check classes if (o1.getClass().equals(o2.getClass())) { // Check if object implements comparable if (o1 instanceof Comparable) return ((Comparable)o1).compareTo(o2); if (o2 instanceof Comparable) return ((Comparable)o2).compareTo(o1); } // Use equal check first if (o1.equals(o2) || o2.equals(o1)) return 0; // Compare Numbers if (o1 instanceof Number && o2 instanceof Number) { // boolean test = obj1.equals(obj2); double d1 = ((Number)o1).doubleValue(); double d2 = ((Number)o2).doubleValue(); return ((d1d2) ? 1 : 0)); } // Compare Date with LocalDate / LocalDateTime if (o1 instanceof Temporal && o2 instanceof Date) { // swap Object tmp = o2; o2 = o1; o1 = tmp; } if (o1 instanceof Date && o2 instanceof LocalDate) return compare(o1, DateUtils.toDate((LocalDate)o2)); if (o1 instanceof Date && o2 instanceof LocalDateTime) return compare(o1, DateUtils.toDate((LocalDateTime)o2)); // Compare Strings return o1.toString().compareTo(o2.toString()); } /** * Checks whether a preferred value is valid and returns an alternative value if not. * @param the type of the values * @param preferred the preferred return value * @param alternative the alternative return value used if the preferred value is null * @return the preferred value if it is not null or the alternative value otherwise */ public static T coalesce(T preferred, T alternative) { return (preferred!=null ? preferred : alternative); } /** * converts an object to an integer. If conversion is not possible, an error is thrown * @param v the value to convert * @return the integer value */ public static int toInteger(Object v) { if (ObjectUtils.isEmpty(v)) return 0; if (v instanceof Number) return ((Number)v).intValue(); // Try to convert String str = v.toString(); return Integer.parseInt(str); } /** * Converts an object value to an integer. *

* If the object value supplied is null or if conversion is not possible then the default value is returned. * @param v the obect to convert * @param defValue the default value if o is null or conversion is not possible * @return the Integer value of o or a default value */ public static int getInteger(Object v, int defValue) { // Check empty if (ObjectUtils.isEmpty(v)) return defValue; try { // Try to convert return toInteger(v); } catch (NumberFormatException e) { log.error(String.format("Cannot convert value [%s] to int", v)); return defValue; } } /** * Converts an object value to an integer. *

* If the object value supplied is null or if conversion is not possible then 0 is returned. * @param v the object value to convert * @return the Integer value of o or 0 */ public static int getInteger(Object v) { return getInteger(v, 0); } /** * converts an object to a long. If conversion is not possible, an error is thrown * @param v the value to convert * @return the long value */ public static long toLong(Object v) { if (ObjectUtils.isEmpty(v)) return 0; if (v instanceof Number) return ((Number)v).longValue(); // Try to convert String str = v.toString(); return Long.parseLong(str); } /** * Converts an object value to a long. *

* If the object value supplied is null or if conversion is not possible then the default value is returned. * @param v the obect to convert * @param defValue the default value if o is null or conversion is not possible * @return the Integer value of o or a default value */ public static long getLong(Object v, long defValue) { // Check empty if (ObjectUtils.isEmpty(v)) return defValue; try { // Try to convert return toLong(v); } catch (NumberFormatException e) { log.error(String.format("Cannot convert value [%s] to long", v)); return defValue; } } /** * Converts an object value to a long. *

* If the object value supplied is null or if conversion is not possible then 0 is returned. * @param v the object value to convert * @return the Long value of o or 0 */ public static long getLong(Object v) { return getLong(v, 0); } /** * converts an object to a double. If conversion is not possible, an error is thrown * @param v the value to convert * @return the double value */ public static double toDouble(Object v) { // Get Double value if (ObjectUtils.isEmpty(v)) return 0.0; if (v instanceof Number) return ((Number)v).doubleValue(); // parse String for Integer value String val = v.toString(); return Double.parseDouble(val); } /** * Converts an object value to a double. *

* If the object value supplied is null or if conversion is not possible then defValue is returned. * @param v the object value to convert * @param defValue the default value * @return the Long value of o or defValue */ public static double getDouble(Object v, double defValue) { // Check empty if (ObjectUtils.isEmpty(v)) return defValue; try { // Try to convert return toDouble(v); } catch (NumberFormatException e) { log.error(String.format("Cannot convert value [%s] to double", v)); return defValue; } } /** * Converts an object value to a double. *

* If the object value supplied is null or if conversion is not possible then 0.0 is returned. * @param v the object value to convert * @return the Long value of o or 0 */ public static double getDouble(Object v) { return getDouble(v, 0.0); } /** * converts an object to a decimal. If conversion is not possible, an error is thrown * @param v the value to convert * @return the decimal value */ public static BigDecimal toDecimal(Object v) { // Get Double value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof BigDecimal) return ((BigDecimal)v); // Find a suitable converter if (v instanceof Number) { // check other number types if (v instanceof BigInteger) return new BigDecimal((BigInteger)v); if (v instanceof Integer) return BigDecimal.valueOf(((Number)v).intValue()); if (v instanceof Long) return BigDecimal.valueOf(((Number)v).longValue()); // Default: convert via double return BigDecimal.valueOf(((Number)v).doubleValue()); } // parse String for Integer value // Last-Chance > Try a string conversion return new BigDecimal(v.toString()); } /** * Converts an object value to a BigDecimal. *

* If the object value supplied is null or if conversion is not possible then defValue is returned. * @param v the object value to convert * @param defValue the default value * @return the BigDecimal value of v or defValue */ public static BigDecimal getDecimal(Object v, BigDecimal defValue) { // Check empty if (ObjectUtils.isEmpty(v)) return defValue; try { // Try to convert return toDecimal(v); } catch (NumberFormatException e) { log.error(String.format("Cannot convert value [%s] to BigDecimal", v)); return defValue; } } /** * Converts an object value to a BigDecimal. *

* If the object value supplied is null or if conversion is not possible then 0.0 is returned. * @param v the object value to convert * @return the Long value of o or 0 */ public static BigDecimal getDecimal(Object v) { return getDecimal(v, BigDecimal.ZERO); } /** * Converts an object value to a boolean. *

* If the object value supplied is empty then the defValue is returned * Numbers are considered true if they are not equal to zero * String are considered true only if the string is "Y" or "true" * @param v the object to convert * @param defValue the default value * @return the boolean value or defValue if v is null or empty */ public static boolean getBoolean(Object v, boolean defValue) { // Get Boolean value if (ObjectUtils.isEmpty(v)) return defValue; if (v instanceof Boolean) return ((Boolean)v).booleanValue(); if (v instanceof Number) return (((Number)v).intValue()!=0); if (v instanceof String) { String val = ((String)v); if (StringUtils.isEmpty(val)) return defValue; // check for allowed true values return (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("Y")); } return defValue; } /** * Converts an object value to a boolean. * see getBoolean(Object v, boolean defValue) for details. * @param v the object to convert * @return the boolean value or false if v is null or empty */ public static boolean getBoolean(Object v) { return getBoolean(v, false); } /** * Converts an object to an enum of the given type * @param the type of the enum * @param enumType the enum type * @param value the value to convert * @return the enum */ @SuppressWarnings("unchecked") public static > T getEnum(Class enumType, Object value) { // check for null if (isEmpty(value)) return null; // check enum if (value instanceof Enum) { // already an enum: Check type if (value.getClass().equals(enumType)) return (T)value; // try to match names value = ((Enum)value).name(); } // check column data type boolean numeric = (value instanceof Number); T[] items = enumType.getEnumConstants(); if (items.length>0 && (items[0] instanceof EnumValue)) { // custom conversion for (T e : items) { Object eVal = ((EnumValue)e).toValue(numeric); if (ObjectUtils.compareEqual(eVal, value)) return e; } // error: not found throw new ItemNotFoundException(StringUtils.toString(value)); } else if (numeric) { // by ordinal int ordinal = ((Number)value).intValue(); // check range if (ordinal<0 || ordinal>=items.length) throw new ItemNotFoundException(String.valueOf(ordinal)); // return enum return items[ordinal]; } else { // by name String name = StringUtils.toString(value); // find name for (T e : items) if (e.name().equals(name)) return e; // error: not found throw new ItemNotFoundException(name); } } /** * find by name * @param the type of the enum * @param enumType the enum type * @param name the enum name * @return the enum */ public static > T getEnumByName(Class enumType, String name) { // check for null if (isEmpty(name)) return null; // check column data type T[] items = enumType.getEnumConstants(); for (T e : items) if (e.name().equals(name)) return e; // error: not found throw new ItemNotFoundException(name); } /** * Convert Enum to Object * @param enumValue the enum * @param isNumeric flag if number or string is required * @return the number or string representing this enum */ public static Object getEnumValue(Enum enumValue, boolean isNumeric) { // convert if (enumValue instanceof EnumValue) return ((EnumValue)enumValue).toValue(isNumeric); // default return (isNumeric ? enumValue.ordinal() : getString(enumValue)); } /** * Converts an Enum to a String * @param enumValue the enum * @return the corresponding string value */ public static String getString(Enum enumValue) { // convert if (enumValue instanceof EnumValue) return StringUtils.toString(((EnumValue)enumValue).toValue(false)); /* special case */ if (enumValue==null || enumValue.name().equals(NULL)) return null; /* use name */ return enumValue.name(); } /** * Converts an Object to a String * @param value the value to convert * @return the corresponding string value */ public static String getString(Object value) { if (value==null) return null; if (value instanceof String) return (String)value; if (value==NO_VALUE) throw new InvalidValueException(value); // convert if (value instanceof Enum) return getString((Enum)value); if (value instanceof Date) return formatDate((Date)value, true); // default return value.toString(); } /** * Converts an object value to a Date. *

* @param v the object to convert * @return the Date value of o or null * @throws ParseException */ public static Date toDate(Object v) throws ParseException { // Get DateTime value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof java.util.Date) return ((java.util.Date)v); if (v instanceof java.time.LocalDate) return DateUtils.toDate((LocalDate)v); if (v instanceof java.time.LocalDateTime) return DateUtils.toDate((LocalDateTime)v); // Convert from String String str = v.toString(); if (str.length() > 10) return dateTimeFormatter.get().parse(str); else return dateOnlyFormatter.get().parse(str); } /** * Converts an object value to a Date. *

* If the object value supplied is null or if conversion is not possible then null is returned. * @param v the object to convert * @param locale the locale used for conversion * @return the Date value of o or null */ public static Date getDate(Object v, Locale locale) { // Get DateTime value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof Date) return ((Date)v); if (v instanceof java.time.LocalDate) return DateUtils.toDate((LocalDate)v); if (v instanceof java.time.LocalDateTime) return DateUtils.toDate((LocalDateTime)v); // Get Calendar if (v instanceof Number) { // Get Date from a number long l = ((Number)v).longValue(); if (l==0) return DateUtils.getDateNow(); // Year or full date/time? /* if (l<10000) { // Year only Calendar calendar = Calendar.getInstance(getSafeLocale(locale)); calendar.set((int)l, 1, 1); return calendar.getTime(); } */ // Date from long return new Date(l); } // Try to parse return DateUtils.parseDate(v.toString(), locale); } /** * Converts an object value to a Date. *

* @param v the object to convert * @return the Date value of o or null */ public static Date getDate(Object v) { // Get DateTime value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof java.util.Date) return ((java.util.Date)v); if (v instanceof java.time.LocalDate) return DateUtils.toDate((LocalDate)v); if (v instanceof java.time.LocalDateTime) return DateUtils.toDate((LocalDateTime)v); // Convert from String String str = v.toString(); try { if (str.length() > 10) return dateTimeFormatter.get().parse(str); else return dateOnlyFormatter.get().parse(str); } catch (ParseException e) { log.error(String.format("Cannot convert value [%s] to Date", str), e); return null; } } /** * Converts an object value to a Date. *

* @param v the object to convert * @return the Date value of o or null */ public static LocalDate getLocalDate(Object v) { // Get DateTime value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof java.time.LocalDate) return (LocalDate)v; if (v instanceof java.time.LocalDateTime) return ((LocalDateTime)v).toLocalDate(); if (v instanceof java.sql.Timestamp) return ((java.sql.Timestamp)v).toLocalDateTime().toLocalDate(); if (v instanceof java.sql.Date) return ((java.sql.Date)v).toLocalDate(); if (v instanceof java.util.Date) return DateUtils.toLocalDate((Date)v); // Convert from String String str = v.toString(); try { // DateTimeFormatter ISO_LOCAL_DATE return LocalDate.parse(str); } catch (DateTimeParseException e) { log.error(String.format("Cannot convert value [%s] to LocalDate", str), e); return null; } } /** * Converts an object value to a Date. *

* @param v the object to convert * @return the Date value of o or null */ public static LocalDateTime getLocalDateTime(Object v) { // Get DateTime value if (ObjectUtils.isEmpty(v)) return null; if (v instanceof java.time.LocalDate) return ((LocalDate)v).atStartOfDay(); if (v instanceof java.time.LocalDateTime) return (LocalDateTime)v; if (v instanceof java.sql.Timestamp) return ((java.sql.Timestamp)v).toLocalDateTime(); if (v instanceof java.sql.Date) return ((java.sql.Date)v).toLocalDate().atStartOfDay(); if (v instanceof java.util.Date) return DateUtils.toLocalDateTime((Date)v); // Convert from String String str = v.toString(); try { // DateTimeFormatter.ISO_LOCAL_DATE_TIME return LocalDateTime.parse(str); } catch (DateTimeParseException e) { log.error(String.format("Cannot convert value [%s] to LocalDateTime", str), e); return null; } } /** * Formats a given date object to a standard ISO date string. * The format is "yyyy-MM-dd hh:mm:ss" * * @param date the date to be formated * @param withTime indicates whether the date string should include the time or not * @return the date string */ public static String formatDate(Date date, boolean withTime) { if (date==null) return null; if (withTime) return dateTimeFormatter.get().format(date); else return dateOnlyFormatter.get().format(date); } /** * Generic conversion function that will convert a object to another value type. * * @param the type to convert to * @param c the class type to convert to * @param v the object to convert * * @return the Date value of o or null * * @throws ClassCastException if the object is not null and is not assignable to the type T. */ @SuppressWarnings("unchecked") public static T convert(Class c, Object v) throws ClassCastException { if (v==null || c.isInstance(v)) return (T)v; if (v==NO_VALUE) throw new InvalidValueException(v); // Get Class form Primitive Type if (c.isPrimitive()) { // Get's the Java Class representing the primitive type c = (Class) MethodUtils.getPrimitiveWrapper(c); } // Convert if (c.isEnum()) { // convert to enum Object ev = getEnum((Class>)c, v); return (T)ev; } if (c.isAssignableFrom(Boolean.class)) return c.cast(getBoolean(v)); if (c.isAssignableFrom(Integer.class)) return c.cast(getInteger(v)); if (c.isAssignableFrom(Long.class)) return c.cast(getLong(v)); if(c.isAssignableFrom(Double.class)) return c.cast(getDouble(v)); if(c.isAssignableFrom(BigDecimal.class)) return c.cast(getDecimal(v)); if (c.isAssignableFrom(String.class)) return c.cast(v.toString()); // other return c.cast(v); } /** * Checks if a class is assignment compatible with another class * @param target the target class * @param source the source class * @return true if assignment compatible or false otherwise */ public static boolean isAssignmentCompatible(Class target, Class source) { // try plain assignment if (target.isAssignableFrom(source)) return true; // Get Class form Primitive Type if (source.isPrimitive()) { // Get's the Java Class representing the primitive type source = MethodUtils.getPrimitiveWrapper(source); if (source == null) return false; if (target.isAssignableFrom(source)) return true; } // Get Class form Primitive Type if (target.isPrimitive()) { // Get's the Java Class representing the primitive type target = MethodUtils.getPrimitiveWrapper(target); if (target == null) return false; if (target.isAssignableFrom(source)) return true; } // Assume all numeric types can be converted to target class Class numberClass = Number.class; if (numberClass.isAssignableFrom(target) && numberClass.isAssignableFrom(source)) { // Both are numeric return true; } // Special case: Allow character to string assignment if (source==Character.class && target==String.class) { return true; } // Not compatible return false; } /** * Generic conversion function that will convert a list to another list type. * * @param the type of elements * @param t the type class * @param source the source collection * * @return the new list type */ public static List convert(Class t, Collection source) { if (source==null) return null; List target = new ArrayList(source.size()); target.addAll(source); return target; } /** * Converts varArgs to an array * * @param the type of elements * @param t the type of the array * @param values the array values * * @return the array */ @SafeVarargs public static T[] toArray(Class t, T... values) { if (values.length==0) throw new InvalidArgumentException("values", values); return values; } /** * Converts an array to a list * * @param the type of elements * @param t the type of the list items * @param array the array to be converted * * @return the list */ public static List arrayToList(Class t, T[] array) { if (array==null) return null; List list = new ArrayList(array.length); for (int i=0; i)) && ((Unwrappable)object).isWrapper(); } /** * Unwraps an object implementing the Unwrappable interface * If the object does not Implement the Interface or is not a wrapper then the object itself is returned * @param the type of the object * @param object the object to unwrap * @return the unwrapped object or the object itself */ @SuppressWarnings("unchecked") public static T unwrap(T object) { if ((object instanceof Unwrappable) && ((Unwrappable)object).isWrapper()) { // recursive return unwrap(((Unwrappable)object).unwrap()); } return object; } /** * returns whether or not a array contains a certain item * performs a simple (==) comparison (fast) * * @param the type of the object * @param array the array to search * @param item the item to search for * * @return true if the array contains the item or false otherwise */ @SuppressWarnings("unchecked") public static int indexOf(T[] array, T item) { if (array==null) return -1; // 1st try (quick) for (int i=0; i)array[i]).isWrapper()) { // unwrap Object unwrapped = ((Unwrappable)array[i]).unwrap(); if (unwrapped==item || unwrapped.equals(item)) return i; } } // 3rd try (unwrap) if ((item instanceof Unwrappable) && ((Unwrappable)item).isWrapper()) { // unwrap return indexOf(array, ((Unwrappable)item).unwrap()); } // not found return -1; } /** * returns whether or not a array contains a certain item * performs a simple (==) comparison (fast) * * @param the type of elements * @param array the array to search * @param item the item to search for * * @return true if the array contains the item or false otherwise */ public static boolean contains(T[] array, T item) { return (indexOf(array, item)>=0); } /** * combines two arrays * @param the type of the array items * @param left the left array * @param right the right array * @return the combined array */ public static T[] combine(T[] left, T[] right) { if (left==null || left.length==0) return right; if (right==null || right.length==0) return left; // combine both T[] result = Arrays.copyOf(left, left.length + right.length); System.arraycopy(right, 0, result, left.length, right.length); return result; } }