MicroSpaceAccessor.java
package org.microspace.specific;
import java.lang.reflect.Method;
import java.util.List;
import java.util.TreeMap;
import org.microspace.annotation.IndexType;
import org.microspace.annotation.Indexed;
import org.microspace.annotation.PartitionId;
import org.microspace.annotation.SpaceRecord;
import org.microspace.annotation.ThreadId;
import org.microspace.exception.IllegalOperationException;
import org.microspace.table.column.Accessor;
import org.microspace.table.column.GetSetPair;
/**
*
* This ia a method based accessor.
*
* @author Gaspar Sinai
* @version 2012-06-01
*
*/
public class MicroSpaceAccessor<T> implements Accessor<T> {
private GetSetPair<T> primaryKeyGetter;
private GetSetPair<T> threadIdGetter;
private GetSetPair<T> partitionIdGetter;
private List<GetSetPair<T>> getSetPairs;
private TreeMap<String, GetSetPair<T>> getSetPairsByName = new TreeMap<String, GetSetPair<T>> ();
private Class<T> targetClass;
private boolean localRecord;
private boolean updatableRecord;
public MicroSpaceAccessor (Class<T> targetClass) {
load (targetClass, false);
}
public MicroSpaceAccessor (Class<T> targetClass, boolean ignoreAnnotations) {
load (targetClass, ignoreAnnotations);
}
private void load (Class<T> targetClass, boolean ignoreAnnotations) {
this.targetClass = targetClass;
Class<?> partitionIdType = null;
NullValueExtractor extractor = new MicroSpaceNullValueExtractor();
// Collect the public getXX methods.
TreeMap<String, MethodBasedGetter<T>> getters = MethodUtils.scanGetters (targetClass, extractor);
TreeMap<String, MethodBasedSetter<T>> setters = MethodUtils.scanSetters (targetClass);
getSetPairs = MethodUtils.generateGetSetPairs (getters, setters);
for (GetSetPair<T> pair : getSetPairs) {
getSetPairsByName.put(pair.getName(), pair);
}
if (ignoreAnnotations) return;
for (MethodBasedGetter<T> getter : getters.values()) {
Indexed property = getter.getMethod().getAnnotation(Indexed.class);
if (property != null) {
getter.setIndexType(getIndexType(getter.getMethod()));
if (property.primaryKey()) {
if (primaryKeyGetter != null) {
throw new IllegalArgumentException("Class "
+ targetClass + " has multiple primary keys.");
}
primaryKeyGetter = getSetPairsByName.get(getter.getName());
}
}
ThreadId threadId = getter.getMethod().getAnnotation(ThreadId.class);
if (threadId != null) {
if (threadIdGetter != null) {
throw new IllegalArgumentException("Class "
+ targetClass + " has multiple ThreadId.");
}
threadIdGetter = getSetPairsByName.get(getter.getName());
}
PartitionId partitionId = getter.getMethod().getAnnotation(PartitionId.class);
if (partitionId != null) {
if (partitionIdGetter != null) {
throw new IllegalArgumentException("Class "
+ targetClass + " has multiple partitionId.");
}
partitionIdGetter = getSetPairsByName.get(getter.getName());
partitionIdType = getter.getReturnType();
}
}
if (partitionIdType != null && !Integer.class.equals(partitionIdType)) {
throw new IllegalArgumentException ("PartitionId is not Integer");
}
if (primaryKeyGetter == null) {
throw new IllegalArgumentException ("No primary key defined for " + targetClass.getName());
}
localRecord = false;
updatableRecord = false;
if (targetClass.isAnnotationPresent(SpaceRecord.class)) {
SpaceRecord annotation = targetClass.getAnnotation(SpaceRecord.class);
localRecord = annotation.local();
updatableRecord = annotation.updatable();
}
}
public GetSetPair<T> getPrimaryKeyGetSetPair() {
return primaryKeyGetter;
}
public GetSetPair<T> getThreadIdGetSetPair() {
return threadIdGetter;
}
public GetSetPair<T> getPartitionIdGetSetPair() {
return partitionIdGetter;
}
public List<GetSetPair<T>> getGetSetPairs() {
return getSetPairs;
}
public GetSetPair<T> getGetSetPair (String name) {
return getSetPairsByName.get(name);
}
public T getBlankObject () {
return MethodUtils.getBlank (targetClass);
}
public Class<T> getTargetClass() {
return targetClass;
}
protected IndexType getIndexType (Method method) {
Indexed it = method.getAnnotation (Indexed.class);
if (it != null && it.type() == IndexType.NONE) return null;
if (it != null && it.type() != IndexType.AUTO) {
if (it.type() == IndexType.SORTED && !Comparable.class.isAssignableFrom(method.getReturnType())){
throw new IllegalOperationException ("SORTED index on " + method.getName() + " is not Comparable");
}
return it.type();
}
if (Comparable.class.isAssignableFrom(method.getReturnType())) {
return IndexType.SORTED;
} else {
return IndexType.HASHED;
}
}
@Override
public boolean isLocalRecord() {
return localRecord;
}
@Override
public boolean isUpdatableRecord() {
return updatableRecord;
}
}