/*
* Copyright (c) 2008-2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.impl;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
import com.emc.storageos.db.client.model.AbstractChangeTrackingMap;
import com.emc.storageos.db.client.model.AbstractChangeTrackingSet;
import com.emc.storageos.db.client.model.AbstractChangeTrackingSetMap;
import com.emc.storageos.db.client.model.AbstractSerializableNestedObject;
import com.emc.storageos.db.client.model.EncryptionProvider;
import com.emc.storageos.db.client.model.NamedURI;
import com.emc.storageos.db.client.model.ScopedLabel;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.netflix.astyanax.ColumnListMutation;
import com.netflix.astyanax.model.Column;
/**
* Utility class for de/serializing an individual column
*/
public class ColumnValue {
/**
* Decrypts and sets data object field value
*
* @param column encrypted column value
* @param pd property
* @param obj wrapper object
* @param provider encryption provider
*/
public static void setEncryptedStringField(Column<CompositeColumnName> column,
PropertyDescriptor pd, Object obj, EncryptionProvider provider) {
byte[] encrypted = column.getByteArrayValue();
String val = provider.decrypt(encrypted);
try {
pd.getWriteMethod().invoke(obj, val);
} catch (final InvocationTargetException e) {
throw DatabaseException.fatals.deserializationFailedEncryptedProperty(pd.getName(), e);
} catch (final IllegalAccessException e) {
throw DatabaseException.fatals.deserializationFailedEncryptedProperty(pd.getName(), e);
}
}
public static void setField(Column<CompositeColumnName> column, PropertyDescriptor pd,
Object obj) {
try {
Class type = pd.getPropertyType();
Object objValue = null;
if (AbstractChangeTrackingSetMap.class.isAssignableFrom(type)) {
objValue = pd.getReadMethod().invoke(obj);
if (objValue == null) {
objValue = type.newInstance();
}
AbstractChangeTrackingSetMap<?> trackingMap = (AbstractChangeTrackingSetMap<?>) objValue;
String entryValue = column.getStringValue();
if (entryValue == null || entryValue.isEmpty()) {
trackingMap.removeNoTrack(column.getName().getTwo(), column.getName().getThree());
} else {
trackingMap.putNoTrack(column.getName().getTwo(), entryValue);
}
} else if (AbstractChangeTrackingMap.class.isAssignableFrom(type)) {
objValue = pd.getReadMethod().invoke(obj);
if (objValue == null) {
objValue = type.newInstance();
}
AbstractChangeTrackingMap<?> trackingMap = (AbstractChangeTrackingMap<?>) objValue;
byte[] entryValue = column.getByteArrayValue();
if (entryValue == null || entryValue.length == 0) {
trackingMap.removeNoTrack(column.getName().getTwo());
} else {
trackingMap.putNoTrack(column.getName().getTwo(), column.getByteArrayValue());
}
} else if (AbstractChangeTrackingSet.class.isAssignableFrom(type)) {
objValue = pd.getReadMethod().invoke(obj);
if (objValue == null) {
objValue = type.newInstance();
}
AbstractChangeTrackingSet trackingSet = (AbstractChangeTrackingSet) objValue;
String entryValue = column.getStringValue();
if (entryValue == null || entryValue.isEmpty()) {
trackingSet.removeNoTrack(column.getName().getTwo());
} else {
trackingSet.addNoTrack(entryValue);
}
} else {
objValue = getPrimitiveColumnValue(column, pd);
}
pd.getWriteMethod().invoke(obj, objValue);
} catch (IllegalAccessException e) {
// should never get here
throw DatabaseException.fatals.deserializationFailedProperty(pd.getName(), e);
} catch (InvocationTargetException e) {
throw DatabaseException.fatals.deserializationFailedProperty(pd.getName(), e);
} catch (InstantiationException e) {
throw DatabaseException.fatals.deserializationFailedProperty(pd.getName(), e);
}
}
public static <T> Object getPrimitiveColumnValue(Column<T> column, PropertyDescriptor pd) {
Object objValue = null;
try {
Class type = pd.getPropertyType();
if (AbstractSerializableNestedObject.class.isAssignableFrom(type)) {
objValue = type.newInstance();
AbstractSerializableNestedObject value = (AbstractSerializableNestedObject) objValue;
value.loadBytes(column.getByteArrayValue());
} else if (type == String.class) {
objValue = column.getStringValue();
} else if (type == URI.class) {
objValue = URI.create(column.getStringValue());
} else if (type == Byte.class) {
objValue = (byte) (column.getIntegerValue() & 0xff);
} else if (type == Boolean.class) {
objValue = column.getBooleanValue();
} else if (type == Short.class) {
objValue = (short) (column.getShortValue());
} else if (type == Integer.class) {
objValue = column.getIntegerValue();
} else if (type == Long.class) {
objValue = column.getLongValue();
} else if (type == Float.class) {
objValue = (float) column.getDoubleValue();
} else if (type == Double.class) {
objValue = column.getDoubleValue();
} else if (type == Date.class) {
objValue = column.getDateValue();
} else if (type == NamedURI.class) {
objValue = NamedURI.fromString(column.getStringValue());
} else if (type == byte[].class) {
objValue = column.getByteArrayValue();
} else if (type == ScopedLabel.class) {
objValue = ScopedLabel.fromString(column.getStringValue());
} else if (type.isEnum()) {
objValue = Enum.valueOf(type, column.getStringValue());
} else if (type == Calendar.class) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(column.getLongValue());
objValue = cal;
} else {
throw new UnsupportedOperationException();
}
} catch (IllegalAccessException e) {
// should never get here
throw DatabaseException.fatals.deserializationFailedProperty(pd.getName(), e);
} catch (InstantiationException e) {
throw DatabaseException.fatals.deserializationFailedProperty(pd.getName(), e);
}
return objValue;
}
/**
* Serialize field into db query
*
* @param columns batch query
* @param name composite column name
* @param val column value
* @param ttl time to live in seconds for this column
* @throws DatabaseException
*/
public static <T> void setColumn(ColumnListMutation<T> columns, T name, Object val, Integer ttl) {
if (val == null) {
columns.putEmptyColumn(name, ttl);
} else if (val.getClass() == byte[].class) {
columns.putColumn(name, (byte[]) val, ttl);
} else if (val.getClass() == String.class) {
columns.putColumn(name, (String) val, ttl);
} else if (val.getClass() == URI.class) {
columns.putColumn(name, val.toString(), ttl);
} else if (val.getClass() == Byte.class) {
columns.putColumn(name, (Byte) val & 0xff, ttl);
} else if (val.getClass() == Boolean.class) {
columns.putColumn(name, (Boolean) val, ttl);
} else if (val.getClass() == Short.class) {
columns.putColumn(name, (Short) val, ttl);
} else if (val.getClass() == Integer.class) {
columns.putColumn(name, (Integer) val, ttl);
} else if (val.getClass() == Long.class) {
columns.putColumn(name, (Long) val, ttl);
} else if (val.getClass() == Float.class) {
columns.putColumn(name, (Float) val, ttl);
} else if (val.getClass() == Double.class) {
columns.putColumn(name, (Double) val, ttl);
} else if (val.getClass() == Date.class) {
columns.putColumn(name, (Date) val, ttl);
} else if (val.getClass() == NamedURI.class) {
columns.putColumn(name, val.toString(), ttl);
} else if (val.getClass() == ScopedLabel.class) {
columns.putColumn(name, val.toString(), ttl);
} else if (val instanceof Calendar) {
columns.putColumn(name, ((Calendar) val).getTimeInMillis(), ttl);
} else if (val.getClass().isEnum()) {
columns.putColumn(name, ((Enum<?>) val).name(), ttl);
} else {
throw DatabaseException.fatals.serializationFailedUnsupportedType(name);
}
}
/**
* Serialize field into db query
*
* @param columns batch query
* @param name composite column name
* @param val column value
* @throws DatabaseException
*/
public static void setColumn(ColumnListMutation<CompositeColumnName> columns,
CompositeColumnName name, Object val) {
setColumn(columns, name, val, null);
}
}