All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fnklabs.draenei.orm.ColumnMetadata Maven / Gradle / Ivy
package com.fnklabs.draenei.orm;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.TableMetadata;
import com.fnklabs.draenei.orm.annotations.Column;
import com.fnklabs.draenei.orm.annotations.PrimaryKey;
import com.fnklabs.draenei.orm.exception.MetadataException;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
/**
* Column metadata
*
* @param Column java class type
*/
class ColumnMetadata {
public static final Logger LOGGER = LoggerFactory.getLogger(ColumnMetadata.class);
/**
* Column field java class type
*/
private final Class type;
/**
* Column name
*/
private final String name;
/**
* Field read method
*/
@NotNull
private final Method readMethod;
/**
* Field write method
*/
@NotNull
private final Method writeMethod;
/**
* DataStax column metadata to serialize and deserialize data
*/
private final com.datastax.driver.core.ColumnMetadata columnMetadata;
/**
* Enum types
*/
private final Map enumValues = new HashMap<>();
/**
* @param propertyDescriptor Field property descriptor
* @param type Column java class type
* @param name Column name
* @param columnMetadata datastax driver ColumnMetadata
*/
public ColumnMetadata(PropertyDescriptor propertyDescriptor, Class type, String name, com.datastax.driver.core.ColumnMetadata columnMetadata) {
this.columnMetadata = columnMetadata;
if (propertyDescriptor.getReadMethod() == null) {
throw new MetadataException(String.format("Can't retrieve read method for %s#%s", type.getName(), propertyDescriptor.getName()));
}
this.readMethod = propertyDescriptor.getReadMethod();
if (propertyDescriptor.getWriteMethod() == null) {
throw new MetadataException(String.format("Can't retrieve write method for %s#%s", type.getName(), propertyDescriptor.getName()));
}
this.writeMethod = propertyDescriptor.getWriteMethod();
this.type = type;
this.name = name;
if (type.isEnum()) { // todo unsafe operation. use #name() to retrieve enum name
for (T constant : type.getEnumConstants()) {
enumValues.put(constant.toString(), constant);
}
}
}
public Class getType() {
return type;
}
public String getName() {
return name;
}
protected void writeValue(@NotNull Object entity, @Nullable Object value) {
if (value == null) { // don't set null value todo check method arguments annotations for NotNull
return;
}
Method writeMethod = getWriteMethod();
try {
writeMethod.invoke(entity, value);
} catch (InvocationTargetException | IllegalAccessException e) {
LOGGER.warn("Can't invoker write method", e);
}
}
/**
* Read column value from entity
*
* @param object Entity object instance
*
* @return
*/
@Nullable
protected T readValue(Object object) {
Method readMethod = getReadMethod();
try {
return (T) readMethod.invoke(object);
} catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
LOGGER.warn("Can't invoke read method", e);
}
return null;
}
/**
* Serialize column value to cassandra data
*
* @param value Column java value
*
* @return Cassandra data
*/
protected ByteBuffer serialize(Object value) {
if (value == null) {
return null;
}
if (value.getClass().isEnum()) {
return DataType.text().serialize(value.toString(), ProtocolVersion.NEWEST_SUPPORTED);
}
return columnMetadata.getType().serialize(value, ProtocolVersion.NEWEST_SUPPORTED);
}
/**
* Deserialize data from cassandra to java type
*
* @param data Serialized cassandra type
* @param Entity class java type
*
* @return Deserialized object
*/
@SuppressWarnings("Unchecked")
protected T deserialize(@Nullable ByteBuffer data) {
if (data == null) {
return null;
}
Object deserializedObject = columnMetadata.getType().deserialize(data, ProtocolVersion.NEWEST_SUPPORTED);
if (getType().isEnum()) {
String value = (String) DataType.text().deserialize(data, ProtocolVersion.NEWEST_SUPPORTED);
return (T) enumValues.get(value);
}
return (T) deserializedObject;
}
@NotNull
private Method getReadMethod() {
return readMethod;
}
@NotNull
private Method getWriteMethod() {
return writeMethod;
}
/**
* Build column metadata from field
*
* @param propertyDescriptor Field property descriptor
* @param clazz Entity java class
*
* @return Column metadata
*/
@Nullable
protected static ColumnMetadata buildColumnMetadata(@NotNull PropertyDescriptor propertyDescriptor,
@NotNull Class clazz,
@NotNull TableMetadata tableMetadata) throws NoSuchFieldException {
String name = propertyDescriptor.getName();
Field field = clazz.getDeclaredField(name);
Column columnAnnotation = field.getDeclaredAnnotation(Column.class);
if (columnAnnotation != null) {
String columnName = getColumnName(propertyDescriptor, columnAnnotation);
com.datastax.driver.core.ColumnMetadata columnMetadata = tableMetadata.getColumn(columnName);
PrimaryKey primaryKeyAnnotation = field.getDeclaredAnnotation(PrimaryKey.class);
if (primaryKeyAnnotation != null) {
PrimaryKeyMetadata> primaryKeyMetadata = new PrimaryKeyMetadata<>(
propertyDescriptor,
columnName,
primaryKeyAnnotation.order(),
primaryKeyAnnotation.isPartitionKey(),
field.getType(),
columnMetadata
);
return primaryKeyMetadata;
}
return new ColumnMetadata<>(propertyDescriptor, field.getType(), columnName, columnMetadata);
}
return null;
}
private static String getColumnName(@NotNull PropertyDescriptor propertyDescriptor, @NotNull Column columnAnnotation) {
String columnName = columnAnnotation.name();
if (StringUtils.isEmpty(columnName)) {
columnName = propertyDescriptor.getName();
}
return columnName;
}
}