package eworks.RQL.engine;

import java.util.Hashtable;
import eworks.RDF.model.*;

/**
 * <p>A symbol table that is used by <code>RqlEngine</code> class for
 * storing the values of variables.</p>
 * 
 * @author Fabian Wleklinski (<a href="mailto:fabian@wleklinski.de">fabian@wleklinski.de</a>)
 * @see RqlEngine
 * @version 1.00 (2003-11-03)
 */
public class SymbolTable extends Hashtable {

	/**
	 * Creates a new and empty symbol table using the default capacity.
	 */
	public SymbolTable() {
		super();
	}

	/**
	 * Creates a new and empty symbol table with the given intial capacity.
	 * @param initialCapacity The symbol table's initial capicity
	 * 
	 */
	public SymbolTable(int initialCapacity) {
		super(initialCapacity);
	}

	/**
	 * Returns the value of the variable specified by <code>name</code>.
	 * @param name The variable's name
	 * @return The variable's value
	 * @throws VariableNotBoundException Thrown if there is no bound variable
	 * named <code>name</code>
	 */
	public LiteralValue get(String name) throws VariableNotBoundException {
		LiteralValue result = (LiteralValue) super.get(name);
		if (result == null)
			throw new VariableNotBoundException("name: '" + name + "'");
		return result;
	}
	
	/**
	 * Returns all bound variables and their values as tuple, using an
	 * instance of <code>Tuple</code>.
	 * @return A tuple built by all contained variables and their values.
	 */
	public Tuple getTuple() {
		/*
		if (super.size()==3)
			return new eworks.RQL.model.Statement(super.values());
		else
		*/
		return new TupleImpl(super.values());
	}
	
	/**
	 * Binds the variable <code>variable</code> to the value
	 * <code>value</code>.
	 * @param variable The variable to be bound.
	 * @param value The value to be bound.
	 * @throws VariableAlreadyBoundException is thrown if the variable
	 * <code>variable</code> is already bound.
	 */
	public void bind(eworks.RQL.model.Variable variable,LiteralValue value) throws
	VariableAlreadyBoundException {
		
		if (variable != null)
			if (super.containsKey(variable.getName()))
				throw new VariableAlreadyBoundException(variable);
			
		super.put(variable != null ? variable.getName() : Integer.toString(super.size()), value);
	}
}