Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Mapping: Per-column and per-class TTL specification added. #120

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+461 −31
Split
@@ -0,0 +1,13 @@
+package com.netflix.astyanax.mapping;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+/**
+ * Allows for any annotations to be used to mark columns in a bean
+ */
+public interface AnnotationSet2<ID extends Annotation, COLUMN extends Annotation>
+ extends AnnotationSet<ID, COLUMN> {
+
+ public int getColumnTtl(Field field, COLUMN annotation);
+}
@@ -49,37 +49,42 @@
static <T> void setColumnMutationFromField(T instance, Field field,
String columnName, ColumnListMutation<String> mutation) {
+ setColumnMutationFromField(instance, field, columnName, mutation, null);
+ }
+
+ static <T> void setColumnMutationFromField(T instance, Field field,
+ String columnName, ColumnListMutation<String> mutation, Integer ttl) {
try {
Object objValue = field.get(instance);
if (objValue != null) {
if ((objValue.getClass() == Byte.class)
|| (objValue.getClass() == Byte.TYPE)) {
- mutation.putColumn(columnName, (Byte) objValue & 0xff, null);
+ mutation.putColumn(columnName, (Byte) objValue & 0xff, ttl);
} else if ((objValue.getClass() == Boolean.class)
|| (objValue.getClass() == Boolean.TYPE)) {
- mutation.putColumn(columnName, (Boolean) objValue, null);
+ mutation.putColumn(columnName, (Boolean) objValue, ttl);
} else if ((objValue.getClass() == Short.class)
|| (objValue.getClass() == Short.TYPE)) {
- mutation.putColumn(columnName, (Short) objValue, null);
+ mutation.putColumn(columnName, (Short) objValue, ttl);
} else if ((objValue.getClass() == Integer.class)
|| (objValue.getClass() == Integer.TYPE)) {
- mutation.putColumn(columnName, (Integer) objValue, null);
+ mutation.putColumn(columnName, (Integer) objValue, ttl);
} else if ((objValue.getClass() == Long.class)
|| (objValue.getClass() == Long.TYPE)) {
- mutation.putColumn(columnName, (Long) objValue, null);
+ mutation.putColumn(columnName, (Long) objValue, ttl);
} else if ((objValue.getClass() == Float.class)
|| (objValue.getClass() == Float.TYPE)) {
- mutation.putColumn(columnName, (Float) objValue, null);
+ mutation.putColumn(columnName, (Float) objValue, ttl);
} else if ((objValue.getClass() == Double.class)
|| (objValue.getClass() == Double.TYPE)) {
- mutation.putColumn(columnName, (Double) objValue, null);
+ mutation.putColumn(columnName, (Double) objValue, ttl);
} else if (objValue.getClass() == Date.class) {
- mutation.putColumn(columnName, (Date) objValue, null);
+ mutation.putColumn(columnName, (Date) objValue, ttl);
} else if (objValue.getClass() == String.class) {
- mutation.putColumn(columnName, (String) objValue, null);
- } else if(objValue.getClass() == byte[].class) {
- mutation.putColumn(columnName, (byte[]) objValue, null);
+ mutation.putColumn(columnName, (String) objValue, ttl);
+ } else if (objValue.getClass() == byte[].class) {
+ mutation.putColumn(columnName, (byte[]) objValue, ttl);
} else {
throw new UnsupportedOperationException();
}
@@ -1,6 +1,10 @@
package com.netflix.astyanax.mapping;
-import java.lang.annotation.*;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
@Documented
@Target({ ElementType.FIELD })
@@ -13,4 +17,14 @@
* @return column name
*/
String value() default "";
+
+ /**
+ * The time-to-live in seconds with which this particular field should be
+ * persisted as. By default no expiration deadline (ttl) is set. Setting a
+ * value of <code>0</code> disables expiration for this column, overriding a
+ * class-wide setting on {@link DefaultAnnotationSet}.
+ *
+ * @return
+ */
+ int ttl() default -1;
}
@@ -5,7 +5,24 @@
/**
* The default annotation set. Supports {@link Id} and {@link Column}
*/
-public class DefaultAnnotationSet implements AnnotationSet<Id, Column> {
+public class DefaultAnnotationSet implements AnnotationSet2<Id, Column> {
+
+ private Integer defaultTtl = null;
+
+ public DefaultAnnotationSet() {
+ this(null);
+ }
+
+ /**
+ * Specify a default time-to-live for columns with no own ttl specification.
+ *
+ * @param defaultColumnTtl
+ * a negative value or 0 disables default ttl setting
+ */
+ public DefaultAnnotationSet(Integer defaultColumnTtl) {
+ this.defaultTtl = defaultColumnTtl;
+ }
+
@Override
public Class<Id> getIdAnnotation() {
return Id.class;
@@ -27,4 +44,14 @@ public String getColumnName(Field field, Column annotation) {
String name = annotation.value();
return (name.length() > 0) ? name : field.getName();
}
+
+ @Override
+ public int getColumnTtl(Field field, Column annotation) {
+ if (annotation.ttl() > -1) {
+ return annotation.ttl();
+ } else if (defaultTtl != null && defaultTtl.intValue() > 0) {
+ return defaultTtl.intValue();
+ }
+ return -1;
+ }
}
@@ -0,0 +1,30 @@
+package com.netflix.astyanax.mapping;
+
+import java.lang.reflect.Field;
+
+public class FieldMapping {
+
+ private Field field;
+
+ private Integer ttl = null;
+
+ public FieldMapping() {
+
+ }
+
+ public Field getField() {
+ return field;
+ }
+
+ public void setField(Field field) {
+ this.field = field;
+ }
+
+ public Integer getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(Integer ttl) {
+ this.ttl = ttl;
+ }
+}
@@ -30,7 +30,7 @@
*/
@SuppressWarnings({ "SuspiciousMethodCalls" })
public class Mapping<T> {
- private final ImmutableMap<String, Field> fields;
+ private final ImmutableMap<String, FieldMapping> fields;
private final String idFieldName;
private final Class<T> clazz;
@@ -83,7 +83,8 @@ public Mapping(Class<T> clazz, AnnotationSet<?, ?> annotationSet) {
this.clazz = clazz;
String localKeyFieldName = null;
- ImmutableMap.Builder<String, Field> builder = ImmutableMap.builder();
+ ImmutableMap.Builder<String, FieldMapping> builder = ImmutableMap
+ .builder();
AtomicBoolean isKey = new AtomicBoolean();
Set<String> usedNames = Sets.newHashSet();
@@ -131,13 +132,13 @@ public Mapping(Class<T> clazz, AnnotationSet<?, ?> annotationSet) {
*/
public <V> V getColumnValue(T instance, String columnName,
Class<V> valueClass) {
- Field field = fields.get(columnName);
- if (field == null) {
+ FieldMapping fieldMapping = fields.get(columnName);
+ if (fieldMapping == null) {
throw new IllegalArgumentException("Column not found: "
+ columnName);
}
try {
- return valueClass.cast(field.get(instance));
+ return valueClass.cast(fieldMapping.getField().get(instance));
} catch (IllegalAccessException e) {
throw new RuntimeException(e); // should never get here
}
@@ -169,13 +170,13 @@ public Mapping(Class<T> clazz, AnnotationSet<?, ?> annotationSet) {
* class)
*/
public <V> void setColumnValue(T instance, String columnName, V value) {
- Field field = fields.get(columnName);
- if (field == null) {
+ FieldMapping fieldMapping = fields.get(columnName);
+ if (fieldMapping == null) {
throw new IllegalArgumentException("Column not found: "
+ columnName);
}
try {
- field.set(instance, value);
+ fieldMapping.getField().set(instance, value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e); // should never get here
}
@@ -192,8 +193,10 @@ public Mapping(Class<T> clazz, AnnotationSet<?, ?> annotationSet) {
*/
public void fillMutation(T instance, ColumnListMutation<String> mutation) {
for (String fieldName : getNames()) {
+ FieldMapping fieldMapping = fields.get(fieldName);
Coercions.setColumnMutationFromField(instance,
- fields.get(fieldName), fieldName, mutation);
+ fieldMapping.getField(), fieldName, mutation,
+ fieldMapping.getTtl());
}
}
@@ -225,10 +228,11 @@ public T newInstance(ColumnList<String> columns)
*/
public T initInstance(T instance, ColumnList<String> columns) {
for (com.netflix.astyanax.model.Column<String> column : columns) {
- Field field = fields.get(column.getName());
- if (field != null) { // otherwise it may be a column that was
- // removed, etc.
- Coercions.setFieldFromColumn(instance, field, column);
+ FieldMapping fieldMapping = fields.get(column.getName());
+ if (fieldMapping != null) { // otherwise it may be a column that was
+ // removed, etc.
+ Coercions.setFieldFromColumn(instance, fieldMapping.getField(),
+ column);
}
}
return instance;
@@ -267,13 +271,13 @@ public T initInstance(T instance, ColumnList<String> columns) {
}
Class<?> getIdFieldClass() {
- return fields.get(idFieldName).getType();
+ return fields.get(idFieldName).getField().getType();
}
private <ID extends Annotation, COLUMN extends Annotation> String mapField(
Field field, AnnotationSet<ID, COLUMN> annotationSet,
- ImmutableMap.Builder<String, Field> builder, Set<String> usedNames,
- AtomicBoolean isKey) {
+ ImmutableMap.Builder<String, FieldMapping> builder,
+ Set<String> usedNames, AtomicBoolean isKey) {
String mappingName = null;
ID idAnnotation = field.getAnnotation(annotationSet.getIdAnnotation());
@@ -293,8 +297,13 @@ public T initInstance(T instance, ColumnList<String> columns) {
isKey.set(false);
}
+ int ttl = -1;
if ((columnAnnotation != null)) {
mappingName = annotationSet.getColumnName(field, columnAnnotation);
+ if (annotationSet instanceof AnnotationSet2) {
+ ttl = ((AnnotationSet2<ID, COLUMN>) annotationSet)
+ .getColumnTtl(field, columnAnnotation);
+ }
}
if (mappingName != null) {
@@ -304,7 +313,12 @@ public T initInstance(T instance, ColumnList<String> columns) {
usedNames.add(mappingName.toLowerCase());
field.setAccessible(true);
- builder.put(mappingName, field);
+ FieldMapping fieldMapping = new FieldMapping();
+ fieldMapping.setField(field);
+ if (ttl > -1) {
+ fieldMapping.setTtl(ttl);
+ }
+ builder.put(mappingName, fieldMapping);
}
return mappingName;
Oops, something went wrong.