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

org.plasma.sdo.helper.DataConverter Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/**
 *         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 
 * .
 *  
 */
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 volatile 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, Map> javaClassToAllowableTypesMap;
    
    private static Map, Method> javaClassToConverterFromMethodMap;

    
    private DataConverter() {
     	
        if (javaClassToAllowableTypesMap == null) {
            javaClassToAllowableTypesMap = new HashMap, Map>();
            for (int i = 0; i < DataType.values().length; i++) {
                DataType dataTypeEnum = DataType.values()[i];
                
                Class javaClass = toPrimitiveJavaClass(dataTypeEnum);
                
                Map allowableMap = new HashMap();
                List list = getAllowableTargetTypes(dataTypeEnum);
                for (DataType allowableType : list)
                    allowableMap.put(allowableType.toString(), allowableType);                
                javaClassToAllowableTypesMap.put(javaClass, allowableMap);
            } 
        }
        if (javaClassToConverterFromMethodMap == null) {
        	javaClassToConverterFromMethodMap = new HashMap, Method>();
        	Map, 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>)new ArrayList().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>> 
            THREADLOCAL_FORMATS = new ThreadLocal>>() {
            @Override
            protected SoftReference> initialValue() {
                return new SoftReference>(
                        new HashMap());
            }
            
        };
        
        /**
         * creates a {@link SimpleDateFormat} for the requested format string.
         * 
         * @param pattern
         *            a non-null format String according to
         *            {@link SimpleDateFormat}. The format is not checked against
         *            null 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> ref = THREADLOCAL_FORMATS.get();
            Map formats = ref.get();
            if (formats == null) {
                formats = new HashMap();
                THREADLOCAL_FORMATS.set(
                        new SoftReference>(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 result = new ArrayList();
        			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 result = new ArrayList();
        			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 list = (List)value;
            Iterator 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 result = new ArrayList();
        			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 result = new ArrayList();
        			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 result = new ArrayList();
        			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 list = (List)value;
            Iterator 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 result = new ArrayList();
        			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, typeClass, 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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
            	for (String arrayValue : strings)
            		list.add(Short.valueOf(arrayValue));
            	return list;
        	}
        case Strings:  
        	if (!value.startsWith("[")) { 
                String[] values = value.split("\\s");
                List list = new ArrayList(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 = new ArrayList>();            	
            	for (String arrayValue : strings) {
                    String[] values = arrayValue.split("\\s");
                    List subList = new ArrayList(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 list = new ArrayList();            	
	            	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 list = new ArrayList();            	
            	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList();            	
                	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 list = new ArrayList(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 = new ArrayList>();            	
                	for (String arrayValue : strings) {
                        String[] values = arrayValue.split("\\s");
                        List subList = new ArrayList(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 list = new ArrayList();            	
		            	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 list = new ArrayList();            	
                	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 toStrings(Type sourceType, Object value)
    {    
        DataType sourceDataType = DataType.valueOf(sourceType.getName());
        switch (sourceDataType) {
        case Strings:
            return (List)value;
        case String:
            String[] values = ((String)value).split("\\s");
            List list = new ArrayList(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 value)
    {    
        DataType targetDataType = DataType.valueOf(targetType.getName());
        switch (targetDataType) {
        case Strings:
            return value;
        case String:
            StringBuffer buf = new StringBuffer();
            Iterator 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 getAllowableTargetTypes(DataType dataType) {
        List result = new ArrayList();
        
        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();
    }    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy