Isolator.java

package org.microspace.table;

import java.math.BigInteger;

import org.microspace.exception.IllegalOperationException;
import org.microspace.specific.CurrentTimeProvider;
import org.microspace.table.column.Accessor;
import org.microspace.table.column.Getter;
import org.microspace.table.column.IndexedMap;
import org.microspace.table.column.IndexedSet;

/**
 * A front map that can be used as a transaction map.
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 */
public class Isolator<T> extends SimpleUnsafeTable<T> {

	public enum State {
		CREATED, LOCKED
	}
	
	State state;
	
	protected final IndexedMap<Object, BigInteger> backUpdateCount;
	protected final IndexedSet<Object> updates;

	public Isolator(Class<T> clazz, CurrentTimeProvider currentTimeProvider) {
		super(clazz, currentTimeProvider);
		Accessor<T> getters = getAccessor();
		backUpdateCount = new IndexedMap<Object, BigInteger> (getters.getPrimaryKeyGetSetPair().getIndexType());
		updates = new IndexedSet<Object> (getters.getPrimaryKeyGetSetPair().getIndexType());
		state = State.CREATED;
	}

	public Isolator(Accessor<T> accessor, CurrentTimeProvider currentTimeProvider) {
		super(accessor, currentTimeProvider);
		Accessor<T> getters = getAccessor();
		backUpdateCount = new IndexedMap<Object, BigInteger> (getters.getPrimaryKeyGetSetPair().getIndexType());
		updates = new IndexedSet<Object> (getters.getPrimaryKeyGetSetPair().getIndexType());
		state = State.CREATED;
	}

	public IndexedSet<Object> keySet () {
		return entries.keySet ();
	}
	
	public void setFirstEntry (Entry<T> container) {
		Getter<T> keyGetter = getAccessor().getPrimaryKeyGetSetPair();
		Object key = keyGetter.get (container.getSpaceEntry());
		if (entries.get(key) != null) {
			throw new IllegalArgumentException ("Map already has the key.");
		}
		if (backUpdateCount.put (key, container.getUpdateCount()) != null) {
			throw new IllegalArgumentException ("Removed container is already copied.");
		}
		if (getState() == State.LOCKED){
			throw new IllegalOperationException("Map is locked.");
		}
		if (container.isRemoved()) {
			@SuppressWarnings("unused")
			T t = readById(container.getPrimaryKey());
			updates.add (keyGetter.get(container.getSpaceEntry()));
		}
		super.setFirstEntry(container);
	}

	public BigInteger getBackUpdateCount (Object o) {
		return backUpdateCount.get(o);
	}
	
	public IndexedSet<Object>  getUpdatedKeys () {
		return updates;
		
	}
	
	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	/**
	 * Removes are marke only.
	 */
	@Override
	protected void remove (Entry<T> container) {
		remove (container, true);
	}
	
	@Override
	public void setEntry (Entry<T> container) {
		if (getState() == State.LOCKED){
			throw new IllegalOperationException("Map is locked.");
		}
		// Load up the entry if it exists.
		@SuppressWarnings("unused")
		T t = readById(container.getPrimaryKey());
		Getter<T> keyGetter = getAccessor().getPrimaryKeyGetSetPair();
		updates.add (keyGetter.get(container.getSpaceEntry()));
		if (container.isRemoved()) {
			remove (container);
		} else {
			move (container);			
		}
	}
	
	public void clear () {
		if (getState() == State.LOCKED){
			throw new IllegalOperationException ("Map is locked.");
		}
		backUpdateCount.clear ();
		updates.clear();
		super.clear();
	}
	
	
}