Java tutorial
/** * PlasmaSDO License * * This is a community release of PlasmaSDO, a dual-license * Service Data Object (SDO) 2.1 implementation. * This particular copy of the software is released under the * version 2 of the GNU General Public License. PlasmaSDO was developed by * TerraMeta Software, Inc. * * Copyright (c) 2013, TerraMeta Software, Inc. All rights reserved. * * General License information can be found below. * * This distribution may include materials developed by third * parties. For license and attribution notices for these * materials, please refer to the documentation that accompanies * this distribution (see the "Licenses for Third-Party Components" * appendix) or view the online documentation at * <http://plasma-sdo.org/licenses/>. * */ package org.plasma.sdo.helper; import java.lang.ref.SoftReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.Duration; import org.joda.time.format.ISOPeriodFormat; import org.joda.time.format.PeriodFormatter; import org.plasma.sdo.DataType; import org.plasma.sdo.PlasmaDataObjectException; import commonj.sdo.Property; import commonj.sdo.Type; public class DataConverter { private static Log log = LogFactory.getFactory().getInstance(DataConverter.class); static public DataConverter INSTANCE = initializeInstance(); public static final String FORMAT_PATTERN_TIME = "HH:mm:ss'.'SSS'Z'"; public static final String FORMAT_PATTERN_DATE = "yyyy-MM-dd'T'HH:mm:ss"; // Note: the Java class for SDO dataTime datatype is String. This seems unfortunate // because a java.util.Date is certainly capable of representing // far more precision that than month/day/year. It seems also // that users would expect generated method signatures for // dataTime to be java.util.Date. Have to comply w/the spec though // but can compensate for this by allowing more precision // in the SDO date datatype. See above data format which allows // seconds precision. public static final String FORMAT_PATTERN_DATETIME = "yyyy-MM-dd'T'HH:mm:ss'.'SSS'Z'"; public static final String FORMAT_PATTERN_DAY = "dd"; public static final String FORMAT_PATTERN_MONTH = "MM"; public static final String FORMAT_PATTERN_MONTHDAY = "MM-dd"; public static final String FORMAT_PATTERN_YEAR = "yyyy"; public static final String FORMAT_PATTERN_YEARMONTH = "yyyy-MM"; public static final String FORMAT_PATTERN_YEARMONTHDAY = "yyyy-MM-dd"; private static Map<Class<?>, Map<String, DataType>> javaClassToAllowableTypesMap; private static Map<Class<?>, Method> javaClassToConverterFromMethodMap; private DataConverter() { if (javaClassToAllowableTypesMap == null) { javaClassToAllowableTypesMap = new HashMap<Class<?>, Map<String, DataType>>(); for (int i = 0; i < DataType.values().length; i++) { DataType dataTypeEnum = DataType.values()[i]; Class<?> javaClass = toPrimitiveJavaClass(dataTypeEnum); Map<String, DataType> allowableMap = new HashMap<String, DataType>(); List<DataType> list = getAllowableTargetTypes(dataTypeEnum); for (DataType allowableType : list) allowableMap.put(allowableType.toString(), allowableType); javaClassToAllowableTypesMap.put(javaClass, allowableMap); } } if (javaClassToConverterFromMethodMap == null) { javaClassToConverterFromMethodMap = new HashMap<Class<?>, Method>(); Map<Class<?>, Method> map = javaClassToConverterFromMethodMap; try { Method method = this.getClass().getMethod("fromBoolean", Type.class, boolean.class); map.put(Boolean.class, method); map.put(boolean.class, method); method = this.getClass().getMethod("fromByte", Type.class, byte.class); map.put(Byte.class, method); map.put(byte.class, method); method = this.getClass().getMethod("fromBytes", Type.class, byte[].class); map.put(Byte[].class, method); map.put(byte[].class, method); method = this.getClass().getMethod("fromCharacter", Type.class, char.class); map.put(Character.class, method); map.put(char.class, method); method = this.getClass().getMethod("fromDate", Type.class, Date.class); map.put(Date.class, method); method = this.getClass().getMethod("fromDecimal", Type.class, BigDecimal.class); map.put(BigDecimal.class, method); method = this.getClass().getMethod("fromDouble", Type.class, double.class); map.put(Double.class, method); map.put(double.class, method); method = this.getClass().getMethod("fromFloat", Type.class, float.class); map.put(Float.class, method); map.put(float.class, method); method = this.getClass().getMethod("fromInt", Type.class, int.class); map.put(int.class, method); map.put(Integer.class, method); method = this.getClass().getMethod("fromInteger", Type.class, BigInteger.class); map.put(BigInteger.class, method); method = this.getClass().getMethod("fromLong", Type.class, long.class); map.put(Long.class, method); map.put(long.class, method); method = this.getClass().getMethod("fromShort", Type.class, short.class); map.put(Short.class, method); map.put(short.class, method); method = this.getClass().getMethod("fromString", Type.class, String.class); map.put(String.class, method); //Class<?> stringListClass = (java.lang.Class<java.util.List<java.lang.String>>)new ArrayList<java.lang.String>().getClass(); method = this.getClass().getMethod("fromStrings", Type.class, List.class); map.put(List.class, method); } catch (NoSuchMethodException e) { log.error(e.getMessage(), e); } } } public DateFormat[] getDateFormats() { DateFormat[] result = new DateFormat[9]; result[0] = DateFormatMap.get(FORMAT_PATTERN_TIME); result[1] = DateFormatMap.get(FORMAT_PATTERN_DATE); result[2] = DateFormatMap.get(FORMAT_PATTERN_DATETIME); result[3] = DateFormatMap.get(FORMAT_PATTERN_DAY); result[4] = DateFormatMap.get(FORMAT_PATTERN_MONTH); result[5] = DateFormatMap.get(FORMAT_PATTERN_MONTHDAY); result[6] = DateFormatMap.get(FORMAT_PATTERN_YEAR); result[7] = DateFormatMap.get(FORMAT_PATTERN_YEARMONTH); result[8] = DateFormatMap.get(FORMAT_PATTERN_YEARMONTHDAY); return result; } /** * A factory for {@link SimpleDateFormat}s. The instances are stored in a * threadlocal way because SimpleDateFormat is not threadsafe as noted in * {@link SimpleDateFormat its javadoc}. */ final static class DateFormatMap { private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>> THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() { @Override protected SoftReference<Map<String, SimpleDateFormat>> initialValue() { return new SoftReference<Map<String, SimpleDateFormat>>(new HashMap<String, SimpleDateFormat>()); } }; /** * creates a {@link SimpleDateFormat} for the requested format string. * * @param pattern * a non-<code>null</code> format String according to * {@link SimpleDateFormat}. The format is not checked against * <code>null</code> since all paths go through * {@link DateUtils}. * @return the requested format. This simple dateformat should not be used * to {@link SimpleDateFormat#applyPattern(String) apply} to a * different pattern. */ public static SimpleDateFormat get(String pattern) { SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get(); Map<String, SimpleDateFormat> formats = ref.get(); if (formats == null) { formats = new HashMap<String, SimpleDateFormat>(); THREADLOCAL_FORMATS.set(new SoftReference<Map<String, SimpleDateFormat>>(formats)); } SimpleDateFormat format = formats.get(pattern); if (format == null) { format = new SimpleDateFormat(pattern, Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); formats.put(pattern, format); } return format; } } private static synchronized DataConverter initializeInstance() { if (INSTANCE == null) INSTANCE = new DataConverter(); return INSTANCE; } public DateFormat getDateTimeFormat() { return DateFormatMap.get(FORMAT_PATTERN_DATETIME); } public DateFormat getTimeFormat() { return DateFormatMap.get(FORMAT_PATTERN_TIME); } public DateFormat getDateFormat() { return DateFormatMap.get(FORMAT_PATTERN_DATE); } public PeriodFormatter getDurationFormat() { return ISOPeriodFormat.standard(); } public DateFormat getDayFormat() { return DateFormatMap.get(FORMAT_PATTERN_DAY); } public DateFormat getMonthFormat() { return DateFormatMap.get(FORMAT_PATTERN_MONTH); } public DateFormat getMonthDayFormat() { return DateFormatMap.get(FORMAT_PATTERN_MONTHDAY); } public DateFormat getYearFormat() { return DateFormatMap.get(FORMAT_PATTERN_YEAR); } public DateFormat getYearMonthFormat() { return DateFormatMap.get(FORMAT_PATTERN_YEARMONTH); } public DateFormat getYearMonthDayFormat() { return DateFormatMap.get(FORMAT_PATTERN_DAY); } public Object convert(Type targetType, Object value) { if (!targetType.isDataType()) throw new IllegalArgumentException( "type " + targetType.getURI() + "#" + targetType.getName() + " is not a data-type"); Method method = javaClassToConverterFromMethodMap.get(value.getClass()); try { return method.invoke(this, targetType, value); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof InvalidDataConversionException) throw (InvalidDataConversionException) e.getTargetException(); else throw new RuntimeException(e.getTargetException()); } } public Object convert(Type targetType, Type sourceType, Object value) { if (!targetType.isDataType()) throw new IllegalArgumentException( "type " + targetType.getURI() + "#" + targetType.getName() + " is not a data-type"); if (!sourceType.isDataType()) throw new IllegalArgumentException( "type " + sourceType.getURI() + "#" + sourceType.getName() + " is not a data-type"); DataType targetDataType = DataType.valueOf(targetType.getName()); DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (targetDataType) { case Boolean: return toBoolean(sourceType, value); case Byte: return toByte(sourceType, value); case Bytes: return toBytes(sourceType, value); case Character: return toCharacter(sourceType, value); case Decimal: return toDecimal(sourceType, value); case Double: return toDouble(sourceType, value); case Float: return toFloat(sourceType, value); case Int: return toInt(sourceType, value); case Integer: return toInteger(sourceType, value); case Long: return toLong(sourceType, value); case Short: return toShort(sourceType, value); case String: return toString(sourceType, value); case Strings: return toStrings(sourceType, value); case Date: return toDate(sourceType, value); case Duration: case DateTime: case Day: case Month: case MonthDay: case Year: case YearMonth: case YearMonthDay: case Time: return toTemporalDataType(targetType, sourceType, value); case URI: case Object: default: throw new InvalidDataConversionException(targetDataType, sourceDataType, value); } } public boolean toBoolean(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Boolean: return ((Boolean) value).booleanValue(); case String: return Boolean.parseBoolean(value.toString()); default: throw new InvalidDataConversionException(DataType.Boolean, sourceDataType, value); } } public Object fromBoolean(Type targetType, boolean value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Boolean: return Boolean.valueOf(value); case String: return String.valueOf(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Boolean, value); } } public byte toByte(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Byte: return ((Byte) value).byteValue(); case Double: return ((Double) value).byteValue(); case Float: return ((Float) value).byteValue(); case Int: return ((Integer) value).byteValue(); case Long: return ((Long) value).byteValue(); case Short: return ((Short) value).byteValue(); case String: // as per spec: 8 bits unsigned [0-9]+ return Integer.valueOf((String) value).byteValue(); default: throw new InvalidDataConversionException(DataType.Byte, sourceDataType, value); } } public Object fromByte(Type targetType, byte value) { DataType targetDataType = DataType.valueOf(targetType.getName()); // as per spec: 8 bits unsigned [0-9]+ switch (targetDataType) { case Byte: return Byte.valueOf(value); case Double: return Double.valueOf((int) value & 0xFF); case Float: return Float.valueOf((int) value & 0xFF); case Int: return Integer.valueOf((int) value & 0xFF); case Long: return Long.valueOf((int) value & 0xFF); case Short: return new Short(Integer.valueOf((int) value & 0xFF).shortValue()); case String: return Integer.valueOf((int) value & 0xFF).toString(); default: throw new InvalidDataConversionException(targetDataType, DataType.Byte, value); } } public byte[] toBytes(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Bytes: return (byte[]) value; case String: return ((String) value).getBytes(); case Integer: return ((BigInteger) value).toByteArray(); default: throw new InvalidDataConversionException(DataType.Bytes, sourceDataType, value); } } public Object fromBytes(Type targetType, byte[] value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Bytes: return value; case String: return toHexString(value); // SDO Spec 2.1.1 Section 8.1 calls for byte array String representation to be HEX case Integer: return new BigInteger(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Bytes, value); } } public char toCharacter(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Character: return ((Character) value).charValue(); case String: return ((String) value).charAt(0); default: throw new InvalidDataConversionException(DataType.Character, sourceDataType, value); } } public Object fromCharacter(Type targetType, char value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Character: return Character.valueOf(value); case String: return String.valueOf(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Character, value); } } public BigDecimal toDecimal(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Decimal: return (BigDecimal) value; case Double: case Float: case Int: case Long: case Integer: return new BigDecimal(((Number) value).doubleValue()); case String: return new BigDecimal((String) value); default: throw new InvalidDataConversionException(DataType.Decimal, sourceDataType, value); } } public Object fromDecimal(Type targetType, BigDecimal value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Decimal: return value; case Double: return new Double(value.doubleValue()); case Float: return new Float(value.floatValue()); case Int: return new Integer(value.intValue()); case Long: return new Long(value.longValue()); case Integer: return value.toBigInteger(); case String: // as per spec: ('+'|'-')? [0-9]* ('.'[0-9]*)? (('E'|'e') ('+'|'-')? [0-9]+)? /* * [123,0] "123" * [-123,0] "-123" * [123,-1] "1.23E+3" * [123,-3] "1.23E+5" * [123,1] "12.3" * [123,5] "0.00123" * [123,10] "1.23E-8" * [-123,12] "-1.23E-10" */ return value.toString(); default: throw new InvalidDataConversionException(targetDataType, DataType.Decimal, value); } } public double toDouble(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Double: return ((Double) value).doubleValue(); case Byte: return ((Byte) value).doubleValue(); case Float: return ((Float) value).doubleValue(); case Int: return ((Integer) value).doubleValue(); case Long: return ((Long) value).doubleValue(); case Short: return ((Short) value).doubleValue(); case Integer: return ((BigInteger) value).doubleValue(); case Decimal: return ((BigDecimal) value).doubleValue(); case String: return Double.parseDouble((String) value); //return Double.valueOf((String)value).doubleValue(); default: throw new InvalidDataConversionException(DataType.Double, sourceDataType, value); } } public Object fromDouble(Type targetType, double value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Double: return Double.valueOf(value); case Byte: return new Byte(Double.valueOf(value).byteValue()); case Float: return new Float(Double.valueOf(value).floatValue()); case Int: return new Integer(Double.valueOf(value).intValue()); case Long: return new Long(Double.valueOf(value).longValue()); case Short: return new Short(Double.valueOf(value).shortValue()); case Integer: return BigInteger.valueOf(Double.valueOf(value).longValue()); case Decimal: return BigDecimal.valueOf(value); case String: // as per spec: Decimal | 'NaN' | '-NaN' | 'Infinity' | '-Infinity' return Double.toString(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Double, value); } } public float toFloat(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Float: return ((Float) value).floatValue(); case Byte: return ((Byte) value).floatValue(); case Double: return ((Double) value).floatValue(); case Int: return ((Integer) value).floatValue(); case Long: return ((Long) value).floatValue(); case Short: return ((Short) value).floatValue(); case Decimal: return ((BigDecimal) value).floatValue(); case Integer: return ((BigInteger) value).floatValue(); case String: return Float.valueOf((String) value).floatValue(); default: throw new InvalidDataConversionException(DataType.Float, sourceDataType, value); } } public Object fromFloat(Type targetType, float value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Float: return Float.valueOf(value); case Byte: return new Byte(Float.valueOf(value).byteValue()); case Double: return new Double(Float.valueOf(value).doubleValue()); case Int: return new Integer(Float.valueOf(value).intValue()); case Long: return new Long(Float.valueOf(value).longValue()); case Short: return new Short(Float.valueOf(value).shortValue()); case Decimal: return BigDecimal.valueOf(value); case Integer: return BigInteger.valueOf(Double.valueOf(value).longValue()); case String: // as per spec: Decimal | 'NaN' | '-NaN' | 'Infinity' | '-Infinity' return Float.toString(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Float, value); } } public int toInt(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Int: return ((Integer) value).intValue(); case Byte: return ((Byte) value).intValue(); case Double: return ((Double) value).intValue(); case Float: return ((Float) value).intValue(); case Long: return ((Long) value).intValue(); case Short: return ((Short) value).intValue(); case Decimal: return ((BigDecimal) value).intValue(); case Integer: return ((BigInteger) value).intValue(); case String: return Integer.parseInt((String) value); default: throw new InvalidDataConversionException(DataType.Int, sourceDataType, value); } } public Object fromInt(Type targetType, int value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Int: return Integer.valueOf(value); case Byte: return new Byte(Integer.valueOf(value).byteValue()); case Double: return new Double(Integer.valueOf(value).doubleValue()); case Float: return new Float(Integer.valueOf(value).floatValue()); case Long: return new Long(Integer.valueOf(value).longValue()); case Short: return new Short(Integer.valueOf(value).shortValue()); case Decimal: return BigDecimal.valueOf(value); case Integer: return BigInteger.valueOf(Integer.valueOf(value).longValue()); case String: return Integer.toString(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Int, value); } } public BigInteger toInteger(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Integer: return (BigInteger) value; case Double: return BigInteger.valueOf(((Double) value).longValue()); case Float: return BigInteger.valueOf(((Float) value).longValue()); case Int: return BigInteger.valueOf(((Integer) value).longValue()); case Long: return BigInteger.valueOf(((Long) value).longValue()); case Decimal: return BigInteger.valueOf(((BigDecimal) value).longValue()); case Bytes: return new BigInteger((byte[]) value); case String: return new BigInteger((String) value); default: throw new InvalidDataConversionException(DataType.Integer, sourceDataType, value); } } public Object fromInteger(Type targetType, BigInteger value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Integer: return value; case Double: return new Double(value.doubleValue()); case Float: return new Float(value.floatValue()); case Int: return new Integer(value.intValue()); case Long: return new Long(value.longValue()); case Decimal: return new BigDecimal(value.doubleValue()); case Bytes: return value.toByteArray(); case String: //as per spec: ('+'|'-')? [0-9]+ return value.toString(); default: throw new InvalidDataConversionException(targetDataType, DataType.Integer, value); } } public long toLong(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Long: return ((Long) value).longValue(); case Byte: return ((Byte) value).longValue(); case Double: return ((Double) value).longValue(); case Float: return ((Float) value).longValue(); case Int: return ((Integer) value).longValue(); case Short: return ((Short) value).longValue(); case Decimal: return ((BigDecimal) value).longValue(); case Integer: return ((BigInteger) value).longValue(); case Date: return ((Date) value).getTime(); case String: return Long.parseLong((String) value); default: throw new InvalidDataConversionException(DataType.Long, sourceDataType, value); } } public Object fromLong(Type targetType, long value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Long: return Long.valueOf(value); case Byte: return new Byte(Long.valueOf(value).byteValue()); case Double: return new Double(Long.valueOf(value).doubleValue()); case Float: return new Float(Long.valueOf(value).floatValue()); case Int: return new Integer(Long.valueOf(value).intValue()); case Short: return new Short(Long.valueOf(value).shortValue()); case Decimal: return new BigDecimal(Long.valueOf(value).longValue()); case Integer: return BigInteger.valueOf(Long.valueOf(value).longValue()); case Date: return new Date(value); case String: return Long.toString(value); default: throw new InvalidDataConversionException(targetDataType, DataType.Long, value); } } public short toShort(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Short: return ((Short) value).shortValue(); case Byte: return ((Byte) value).shortValue(); case Double: return ((Double) value).shortValue(); case Float: return ((Float) value).shortValue(); case Int: return ((Integer) value).shortValue(); case Long: return ((Long) value).shortValue(); case String: return Short.parseShort((String) value); default: throw new InvalidDataConversionException(DataType.Short, sourceDataType, value); } } public Object fromShort(Type targetType, short value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Short: return Short.valueOf(value); case Byte: return new Byte(Short.valueOf(value).byteValue()); case Double: return new Double(Short.valueOf(value).doubleValue()); case Float: return new Float(Short.valueOf(value).floatValue()); case Int: return new Integer(Short.valueOf(value).intValue()); case Long: return new Long(Short.valueOf(value).longValue()); case String: return Short.valueOf(value).toString(); default: throw new InvalidDataConversionException(targetDataType, DataType.Short, value); } } /** * Converts the given value to a string. Uses java.util.Arrays * formatting if an array of objects of the target type is detected. * @param sourceType the target datatype * @param value the value to convert * @return the string value * @throws InvalidDataConversionException if the given source * type cannot be converted to string as per the SDO 2.1 * datatype conversion table. * @throws IllegalArgumentException if the given value is not * the expected Java type as per the SDO 2.1 specification */ @SuppressWarnings("unchecked") public String toString(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case String: case DateTime: case Month: case MonthDay: case Day: case Time: case Year: case YearMonth: case YearMonthDay: case Duration: case URI: if (value instanceof String) { return (String) value; } else { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(listValue instanceof String)) throwExpectedInstance(sourceDataType, String.class, listValue.getClass()); return Arrays.toString(list.toArray()); } else { throwExpectedInstance(sourceDataType, String.class, value.getClass()); } } case Decimal: if (value instanceof BigDecimal) { return ((BigDecimal) value).toString(); } else { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(listValue instanceof BigDecimal)) throwExpectedInstance(sourceDataType, BigDecimal.class, listValue.getClass()); return Arrays.toString(list.toArray()); } else { throwExpectedInstance(sourceDataType, BigDecimal.class, value.getClass()); } } case Bytes: if (value instanceof byte[]) { return toHexString(((byte[]) value)); // as per spec: [0-9A-F]+ } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> list = (List<?>) value; for (Object listValue : list) { if (!(listValue instanceof byte[])) throwExpectedInstance(sourceDataType, byte[].class, listValue.getClass()); result.add(toHexString((byte[]) listValue)); } return Arrays.toString(result.toArray()); } else { throwExpectedInstance(sourceDataType, byte[].class, value.getClass()); } } case Byte: if (value instanceof Byte) { // as per spec: 8 bits unsigned [0-9]+ return Integer.valueOf(((Byte) value).byteValue() & 0xFF).toString(); } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> list = (List<?>) value; for (Object listValue : list) { if (!(listValue instanceof Byte)) throwExpectedInstance(sourceDataType, Byte.class, listValue.getClass()); result.add(Integer.valueOf(((Byte) listValue).byteValue() & 0xFF).toString()); } return Arrays.toString(result.toArray()); } else { throwExpectedInstance(sourceDataType, Byte.class, value.getClass()); } } case Boolean: return toString(sourceDataType, Boolean.class, value); case Character: return toString(sourceDataType, Character.class, value); case Double: return toString(sourceDataType, Double.class, value); case Float: return toString(sourceDataType, Float.class, value); case Int: return toString(sourceDataType, Integer.class, value); case Integer: return toString(sourceDataType, BigInteger.class, value); case Long: return toString(sourceDataType, Long.class, value); case Short: return toString(sourceDataType, Short.class, value); case Strings: // FIXME: add many condition if (!(value instanceof List)) throw new IllegalArgumentException("expected value as class " + List.class.getName() + ", not " + value.getClass().getName() + ", for datatype '" + sourceDataType.name() + "'"); StringBuffer buf = new StringBuffer(); List<String> list = (List<String>) value; Iterator<String> iter = list.iterator(); for (int i = 0; iter.hasNext(); i++) { if (i > 0) buf.append(" "); buf.append(iter.next()); } return buf.toString(); case Date: if (value instanceof Date) { return this.getDateFormat().format(value); } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> dateList = (List<?>) value; for (Object listValue : dateList) { if (!(listValue instanceof Date)) throwExpectedInstance(sourceDataType, Date.class, listValue.getClass()); result.add(this.getDateFormat().format(value)); } return Arrays.toString(result.toArray()); } else { throwExpectedInstance(sourceDataType, Date.class, value.getClass()); } } case Object: // FIXME: add many condition return String.valueOf(value); default: throw new InvalidDataConversionException(DataType.String, sourceDataType, value); } } private String toString(DataType sourceDataType, Class<?> typeClass, Object value) { String result = null; if (typeClass.isAssignableFrom(value.getClass())) { result = String.valueOf(value); } else { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(typeClass.isAssignableFrom(listValue.getClass()))) throwExpectedInstance(sourceDataType, typeClass, listValue.getClass()); result = Arrays.toString(list.toArray()); } else { throwExpectedInstance(sourceDataType, typeClass, value.getClass()); } } return result; } /** * Converts the given value to a string. Uses java.util.Arrays * formatting if the target property is a 'many' property. * If an array of objects of the target type is detected for the given value, * and the given property is not a 'many' property, * an IllegalArgumentException is thrown. * @param sourceProperty the property type for the given property * @param value the value to convert * @return the string value * @throws InvalidDataConversionException If an array of objects of the target type * is detected for the given value, * and the given property is not a 'many' property * @throws IllegalArgumentException if the given value is not * the expected Java type as per the SDO 2.1 specification * @throws IllegalArgumentException if an array of objects of the target type is detected for the given value, * and the given property is not a 'many' property */ @SuppressWarnings("unchecked") public String toString(Property property, Object value) { DataType sourceDataType = DataType.valueOf(property.getType().getName()); switch (sourceDataType) { case String: case DateTime: case Month: case MonthDay: case Day: case Time: case Year: case YearMonth: case YearMonthDay: case Duration: case URI: if (!property.isMany()) { if (value instanceof String) { return (String) value; } else throwExpectedInstance(sourceDataType, String.class, value.getClass()); } else { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(listValue instanceof String)) throwExpectedInstance(sourceDataType, String.class, listValue.getClass()); return Arrays.toString(list.toArray()); } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } case Decimal: if (!property.isMany()) { if (value instanceof BigDecimal) { return ((BigDecimal) value).toString(); } else throwExpectedInstance(sourceDataType, BigDecimal.class, value.getClass()); } else { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(listValue instanceof BigDecimal)) throwExpectedInstance(sourceDataType, BigDecimal.class, listValue.getClass()); return Arrays.toString(list.toArray()); } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } case Bytes: if (!property.isMany()) { if (value instanceof byte[]) { return toHexString(((byte[]) value)); // as per spec: [0-9A-F]+ } else throwExpectedInstance(sourceDataType, byte[].class, value.getClass()); } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> list = (List<?>) value; for (Object listValue : list) { if (!(listValue instanceof byte[])) throwExpectedInstance(sourceDataType, byte[].class, listValue.getClass()); result.add(toHexString((byte[]) listValue)); } return Arrays.toString(result.toArray()); } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } case Byte: if (!property.isMany()) { if (value instanceof Byte) { // as per spec: 8 bits unsigned [0-9]+ return Integer.valueOf(((Byte) value).byteValue() & 0xFF).toString(); } else throwExpectedInstance(sourceDataType, Byte.class, value.getClass()); } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> list = (List<?>) value; for (Object listValue : list) { if (!(listValue instanceof Byte)) throwExpectedInstance(sourceDataType, Byte.class, listValue.getClass()); result.add(Integer.valueOf(((Byte) listValue).byteValue() & 0xFF).toString()); } return Arrays.toString(result.toArray()); } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } case Boolean: return toString(property, Boolean.class, value); case Character: return toString(property, Character.class, value); case Double: return toString(property, Double.class, value); case Float: return toString(property, Float.class, value); case Int: return toString(property, Integer.class, value); case Integer: return toString(property, BigInteger.class, value); case Long: return toString(property, Long.class, value); case Short: return toString(property, Short.class, value); case Strings: // FIXME: add many condition if (!(value instanceof List)) throw new IllegalArgumentException("expected value as class " + List.class.getName() + ", not " + value.getClass().getName() + ", for datatype '" + sourceDataType.name() + "'"); StringBuffer buf = new StringBuffer(); List<String> list = (List<String>) value; Iterator<String> iter = list.iterator(); for (int i = 0; iter.hasNext(); i++) { if (i > 0) buf.append(" "); buf.append(iter.next()); } return buf.toString(); case Date: if (!property.isMany()) { if (value instanceof Date) { return this.getDateFormat().format(value); } else throwExpectedInstance(sourceDataType, Date.class, value.getClass()); } else { if (value instanceof List) { List<String> result = new ArrayList<String>(); List<?> dateList = (List<?>) value; for (Object listValue : dateList) { if (!(listValue instanceof Date)) throwExpectedInstance(sourceDataType, Date.class, listValue.getClass()); result.add(this.getDateFormat().format(value)); } return Arrays.toString(result.toArray()); } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } case Object: // FIXME: add many condition return String.valueOf(value); default: throw new InvalidDataConversionException(DataType.String, sourceDataType, value); } } private String toString(Property property, Class<?> typeClass, Object value) { DataType sourceDataType = DataType.valueOf(property.getType().getName()); String result = null; if (!property.isMany()) { if (typeClass.isAssignableFrom(value.getClass())) { result = String.valueOf(value); } else throwExpectedInstance(sourceDataType, Date.class, value.getClass()); } else { if (value instanceof List) { if (value instanceof List) { List<?> list = (List<?>) value; for (Object listValue : (List<?>) value) if (!(typeClass.isAssignableFrom(listValue.getClass()))) throwExpectedInstance(sourceDataType, typeClass, listValue.getClass()); result = Arrays.toString(list.toArray()); } else { throwExpectedInstance(sourceDataType, typeClass, value.getClass()); } } else { throw new IllegalArgumentException( "expected value as instanceof List for 'many' property, " + property.toString()); } } return result; } private void throwExpectedInstance(DataType dataType, Class expectedClass, Class foundClass) { throw new IllegalArgumentException("expected value or list of class " + expectedClass.getName() + ", not " + foundClass.getName() + ", for datatype '" + dataType.name() + "'"); } /** * Converts the given string value to an object appropriate * for the target type. If java.util.Arrays formatting * is detected for the given string value, the formatting is * removed and the arrays converted into a list * of elements appropriate for the target type. * @param targetType the target data type * @param value the value * @return the converted value */ public Object fromString(Type targetType, String value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case String: if (!value.startsWith("[")) { return value; } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<String> list = new ArrayList<String>(); for (String arrayValue : strings) list.add(arrayValue); return list; } case Decimal: if (!value.startsWith("[")) { return new BigDecimal(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<BigDecimal> list = new ArrayList<BigDecimal>(); for (String arrayValue : strings) list.add(new BigDecimal(arrayValue)); return list; } case Bytes: if (!value.startsWith("[")) { return value.getBytes(); // FIXME: charset? } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<byte[]> list = new ArrayList<byte[]>(); for (String arrayValue : strings) list.add(value.getBytes()); // FIXME: charset? return list; } case Byte: if (!value.startsWith("[")) { byte[] byteArray = value.getBytes(); // FIXME: charset? return new Byte(byteArray[0]); //TODO: truncation warning? } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Byte> list = new ArrayList<Byte>(); byte[] byteArray = null; for (String arrayValue : strings) { byteArray = arrayValue.getBytes(); list.add(new Byte(byteArray[0])); } return list; } case Boolean: if (!value.startsWith("[")) { return Boolean.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Boolean> list = new ArrayList<Boolean>(); for (String arrayValue : strings) list.add(Boolean.valueOf(arrayValue)); return list; } case Character: if (!value.startsWith("[")) { return Character.valueOf(value.charAt(0)); // TODO: truncation warning? } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Character> list = new ArrayList<Character>(); for (String arrayValue : strings) list.add(Character.valueOf(arrayValue.charAt(0))); return list; } case Double: if (!value.startsWith("[")) { return Double.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Double> list = new ArrayList<Double>(); for (String arrayValue : strings) list.add(Double.valueOf(arrayValue)); return list; } case Float: if (!value.startsWith("[")) { return Float.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Float> list = new ArrayList<Float>(); for (String arrayValue : strings) list.add(Float.valueOf(arrayValue)); return list; } case Int: if (!value.startsWith("[")) { return Integer.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Integer> list = new ArrayList<Integer>(); for (String arrayValue : strings) list.add(Integer.valueOf(arrayValue)); return list; } case Integer: if (!value.startsWith("[")) { return new BigInteger(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<BigInteger> list = new ArrayList<BigInteger>(); for (String arrayValue : strings) list.add(new BigInteger(arrayValue)); return list; } case Long: if (!value.startsWith("[")) { return Long.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Long> list = new ArrayList<Long>(); for (String arrayValue : strings) list.add(Long.valueOf(arrayValue)); return list; } case Short: if (!value.startsWith("[")) { return Short.valueOf(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Short> list = new ArrayList<Short>(); for (String arrayValue : strings) list.add(Short.valueOf(arrayValue)); return list; } case Strings: if (!value.startsWith("[")) { String[] values = value.split("\\s"); List<String> list = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) list.add(values[i]); return list; } else { // don't replace whitespace internal to individual 'strings' value String tempValue = value.replaceAll("[\\[\\]]", ""); tempValue.trim(); // just trim Arrays formatting String[] strings = tempValue.split(","); List<List<String>> list = new ArrayList<List<String>>(); for (String arrayValue : strings) { String[] values = arrayValue.split("\\s"); List<String> subList = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) subList.add(values[i]); list.add(subList); } return list; } case Date: try { if (!value.startsWith("[")) { return getDateFormat().parse(value); } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Date> list = new ArrayList<Date>(); for (String arrayValue : strings) list.add(getDateFormat().parse(arrayValue)); return list; } } catch (ParseException e) { throw new PlasmaDataObjectException(e); } case DateTime: case Month: case MonthDay: case URI: case Day: case Duration: case Time: case Year: case YearMonth: case YearMonthDay: // TODO: See lexical XML Schema string representation for these types if (!value.startsWith("[")) { return value; } else { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<String> list = new ArrayList<String>(); for (String arrayValue : strings) list.add(arrayValue); return list; } default: throw new InvalidDataConversionException(targetDataType, DataType.String, value); } } /** * Converts the given string value to an object appropriate * for the target property and its type. If the given property is a 'many' property, * java.util.Arrays formatting is expected. * Any java.util.Arrays formatting is * removed and the arrays converted into a list * of elements appropriate for the target type. * @param targetType the target data type * @param value the value to convert from string * @return the converted value * @throws IllegalArgumentException if the given property is a 'many' property and no * java.util.Arrays formatting is detected for the given value. */ public Object fromString(Property targetProperty, String value) { DataType targetDataType = DataType.valueOf(targetProperty.getType().getName()); switch (targetDataType) { case String: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return value; } else { // ignore arrays formatting for singular properties as these are allowed to contain '[' return value; } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<String> list = new ArrayList<String>(); for (String arrayValue : strings) list.add(arrayValue); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Decimal: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return new BigDecimal(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<BigDecimal> list = new ArrayList<BigDecimal>(); for (String arrayValue : strings) list.add(new BigDecimal(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Bytes: if (!targetProperty.isMany()) { return value.getBytes(); // FIXME: charset? } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<byte[]> list = new ArrayList<byte[]>(); for (String arrayValue : strings) list.add(value.getBytes()); // FIXME: charset? return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Byte: if (!targetProperty.isMany()) { byte[] byteArray = value.getBytes(); // FIXME: charset? return new Byte(byteArray[0]); //TODO: truncation warning? } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Byte> list = new ArrayList<Byte>(); byte[] byteArray = null; for (String arrayValue : strings) { byteArray = arrayValue.getBytes(); list.add(new Byte(byteArray[0])); } return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Boolean: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Boolean.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Boolean> list = new ArrayList<Boolean>(); for (String arrayValue : strings) list.add(Boolean.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Character: if (!targetProperty.isMany()) { return Character.valueOf(value.charAt(0)); // TODO: truncation warning? } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Character> list = new ArrayList<Character>(); for (String arrayValue : strings) list.add(Character.valueOf(arrayValue.charAt(0))); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Double: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Double.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Double> list = new ArrayList<Double>(); for (String arrayValue : strings) list.add(Double.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Float: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Float.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Float> list = new ArrayList<Float>(); for (String arrayValue : strings) list.add(Float.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Int: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Integer.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Integer> list = new ArrayList<Integer>(); for (String arrayValue : strings) list.add(Integer.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Integer: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return new BigInteger(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<BigInteger> list = new ArrayList<BigInteger>(); for (String arrayValue : strings) list.add(new BigInteger(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Long: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Long.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Long> list = new ArrayList<Long>(); for (String arrayValue : strings) list.add(Long.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Short: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { return Short.valueOf(value); } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Short> list = new ArrayList<Short>(); for (String arrayValue : strings) list.add(Short.valueOf(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Strings: if (!targetProperty.isMany()) { String[] values = value.split("\\s"); List<String> list = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) list.add(values[i]); return list; } else { if (value.startsWith("[")) { // don't replace whitespace internal to individual 'strings' value String tempValue = value.replaceAll("[\\[\\]]", ""); tempValue.trim(); // just trim Arrays formatting String[] strings = tempValue.split(","); List<List<String>> list = new ArrayList<List<String>>(); for (String arrayValue : strings) { String[] values = arrayValue.split("\\s"); List<String> subList = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) subList.add(values[i]); list.add(subList); } return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } case Date: try { if (!targetProperty.isMany()) { return getDateFormat().parse(value); } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<Date> list = new ArrayList<Date>(); for (String arrayValue : strings) list.add(getDateFormat().parse(arrayValue)); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } } catch (ParseException e) { throw new PlasmaDataObjectException(e); } case DateTime: case Month: case MonthDay: case URI: case Day: case Duration: case Time: case Year: case YearMonth: case YearMonthDay: if (!targetProperty.isMany()) { if (!value.startsWith("[")) { // TODO: See lexical XML Schema string representation for these types return value; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting expected for the given value, for the given singular property, " + targetProperty.toString()); } } else { if (value.startsWith("[")) { String[] strings = value.replaceAll("[\\[\\]\\s]", "").split(","); List<String> list = new ArrayList<String>(); for (String arrayValue : strings) list.add(arrayValue); return list; } else { throw new IllegalArgumentException( "no java.util.Arrays formatting detected for the given value, for the given 'many' property, " + targetProperty.toString()); } } default: throw new InvalidDataConversionException(targetDataType, DataType.String, value); } } public List<String> toStrings(Type sourceType, Object value) { DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Strings: return (List<String>) value; case String: String[] values = ((String) value).split("\\s"); List<String> list = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) list.add(values[i]); // what no Java 5 sugar for this ?? return list; default: throw new InvalidDataConversionException(DataType.Strings, sourceDataType, value); } } public Object fromStrings(Type targetType, List<String> value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Strings: return value; case String: StringBuffer buf = new StringBuffer(); Iterator<String> iter = value.iterator(); for (int i = 0; iter.hasNext(); i++) { if (i > 0) buf.append(" "); buf.append(iter.next()); } return buf.toString(); default: throw new InvalidDataConversionException(targetDataType, DataType.Strings, value); } } public java.util.Date toDate(Type sourceType, Object value) { DateFormat format = null; DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Date: return (Date) value; case Long: return new Date(((Long) value).longValue()); case Day: format = getDayFormat(); break; case Month: format = getMonthFormat(); break; case MonthDay: format = getMonthDayFormat(); break; case Time: format = getTimeFormat(); break; case Year: format = getYearFormat(); break; case YearMonth: format = getYearMonthFormat(); break; case YearMonthDay: format = getYearMonthDayFormat(); break; case Duration: // FIXME use correct parse case DateTime: case String: format = getDateTimeFormat(); break; default: throw new InvalidDataConversionException(DataType.Date, sourceDataType, value); } try { return format.parse((String) value); } catch (ParseException e) { if (format instanceof SimpleDateFormat) throw new InvalidDataFormatException("expected " + sourceDataType.toString() + " pattern '" + ((SimpleDateFormat) format).toPattern() + "' for value '" + value.toString() + "'", e); else throw new InvalidDataFormatException("expected " + sourceDataType.toString() + " pattern '" + "unknown" + "' for value '" + value.toString() + "'", e); } } public Object fromDate(Type targetType, Date value) { DataType targetDataType = DataType.valueOf(targetType.getName()); switch (targetDataType) { case Date: return value; case DateTime: return this.getDateTimeFormat().format(value); case Day: return this.getDayFormat().format(value); case Month: return this.getMonthFormat().format(value); case MonthDay: return this.getMonthDayFormat().format(value); case Time: return this.getTimeFormat().format(value); case Year: return this.getYearFormat().format(value); case YearMonth: return this.getYearMonthFormat().format(value); case YearMonthDay: return this.getYearMonthDayFormat().format(value); case Long: return new Long(value.getTime()); case String: // use format with max precision return this.getDateTimeFormat().format(value); case Duration: return new Duration(value.getTime()); default: throw new InvalidDataConversionException(targetDataType, DataType.Date, value); } } public String toTemporalDataType(Type targetType, Type sourceType, Object value) { DataType targetDataType = DataType.valueOf(targetType.getName()); DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (sourceDataType) { case Date: case String: default: throw new InvalidDataConversionException(targetDataType, sourceDataType, value); } } public Object fromTemporalDataType(Type targetType, Type sourceType, String value) { DataType targetDataType = DataType.valueOf(targetType.getName()); DataType sourceDataType = DataType.valueOf(sourceType.getName()); switch (targetDataType) { default: throw new InvalidDataConversionException(targetDataType, sourceDataType, value); } } /** * Returns a primitive Java class, wherever possible, for * the given SDO data-type (as * per the SDO Specification 2.10 Section 8.1), and where * no primitive exists for the give SDO datatype, the appropriate * class is returned. * @param dataType the SDO datatype * @return the primitive Java class. */ public Class<?> toPrimitiveJavaClass(DataType dataType) { switch (dataType) { case Boolean: return boolean.class; case Byte: return byte.class; case Bytes: return byte[].class; case Character: return char.class; case Date: return java.util.Date.class; case DateTime: return String.class; case Day: return String.class; case Decimal: return java.math.BigDecimal.class; case Double: return double.class; case Duration: return String.class; case Float: return float.class; case Int: return int.class; case Integer: return java.math.BigInteger.class; case Long: return long.class; case Month: return String.class; case MonthDay: return String.class; case Object: return java.lang.Object.class; case Short: return short.class; case String: return String.class; case Strings: return java.util.List.class; // of String case Time: return String.class; case URI: return String.class; case Year: return String.class; case YearMonth: return String.class; case YearMonthDay: return String.class; default: throw new PlasmaDataObjectException("unknown SDO datatype, " + dataType.toString()); } } /** * Returns a primitive wrapper Java class, wherever possible, for * the given SDO data-type (as * per the SDO Specification 2.10 Section 8.1), and where * no primitive exists for the give SDO datatype, the appropriate * class is returned. * @param dataType the SDO datatype * @return the primitive Java class. */ public Class<?> toWrapperJavaClass(DataType dataType) { switch (dataType) { case Boolean: return Boolean.class; case Byte: return Byte.class; case Bytes: return byte[].class; case Character: return Character.class; case Date: return java.util.Date.class; case DateTime: return String.class; case Day: return String.class; case Decimal: return java.math.BigDecimal.class; case Double: return Double.class; case Duration: return String.class; case Float: return Float.class; case Int: return Integer.class; case Integer: return java.math.BigInteger.class; case Long: return Long.class; case Month: return String.class; case MonthDay: return String.class; case Object: return java.lang.Object.class; case Short: return Short.class; case String: return String.class; case Strings: return java.util.List.class; // of String case Time: return String.class; case URI: return String.class; case Year: return String.class; case YearMonth: return String.class; case YearMonthDay: return String.class; default: throw new PlasmaDataObjectException("unknown SDO datatype, " + dataType.toString()); } } public List<DataType> getAllowableTargetTypes(DataType dataType) { List<DataType> result = new ArrayList<DataType>(); switch (dataType) { case Boolean: result.add(DataType.Boolean); result.add(DataType.String); break; case Byte: result.add(DataType.Byte); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.Short); result.add(DataType.String); break; case Bytes: result.add(DataType.Bytes); result.add(DataType.String); result.add(DataType.Integer); break; case Character: result.add(DataType.Character); result.add(DataType.String); break; case Decimal: result.add(DataType.Decimal); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.Integer); result.add(DataType.String); break; case Double: result.add(DataType.Double); result.add(DataType.Byte); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.Short); result.add(DataType.Decimal); result.add(DataType.Integer); result.add(DataType.String); break; case Float: result.add(DataType.Float); result.add(DataType.Byte); result.add(DataType.Double); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.Short); result.add(DataType.Decimal); result.add(DataType.Integer); result.add(DataType.String); break; case Int: result.add(DataType.Int); result.add(DataType.Byte); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Long); result.add(DataType.Short); result.add(DataType.Decimal); result.add(DataType.Integer); result.add(DataType.String); break; case Integer: result.add(DataType.Integer); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.Bytes); result.add(DataType.Decimal); result.add(DataType.String); break; case Long: result.add(DataType.Long); result.add(DataType.Byte); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Short); result.add(DataType.Decimal); result.add(DataType.Integer); result.add(DataType.Date); result.add(DataType.String); break; case Short: result.add(DataType.Short); result.add(DataType.Byte); result.add(DataType.Double); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Long); result.add(DataType.String); break; case String: result.add(DataType.String); result.add(DataType.Boolean); result.add(DataType.Byte); result.add(DataType.Bytes); result.add(DataType.Character); result.add(DataType.Date); result.add(DataType.DateTime); result.add(DataType.Day); result.add(DataType.Decimal); result.add(DataType.Double); result.add(DataType.Duration); result.add(DataType.Float); result.add(DataType.Int); result.add(DataType.Integer); result.add(DataType.Long); result.add(DataType.Month); result.add(DataType.MonthDay); result.add(DataType.Short); result.add(DataType.Strings); result.add(DataType.Time); result.add(DataType.URI); result.add(DataType.Year); result.add(DataType.YearMonth); result.add(DataType.YearMonthDay); break; case Strings: result.add(DataType.Strings); result.add(DataType.String); break; case Date: result.add(DataType.Date); result.add(DataType.Long); result.add(DataType.String); break; case Duration: result.add(DataType.Duration); result.add(DataType.Date); result.add(DataType.String); break; case DateTime: result.add(DataType.DateTime); result.add(DataType.Date); result.add(DataType.String); break; case Day: result.add(DataType.Day); result.add(DataType.Date); result.add(DataType.String); break; case Month: result.add(DataType.Month); result.add(DataType.Date); result.add(DataType.String); break; case MonthDay: result.add(DataType.MonthDay); result.add(DataType.Date); result.add(DataType.String); break; case Year: result.add(DataType.Year); result.add(DataType.Date); result.add(DataType.String); break; case YearMonth: result.add(DataType.YearMonth); result.add(DataType.Date); result.add(DataType.String); break; case YearMonthDay: result.add(DataType.YearMonthDay); result.add(DataType.Date); result.add(DataType.String); break; case Time: result.add(DataType.Time); result.add(DataType.Date); result.add(DataType.String); break; case URI: result.add(DataType.String); break; case Object: default: } return result; } private String toHexString(byte[] block) { StringBuffer buf = new StringBuffer(); char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; int len = block.length; int high = 0; int low = 0; for (int i = 0; i < len; i++) { high = ((block[i] & 0xf0) >> 4); low = (block[i] & 0x0f); buf.append(hexChars[high]); buf.append(hexChars[low]); } return buf.toString(); } }