ColumnReferences.java

package org.microspace.table.column;

import org.microspace.annotation.IndexType;

/**
 * This class provides an easy lookup of primary keys that refer to a certain indexed column.
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 * @version 2012-06-01
 *
 */
public class ColumnReferences<T> {
	
	final IndexedMap<Object, IndexedSet<Object>> map;
	final Getter<T> primaryKeyGetter;
	final Getter<T> fieldGetter;
	final IndexedSet<Object> nullKeySet;
	
	public ColumnReferences (Getter<T> primaryKeyGetter, Getter<T> fieldGetter) {
		this.primaryKeyGetter = primaryKeyGetter;
		this.fieldGetter = fieldGetter;
		map = new IndexedMap<Object, IndexedSet<Object>> (fieldGetter.getIndexType());
		this.nullKeySet = new IndexedSet<Object> (this.primaryKeyGetter.getIndexType());
	}

	// 
	public void moveKey (Object key, Object oldFieldValue, Object newFieldValue) {
		if (fieldGetter.isNull(oldFieldValue)) oldFieldValue = null;
		if (fieldGetter.isNull(newFieldValue)) newFieldValue = null;
		if (isSameObject (fieldGetter.getIndexType(), oldFieldValue, newFieldValue)) return;
		IndexedSet<Object> oldMatches = (oldFieldValue == null) ? null : map.get (oldFieldValue);
		if (newFieldValue != null) {
			IndexedSet<Object> newMatches = map.get (newFieldValue);
			if (newMatches == null) {
				newMatches = new IndexedSet<Object> (this.primaryKeyGetter.getIndexType());
				map.put (newFieldValue, newMatches);
			}
			if (newMatches == oldMatches) return;
			if (oldMatches != null) {
				oldMatches.remove (key);
			}
			newMatches.add(key);
		} else if (oldMatches != null) {
			oldMatches.remove (key);
		}
	}
	
	public IndexedSet<Object> getMatchingKeys(Object fieldValue) {
		IndexedSet<Object> ret = map.get (fieldValue);
		return ret == null ? nullKeySet : ret;
	}
	
	public int size (Object fieldValue) {
		IndexedSet<Object> ret = map.get (fieldValue);
		return ret == null ? 0 : ret.size();
	}
	
	@SuppressWarnings("unchecked")
	private boolean isSameObject (IndexType type, Object o0, Object o1) {
		if (o0 == o1) return true;
		if (o0 == null || o1 == null) return false;
		switch (type){
		case SORTED:
			return ((Comparable<Object>)o0).compareTo((Comparable<Object>)o1) == 0;
		case HASHED:
		default:
			return o0.equals (o1);
		}
	}

	public Getter<T> getPrimaryKeyGetter() {
		return primaryKeyGetter;
	}

	public Getter<T> getFieldGetter() {
		return fieldGetter;
	}
	
}