private Object convertToSqlValue(Property property, Object value) throws SQLException {

    if (!property.getType().isDataType())
      throw new IllegalArgumentException("expected data type property, not " + property.toString());
    DataType dataType = DataType.valueOf(property.getType().getName());
    Object result;
    switch (dataType) {
      case String:
      case URI:
      case Month:
      case MonthDay:
      case Day:
      case Time:
      case Year:
      case YearMonth:
      case YearMonthDay:
      case Duration:
        result = DataConverter.INSTANCE.toString(property.getType(), value);
        break;
      case Date:
        // Plasma SDO allows more precision than just month/day/year
        // in an SDO date datatype, and using java.sql.Date will truncate
        // here so use java.sql.Timestamp.
        Date date = DataConverter.INSTANCE.toDate(property.getType(), value);
        result = new java.sql.Timestamp(date.getTime());
        break;
      case DateTime:
        date = DataConverter.INSTANCE.toDate(property.getType(), value);
        result = new java.sql.Timestamp(date.getTime());
        break;
      case Decimal:
        result = DataConverter.INSTANCE.toDecimal(property.getType(), value);
        break;
      case Bytes:
        result = DataConverter.INSTANCE.toBytes(property.getType(), value);
        break;
      case Byte:
        result = DataConverter.INSTANCE.toByte(property.getType(), value);
        break;
      case Boolean:
        result = DataConverter.INSTANCE.toBoolean(property.getType(), value);
        break;
      case Character:
        result = DataConverter.INSTANCE.toString(property.getType(), value);
        break;
      case Double:
        result = DataConverter.INSTANCE.toDouble(property.getType(), value);
        break;
      case Float:
        result = DataConverter.INSTANCE.toDouble(property.getType(), value);
        break;
      case Int:
        result = DataConverter.INSTANCE.toInt(property.getType(), value);
        break;
      case Integer:
        result = DataConverter.INSTANCE.toInteger(property.getType(), value);
        break;
      case Long:
        result = DataConverter.INSTANCE.toLong(property.getType(), value);
        break;
      case Short:
        result = DataConverter.INSTANCE.toShort(property.getType(), value);
        break;
      case Strings:
        result = DataConverter.INSTANCE.toString(property.getType(), value);
        break;
      case Object:
      default:
        result = DataConverter.INSTANCE.toString(property.getType(), value);
        break;
    }

    return result;
  }
  /**
   * Converts the given value from bytes based on data type and cardinality information for the
   * given property. For 'many' or multi-valued properties, if the SDO Java type for the property is
   * not already String, the value is first converted from a String using the SDO conversion which
   * uses java.util.Arrays formatting, resulting in an array of primitive types. For non 'many' or
   * singular properties, only the HBase Bytes utility is used.
   *
   * @param targetProperty the property
   * @param value the bytes value
   * @return the converted object
   * @throws IllegalArgumentException if the given property is not a data type property
   */
  public Object fromBytes(Property targetProperty, byte[] value) {
    Object result = null;

    if (!targetProperty.getType().isDataType())
      throw new IllegalArgumentException(
          "property " + targetProperty.toString() + " is not a datatype property");

    DataType targetDataType = DataType.valueOf(targetProperty.getType().getName());

    switch (targetDataType) {
        // Data types stored as String bytes in HBase
      case String:
      case Strings:
      case URI:
      case Month:
      case MonthDay:
      case Day:
      case Time:
      case Year:
      case YearMonth:
      case YearMonthDay:
      case Duration:
        String resultStr = Bytes.toString(value);
        result = DataConverter.INSTANCE.fromString(targetProperty, resultStr);
        break;
      case Date:
        resultStr = Bytes.toString(value);
        result = DataConverter.INSTANCE.fromString(targetProperty, resultStr);
        break;
      case DateTime:
        // NOTE: remember datetime is a String Java representation in SDO 2.1
        resultStr = Bytes.toString(value);
        result = DataConverter.INSTANCE.fromString(targetProperty, resultStr);
        break;

        // Data types stored by directly converting from primitive types to bytes in HBase.
        // TODO: for these data types determine if there is a way to "delimit" multiple values yet
        // not take the extra and expensive step of first converting to delimited String.
      case Decimal:
        if (!targetProperty.isMany()) result = Bytes.toBigDecimal(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Bytes:
        if (!targetProperty.isMany()) result = value; // already bytes
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Byte:
        if (!targetProperty.isMany()) {
          // NOTE: no toByte method as would expect as there is opposite method, see below
          // e.g. Bytes.toByte(value);
          if (value != null) {
            if (value.length > 2)
              log.warn(
                  "truncating "
                      + String.valueOf(value.length)
                      + " length byte array for target data type 'byte'");
            result = value[0];
          }
        } else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Boolean:
        if (!targetProperty.isMany()) result = Bytes.toBoolean(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Character:
        if (!targetProperty.isMany()) result = Character.valueOf(Bytes.toString(value).charAt(0));
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Double:
        if (!targetProperty.isMany()) result = Bytes.toDouble(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Float:
        if (!targetProperty.isMany()) result = Bytes.toFloat(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Int:
        if (!targetProperty.isMany()) result = Bytes.toInt(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Integer:
        if (!targetProperty.isMany()) result = new BigInteger(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Long:
        if (!targetProperty.isMany()) result = Bytes.toLong(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Short:
        if (!targetProperty.isMany()) result = Bytes.toShort(value);
        else result = DataConverter.INSTANCE.fromString(targetProperty, Bytes.toString(value));
        break;
      case Object:
        // FIXME: custom serialization?
      default:
        result = Bytes.toString(value);
        break;
    }

    return result;
  }
 private Object convertFrom(ResultSet rs, int columnIndex, int sourceType, Property property)
     throws SQLException {
   Object result = null;
   if (!property.getType().isDataType())
     throw new IllegalArgumentException("expected data type property, not " + property.toString());
   DataType targetDataType = DataType.valueOf(property.getType().getName());
   switch (targetDataType) {
     case String:
     case URI:
     case Month:
     case MonthDay:
     case Day:
     case Time:
     case Year:
     case YearMonth:
     case YearMonthDay:
     case Duration:
       result = rs.getString(columnIndex);
       break;
     case Date:
       java.sql.Timestamp ts = rs.getTimestamp(columnIndex);
       if (ts != null) result = new java.util.Date(ts.getTime());
       break;
     case DateTime:
       ts = rs.getTimestamp(columnIndex);
       if (ts != null) {
         // format DateTime String for SDO
         java.util.Date date = new java.util.Date(ts.getTime());
         result = DataConverter.INSTANCE.getDateTimeFormat().format(date);
       }
       break;
     case Decimal:
       result = rs.getBigDecimal(columnIndex);
       break;
     case Bytes:
       if (sourceType != Types.BLOB) {
         result = rs.getBytes(columnIndex);
       } else if (sourceType == Types.BLOB) {
         Blob blob = rs.getBlob(columnIndex);
         if (blob != null) {
           long blobLen = blob.length(); // for debugging
           // Note: blob.getBytes(columnIndex, blob.length()); is somehow truncating the array
           // by something like 14 bytes (?!!) even though blob.length() returns the expected
           // length
           // using getBinaryStream which is preferred anyway
           InputStream is = blob.getBinaryStream();
           try {
             byte[] bytes = IOUtils.toByteArray(is);
             long len = bytes.length; // for debugging
             result = bytes;
           } catch (IOException e) {
             throw new RDBServiceException(e);
           } finally {
             try {
               is.close();
             } catch (IOException e) {
               log.error(e.getMessage(), e);
             }
           }
         }
       }
       break;
     case Byte:
       result = rs.getByte(columnIndex);
       break;
     case Boolean:
       result = rs.getBoolean(columnIndex);
       break;
     case Character:
       result = rs.getInt(columnIndex);
       break;
     case Double:
       result = rs.getDouble(columnIndex);
       break;
     case Float:
       result = rs.getFloat(columnIndex);
       break;
     case Int:
       result = rs.getInt(columnIndex);
       break;
     case Integer:
       result = new BigInteger(rs.getString(columnIndex));
       break;
     case Long:
       result = rs.getLong(columnIndex);
       break;
     case Short:
       result = rs.getShort(columnIndex);
       break;
     case Strings:
       String value = rs.getString(columnIndex);
       if (value != null) {
         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]); // what no Java 5 sugar for this ??
         result = list;
       }
       break;
     case Object:
     default:
       result = rs.getObject(columnIndex);
       break;
   }
   return result;
 }
  /**
   * Converts the given value to bytes based on data type and cardinality information for the given
   * property. For 'many' or multi-valued properties, if the SDO Java type for the property is not
   * already String, the value is first converted to String using the SDO conversion which uses
   * java.util.Arrays formatting. For non 'many' or singular properties, only the HBase Bytes
   * utility is used.
   *
   * @param sourceProperty the source property
   * @param value the value
   * @return the bytes
   * @throws IllegalArgumentException if the given property is not a data type property
   */
  public byte[] toBytes(Property sourceProperty, Object value) {
    byte[] result;

    if (!sourceProperty.getType().isDataType())
      throw new IllegalArgumentException(
          "property " + sourceProperty.toString() + " is not a datatype property");
    DataType dataType = DataType.valueOf(sourceProperty.getType().getName());

    switch (dataType) {
        // Data types stored as String bytes in HBase
      case String:
      case Strings:
      case URI:
      case Month:
      case MonthDay:
      case Day:
      case Time:
      case Year:
      case YearMonth:
      case YearMonthDay:
      case Date:
      case Duration:
        String resultStr = DataConverter.INSTANCE.toString(sourceProperty, value);
        result = Bytes.toBytes(resultStr);
        break;
      case DateTime:
        resultStr = DataConverter.INSTANCE.toString(sourceProperty, value);
        result = Bytes.toBytes(resultStr);
        break;
        // Data types stored by directly converting from primitive types to bytes in HBase. When
        // the given property is a 'many' property, the value is first converted to String so
        // can be delimited.
      case Decimal:
        if (!sourceProperty.isMany()) {
          BigDecimal resultDecimal =
              DataConverter.INSTANCE.toDecimal(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultDecimal);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Bytes:
        if (!sourceProperty.isMany()) {
          byte[] resultBytes = DataConverter.INSTANCE.toBytes(sourceProperty.getType(), value);
          result = resultBytes;
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Byte:
        if (!sourceProperty.isMany()) {
          byte resultByte = DataConverter.INSTANCE.toByte(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultByte);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Boolean:
        if (!sourceProperty.isMany()) {
          boolean resultBool = DataConverter.INSTANCE.toBoolean(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultBool);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Character:
        if (!sourceProperty.isMany()) {
          resultStr = DataConverter.INSTANCE.toString(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultStr);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Double:
        if (!sourceProperty.isMany()) {
          double resultDouble = DataConverter.INSTANCE.toDouble(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultDouble);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Float:
        if (!sourceProperty.isMany()) {
          float resultFloat = DataConverter.INSTANCE.toFloat(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultFloat);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Int:
        if (!sourceProperty.isMany()) {
          int resultInt = DataConverter.INSTANCE.toInt(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultInt);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Integer:
        if (!sourceProperty.isMany()) {
          BigInteger resultInteger =
              DataConverter.INSTANCE.toInteger(sourceProperty.getType(), value);
          result = resultInteger.toByteArray();
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Long:
        if (!sourceProperty.isMany()) {
          long resultLong = DataConverter.INSTANCE.toLong(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultLong);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Short:
        if (!sourceProperty.isMany()) {
          short resultShort = DataConverter.INSTANCE.toShort(sourceProperty.getType(), value);
          result = Bytes.toBytes(resultShort);
        } else {
          String strResult = DataConverter.INSTANCE.toString(sourceProperty, value);
          result = Bytes.toBytes(strResult);
        }
        break;
      case Object:
        // FIXME: do we serialize objects in some custom format for hbase
      default:
        resultStr = DataConverter.INSTANCE.toString(sourceProperty.getType(), value);
        result = Bytes.toBytes(resultStr);
        break;
    }
    return result;
  }