/**
   * Set a property's value.
   *
   * @param lastProperty the property to queries.
   * @param lastDataObject the DataObject, owner of the queried property
   * @param numInLastProperty the index number in the value list of the above property
   * @param value the value to be set as the target property's value
   * @param convertValue boolean used for set if we should convert the value
   */
  private void set(
      Property lastProperty,
      DataObject lastDataObject,
      int numInLastProperty,
      Object value,
      boolean convertValue) {
    if (numInLastProperty == -1) {
      if (lastDataObject != null) {
        if (convertValue) {
          DataHelper dataHelper =
              ((SDODataObject) lastDataObject).getType().getHelperContext().getDataHelper();
          value = dataHelper.convert(lastProperty, value);
        }
        lastDataObject.set(lastProperty, value);
      } else {
        throw new IllegalArgumentException("lastDataObject is null");
      }
    } else { // case like set("a/b.1", List) will cause a list be added into a existed list
      List objects = lastDataObject.getList(lastProperty);

      if (convertValue) {
        DataHelper dataHelper =
            ((SDODataObject) lastDataObject).getType().getHelperContext().getDataHelper();
        value = dataHelper.convert(lastProperty.getType(), value);
      }

      Sequence seq = lastDataObject.getSequence();
      if (seq != null) {
        seq.setValue(numInLastProperty, value);
      } else {
        objects.set(numInLastProperty, value);
      }
    }
  }
  /**
   * Create a shallow copy of the DataObject dataObject: Creates a new DataObject copiedDataObject
   * with the same values as the source dataObject for each property where
   * property.getType().isDataType() is true. The value of such a Property property in
   * copiedDataObject is: dataObject.get(property) for single-valued Properties
   * (copiedDataObject.get(property) equals() dataObject.get(property)), or a List where each member
   * is equal to the member at the same index in dataObject for multi-valued Properties
   * copiedDataObject.getList(property).get(i) equals() dataObject.getList(property).get(i) The
   * copied Object is unset for each Property where property.getType().isDataType() is false since
   * they are not copied. Read-only properties are copied. A copied object shares metadata with the
   * source object sourceDO.getType() == copiedDO.getType() If a ChangeSummary is part of the source
   * DataObject the copy has a new, empty ChangeSummary. Logging state is the same as the source
   * ChangeSummary.
   *
   * @param dataObject to be copied
   * @return copy of dataObject
   */
  public DataObject copyShallow(DataObject dataObject) {
    if (null == dataObject) {
      return null;
    }
    SDODataObject copy =
        (SDODataObject)
            getHelperContext()
                .getDataFactory()
                .create(dataObject.getType().getURI(), dataObject.getType().getName());

    List ocListOriginal = ((SDODataObject) dataObject)._getOpenContentProperties();
    for (Iterator anOCIterator = ocListOriginal.iterator(); anOCIterator.hasNext(); ) {
      copy.addOpenContentProperty((Property) anOCIterator.next());
    }

    List ocAttrsListOriginal = ((SDODataObject) dataObject)._getOpenContentPropertiesAttributes();
    for (Iterator anOCAttrIterator = ocAttrsListOriginal.iterator(); anOCAttrIterator.hasNext(); ) {
      copy.addOpenContentProperty((Property) anOCAttrIterator.next());
    }

    List allProperties = copy.getInstanceProperties(); // start iterating all copy's properties
    Iterator iterProperties = allProperties.iterator();
    while (iterProperties.hasNext()) {
      SDOProperty eachProperty = (SDOProperty) iterProperties.next();
      if (dataObject.isSet(eachProperty)) {
        Object o = getValue((SDODataObject) dataObject, eachProperty, null);
        if (eachProperty.getType().isDataType()) {
          if (!eachProperty.getType().isChangeSummaryType()) {
            // we defer sequence updates at this point
            copy.setInternal(eachProperty, o, false); // make copy if current property is datatype
          }
        }
      }
    }

    if (dataObject.getType().isSequenced()) {
      List settings = ((SDOSequence) dataObject.getSequence()).getSettings();
      for (int index = 0, size = dataObject.getSequence().size(); index < size; index++) {
        Setting nextSetting = (Setting) settings.get(index);

        Property prop = dataObject.getSequence().getProperty(index);
        if (prop == null || ((SDOType) prop.getType()).isDataType()) {
          Setting copySetting = nextSetting.copy(copy);
          copy.getSequence().getSettings().add(copySetting);
          copy.getSequence().addValueToSettings(copySetting);
        }
      }
    }

    if ((copy != null)
        && (copy.getChangeSummary() != null)
        && (copy.getType().getChangeSummaryProperty() != null)) {
      if (((SDODataObject) dataObject).getChangeSummary().isLogging()) {
        copy.getChangeSummary().setLogging(true);
      }
    }

    return copy;
  }
 public void testSetDefineOpenContent() throws Exception {
   rootDataObject.set("addressOpenContent", childDataObject);
   Property openProp = rootDataObject.getInstanceProperty("addressOpenContent");
   assertNotNull(openProp);
   assertTrue(openProp.isOpenContent());
   assertTrue(openProp.isContainment());
   assertFalse(openProp.isMany());
   assertEquals(childDataObject.getType(), openProp.getType());
 }
 public void testSetDefineOpenContentSimple() throws Exception {
   rootDataObject.set("stringOpenContent", "someString");
   Property openProp = rootDataObject.getInstanceProperty("stringOpenContent");
   assertNotNull(openProp);
   assertTrue(openProp.isOpenContent());
   assertFalse(openProp.isContainment());
   assertFalse(openProp.isMany());
   assertEquals(SDOConstants.SDO_STRING, openProp.getType());
 }
 public void testSetDefineOpenContentSimple2() throws Exception {
   BigInteger value = new BigInteger("123");
   rootDataObject.set("stringOpenContent", value);
   Property openProp = rootDataObject.getInstanceProperty("stringOpenContent");
   assertNotNull(openProp);
   assertTrue(openProp.isOpenContent());
   assertFalse(openProp.isContainment());
   assertFalse(openProp.isMany());
   assertEquals(SDOConstants.SDO_INTEGER, openProp.getType());
 }
 public void testSetDefineOpenContentManyProperty() throws Exception {
   List value = new ArrayList();
   value.add(childDataObject);
   rootDataObject.set("addressOpenContent", value);
   Property openProp = rootDataObject.getInstanceProperty("addressOpenContent");
   assertNotNull(openProp);
   assertTrue(openProp.isOpenContent());
   assertTrue(openProp.isContainment());
   assertTrue(openProp.isMany());
   assertEquals(childDataObject.getType(), openProp.getType());
 }
  public void testSetDefineOpenContentManySimpleProperty() throws Exception {
    List value = new ArrayList();
    value.add(new Integer(4));
    rootDataObject.set("addressOpenContent", value);
    Property openProp = rootDataObject.getInstanceProperty("addressOpenContent");
    assertNotNull(openProp);
    assertTrue(openProp.isOpenContent());
    assertFalse(openProp.isContainment());
    assertTrue(openProp.isMany());
    assertEquals(SDOConstants.SDO_INTOBJECT, openProp.getType());

    assertTrue(rootDataObject.isSet("addressOpenContent"));
    rootDataObject.unset("addressOpenContent");
    assertFalse(rootDataObject.isSet("addressOpenContent"));
  }
  /**
   * Creates an XMLDocument with the specified XML rootElement for the DataObject.
   *
   * @param dataObject specifies DataObject to be saved
   * @param rootElementURI the Target Namespace URI of the root XML element
   * @param rootElementName the Name of the root XML element
   * @return XMLDocument a new XMLDocument set with the specified parameters.
   */
  public XMLDocument createDocument(
      DataObject dataObject, String rootElementURI, String rootElementName) {
    SDOXMLDocument document = new SDOXMLDocument();
    document.setRootObject(dataObject);
    document.setRootElementURI(rootElementURI);
    if (rootElementName != null) {
      document.setRootElementName(rootElementName);
    }

    Property globalProp =
        getHelperContext().getXSDHelper().getGlobalProperty(rootElementURI, rootElementName, true);
    if (null != globalProp) {
      document.setSchemaType(((SDOType) globalProp.getType()).getXsdType());
    }

    document.setEncoding(SDOXMLDocument.DEFAULT_XML_ENCODING);
    document.setXMLVersion(SDOXMLDocument.DEFAULT_XML_VERSION);

    return document;
  }
  public void testSetDefineOpenContentManyPropertyContainmentChild() throws Exception {
    SDOType typeType = (SDOType) typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.TYPE);

    List value = new ArrayList();
    Type addressSDOType = typeHelper.getType("my.uri", "address");
    DataObject childDataObjectContainment = dataFactory.create(addressSDOType);

    DataObject someOther = dataFactory.create(typeType);
    someOther.set("name", "someOther");
    someOther.set("uri", "my.uri");
    addProperty(someOther, "test", addressSDOType, true, false, true);
    Type someOtherParentType = typeHelper.define(someOther);
    DataObject someOtherParentDO = dataFactory.create(someOtherParentType);
    someOtherParentDO.set("test", childDataObjectContainment);

    value.add(childDataObjectContainment);
    rootDataObject.set("addressOpenContent", value);
    Property openProp = rootDataObject.getInstanceProperty("addressOpenContent");
    assertNotNull(openProp);
    assertTrue(openProp.isOpenContent());
    assertFalse(openProp.isContainment());
    assertTrue(openProp.isMany());
    assertEquals(childDataObject.getType(), openProp.getType());
  }
  /**
   * access the wanted values through path and convert it into required java class. If conversion is
   * not supported, exception is thrown.
   *
   * @param path string representation of accessing path
   * @param cls the java class that accessed value is to be converted to
   * @param caller the DataObject that pass the path in
   * @return values to be accessed
   * @throws ClassCastException
   */
  public Object convertObjectToValueByPath(String path, Class cls, DataObject caller)
      throws ClassCastException {
    if ((null == path) || (path == "")) {
      throw new ClassCastException("Attempting null value conversion.");
    }
    try {
      int lastSlashIndex = path.lastIndexOf('/');
      SDODataObject lastDataObject;
      String lastPropertyName;
      Property lastProperty;
      int numInLastProperty = -1;

      // to do: if "/" or ".." lastDataObject = container or root
      if (-1 < lastSlashIndex) { // case 1 "a/b/c"
        String frag = path.substring(lastSlashIndex + 1);
        int indexOfDot = frag.lastIndexOf('.');
        int indexOfOpenBracket = frag.lastIndexOf('[');
        int indexOfCloseBracket = frag.lastIndexOf(']');
        numInLastProperty =
            getNumberInFrag(frag, indexOfDot, indexOfOpenBracket, indexOfCloseBracket);
        lastPropertyName =
            getPropertyNameInFrag(
                frag,
                numInLastProperty,
                indexOfDot,
                indexOfOpenBracket); // getPropertyNameFromFragment(path.substring(lastSlashIndex +
        // 1));// get last property name on path for case 1
        lastDataObject =
            (SDODataObject)
                caller.getDataObject(
                    path.substring(0, lastSlashIndex)); // get last dataobject on path
        if (lastDataObject == null) {
          return null;
        }
        lastProperty =
            lastDataObject.getInstanceProperty(lastPropertyName); // get property of this dataobject
      } else { // case 2 "a"
        // to do: call eextractPositionAndPropertyName() here
        String frag = path;
        int indexOfDot = frag.lastIndexOf('.');
        int indexOfOpenBracket = frag.lastIndexOf('[');
        int indexOfCloseBracket = frag.lastIndexOf(']');
        numInLastProperty =
            getNumberInFrag(frag, indexOfDot, indexOfOpenBracket, indexOfCloseBracket);
        lastPropertyName =
            getPropertyNameInFrag(
                frag,
                numInLastProperty,
                indexOfDot,
                indexOfOpenBracket); // getPropertyNameFromFragment(path);// get last property name
        // on path for case 1
        lastDataObject = (SDODataObject) caller;
        if (lastDataObject == null) {
          return null;
        }
        lastProperty =
            caller.getInstanceProperty(lastPropertyName); // get property of this dataobject
      }

      if ((lastProperty != null)
          && (cls == Date.class)
          && lastProperty
              .getType()
              .equals(
                  SDOConstants
                      .SDO_STRING)) { // in case getDate, for string property, use DataHelper
        DataHelper dHelper = HelperProvider.getDefaultContext().getDataHelper();
        String dateString;
        if (numInLastProperty == -1) {
          dateString = (String) lastDataObject.get(lastProperty);
        } else {
          dateString = (String) (lastDataObject.getList(lastProperty)).get(numInLastProperty);
        }
        return dHelper.toDate(dateString);
      }
      return lastDataObject.convertObjectToValue(lastProperty, numInLastProperty, cls);
    } catch (
        IllegalArgumentException
            e) { // according to exception table 1st row, when get(Property) and get(Index) throw
      // IllegalArgument, get(String) return null
      throw new ClassCastException("Conversion is not supported.");
      // return null;
    }
  }
  /**
   * Access the DataObject value by using the fragment containing query informations.
   *
   * @param frag one string fragment in the path
   * @param openBracketIndex the index of open bracket in a fragment
   * @param closeBracketIndex the index of close bracket in a fragment
   * @param equalsignIndex the index of equalsign in string fragment quoted by brackets
   * @param caller the DataObject that passes the path information in
   * @param callerProperty the name of the property
   * @return the DataObject as value of the property having name as the above callerProperty
   */
  private DataObject getDataObjectFromQuery(
      String frag,
      int openBracketIndex,
      int closeBracketIndex,
      int equalsignIndex,
      DataObject caller,
      String callerProperty) {
    try {
      // trim off any whitespace for property names
      String propertyNameOfQryDataObject =
          frag.substring(openBracketIndex + 1, equalsignIndex + openBracketIndex).trim();
      List objects = caller.getList(caller.getInstanceProperty(callerProperty));
      String query = frag.substring(equalsignIndex + openBracketIndex + 1, closeBracketIndex);
      String value = null;
      int firstQuoteIndex = query.indexOf('\'');
      int lastQuoteIndex = query.lastIndexOf('\'');
      if ((firstQuoteIndex == -1)
          && (lastQuoteIndex == -1)) { // !! note: case: [number=1'23'] is assume not to happen !!
        firstQuoteIndex = query.indexOf("\"");
        lastQuoteIndex = query.lastIndexOf("\"");
      }
      if ((firstQuoteIndex != -1)
          && (lastQuoteIndex != -1)
          && (firstQuoteIndex < lastQuoteIndex)) { // quoted string existed
        value = query.substring(firstQuoteIndex + 1, lastQuoteIndex);
      } else {
        // if the value is not enclosed on quotes, trim off any whitespace
        value = query.trim();
      }
      Iterator iterObjects = objects.iterator();
      Object queryValue = value;
      Object actualValue = null;
      while (iterObjects.hasNext()) {
        DataObject cur = (DataObject) iterObjects.next();
        Property p = cur.getInstanceProperty(propertyNameOfQryDataObject);
        if (p != null) {
          try {
            queryValue =
                XMLConversionManager.getDefaultXMLManager()
                    .convertObject(queryValue, p.getType().getInstanceClass());
          } catch (ConversionException e) {
            // do nothing, skip
          }

          if (!p.isMany()) {
            actualValue = cur.get(p);
            if (actualValue.equals(queryValue)) {
              return cur;
            }
          } else { // case p is many type
            List values = cur.getList(p);
            Iterator iterValues = values.iterator();

            while (iterValues.hasNext()) {
              actualValue = iterValues.next();
              if (actualValue.equals(queryValue)) {
                return cur;
              }
            }
          }
        }
      }

      return null;
    } catch (IllegalArgumentException e) {
      return null;
    }
  }
  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;
  }
 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;
 }
 private int convertToSqlType(Property property, Object value) {
   int result;
   if (!property.getType().isDataType())
     throw new IllegalArgumentException("expected data type property, not " + property.toString());
   DataType dataType = DataType.valueOf(property.getType().getName());
   switch (dataType) {
     case String:
     case URI:
     case Month:
     case MonthDay:
     case Day:
     case Time:
     case Year:
     case YearMonth:
     case YearMonthDay:
     case Duration:
     case Strings:
       result = java.sql.Types.VARCHAR;
       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.
       result = java.sql.Types.TIMESTAMP;
       break;
     case DateTime:
       result = java.sql.Types.TIMESTAMP;
       // FIXME: so what SDO datatype maps to a SQL timestamp??
       break;
     case Decimal:
       result = java.sql.Types.DECIMAL;
       break;
     case Bytes:
       // FIXME: how do we know whether a Blob here
       result = java.sql.Types.VARBINARY;
       break;
     case Byte:
       result = java.sql.Types.VARBINARY;
       break;
     case Boolean:
       result = java.sql.Types.BOOLEAN;
       break;
     case Character:
       result = java.sql.Types.CHAR;
       break;
     case Double:
       result = java.sql.Types.DOUBLE;
       break;
     case Float:
       result = java.sql.Types.FLOAT;
       break;
     case Int:
       result = java.sql.Types.INTEGER;
       break;
     case Integer:
       result = java.sql.Types.BIGINT;
       break;
     case Long:
       result = java.sql.Types.INTEGER; // FIXME: no JDBC long??
       break;
     case Short:
       result = java.sql.Types.SMALLINT;
       break;
     case Object:
     default:
       result = java.sql.Types.VARCHAR;
       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;
  }
  /**
   * 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;
  }