MorphicArray.java

package edu.udel.cis.vsl.tass.morph;

import java.util.Arrays;
import java.util.Iterator;

public class MorphicArray<T extends Morphic> extends MorphicObject implements
		Iterable<T> {

	private Morphic[] data;

	/**
	 * Construct new component array with this length. All elements initially
	 * null.
	 */
	MorphicArray(int length) {
		data = new Morphic[length];
	}

	MorphicArray(MorphicArray<T> oldArray) {
		data = Arrays.copyOf(oldArray.data, oldArray.data.length);
	}

	Morphic[] data() {
		return data;
	}

	public int length() {
		return data.length;
	}

	@SuppressWarnings("unchecked")
	public T get(int index) {
		if (index >= data.length) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		return (T) data[index];
	}

	public void set(int index, T element) {
		assert !isCommitted();
		if (index >= data.length) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		data[index] = element;
	}

	@Override
	protected boolean computeEquals(Morphic component) {
		if (component instanceof MorphicArray<?>) {
			MorphicArray<?> that = (MorphicArray<?>) component;

			return Arrays.equals(data, that.data);
		}
		return false;
	}

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

	@SuppressWarnings("unchecked")
	void canonicalizeChildren(MorphicFactoryIF<? super T> elementFactory) {
		for (int i = 0; i < data.length; i++) {
			T datum = (T) data[i];

			if (datum != null) {
				T newDatum = (T) elementFactory.canonic(datum);

				if (datum != newDatum)
					data[i] = newDatum;
			}
		}
	}

	@Override
	protected void commitChildren() {
		for (Morphic datum : data) {
			if (datum != null)
				datum.commit();
		}
	}

	@Override
	public Iterator<T> iterator() {
		return new MorphicArrayIterator<T>(data);
	}

	@Override
	public String toString() {
		String result = "[";
		int length = data.length;

		for (int i = 0; i < length; i++) {
			if (i > 0)
				result += ", ";
			result += data[i];
		}
		result += "]";
		return result;
	}

	class MorphicArrayIterator<S extends Morphic> implements Iterator<S> {
		Morphic[] data;
		int index = 0;

		MorphicArrayIterator(Morphic[] data) {
			this.data = data;
		}

		@Override
		public boolean hasNext() {
			return index < data.length;
		}

		@SuppressWarnings("unchecked")
		@Override
		public S next() {
			S result = (S) data[index];

			index++;
			return result;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

}