Value.java

package edu.udel.cis.vsl.tass.dynamic.impl.value;

import edu.udel.cis.vsl.tass.dynamic.IF.type.ValueTypeIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ValueIF;
import edu.udel.cis.vsl.tass.dynamic.impl.type.ValueTypeFactory;
import edu.udel.cis.vsl.tass.morph.Morphic;
import edu.udel.cis.vsl.tass.morph.MorphicObject;
import edu.udel.cis.vsl.tass.symbolic.IF.SymbolicExpressionIF;

/**
 * The root of the hierarchy of classes implementing ValueIF. This
 * implementation of values uses the Flyweight Pattern. Moreover, Values are
 * immutable (or at least obervably immutable). This makes things like hashCode
 * and testing for equality very easy after the value is produced from the
 * ValueFactory.
 */
public abstract class Value extends MorphicObject implements ValueIF {

	private ValueTypeIF valueType;

	/**
	 * Symbolic expression representation of this value. Cached for performance.
	 * May be null. Can only be cached if value is committed, else state could
	 * change.
	 */
	private SymbolicExpressionIF symbolicExpression = null;

	Value(ValueTypeIF valueType) {
		assert valueType != null;
		this.valueType = valueType;
	}

	@Override
	public ValueTypeIF valueType() {
		return valueType;
	}

	protected void setType(ValueTypeIF valueType) {
		this.valueType = valueType;
	}

	/**
	 * Determine if the two are equal. This method is meant to be overridden,
	 * but in the overriding method this should be called first as super.
	 */
	@Override
	protected boolean computeEquals(Morphic component) {
		return component instanceof Value
				&& ((Value) component).valueType.equals(valueType);
	}

	@Override
	public String typedString() {
		return this.toString() + " (" + valueType.toString() + ")";
	}

	@Override
	protected int computeHashCode() {
		return valueType.hashCode();
	}

	@Override
	protected void commitChildren() {
		valueType.commit();
	}

	protected void canonicalizeChildren(ValueFactory valueFactory,
			ValueTypeFactory typeFactory) {
		valueType = typeFactory.canonic(valueType);
	}

	protected void setSymbolicExpression(SymbolicExpressionIF symbolicExpression) {
		assert isCommitted();
		this.symbolicExpression = symbolicExpression;
	}

	public SymbolicExpressionIF getSymbolicExpression() {
		return symbolicExpression;
	}
}