FieldBasedAccessor.java

package org.microspace.specific;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

import org.microspace.annotation.IndexType;
import org.microspace.annotation.SpaceRecord;
import org.microspace.annotation.ThreadId;
import org.microspace.table.column.Accessor;
import org.microspace.table.column.GetSetPair;

/**
 * A simple object that has only fields can be accessed by this Class.
 * <pre>
 * public class {
 *  	public String id;
 * 		public BigDecimal price;
 * 		public String name;
 * }
 * </pre>
 * The first n fields can be specified. The first field has to be the primaryKey.
 * <p>
 * Currently {@link ThreadId ThreadId} is not supported.
 * @author gsinai
 * @version 2012-01-29
 */
public class FieldBasedAccessor<T> implements Accessor<T> {
	private GetSetPair<T> primaryKeyGetter;
	
	private List<GetSetPair<T>> getSetPairs = new ArrayList<GetSetPair<T>> ();
	private TreeMap<String, GetSetPair<T>> getSetPairsByName = new TreeMap<String, GetSetPair<T>> ();
	
	private Class<T> targetClass;
	
	private boolean localRecord;
	private boolean updatableRecord;

	public FieldBasedAccessor (Class<T> targetClass, int indexedFieldCount) {
		this.targetClass = targetClass;
		for (Field field : targetClass.getFields()) {
			if (!Modifier.isFinal(field.getModifiers()) && !Modifier.isPublic(field.getModifiers())) {
				continue;
			}
			FieldBasedGetterSetter<T> pair = new FieldBasedGetterSetter<T> (field);
			if (getSetPairs.size() < indexedFieldCount) {
				pair.setIndexType(getIndexType (field));
			}
			if (primaryKeyGetter == null) {
				primaryKeyGetter = pair;
			}
			pair.setIndex(getSetPairs.size());
			getSetPairsByName.put(pair.getName(), pair);
			getSetPairs.add (pair);
		}
		if (primaryKeyGetter == null) {
			throw new IllegalArgumentException ("No primary key defined for " + targetClass);
		}
		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 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 (Field field) {
		if (Comparable.class.isAssignableFrom(field.getType())) {
			return IndexType.SORTED;
		} else {
			return IndexType.HASHED;
		}
	}

	@Override
	public GetSetPair<T> getThreadIdGetSetPair() {
		return null;
	}
	
	@Override
	public GetSetPair<T> getPartitionIdGetSetPair() {
		return null;
	}
	@Override
	public boolean isLocalRecord() {
		return localRecord;
	}
	@Override
	public boolean isUpdatableRecord() {
		return updatableRecord;
	}

}