package er.extensions.foundation;
import java.math.BigDecimal;
import java.util.ArrayList;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSData;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSMutableData;
import com.webobjects.foundation.NSPropertyListSerialization;
import com.webobjects.foundation.NSRange;
import com.webobjects.foundation.NSSet;
/**
* ERXValueUtilities has useful conversion methods for
* reading and transforming <code>boolean</code>,
* <code>int</code> and <code>float</code>values.
* Unless otherwise stated, when an empty string
* (or one containing only whitespace) is given, then
* the string is assumed to be null. This is because
* D2W is not able to give back null values anymore.
*
* @author ak on Mon Oct 28 2002
*/
public class ERXValueUtilities {
/**
* Returns whether or not the given object is null or NSKVC.Null.
*
* @param obj the object to check
* @return true if the object is null or NSKVC.Null
*/
public static boolean isNull(Object obj) {
return obj == null || obj == NSKeyValueCoding.NullValue || obj instanceof NSKeyValueCoding.Null;
}
/**
* Basic utility method for determining if an object represents either a
* true or false value. The current implementation tests if the object is an
* instance of a String or a Number. Numbers are false if they equal
* <code>0</code>, Strings are false if they equal (case insensitive) 'no',
* 'false' or parse to 0.
*
* @param obj
* object to be evaluated
* @return boolean evaluation of the given object
*
*/
public static boolean booleanValue(Object obj) {
return ERXValueUtilities.booleanValueWithDefault(obj, false);
}
/**
* Basic utility method for determining if an object represents either a
* true or false value. The current implementation tests if the object is an
* instance of a <code>String</code>, or a <code>Number</code>. Numbers are
* false if they equal <code>0</code>, Strings are false if they equal (case
* insensitive) 'no', 'false' or parse to 0. The default value is used if
* the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return boolean evaluation of the given object
*
*/
public static boolean booleanValueWithDefault(Object obj, boolean def) {
return ERXValueUtilities.isNull(obj) ? def : BooleanValueWithDefault(obj, Boolean.valueOf(def));
}
/**
* Basic utility method for determining if an object represents either a
* true or false value. The current implementation tests if the object is an
* instance of a <code>String</code>, or a <code>Number</code>. Numbers are
* false if they equal <code>0</code>, Strings are false if they equal (case
* insensitive) 'no', 'false' or parse to 0. The default value is used if
* the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return boolean evaluation of the given object
*
*/
public static Boolean BooleanValueWithDefault(Object obj, Boolean def) {
Boolean flag = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof Number) {
if (((Number) obj).intValue() == 0) {
flag = Boolean.FALSE;
} else {
flag = Boolean.TRUE;
}
} else if (obj instanceof String) {
String strValue = ((String) obj).trim();
if (strValue.length() > 0) {
if (strValue.equalsIgnoreCase("no") || strValue.equalsIgnoreCase("false") || strValue.equalsIgnoreCase("n")) {
flag = Boolean.FALSE;
} else if (strValue.equalsIgnoreCase("yes") || strValue.equalsIgnoreCase("true") || strValue.equalsIgnoreCase("y")) {
flag = Boolean.TRUE;
} else {
try {
if (Integer.parseInt(strValue) == 0) {
flag = Boolean.FALSE;
} else {
flag = Boolean.TRUE;
}
} catch (NumberFormatException numberformatexception) {
throw new IllegalArgumentException("Failed to parse a boolean from the value '" + strValue + "'.");
}
}
}
} else if (obj instanceof Boolean) {
flag = (Boolean) obj;
// MS: Nothing actually implements BooleanOperation ...
} else if( obj instanceof ERXUtilities.BooleanOperation ) {
flag = ((ERXUtilities.BooleanOperation) obj ).value();
} else {
throw new IllegalArgumentException("Failed to parse a boolean from the value '" + obj + "'.");
}
}
return flag;
}
/**
* Basic utility method for reading int values. The current implementation
* uses {@link #intValueWithDefault(Object, int)} with a default of
* <code>0</code>.
*
* @param obj
* object to be evaluated
* @return integer evaluation of the given object
*
*/
public static int intValue(Object obj) {
return ERXValueUtilities.intValueWithDefault(obj, 0);
}
/**
* Basic utility method for reading <code>int</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return integer evaluation of the given object
*
*/
public static int intValueWithDefault(Object obj, int def) {
return ERXValueUtilities.isNull(obj) ? def : IntegerValueWithDefault(obj, Integer.valueOf(def));
}
/**
* Basic utility method for reading <code>Integer</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return Integer evaluation of the given object
*
*/
public static Integer IntegerValueWithDefault(Object obj, Integer def) {
Integer value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof Integer) {
value = ((Integer) obj).intValue();
} else if (obj instanceof Number) {
value = Integer.valueOf(((Number) obj).intValue());
} else if (obj instanceof String) {
try {
String strValue = ((String) obj).trim(); // Need to trim
// trailing
// space
if (strValue.length() > 0) {
value = Integer.valueOf(strValue);
}
} catch (NumberFormatException numberformatexception) {
throw new IllegalArgumentException("Failed to parse an integer from the value '" + obj + "'.", numberformatexception);
}
} else if (obj instanceof Boolean) {
value = ((Boolean) obj).booleanValue() ? Integer.valueOf(1) : def;
}
} else {
value = def;
}
return value;
}
/**
* Basic utility method for reading float values. The current implementation
* uses {@link #floatValueWithDefault(Object, float)} with a default of
* <code>0</code>.
*
* @param obj
* object to be evaluated
* @return float evaluation of the given object
*
*/
public static float floatValue(Object obj) {
return ERXValueUtilities.floatValueWithDefault(obj, 0);
}
/**
* Basic utility method for reading <code>float</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return float evaluation of the given object
*
*/
public static float floatValueWithDefault(Object obj, float def) {
return ERXValueUtilities.isNull(obj) ? def : FloatValueWithDefault(obj, Float.valueOf(def));
}
/**
* Basic utility method for reading <code>Float</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return Float evaluation of the given object
*
*/
public static Float FloatValueWithDefault(Object obj, Float def) {
Float value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof Float) {
value = (Float) obj;
} else if (obj instanceof Number) {
value = Float.valueOf(((Number) obj).floatValue());
} else if (obj instanceof String) {
try {
String strValue = ((String) obj).trim(); // Need to trim
// trailing
// space
if (strValue.length() > 0) {
value = Float.valueOf(strValue);
}
} catch (NumberFormatException numberformatexception) {
throw new IllegalArgumentException("Failed to parse a float from the value '" + obj + "'.", numberformatexception);
}
} else if (obj instanceof Boolean) {
value = ((Boolean) obj).booleanValue() ? Float.valueOf(1.0f) : def;
}
} else {
value = def;
}
return value;
}
/**
* Basic utility method for reading double values. The current
* implementation uses {@link #doubleValueWithDefault(Object, double)} with
* a default of <code>0</code>.
*
* @param obj
* object to be evaluated
* @return double evaluation of the given object
*
*/
public static double doubleValue(Object obj) {
return ERXValueUtilities.doubleValueWithDefault(obj, 0);
}
/**
* Basic utility method for reading <code>double</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return double evaluation of the given object
*
*/
public static double doubleValueWithDefault(Object obj, double def) {
return ERXValueUtilities.isNull(obj) ? def : DoubleValueWithDefault(obj, Double.valueOf(def));
}
/**
* Basic utility method for reading <code>Double</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return Double evaluation of the given object
*
*/
public static Double DoubleValueWithDefault(Object obj, Double def) {
Double value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof Double) {
value = (Double) obj;
} else if (obj instanceof Number) {
value = Double.valueOf(((Number) obj).doubleValue());
} else if (obj instanceof String) {
try {
String strValue = ((String) obj).trim(); // Need to trim
// trailing
// space
if (strValue.length() > 0) {
value = Double.valueOf(strValue);
}
} catch (NumberFormatException numberformatexception) {
throw new IllegalArgumentException("Failed to parse a double from the value '" + obj + "'.", numberformatexception);
}
} else if (obj instanceof Boolean) {
value = ((Boolean) obj).booleanValue() ? Double.valueOf(1.0) : def;
}
} else {
value = def;
}
return value;
}
/**
* Basic utility method for reading long values. The current implementation
* uses {@link #longValueWithDefault(Object, long)} with a default of
* <code>0</code>.
*
* @param obj
* object to be evaluated
* @return long evaluation of the given object
*
*/
public static long longValue(Object obj) {
return ERXValueUtilities.longValueWithDefault(obj, 0);
}
/**
* Basic utility method for reading <code>long</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return long evaluation of the given object
*
*/
public static long longValueWithDefault(Object obj, long def) {
return ERXValueUtilities.isNull(obj) ? def : LongValueWithDefault(obj, Long.valueOf(def));
}
/**
* Basic utility method for reading <code>Long</code> values. The current
* implementation tests if the object is an instance of a String, Number and
* Boolean. Booleans are 1 if they equal <code>true</code>. The default
* value is used if the object is null or the boolean value is false.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return Long evaluation of the given object
*
*/
public static Long LongValueWithDefault(Object obj, Long def) {
Long value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof Long) {
value = (Long) obj;
} else if (obj instanceof Number) {
value = Long.valueOf(((Number) obj).longValue());
} else if (obj instanceof String) {
try {
String strValue = ((String) obj).trim(); // Need to trim
// trailing
// space
if (strValue.length() > 0) {
value = Long.valueOf(strValue);
}
} catch (NumberFormatException numberformatexception) {
throw new IllegalArgumentException("Failed to parse a long from the value '" + obj + "'.", numberformatexception);
}
} else if (obj instanceof Boolean) {
value = ((Boolean) obj).booleanValue() ? Long.valueOf(1L) : def;
}
} else {
value = def;
}
return value;
}
/**
* Basic utility method for reading NSArray values which works also with
* Strings. The current implementation uses
* {@link #arrayValueWithDefault(Object, NSArray)} with a default of
* <code>null</code>.
*
* @param obj
* object to be evaluated
* @return NSArray evaluation of the given object
*
*/
public static NSArray arrayValue(Object obj) {
return ERXValueUtilities.arrayValueWithDefault(obj, null);
}
/**
* Basic utility method for reading <code>NSArray</code> values which also
* works with serialized NSArrays and comma separated items. The default
* value is used if the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return NSArray evaluation of the given object
*
*/
public static NSArray arrayValueWithDefault(Object obj, NSArray def) {
NSArray value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof NSArray) {
value = (NSArray) obj;
} else if (obj instanceof String) {
String strValue = ((String) obj).trim();
if (strValue.length() > 0) {
if (strValue.charAt(0) != '(') {
strValue = "(" + strValue + ")";
}
value = (NSArray) NSPropertyListSerialization.propertyListFromString(strValue);
if (value == null) {
throw new IllegalArgumentException("Failed to parse an array from the value '" + obj + "'.");
}
}
} else {
throw new IllegalArgumentException("Failed to parse an array from the value '" + obj + "'.");
}
}
return value;
}
/**
* Basic utility method for reading NSSet values which works also with
* Strings. The current implementation uses
* {@link #setValueWithDefault(Object, NSSet)} with a default of
* <code>null</code>.
*
* @param obj
* object to be evaluated
* @return NSSet evaluation of the given object
*
*/
public static NSSet setValue(Object obj) {
return ERXValueUtilities.setValueWithDefault(obj, null);
}
/**
* Basic utility method for reading <code>NSSet</code> values which also
* works with serialized NSSets and comma separated items. The default value
* is used if the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return NSSet evaluation of the given object
*
*/
public static NSSet setValueWithDefault(Object obj, NSSet def) {
NSSet value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof NSSet) {
value = (NSSet) obj;
} else if (obj instanceof NSArray) {
value = new NSSet((NSArray) obj);
} else if (obj instanceof String) {
NSArray array = arrayValueWithDefault(obj, null);
if (array != null) {
value = new NSSet(array);
}
} else {
throw new IllegalArgumentException("Failed to parse a set from the value '" + obj + "'.");
}
}
return value;
}
/**
* Basic utility method for reading NSDictionary values which works also
* with Strings. The current implementation uses
* {@link #dictionaryValueWithDefault(Object, NSDictionary)} with a default
* of <code>null</code>.
*
* @param obj
* object to be evaluated
* @return NSDictionary evaluation of the given object
*
*/
public static NSDictionary dictionaryValue(Object obj) {
return ERXValueUtilities.dictionaryValueWithDefault(obj, null);
}
/**
* Basic utility method for reading <code>NSDictionary</code> values which
* also works with serialized NSDictionarys. The default value is used if
* the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return NSDictionary evaluation of the given object
*
*/
public static NSDictionary dictionaryValueWithDefault(Object obj, NSDictionary def) {
NSDictionary value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof NSDictionary) {
value = (NSDictionary) obj;
} else if (obj instanceof String) {
String strValue = ((String) obj).trim();
if (strValue.length() > 0) {
Object objValue = NSPropertyListSerialization.propertyListFromString((String) obj);
if (objValue == null || !(objValue instanceof NSDictionary)) {
throw new IllegalArgumentException("Failed to parse a dictionary from the value '" + obj + "'.");
}
value = (NSDictionary) objValue;
}
} else {
throw new IllegalArgumentException("Failed to parse a dictionary from the value '" + obj + "'.");
}
}
return value;
}
/**
* Basic utility method for reading NSData values which works also with
* Strings. The current implementation uses
* {@link #dataValueWithDefault(Object, NSData)} with a default of
* <code>null</code>.
*
* @param obj
* object to be evaluated
* @return NSData evaluation of the given object
*
*/
public static NSData dataValue(Object obj) {
return ERXValueUtilities.dataValueWithDefault(obj, null);
}
/**
* Basic utility method for reading <code>NSData</code> values which also
* works with serialized NSData. The default value is used if the object is
* null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return NSData evaluation of the given object
*
*/
public static NSData dataValueWithDefault(Object obj, NSData def) {
NSData value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof NSData) {
value = (NSData) obj;
} else if (obj instanceof byte[]) {
byte[] byteValue = (byte[]) obj;
value = new NSData(byteValue, new NSRange(0, byteValue.length), true);
} else if (obj instanceof String) {
String strValue = ((String) obj).trim();
if (strValue.length() > 0) {
Object objValue = NSPropertyListSerialization.propertyListFromString(strValue); // MS:
// Encoding?
if (objValue == null || !(objValue instanceof NSData)) {
throw new IllegalArgumentException("Failed to parse data from the value '" + obj + "'.");
}
value = (NSData) objValue;
if (value instanceof NSMutableData) {
// AK: we need NSData if we want to use it for a PK, but
// we get NSMutableData
value = new NSData(value);
}
}
} else {
throw new IllegalArgumentException("Failed to parse data from the value '" + obj + "'.");
}
}
return value;
}
/**
* Basic utility method for reading BigDecimal values which works also with
* Strings. The current implementation uses
* {@link #bigDecimalValueWithDefault(Object, BigDecimal)} with a default of
* <code>null</code>.
*
* @param obj
* object to be evaluated
* @return BigDecimal evaluation of the given object
*
*/
public static BigDecimal bigDecimalValue(Object obj) {
return ERXValueUtilities.bigDecimalValueWithDefault(obj, null);
}
/**
* Basic utility method for reading <code>BigDecimal</code> values. The
* default value is used if the object is null.
*
* @param obj
* object to be evaluated
* @param def
* default value if object is null
* @return BigDecimal evaluation of the given object
*
*/
public static BigDecimal bigDecimalValueWithDefault(Object obj, BigDecimal def) {
BigDecimal value = def;
if (!ERXValueUtilities.isNull(obj)) {
if (obj instanceof BigDecimal) {
value = (BigDecimal) obj;
} else if (obj instanceof String) {
String strValue = ((String) obj).trim();
if (strValue.length() > 0) {
value = new BigDecimal(strValue);
}
} else if (obj instanceof Integer) {
value = new BigDecimal(((Integer) obj).intValue());
} else if (obj instanceof Long) {
value = new BigDecimal(((Long) obj).longValue());
} else if (obj instanceof Float) {
value = new BigDecimal(((Float) obj).floatValue());
} else if (obj instanceof Double) {
value = new BigDecimal(((Double) obj).doubleValue());
} else if (obj instanceof Number) {
value = new BigDecimal(((Number) obj).doubleValue());
} else if (obj instanceof Boolean) {
value = new BigDecimal(((Boolean) obj).booleanValue() ? 1 : 0);
} else {
throw new IllegalArgumentException("Failed to parse a BigDecimal from the value '" + obj + "'.");
}
}
return value;
}
/**
* Returns the comparison value between int1 and int2 (using Comparator
* rules)
*
* @param int1
* value 1
* @param int2
* value 2
* @return the Comparator comparison between the two values
*/
public static int compare(final int int1, final int int2) {
return int1 > int2 ? 1 : (int1 < int2 ? -1 : 0);
}
/**
* Basic utility method for reading Enum values.
*
* @param <T>
* Enum type evaluated
* @param obj
* object to evaluate
* @param enumType
* The desired enum class
* @return
* Enum evaluation of the given object or the default
*/
public static <T extends Enum<T>> T enumValue(Object obj, Class<T> enumType) {
return ERXValueUtilities.enumValueWithDefault(obj, enumType, null);
}
/**
* Basic utility method for reading Enum values.
*
* @param obj
* object to be evaluated
* @param def
* default value returned if object is null. If this value is null,
* the method throws a NullPointerException
* @param <T>
* enum type evaluated
* @return Enum evaluation of the given object
*/
public static <T extends Enum<T>> T enumValueWithRequiredDefault(Object obj, T def) {
return ERXValueUtilities.enumValueWithDefault(obj, (Class<T>)def.getClass(), def);
}
/**
* Basic utility method for reading Enum values.
*
* @param <T>
* Enum type evaluated
* @param obj
* object to evaluate
* @param enumType
* The desired enum class
* @param def
* default value returned if obj is null.
* @return
* Enum evaluation of the given object or the default
*/
public static <T extends Enum<T>> T enumValueWithDefault(Object obj, Class<T> enumType, T def) {
T result = def;
if(!ERXValueUtilities.isNull(obj)) {
if(obj instanceof Enum) {
result = (T)obj;
}
else if (obj instanceof String) {
result = Enum.valueOf(enumType, (String)obj);
}
else {
throw new IllegalArgumentException("Failed to parse an enum from the value '" + obj + "'.");
}
}
return result;
}
/**
* <span class="ja">
* 複数の文字列を文字列配列として返す
*
* @param anyStrings - 複数の文字列
*
* @return String[] 指定された文字列が無いときは null
*
* @author A10 nettani
* </span>
*/
public static String[] stringsToStringArray(String ... anyStrings) {
int aryLen = anyStrings.length;
if(aryLen <= 0) return null;
ArrayList<String> strlist = new ArrayList<>();
String wkStr = null;
for(int loop = 0; loop < aryLen; loop++){
wkStr = anyStrings[loop];
//System.out.println("***++++++******** anyStrings[" + loop + "] = " + wkStr);
if((wkStr != null) && (wkStr.length() > 0))
strlist.add(wkStr);
}
if(strlist.isEmpty()){
return null;
}
//return (String[]) strlist.toArray(); // Stringにキャスト出来ない時があるので
aryLen = strlist.size();
String[] wkStrs = new String[aryLen];
for(int loop = 0; loop < aryLen; loop++){
wkStrs[loop] = strlist.get(loop);
}
return wkStrs;
}
/**
* <span class="ja">
* 複数のオブジェクトをオブジェクト配列として返す
*
* @param anyObjects - 複数のオブジェクト
*
* @return Object[] 指定された文字列が無いときはnull
*
* @author A10 nettani
* </span>
*/
public static Object[] objectsToObjectArray(Object ... anyObjects) {
int aryLen = anyObjects.length;
if(aryLen <= 0) return null;
ArrayList<Object> objlist = new ArrayList<>();
Object wkObj = null;
for(int loop = 0; loop < aryLen; loop++){
wkObj = anyObjects[loop];
if(wkObj != null)
objlist.add(wkObj);
}
if(objlist.isEmpty()){
return null;
}
return objlist.toArray();
}
/**
* <span class="ja">
* 文字列配列を「,」で連結して返す。
*
* @param sa - 文字列配列
*
* @return 連結した文字配列
* </span>
*/
public static String stringArrayToString(String[] sa) {
if((sa == null) || (sa.length <= 0)) return null;
StringBuilder sbuff = new StringBuilder();
int len = sa.length;
for(int loop = 0; loop < len; loop++){
sbuff.append(sa[loop]);
if((loop +1) < len) sbuff.append(',');
}
return (sbuff.length() > 0)? sbuff.toString(): null;
}
}