*/
public double toDateDouble(Object value)
{
- // seems access stores dates in the local timezone. guess you just
- // hope you read it in the same timezone in which it was written!
- long time = ((value instanceof Date) ?
- ((Date)value).getTime() :
- ((value instanceof Calendar) ?
- ((Calendar)value).getTimeInMillis() :
- ((Number)value).longValue()));
- time += getToLocalTimeZoneOffset(time);
- time += MILLIS_BETWEEN_EPOCH_AND_1900;
- return time / MILLISECONDS_PER_DAY;
+ // seems access stores dates in the local timezone. guess you just
+ // hope you read it in the same timezone in which it was written!
+ long time = toDateLong(value);
+ time += getToLocalTimeZoneOffset(time);
+ time += MILLIS_BETWEEN_EPOCH_AND_1900;
+ return time / MILLISECONDS_PER_DAY;
+ }
+
+ /**
+ * @return an appropriate Date long value for the given object
+ */
+ private static long toDateLong(Object value)
+ {
+ return ((value instanceof Date) ?
+ ((Date)value).getTime() :
+ ((value instanceof Calendar) ?
+ ((Calendar)value).getTimeInMillis() :
+ ((Number)value).longValue()));
}
/**
} catch(SQLException e) {
throw (IOException)(new IOException(e.getMessage())).initCause(e);
}
+ } else if(value instanceof RawData) {
+ return ((RawData)value).getBytes();
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
return !(value instanceof byte[]);
}
+ /**
+ * Converts the given value to the "internal" representation for the given
+ * data type.
+ */
+ public static Object toInternalValue(DataType dataType, Object value)
+ throws IOException
+ {
+ if(value != null) {
+ switch(dataType) {
+ case BOOLEAN:
+ return ((value instanceof Boolean) ? value : toBooleanValue(value));
+ case BYTE:
+ return ((value instanceof Byte) ? value : toNumber(value).byteValue());
+ case INT:
+ return ((value instanceof Short) ? value :
+ toNumber(value).shortValue());
+ case LONG:
+ return ((value instanceof Integer) ? value :
+ toNumber(value).intValue());
+ case MONEY:
+ return toBigDecimal(value);
+ case FLOAT:
+ return ((value instanceof Float) ? value :
+ toNumber(value).floatValue());
+ case DOUBLE:
+ return ((value instanceof Double) ? value :
+ toNumber(value).doubleValue());
+ case SHORT_DATE_TIME:
+ return ((value instanceof DateExt) ? value :
+ new Date(toDateLong(value)));
+ case TEXT:
+ case MEMO:
+ case GUID:
+ return ((value instanceof String) ? value :
+ toCharSequence(value).toString());
+ case NUMERIC:
+ return toBigDecimal(value);
+ case COMPLEX_TYPE:
+ // leave alone for now?
+ break;
+ default:
+ // some variation of binary data
+ return toByteArray(value);
+ }
+ }
+
+ return value;
+ }
+
/**
* Date subclass which stashes the original date bits, in case we attempt to
* re-write the value (will not lose precision).
package com.healthmarketscience.jackcess.util;
+import java.io.IOException;
+
+import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Table;
+import com.healthmarketscience.jackcess.impl.ColumnImpl;
import org.apache.commons.lang.ObjectUtils;
/**
- * Simple concrete implementation of ColumnMatcher which test for equality.
+ * Simple concrete implementation of ColumnMatcher which tests for equality.
+ * If initial comparison fails, attempts to coerce the values to a common type
+ * for comparison.
*
* @author James Ahlborn
* @usage _general_class_
public boolean matches(Table table, String columnName, Object value1,
Object value2)
{
- return ObjectUtils.equals(value1, value2);
+ if(ObjectUtils.equals(value1, value2)) {
+ return true;
+ }
+
+ if((value1 != null) && (value2 != null) &&
+ (value1.getClass() != value2.getClass())) {
+
+ // the values aren't the same type, try coercing them to "internal"
+ // values and try again
+ DataType dataType = table.getColumn(columnName).getType();
+ try {
+ Object internalV1 = ColumnImpl.toInternalValue(dataType, value1);
+ Object internalV2 = ColumnImpl.toInternalValue(dataType, value2);
+
+ return ObjectUtils.equals(internalV1, internalV2);
+ } catch(IOException e) {
+ // ignored, just go with the original result
+ }
+ }
+ return false;
}
+
}